Added Video Export feature with according Options in the Options Menu
Fixed Linear Interpolation
This commit is contained in:
@@ -17,9 +17,9 @@ buildscript {
|
||||
|
||||
apply plugin: 'forge'
|
||||
|
||||
version = "1.0"
|
||||
group= "com.yourname.modid" // http://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||
archivesBaseName = "modid"
|
||||
version = "0.4"
|
||||
group= "eu.crushedpixel.replaymod"
|
||||
archivesBaseName = "replaymod"
|
||||
|
||||
minecraft {
|
||||
version = "1.8-11.14.0.1255-1.8"
|
||||
@@ -34,6 +34,7 @@ minecraft {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'lib', includes: ['*.jar'])
|
||||
// you may put jars on which you depend on in ./libs
|
||||
// or you may define them like so..
|
||||
//compile "some.group:artifact:version:classifier"
|
||||
|
||||
@@ -27,6 +27,8 @@ public class ReplayMod
|
||||
{
|
||||
|
||||
//TODO: Set ReplayHandler replaying to false when replay is exited
|
||||
//TODO: Hide Titles upon hurrying
|
||||
//TODO: Override Enchantment Rendering for items when replaying (to adjust speed of animation)
|
||||
|
||||
//XXX
|
||||
//Known Bugs
|
||||
@@ -44,7 +46,7 @@ public class ReplayMod
|
||||
|
||||
public static GuiReplayOverlay overlay = new GuiReplayOverlay();
|
||||
|
||||
public static ReplaySettings replaySettings = new ReplaySettings(0, true, true, true, false, false);
|
||||
public static ReplaySettings replaySettings = new ReplaySettings(true, true, true, false, false, 30, 0.5f);
|
||||
public static Configuration config;
|
||||
|
||||
public static boolean firstMainMenu = true;
|
||||
@@ -66,13 +68,14 @@ public class ReplayMod
|
||||
|
||||
Property recServer = config.get("settings", "enableRecordingServer", true, "Defines whether a recording should be started upon joining a server.");
|
||||
Property recSP = config.get("settings", "enableRecordingSingleplayer", true, "Defines whether a recording should be started upon joining a singleplayer world.");
|
||||
Property maxFileSize = config.get("settings", "maximumFileSize", 0, "The maximum File size (in MB) of a recording. 0 means unlimited.");
|
||||
Property showNot = ReplayMod.instance.config.get("settings", "showNotifications", true, "Defines whether notifications should be sent to the player.");
|
||||
Property linear = ReplayMod.instance.config.get("settings", "forceLinearPath", false, "Defines whether travelling paths should be linear instead of interpolated.");
|
||||
Property lighting = ReplayMod.instance.config.get("settings", "enableLighting", false, "If enabled, the whole map is lighted.");
|
||||
Property vq = ReplayMod.instance.config.get("settings", "videoQuality", 0.5f, "The quality of the exported video files from 0.1 to 0.9");
|
||||
Property framerate = ReplayMod.instance.config.get("settings", "videoFramerate", 30, "The framerate of the exported video files from 10 to 120");
|
||||
|
||||
replaySettings = new ReplaySettings(maxFileSize.getInt(0), recServer.getBoolean(true), recSP.getBoolean(true), showNot.getBoolean(true),
|
||||
linear.getBoolean(false), lighting.getBoolean(false));
|
||||
replaySettings = new ReplaySettings(recServer.getBoolean(true), recSP.getBoolean(true), showNot.getBoolean(true),
|
||||
linear.getBoolean(false), lighting.getBoolean(false), framerate.getInt(30), (float)vq.getDouble(0.5));
|
||||
|
||||
config.save();
|
||||
}
|
||||
|
||||
@@ -9,12 +9,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.FileEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
@@ -22,7 +17,6 @@ import com.google.gson.JsonParser;
|
||||
|
||||
import eu.crushedpixel.replaymod.api.client.holders.ApiError;
|
||||
import eu.crushedpixel.replaymod.api.client.holders.AuthKey;
|
||||
import eu.crushedpixel.replaymod.api.client.holders.Category;
|
||||
import eu.crushedpixel.replaymod.api.client.holders.FileInfo;
|
||||
import eu.crushedpixel.replaymod.api.client.holders.Success;
|
||||
import eu.crushedpixel.replaymod.api.client.holders.UserFiles;
|
||||
@@ -77,6 +71,13 @@ public class ApiClient {
|
||||
FileInfo[] info = invokeAndReturn(builder, FileInfo[].class); //TODO: Test if that works
|
||||
return info;
|
||||
}
|
||||
|
||||
public void downloadThumbnail(int file, File target) throws IOException {
|
||||
QueryBuilder builder = new QueryBuilder(ApiMethods.get_thumbnail);
|
||||
builder.put("id", file);
|
||||
URL url = new URL(builder.toString());
|
||||
FileUtils.copyURLToFile(url, target);
|
||||
}
|
||||
|
||||
public void downloadFile(String auth, int file, File target) throws IOException {
|
||||
QueryBuilder builder = new QueryBuilder(ApiMethods.download_file);
|
||||
|
||||
@@ -8,6 +8,7 @@ public class ApiMethods {
|
||||
public static final String file_details = "file_details";
|
||||
public static final String upload_file = "upload_file";
|
||||
public static final String download_file = "download_file";
|
||||
public static final String get_thumbnail = "get_thumbnail";
|
||||
public static final String remove_file = "remove_file";
|
||||
public static final String rate_file = "rate_file";
|
||||
|
||||
|
||||
@@ -10,6 +10,9 @@ public class FileInfo {
|
||||
private Rating ratings;
|
||||
private int size;
|
||||
private int category;
|
||||
private int downloads;
|
||||
private String name;
|
||||
private boolean thumbnail;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
@@ -29,5 +32,15 @@ public class FileInfo {
|
||||
public int getCategory() {
|
||||
return category;
|
||||
}
|
||||
public int getDownloads() {
|
||||
return downloads;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public boolean hasThumbnail() {
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.lang.reflect.Field;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.play.server.S03PacketTimeUpdate;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.util.MovingObjectPosition;
|
||||
import net.minecraft.util.Vec3;
|
||||
@@ -15,6 +16,7 @@ import org.lwjgl.Sys;
|
||||
import eu.crushedpixel.replaymod.holders.Position;
|
||||
import eu.crushedpixel.replaymod.replay.LesserDataWatcher;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import eu.crushedpixel.replaymod.replay.TimeHandler;
|
||||
|
||||
public class CameraEntity extends EntityPlayer {
|
||||
|
||||
@@ -37,14 +39,19 @@ public class CameraEntity extends EntityPlayer {
|
||||
mc.thePlayer.rotationPitch = mc.getRenderViewEntity().rotationPitch;
|
||||
mc.thePlayer.rotationYaw = mc.getRenderViewEntity().rotationYaw;
|
||||
|
||||
/*
|
||||
mc.thePlayer.posX = mc.getRenderViewEntity().posX;
|
||||
mc.thePlayer.posY = mc.getRenderViewEntity().posY;
|
||||
mc.thePlayer.posZ = mc.getRenderViewEntity().posZ;
|
||||
|
||||
TimeHandler.setDesiredDaytime(18000);
|
||||
TimeHandler.setTimeOverridden(true);
|
||||
*/
|
||||
|
||||
//removes water/suffocation/shadow overlays in screen
|
||||
//mc.thePlayer.posX = 0;
|
||||
//mc.thePlayer.posY = 500;
|
||||
//mc.thePlayer.posZ = 0;
|
||||
mc.thePlayer.posX = 0;
|
||||
mc.thePlayer.posY = 500;
|
||||
mc.thePlayer.posZ = 0;
|
||||
}
|
||||
|
||||
if(direction == null || motion < 0.1) {
|
||||
|
||||
@@ -15,11 +15,11 @@ import net.minecraft.client.gui.GuiVideoSettings;
|
||||
import net.minecraft.client.gui.inventory.GuiInventory;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.client.settings.GameSettings.Options;
|
||||
import net.minecraft.util.Timer;
|
||||
import net.minecraftforge.client.event.GuiOpenEvent;
|
||||
import net.minecraftforge.client.event.GuiScreenEvent.ActionPerformedEvent;
|
||||
import net.minecraftforge.client.event.GuiScreenEvent.DrawScreenEvent;
|
||||
import net.minecraftforge.client.event.GuiScreenEvent.InitGuiEvent;
|
||||
import net.minecraftforge.fml.common.eventhandler.Event.Result;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.gui.GuiConstants;
|
||||
@@ -32,8 +32,9 @@ import eu.crushedpixel.replaymod.gui.replaymanager.GuiReplayManager;
|
||||
import eu.crushedpixel.replaymod.gui.replaymanager.ResourceHelper;
|
||||
import eu.crushedpixel.replaymod.online.authentication.AuthenticationHandler;
|
||||
import eu.crushedpixel.replaymod.registry.ReplayGuiRegistry;
|
||||
import eu.crushedpixel.replaymod.replay.MCTimerHandler;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import eu.crushedpixel.replaymod.replay.ReplaySender;
|
||||
import eu.crushedpixel.replaymod.video.VideoWriter;
|
||||
|
||||
public class GuiEventHandler {
|
||||
|
||||
@@ -51,6 +52,11 @@ public class GuiEventHandler {
|
||||
|
||||
@SubscribeEvent
|
||||
public void onGui(GuiOpenEvent event) {
|
||||
if(VideoWriter.isRecording()) {
|
||||
event.gui = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!(event.gui instanceof GuiReplayManager || event.gui instanceof GuiUploadFile)) ResourceHelper.freeAllResources();
|
||||
|
||||
if(event.gui instanceof GuiMainMenu) {
|
||||
@@ -60,8 +66,7 @@ public class GuiEventHandler {
|
||||
return;
|
||||
} else {
|
||||
try {
|
||||
Timer timer = (Timer)ReplaySender.mcTimer.get(mc);
|
||||
timer.timerSpeed = 1f;
|
||||
MCTimerHandler.setTimerSpeed(1);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -46,9 +46,11 @@ import eu.crushedpixel.replaymod.holders.PositionKeyframe;
|
||||
import eu.crushedpixel.replaymod.holders.TimeKeyframe;
|
||||
import eu.crushedpixel.replaymod.reflection.MCPNames;
|
||||
import eu.crushedpixel.replaymod.registry.ReplayGuiRegistry;
|
||||
import eu.crushedpixel.replaymod.replay.MCTimerHandler;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayProcess;
|
||||
import eu.crushedpixel.replaymod.replay.screenshot.ReplayScreenshot;
|
||||
import eu.crushedpixel.replaymod.video.ReplayScreenshot;
|
||||
import eu.crushedpixel.replaymod.video.VideoWriter;
|
||||
|
||||
public class GuiReplayOverlay extends Gui {
|
||||
|
||||
@@ -58,7 +60,7 @@ public class GuiReplayOverlay extends Gui {
|
||||
private int sliderY = 10;
|
||||
|
||||
private int timelineX = sliderX+100+5;
|
||||
private int realTimelineX = 10 + 3*25;
|
||||
private int realTimelineX = 10 + 4*25;
|
||||
private int realTimelineY = 33+10;
|
||||
|
||||
private int ppButtonX = 10;
|
||||
@@ -67,10 +69,13 @@ public class GuiReplayOverlay extends Gui {
|
||||
private int r_ppButtonX = 10;
|
||||
private int r_ppButtonY = realTimelineY+1;
|
||||
|
||||
private int place_ButtonX = 35;
|
||||
private int exportButtonX = 35;
|
||||
private int exportButtonY = realTimelineY+1;
|
||||
|
||||
private int place_ButtonX = 60;
|
||||
private int place_ButtonY = realTimelineY+1;
|
||||
|
||||
private int time_ButtonX = 60;
|
||||
private int time_ButtonX = 85;
|
||||
private int time_ButtonY = realTimelineY+1;
|
||||
|
||||
private long lastSystemTime = System.currentTimeMillis();
|
||||
@@ -109,11 +114,12 @@ public class GuiReplayOverlay extends Gui {
|
||||
@SubscribeEvent
|
||||
public void tick(TickEvent event) {
|
||||
if(!ReplayHandler.replayActive()) return;
|
||||
if(ReplayHandler.isReplaying() && !ReplayProcess.isVideoRecording()) ReplayProcess.tickReplay();
|
||||
ReplayProcess.unblock();
|
||||
if(ReplayHandler.getCameraEntity() != null)
|
||||
ReplayHandler.getCameraEntity().updateMovement();
|
||||
onMouseMove(new MouseEvent());
|
||||
if(!ReplayHandler.isReplaying()) onMouseMove(new MouseEvent());
|
||||
FMLCommonHandler.instance().bus().post(new InputEvent.KeyInputEvent());
|
||||
if(ReplayHandler.isReplaying()) ReplayProcess.tickReplay();
|
||||
}
|
||||
|
||||
private double lastX, lastY, lastZ;
|
||||
@@ -129,7 +135,7 @@ public class GuiReplayOverlay extends Gui {
|
||||
if(mc != null && mc.thePlayer != null)
|
||||
MinecraftTicker.runMouseKeyboardTick(mc);
|
||||
}
|
||||
if(mc.getRenderViewEntity() == mc.thePlayer) {
|
||||
if(mc.getRenderViewEntity() == mc.thePlayer || !mc.getRenderViewEntity().isEntityAlive()) {
|
||||
ReplayHandler.spectateCamera();
|
||||
ReplayHandler.getCameraEntity().movePath(new Position(lastX, lastY, lastZ, lastPitch, lastYaw));
|
||||
} else if(!ReplayHandler.isCamera()) {
|
||||
@@ -153,12 +159,22 @@ public class GuiReplayOverlay extends Gui {
|
||||
speedSlider = new GuiReplaySpeedSlider(1, sliderX, sliderY, "Speed");
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onRenderGui(RenderGameOverlayEvent event) {
|
||||
if(VideoWriter.isRecording()) {
|
||||
event.setCanceled(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SubscribeEvent
|
||||
public void onRenderGui(RenderGameOverlayEvent.Post event) throws IllegalArgumentException, IllegalAccessException {
|
||||
if(!ReplayHandler.replayActive() || FMLClientHandler.instance().isGUIOpen(GuiSpectateSelection.class)) {
|
||||
if(!ReplayHandler.replayActive() || FMLClientHandler.instance().isGUIOpen(GuiSpectateSelection.class) || VideoWriter.isRecording()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//System.out.println(System.currentTimeMillis()+" | "+MCTimerHandler.getTicks()+" | "+MCTimerHandler.getPartialTicks());
|
||||
|
||||
if(!ReplayGuiRegistry.hidden) ReplayGuiRegistry.hide();
|
||||
|
||||
if(event.type == ElementType.PLAYER_LIST) {
|
||||
@@ -227,6 +243,8 @@ public class GuiReplayOverlay extends Gui {
|
||||
ReplayHandler.setSpeed(speedSlider.getSliderValue());
|
||||
}
|
||||
|
||||
} else if(mouseX >= exportButtonX && mouseX <= exportButtonX+20 && mouseY >= exportButtonY && exportButtonY <= exportButtonY+20) {
|
||||
ReplayHandler.startPath(true);
|
||||
}
|
||||
|
||||
if(mouseX >= timelineX+4 && mouseX <= width - 18 && mouseY >= 11 && mouseY <= 29) {
|
||||
@@ -256,6 +274,28 @@ public class GuiReplayOverlay extends Gui {
|
||||
} catch(Exception e) {}
|
||||
}
|
||||
|
||||
//TODO: Save Video Button
|
||||
hover = false;
|
||||
x = 0;
|
||||
y = 18;
|
||||
|
||||
if(FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) {
|
||||
if(mouseX >= exportButtonX && mouseX <= exportButtonX+20
|
||||
&& mouseY >= exportButtonY && mouseY <= exportButtonY+20) {
|
||||
hover = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(hover) {
|
||||
x = 20;
|
||||
}
|
||||
|
||||
mc.renderEngine.bindTexture(timelineLocation);
|
||||
|
||||
GlStateManager.resetColor();
|
||||
this.drawModalRectWithCustomSizedTexture(exportButtonX, exportButtonY, x, y, 20, 20, 64, 64);
|
||||
|
||||
//GlStateManager.resetColor();
|
||||
|
||||
//Place Keyframe Button
|
||||
hover = false;
|
||||
@@ -703,7 +743,7 @@ public class GuiReplayOverlay extends Gui {
|
||||
if(ReplayHandler.isReplaying()) {
|
||||
ReplayHandler.interruptReplay();
|
||||
} else {
|
||||
ReplayHandler.startPath();
|
||||
ReplayHandler.startPath(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ import eu.crushedpixel.replaymod.entities.CameraEntity.MoveDirection;
|
||||
import eu.crushedpixel.replaymod.gui.GuiMouseInput;
|
||||
import eu.crushedpixel.replaymod.registry.KeybindRegistry;
|
||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
import eu.crushedpixel.replaymod.replay.screenshot.ReplayScreenshot;
|
||||
import eu.crushedpixel.replaymod.replay.spectate.SpectateHandler;
|
||||
import eu.crushedpixel.replaymod.video.ReplayScreenshot;
|
||||
|
||||
public class KeyInputHandler {
|
||||
|
||||
@@ -25,7 +25,9 @@ public class KeyInputHandler {
|
||||
if(mc.currentScreen != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
boolean found = false;
|
||||
|
||||
KeyBinding[] keyBindings = Minecraft.getMinecraft().gameSettings.keyBindings;
|
||||
for(KeyBinding kb : keyBindings) {
|
||||
if(!kb.isKeyDown()) {
|
||||
@@ -36,27 +38,22 @@ public class KeyInputHandler {
|
||||
if(ReplayHandler.isCamera()) {
|
||||
if(kb.getKeyDescription().equals("key.forward")) {
|
||||
ReplayHandler.getCameraEntity().setMovement(MoveDirection.FORWARD);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals("key.back")) {
|
||||
ReplayHandler.getCameraEntity().setMovement(MoveDirection.BACKWARD);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals("key.jump")) {
|
||||
ReplayHandler.getCameraEntity().setMovement(MoveDirection.UP);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals("key.left")) {
|
||||
ReplayHandler.getCameraEntity().setMovement(MoveDirection.LEFT);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals("key.right")) {
|
||||
ReplayHandler.getCameraEntity().setMovement(MoveDirection.RIGHT);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(kb.getKeyDescription().equals("key.sneak")) {
|
||||
@@ -65,35 +62,31 @@ public class KeyInputHandler {
|
||||
} else {
|
||||
ReplayHandler.spectateCamera();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals("key.chat")) {
|
||||
mc.displayGuiScreen(new GuiMouseInput());
|
||||
continue;
|
||||
}
|
||||
|
||||
//Custom registered handlers
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_THUMBNAIL) && kb.isPressed()) {
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_THUMBNAIL) && kb.isPressed() && !found) {
|
||||
System.out.println("thumbnail key pressed");
|
||||
ReplayScreenshot.prepareScreenshot();
|
||||
GuiReplayOverlay.requestScreenshot();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_SPECTATE) && kb.isPressed()) {
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_SPECTATE) && kb.isPressed() && !found) {
|
||||
SpectateHandler.openSpectateSelection();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_LIGHTING) && kb.isPressed()) {
|
||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_LIGHTING) && kb.isPressed() && !found) {
|
||||
ReplayMod.replaySettings.setLightingEnabled(!ReplayMod.replaySettings.isLightingEnabled());
|
||||
continue;
|
||||
}
|
||||
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +76,7 @@ public class MinecraftTicker {
|
||||
|
||||
public static void runMouseKeyboardTick(Minecraft mc) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException {
|
||||
|
||||
if(mc.thePlayer == null) return;
|
||||
try {
|
||||
mc.mcProfiler.endStartSection("mouse");
|
||||
int i;
|
||||
@@ -435,8 +436,6 @@ public class MinecraftTicker {
|
||||
|
||||
if(mc != null)
|
||||
systemTime.set(mc, getSystemTime.invoke(mc));
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch(Exception e) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package eu.crushedpixel.replaymod.gui.replaymanager;
|
||||
package eu.crushedpixel.replaymod.gui;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
@@ -18,6 +18,7 @@ import net.minecraft.client.gui.GuiListExtended.IGuiListEntry;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.texture.DynamicTexture;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import eu.crushedpixel.replaymod.gui.replaymanager.ResourceHelper;
|
||||
import eu.crushedpixel.replaymod.recording.ReplayMetaData;
|
||||
|
||||
public class GuiReplayListEntry implements IGuiListEntry {
|
||||
@@ -66,7 +67,7 @@ public class GuiReplayListEntry implements IGuiListEntry {
|
||||
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY, boolean isSelected) {
|
||||
try {
|
||||
minecraft.fontRendererObj.drawString(fileName, x + 3, y + 1, 16777215);
|
||||
|
||||
|
||||
if(y < -slotHeight || y > parent.height) {
|
||||
if(registered) {
|
||||
registered = false;
|
||||
@@ -79,7 +80,11 @@ public class GuiReplayListEntry implements IGuiListEntry {
|
||||
} else {
|
||||
if(!registered) {
|
||||
textureResource = new ResourceLocation("thumbs/"+fileName);
|
||||
image = ImageIO.read(imageFile);
|
||||
if(imageFile == null) {
|
||||
image = ResourceHelper.getDefaultThumbnail();
|
||||
} else {
|
||||
image = ImageIO.read(imageFile);
|
||||
}
|
||||
dynTex = new DynamicTexture(image);
|
||||
minecraft.getTextureManager().loadTexture(textureResource, dynTex);
|
||||
dynTex.updateDynamicTexture();
|
||||
@@ -1,4 +1,4 @@
|
||||
package eu.crushedpixel.replaymod.gui.replaymanager;
|
||||
package eu.crushedpixel.replaymod.gui;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
@@ -15,29 +15,21 @@ import org.lwjgl.input.Mouse;
|
||||
|
||||
import eu.crushedpixel.replaymod.recording.ReplayMetaData;
|
||||
|
||||
public class GuiReplayListExtended extends GuiListExtended {
|
||||
public abstract class GuiReplayListExtended extends GuiListExtended {
|
||||
|
||||
private GuiReplayManager parent;
|
||||
public int selected = -1;
|
||||
|
||||
public GuiReplayListExtended(GuiReplayManager parent, Minecraft mcIn, int p_i45010_2_,
|
||||
public GuiReplayListExtended(Minecraft mcIn, int p_i45010_2_,
|
||||
int p_i45010_3_, int p_i45010_4_, int p_i45010_5_, int p_i45010_6_) {
|
||||
super(mcIn, p_i45010_2_, p_i45010_3_, p_i45010_4_, p_i45010_5_, p_i45010_6_);
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public int selected = -1;
|
||||
|
||||
@Override
|
||||
protected void elementClicked(int slotIndex, boolean isDoubleClick,
|
||||
int mouseX, int mouseY) {
|
||||
super.elementClicked(slotIndex, isDoubleClick, mouseX, mouseY);
|
||||
this.selected = slotIndex;
|
||||
parent.setButtonsEnabled(true);
|
||||
if(isDoubleClick) {
|
||||
parent.loadReplay(slotIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void drawSelectionBox(int p_148120_1_, int p_148120_2_, int p_148120_3_, int p_148120_4_)
|
||||
@@ -22,12 +22,14 @@ public class GuiReplaySettings extends GuiScreen {
|
||||
private GuiScreen parentGuiScreen;
|
||||
protected String screenTitle = "Replay Mod Settings";
|
||||
|
||||
private static final int MAXSIZE_SLIDER_ID = 9003;
|
||||
//TODO: Move to GuiConstants
|
||||
private static final int QUALITY_SLIDER_ID = 9003;
|
||||
private static final int RECORDSERVER_ID = 9004;
|
||||
private static final int RECORDSP_ID = 9005;
|
||||
private static final int SEND_CHAT = 9006;
|
||||
private static final int FORCE_LINEAR = 9007;
|
||||
private static final int ENABLE_LIGHTING = 9008;
|
||||
private static final int FRAMERATE_SLIDER_ID = 9009;
|
||||
|
||||
private GuiButton recordServerButton, recordSPButton, sendChatButton, linearButton, lightingButton;
|
||||
|
||||
@@ -47,18 +49,11 @@ public class GuiReplaySettings extends GuiScreen {
|
||||
int i = 0;
|
||||
for (Entry<String, Object> e : aoptions.entrySet()) {
|
||||
|
||||
/*
|
||||
if(e.getKey().equals("Maximum File Size")) {
|
||||
float minValue = -1;
|
||||
float maxValue = 10000;
|
||||
float valueSteps = 1;
|
||||
|
||||
int val = (Integer)e.getValue();
|
||||
this.buttonList.add(new GuiSizeLimitOptionSlider(MAXSIZE_SLIDER_ID, this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), 0, 39, 1, val, e.getKey()));
|
||||
|
||||
} else
|
||||
*/
|
||||
if(e.getKey().equals("Enable Notifications")) {
|
||||
if(e.getKey().equals("Video Quality")) {
|
||||
this.buttonList.add(new GuiVideoQualitySlider(QUALITY_SLIDER_ID, this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), (Float)e.getValue(), "Video Quality"));
|
||||
} else if(e.getKey().equals("Video Framerate")) {
|
||||
this.buttonList.add(new GuiVideoFramerateSlider(FRAMERATE_SLIDER_ID, this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), (Integer)e.getValue(), "Video Framerate"));
|
||||
} else if(e.getKey().equals("Enable Notifications")) {
|
||||
sendChatButton = new GuiButton(SEND_CHAT, this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), 150, 20, "Enable Notifications: "+onOff((Boolean)e.getValue()));
|
||||
this.buttonList.add(sendChatButton);
|
||||
} else if(e.getKey().equals("Record Server")) {
|
||||
|
||||
@@ -1,185 +0,0 @@
|
||||
package eu.crushedpixel.replaymod.gui;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
|
||||
public class GuiSizeLimitOptionSlider extends GuiButton {
|
||||
|
||||
public GuiSizeLimitOptionSlider(int buttonId, int p_i45017_2_, int p_i45017_3_, float valueMin, float valueMax, float valueStep, int sliderValue, String displayKey)
|
||||
{
|
||||
super(buttonId, p_i45017_2_, p_i45017_3_, 150, 20, "");
|
||||
this.valueMin = valueMin;
|
||||
this.valueMax = valueMax;
|
||||
this.valueStep = valueStep;
|
||||
this.sliderValue = sliderValue;
|
||||
this.displayString = displayKey+": "+translate(sliderValue);
|
||||
this.displayKey = displayKey;
|
||||
|
||||
float val = realToNormalized(convertScaleRet(sliderValue));
|
||||
|
||||
|
||||
this.sliderValue = val;
|
||||
}
|
||||
|
||||
private float sliderValue;
|
||||
public boolean dragging;
|
||||
private GameSettings.Options options;
|
||||
|
||||
private float valueStep, valueMin, valueMax;
|
||||
private String displayKey;
|
||||
|
||||
|
||||
protected int getHoverState(boolean mouseOver) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void mouseDragged(Minecraft mc, int mouseX, int mouseY) {
|
||||
if (this.visible) {
|
||||
if (this.dragging) {
|
||||
sliderValue = (float)(mouseX - (this.xPosition + 4)) / (float)(this.width - 8);
|
||||
sliderValue = MathHelper.clamp_float(sliderValue, 0.0F, 1.0F);
|
||||
float f = denormalizeValue(sliderValue);
|
||||
sliderValue = normalizeValue(f);
|
||||
this.displayString = displayKey+": "+translate(convertScale(normalizedToReal(sliderValue)));
|
||||
ReplayMod.replaySettings.setMaximumFileSize(convertScale(normalizedToReal(sliderValue)));
|
||||
}
|
||||
|
||||
mc.getTextureManager().bindTexture(buttonTextures);
|
||||
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
this.drawTexturedModalRect(this.xPosition + (int)(sliderValue * (float)(this.width - 8)), this.yPosition, 0, 66, 4, 20);
|
||||
this.drawTexturedModalRect(this.xPosition + (int)(sliderValue * (float)(this.width - 8)) + 4, this.yPosition, 196, 66, 4, 20);
|
||||
}
|
||||
}
|
||||
|
||||
public static String translate(int value) {
|
||||
if(value == 0) {
|
||||
return "Unlimited";
|
||||
} else {
|
||||
return convertToStringRepresentation(value);
|
||||
}
|
||||
}
|
||||
|
||||
public static int convertScale(float value) {
|
||||
if(value == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
if(value > 20) {
|
||||
value = 1024+((value-20)*1024);
|
||||
} else {
|
||||
value = value*50;
|
||||
}
|
||||
if(value == 1000) {
|
||||
value = 1024;
|
||||
}
|
||||
return Math.round(value);
|
||||
}
|
||||
}
|
||||
|
||||
public static int convertScaleRet(float value) {
|
||||
if(value == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
if(value >= 1024) {
|
||||
value = 20+((value-1024)/1024);
|
||||
} else {
|
||||
value = value/50;
|
||||
}
|
||||
if(value == 1024) {
|
||||
value = 1000;
|
||||
}
|
||||
return Math.round(value);
|
||||
}
|
||||
}
|
||||
|
||||
public static String convertToStringRepresentation(final long value){
|
||||
long M = 1;
|
||||
long G = 1024;
|
||||
long T = G * 1024;
|
||||
|
||||
final long[] dividers = new long[] { T, G, M};
|
||||
final String[] units = new String[] { "TB", "GB", "MB"};
|
||||
if(value < 1)
|
||||
throw new IllegalArgumentException("Invalid file size: " + value);
|
||||
String result = null;
|
||||
for(int i = 0; i < dividers.length; i++){
|
||||
final long divider = dividers[i];
|
||||
if(value >= divider){
|
||||
result = format(value, divider, units[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String format(final long value,
|
||||
final long divider,
|
||||
final String unit){
|
||||
final double result =
|
||||
divider > 1 ? (double) value / (double) divider : (double) value;
|
||||
return String.format("%.0f %s", Double.valueOf(result), unit);
|
||||
}
|
||||
|
||||
public float normalizedToReal(float value) {
|
||||
float min = 0 - valueMin;
|
||||
float max = valueMax + min;
|
||||
|
||||
return Math.round(value*(max) - min);
|
||||
}
|
||||
|
||||
public float realToNormalized(float value) {
|
||||
float min = 0 - valueMin;
|
||||
float max = valueMax + min;
|
||||
|
||||
return value/(max) - min;
|
||||
}
|
||||
|
||||
public float normalizeValue(float p_148266_1_)
|
||||
{
|
||||
return MathHelper.clamp_float((this.snapToStepClamp(p_148266_1_) - this.valueMin) / (this.valueMax - this.valueMin), 0.0F, 1.0F);
|
||||
}
|
||||
|
||||
public float denormalizeValue(float p_148262_1_)
|
||||
{
|
||||
return this.snapToStepClamp(this.valueMin + (this.valueMax - this.valueMin) * MathHelper.clamp_float(p_148262_1_, 0.0F, 1.0F));
|
||||
}
|
||||
|
||||
public float snapToStepClamp(float p_148268_1_)
|
||||
{
|
||||
p_148268_1_ = this.snapToStep(p_148268_1_);
|
||||
return MathHelper.clamp_float(p_148268_1_, this.valueMin, this.valueMax);
|
||||
}
|
||||
|
||||
protected float snapToStep(float p_148264_1_)
|
||||
{
|
||||
if (this.valueStep > 0.0F)
|
||||
{
|
||||
p_148264_1_ = this.valueStep * (float)Math.round(p_148264_1_ / this.valueStep);
|
||||
}
|
||||
|
||||
return p_148264_1_;
|
||||
}
|
||||
|
||||
public boolean mousePressed(Minecraft mc, int mouseX, int mouseY)
|
||||
{
|
||||
if (super.mousePressed(mc, mouseX, mouseY))
|
||||
{
|
||||
this.dragging = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void mouseReleased(int mouseX, int mouseY)
|
||||
{
|
||||
this.dragging = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package eu.crushedpixel.replaymod.gui;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
|
||||
public class GuiVideoFramerateSlider extends GuiButton {
|
||||
|
||||
public GuiVideoFramerateSlider(int buttonId, int p_i45017_2_, int p_i45017_3_, int initialFramerate, String displayKey) {
|
||||
super(buttonId, p_i45017_2_, p_i45017_3_, 150, 20, "");
|
||||
this.sliderValue = normalizeValue(initialFramerate);
|
||||
this.displayString = displayKey+": "+translate(initialFramerate);
|
||||
this.displayKey = displayKey;
|
||||
}
|
||||
|
||||
private String displayKey;
|
||||
private float sliderValue;
|
||||
public boolean dragging;
|
||||
|
||||
private String translate(int value) {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
|
||||
protected int getHoverState(boolean mouseOver) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseDragged(Minecraft mc, int mouseX, int mouseY) {
|
||||
if (this.visible) {
|
||||
if (this.dragging) {
|
||||
sliderValue = (float)(mouseX - (this.xPosition + 4)) / (float)(this.width - 8);
|
||||
sliderValue = MathHelper.clamp_float(sliderValue, 0.0F, 1.0F);
|
||||
int f = denormalizeValue(sliderValue);
|
||||
this.displayString = displayKey+": "+translate(f);
|
||||
ReplayMod.replaySettings.setVideoFramerate(f);
|
||||
}
|
||||
|
||||
mc.getTextureManager().bindTexture(buttonTextures);
|
||||
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
this.drawTexturedModalRect(this.xPosition + (int)(sliderValue * (float)(this.width - 8)), this.yPosition, 0, 66, 4, 20);
|
||||
this.drawTexturedModalRect(this.xPosition + (int)(sliderValue * (float)(this.width - 8)) + 4, this.yPosition, 196, 66, 4, 20);
|
||||
}
|
||||
}
|
||||
|
||||
private float normalizeValue(int val) {
|
||||
return (val-10)/110f;
|
||||
}
|
||||
|
||||
private int denormalizeValue(float val) {
|
||||
//Transfers the value ranging from 0.0 to 1.0 to the scale of 10 to 120
|
||||
float r = 110f*val;
|
||||
return Math.round(10+r);
|
||||
}
|
||||
|
||||
public boolean mousePressed(Minecraft mc, int mouseX, int mouseY) {
|
||||
if (super.mousePressed(mc, mouseX, mouseY)) {
|
||||
this.dragging = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void mouseReleased(int mouseX, int mouseY) {
|
||||
this.dragging = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package eu.crushedpixel.replaymod.gui;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
|
||||
public class GuiVideoQualitySlider extends GuiButton {
|
||||
|
||||
public GuiVideoQualitySlider(int buttonId, int p_i45017_2_, int p_i45017_3_, float initialQuality, String displayKey) {
|
||||
super(buttonId, p_i45017_2_, p_i45017_3_, 150, 20, "");
|
||||
this.sliderValue = normalizeValue(initialQuality);
|
||||
this.displayString = displayKey+": "+translate(initialQuality);
|
||||
this.displayKey = displayKey;
|
||||
}
|
||||
|
||||
private String displayKey;
|
||||
private float sliderValue;
|
||||
public boolean dragging;
|
||||
|
||||
private String translate(float value) {
|
||||
if(value <= 0.3) {
|
||||
return "Draft";
|
||||
} else if(value <= 0.5) {
|
||||
return "Normal";
|
||||
} else if(value <= 0.7) {
|
||||
return "Good";
|
||||
}
|
||||
return "Best";
|
||||
}
|
||||
|
||||
protected int getHoverState(boolean mouseOver) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseDragged(Minecraft mc, int mouseX, int mouseY) {
|
||||
if (this.visible) {
|
||||
if (this.dragging) {
|
||||
sliderValue = (float)(mouseX - (this.xPosition + 4)) / (float)(this.width - 8);
|
||||
sliderValue = MathHelper.clamp_float(sliderValue, 0.0F, 1.0F);
|
||||
float f = denormalizeValue(sliderValue);
|
||||
f = snapValue(f);
|
||||
sliderValue = normalizeValue(f);
|
||||
this.displayString = displayKey+": "+translate(f);
|
||||
ReplayMod.replaySettings.setVideoQuality(f);
|
||||
}
|
||||
|
||||
mc.getTextureManager().bindTexture(buttonTextures);
|
||||
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
this.drawTexturedModalRect(this.xPosition + (int)(sliderValue * (float)(this.width - 8)), this.yPosition, 0, 66, 4, 20);
|
||||
this.drawTexturedModalRect(this.xPosition + (int)(sliderValue * (float)(this.width - 8)) + 4, this.yPosition, 196, 66, 4, 20);
|
||||
}
|
||||
}
|
||||
|
||||
private float snapValue(float val) {
|
||||
int i = Math.round(val*10);
|
||||
return i/10f;
|
||||
}
|
||||
|
||||
private float normalizeValue(float val) {
|
||||
return (val-0.1f)/0.8f;
|
||||
}
|
||||
|
||||
private float denormalizeValue(float val) {
|
||||
//Transfers the value ranging from 0.0 to 1.0 to the scale of 0.1 to 0.9
|
||||
float r = 0.8f*val;
|
||||
return 0.1f+r;
|
||||
}
|
||||
|
||||
public boolean mousePressed(Minecraft mc, int mouseX, int mouseY) {
|
||||
if (super.mousePressed(mc, mouseX, mouseY)) {
|
||||
this.dragging = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void mouseReleased(int mouseX, int mouseY) {
|
||||
this.dragging = false;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package eu.crushedpixel.replaymod.gui.online;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -14,19 +15,26 @@ import net.minecraft.client.resources.I18n;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import scala.actors.threadpool.Arrays;
|
||||
|
||||
import com.mojang.realmsclient.gui.GuiCallback;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.api.client.ApiException;
|
||||
import eu.crushedpixel.replaymod.api.client.holders.FileInfo;
|
||||
import eu.crushedpixel.replaymod.gui.GuiConstants;
|
||||
import eu.crushedpixel.replaymod.gui.GuiReplayListExtended;
|
||||
import eu.crushedpixel.replaymod.gui.replaymanager.GuiReplayManager;
|
||||
import eu.crushedpixel.replaymod.online.authentication.AuthenticationHandler;
|
||||
|
||||
public class GuiReplayCenter extends GuiScreen implements GuiYesNoCallback {
|
||||
|
||||
private enum Tab {
|
||||
RECENT_FILES, BEST_FILES, MY_FILES, SEARCH;
|
||||
}
|
||||
|
||||
private GuiReplayListExtended currentList;
|
||||
|
||||
private ReplayFileList recentFileList, bestFileList, myFileList, searchFileList;
|
||||
|
||||
private Tab currentTab = Tab.RECENT_FILES;
|
||||
|
||||
@Override
|
||||
public void initGui() {
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
@@ -40,7 +48,7 @@ public class GuiReplayCenter extends GuiScreen implements GuiYesNoCallback {
|
||||
|
||||
GuiButton recentButton = new GuiButton(GuiConstants.CENTER_RECENT_BUTTON, 20, 30, "Newest Replays");
|
||||
buttonBar.add(recentButton);
|
||||
|
||||
|
||||
GuiButton bestButton = new GuiButton(GuiConstants.CENTER_BEST_BUTTON, 20, 30, "Best Replays");
|
||||
buttonBar.add(bestButton);
|
||||
|
||||
@@ -70,7 +78,7 @@ public class GuiReplayCenter extends GuiScreen implements GuiYesNoCallback {
|
||||
|
||||
GuiButton exitButton = new GuiButton(GuiConstants.CENTER_BACK_BUTTON, 20, 20, "Main Menu");
|
||||
bottomBar.add(exitButton);
|
||||
|
||||
|
||||
GuiButton managerButton = new GuiButton(GuiConstants.CENTER_MANAGER_BUTTON, 20, 20, "Replay Manager");
|
||||
bottomBar.add(managerButton);
|
||||
|
||||
@@ -91,7 +99,7 @@ public class GuiReplayCenter extends GuiScreen implements GuiYesNoCallback {
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
showOnlineRecent();
|
||||
}
|
||||
|
||||
@@ -107,11 +115,11 @@ public class GuiReplayCenter extends GuiScreen implements GuiYesNoCallback {
|
||||
} else if(button.id == GuiConstants.CENTER_RECENT_BUTTON) {
|
||||
showOnlineRecent();
|
||||
} else if(button.id == GuiConstants.CENTER_BEST_BUTTON) {
|
||||
|
||||
|
||||
} else if(button.id == GuiConstants.CENTER_MY_REPLAYS_BUTTON) {
|
||||
|
||||
|
||||
} else if(button.id == GuiConstants.CENTER_SEARCH_BUTTON) {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,22 +152,66 @@ public class GuiReplayCenter extends GuiScreen implements GuiYesNoCallback {
|
||||
this.drawDefaultBackground();
|
||||
this.drawCenteredString(fontRendererObj, "Replay Center", this.width/2, 8, Color.WHITE.getRGB());
|
||||
|
||||
if(currentList != null) {
|
||||
currentList.drawScreen(mouseX, mouseY, partialTicks);
|
||||
}
|
||||
|
||||
super.drawScreen(mouseX, mouseY, partialTicks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMouseInput() throws IOException {
|
||||
super.handleMouseInput();
|
||||
if(currentList != null) {
|
||||
this.currentList.handleMouseInput();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
|
||||
super.mouseClicked(mouseX, mouseY, mouseButton);
|
||||
if(currentList != null) {
|
||||
this.currentList.mouseClicked(mouseX, mouseY, mouseButton);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseReleased(int mouseX, int mouseY, int state) {
|
||||
super.mouseReleased(mouseX, mouseY, state);
|
||||
if(currentList != null) {
|
||||
this.currentList.mouseReleased(mouseX, mouseY, state);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGuiClosed() {
|
||||
Keyboard.enableRepeatEvents(false);
|
||||
}
|
||||
|
||||
public void showOnlineRecent() {
|
||||
mc.addScheduledTask(new Runnable() {
|
||||
Thread t = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if(recentFileList == null) {
|
||||
recentFileList = new ReplayFileList(mc, width, height, 50, height-40, 36);
|
||||
} else {
|
||||
recentFileList.clearEntries();
|
||||
recentFileList.width = width;
|
||||
recentFileList.height = height;
|
||||
recentFileList.top = 50;
|
||||
recentFileList.bottom = height-40;
|
||||
}
|
||||
currentTab = Tab.RECENT_FILES;
|
||||
currentList = recentFileList;
|
||||
FileInfo[] files = ReplayMod.apiClient.getRecentFiles();
|
||||
for(FileInfo i : files) {
|
||||
//TODO: Display the Files
|
||||
File tmp = null;
|
||||
if(i.hasThumbnail()) {
|
||||
tmp = File.createTempFile("thumb_online_"+i.getId(), "jpg");
|
||||
ReplayMod.apiClient.downloadThumbnail(i.getId(), tmp);
|
||||
}
|
||||
recentFileList.addEntry(i.getName(), i.getMetadata(), tmp);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
@@ -168,7 +220,8 @@ public class GuiReplayCenter extends GuiScreen implements GuiYesNoCallback {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
t.start();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package eu.crushedpixel.replaymod.gui.online;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import eu.crushedpixel.replaymod.gui.GuiReplayListExtended;
|
||||
|
||||
public class ReplayFileList extends GuiReplayListExtended {
|
||||
|
||||
public ReplayFileList(Minecraft mcIn, int p_i45010_2_, int p_i45010_3_,
|
||||
int p_i45010_4_, int p_i45010_5_, int p_i45010_6_) {
|
||||
super(mcIn, p_i45010_2_, p_i45010_3_, p_i45010_4_, p_i45010_5_, p_i45010_6_);
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import org.lwjgl.input.Keyboard;
|
||||
import com.google.gson.Gson;
|
||||
import com.mojang.realmsclient.util.Pair;
|
||||
|
||||
import eu.crushedpixel.replaymod.gui.GuiReplayListExtended;
|
||||
import eu.crushedpixel.replaymod.gui.GuiReplaySettings;
|
||||
import eu.crushedpixel.replaymod.gui.online.GuiUploadFile;
|
||||
import eu.crushedpixel.replaymod.online.authentication.AuthenticationHandler;
|
||||
@@ -95,16 +96,14 @@ public class GuiReplayManager extends GuiScreen implements GuiYesNoCallback {
|
||||
img = ImageUtils.scaleImage(bimg, new Dimension(1280, 720));
|
||||
}
|
||||
}
|
||||
|
||||
//If thumb is null, set image to placeholder
|
||||
if(img == null) {
|
||||
img = ImageIO.read(MCPNames.class.getClassLoader().getResourceAsStream("default_thumb.jpg"));
|
||||
|
||||
File tmp = null;
|
||||
if(img != null) {
|
||||
tmp = File.createTempFile(FilenameUtils.getBaseName(file.getAbsolutePath()), "jpg");
|
||||
tmp.deleteOnExit();
|
||||
|
||||
ImageIO.write(img, "jpg", tmp);
|
||||
}
|
||||
|
||||
File tmp = File.createTempFile(FilenameUtils.getBaseName(file.getAbsolutePath()), "jpg");
|
||||
tmp.deleteOnExit();
|
||||
|
||||
ImageIO.write(img, "jpg", tmp);
|
||||
|
||||
InputStream is = archive.getInputStream(metadata);
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(is));
|
||||
@@ -116,9 +115,7 @@ public class GuiReplayManager extends GuiScreen implements GuiYesNoCallback {
|
||||
replayFileList.add(Pair.of(Pair.of(file, metaData), tmp));
|
||||
|
||||
archive.close();
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch(Exception e) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +141,7 @@ public class GuiReplayManager extends GuiScreen implements GuiYesNoCallback {
|
||||
|
||||
@Override
|
||||
public void initGui() {
|
||||
replayGuiList = new GuiReplayListExtended(this, this.mc, this.width, this.height, 32, this.height - 64, 36);
|
||||
replayGuiList = new ReplayManagerReplayList(this, this.mc, this.width, this.height, 32, this.height - 64, 36);
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
this.buttonList.clear();
|
||||
|
||||
@@ -170,26 +167,26 @@ public class GuiReplayManager extends GuiScreen implements GuiYesNoCallback {
|
||||
setButtonsEnabled(false);
|
||||
}
|
||||
|
||||
public void handleMouseInput() throws IOException
|
||||
{
|
||||
@Override
|
||||
public void handleMouseInput() throws IOException {
|
||||
super.handleMouseInput();
|
||||
this.replayGuiList.handleMouseInput();
|
||||
}
|
||||
|
||||
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException
|
||||
{
|
||||
@Override
|
||||
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
|
||||
super.mouseClicked(mouseX, mouseY, mouseButton);
|
||||
this.replayGuiList.mouseClicked(mouseX, mouseY, mouseButton);
|
||||
}
|
||||
|
||||
protected void mouseReleased(int mouseX, int mouseY, int state)
|
||||
{
|
||||
@Override
|
||||
protected void mouseReleased(int mouseX, int mouseY, int state) {
|
||||
super.mouseReleased(mouseX, mouseY, state);
|
||||
this.replayGuiList.mouseReleased(mouseX, mouseY, state);
|
||||
}
|
||||
|
||||
public void drawScreen(int mouseX, int mouseY, float partialTicks)
|
||||
{
|
||||
@Override
|
||||
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
|
||||
this.hoveringText = null;
|
||||
this.drawDefaultBackground();
|
||||
this.replayGuiList.drawScreen(mouseX, mouseY, partialTicks);
|
||||
@@ -198,8 +195,7 @@ public class GuiReplayManager extends GuiScreen implements GuiYesNoCallback {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void actionPerformed(GuiButton button) throws IOException
|
||||
{
|
||||
protected void actionPerformed(GuiButton button) throws IOException {
|
||||
if(button.enabled) {
|
||||
if(button.id == LOAD_BUTTON_ID) {
|
||||
loadReplay(replayGuiList.selected);
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package eu.crushedpixel.replaymod.gui.replaymanager;
|
||||
|
||||
import eu.crushedpixel.replaymod.gui.GuiReplayListExtended;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
public class ReplayManagerReplayList extends GuiReplayListExtended {
|
||||
|
||||
private GuiReplayManager parent;
|
||||
|
||||
public ReplayManagerReplayList(GuiReplayManager parent, Minecraft mcIn,
|
||||
int p_i45010_2_, int p_i45010_3_, int p_i45010_4_, int p_i45010_5_,
|
||||
int p_i45010_6_) {
|
||||
super(mcIn, p_i45010_2_, p_i45010_3_, p_i45010_4_, p_i45010_5_,
|
||||
p_i45010_6_);
|
||||
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void elementClicked(int slotIndex, boolean isDoubleClick,
|
||||
int mouseX, int mouseY) {
|
||||
super.elementClicked(slotIndex, isDoubleClick, mouseX, mouseY);
|
||||
parent.setButtonsEnabled(true);
|
||||
if(isDoubleClick) {
|
||||
parent.loadReplay(slotIndex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,29 +1,47 @@
|
||||
package eu.crushedpixel.replaymod.gui.replaymanager;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import eu.crushedpixel.replaymod.reflection.MCPNames;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class ResourceHelper {
|
||||
|
||||
private static BufferedImage defaultThumb;
|
||||
|
||||
static {
|
||||
try {
|
||||
defaultThumb = ImageIO.read(MCPNames.class.getClassLoader().getResourceAsStream("default_thumb.jpg"));
|
||||
} catch(Exception e) {
|
||||
defaultThumb = new BufferedImage(1, 1, BufferedImage.TYPE_3BYTE_BGR);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
private static List<ResourceLocation> openResources = new ArrayList<ResourceLocation>();
|
||||
|
||||
|
||||
public static void registerResource(ResourceLocation loc) {
|
||||
openResources.add(loc);
|
||||
}
|
||||
|
||||
|
||||
public static void freeResource(ResourceLocation loc) {
|
||||
Minecraft.getMinecraft().getTextureManager().deleteTexture(loc);
|
||||
openResources.remove(loc);
|
||||
}
|
||||
|
||||
|
||||
public static void freeAllResources() {
|
||||
for(ResourceLocation loc : openResources) {
|
||||
Minecraft.getMinecraft().getTextureManager().deleteTexture(loc);
|
||||
}
|
||||
|
||||
|
||||
openResources = new ArrayList<ResourceLocation>();
|
||||
}
|
||||
|
||||
public static BufferedImage getDefaultThumbnail() {
|
||||
return defaultThumb;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,5 +63,8 @@ public class Position {
|
||||
this.yaw = yaw;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "X="+x+", Y="+y+", Z="+z+", Yaw="+yaw+", Pitch="+pitch;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,10 @@ import akka.japi.Pair;
|
||||
|
||||
public abstract class LinearInterpolation<K> {
|
||||
|
||||
public LinearInterpolation() {
|
||||
points = new ArrayList<K>();
|
||||
}
|
||||
|
||||
protected List<K> points = new ArrayList<K>();
|
||||
|
||||
public abstract K getPoint(float position);
|
||||
@@ -21,9 +25,9 @@ public abstract class LinearInterpolation<K> {
|
||||
|
||||
protected Pair<Float, Pair<K, K>> getCurrentPoints(float position) {
|
||||
if(points.size() == 0) return null;
|
||||
float pos = position * (points.size()-1);
|
||||
int cubicNum = Math.round(pos);
|
||||
float cubicPos = (pos - cubicNum);
|
||||
position = position * (points.size()-1);
|
||||
int cubicNum = (int)Math.min(points.size()-1, position);
|
||||
float cubicPos = (position - cubicNum);
|
||||
|
||||
if(cubicNum == points.size()-1) {
|
||||
cubicNum--;
|
||||
|
||||
@@ -6,11 +6,16 @@ import eu.crushedpixel.replaymod.holders.Position;
|
||||
public class LinearPoint extends LinearInterpolation<Position> {
|
||||
|
||||
@Override
|
||||
public Position getPoint(float position) {
|
||||
Pair<Float, Pair<Position, Position>> pair = getCurrentPoints(position);
|
||||
public Position getPoint(float positionIn) {
|
||||
Pair<Float, Pair<Position, Position>> pair = getCurrentPoints(positionIn);
|
||||
if(pair == null) return null;
|
||||
|
||||
float perc = pair.first();
|
||||
//float position = positionIn * (points.size()-1);
|
||||
//int cubicNum = (int)Math.min(points.size()-1, position);
|
||||
//float perc = (position - cubicNum);
|
||||
|
||||
//System.out.println(cubicNum+" | "+perc+" | "+positionIn);
|
||||
|
||||
Position first = pair.second().first();
|
||||
Position second = pair.second().second();
|
||||
@@ -23,7 +28,7 @@ public class LinearPoint extends LinearInterpolation<Position> {
|
||||
float yaw = (float)getInterpolatedValue(first.getYaw(), second.getYaw(), perc);
|
||||
|
||||
Position inter = new Position(x, y, z, pitch, yaw);
|
||||
//System.out.println(position+" | "+cubicNum+" | "+perc+" | "+first+" | "+second+" | "+inter);
|
||||
return inter;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -99,12 +99,10 @@ public class ConnectionEventHandler {
|
||||
|
||||
currentFile.createNewFile();
|
||||
|
||||
int maxFileSize = ReplayMod.replaySettings.getMaximumFileSize();
|
||||
|
||||
PacketListener insert = null;
|
||||
|
||||
pipeline.addBefore(packetHandlerKey, "replay_recorder", insert = new PacketListener
|
||||
(currentFile, fileName, worldName, System.currentTimeMillis(), maxFileSize, event.isLocal));
|
||||
(currentFile, fileName, worldName, System.currentTimeMillis(), event.isLocal));
|
||||
ChatMessageRequests.addChatMessage("Recording started!", ChatMessageType.INFORMATION);
|
||||
isRecording = true;
|
||||
|
||||
|
||||
@@ -31,8 +31,6 @@ public abstract class DataListener extends ChannelInboundHandlerAdapter {
|
||||
|
||||
protected File file;
|
||||
protected Long startTime = null;
|
||||
protected long maxSize;
|
||||
protected long totalBytes = 0;
|
||||
protected String name;
|
||||
protected String worldName;
|
||||
|
||||
@@ -53,10 +51,9 @@ public abstract class DataListener extends ChannelInboundHandlerAdapter {
|
||||
System.out.println(worldName);
|
||||
}
|
||||
|
||||
public DataListener(File file, String name, String worldName, long startTime, int maxSize, boolean singleplayer) throws FileNotFoundException {
|
||||
public DataListener(File file, String name, String worldName, long startTime, boolean singleplayer) throws FileNotFoundException {
|
||||
this.file = file;
|
||||
this.startTime = startTime;
|
||||
this.maxSize = maxSize*1024*1024;
|
||||
this.name = name;
|
||||
this.worldName = worldName;
|
||||
this.singleplayer = singleplayer;
|
||||
|
||||
@@ -24,8 +24,8 @@ import eu.crushedpixel.replaymod.reflection.MCPNames;
|
||||
|
||||
public class PacketListener extends DataListener {
|
||||
|
||||
public PacketListener(File file, String name, String worldName, long startTime, int maxSize, boolean singleplayer) throws FileNotFoundException {
|
||||
super(file, name, worldName, startTime, maxSize, singleplayer);
|
||||
public PacketListener(File file, String name, String worldName, long startTime, boolean singleplayer) throws FileNotFoundException {
|
||||
super(file, name, worldName, startTime, singleplayer);
|
||||
}
|
||||
|
||||
private static final Minecraft mc = Minecraft.getMinecraft();
|
||||
@@ -132,13 +132,6 @@ public class PacketListener extends DataListener {
|
||||
byte[] array = new byte[bb.readableBytes()];
|
||||
bb.readBytes(array);
|
||||
|
||||
totalBytes += (array.length + (2*4)); //two Integer values and the Packet size
|
||||
if(totalBytes >= maxSize && maxSize > 0) {
|
||||
ChatMessageRequests.addChatMessage("Maximum file size exceeded", ChatMessageType.WARNING);
|
||||
ChatMessageRequests.addChatMessage("The Recording has been stopped", ChatMessageType.WARNING);
|
||||
alive = false;
|
||||
}
|
||||
|
||||
bb.readerIndex(0);
|
||||
|
||||
return new PacketData(array, timestamp);
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
package eu.crushedpixel.replaymod.replay;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.util.Timer;
|
||||
import eu.crushedpixel.replaymod.reflection.MCPNames;
|
||||
import eu.crushedpixel.replaymod.video.ReplayTimer;
|
||||
|
||||
public class MCTimerHandler {
|
||||
|
||||
private static Field mcTimer;
|
||||
private static Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
private static ReplayTimer rpt = new ReplayTimer(20);
|
||||
private static Timer timerBefore;
|
||||
|
||||
static {
|
||||
try {
|
||||
mcTimer = Minecraft.class.getDeclaredField(MCPNames.field("field_71428_T"));
|
||||
mcTimer.setAccessible(true);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setActiveTimer() {
|
||||
try {
|
||||
if(timerBefore != null) {
|
||||
mcTimer.set(mc, timerBefore);
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setPassiveTimer() {
|
||||
try {
|
||||
if(!(getTimer() instanceof ReplayTimer)) {
|
||||
timerBefore = getTimer();
|
||||
System.out.println("here");
|
||||
mcTimer.set(mc, rpt);
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static int getTicks() {
|
||||
try {
|
||||
Timer t = getTimer();
|
||||
return t.elapsedTicks;
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static float getPartialTicks() {
|
||||
try {
|
||||
Timer t = getTimer();
|
||||
return t.elapsedPartialTicks;
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static float getRenderTicks() {
|
||||
try {
|
||||
Timer t = getTimer();
|
||||
return t.renderPartialTicks;
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static Timer getTimer() throws IllegalArgumentException, IllegalAccessException {
|
||||
return (Timer)mcTimer.get(mc);
|
||||
}
|
||||
|
||||
public static void advanceTicks(int ticks) {
|
||||
try {
|
||||
Timer t = getTimer();
|
||||
t.elapsedTicks += ticks;
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void advancePartialTicks(float ticks) {
|
||||
try {
|
||||
Timer t = getTimer();
|
||||
t.elapsedPartialTicks += ticks;
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void advanceRenderPartialTicks(float ticks) {
|
||||
try {
|
||||
Timer t = getTimer();
|
||||
t.renderPartialTicks += ticks;
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setTimerSpeed(float speed) {
|
||||
try {
|
||||
Timer t = getTimer();
|
||||
t.timerSpeed = speed;
|
||||
if(timerBefore != null) {
|
||||
timerBefore.timerSpeed = speed;
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setRenderPartialTicks(float ticks) {
|
||||
try {
|
||||
getTimer().renderPartialTicks = ticks;
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setPartialTicks(float ticks) {
|
||||
try {
|
||||
getTimer().elapsedPartialTicks = ticks;
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setTicks(int ticks) {
|
||||
try {
|
||||
getTimer().elapsedTicks = ticks;
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static float getTimerSpeed() {
|
||||
try {
|
||||
return getTimer().timerSpeed;
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static void updateTimer(double d) {
|
||||
try{
|
||||
Timer t = getTimer();
|
||||
double d2 = d;
|
||||
d2 = MathHelper.clamp_double(d2, 0.0D, 1.0D);
|
||||
t.elapsedPartialTicks = (float)((double)t.elapsedPartialTicks + d2 * (double)t.timerSpeed * 20);
|
||||
t.elapsedTicks = (int)t.elapsedPartialTicks;
|
||||
t.elapsedPartialTicks -= (float)t.elapsedTicks;
|
||||
|
||||
if (t.elapsedTicks > 10)
|
||||
{
|
||||
t.elapsedTicks = 10;
|
||||
}
|
||||
|
||||
t.renderPartialTicks = t.elapsedPartialTicks;
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ 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.Packet;
|
||||
import net.minecraft.network.play.INetHandlerPlayClient;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
@@ -27,7 +28,6 @@ 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 {
|
||||
|
||||
@@ -54,6 +54,15 @@ public class ReplayHandler {
|
||||
|
||||
private static Entity currentEntity = null;
|
||||
|
||||
public static void insertPacketInstantly(Packet p) {
|
||||
if(replaySender != null) {
|
||||
try {
|
||||
replaySender.channelRead(null, p);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void spectateEntity(Entity e) {
|
||||
currentEntity = e;
|
||||
mc.setRenderViewEntity(currentEntity);
|
||||
@@ -88,8 +97,8 @@ public class ReplayHandler {
|
||||
isReplaying = replaying;
|
||||
}
|
||||
|
||||
public static void startPath() {
|
||||
ReplayProcess.startReplayProcess();
|
||||
public static void startPath(boolean save) {
|
||||
if(!ReplayHandler.isReplaying()) ReplayProcess.startReplayProcess(save);
|
||||
}
|
||||
|
||||
public static void interruptReplay() {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package eu.crushedpixel.replaymod.replay;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
@@ -12,6 +14,8 @@ import eu.crushedpixel.replaymod.holders.TimeKeyframe;
|
||||
import eu.crushedpixel.replaymod.interpolation.LinearPoint;
|
||||
import eu.crushedpixel.replaymod.interpolation.LinearTimestamp;
|
||||
import eu.crushedpixel.replaymod.interpolation.SplinePoint;
|
||||
import eu.crushedpixel.replaymod.video.ScreenCapture;
|
||||
import eu.crushedpixel.replaymod.video.VideoWriter;
|
||||
|
||||
public class ReplayProcess {
|
||||
|
||||
@@ -31,15 +35,23 @@ public class ReplayProcess {
|
||||
private static LinearTimestamp timeLinear = null;
|
||||
|
||||
private static double previousReplaySpeed = 0;
|
||||
|
||||
|
||||
private static boolean calculated = false;
|
||||
|
||||
public static void startReplayProcess() {
|
||||
private static boolean isVideoRecording = false;
|
||||
|
||||
public static boolean isVideoRecording() {
|
||||
return isVideoRecording;
|
||||
}
|
||||
|
||||
public static void startReplayProcess(boolean record) {
|
||||
isVideoRecording = record;
|
||||
lastPosition = null;
|
||||
motionSpline = null;
|
||||
timeLinear = null;
|
||||
calculated = false;
|
||||
|
||||
requestFinish = false;
|
||||
|
||||
ChatMessageRequests.initialize();
|
||||
if(ReplayHandler.getPosKeyframeCount() < 2) {
|
||||
ChatMessageRequests.addChatMessage("At least 2 position keyframes required!", ChatMessageType.WARNING);
|
||||
@@ -64,17 +76,69 @@ public class ReplayProcess {
|
||||
}
|
||||
|
||||
ChatMessageRequests.addChatMessage("Replay started!", ChatMessageType.INFORMATION);
|
||||
|
||||
if(isVideoRecording()) {
|
||||
ticks = 0;
|
||||
MCTimerHandler.setTimerSpeed(1);
|
||||
MCTimerHandler.setPassiveTimer();
|
||||
Thread t = new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while(ReplayHandler.isReplaying()) {
|
||||
if(!blocked) {
|
||||
mc.addScheduledTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ReplayProcess.tickReplay();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
t.start();
|
||||
}
|
||||
}
|
||||
|
||||
public static void stopReplayProcess(boolean finished) {
|
||||
if(!ReplayHandler.isReplaying()) return;
|
||||
if(finished) ChatMessageRequests.addChatMessage("Replay finished!", ChatMessageType.INFORMATION);
|
||||
else ChatMessageRequests.addChatMessage("Replay stopped!", ChatMessageType.INFORMATION);
|
||||
ReplayHandler.setReplaying(false);
|
||||
MCTimerHandler.setActiveTimer();
|
||||
ReplayHandler.setSpeed(previousReplaySpeed);
|
||||
ReplayHandler.setSpeed(0);
|
||||
}
|
||||
|
||||
public static void tickReplay() {
|
||||
private static boolean blocked = false;
|
||||
private static boolean deepBlock = false;
|
||||
|
||||
private static float ticks = 0;
|
||||
|
||||
private static boolean requestFinish = false;
|
||||
|
||||
public static void unblock() {
|
||||
if(!deepBlock) blocked = false;
|
||||
}
|
||||
|
||||
public static void tickReplay() {
|
||||
if(isVideoRecording()) {
|
||||
recordingTick();
|
||||
} else {
|
||||
normalTick();
|
||||
}
|
||||
}
|
||||
|
||||
private static void normalTick() {
|
||||
|
||||
if(ReplayHandler.isHurrying()) {
|
||||
lastRealTime = System.currentTimeMillis();
|
||||
return;
|
||||
@@ -91,7 +155,7 @@ public class ReplayProcess {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(linear && motionLinear == null) {
|
||||
//set up linear path
|
||||
motionLinear = new LinearPoint();
|
||||
@@ -115,9 +179,9 @@ public class ReplayProcess {
|
||||
|
||||
if(!calculated) {
|
||||
calculated = true;
|
||||
motionSpline.calcSpline();
|
||||
if(motionSpline != null) motionSpline.calcSpline();
|
||||
}
|
||||
|
||||
|
||||
long curTime = System.currentTimeMillis();
|
||||
long timeStep = curTime - lastRealTime;
|
||||
|
||||
@@ -169,7 +233,165 @@ public class ReplayProcess {
|
||||
if(!(nextTime == null || lastTime == null)) {
|
||||
curSpeed = ((double)((nextTime.getTimestamp()-lastTime.getTimestamp())))/((double)((nextTimeStamp-lastTimeStamp)));
|
||||
}
|
||||
|
||||
|
||||
if(lastTimeStamp == nextTimeStamp) {
|
||||
curSpeed = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
int currentDiff = nextPosStamp - lastPosStamp;
|
||||
int current = curRealReplayTime - lastPosStamp;
|
||||
|
||||
float currentStepPerc = (float)current/(float)currentDiff; //The percentage of the travelled path between the current positions
|
||||
if(Float.isInfinite(currentStepPerc)) currentStepPerc = 0;
|
||||
|
||||
float splinePos = ((float)ReplayHandler.getKeyframeIndex(lastPos) + currentStepPerc)/(float)(ReplayHandler.getPosKeyframeCount()-1);
|
||||
float timePos = ((float)ReplayHandler.getKeyframeIndex(lastTime) + currentStepPerc)/(float)(ReplayHandler.getTimeKeyframeCount()-1);
|
||||
|
||||
Position pos = null;
|
||||
if(!linear) {
|
||||
pos = motionSpline.getPoint(Math.max(0, Math.min(1, splinePos)));
|
||||
} else {
|
||||
pos = motionLinear.getPoint(Math.max(0, Math.min(1, splinePos)));
|
||||
}
|
||||
|
||||
Integer curPos = null;
|
||||
if(timeLinear != null) {
|
||||
curPos = timeLinear.getPoint(Math.max(0, Math.min(1, timePos)));
|
||||
}
|
||||
|
||||
if(pos != null) ReplayHandler.getCameraEntity().movePath(pos);
|
||||
|
||||
ReplayHandler.setSpeed(curSpeed);
|
||||
|
||||
if(curPos != null) ReplayHandler.setReplayPos(curPos);
|
||||
|
||||
//splinePos = (index of last entry + add) / total entries
|
||||
|
||||
lastRealReplayTime = curRealReplayTime;
|
||||
lastRealTime = curTime;
|
||||
|
||||
if(requestFinish) {
|
||||
stopReplayProcess(true);
|
||||
requestFinish = false;
|
||||
}
|
||||
|
||||
if(splinePos >= 1) {
|
||||
requestFinish = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static void recordingTick() {
|
||||
if(ReplayHandler.isHurrying()) {
|
||||
if(!isVideoRecording()) {
|
||||
lastRealTime = System.currentTimeMillis();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(blocked && isVideoRecording()) {
|
||||
return;
|
||||
}
|
||||
deepBlock = true;
|
||||
blocked = true;
|
||||
|
||||
if(!linear && motionSpline == null) {
|
||||
//set up spline path
|
||||
motionSpline = new SplinePoint();
|
||||
for(Keyframe kf : ReplayHandler.getKeyframes()) {
|
||||
if(kf instanceof PositionKeyframe) {
|
||||
PositionKeyframe pkf = (PositionKeyframe)kf;
|
||||
Position pos = pkf.getPosition();
|
||||
motionSpline.addPoint(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(linear && motionLinear == null) {
|
||||
//set up linear path
|
||||
motionLinear = new LinearPoint();
|
||||
for(Keyframe kf : ReplayHandler.getKeyframes()) {
|
||||
if(kf instanceof PositionKeyframe) {
|
||||
PositionKeyframe pkf = (PositionKeyframe)kf;
|
||||
Position pos = pkf.getPosition();
|
||||
motionLinear.addPoint(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(timeLinear == null) {
|
||||
timeLinear = new LinearTimestamp();
|
||||
for(Keyframe kf : ReplayHandler.getKeyframes()) {
|
||||
if(kf instanceof TimeKeyframe) {
|
||||
timeLinear.addPoint(((TimeKeyframe)kf).getTimestamp());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(!calculated) {
|
||||
calculated = true;
|
||||
motionSpline.calcSpline();
|
||||
}
|
||||
|
||||
long timeStep;
|
||||
|
||||
long curTime = System.currentTimeMillis();
|
||||
|
||||
if(isVideoRecording()) {
|
||||
timeStep = 1000/ReplayMod.replaySettings.getVideoFramerate();
|
||||
} else {
|
||||
timeStep = curTime - lastRealTime;
|
||||
}
|
||||
|
||||
int curRealReplayTime = (int)(lastRealReplayTime + timeStep);
|
||||
|
||||
PositionKeyframe lastPos = ReplayHandler.getPreviousPositionKeyframe(curRealReplayTime);
|
||||
PositionKeyframe nextPos = ReplayHandler.getNextPositionKeyframe(curRealReplayTime);
|
||||
|
||||
ReplayHandler.setRealTimelineCursor(curRealReplayTime);
|
||||
|
||||
int lastPosStamp = 0;
|
||||
int nextPosStamp = 0;
|
||||
|
||||
if(nextPos != null || lastPos != null) {
|
||||
if(nextPos != null) {
|
||||
nextPosStamp = nextPos.getRealTimestamp();
|
||||
} else {
|
||||
nextPosStamp = lastPos.getRealTimestamp();
|
||||
}
|
||||
|
||||
if(lastPos != null) {
|
||||
lastPosStamp = lastPos.getRealTimestamp();
|
||||
} else {
|
||||
lastPosStamp = nextPos.getRealTimestamp();
|
||||
}
|
||||
}
|
||||
|
||||
TimeKeyframe lastTime = ReplayHandler.getPreviousTimeKeyframe(curRealReplayTime);
|
||||
TimeKeyframe nextTime = ReplayHandler.getNextTimeKeyframe(curRealReplayTime);
|
||||
|
||||
int lastTimeStamp = 0;
|
||||
int nextTimeStamp = 0;
|
||||
|
||||
double curSpeed = 0f;
|
||||
|
||||
if(nextTime != null || lastTime != null) {
|
||||
if(nextTime != null) {
|
||||
nextTimeStamp = nextTime.getRealTimestamp();
|
||||
} else {
|
||||
nextTimeStamp = lastTime.getRealTimestamp();
|
||||
}
|
||||
|
||||
if(lastTime != null) {
|
||||
lastTimeStamp = lastTime.getRealTimestamp();
|
||||
} else {
|
||||
lastTimeStamp = nextTime.getRealTimestamp();
|
||||
}
|
||||
|
||||
if(!(nextTime == null || lastTime == null)) {
|
||||
curSpeed = ((double)((nextTime.getTimestamp()-lastTime.getTimestamp())))/((double)((nextTimeStamp-lastTimeStamp)));
|
||||
}
|
||||
|
||||
if(lastTimeStamp == nextTimeStamp) {
|
||||
curSpeed = 0f;
|
||||
}
|
||||
@@ -198,8 +420,10 @@ public class ReplayProcess {
|
||||
|
||||
if(pos != null) ReplayHandler.getCameraEntity().movePath(pos);
|
||||
|
||||
ReplayHandler.setSpeed(curSpeed);
|
||||
|
||||
ReplayHandler.setSpeed((float)curSpeed);
|
||||
if(isVideoRecording()) {
|
||||
MCTimerHandler.updateTimer((1f/ReplayMod.replaySettings.getVideoFramerate()));
|
||||
}
|
||||
if(curPos != null) ReplayHandler.setReplayPos(curPos);
|
||||
|
||||
//splinePos = (index of last entry + add) / total entries
|
||||
@@ -207,6 +431,28 @@ public class ReplayProcess {
|
||||
lastRealReplayTime = curRealReplayTime;
|
||||
lastRealTime = curTime;
|
||||
|
||||
if(splinePos >= 1) stopReplayProcess(true);
|
||||
//Video capturing, for testing purposes
|
||||
if(isVideoRecording()) {
|
||||
try {
|
||||
if(!VideoWriter.isRecording() && ReplayHandler.isReplaying()) {
|
||||
VideoWriter.startRecording(mc.displayWidth, mc.displayHeight);
|
||||
} else {
|
||||
VideoWriter.writeImage(ScreenCapture.captureScreen());
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if(requestFinish) {
|
||||
stopReplayProcess(true);
|
||||
VideoWriter.endRecording();
|
||||
}
|
||||
|
||||
if(splinePos >= 1) {
|
||||
requestFinish = true;
|
||||
}
|
||||
|
||||
deepBlock = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiDownloadTerrain;
|
||||
@@ -27,10 +28,12 @@ import net.minecraft.network.Packet;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.network.play.server.S01PacketJoinGame;
|
||||
import net.minecraft.network.play.server.S02PacketChat;
|
||||
import net.minecraft.network.play.server.S03PacketTimeUpdate;
|
||||
import net.minecraft.network.play.server.S06PacketUpdateHealth;
|
||||
import net.minecraft.network.play.server.S07PacketRespawn;
|
||||
import net.minecraft.network.play.server.S08PacketPlayerPosLook;
|
||||
import net.minecraft.network.play.server.S0BPacketAnimation;
|
||||
import net.minecraft.network.play.server.S0CPacketSpawnPlayer;
|
||||
import net.minecraft.network.play.server.S1CPacketEntityMetadata;
|
||||
import net.minecraft.network.play.server.S1DPacketEntityEffect;
|
||||
import net.minecraft.network.play.server.S1FPacketSetExperience;
|
||||
@@ -44,11 +47,12 @@ import net.minecraft.network.play.server.S2FPacketSetSlot;
|
||||
import net.minecraft.network.play.server.S30PacketWindowItems;
|
||||
import net.minecraft.network.play.server.S36PacketSignEditorOpen;
|
||||
import net.minecraft.network.play.server.S37PacketStatistics;
|
||||
import net.minecraft.network.play.server.S38PacketPlayerListItem;
|
||||
import net.minecraft.network.play.server.S38PacketPlayerListItem.AddPlayerData;
|
||||
import net.minecraft.network.play.server.S39PacketPlayerAbilities;
|
||||
import net.minecraft.network.play.server.S43PacketCamera;
|
||||
import net.minecraft.network.play.server.S45PacketTitle;
|
||||
import net.minecraft.network.play.server.S48PacketResourcePackSend;
|
||||
import net.minecraft.util.Timer;
|
||||
import net.minecraft.world.EnumDifficulty;
|
||||
import net.minecraft.world.WorldSettings.GameType;
|
||||
import net.minecraft.world.WorldType;
|
||||
@@ -59,6 +63,7 @@ import org.apache.commons.compress.archivers.zip.ZipFile;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.entities.CameraEntity;
|
||||
@@ -106,16 +111,6 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
private Field chatPacketPosition;
|
||||
|
||||
private Minecraft mc = Minecraft.getMinecraft();
|
||||
public static Field mcTimer;
|
||||
|
||||
static {
|
||||
try {
|
||||
mcTimer = Minecraft.class.getDeclaredField(MCPNames.field("field_71428_T"));
|
||||
mcTimer.setAccessible(true);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private long now = System.currentTimeMillis();
|
||||
|
||||
@@ -168,13 +163,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
|
||||
public void setReplaySpeed(final double d) {
|
||||
if(d != 0) this.replaySpeed = d;
|
||||
try {
|
||||
Timer timer = (Timer)mcTimer.get(mc);
|
||||
timer.timerSpeed = (float)d;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
MCTimerHandler.setTimerSpeed((float)d);
|
||||
}
|
||||
|
||||
public ReplaySender(final File replayFile, NetworkManager nm) {
|
||||
@@ -246,7 +235,6 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
try {
|
||||
dis = new DataInputStream(archive.getInputStream(replayEntry));
|
||||
} catch(Exception e) {
|
||||
@@ -267,7 +255,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
lastPacketSent = System.currentTimeMillis();
|
||||
ReplayHandler.restartReplay();
|
||||
}
|
||||
while(!startFromBeginning && (!paused() || FMLClientHandler.instance().isGUIOpen(GuiDownloadTerrain.class))) {
|
||||
while(!terminate && !startFromBeginning && (!paused() || FMLClientHandler.instance().isGUIOpen(GuiDownloadTerrain.class))) {
|
||||
try {
|
||||
|
||||
/*
|
||||
@@ -316,9 +304,9 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
if(hurryToTimestamp && currentTimeStamp >= desiredTimeStamp && !startFromBeginning) {
|
||||
hurryToTimestamp = false;
|
||||
if(!ReplayHandler.isReplaying() || hasRestarted) {
|
||||
((Timer)mcTimer.get(mc)).elapsedPartialTicks += 5;
|
||||
((Timer)mcTimer.get(mc)).elapsedTicks += 5;
|
||||
((Timer)mcTimer.get(mc)).renderPartialTicks += 5;
|
||||
MCTimerHandler.advanceRenderPartialTicks(5);
|
||||
MCTimerHandler.advancePartialTicks(5);
|
||||
MCTimerHandler.advanceTicks(5);
|
||||
}
|
||||
if(!ReplayHandler.isReplaying()) {
|
||||
Position pos = ReplayHandler.getLastPosition();
|
||||
@@ -339,8 +327,11 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
}
|
||||
|
||||
} catch(EOFException eof) {
|
||||
dis = new DataInputStream(archive.getInputStream(replayEntry));
|
||||
setReplaySpeed(0);
|
||||
} catch(IOException e) {}
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(Exception e) {
|
||||
@@ -369,6 +360,21 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
|
||||
private boolean allowMovement = false;
|
||||
|
||||
private static Field playerUUIDField;
|
||||
private static Field gameProfileField;
|
||||
|
||||
static {
|
||||
try {
|
||||
playerUUIDField = S0CPacketSpawnPlayer.class.getDeclaredField(MCPNames.field("field_179820_b"));
|
||||
playerUUIDField.setAccessible(true);
|
||||
|
||||
gameProfileField = S38PacketPlayerListItem.AddPlayerData.class.getDeclaredField("field_179964_d");
|
||||
gameProfileField.setAccessible(true);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object msg)
|
||||
throws Exception {
|
||||
@@ -376,6 +382,10 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
return;
|
||||
}
|
||||
|
||||
if(ctx == null) {
|
||||
ctx = this.ctx;
|
||||
}
|
||||
|
||||
if(msg instanceof Packet) {
|
||||
super.channelRead(ctx, msg);
|
||||
return;
|
||||
@@ -396,6 +406,10 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
p instanceof S2APacketParticles) return;
|
||||
}
|
||||
|
||||
if(p instanceof S03PacketTimeUpdate) {
|
||||
p = TimeHandler.getTimePacket((S03PacketTimeUpdate)p);
|
||||
}
|
||||
|
||||
if(p instanceof S02PacketChat) {
|
||||
byte pos = (Byte)chatPacketPosition.get(p);
|
||||
if(pos == 1) { //Ignores command block output sent
|
||||
@@ -408,22 +422,6 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
try {
|
||||
p.readPacketData(pb);
|
||||
|
||||
/*
|
||||
if(p instanceof S0CPacketSpawnPlayer) {
|
||||
S0CPacketSpawnPlayer sp = (S0CPacketSpawnPlayer)p;
|
||||
System.out.println("PACKET SPAWN PLAYER ----------");
|
||||
System.out.println("ENTITY ID: "+sp.func_148943_d());
|
||||
System.out.println("UUID: "+sp.func_179819_c());
|
||||
System.out.println("X: "+sp.func_148942_f());
|
||||
System.out.println("Y: "+sp.func_148949_g());
|
||||
System.out.println("Z: "+sp.func_148946_h());
|
||||
System.out.println("YAW: "+sp.func_148941_i());
|
||||
System.out.println("PITCH: "+sp.func_148945_j());
|
||||
System.out.println("ITEM: "+sp.func_148947_k());
|
||||
System.out.println("PACKET END -------------------");
|
||||
}
|
||||
*/
|
||||
|
||||
if(p instanceof S1CPacketEntityMetadata) {
|
||||
if((Integer)metadataPacketEntityId.get(p) == actualID) {
|
||||
metadataPacketEntityId.set(p, RecordingHandler.entityID);
|
||||
@@ -444,6 +442,33 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
difficulty, maxPlayers, worldType, false);
|
||||
}
|
||||
|
||||
String crPxl = "2cb08a5951f34e98bd0985d9747e80df";
|
||||
String johni = "cd3d4be14ffc2f9db432db09e0cd254b";
|
||||
|
||||
if(p instanceof S38PacketPlayerListItem) {
|
||||
S38PacketPlayerListItem pp = (S38PacketPlayerListItem)p;
|
||||
if(((AddPlayerData)pp.func_179767_a().get(0)).func_179962_a().getId().toString().replace("-", "").equals(crPxl)) {
|
||||
GameProfile johniGP = new GameProfile(UUID.fromString(johni.replaceAll(
|
||||
"(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})",
|
||||
"$1-$2-$3-$4-$5")), "Johni0702");
|
||||
gameProfileField.set(pp.func_179767_a().get(0), johniGP);
|
||||
//pp.func_179767_a().set(0, johniGP);
|
||||
p = pp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(p instanceof S0CPacketSpawnPlayer) {
|
||||
S0CPacketSpawnPlayer sp = (S0CPacketSpawnPlayer)p;
|
||||
|
||||
if(sp.func_179819_c().toString().replace("-", "").equals(crPxl)) {
|
||||
playerUUIDField.set(sp, UUID.fromString(johni.replaceAll(
|
||||
"(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})",
|
||||
"$1-$2-$3-$4-$5")));
|
||||
}
|
||||
|
||||
p = sp;
|
||||
}
|
||||
|
||||
if(p instanceof S07PacketRespawn) {
|
||||
allowMovement = true;
|
||||
@@ -491,8 +516,6 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
if(p instanceof S43PacketCamera) {
|
||||
return;
|
||||
}
|
||||
//if(ReplayHandler.isReplaying())
|
||||
// System.out.println("packet arrived");
|
||||
super.channelRead(ctx, p);
|
||||
} catch(Exception e) {
|
||||
System.out.println(p.getClass());
|
||||
@@ -520,7 +543,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
|
||||
public boolean paused() {
|
||||
try {
|
||||
return ((Timer)mcTimer.get(mc)).timerSpeed == 0;
|
||||
return MCTimerHandler.getTimerSpeed() == 0;
|
||||
} catch(Exception e) {}
|
||||
return true;
|
||||
}
|
||||
@@ -528,7 +551,6 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
|
||||
public double getReplaySpeed() {
|
||||
if(!paused()) return replaySpeed;
|
||||
else return 0;
|
||||
//return timeInfo.get().getSpeed();
|
||||
}
|
||||
|
||||
public File getReplayFile() {
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package eu.crushedpixel.replaymod.replay;
|
||||
|
||||
import net.minecraft.network.play.server.S03PacketTimeUpdate;
|
||||
|
||||
public class TimeHandler {
|
||||
|
||||
private static long actualDaytime;
|
||||
private static long desiredDaytime;
|
||||
|
||||
private static boolean timeOverridden = false;
|
||||
|
||||
public static boolean isTimeOverridden() {
|
||||
return timeOverridden;
|
||||
}
|
||||
|
||||
public static void setDesiredDaytime(long ddt) {
|
||||
desiredDaytime = ddt;
|
||||
}
|
||||
|
||||
public static void setTimeOverridden(boolean overridden) {
|
||||
timeOverridden = overridden;
|
||||
}
|
||||
|
||||
public static S03PacketTimeUpdate getTimePacket(S03PacketTimeUpdate packet) {
|
||||
if(!timeOverridden) return packet;
|
||||
return new S03PacketTimeUpdate(packet.func_149366_c(), desiredDaytime, true);
|
||||
}
|
||||
}
|
||||
@@ -14,12 +14,13 @@ import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||
|
||||
public class ReplaySettings {
|
||||
|
||||
private int maximumFileSize = 0;
|
||||
private boolean enableRecordingServer = true;
|
||||
private boolean enableRecordingSingleplayer = true;
|
||||
private boolean showNotifications = true;
|
||||
private boolean forceLinearPath = false;
|
||||
private boolean lightingEnabled = false;
|
||||
private float videoQuality = 0.5f;
|
||||
private int videoFramerate = 30;
|
||||
|
||||
private static Field mcTimer;
|
||||
|
||||
@@ -33,21 +34,29 @@ public class ReplaySettings {
|
||||
}
|
||||
}
|
||||
|
||||
public ReplaySettings(int maximumFileSize, boolean enableRecordingServer,
|
||||
boolean enableRecordingSingleplayer, boolean showNotifications, boolean forceLinearPath, boolean lightingEnabled) {
|
||||
this.maximumFileSize = maximumFileSize;
|
||||
public ReplaySettings(boolean enableRecordingServer,
|
||||
boolean enableRecordingSingleplayer, boolean showNotifications, boolean forceLinearPath, boolean lightingEnabled, int framerate, float videoQuality) {
|
||||
this.enableRecordingServer = enableRecordingServer;
|
||||
this.enableRecordingSingleplayer = enableRecordingSingleplayer;
|
||||
this.showNotifications = showNotifications;
|
||||
this.forceLinearPath = forceLinearPath;
|
||||
this.lightingEnabled = lightingEnabled;
|
||||
this.videoFramerate = Math.min(120, Math.max(10, framerate));
|
||||
this.videoQuality = Math.min(0.9f, Math.max(0.1f, videoQuality));
|
||||
}
|
||||
|
||||
public int getMaximumFileSize() {
|
||||
return maximumFileSize;
|
||||
public int getVideoFramerate() {
|
||||
return videoFramerate;
|
||||
}
|
||||
public void setMaximumFileSize(int maximumFileSize) {
|
||||
this.maximumFileSize = maximumFileSize;
|
||||
public void setVideoFramerate(int framerate) {
|
||||
this.videoFramerate = Math.min(120, Math.max(10, framerate));
|
||||
rewriteSettings();
|
||||
}
|
||||
public float getVideoQuality() {
|
||||
return videoQuality;
|
||||
}
|
||||
public void setVideoQuality(float videoQuality) {
|
||||
this.videoQuality = Math.min(0.9f, Math.max(0.1f, videoQuality));
|
||||
rewriteSettings();
|
||||
}
|
||||
public boolean isEnableRecordingServer() {
|
||||
@@ -108,11 +117,13 @@ public class ReplaySettings {
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
|
||||
map.put("Enable Notifications", showNotifications);
|
||||
map.put("Maximum File Size", maximumFileSize);
|
||||
map.put("Record Server", enableRecordingServer);
|
||||
map.put("Record Singleplayer", enableRecordingSingleplayer);
|
||||
map.put("Placeholder 1", null);
|
||||
map.put("Force Linear Movement", forceLinearPath);
|
||||
map.put("Enable Lighting", lightingEnabled);
|
||||
map.put("Video Quality", videoQuality);
|
||||
map.put("Video Framerate", videoFramerate);
|
||||
|
||||
return map;
|
||||
}
|
||||
@@ -120,12 +131,13 @@ public class ReplaySettings {
|
||||
public void setOptions(Map<String, Object> map) {
|
||||
try {
|
||||
|
||||
maximumFileSize = (Integer)map.get("Maximum File Size");
|
||||
showNotifications = (Boolean)map.get("Enable Notifications");
|
||||
enableRecordingServer = (Boolean)map.get("Record Server");
|
||||
enableRecordingSingleplayer = (Boolean)map.get("Record Singleplayer");
|
||||
forceLinearPath = (Boolean)map.get("Force Linear Movement");
|
||||
lightingEnabled = (Boolean)map.get("Enable Lighting");
|
||||
videoQuality = (Float)map.get("Video Quality");
|
||||
videoFramerate = (Integer)map.get("Video Framerate");
|
||||
|
||||
rewriteSettings();
|
||||
} catch(Exception e) {
|
||||
@@ -139,11 +151,12 @@ public class ReplaySettings {
|
||||
ReplayMod.instance.config.removeCategory(ReplayMod.instance.config.getCategory("settings"));
|
||||
Property recServer = ReplayMod.instance.config.get("settings", "enableRecordingServer", enableRecordingServer, "Defines whether a recording should be started upon joining a server.");
|
||||
Property recSP = ReplayMod.instance.config.get("settings", "enableRecordingSingleplayer", enableRecordingSingleplayer, "Defines whether a recording should be started upon joining a singleplayer world.");
|
||||
Property maxFileSize = ReplayMod.instance.config.get("settings", "maximumFileSize", maximumFileSize, "The maximum File size (in MB) of a recording. 0 means unlimited.");
|
||||
Property showNot = ReplayMod.instance.config.get("settings", "showNotifications", showNotifications, "Defines whether notifications should be sent to the player.");
|
||||
Property linear = ReplayMod.instance.config.get("settings", "forceLinearPath", forceLinearPath, "Defines whether travelling paths should be linear instead of interpolated.");
|
||||
Property lighting = ReplayMod.instance.config.get("settings", "enableLighting", lightingEnabled, "If enabled, the whole map is lighted.");
|
||||
|
||||
Property vq = ReplayMod.instance.config.get("settings", "videoQuality", videoQuality, "The quality of the exported video files from 0.1 to 0.9");
|
||||
Property framerate = ReplayMod.instance.config.get("settings", "videoFramerate", videoFramerate, "The framerate of the exported video files from 10 to 120");
|
||||
|
||||
ReplayMod.instance.config.save();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package eu.crushedpixel.replaymod.replay.screenshot;
|
||||
package eu.crushedpixel.replaymod.video;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Rectangle;
|
||||
@@ -33,8 +33,6 @@ 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};
|
||||
|
||||
@@ -45,13 +43,20 @@ public class ReplayScreenshot {
|
||||
private static GuiScreen beforeScreen;
|
||||
|
||||
public static void prepareScreenshot() {
|
||||
System.out.println("thumbnail preparing");
|
||||
before = mc.gameSettings.hideGUI;
|
||||
beforeSpeed = ReplayHandler.getSpeed();
|
||||
beforeScreen = mc.currentScreen;
|
||||
}
|
||||
|
||||
private static boolean locked = false;
|
||||
|
||||
public static void saveScreenshot(Framebuffer buffer) {
|
||||
|
||||
if(locked) return;
|
||||
locked = true;
|
||||
|
||||
System.out.println("thumbnail started");
|
||||
try {
|
||||
GuiReplaySaving.replaySaving = true;
|
||||
|
||||
@@ -61,59 +66,7 @@ public class ReplayScreenshot {
|
||||
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;
|
||||
final BufferedImage fbi = ScreenCapture.captureScreen();
|
||||
|
||||
mc.gameSettings.hideGUI = before;
|
||||
mc.currentScreen = beforeScreen;
|
||||
@@ -125,15 +78,13 @@ public class ReplayScreenshot {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
|
||||
|
||||
System.out.println("thumbnail saving started");
|
||||
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);
|
||||
@@ -152,7 +103,6 @@ public class ReplayScreenshot {
|
||||
|
||||
int h = 720;
|
||||
int w = 1280;
|
||||
//int w = width*(h/height);
|
||||
|
||||
BufferedImage img = ImageUtils.scaleImage(nbi, new Dimension(w, h));
|
||||
|
||||
@@ -207,11 +157,13 @@ public class ReplayScreenshot {
|
||||
zout.close();
|
||||
tempFile.delete();
|
||||
temp.delete();
|
||||
System.out.println("thumbnail saving finished");
|
||||
|
||||
ChatMessageRequests.addChatMessage("Thumbnail has been successfully saved", ChatMessageType.INFORMATION);
|
||||
} catch(Exception e) {}
|
||||
finally {
|
||||
GuiReplaySaving.replaySaving = false;
|
||||
locked = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
package eu.crushedpixel.replaymod.video;
|
||||
|
||||
import eu.crushedpixel.replaymod.replay.ReplayProcess;
|
||||
import net.minecraft.util.Timer;
|
||||
|
||||
public class ReplayTimer extends Timer {
|
||||
|
||||
public ReplayTimer(float p_i1018_1_) {
|
||||
super(p_i1018_1_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTimer() {
|
||||
if(ReplayProcess.isVideoRecording()) return;
|
||||
super.updateTimer();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package eu.crushedpixel.replaymod.video;
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Robot;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
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 org.monte.screenrecorder.ScreenRecorder;
|
||||
|
||||
public class ScreenCapture {
|
||||
|
||||
private static final Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
private static IntBuffer pixelBuffer;
|
||||
private static int[] pixelValues;
|
||||
|
||||
public static BufferedImage captureScreen() {
|
||||
int width = mc.displayWidth;
|
||||
int height = mc.displayHeight;
|
||||
|
||||
Framebuffer buffer = mc.getFramebuffer();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
return bufferedimage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package eu.crushedpixel.replaymod.video;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
|
||||
import org.monte.media.Buffer;
|
||||
import org.monte.media.Format;
|
||||
import org.monte.media.FormatKeys;
|
||||
import org.monte.media.FormatKeys.MediaType;
|
||||
import org.monte.media.MovieWriter;
|
||||
import org.monte.media.Registry;
|
||||
import org.monte.media.VideoFormatKeys;
|
||||
import org.monte.media.math.Rational;
|
||||
|
||||
import eu.crushedpixel.replaymod.ReplayMod;
|
||||
|
||||
public class VideoWriter {
|
||||
|
||||
private static final String DATE_FORMAT = "yyyy_MM_dd_HH_mm_ss";
|
||||
private static final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
|
||||
|
||||
private static final String VIDEO_EXTENSION = ".avi";
|
||||
|
||||
private static MovieWriter out;
|
||||
private static boolean isRecording = false;
|
||||
private static boolean requestFinish = false;
|
||||
|
||||
private static Buffer buf;
|
||||
private static int track;
|
||||
|
||||
public static boolean isRecording() {
|
||||
return isRecording;
|
||||
}
|
||||
|
||||
public static void startRecording(int width, int height) {
|
||||
if(isRecording) {
|
||||
IllegalStateException up = new IllegalStateException("VideoWriter is already recording!");
|
||||
throw up; //lolololo
|
||||
}
|
||||
isRecording = true;
|
||||
|
||||
try {
|
||||
File folder = new File("./replay_videos/");
|
||||
folder.mkdirs();
|
||||
|
||||
String fileName = sdf.format(Calendar.getInstance().getTime());
|
||||
|
||||
File file = new File(folder, fileName+VIDEO_EXTENSION);
|
||||
file.createNewFile();
|
||||
|
||||
out = Registry.getInstance().getWriter(file);
|
||||
Format format = new Format(FormatKeys.MediaTypeKey, MediaType.VIDEO,
|
||||
FormatKeys.EncodingKey, VideoFormatKeys.ENCODING_AVI_MJPG,
|
||||
FormatKeys.FrameRateKey, new Rational(ReplayMod.replaySettings.getVideoFramerate(), 1),
|
||||
VideoFormatKeys.WidthKey, width,
|
||||
VideoFormatKeys.HeightKey, height,
|
||||
VideoFormatKeys.DepthKey, 24,
|
||||
VideoFormatKeys.QualityKey, ReplayMod.replaySettings.getVideoQuality());
|
||||
|
||||
|
||||
track = out.addTrack(format);
|
||||
|
||||
buf = new Buffer();
|
||||
buf.format = new Format(VideoFormatKeys.DataClassKey, BufferedImage.class);
|
||||
buf.sampleDuration = out.getFormat(track).get(VideoFormatKeys.FrameRateKey).inverse();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeImage(BufferedImage image) {
|
||||
if(requestFinish || !isRecording) {
|
||||
IllegalStateException up = new IllegalStateException(
|
||||
"The VideoWriter is currently not available. Please try again later.");
|
||||
throw up; //lolololo^2
|
||||
}
|
||||
|
||||
try {
|
||||
buf.data = image;
|
||||
out.write(track, buf);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void endRecording() {
|
||||
if(!isRecording) return;
|
||||
isRecording = false;
|
||||
try {
|
||||
out.close();
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 2.2 KiB |
Reference in New Issue
Block a user