Replaced Spectate Selection GUI with Player Overview GUI, added way to hide specific players
Updated Skin File retrieving to new Mojang API IMPORTANT: clean and rebuild the IntelliJ project, Access Transformers added!
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
package eu.crushedpixel.replaymod;
|
package eu.crushedpixel.replaymod;
|
||||||
|
|
||||||
import eu.crushedpixel.replaymod.api.client.ApiClient;
|
import eu.crushedpixel.replaymod.api.ApiClient;
|
||||||
import eu.crushedpixel.replaymod.chat.ChatMessageHandler;
|
import eu.crushedpixel.replaymod.chat.ChatMessageHandler;
|
||||||
import eu.crushedpixel.replaymod.events.*;
|
import eu.crushedpixel.replaymod.events.*;
|
||||||
import eu.crushedpixel.replaymod.localization.LocalizedResourcePack;
|
import eu.crushedpixel.replaymod.localization.LocalizedResourcePack;
|
||||||
@@ -8,6 +8,7 @@ import eu.crushedpixel.replaymod.online.authentication.AuthenticationHandler;
|
|||||||
import eu.crushedpixel.replaymod.recording.ConnectionEventHandler;
|
import eu.crushedpixel.replaymod.recording.ConnectionEventHandler;
|
||||||
import eu.crushedpixel.replaymod.reflection.MCPNames;
|
import eu.crushedpixel.replaymod.reflection.MCPNames;
|
||||||
import eu.crushedpixel.replaymod.registry.*;
|
import eu.crushedpixel.replaymod.registry.*;
|
||||||
|
import eu.crushedpixel.replaymod.renderer.InvisibilityRender;
|
||||||
import eu.crushedpixel.replaymod.renderer.SafeEntityRenderer;
|
import eu.crushedpixel.replaymod.renderer.SafeEntityRenderer;
|
||||||
import eu.crushedpixel.replaymod.replay.ReplaySender;
|
import eu.crushedpixel.replaymod.replay.ReplaySender;
|
||||||
import eu.crushedpixel.replaymod.settings.ReplaySettings;
|
import eu.crushedpixel.replaymod.settings.ReplaySettings;
|
||||||
@@ -134,6 +135,9 @@ public class ReplayMod {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mc.getRenderManager().skinMap.put("default", new InvisibilityRender(mc.getRenderManager()));
|
||||||
|
mc.getRenderManager().skinMap.put("slim", new InvisibilityRender(mc.getRenderManager(), true));
|
||||||
|
|
||||||
//clean up replay_recordings folder
|
//clean up replay_recordings folder
|
||||||
removeTmcprFiles();
|
removeTmcprFiles();
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import eu.crushedpixel.replaymod.gui.GuiMouseInput;
|
|||||||
import eu.crushedpixel.replaymod.registry.KeybindRegistry;
|
import eu.crushedpixel.replaymod.registry.KeybindRegistry;
|
||||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||||
import eu.crushedpixel.replaymod.replay.ReplayProcess;
|
import eu.crushedpixel.replaymod.replay.ReplayProcess;
|
||||||
import eu.crushedpixel.replaymod.replay.spectate.SpectateHandler;
|
import eu.crushedpixel.replaymod.registry.PlayerHandler;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.settings.KeyBinding;
|
import net.minecraft.client.settings.KeyBinding;
|
||||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||||
@@ -124,8 +124,8 @@ public class KeyInputHandler {
|
|||||||
TickAndRenderListener.requestScreenshot();
|
TickAndRenderListener.requestScreenshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_SPECTATE) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !found) {
|
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_PLAYER_OVERVIEW) && (kb.isPressed() || kb.getKeyCode() == keyCode) && !found) {
|
||||||
SpectateHandler.openSpectateSelection();
|
PlayerHandler.openPlayerOverview();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_LIGHTING) && (kb.isPressed() || kb.getKeyCode() == keyCode)) {
|
if(kb.getKeyDescription().equals(KeybindRegistry.KEY_LIGHTING) && (kb.isPressed() || kb.getKeyCode() == keyCode)) {
|
||||||
|
|||||||
@@ -66,4 +66,17 @@ public class GuiConstants {
|
|||||||
public static final int KEYFRAME_REPOSITORY_ADD_BUTTON = 3456;
|
public static final int KEYFRAME_REPOSITORY_ADD_BUTTON = 3456;
|
||||||
public static final int KEYFRAME_REPOSITORY_REMOVE_BUTTON = 4567;
|
public static final int KEYFRAME_REPOSITORY_REMOVE_BUTTON = 4567;
|
||||||
public static final int KEYFRAME_REPOSITORY_LOAD_BUTTON = 5678;
|
public static final int KEYFRAME_REPOSITORY_LOAD_BUTTON = 5678;
|
||||||
|
|
||||||
|
public static final int KEYFRAME_EDITOR_SAVE_BUTTON = 6000;
|
||||||
|
public static final int KEYFRAME_EDITOR_CANCEL_BUTTON = 6001;
|
||||||
|
public static final int KEYFRAME_EDITOR_RIGHT_BUTTON = 6002;
|
||||||
|
public static final int KEYFRAME_EDITOR_LEFT_BUTTON = 6003;
|
||||||
|
public static final int KEYFRAME_EDITOR_X_INPUT = 6004;
|
||||||
|
public static final int KEYFRAME_EDITOR_Y_INPUT = 6005;
|
||||||
|
public static final int KEYFRAME_EDITOR_Z_INPUT = 6006;
|
||||||
|
public static final int KEYFRAME_EDITOR_PITCH_INPUT = 6007;
|
||||||
|
public static final int KEYFRAME_EDITOR_YAW_INPUT = 6008;
|
||||||
|
|
||||||
|
public static final int PLAYER_OVERVIEW_HIDE_ALL = 1010;
|
||||||
|
public static final int PLAYER_OVERVIEW_SHOW_ALL = 0101;
|
||||||
}
|
}
|
||||||
|
|||||||
317
src/main/java/eu/crushedpixel/replaymod/gui/GuiPlayerOverview.java
Executable file
317
src/main/java/eu/crushedpixel/replaymod/gui/GuiPlayerOverview.java
Executable file
@@ -0,0 +1,317 @@
|
|||||||
|
package eu.crushedpixel.replaymod.gui;
|
||||||
|
|
||||||
|
import com.mojang.realmsclient.util.Pair;
|
||||||
|
import eu.crushedpixel.replaymod.ReplayMod;
|
||||||
|
import eu.crushedpixel.replaymod.api.mojang.SkinDownloader;
|
||||||
|
import eu.crushedpixel.replaymod.registry.PlayerHandler;
|
||||||
|
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.Gui;
|
||||||
|
import net.minecraft.client.gui.GuiButton;
|
||||||
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
|
import net.minecraft.client.renderer.GlStateManager;
|
||||||
|
import net.minecraft.client.renderer.texture.ITextureObject;
|
||||||
|
import net.minecraft.client.resources.DefaultPlayerSkin;
|
||||||
|
import net.minecraft.client.resources.I18n;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.entity.player.EnumPlayerModelParts;
|
||||||
|
import net.minecraft.potion.Potion;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraftforge.fml.client.config.GuiCheckBox;
|
||||||
|
import org.lwjgl.input.Mouse;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GuiPlayerOverview extends GuiScreen {
|
||||||
|
|
||||||
|
private List<Pair<EntityPlayer, ResourceLocation>> players;
|
||||||
|
private List<GuiCheckBox> checkBoxes;
|
||||||
|
private List<Integer> loadedPlayers = new ArrayList<Integer>();
|
||||||
|
|
||||||
|
private GuiCheckBox hideAllBox, showAllBox;
|
||||||
|
|
||||||
|
private boolean initialized = false;
|
||||||
|
|
||||||
|
private int playerCount;
|
||||||
|
private int upperPlayer = 0;
|
||||||
|
|
||||||
|
private int lowerBound;
|
||||||
|
|
||||||
|
private boolean drag = false;
|
||||||
|
private int lastY = 0;
|
||||||
|
private int fitting = 0;
|
||||||
|
|
||||||
|
private final Minecraft mc = Minecraft.getMinecraft();
|
||||||
|
|
||||||
|
private final String screenTitle = I18n.format("replaymod.input.playeroverview");
|
||||||
|
|
||||||
|
public GuiPlayerOverview(List<EntityPlayer> players) {
|
||||||
|
Collections.sort(players, new PlayerComparator());
|
||||||
|
|
||||||
|
this.players = new ArrayList<Pair<EntityPlayer, ResourceLocation>>();
|
||||||
|
this.checkBoxes = new ArrayList<GuiCheckBox>();
|
||||||
|
|
||||||
|
for(final EntityPlayer p : players) {
|
||||||
|
final ResourceLocation loc = new ResourceLocation("/temp-skins/" + p.getGameProfile().getName());
|
||||||
|
|
||||||
|
this.players.add(Pair.of(p, loc));
|
||||||
|
|
||||||
|
//mc.getTextureManager().loadTexture(loc, new SimpleTexture(DefaultPlayerSkin.getDefaultSkin(p.getUniqueID())));
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
final ITextureObject tex = SkinDownloader.getDownloadImageSkin(loc, p.getUniqueID());
|
||||||
|
mc.addScheduledTask(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mc.getTextureManager().loadTexture(loc, tex);
|
||||||
|
loadedPlayers.add(p.getEntityId());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch(Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
playerCount = players.size();
|
||||||
|
|
||||||
|
ReplayMod.replaySender.setReplaySpeed(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSpectator(EntityPlayer e) {
|
||||||
|
return e.isInvisible() && e.getActivePotionEffect(Potion.invisibility) == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void mouseClicked(int mouseX, int mouseY, int mouseButton)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
if(fitting < playerCount) {
|
||||||
|
float visiblePerc = (float) fitting / (float) playerCount;
|
||||||
|
|
||||||
|
int h = this.height - 32 - 32;
|
||||||
|
int offset = Math.round((upperPlayer / (fitting)) * visiblePerc * h);
|
||||||
|
|
||||||
|
int lower = Math.round(32 + offset + (h * visiblePerc)) - 2;
|
||||||
|
|
||||||
|
int k2 = (int) (this.width * 0.3);
|
||||||
|
|
||||||
|
if(mouseX >= k2 - 16 && mouseX <= k2 - 12 && mouseY >= 32 - 2 + offset && mouseY <= lower) {
|
||||||
|
lastY = mouseY;
|
||||||
|
drag = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int k2 = (int) (this.width * 0.3);
|
||||||
|
|
||||||
|
if(mouseX >= k2 && mouseX <= (this.width * 0.6) && mouseY >= 60 && mouseY <= lowerBound) {
|
||||||
|
int off = mouseY - 60;
|
||||||
|
int p = (off / 21) + upperPlayer;
|
||||||
|
ReplayHandler.spectateEntity(players.get(p).first());
|
||||||
|
mc.displayGuiScreen(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
super.mouseClicked(mouseX, mouseY, mouseButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void mouseClickMove(int mouseX, int mouseY,
|
||||||
|
int clickedMouseButton, long timeSinceLastClick) {
|
||||||
|
|
||||||
|
if(drag) {
|
||||||
|
float step = 1f / (float) playerCount;
|
||||||
|
|
||||||
|
int diff = mouseY - lastY;
|
||||||
|
int h = this.height - 32 - 32;
|
||||||
|
|
||||||
|
float percDiff = (float) diff / (float) h;
|
||||||
|
if(Math.abs(percDiff) > Math.abs(step)) {
|
||||||
|
int s = (int) (percDiff / step);
|
||||||
|
lastY = mouseY;
|
||||||
|
upperPlayer += s;
|
||||||
|
if(upperPlayer > playerCount - fitting) {
|
||||||
|
upperPlayer = playerCount - fitting;
|
||||||
|
} else if(upperPlayer < 0) {
|
||||||
|
upperPlayer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void mouseReleased(int mouseX, int mouseY, int state) {
|
||||||
|
drag = false;
|
||||||
|
|
||||||
|
for(GuiCheckBox checkBox : checkBoxes) {
|
||||||
|
checkBox.mouseReleased(mouseX, mouseY);
|
||||||
|
}
|
||||||
|
|
||||||
|
super.mouseReleased(mouseX, mouseY, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initGui() {
|
||||||
|
upperPlayer = 0;
|
||||||
|
lowerBound = this.height - 10;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for(GuiCheckBox checkBox : checkBoxes) {
|
||||||
|
checkBox.xPosition = (int)(this.width*0.7)-5;
|
||||||
|
buttonList.add(checkBox);
|
||||||
|
i++;
|
||||||
|
if(i >= fitting) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!initialized) {
|
||||||
|
hideAllBox = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_HIDE_ALL, 0, 0, "", false);
|
||||||
|
showAllBox = new GuiCheckBox(GuiConstants.PLAYER_OVERVIEW_SHOW_ALL, 0, 0, "", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
hideAllBox.xPosition = (int)(this.width*0.7)-5;
|
||||||
|
showAllBox.xPosition = (int)(this.width*0.7)-20;
|
||||||
|
hideAllBox.yPosition = showAllBox.yPosition = 45;
|
||||||
|
|
||||||
|
buttonList.add(hideAllBox);
|
||||||
|
buttonList.add(showAllBox);
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void actionPerformed(GuiButton button) throws IOException {
|
||||||
|
if(button == showAllBox) {
|
||||||
|
showAllBox.setIsChecked(true);
|
||||||
|
for(Pair<EntityPlayer, ResourceLocation> p : players) {
|
||||||
|
PlayerHandler.showPlayer(p.first());
|
||||||
|
}
|
||||||
|
} else if(button == hideAllBox) {
|
||||||
|
hideAllBox.setIsChecked(false);
|
||||||
|
for(Pair<EntityPlayer, ResourceLocation> p : players) {
|
||||||
|
PlayerHandler.hidePlayer(p.first());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!(button instanceof GuiCheckBox)) return;
|
||||||
|
if(button.id >= fitting) return;
|
||||||
|
if(!checkBoxes.contains(button)) return;
|
||||||
|
PlayerHandler.setIsVisible(players.get(upperPlayer + button.id).first(), ((GuiCheckBox)button).isChecked());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
|
||||||
|
this.drawCenteredString(fontRendererObj, screenTitle, this.width / 2, 5, Color.WHITE.getRGB());
|
||||||
|
int k2 = (int)(this.width * 0.3);
|
||||||
|
int l2 = 60;
|
||||||
|
int l3 = l2;
|
||||||
|
|
||||||
|
drawGradientRect(k2 - 20, 20, (int) (this.width * 0.7) + 20, this.height - 30 - 2 + 10, -1072689136, -804253680);
|
||||||
|
|
||||||
|
drawString(fontRendererObj, I18n.format("replaymod.gui.playeroverview.spectate"), k2 - 10, 30, Color.WHITE.getRGB());
|
||||||
|
|
||||||
|
String visibleString = I18n.format("replaymod.gui.playeroverview.visible");
|
||||||
|
drawString(fontRendererObj, visibleString, (int) (this.width * 0.7) + 10 - fontRendererObj.getStringWidth(visibleString), 30, Color.WHITE.getRGB());
|
||||||
|
|
||||||
|
fitting = 0;
|
||||||
|
|
||||||
|
int sk = 0;
|
||||||
|
for(Pair<EntityPlayer, ResourceLocation> p : players) {
|
||||||
|
if(sk < upperPlayer) {
|
||||||
|
sk++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
boolean spec = isSpectator(p.first());
|
||||||
|
|
||||||
|
this.drawString(fontRendererObj, p.first().getName(), k2 + 16 + 5, l2 + 8 - (fontRendererObj.FONT_HEIGHT / 2),
|
||||||
|
spec ? Color.DARK_GRAY.getRGB() : Color.WHITE.getRGB());
|
||||||
|
|
||||||
|
if(loadedPlayers.contains(p.first().getEntityId())) {
|
||||||
|
mc.getTextureManager().bindTexture(p.second());
|
||||||
|
} else {
|
||||||
|
mc.getTextureManager().bindTexture(DefaultPlayerSkin.getDefaultSkin(p.first().getUniqueID()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
drawScaledCustomSizeModalRect(k2, l2, 8.0F, 8.0F, 8, 8, 16, 16, 64.0F, 64.0F);
|
||||||
|
if(p.first().func_175148_a(EnumPlayerModelParts.HAT))
|
||||||
|
Gui.drawScaledCustomSizeModalRect(k2, l2, 40.0F, 8.0F, 8, 8, 16, 16, 64.0F, 64.0F);
|
||||||
|
|
||||||
|
GlStateManager.resetColor();
|
||||||
|
if(fitting >= checkBoxes.size()) {
|
||||||
|
checkBoxes.add(new GuiCheckBox(checkBoxes.size(), (int)(this.width*0.7)-5, l2+3, "", true));
|
||||||
|
buttonList.add(checkBoxes.get(checkBoxes.size() - 1));
|
||||||
|
}
|
||||||
|
checkBoxes.get(fitting).setIsChecked(!PlayerHandler.isHidden(p.first().getEntityId()));
|
||||||
|
|
||||||
|
l2 += 16 + 5;
|
||||||
|
fitting++;
|
||||||
|
if(l2 + 32 > lowerBound) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int dw = Mouse.getDWheel();
|
||||||
|
if(dw > 0) {
|
||||||
|
dw = -1;
|
||||||
|
} else if(dw < 0) {
|
||||||
|
dw = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
upperPlayer = Math.max(Math.min(upperPlayer + dw, playerCount - fitting), 0);
|
||||||
|
|
||||||
|
if(fitting < playerCount) {
|
||||||
|
float visiblePerc = ((float) fitting) / playerCount;
|
||||||
|
int barHeight = (int) (visiblePerc * (height - 32 - 32));
|
||||||
|
|
||||||
|
float posPerc = ((float) upperPlayer) / playerCount;
|
||||||
|
int barY = (int) (posPerc * (height - 32 - 32));
|
||||||
|
|
||||||
|
drawRect(k2 - 18, l3 - 2, k2 - 10, this.height - 30 - 2, Color.BLACK.getRGB());
|
||||||
|
drawRect(k2 - 16, l3+2 - 2 + barY, k2 - 12, 30+2 - 1 + barY + barHeight, Color.LIGHT_GRAY.getRGB());
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for(GuiCheckBox checkBox : checkBoxes) {
|
||||||
|
checkBox.drawButton(mc, mouseX, mouseY);
|
||||||
|
i++;
|
||||||
|
if(i >= fitting) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
hideAllBox.drawButton(mc, mouseX, mouseY);
|
||||||
|
showAllBox.drawButton(mc, mouseX, mouseY);
|
||||||
|
|
||||||
|
if(hideAllBox.isMouseOver()) {
|
||||||
|
drawCenteredString(fontRendererObj, I18n.format("replaymod.gui.playeroverview.hideall"), mouseX, mouseY+5, Color.WHITE.getRGB());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(showAllBox.isMouseOver()) {
|
||||||
|
drawCenteredString(fontRendererObj, I18n.format("replaymod.gui.playeroverview.showall"), mouseX, mouseY+5, Color.WHITE.getRGB());
|
||||||
|
}
|
||||||
|
|
||||||
|
drawRect(0, 0, 0, 0, Color.LIGHT_GRAY.getRGB());
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PlayerComparator implements Comparator<EntityPlayer> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(EntityPlayer o1, EntityPlayer o2) {
|
||||||
|
if(isSpectator(o1) && !isSpectator(o2)) {
|
||||||
|
return 1;
|
||||||
|
} else if(isSpectator(o2) && !isSpectator(o1)) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return o1.getName().compareToIgnoreCase(o2.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,199 +0,0 @@
|
|||||||
package eu.crushedpixel.replaymod.gui;
|
|
||||||
|
|
||||||
import com.mojang.realmsclient.util.Pair;
|
|
||||||
import eu.crushedpixel.replaymod.ReplayMod;
|
|
||||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
|
||||||
import net.minecraft.client.entity.AbstractClientPlayer;
|
|
||||||
import net.minecraft.client.gui.Gui;
|
|
||||||
import net.minecraft.client.gui.GuiScreen;
|
|
||||||
import net.minecraft.client.renderer.GlStateManager;
|
|
||||||
import net.minecraft.client.resources.I18n;
|
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
|
||||||
import net.minecraft.entity.player.EnumPlayerModelParts;
|
|
||||||
import net.minecraft.potion.Potion;
|
|
||||||
import net.minecraft.util.ResourceLocation;
|
|
||||||
import org.lwjgl.input.Mouse;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class GuiSpectateSelection extends GuiScreen {
|
|
||||||
|
|
||||||
private List<Pair<EntityPlayer, ResourceLocation>> players;
|
|
||||||
private int playerCount;
|
|
||||||
private int upperPlayer = 0;
|
|
||||||
|
|
||||||
private int lowerBound;
|
|
||||||
|
|
||||||
private boolean drag = false;
|
|
||||||
private int lastY = 0;
|
|
||||||
private int fitting = 0;
|
|
||||||
|
|
||||||
private final String screenTitle = I18n.format("replaymod.gui.spectate.title");
|
|
||||||
|
|
||||||
public GuiSpectateSelection(List<EntityPlayer> players) {
|
|
||||||
Collections.sort(players, new PlayerComparator());
|
|
||||||
|
|
||||||
this.players = new ArrayList<Pair<EntityPlayer, ResourceLocation>>();
|
|
||||||
|
|
||||||
for(EntityPlayer p : players) {
|
|
||||||
ResourceLocation loc = new ResourceLocation("/temp-skins/" + p.getGameProfile().getName());
|
|
||||||
AbstractClientPlayer.getDownloadImageSkin(loc, p.getName());
|
|
||||||
this.players.add(Pair.of(p, loc));
|
|
||||||
}
|
|
||||||
|
|
||||||
playerCount = players.size();
|
|
||||||
|
|
||||||
ReplayMod.replaySender.setReplaySpeed(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isSpectator(EntityPlayer e) {
|
|
||||||
return e.isInvisible() && e.getActivePotionEffect(Potion.invisibility) == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void mouseClicked(int mouseX, int mouseY, int mouseButton)
|
|
||||||
throws IOException {
|
|
||||||
|
|
||||||
if(fitting < playerCount) {
|
|
||||||
float visiblePerc = (float) fitting / (float) playerCount;
|
|
||||||
|
|
||||||
int h = this.height - 32 - 32;
|
|
||||||
int offset = Math.round((upperPlayer / (fitting)) * visiblePerc * h);
|
|
||||||
|
|
||||||
int lower = Math.round(32 + offset + (h * visiblePerc)) - 2;
|
|
||||||
|
|
||||||
int k2 = (int) (this.width * 0.4);
|
|
||||||
|
|
||||||
if(mouseX >= k2 - 16 && mouseX <= k2 - 12 && mouseY >= 32 - 2 + offset && mouseY <= lower) {
|
|
||||||
lastY = mouseY;
|
|
||||||
drag = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int k2 = (int) (this.width * 0.4);
|
|
||||||
|
|
||||||
if(mouseX >= k2 && mouseX <= (this.width * 0.6) && mouseY >= 30 && mouseY <= lowerBound) {
|
|
||||||
int off = mouseY - 30;
|
|
||||||
int p = (off / 21) + upperPlayer;
|
|
||||||
ReplayHandler.spectateEntity(players.get(p).first());
|
|
||||||
mc.displayGuiScreen(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void mouseClickMove(int mouseX, int mouseY,
|
|
||||||
int clickedMouseButton, long timeSinceLastClick) {
|
|
||||||
|
|
||||||
if(drag) {
|
|
||||||
float step = 1f / (float) playerCount;
|
|
||||||
|
|
||||||
int diff = mouseY - lastY;
|
|
||||||
int h = this.height - 32 - 32;
|
|
||||||
|
|
||||||
float percDiff = (float) diff / (float) h;
|
|
||||||
if(Math.abs(percDiff) > Math.abs(step)) {
|
|
||||||
int s = (int) (percDiff / step);
|
|
||||||
lastY = mouseY;
|
|
||||||
upperPlayer += s;
|
|
||||||
if(upperPlayer > playerCount - fitting) {
|
|
||||||
upperPlayer = playerCount - fitting;
|
|
||||||
} else if(upperPlayer < 0) {
|
|
||||||
upperPlayer = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void mouseReleased(int mouseX, int mouseY, int state) {
|
|
||||||
drag = false;
|
|
||||||
|
|
||||||
super.mouseReleased(mouseX, mouseY, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void initGui() {
|
|
||||||
upperPlayer = 0;
|
|
||||||
lowerBound = this.height - 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
|
|
||||||
this.drawCenteredString(fontRendererObj, screenTitle, this.width / 2, 5, Color.WHITE.getRGB());
|
|
||||||
int k2 = (int) (this.width * 0.4);
|
|
||||||
int l2 = 30;
|
|
||||||
|
|
||||||
drawGradientRect(k2 - 10, l2 - 10, (int) (this.width * 0.6) + 20, this.height - 30 - 2 + 10, -1072689136, -804253680);
|
|
||||||
|
|
||||||
fitting = 0;
|
|
||||||
|
|
||||||
int sk = 0;
|
|
||||||
for(Pair<EntityPlayer, ResourceLocation> p : players) {
|
|
||||||
if(sk < upperPlayer) {
|
|
||||||
sk++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
boolean spec = isSpectator(p.first());
|
|
||||||
|
|
||||||
this.drawString(fontRendererObj, p.first().getName(), k2 + 16 + 5, l2 + 8 - (fontRendererObj.FONT_HEIGHT / 2),
|
|
||||||
spec ? Color.DARK_GRAY.getRGB() : Color.WHITE.getRGB());
|
|
||||||
|
|
||||||
mc.getTextureManager().bindTexture(p.second());
|
|
||||||
|
|
||||||
drawScaledCustomSizeModalRect(k2, l2, 8.0F, 8.0F, 8, 8, 16, 16, 64.0F, 64.0F);
|
|
||||||
if(p.first().func_175148_a(EnumPlayerModelParts.HAT))
|
|
||||||
Gui.drawScaledCustomSizeModalRect(k2, l2, 40.0F, 8.0F, 8, 8, 16, 16, 64.0F, 64.0F);
|
|
||||||
|
|
||||||
GlStateManager.resetColor();
|
|
||||||
|
|
||||||
l2 += 16 + 5;
|
|
||||||
fitting++;
|
|
||||||
if(l2 + 32 > lowerBound) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int dw = Mouse.getDWheel();
|
|
||||||
if(dw > 0) {
|
|
||||||
dw = -1;
|
|
||||||
} else if(dw < 0) {
|
|
||||||
dw = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
upperPlayer = Math.max(Math.min(upperPlayer + dw, playerCount - fitting), 0);
|
|
||||||
|
|
||||||
if(fitting < playerCount) {
|
|
||||||
float visiblePerc = ((float) fitting) / playerCount;
|
|
||||||
int barHeight = (int) (visiblePerc * (height - 32 - 32));
|
|
||||||
|
|
||||||
float posPerc = ((float) upperPlayer) / playerCount;
|
|
||||||
int barY = (int) (posPerc * (height - 32 - 32));
|
|
||||||
|
|
||||||
drawRect(k2 - 18, 30 - 2, k2 - 10, this.height - 30 - 2, Color.BLACK.getRGB());
|
|
||||||
drawRect(k2 - 16, 32 - 2 + barY, k2 - 12, 32 - 1 + barY + barHeight, Color.LIGHT_GRAY.getRGB());
|
|
||||||
}
|
|
||||||
super.drawScreen(mouseX, mouseY, partialTicks);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class PlayerComparator implements Comparator<EntityPlayer> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compare(EntityPlayer o1, EntityPlayer o2) {
|
|
||||||
if(isSpectator(o1) && !isSpectator(o2)) {
|
|
||||||
return 1;
|
|
||||||
} else if(isSpectator(o2) && !isSpectator(o1)) {
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
return o1.getName().compareToIgnoreCase(o2.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,7 +12,7 @@ public class KeybindRegistry {
|
|||||||
|
|
||||||
public static final String KEY_LIGHTING = "replaymod.input.lighting";
|
public static final String KEY_LIGHTING = "replaymod.input.lighting";
|
||||||
public static final String KEY_THUMBNAIL = "replaymod.input.thumbnail";
|
public static final String KEY_THUMBNAIL = "replaymod.input.thumbnail";
|
||||||
public static final String KEY_SPECTATE = "replaymod.input.spectate";
|
public static final String KEY_PLAYER_OVERVIEW = "replaymod.input.playeroverview";
|
||||||
public static final String KEY_CLEAR_KEYFRAMES = "replaymod.input.clearkeyframes";
|
public static final String KEY_CLEAR_KEYFRAMES = "replaymod.input.clearkeyframes";
|
||||||
public static final String KEY_SYNC_TIMELINE = "replaymod.input.synctimeline";
|
public static final String KEY_SYNC_TIMELINE = "replaymod.input.synctimeline";
|
||||||
public static final String KEY_KEYFRAME_PRESETS = "replaymod.input.keyframerepository";
|
public static final String KEY_KEYFRAME_PRESETS = "replaymod.input.keyframerepository";
|
||||||
@@ -27,7 +27,7 @@ public class KeybindRegistry {
|
|||||||
|
|
||||||
bindings.add(new KeyBinding(KEY_LIGHTING, Keyboard.KEY_M, "replaymod.title"));
|
bindings.add(new KeyBinding(KEY_LIGHTING, Keyboard.KEY_M, "replaymod.title"));
|
||||||
bindings.add(new KeyBinding(KEY_THUMBNAIL, Keyboard.KEY_N, "replaymod.title"));
|
bindings.add(new KeyBinding(KEY_THUMBNAIL, Keyboard.KEY_N, "replaymod.title"));
|
||||||
bindings.add(new KeyBinding(KEY_SPECTATE, Keyboard.KEY_B, "replaymod.title"));
|
bindings.add(new KeyBinding(KEY_PLAYER_OVERVIEW, Keyboard.KEY_B, "replaymod.title"));
|
||||||
bindings.add(new KeyBinding(KEY_SYNC_TIMELINE, Keyboard.KEY_V, "replaymod.title"));
|
bindings.add(new KeyBinding(KEY_SYNC_TIMELINE, Keyboard.KEY_V, "replaymod.title"));
|
||||||
bindings.add(new KeyBinding(KEY_CLEAR_KEYFRAMES, Keyboard.KEY_C, "replaymod.title"));
|
bindings.add(new KeyBinding(KEY_CLEAR_KEYFRAMES, Keyboard.KEY_C, "replaymod.title"));
|
||||||
bindings.add(new KeyBinding(KEY_KEYFRAME_PRESETS, Keyboard.KEY_X, "replaymod.title"));
|
bindings.add(new KeyBinding(KEY_KEYFRAME_PRESETS, Keyboard.KEY_X, "replaymod.title"));
|
||||||
|
|||||||
67
src/main/java/eu/crushedpixel/replaymod/registry/PlayerHandler.java
Executable file
67
src/main/java/eu/crushedpixel/replaymod/registry/PlayerHandler.java
Executable file
@@ -0,0 +1,67 @@
|
|||||||
|
package eu.crushedpixel.replaymod.registry;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import eu.crushedpixel.replaymod.entities.CameraEntity;
|
||||||
|
import eu.crushedpixel.replaymod.gui.GuiPlayerOverview;
|
||||||
|
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class PlayerHandler {
|
||||||
|
|
||||||
|
private static Minecraft mc = Minecraft.getMinecraft();
|
||||||
|
|
||||||
|
private static Predicate<EntityPlayer> playerPredicate = new Predicate<EntityPlayer>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(EntityPlayer input) {
|
||||||
|
if(input instanceof CameraEntity || input == mc.thePlayer) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static List<Integer> hidden = new ArrayList<Integer>();
|
||||||
|
|
||||||
|
public static void hidePlayer(EntityPlayer player) {
|
||||||
|
hidden.remove((Integer) player.getEntityId());
|
||||||
|
hidden.add(player.getEntityId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void showPlayer(EntityPlayer player) {
|
||||||
|
hidden.remove((Integer) player.getEntityId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setIsVisible(EntityPlayer player, boolean visible) {
|
||||||
|
if(visible) showPlayer(player);
|
||||||
|
else hidePlayer(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Integer> getHiddenPlayers() {
|
||||||
|
return hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isHidden(int id) {
|
||||||
|
return hidden.contains(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetHiddenPlayers() {
|
||||||
|
for(int i : hidden) {
|
||||||
|
Entity ent = mc.theWorld.getEntityByID(i);
|
||||||
|
if(ent != null) {
|
||||||
|
ent.setInvisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void openPlayerOverview() {
|
||||||
|
if(!ReplayHandler.isInReplay()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<EntityPlayer> players = mc.theWorld.getEntities(EntityPlayer.class, playerPredicate);
|
||||||
|
mc.displayGuiScreen(new GuiPlayerOverview(players));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package eu.crushedpixel.replaymod.renderer;
|
||||||
|
|
||||||
|
import eu.crushedpixel.replaymod.registry.PlayerHandler;
|
||||||
|
import net.minecraft.client.renderer.culling.ICamera;
|
||||||
|
import net.minecraft.client.renderer.entity.RenderManager;
|
||||||
|
import net.minecraft.client.renderer.entity.RenderPlayer;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
|
||||||
|
public class InvisibilityRender extends RenderPlayer {
|
||||||
|
|
||||||
|
public InvisibilityRender(RenderManager renderManager) {
|
||||||
|
super(renderManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvisibilityRender(RenderManager renderManager, boolean useSmallArms) {
|
||||||
|
super(renderManager, useSmallArms);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldRender(Entity entity, ICamera camera, double camX, double camY, double camZ) {
|
||||||
|
if(PlayerHandler.isHidden(entity.getEntityId())) return false;
|
||||||
|
return super.shouldRender(entity, camera, camX, camY, camZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import com.mojang.authlib.GameProfile;
|
|||||||
import eu.crushedpixel.replaymod.ReplayMod;
|
import eu.crushedpixel.replaymod.ReplayMod;
|
||||||
import eu.crushedpixel.replaymod.entities.CameraEntity;
|
import eu.crushedpixel.replaymod.entities.CameraEntity;
|
||||||
import eu.crushedpixel.replaymod.holders.*;
|
import eu.crushedpixel.replaymod.holders.*;
|
||||||
|
import eu.crushedpixel.replaymod.registry.PlayerHandler;
|
||||||
import eu.crushedpixel.replaymod.utils.ReplayFile;
|
import eu.crushedpixel.replaymod.utils.ReplayFile;
|
||||||
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
import eu.crushedpixel.replaymod.utils.ReplayFileIO;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
@@ -343,6 +344,8 @@ public class ReplayHandler {
|
|||||||
KeyframeSet[] paths = currentReplayFile.paths().get();
|
KeyframeSet[] paths = currentReplayFile.paths().get();
|
||||||
ReplayHandler.setKeyframeRepository(paths == null ? new KeyframeSet[0] : paths, false);
|
ReplayHandler.setKeyframeRepository(paths == null ? new KeyframeSet[0] : paths, false);
|
||||||
|
|
||||||
|
PlayerHandler.resetHiddenPlayers();
|
||||||
|
|
||||||
ReplayMod.replaySender = new ReplaySender(currentReplayFile, true);
|
ReplayMod.replaySender = new ReplaySender(currentReplayFile, true);
|
||||||
channel.pipeline().addFirst(ReplayMod.replaySender);
|
channel.pipeline().addFirst(ReplayMod.replaySender);
|
||||||
channel.pipeline().fireChannelActive();
|
channel.pipeline().fireChannelActive();
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
package eu.crushedpixel.replaymod.replay.spectate;
|
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
|
||||||
import eu.crushedpixel.replaymod.entities.CameraEntity;
|
|
||||||
import eu.crushedpixel.replaymod.gui.GuiSpectateSelection;
|
|
||||||
import eu.crushedpixel.replaymod.replay.ReplayHandler;
|
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class SpectateHandler {
|
|
||||||
|
|
||||||
private static Minecraft mc = Minecraft.getMinecraft();
|
|
||||||
|
|
||||||
private static Predicate<EntityPlayer> playerPredicate = new Predicate<EntityPlayer>() {
|
|
||||||
@Override
|
|
||||||
public boolean apply(EntityPlayer input) {
|
|
||||||
if(input instanceof CameraEntity || input == mc.thePlayer) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public static void openSpectateSelection() {
|
|
||||||
if(!ReplayHandler.isInReplay()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<EntityPlayer> players = mc.theWorld.getEntities(EntityPlayer.class, playerPredicate);
|
|
||||||
mc.displayGuiScreen(new GuiSpectateSelection(players));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# To apply changes in this file run: ./gradlew clean setupDevWorkspace idea
|
# To apply changes in this file run: ./gradlew clean setupDecompWorkspace idea
|
||||||
|
|
||||||
# Minecraft
|
# Minecraft
|
||||||
public net.minecraft.client.Minecraft field_71428_T # timer
|
public net.minecraft.client.Minecraft field_71428_T # timer
|
||||||
@@ -39,5 +39,8 @@ public net.minecraft.client.resources.ResourcePackRepository field_148534_e # di
|
|||||||
# EntityRenderer
|
# EntityRenderer
|
||||||
public net.minecraft.client.renderer.EntityRenderer field_147711_ac # resourceManager
|
public net.minecraft.client.renderer.EntityRenderer field_147711_ac # resourceManager
|
||||||
|
|
||||||
|
#RenderManager
|
||||||
|
public net.minecraft.client.renderer.entity.RenderManager field_178636_l # skinMap
|
||||||
|
|
||||||
# Example
|
# Example
|
||||||
# public net.minecraft.package.ClassName func_some_id(Ljava/lang/Class;IZS)V # methodName
|
# public net.minecraft.package.ClassName func_some_id(Ljava/lang/Class;IZS)V # methodName
|
||||||
|
|||||||
@@ -156,17 +156,19 @@ replaymod.gui.editor.trim.description=Removes the beginning and end of a Replay
|
|||||||
replaymod.gui.editor.connect.description=Connects multiple Replays in the specified order
|
replaymod.gui.editor.connect.description=Connects multiple Replays in the specified order
|
||||||
replaymod.gui.editor.modify.description=Provides several filters to modify Replay Files
|
replaymod.gui.editor.modify.description=Provides several filters to modify Replay Files
|
||||||
|
|
||||||
#Spectate Player GUI
|
|
||||||
replaymod.gui.spectate.title=Spectate Player
|
|
||||||
|
|
||||||
#Cancel Replay GUI
|
#Cancel Replay GUI
|
||||||
replaymod.gui.cancelrender.title=Cancel Rendering
|
replaymod.gui.cancelrender.title=Cancel Rendering
|
||||||
replaymod.gui.cancelrender.message=Are you sure that you want to cancel the current rendering process?
|
replaymod.gui.cancelrender.message=Are you sure that you want to cancel the current rendering process?
|
||||||
|
|
||||||
#Saving Replay GUI
|
#Saving Replay GUI
|
||||||
replaymod.gui.replaysaving.title=Saving Replay File...
|
replaymod.gui.replaysaving.title=Saving Replay File...
|
||||||
replaymod.gui.replaysaving.message=Please wait while your recent Replay is being saved.
|
replaymod.gui.replaysaving.message=Please wait while your recent Replay is being saved.
|
||||||
|
|
||||||
|
#Player Overview GUI
|
||||||
|
replaymod.gui.playeroverview.visible=Visible
|
||||||
|
replaymod.gui.playeroverview.hideall=Hide all
|
||||||
|
replaymod.gui.playeroverview.showall=Show all
|
||||||
|
replaymod.gui.playeroverview.spectate=Spectate Player
|
||||||
|
|
||||||
#Replay Mod Settings GUI
|
#Replay Mod Settings GUI
|
||||||
replaymod.gui.settings.title=Replay Mod Settings
|
replaymod.gui.settings.title=Replay Mod Settings
|
||||||
|
|
||||||
@@ -195,7 +197,7 @@ replaymod.gui.settings.warning.lineb=applied the next time you join a world.
|
|||||||
#Replay Mod Keybindings
|
#Replay Mod Keybindings
|
||||||
replaymod.input.lighting=Toggle Lighting
|
replaymod.input.lighting=Toggle Lighting
|
||||||
replaymod.input.thumbnail=Capture Thumbnail
|
replaymod.input.thumbnail=Capture Thumbnail
|
||||||
replaymod.input.spectate=Spectate Players
|
replaymod.input.playeroverview=Player Overview
|
||||||
replaymod.input.clearkeyframes=Clear Keyframes
|
replaymod.input.clearkeyframes=Clear Keyframes
|
||||||
replaymod.input.synctimeline=Synchronize Timeline
|
replaymod.input.synctimeline=Synchronize Timeline
|
||||||
replaymod.input.keyframerepository=Open Keyframe Presets
|
replaymod.input.keyframerepository=Open Keyframe Presets
|
||||||
@@ -216,3 +218,11 @@ replaymod.gui.keyframerepository.noentries=No Presets available
|
|||||||
|
|
||||||
replaymod.gui.keyframerepository.preset.defaultname=New Keyframe Preset
|
replaymod.gui.keyframerepository.preset.defaultname=New Keyframe Preset
|
||||||
replaymod.gui.keyframerepository.duplicate=This Preset already exists
|
replaymod.gui.keyframerepository.duplicate=This Preset already exists
|
||||||
|
|
||||||
|
#Edit Keyframe GUI
|
||||||
|
replaymod.gui.editkeyframe.title=Edit Keyframe
|
||||||
|
replaymod.gui.editkeyframe.xpos=X Position
|
||||||
|
replaymod.gui.editkeyframe.ypos=Y Position
|
||||||
|
replaymod.gui.editkeyframe.zpos=Z Position
|
||||||
|
replaymod.gui.editkeyframe.campitch=Camera Pitch
|
||||||
|
replaymod.gui.editkeyframe.camyaw=Camera Yaw
|
||||||
|
|||||||
Reference in New Issue
Block a user