Split mod into core, recording, replay, render[todo], paths[todo] and extras[wip] modules
Move everything to com.replaymod package Add KeyBindingRegistry and SettingsRegistry Recreate settings GUI with new GUI API and dynamically from SettingsRegistry Use ReplayFile from ReplayStudio ReplayHandler is now object oriented Add GuiOverlay, GuiSlider and GuiTexturedButton to GUI API Rewrite both overlays to use new GUI API Fix size capping in vertical and horizontal layout Allow CustomLayouts to have parents Fix tooltip rendering when close to screen border Allow changing of columns in GridLayout
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
package com.replaymod.replay.gui.overlay;
|
||||
|
||||
import de.johni0702.replaystudio.data.Marker;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import eu.crushedpixel.replaymod.gui.elements.timelines.GuiTimeline;
|
||||
import eu.crushedpixel.replaymod.holders.AdvancedPosition;
|
||||
import com.replaymod.replay.ReplayHandler;
|
||||
import eu.crushedpixel.replaymod.utils.MouseUtils;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import org.lwjgl.util.Point;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class GuiMarkerTimeline extends GuiTimeline {
|
||||
private static final int KEYFRAME_MARKER_X = 109;
|
||||
private static final int KEYFRAME_MARKER_Y = 20;
|
||||
|
||||
private final ReplayHandler replayHandler;
|
||||
private Marker selectedMarker;
|
||||
private Marker clickedMarker;
|
||||
private long clickTime;
|
||||
private boolean dragging;
|
||||
|
||||
public GuiMarkerTimeline(ReplayHandler replayHandler, int positionX, int positionY, int width, int height) {
|
||||
super(positionX, positionY, width, height);
|
||||
this.replayHandler = replayHandler;
|
||||
this.showMarkers = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClick(Minecraft mc, int mouseX, int mouseY, int button) {
|
||||
if(!enabled) return false;
|
||||
|
||||
long time = getTimeAt(mouseX, mouseY);
|
||||
if(time == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int tolerance = (int) (2 * Math.round(zoom * timelineLength / width));
|
||||
|
||||
Marker closest = null;
|
||||
if(mouseY >= positionY + BORDER_TOP + 10) {
|
||||
long distance = tolerance;
|
||||
for (Marker m : replayHandler.getMarkers()) {
|
||||
long d = Math.abs(m.getTime() - time);
|
||||
if (d <= distance) {
|
||||
closest = m;
|
||||
distance = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//left mouse button
|
||||
if(button == 0) {
|
||||
if(closest == null) { //if no keyframe clicked, jump in time
|
||||
replayHandler.doJump((int) getTimeAt(mouseX, mouseY), true);
|
||||
} else {
|
||||
selectedMarker = closest;
|
||||
// If we clicked on a key frame, then continue monitoring the mouse for movements
|
||||
long currentTime = System.currentTimeMillis();
|
||||
if(currentTime - clickTime < 500) { // if double clicked then open GUI instead
|
||||
// mc.displayGuiScreen(GuiEditKeyframe.create(closest));
|
||||
// TODO Edit Gui
|
||||
this.clickedMarker = null;
|
||||
} else {
|
||||
this.clickedMarker = closest;
|
||||
this.dragging = false;
|
||||
}
|
||||
this.clickTime = currentTime;
|
||||
}
|
||||
|
||||
} else if(button == 1) {
|
||||
if(closest != null) {
|
||||
//Jump to clicked Marker Keyframe (explicitly force to jump to this position)
|
||||
replayHandler.setTargetPosition(new AdvancedPosition(
|
||||
closest.getX(), closest.getY(), closest.getZ(),
|
||||
closest.getPitch(), closest.getYaw(), closest.getRoll()
|
||||
));
|
||||
|
||||
//perform the jump, telling the Overlay not to override the last position value
|
||||
replayHandler.doJump(closest.getTime(), false);
|
||||
}
|
||||
}
|
||||
|
||||
return isHovering(mouseX, mouseY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDrag(Minecraft mc, int mouseX, int mouseY, int button) {
|
||||
if(!enabled) return;
|
||||
long time = getTimeAt(mouseX, mouseY);
|
||||
if (time != -1) {
|
||||
if (clickedMarker != null) {
|
||||
int tolerance = (int) (2 * Math.round(zoom * timelineLength / width));
|
||||
|
||||
if (dragging || Math.abs(clickedMarker.getTime() - time) > tolerance) {
|
||||
clickedMarker.setTime((int) time);
|
||||
dragging = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseRelease(Minecraft mc, int mouseX, int mouseY, int button) {
|
||||
mouseDrag(mc, mouseX, mouseY, button);
|
||||
clickedMarker = null;
|
||||
if (dragging) {
|
||||
replayHandler.saveMarkers();
|
||||
dragging = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Minecraft mc, int mouseX, int mouseY) {
|
||||
super.draw(mc, mouseX, mouseY);
|
||||
|
||||
int bodyWidth = width - BORDER_LEFT - BORDER_RIGHT;
|
||||
|
||||
long leftTime = Math.round(timeStart * timelineLength);
|
||||
long rightTime = Math.round((timeStart + zoom) * timelineLength);
|
||||
|
||||
double segmentLength = timelineLength * zoom;
|
||||
|
||||
drawTimelineCursor(leftTime, rightTime, bodyWidth);
|
||||
|
||||
//Draw Keyframe logos
|
||||
for (Marker marker : replayHandler.getMarkers()) {
|
||||
drawMarker(marker, bodyWidth, leftTime, rightTime, segmentLength);
|
||||
}
|
||||
}
|
||||
|
||||
private int getMarkerX(int timestamp, long leftTime, int bodyWidth, double segmentLength) {
|
||||
long positionInSegment = timestamp - leftTime;
|
||||
double fractionOfSegment = positionInSegment / segmentLength;
|
||||
return (int) (positionX + BORDER_LEFT + fractionOfSegment * bodyWidth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawOverlay(Minecraft mc, int mouseX, int mouseY) {
|
||||
boolean drawn = false;
|
||||
|
||||
int bodyWidth = width - BORDER_LEFT - BORDER_RIGHT;
|
||||
|
||||
long leftTime = Math.round(timeStart * timelineLength);
|
||||
double segmentLength = timelineLength * zoom;
|
||||
|
||||
for (Marker marker : replayHandler.getMarkers()) {
|
||||
int markerX = getMarkerX(marker.getTime(), leftTime, bodyWidth, segmentLength);
|
||||
|
||||
if(MouseUtils.isMouseWithinBounds(markerX - 2, this.positionY + BORDER_TOP + 10 + 1, 5, 5)) {
|
||||
Point mouse = MouseUtils.getMousePos();
|
||||
String markerName = marker.getName();
|
||||
if(markerName == null || markerName.isEmpty()) markerName = I18n.format("replaymod.gui.ingame.unnamedmarker");
|
||||
ReplayMod.tooltipRenderer.drawTooltip(mouse.getX(), mouse.getY(), markerName, null, Color.WHITE);
|
||||
|
||||
drawn = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!drawn) {
|
||||
super.drawOverlay(mc, mouseX, mouseY);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawMarker(Marker marker, int bodyWidth, long leftTime, long rightTime, double segmentLength) {
|
||||
if (marker.getTime() <= rightTime && marker.getTime() >= leftTime) {
|
||||
int textureX = KEYFRAME_MARKER_X;
|
||||
int textureY = KEYFRAME_MARKER_Y;
|
||||
int y = positionY+10;
|
||||
|
||||
int keyframeX = getMarkerX(marker.getTime(), leftTime, bodyWidth, segmentLength);
|
||||
|
||||
if (selectedMarker == marker) {
|
||||
textureX += 5;
|
||||
}
|
||||
|
||||
rect(keyframeX - 2, y + BORDER_TOP, textureX, textureY, 5, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package com.replaymod.replay.gui.overlay;
|
||||
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import com.replaymod.replay.ReplayHandler;
|
||||
import com.replaymod.replay.ReplaySender;
|
||||
import de.johni0702.minecraft.gui.GuiRenderer;
|
||||
import de.johni0702.minecraft.gui.RenderInfo;
|
||||
import de.johni0702.minecraft.gui.container.AbstractGuiOverlay;
|
||||
import de.johni0702.minecraft.gui.container.GuiPanel;
|
||||
import de.johni0702.minecraft.gui.element.GuiSlider;
|
||||
import de.johni0702.minecraft.gui.element.GuiTexturedButton;
|
||||
import de.johni0702.minecraft.gui.element.advanced.GuiTimeline;
|
||||
import de.johni0702.minecraft.gui.element.advanced.IGuiTimeline;
|
||||
import de.johni0702.minecraft.gui.layout.CustomLayout;
|
||||
import de.johni0702.minecraft.gui.layout.HorizontalLayout;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.InputEvent;
|
||||
import org.lwjgl.util.ReadableDimension;
|
||||
import org.lwjgl.util.ReadablePoint;
|
||||
import org.lwjgl.util.WritablePoint;
|
||||
|
||||
import static com.replaymod.core.ReplayMod.TEXTURE_SIZE;
|
||||
|
||||
public class GuiReplayOverlay extends AbstractGuiOverlay<GuiReplayOverlay> {
|
||||
|
||||
private final ReplayHandler replayHandler;
|
||||
public final GuiPanel topPanel = new GuiPanel(this)
|
||||
.setLayout(new HorizontalLayout(HorizontalLayout.Alignment.LEFT).setSpacing(5));
|
||||
public final GuiTexturedButton playPauseButton = new GuiTexturedButton().setSize(20, 20)
|
||||
.setTexture(ReplayMod.TEXTURE, TEXTURE_SIZE);
|
||||
public final GuiSlider speedSlider = new GuiSlider().setSize(100, 20).setSteps(37); // 0.0 is not included
|
||||
public final GuiTimeline timeline = new GuiTimeline(){
|
||||
@Override
|
||||
public void draw(GuiRenderer renderer, ReadableDimension size, RenderInfo renderInfo) {
|
||||
setCursorPosition(replayHandler.getReplaySender().currentTimeStamp());
|
||||
super.draw(renderer, size, renderInfo);
|
||||
}
|
||||
}.setSize(Integer.MAX_VALUE, 20);
|
||||
|
||||
public GuiReplayOverlay(final ReplayHandler replayHandler) {
|
||||
this.replayHandler = replayHandler;
|
||||
|
||||
topPanel.addElements(null, playPauseButton, speedSlider, timeline);
|
||||
setLayout(new CustomLayout<GuiReplayOverlay>() {
|
||||
@Override
|
||||
protected void layout(GuiReplayOverlay container, int width, int height) {
|
||||
pos(topPanel, 10, 10);
|
||||
size(topPanel, width - 20, 20);
|
||||
}
|
||||
});
|
||||
|
||||
playPauseButton.setTexturePosH(new ReadablePoint() {
|
||||
@Override
|
||||
public int getX() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getY() {
|
||||
return replayHandler.getReplaySender().paused() ? 0 : 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getLocation(WritablePoint dest) {
|
||||
dest.setLocation(getX(), getY());
|
||||
}
|
||||
}).onClick(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ReplaySender replaySender = replayHandler.getReplaySender();
|
||||
// If currently paused
|
||||
if (replaySender.paused()) {
|
||||
// then play
|
||||
replaySender.setReplaySpeed(getSpeed());
|
||||
} else {
|
||||
// else pause
|
||||
replaySender.setReplaySpeed(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
speedSlider.onValueChanged(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
double speed = getSpeed();
|
||||
speedSlider.setText(I18n.format("replaymod.gui.speed") + ": " + speed + "x");
|
||||
ReplaySender replaySender = replayHandler.getReplaySender();
|
||||
if (!replaySender.paused()) {
|
||||
replaySender.setReplaySpeed(speed);
|
||||
}
|
||||
}
|
||||
}).setValue(9);
|
||||
|
||||
timeline.onClick(new IGuiTimeline.OnClick() {
|
||||
@Override
|
||||
public void run(int time) {
|
||||
replayHandler.doJump(time, true);
|
||||
}
|
||||
}).setLength(replayHandler.getReplaySender().replayLength());
|
||||
}
|
||||
|
||||
private double getSpeed() {
|
||||
int value = speedSlider.getValue() + 1;
|
||||
if (value <= 9) {
|
||||
return value / 10d;
|
||||
} else {
|
||||
return 1 + (0.25d * (value - 10));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean visible) {
|
||||
if (isVisible() != visible) {
|
||||
if (visible) {
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
} else {
|
||||
FMLCommonHandler.instance().bus().unregister(this);
|
||||
}
|
||||
}
|
||||
super.setVisible(visible);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onKeyInput(InputEvent.KeyInputEvent event) {
|
||||
GameSettings gameSettings = getMinecraft().gameSettings;
|
||||
while (gameSettings.keyBindChat.isPressed() || gameSettings.keyBindCommand.isPressed()) {
|
||||
if (!isMouseVisible()) {
|
||||
setMouseVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GuiReplayOverlay getThis() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
100
src/main/java/com/replaymod/replay/gui/screen/GuiRenameReplay.java
Executable file
100
src/main/java/com/replaymod/replay/gui/screen/GuiRenameReplay.java
Executable file
@@ -0,0 +1,100 @@
|
||||
package com.replaymod.replay.gui.screen;
|
||||
|
||||
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiErrorScreen;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiTextField;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public class GuiRenameReplay extends GuiScreen {
|
||||
private GuiScreen parent;
|
||||
private GuiTextField replayNameInput;
|
||||
private File file;
|
||||
|
||||
public GuiRenameReplay(GuiScreen parent, File file) {
|
||||
this.parent = parent;
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateScreen() {
|
||||
this.replayNameInput.updateCursorCounter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui() {
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<GuiButton> buttonList = this.buttonList;
|
||||
buttonList.clear();
|
||||
buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 4 + 96 + 12, I18n.format("replaymod.gui.rename")));
|
||||
buttonList.add(new GuiButton(1, this.width / 2 - 100, this.height / 4 + 120 + 12, I18n.format("replaymod.gui.cancel")));
|
||||
String s = FilenameUtils.getBaseName(file.getAbsolutePath());
|
||||
this.replayNameInput = new GuiTextField(2, this.fontRendererObj, this.width / 2 - 100, 60, 200, 20);
|
||||
this.replayNameInput.setFocused(true);
|
||||
this.replayNameInput.setText(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGuiClosed() {
|
||||
Keyboard.enableRepeatEvents(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void actionPerformed(GuiButton button) throws IOException {
|
||||
if(button.enabled) {
|
||||
if(button.id == 1) {
|
||||
this.mc.displayGuiScreen(this.parent);
|
||||
} else if(button.id == 0) {
|
||||
File folder = ReplayFileIO.getReplayFolder();
|
||||
|
||||
File initRenamed = new File(folder, (this.replayNameInput.getText().trim() + ".zip").replaceAll("[^a-zA-Z0-9\\.\\- ]", "_"));
|
||||
File renamed = ReplayFileIO.getNextFreeFile(initRenamed);
|
||||
try {
|
||||
FileUtils.moveFile(file, renamed);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
mc.displayGuiScreen(new GuiErrorScreen(
|
||||
I18n.format("replaymod.gui.viewer.delete.failed1"),
|
||||
I18n.format("replaymod.gui.viewer.delete.failed2")
|
||||
));
|
||||
return;
|
||||
}
|
||||
this.mc.displayGuiScreen(this.parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void keyTyped(char typedChar, int keyCode) throws IOException {
|
||||
this.replayNameInput.textboxKeyTyped(typedChar, keyCode);
|
||||
((GuiButton) this.buttonList.get(0)).enabled = this.replayNameInput.getText().trim().length() > 0;
|
||||
|
||||
if(keyCode == 28 || keyCode == 156) {
|
||||
this.actionPerformed((GuiButton) this.buttonList.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
|
||||
super.mouseClicked(mouseX, mouseY, mouseButton);
|
||||
this.replayNameInput.mouseClicked(mouseX, mouseY, mouseButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
|
||||
this.drawDefaultBackground();
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("replaymod.gui.viewer.rename.title"), this.width / 2, 20, 16777215);
|
||||
this.drawString(this.fontRendererObj, I18n.format("replaymod.gui.viewer.rename.name"), this.width / 2 - 100, 47, 10526880);
|
||||
this.replayNameInput.drawTextBox();
|
||||
super.drawScreen(mouseX, mouseY, partialTicks);
|
||||
}
|
||||
}
|
||||
360
src/main/java/com/replaymod/replay/gui/screen/GuiReplayViewer.java
Executable file
360
src/main/java/com/replaymod/replay/gui/screen/GuiReplayViewer.java
Executable file
@@ -0,0 +1,360 @@
|
||||
package com.replaymod.replay.gui.screen;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.mojang.realmsclient.util.Pair;
|
||||
import com.replaymod.core.ReplayMod;
|
||||
import com.replaymod.core.gui.GuiReplaySettings;
|
||||
import com.replaymod.replay.ReplayModReplay;
|
||||
import de.johni0702.replaystudio.replay.ReplayFile;
|
||||
import de.johni0702.replaystudio.replay.ReplayMetaData;
|
||||
import de.johni0702.replaystudio.replay.ZipReplayFile;
|
||||
import de.johni0702.replaystudio.studio.ReplayStudio;
|
||||
import eu.crushedpixel.replaymod.api.replay.holders.FileInfo;
|
||||
import eu.crushedpixel.replaymod.gui.elements.GuiLoadingListEntry;
|
||||
import eu.crushedpixel.replaymod.gui.elements.GuiReplayListEntry;
|
||||
import eu.crushedpixel.replaymod.gui.elements.GuiReplayListExtended;
|
||||
import eu.crushedpixel.replaymod.gui.online.GuiUploadFile;
|
||||
import eu.crushedpixel.replaymod.registry.ResourceHelper;
|
||||
import eu.crushedpixel.replaymod.utils.ImageUtils;
|
||||
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiYesNo;
|
||||
import net.minecraft.client.gui.GuiYesNoCallback;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.util.Util;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.lwjgl.Sys;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
public class GuiReplayViewer extends GuiScreen implements GuiYesNoCallback {
|
||||
|
||||
private static final int LOAD_BUTTON_ID = 9001;
|
||||
private static final int UPLOAD_BUTTON_ID = 9002;
|
||||
private static final int FOLDER_BUTTON_ID = 9003;
|
||||
private static final int RENAME_BUTTON_ID = 9004;
|
||||
private static final int DELETE_BUTTON_ID = 9005;
|
||||
private static final int SETTINGS_BUTTON_ID = 9006;
|
||||
private static final int CANCEL_BUTTON_ID = 9007;
|
||||
private final ReplayModReplay mod;
|
||||
private boolean initialized;
|
||||
private GuiReplayListExtended replayGuiList;
|
||||
private List<Pair<Pair<File, ReplayMetaData>, File>> replayFileList = new ArrayList<Pair<Pair<File, ReplayMetaData>, File>>();
|
||||
private GuiButton loadButton;
|
||||
private GuiButton uploadButton;
|
||||
private GuiButton renameButton;
|
||||
private GuiButton deleteButton;
|
||||
private boolean delete_file = false;
|
||||
|
||||
private Queue<Runnable> loadedReplaysQueue = new ConcurrentLinkedQueue<Runnable>();
|
||||
|
||||
private Thread fileReloader;
|
||||
|
||||
public GuiReplayViewer(ReplayModReplay mod) {
|
||||
this.mod = mod;
|
||||
}
|
||||
|
||||
private class FileReloaderThread extends Thread {
|
||||
private final GuiLoadingListEntry loadingListEntry = new GuiLoadingListEntry();
|
||||
|
||||
@Override
|
||||
public synchronized void start() {
|
||||
replayFileList = new ArrayList<Pair<Pair<File, ReplayMetaData>, File>>();
|
||||
replayGuiList.clearEntries();
|
||||
replayGuiList.addEntry(loadingListEntry);
|
||||
super.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for(final File file : ReplayFileIO.getAllReplayFiles()) {
|
||||
if(interrupted()) break;
|
||||
try {
|
||||
ReplayFile replayFile = new ZipReplayFile(new ReplayStudio(), file);
|
||||
final ReplayMetaData metaData = replayFile.getMetaData();
|
||||
Optional<BufferedImage> thumb = replayFile.getThumb();
|
||||
|
||||
replayFile.close();
|
||||
|
||||
File tmp = null;
|
||||
if(thumb.isPresent()) {
|
||||
BufferedImage img = ImageUtils.scaleImage(thumb.get(), new Dimension(1280, 720));
|
||||
tmp = File.createTempFile(FilenameUtils.getBaseName(file.getAbsolutePath())+"_THUMBNAIL", "jpg");
|
||||
tmp.deleteOnExit();
|
||||
|
||||
ImageIO.write(img, "jpg", tmp);
|
||||
}
|
||||
|
||||
final File thumbFile = tmp;
|
||||
loadedReplaysQueue.offer(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
addEntry(file, metaData, thumbFile);
|
||||
}
|
||||
});
|
||||
} catch(Exception e) {
|
||||
FMLLog.getLogger().error("Could not load Replay File "+file.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
loadedReplaysQueue.offer(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
replayGuiList.removeEntry(loadingListEntry);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static GuiYesNo getYesNoGui(GuiYesNoCallback p_152129_0_, String file, int p_152129_2_) {
|
||||
String s1 = I18n.format("replaymod.gui.viewer.delete.linea");
|
||||
String s2 = "\'" + file + "\' " + I18n.format("replaymod.gui.viewer.delete.lineb");
|
||||
String s3 = I18n.format("replaymod.gui.delete");
|
||||
String s4 = I18n.format("replaymod.gui.cancel");
|
||||
return new GuiYesNo(p_152129_0_, s1, s2, s3, s4, p_152129_2_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGuiClosed() {
|
||||
ResourceHelper.freeAllResources();
|
||||
super.onGuiClosed();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public void initGui() {
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
|
||||
if(!this.initialized) {
|
||||
replayGuiList = new ReplayList(this, this.mc, this.width, this.height, 32, this.height - 64, 36);
|
||||
this.initialized = true;
|
||||
} else {
|
||||
this.replayGuiList.setDimensions(this.width, this.height, 32, this.height - 64);
|
||||
}
|
||||
|
||||
try {
|
||||
if(fileReloader != null) {
|
||||
fileReloader.interrupt();
|
||||
fileReloader.join();
|
||||
}
|
||||
|
||||
fileReloader = new FileReloaderThread();
|
||||
fileReloader.start();
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
this.createButtons();
|
||||
}
|
||||
|
||||
private void createButtons() {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<GuiButton> buttonList = this.buttonList;
|
||||
buttonList.add(loadButton = new GuiButton(LOAD_BUTTON_ID, this.width / 2 - 154, this.height - 52, 73, 20, I18n.format("replaymod.gui.load")));
|
||||
buttonList.add(uploadButton = new GuiButton(UPLOAD_BUTTON_ID, this.width / 2 - 154 + 78, this.height - 52, 73, 20, I18n.format("replaymod.gui.upload")));
|
||||
buttonList.add(new GuiButton(FOLDER_BUTTON_ID, this.width / 2 + 4, this.height - 52, 150, 20, I18n.format("replaymod.gui.viewer.replayfolder")));
|
||||
buttonList.add(renameButton = new GuiButton(RENAME_BUTTON_ID, this.width / 2 - 154, this.height - 28, 72, 20, I18n.format("replaymod.gui.rename")));
|
||||
buttonList.add(deleteButton = new GuiButton(DELETE_BUTTON_ID, this.width / 2 - 76, this.height - 28, 72, 20, I18n.format("replaymod.gui.delete")));
|
||||
buttonList.add(new GuiButton(SETTINGS_BUTTON_ID, this.width / 2 + 4, this.height - 28, 72, 20, I18n.format("replaymod.gui.settings")));
|
||||
buttonList.add(new GuiButton(CANCEL_BUTTON_ID, this.width / 2 + 4 + 78, this.height - 28, 72, 20, I18n.format("replaymod.gui.cancel")));
|
||||
setButtonsEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMouseInput() throws IOException {
|
||||
super.handleMouseInput();
|
||||
this.replayGuiList.handleMouseInput();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
|
||||
super.mouseClicked(mouseX, mouseY, mouseButton);
|
||||
this.replayGuiList.mouseClicked(mouseX, mouseY, mouseButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseReleased(int mouseX, int mouseY, int state) {
|
||||
super.mouseReleased(mouseX, mouseY, state);
|
||||
this.replayGuiList.mouseReleased(mouseX, mouseY, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
|
||||
this.drawDefaultBackground();
|
||||
this.replayGuiList.drawScreen(mouseX, mouseY, partialTicks);
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("replaymod.gui.replayviewer"), this.width / 2, 20, 16777215);
|
||||
|
||||
super.drawScreen(mouseX, mouseY, partialTicks);
|
||||
|
||||
if(uploadButton.isMouseOver() && !uploadButton.enabled && loadButton.enabled) {
|
||||
if(currentFileUploaded) {
|
||||
ReplayMod.tooltipRenderer.drawTooltip(mouseX, mouseY, I18n.format("replaymod.gui.viewer.alreadyuploaded"), this, Color.RED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void actionPerformed(GuiButton button) throws IOException {
|
||||
if(button.enabled) {
|
||||
if(button.id == LOAD_BUTTON_ID) {
|
||||
loadReplay(replayGuiList.selected);
|
||||
} else if(button.id == CANCEL_BUTTON_ID) {
|
||||
mc.displayGuiScreen(null);
|
||||
} else if(button.id == DELETE_BUTTON_ID) {
|
||||
String s = ((GuiReplayListEntry)replayGuiList.getListEntry(replayGuiList.selected)).getFileInfo().getName();
|
||||
|
||||
if(s != null) {
|
||||
delete_file = true;
|
||||
GuiYesNo guiyesno = getYesNoGui(this, s, 1);
|
||||
this.mc.displayGuiScreen(guiyesno);
|
||||
}
|
||||
} else if(button.id == SETTINGS_BUTTON_ID) {
|
||||
new GuiReplaySettings(this, ReplayMod.instance.getSettingsRegistry()).display();
|
||||
} else if(button.id == RENAME_BUTTON_ID) {
|
||||
File file = replayFileList.get(replayGuiList.selected).first().first();
|
||||
this.mc.displayGuiScreen(new GuiRenameReplay(this, file));
|
||||
} else if(button.id == UPLOAD_BUTTON_ID) {
|
||||
File file = replayFileList.get(replayGuiList.selected).first().first();
|
||||
this.mc.displayGuiScreen(new GuiUploadFile(file, this));
|
||||
} else if(button.id == FOLDER_BUTTON_ID) {
|
||||
File file1 = ReplayFileIO.getReplayFolder();
|
||||
|
||||
String s = file1.getAbsolutePath();
|
||||
|
||||
if(Util.getOSType() == Util.EnumOS.OSX) {
|
||||
try {
|
||||
Runtime.getRuntime().exec(new String[]{"/usr/bin/open", s});
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
LogManager.getLogger().error("Cannot open file", e);
|
||||
}
|
||||
} else if(Util.getOSType() == Util.EnumOS.WINDOWS) {
|
||||
String s1 = String.format("cmd.exe /C start \"Open file\" \"%s\"", s);
|
||||
|
||||
try {
|
||||
Runtime.getRuntime().exec(s1);
|
||||
return;
|
||||
} catch(IOException e) {
|
||||
LogManager.getLogger().error("Cannot open file", e);
|
||||
}
|
||||
}
|
||||
|
||||
boolean flag = false;
|
||||
|
||||
try {
|
||||
Desktop.getDesktop().browse(file1.toURI());
|
||||
} catch(Throwable throwable) {
|
||||
flag = true;
|
||||
}
|
||||
|
||||
if(flag) {
|
||||
Sys.openURL("file://" + s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void confirmClicked(boolean result, int id) {
|
||||
if(this.delete_file) {
|
||||
this.delete_file = false;
|
||||
|
||||
if(result) {
|
||||
try {
|
||||
FileUtils.forceDelete(replayFileList.get(replayGuiList.selected).first().first());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
replayFileList.remove(replayGuiList.selected);
|
||||
replayGuiList.selected = -1;
|
||||
}
|
||||
|
||||
this.mc.displayGuiScreen(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateScreen() {
|
||||
super.updateScreen();
|
||||
while (!loadedReplaysQueue.isEmpty()) {
|
||||
loadedReplaysQueue.poll().run();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean currentFileUploaded = false;
|
||||
|
||||
public void setButtonsEnabled(boolean b) {
|
||||
loadButton.enabled = b;
|
||||
|
||||
if(b) {
|
||||
currentFileUploaded = ReplayMod.uploadedFileHandler.isUploaded(replayFileList.get(replayGuiList.selected).first().first());
|
||||
uploadButton.enabled = !currentFileUploaded;
|
||||
} else {
|
||||
uploadButton.enabled = false;
|
||||
}
|
||||
|
||||
|
||||
renameButton.enabled = b;
|
||||
deleteButton.enabled = b;
|
||||
}
|
||||
|
||||
public void loadReplay(int id) {
|
||||
mc.displayGuiScreen(null);
|
||||
|
||||
try {
|
||||
mod.startReplay(replayFileList.get(id).first().first());
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void addEntry(File file, ReplayMetaData metaData, File thumb) {
|
||||
final Pair<Pair<File, ReplayMetaData>, File> p = Pair.of(Pair.of(file, metaData), thumb);
|
||||
final int index = getInsertionIndex(p, replayFileList);
|
||||
|
||||
replayFileList.add(index, p);
|
||||
|
||||
final FileInfo fileInfo = new FileInfo(-1, p.first().second(), null, null,
|
||||
-1, -1, -1, FilenameUtils.getBaseName(p.first().first().getName()), true, -1);
|
||||
|
||||
replayGuiList.addEntry(index, new GuiReplayListEntry(replayGuiList, fileInfo, p.second()));
|
||||
}
|
||||
|
||||
private static FileAgeComparator fileAgeComparator = new FileAgeComparator();
|
||||
|
||||
public static class FileAgeComparator implements Comparator<Pair<Pair<File, ReplayMetaData>, File>> {
|
||||
|
||||
@Override
|
||||
public int compare(Pair<Pair<File, ReplayMetaData>, File> o1, Pair<Pair<File, ReplayMetaData>, File> o2) {
|
||||
try {
|
||||
return new Date(o2.first().second().getDate()).compareTo(new Date(o1.first().second().getDate()));
|
||||
} catch(Exception e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getInsertionIndex(Pair<Pair<File, ReplayMetaData>, File> p, List<Pair<Pair<File, ReplayMetaData>, File>> list) {
|
||||
List<Pair<Pair<File, ReplayMetaData>, File>> nl = new ArrayList<Pair<Pair<File, ReplayMetaData>, File>>(list);
|
||||
|
||||
nl.add(p);
|
||||
Collections.sort(nl, fileAgeComparator);
|
||||
|
||||
return nl.indexOf(p);
|
||||
}
|
||||
|
||||
}
|
||||
29
src/main/java/com/replaymod/replay/gui/screen/ReplayList.java
Executable file
29
src/main/java/com/replaymod/replay/gui/screen/ReplayList.java
Executable file
@@ -0,0 +1,29 @@
|
||||
package com.replaymod.replay.gui.screen;
|
||||
|
||||
import eu.crushedpixel.replaymod.gui.elements.GuiReplayListExtended;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
public class ReplayList extends GuiReplayListExtended {
|
||||
|
||||
private GuiReplayViewer parent;
|
||||
|
||||
public ReplayList(GuiReplayViewer 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user