Started implementing authentication system

Added information (MC Version and online Users) to Replay Metadata
This commit is contained in:
Marius Metzger
2015-01-22 22:21:25 +01:00
parent ebe6334232
commit 9ae8f9fc5e
17 changed files with 329 additions and 182 deletions

View File

@@ -1,5 +1,6 @@
package eu.crushedpixel.replaymod;
import net.minecraft.client.Minecraft;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
@@ -11,6 +12,7 @@ import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import eu.crushedpixel.replaymod.authentication.AuthenticationHandler;
import eu.crushedpixel.replaymod.events.GuiEventHandler;
import eu.crushedpixel.replaymod.events.GuiReplayOverlay;
import eu.crushedpixel.replaymod.events.RecordingHandler;
@@ -33,19 +35,18 @@ public class ReplayMod
//
//
public static final String MODID = "replaymod";
public static final String VERSION = "0.0.1";
public static GuiReplayOverlay overlay = new GuiReplayOverlay();
public static ReplaySettings replaySettings = new ReplaySettings(0, true, true, true, false);
public static ReplaySettings replaySettings = new ReplaySettings(0, true, true, true, false, false);
public static Configuration config;
public static RecordingHandler recordingHandler;
public static int PLAYER_ID = -1;
public static int TP_DISTANCE_LIMIT = 128;
// The instance of your mod that Forge uses.
@Instance(value = "ReplayModID")
public static ReplayMod instance;
@@ -60,8 +61,10 @@ public class ReplayMod
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.");
replaySettings = new ReplaySettings(maxFileSize.getInt(0), recServer.getBoolean(true), recSP.getBoolean(true), showNot.getBoolean(true), linear.getBoolean(false));
replaySettings = new ReplaySettings(maxFileSize.getInt(0), recServer.getBoolean(true), recSP.getBoolean(true), showNot.getBoolean(true),
linear.getBoolean(false), lighting.getBoolean(false));
config.save();
}
@@ -84,5 +87,7 @@ public class ReplayMod
overlay = new GuiReplayOverlay();
FMLCommonHandler.instance().bus().register(overlay);
MinecraftForge.EVENT_BUS.register(overlay);
AuthenticationHandler.authenticate();
}
}

View File

@@ -0,0 +1,44 @@
package eu.crushedpixel.replaymod.authentication;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.client.Minecraft;
import eu.crushedpixel.replaymod.reflection.MCPNames;
public class AuthenticationHandler {
private static Minecraft mc = Minecraft.getMinecraft();
private static boolean auth = false;
public static boolean isAuthenticated() {
return auth;
}
public static void authenticate() {
auth = isPremiumUsername(Minecraft.getMinecraft().getSession().getUsername());
}
private static final List<String> PREMIUM_USERS = new ArrayList<String>() {
{
add("Ender_Workbench");
add("oleoleMC");
add("Johni0702");
add("Rafessor");
add("bluffamachuck");
add("Panguino");
add("SixteenBy16");
}
};
private static boolean isPremiumUsername(String username) {
//TODO: API check with the website
return (PREMIUM_USERS.contains(username) || MCPNames.env.isMCPEnvironment());
}
private static boolean isPremiumUUID(String uuid) {
//TODO: API check with the website
return false;
}
}

View File

@@ -3,13 +3,12 @@ package eu.crushedpixel.replaymod.entities;
import java.lang.reflect.Field;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.MathHelper;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import net.minecraft.world.WorldSettings.GameType;
import org.lwjgl.Sys;
@@ -17,19 +16,19 @@ import eu.crushedpixel.replaymod.holders.Position;
import eu.crushedpixel.replaymod.replay.LesserDataWatcher;
import eu.crushedpixel.replaymod.replay.ReplayHandler;
public class CameraEntity extends Entity {
public class CameraEntity extends EntityPlayer {
private Vec3 direction;
private double motion;
private Field drawBlockOutline;
private static final double SPEED = 10; //2 blocks per second
private double decay = 4; //decays by 75% per second;
private double decay = 6; //decays by 75% per second;
private long lastCall = 0;
//frac = time since last tick
public void updateMovement() {
Minecraft mc = Minecraft.getMinecraft();
@@ -37,44 +36,44 @@ public class CameraEntity extends Entity {
//Aligns the particle rotation
mc.thePlayer.rotationPitch = ReplayHandler.getCameraEntity().rotationPitch;
mc.thePlayer.rotationYaw = ReplayHandler.getCameraEntity().rotationYaw;
//removes water/suffocation/shadow overlays in screen
mc.thePlayer.posX = 0;
mc.thePlayer.posY = 500;
mc.thePlayer.posZ = 0;
//mc.thePlayer.posX = ReplayHandler.getCameraEntity().posX;
//mc.thePlayer.posY = ReplayHandler.getCameraEntity().posY;
//mc.thePlayer.posZ = ReplayHandler.getCameraEntity().posZ;
}
if(direction == null || motion < 0.1) {
lastCall = Sys.getTime();
return;
}
long frac = Sys.getTime() - lastCall;
if(frac == 0) return;
Vec3 movement = direction.normalize();
double factor = motion*(frac/1000D);
moveRelative(movement.xCoord*factor, movement.yCoord*factor, movement.zCoord*factor);
double decFac = Math.max(0, 1-(decay*(frac/1000D)));
motion *= decFac;
lastCall = Sys.getTime();
}
public void setDirection(float pitch, float yaw) {
this.setRotation(yaw, pitch);
}
public void setMovement(MoveDirection dir) {
Vec3 oldDir = direction;
switch(dir) {
case BACKWARD:
direction = this.getVectorForRotation(-rotationPitch, rotationYaw-180);
@@ -95,84 +94,65 @@ public class CameraEntity extends Entity {
direction = this.getVectorForRotation(-90, 0);
break;
}
if(oldDir != null) direction = direction.normalize().add(new Vec3(oldDir.xCoord*(motion/4f), oldDir.yCoord*(motion/4f), oldDir.zCoord*(motion/4f)).normalize());
this.motion = SPEED;
}
public void moveAbsolute(double x, double y, double z) {
if(ReplayHandler.isReplaying()) return;
this.posX = x;
this.posY = y;
this.posZ = z;
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
this.lastTickPosX = this.posX;
this.lastTickPosY = this.posY;
this.lastTickPosZ = this.posZ;
this.lastTickPosX = this.prevPosX = this.posX = x;
this.lastTickPosY = this.prevPosY = this.posY = y;
this.lastTickPosZ = this.prevPosZ = this.posZ = z;
}
public void moveRelative(double x, double y, double z) {
if(ReplayHandler.isReplaying()) return;
this.posX += x;
this.posY += y;
this.posZ += z;
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
this.lastTickPosX = this.posX;
this.lastTickPosY = this.posY;
this.lastTickPosZ = this.posZ;
this.lastTickPosX = this.prevPosX = this.posX = this.posX+x;
this.lastTickPosY = this.prevPosY = this.posY = this.posY+y;
this.lastTickPosZ = this.prevPosZ = this.posZ = this.posZ+z;
}
public void movePath(Position pos) {
this.posX = pos.getX();
this.posY = pos.getY();
this.posZ = pos.getZ();
this.rotationPitch = pos.getPitch();
this.rotationYaw = pos.getYaw();
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
this.prevRotationPitch = this.rotationPitch;
this.prevRotationYaw = this.rotationYaw;
this.lastTickPosX = this.posX;
this.lastTickPosY = this.posY;
this.lastTickPosZ = this.posZ;
this.prevRotationPitch = this.rotationPitch = pos.getPitch();
this.prevRotationYaw = this.rotationYaw = pos.getYaw();
this.lastTickPosX = this.prevPosX = this.posX = pos.getX();
this.lastTickPosY = this.prevPosY = this.posY = pos.getY();
this.lastTickPosZ = this.prevPosZ = this.posZ = pos.getZ();
}
@Override
protected void entityInit() {
this.dataWatcher = new LesserDataWatcher(this);
}
public CameraEntity(World worldIn) {
super(worldIn);
//super(worldIn);
super(worldIn, Minecraft.getMinecraft().getSession().getProfile());
}
@Override
public void setAngles(float yaw, float pitch)
{
this.rotationYaw = (float)((double)this.rotationYaw + (double)yaw * 0.15D);
this.rotationPitch = (float)((double)this.rotationPitch - (double)pitch * 0.15D);
this.rotationPitch = MathHelper.clamp_float(this.rotationPitch, -90.0F, 90.0F);
this.prevRotationPitch = this.rotationPitch;
this.prevRotationYaw = this.rotationYaw;
}
public void setAngles(float yaw, float pitch)
{
this.rotationYaw = (float)((double)this.rotationYaw + (double)yaw * 0.15D);
this.rotationPitch = (float)((double)this.rotationPitch - (double)pitch * 0.15D);
this.rotationPitch = MathHelper.clamp_float(this.rotationPitch, -90.0F, 90.0F);
this.prevRotationPitch = this.rotationPitch;
this.prevRotationYaw = this.rotationYaw;
}
@Override
public MovingObjectPosition rayTrace(double p_174822_1_, float p_174822_3_) {
return null;
}
public MovingObjectPosition rayTrace(double p_174822_1_, float p_174822_3_) {
return null;
}
@Override
public boolean canBePushed() {
return false;
}
return false;
}
@Override
protected void createRunningParticles() {}
@@ -186,27 +166,21 @@ public class CameraEntity extends Entity {
return false;
}
/*
public enum MoveDirection {
UP, DOWN, LEFT, RIGHT, FORWARD, BACKWARD;
}
@Override
public void setCurrentItemOrArmor(int slotIn, ItemStack stack) {}
@Override
public ItemStack[] getInventory() {
return null;
}
@Override
public boolean isSpectator() {
return true;
}
*/
@Override
protected void readEntityFromNBT(NBTTagCompound tagCompund) {
// TODO Auto-generated method stub
}
@Override
protected void writeEntityToNBT(NBTTagCompound tagCompound) {
// TODO Auto-generated method stub
}
public enum MoveDirection {
UP, DOWN, LEFT, RIGHT, FORWARD, BACKWARD;
}
}

View File

@@ -15,7 +15,8 @@ import net.minecraftforge.client.event.GuiOpenEvent;
import net.minecraftforge.client.event.GuiScreenEvent.ActionPerformedEvent;
import net.minecraftforge.client.event.GuiScreenEvent.InitGuiEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import eu.crushedpixel.replaymod.gui.GuiCustomOptions;
import eu.crushedpixel.replaymod.ReplayMod;
import eu.crushedpixel.replaymod.authentication.AuthenticationHandler;
import eu.crushedpixel.replaymod.gui.GuiExitReplay;
import eu.crushedpixel.replaymod.gui.GuiReplayManager;
import eu.crushedpixel.replaymod.gui.GuiReplaySaving;
@@ -27,6 +28,7 @@ public class GuiEventHandler {
@SubscribeEvent
public void onGui(GuiOpenEvent event) {
if(!AuthenticationHandler.isAuthenticated()) return;
if(event.gui instanceof GuiChat || event.gui instanceof GuiInventory) {
if(ReplayHandler.replayActive()) {
event.setCanceled(true);
@@ -60,7 +62,9 @@ public class GuiEventHandler {
}
}
event.buttonList.add(new GuiButton(REPLAY_MANAGER_ID, event.gui.width / 2 - 100, i1 + 2*24, I18n.format("Replay Manager", new Object[0])));
GuiButton rm = new GuiButton(REPLAY_MANAGER_ID, event.gui.width / 2 - 100, i1 + 2*24, I18n.format("Replay Manager", new Object[0]));
rm.enabled = AuthenticationHandler.isAuthenticated();
event.buttonList.add(rm);
} else if(event.gui instanceof GuiOptions) {
event.buttonList.add(new GuiButton(9001, event.gui.width / 2 - 155, event.gui.height / 6 + 48 - 6 - 24, 310, 20, "Replay Mod Settings..."));
}
@@ -68,6 +72,7 @@ public class GuiEventHandler {
@SubscribeEvent
public void onButton(ActionPerformedEvent event) {
if(!AuthenticationHandler.isAuthenticated()) return;
if(event.gui instanceof GuiMainMenu && event.button.id == REPLAY_MANAGER_ID) {
if(ConnectionEventHandler.saving) {
Minecraft.getMinecraft().displayGuiScreen(new GuiReplaySaving());

View File

@@ -1,3 +1,4 @@
package eu.crushedpixel.replaymod.events;
import java.awt.Color;
@@ -25,10 +26,12 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.InputEvent.KeyInputEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import eu.crushedpixel.replaymod.ReplayMod;
import eu.crushedpixel.replaymod.entities.CameraEntity;
import eu.crushedpixel.replaymod.entities.CameraEntity.MoveDirection;
import eu.crushedpixel.replaymod.gui.GuiMouseInput;
@@ -199,6 +202,13 @@ public class GuiReplayOverlay extends Gui {
mc.displayGuiScreen((GuiScreen)null);
}
CameraEntity cam = ReplayHandler.getCameraEntity();
if(cam != null) {
ReplayHandler.setLastPosition(new Position(cam.posX, cam.posY, cam.posZ, cam.rotationPitch, cam.rotationYaw));
} else {
ReplayHandler.setLastPosition(null);
}
ReplayHandler.setReplayPos((int)time);
}
}
@@ -736,7 +746,7 @@ public class GuiReplayOverlay extends Gui {
return false;
}
}
@SubscribeEvent
public void onMouseMove(MouseEvent event) {
if(!ReplayHandler.replayActive()) return;
@@ -777,7 +787,11 @@ public class GuiReplayOverlay extends Gui {
if(FMLClientHandler.instance().isGUIOpen(GuiMouseInput.class)) {
return;
}
if(Keyboard.isKeyDown(Keyboard.KEY_V) && !Keyboard.isRepeatEvent() && Keyboard.getKeyCount() == 1) {
ReplayMod.replaySettings.setLightingEnabled(!ReplayMod.replaySettings.isLightingEnabled());
}
KeyBinding[] keyBindings = Minecraft.getMinecraft().gameSettings.keyBindings;
for(KeyBinding kb : keyBindings) {
if(!kb.isKeyDown()) {

View File

@@ -30,11 +30,4 @@ public class ReplayTickHandler {
}
}
@SubscribeEvent
public void onFovChange(FOVUpdateEvent event) {
if(ReplayHandler.replayActive()) {
event.newfov = 1f;
}
}
}

View File

@@ -9,6 +9,7 @@ import net.minecraft.client.gui.GuiIngameMenu;
import net.minecraft.client.gui.GuiMainMenu;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.resources.I18n;
import net.minecraft.client.settings.GameSettings.Options;
public class GuiExitReplay extends GuiIngameMenu {
@@ -49,6 +50,8 @@ public class GuiExitReplay extends GuiIngameMenu {
ReplayHandler.endReplay();
ReplayHandler.setSpeed(1f);
mc.gameSettings.setOptionFloatValue(Options.GAMMA, ReplayHandler.getInitialGamma());
ReplayHandler.lastExit = System.currentTimeMillis();
mc.theWorld.sendQuittingDisconnectingPacket();
}

View File

@@ -2,9 +2,11 @@ package eu.crushedpixel.replaymod.gui;
import java.awt.Color;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Map.Entry;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiOptionButton;
import net.minecraft.client.gui.GuiOptionSlider;
@@ -12,6 +14,7 @@ import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n;
import net.minecraftforge.fml.client.FMLClientHandler;
import eu.crushedpixel.replaymod.ReplayMod;
import eu.crushedpixel.replaymod.reflection.MCPNames;
import eu.crushedpixel.replaymod.settings.ReplaySettings;
public class GuiReplaySettings extends GuiScreen {
@@ -24,8 +27,9 @@ public class GuiReplaySettings extends GuiScreen {
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 GuiButton recordServerButton, recordSPButton, sendChatButton, linearButton;
private GuiButton recordServerButton, recordSPButton, sendChatButton, linearButton, lightingButton;
public GuiReplaySettings(GuiScreen parentGuiScreen)
{
@@ -62,6 +66,9 @@ public class GuiReplaySettings extends GuiScreen {
} else if(e.getKey().equals("Force Linear Movement")) {
linearButton = new GuiButton(FORCE_LINEAR, this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), 150, 20, "Camera Path: "+linearOnOff((Boolean)e.getValue()));
this.buttonList.add(linearButton);
} else if(e.getKey().equals("Enable Lighting")) {
lightingButton = new GuiButton(ENABLE_LIGHTING, this.width / 2 - 155 + i % 2 * 160, this.height / 6 + 24 * (i >> 1), 150, 20, "Enable Lighting: "+onOff((Boolean)e.getValue()));
this.buttonList.add(lightingButton);
}
++i;
@@ -88,7 +95,7 @@ public class GuiReplaySettings extends GuiScreen {
this.drawDefaultBackground();
this.drawCenteredString(this.fontRendererObj, "Replay Mod Settings", this.width / 2, 20, 16777215);
if (FMLClientHandler.instance().getClient().thePlayer != null) {
this.drawCenteredString(this.fontRendererObj, "WARNING: These settings are going to be", this.width / 2, 180, Color.RED.getRGB());
this.drawCenteredString(this.fontRendererObj, "WARNING: Recording settings are going to be", this.width / 2, 180, Color.RED.getRGB());
this.drawCenteredString(this.fontRendererObj, "applied the next time you join a world.", this.width / 2, 190, Color.RED.getRGB());
}
super.drawScreen(mouseX, mouseY, partialTicks);
@@ -127,6 +134,12 @@ public class GuiReplaySettings extends GuiScreen {
linearButton.displayString = "Camera Path: "+linearOnOff(enabled);
ReplayMod.replaySettings.setLinearMovement(enabled);
break;
case ENABLE_LIGHTING:
enabled = ReplayMod.replaySettings.isLightingEnabled();
enabled = !enabled;
lightingButton.displayString = "Enable Lighting: "+onOff(enabled);
ReplayMod.replaySettings.setLightingEnabled(enabled);
break;
}
}
}

View File

@@ -1,6 +1,5 @@
package eu.crushedpixel.replaymod.recording;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
@@ -12,19 +11,18 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiMainMenu;
import net.minecraft.network.Packet;
import com.google.gson.Gson;
import eu.crushedpixel.replaymod.chat.ChatMessageRequests;
import eu.crushedpixel.replaymod.chat.ChatMessageRequests.ChatMessageType;
import eu.crushedpixel.replaymod.holders.PacketData;
public abstract class DataListener extends ChannelInboundHandlerAdapter {
@@ -45,6 +43,8 @@ public abstract class DataListener extends ChannelInboundHandlerAdapter {
protected DataWriter dataWriter;
private Gson gson = new Gson();
protected Set<String> players = new HashSet<String>();
public void setWorldName(String worldName) {
this.worldName = worldName;
@@ -69,7 +69,7 @@ public abstract class DataListener extends ChannelInboundHandlerAdapter {
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
dataWriter.requestFinish();
dataWriter.requestFinish(players);
}
public class DataWriter {
@@ -139,14 +139,17 @@ public abstract class DataListener extends ChannelInboundHandlerAdapter {
outputThread.start();
}
public void requestFinish() {
public void requestFinish(Set<String> players) {
active = false;
byte[] buffer = new byte[1024];
try {
ConnectionEventHandler.saving = true;
ReplayMetaData metaData = new ReplayMetaData(singleplayer, worldName, (int) lastSentPacket, startTime);
String mcversion = Minecraft.getMinecraft().getVersion();
String[] pl = players.toArray(new String[players.size()]);
ReplayMetaData metaData = new ReplayMetaData(singleplayer, worldName, (int) lastSentPacket, startTime, pl, mcversion);
String json = gson.toJson(metaData);
File folder = new File("./replay_recordings/");

View File

@@ -8,6 +8,7 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.UUID;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.DataWatcher;
@@ -35,9 +36,13 @@ public class PacketListener extends DataListener {
public void saveOnly(Packet packet) {
try {
if(packet instanceof S0CPacketSpawnPlayer) {
UUID uuid = ((S0CPacketSpawnPlayer)packet).func_179819_c();
players.add(uuid.toString());
}
PacketData pd = getPacketData(context, packet);
dataWriter.writeData(pd);
lastSentPacket = pd.getTimestamp();
writeData(pd);
} catch(Exception e) {
e.printStackTrace();
}
@@ -69,10 +74,14 @@ public class PacketListener extends DataListener {
return;
}
}
if(packet instanceof S0CPacketSpawnPlayer) {
UUID uuid = ((S0CPacketSpawnPlayer)packet).func_179819_c();
players.add(uuid.toString());
}
PacketData pd = getPacketData(ctx, packet);
dataWriter.writeData(pd);
lastSentPacket = pd.getTimestamp();
writeData(pd);
} catch(Exception e) {
e.printStackTrace();
}
@@ -82,6 +91,12 @@ public class PacketListener extends DataListener {
super.channelRead(ctx, msg);
}
private void writeData(PacketData pd) {
dataWriter.writeData(pd);
lastSentPacket = pd.getTimestamp();
}
private PacketData getPacketData(ChannelHandlerContext ctx, Packet packet) throws IOException, IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
if(startTime == null) startTime = System.currentTimeMillis();

View File

@@ -9,37 +9,34 @@ public class ReplayMetaData {
private String serverName;
private int duration;
private long date;
private String[] players;
private String mcversion;
public ReplayMetaData(boolean singleplayer, String serverName,
int duration, long date) {
int duration, long date, String[] players, String mcversion) {
this.singleplayer = singleplayer;
this.serverName = serverName;
this.duration = duration;
this.date = date;
this.players = players;
this.mcversion = mcversion;
}
public boolean isSingleplayer() {
return singleplayer;
}
public void setSingleplayer(boolean singleplayer) {
this.singleplayer = singleplayer;
}
public String getServerName() {
return serverName;
}
public void setServer_name(String serverName) {
this.serverName = serverName;
}
public int getDuration() {
return duration;
}
public void setDuration(int duration) {
this.duration = duration;
}
public long getDate() {
return date;
}
public void setDate(long date) {
this.date = date;
public String[] getPlayers() {
return players;
}
public String getMCVersion() {
return mcversion;
}
}

View File

@@ -32,7 +32,7 @@ public final class MCPNames {
private static final Map<String, String> fields;
private static final Map<String, String> methods;
private static final MCPEnvironment env = new MCPEnvironment();
public static final MCPEnvironment env = new MCPEnvironment();
static {
if (use()) {

View File

@@ -26,22 +26,22 @@ public class LesserDataWatcher extends DataWatcher {
@Override
public byte getWatchableObjectByte(int id) {
return 0;
return 10;
}
@Override
public short getWatchableObjectShort(int id) {
return 0;
return 10;
}
@Override
public int getWatchableObjectInt(int id) {
return 0;
return 10;
}
@Override
public float getWatchableObjectFloat(int id) {
return 0;
return 10f;
}
@Override

View File

@@ -23,6 +23,7 @@ import eu.crushedpixel.replaymod.chat.ChatMessageRequests;
import eu.crushedpixel.replaymod.entities.CameraEntity;
import eu.crushedpixel.replaymod.holders.Keyframe;
import eu.crushedpixel.replaymod.holders.KeyframeComparator;
import eu.crushedpixel.replaymod.holders.Position;
import eu.crushedpixel.replaymod.holders.PositionKeyframe;
import eu.crushedpixel.replaymod.holders.TimeKeyframe;
@@ -47,6 +48,16 @@ public class ReplayHandler {
public static long lastExit = 0;
private static float gamma = 0f;
public static void setInitialGamma(float initial) {
gamma = initial;
}
public static float getInitialGamma() {
return gamma;
}
public static void setReplaying(boolean replaying) {
isReplaying = replaying;
}
@@ -369,4 +380,13 @@ public class ReplayHandler {
public static void setRealTimelineCursor(int pos) {
realTimelinePosition = pos;
}
private static Position lastPosition = null;
public static void setLastPosition(Position position) {
lastPosition = position;
}
public static Position getLastPosition() {
return lastPosition;
}
}

View File

@@ -31,20 +31,24 @@ public class ReplayProcess {
private static LinearTimestamp timeLinear = null;
private static double previousReplaySpeed = 0;
private static boolean calculated = false;
public static void startReplayProcess() {
lastPosition = null;
motionSpline = null;
timeLinear = null;
calculated = false;
ChatMessageRequests.initialize();
if(ReplayHandler.getKeyframes().isEmpty()) {
ChatMessageRequests.addChatMessage("No keyframes set!", ChatMessageType.WARNING);
if(ReplayHandler.getPosKeyframeCount() < 2) {
ChatMessageRequests.addChatMessage("At least 2 position keyframes required!", ChatMessageType.WARNING);
return;
}
startRealTime = System.currentTimeMillis();
lastRealTime = startRealTime;
lastRealReplayTime = 0;
lastTimestamp = -1;
lastPosition = null;
motionSpline = null;
timeLinear = null;
linear = ReplayMod.replaySettings.isLinearMovement();
ReplayHandler.sortKeyframes();
ReplayHandler.setReplaying(true);
@@ -86,10 +90,8 @@ public class ReplayProcess {
motionSpline.addPoint(pos);
}
}
if(motionSpline.getPoints().size() < 3) linear = true;
else motionSpline.calcSpline();
}
if(linear && motionLinear == null) {
//set up linear path
motionLinear = new LinearPoint();
@@ -109,16 +111,13 @@ public class ReplayProcess {
}
}
/*
for(float x = 0; x <= 1f; x+=0.1) {
//timeLinear.getPoint(x);
System.out.println(x+" | "+timeLinear.getPoint(x));
}
*/
//System.out.println(timeLinear.getPoint(0));
}
if(!calculated) {
calculated = true;
motionSpline.calcSpline();
}
long curTime = System.currentTimeMillis();
long timeStep = curTime - lastRealTime;
@@ -170,6 +169,10 @@ 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;

View File

@@ -14,13 +14,11 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiDownloadTerrain;
import net.minecraft.client.particle.EffectRenderer;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.EnumConnectionState;
import net.minecraft.network.EnumPacketDirection;
import net.minecraft.network.NetworkManager;
@@ -32,7 +30,6 @@ 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.S18PacketEntityTeleport;
import net.minecraft.network.play.server.S1CPacketEntityMetadata;
import net.minecraft.network.play.server.S1DPacketEntityEffect;
import net.minecraft.network.play.server.S1FPacketSetExperience;
@@ -61,8 +58,10 @@ import org.apache.commons.io.FilenameUtils;
import com.google.gson.Gson;
import eu.crushedpixel.replaymod.ReplayMod;
import eu.crushedpixel.replaymod.entities.CameraEntity;
import eu.crushedpixel.replaymod.events.RecordingHandler;
import eu.crushedpixel.replaymod.holders.Position;
import eu.crushedpixel.replaymod.recording.ConnectionEventHandler;
import eu.crushedpixel.replaymod.recording.ReplayMetaData;
import eu.crushedpixel.replaymod.reflection.MCPNames;
@@ -112,7 +111,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
private int replayLength = 0;
private int actualID = -1;
private EffectRenderer old = mc.effectRenderer;
private ZipArchiveEntry replayEntry;
@@ -209,6 +208,8 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
} catch (Exception e) {
e.printStackTrace();
}
ReplayHandler.setInitialGamma(mc.gameSettings.gammaSetting);
this.replayFile = replayFile;
this.networkManager = nm;
@@ -312,6 +313,18 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
((Timer)mcTimer.get(mc)).elapsedTicks += 5;
((Timer)mcTimer.get(mc)).renderPartialTicks += 5;
}
if(!ReplayHandler.isReplaying()) {
Position pos = ReplayHandler.getLastPosition();
CameraEntity cam = ReplayHandler.getCameraEntity();
if(cam != null) {
if(Math.abs(pos.getX() - cam.posX) < ReplayMod.TP_DISTANCE_LIMIT && Math.abs(pos.getZ() - cam.posZ) < ReplayMod.TP_DISTANCE_LIMIT)
if(pos != null) {
cam.moveAbsolute(pos.getX(), pos.getY(), pos.getZ());
cam.rotationPitch = pos.getPitch();
cam.rotationYaw = pos.getYaw();
}
}
}
if(!ReplayHandler.isReplaying()) {
setReplaySpeed(0);
}
@@ -348,7 +361,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
};
private boolean allowMovement = false;
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
@@ -422,26 +435,27 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
p = new S01PacketJoinGame(entId, GameType.SPECTATOR, false, dimension,
difficulty, maxPlayers, worldType, false);
}
if(p instanceof S07PacketRespawn) {
allowMovement = true;
}
if(p instanceof S08PacketPlayerPosLook) {
final S08PacketPlayerPosLook ppl = (S08PacketPlayerPosLook)p;
if(ReplayHandler.isReplaying() && !hurryToTimestamp) return;
CameraEntity cent = ReplayHandler.getCameraEntity();
if(!allowMovement && !((Math.abs(cent.posX - ppl.func_148932_c()) > 100) || (Math.abs(cent.posZ - ppl.func_148933_e()) > 100))) {
if(!allowMovement && !((Math.abs(cent.posX - ppl.func_148932_c()) > ReplayMod.TP_DISTANCE_LIMIT) ||
(Math.abs(cent.posZ - ppl.func_148933_e()) > ReplayMod.TP_DISTANCE_LIMIT))) {
return;
} else {
allowMovement = false;
}
Thread t = new Thread(new Runnable() {
@Override

View File

@@ -1,28 +1,48 @@
package eu.crushedpixel.replaymod.settings;
import java.lang.reflect.Field;
import java.util.LinkedHashMap;
import java.util.Map;
import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.GameSettings.Options;
import net.minecraft.util.Timer;
import net.minecraftforge.common.config.Property;
import eu.crushedpixel.replaymod.ReplayMod;
import eu.crushedpixel.replaymod.reflection.MCPNames;
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 static Field mcTimer;
static {
try {
mcTimer = Minecraft.class.getDeclaredField(MCPNames.field("field_71428_T"));
mcTimer.setAccessible(true);
} catch(Exception e) {
mcTimer = null;
e.printStackTrace();
}
}
public ReplaySettings(int maximumFileSize, boolean enableRecordingServer,
boolean enableRecordingSingleplayer, boolean showNotifications, boolean forceLinearPath) {
boolean enableRecordingSingleplayer, boolean showNotifications, boolean forceLinearPath, boolean lightingEnabled) {
this.maximumFileSize = maximumFileSize;
this.enableRecordingServer = enableRecordingServer;
this.enableRecordingSingleplayer = enableRecordingSingleplayer;
this.showNotifications = showNotifications;
this.forceLinearPath = forceLinearPath;
this.lightingEnabled = lightingEnabled;
}
public int getMaximumFileSize() {
return maximumFileSize;
}
@@ -58,44 +78,68 @@ public class ReplaySettings {
this.forceLinearPath = linear;
rewriteSettings();
}
public boolean isLightingEnabled() {
return lightingEnabled;
}
public void setLightingEnabled(boolean enabled) {
this.lightingEnabled = enabled;
if(enabled) {
Minecraft.getMinecraft().gameSettings.setOptionFloatValue(Options.GAMMA, 1000);
} else {
Minecraft.getMinecraft().gameSettings.setOptionFloatValue(Options.GAMMA, ReplayHandler.getInitialGamma());
}
try {
Timer timer = (Timer)mcTimer.get(Minecraft.getMinecraft());
timer.elapsedPartialTicks++;
timer.renderPartialTicks++;
} catch (Exception e) {
e.printStackTrace();
}
rewriteSettings();
}
public Map<String, Object> getOptions() {
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("Force Linear Movement", forceLinearPath);
map.put("Enable Lighting", lightingEnabled);
return map;
}
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");
rewriteSettings();
} catch(Exception e) {
e.printStackTrace();
}
}
public void rewriteSettings() {
ReplayMod.instance.config.load();
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.");
ReplayMod.instance.config.save();
}
}