Compare commits

..

2 Commits

Author SHA1 Message Date
johni0702
d1ed67f1a0 One EventBus to rule them all 2016-09-17 22:01:10 +02:00
johni0702
a80a20c37a Update to Minecraft 1.9.4 2016-09-17 22:00:04 +02:00
92 changed files with 813 additions and 1758 deletions

View File

@@ -1,5 +1,3 @@
import groovy.json.JsonOutput
import java.util.zip.ZipInputStream
buildscript {
@@ -19,8 +17,8 @@ buildscript {
}
}
dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:2.0-SNAPSHOT'
classpath 'org.spongepowered:mixingradle:0.3-SNAPSHOT'
classpath 'net.minecraftforge.gradle:ForgeGradle:2.2-SNAPSHOT'
classpath 'org.spongepowered:mixingradle:0.4-SNAPSHOT'
}
}
@@ -36,9 +34,9 @@ archivesBaseName = "replaymod"
minecraft {
coreMod = 'com.replaymod.core.LoadingPlugin'
version = '1.8-11.14.4.1563'
version = '1.9.4-12.17.0.1976'
runDir = "eclipse"
mappings = "snapshot_nodoc_20141130"
mappings = "snapshot_20160518"
}
repositories {
@@ -59,7 +57,7 @@ configurations {
dependencies {
compile 'org.projectlombok:lombok:1.16.4'
compile 'org.spongepowered:mixin:0.4.3'
compile 'org.spongepowered:mixin:0.5.9-SNAPSHOT'
shade 'com.googlecode.mp4parser:isoparser:1.1.7'
shade 'org.apache.commons:commons-exec:1.3'
shade 'com.google.apis:google-api-services-youtube:v3-rev178-1.22.0'
@@ -136,6 +134,7 @@ jar {
manifest {
attributes 'TweakClass': 'org.spongepowered.asm.launch.MixinTweaker',
'TweakOrder': '0',
'FMLCorePluginContainsFMLMod': 'true',
'FMLAT': 'replaymod_at.cfg'
}
}
@@ -197,85 +196,4 @@ setupDecompWorkspace.dependsOn copySrg
setupDevWorkspace.dependsOn copySrg
project.tasks.idea.dependsOn copySrg
def generateVersionsJson() {
// List all tags
def stdout = new ByteArrayOutputStream()
project.exec {
commandLine 'git', 'for-each-ref', '--sort=taggerdate', '--format=%(refname:short)', 'refs/tags'
standardOutput = stdout
}
def versions = stdout.toString().tokenize('\n').reverse()
def mcVersions = versions.collect {it.substring(0, it.indexOf('-'))}.unique().reverse()
def root = [
homepage: 'https://www.replaymod.com/download/',
promos: [:]
]
mcVersions.forEach { mcVersion ->
def mcVersionRoot = [:]
def latest
def recommended
versions.forEach {
def (thisMcVersion, modVersion, preVersion) = it.tokenize('-')
if (thisMcVersion == mcVersion) {
mcVersionRoot[it] = "See https://github.com/ReplayMod/ReplayMod/releases/$it"
if (latest == null) latest = it
if (preVersion == null) {
if (recommended == null) recommended = it
}
}
}
root[mcVersion] = mcVersionRoot
root.promos[mcVersion + '-latest'] = latest
if (recommended != null) {
root.promos[mcVersion + '-recommended'] = recommended
}
}
root
}
task doRelease() {
doLast {
// Parse version
def version = project.releaseVersion as String
if (project.version.endsWith('*')) {
throw new InvalidUserDataException('Git working tree is dirty. Make sure to commit all changes.')
}
def (mcVersion, modVersion, preVersion) = version.tokenize('-')
preVersion = preVersion != null && preVersion.startsWith('b') ? preVersion.substring(1) : null
// Create new tag
if (preVersion != null) {
project.exec {
commandLine 'git', 'tag',
'-m', "Pre-release $preVersion of $modVersion for Minecraft $mcVersion",
"$mcVersion-$modVersion-b$preVersion"
}
} else {
project.exec {
commandLine 'git', 'tag',
'-m', "Release $modVersion for Minecraft $mcVersion",
"$mcVersion-$modVersion"
}
}
// Switch to master branch to update versions.json
project.exec { commandLine 'git', 'checkout', 'master' }
// Generate versions.json content
def versionsRoot = generateVersionsJson()
def versionsJson = JsonOutput.prettyPrint(JsonOutput.toJson(versionsRoot))
// Write versions.json
new File('versions.json').write(versionsJson)
// Commit changes
project.exec { commandLine 'git', 'add', 'versions.json' }
project.exec { commandLine 'git', 'commit', '-m', "Update versions.json for $version" }
// Return to previous branch
project.exec { commandLine 'git', 'checkout', '-' }
}
}
defaultTasks 'build'

2
jGui

Submodule jGui updated: 163cfe2f8a...f7270bb5f9

View File

@@ -1,23 +0,0 @@
package com.replaymod.compat;
import com.replaymod.compat.shaders.ShaderBeginRender;
import com.replaymod.core.ReplayMod;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.EventBus;
@Mod(modid = ReplayModCompat.MOD_ID, useMetadata = true)
public class ReplayModCompat {
public static final String MOD_ID = "replaymod-compat";
@Mod.Instance(ReplayMod.MOD_ID)
private static ReplayMod core;
@Mod.EventHandler
public void init(FMLInitializationEvent event) {
EventBus bus = FMLCommonHandler.instance().bus();
bus.register(new ShaderBeginRender());
}
}

View File

@@ -1,39 +0,0 @@
package com.replaymod.compat.shaders;
import com.replaymod.render.hooks.EntityRendererHandler;
import net.minecraft.client.Minecraft;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import java.lang.reflect.InvocationTargetException;
public class ShaderBeginRender {
private final Minecraft mc = Minecraft.getMinecraft();
/**
* Invokes Shaders#beginRender when rendering a video,
* as this would usually get called by EntityRenderer#renderWorld,
* which we're not calling during rendering.
*/
@SubscribeEvent
public void onRenderTickStart(TickEvent.RenderTickEvent event) {
if (event.phase != TickEvent.Phase.START) return;
if (ShaderReflection.shaders_beginRender == null) return;
if (ShaderReflection.config_isShaders == null) return;
try {
// check if video is being rendered
if (((EntityRendererHandler.IEntityRenderer) mc.entityRenderer).replayModRender_getHandler() == null)
return;
// check if Shaders are enabled
if (!(boolean) (ShaderReflection.config_isShaders.invoke(null))) return;
ShaderReflection.shaders_beginRender.invoke(null, mc, mc.timer.elapsedPartialTicks, 0);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}

View File

@@ -1,53 +0,0 @@
package com.replaymod.compat.shaders;
import net.minecraft.client.Minecraft;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ShaderReflection {
// Shaders.frameTimeCounter
public static Field shaders_frameTimeCounter;
// Shaders.isShadowPass
public static Field shaders_isShadowPass;
// Shaders.beginRender()
public static Method shaders_beginRender;
// RenderGlobal.chunksToUpdateForced (Optifine only)
public static Field renderGlobal_chunksToUpdateForced;
// Config.isShaders() (Optifine only)
public static Method config_isShaders;
static {
try {
shaders_frameTimeCounter = Class.forName("shadersmod.client.Shaders")
.getDeclaredField("frameTimeCounter");
shaders_frameTimeCounter.setAccessible(true);
shaders_isShadowPass = Class.forName("shadersmod.client.Shaders")
.getDeclaredField("isShadowPass");
shaders_isShadowPass.setAccessible(true);
shaders_beginRender = Class.forName("shadersmod.client.Shaders")
.getDeclaredMethod("beginRender", Minecraft.class, float.class, long.class);
shaders_beginRender.setAccessible(true);
renderGlobal_chunksToUpdateForced = Class.forName("net.minecraft.client.renderer.RenderGlobal")
.getDeclaredField("chunksToUpdateForced");
renderGlobal_chunksToUpdateForced.setAccessible(true);
config_isShaders = Class.forName("Config")
.getDeclaredMethod("isShaders");
config_isShaders.setAccessible(true);
} catch (ClassNotFoundException ignore) {
// no shaders mod installed
} catch (NoSuchMethodException | NoSuchFieldException e) {
// the method wasn't found. Has it been renamed?
e.printStackTrace();
}
}
}

View File

@@ -1,28 +0,0 @@
package com.replaymod.compat.shaders.mixin;
import com.replaymod.compat.shaders.ShaderReflection;
import com.replaymod.replay.ReplayHandler;
import com.replaymod.replay.ReplayModReplay;
import net.minecraft.client.renderer.EntityRenderer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(EntityRenderer.class)
public abstract class MixinShaderEntityRenderer {
@Inject(method = "renderWorldPass", at = @At("HEAD"))
private void replayModCompat_updateShaderFrameTimeCounter(CallbackInfo ignore) {
if (ReplayModReplay.instance.getReplayHandler() == null) return;
if (ShaderReflection.shaders_frameTimeCounter == null) return;
ReplayHandler replayHandler = ReplayModReplay.instance.getReplayHandler();
float timestamp = replayHandler.getReplaySender().currentTimeStamp() / 1000f % 3600f;
try {
ShaderReflection.shaders_frameTimeCounter.set(null, timestamp);
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -1,28 +0,0 @@
package com.replaymod.compat.shaders.mixin;
import com.replaymod.render.hooks.EntityRendererHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.chunk.RenderChunk;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(RenderChunk.class)
public abstract class MixinShaderRenderChunk {
private final Minecraft mc = Minecraft.getMinecraft();
/**
* Changes the RenderChunk#isPlayerUpdate method that Optifine adds
* to always return true while rendering so no chunks are being added
* to a separate rendering queue
*/
@Inject(method = "isPlayerUpdate", at = @At("HEAD"), cancellable = true)
private void replayModCompat_disableIsPlayerUpdate(CallbackInfoReturnable<Boolean> ci) {
if (((EntityRendererHandler.IEntityRenderer) mc.entityRenderer).replayModRender_getHandler() == null) return;
ci.setReturnValue(true);
}
}

View File

@@ -1,40 +0,0 @@
package com.replaymod.compat.shaders.mixin;
import com.replaymod.compat.shaders.ShaderReflection;
import com.replaymod.render.hooks.EntityRendererHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.client.renderer.culling.ICamera;
import net.minecraft.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(RenderGlobal.class)
public abstract class MixinShaderRenderGlobal {
private final Minecraft mc = Minecraft.getMinecraft();
@Shadow
public boolean displayListEntitiesDirty;
@Inject(method = "setupTerrain", at = @At("HEAD"), cancellable = true)
public void replayModCompat_setupTerrain(Entity viewEntity, double partialTicks, ICamera camera,
int frameCount, boolean playerSpectator, CallbackInfo ci) {
if (((EntityRendererHandler.IEntityRenderer) mc.entityRenderer).replayModRender_getHandler() == null) return;
if (ShaderReflection.shaders_isShadowPass == null) return;
// when called by the shadow pass, displayListEntitiesDirty can't be set to false, as no chunk updates
// are being processed. As it's being set to true by ChunkLoadingRenderGlobal#updateChunks, we have to
// set it to false manually to exit the loop imposed by MixinRenderGlobal#replayModRender_setupTerrain.
try {
if ((boolean) ShaderReflection.shaders_isShadowPass.get(null) == true) {
displayListEntitiesDirty = false;
}
} catch (IllegalAccessException ignore) {}
}
}

View File

@@ -15,7 +15,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
public class KeyBindingRegistry {
private Map<String, KeyBinding> keyBindings = new HashMap<String, KeyBinding>();
@@ -56,12 +55,7 @@ public class KeyBindingRegistry {
CrashReport crashReport = CrashReport.makeCrashReport(cause, "Handling Key Binding");
CrashReportCategory category = crashReport.makeCategory("Key Binding");
category.addCrashSection("Key Binding", entry.getKey());
category.addCrashSectionCallable("Handler", new Callable() {
@Override
public Object call() throws Exception {
return runnable;
}
});
category.setDetail("Handler", runnable::toString);
throw new ReportedException(crashReport);
}
}
@@ -78,12 +72,7 @@ public class KeyBindingRegistry {
CrashReport crashReport = CrashReport.makeCrashReport(cause, "Handling Raw Key Binding");
CrashReportCategory category = crashReport.makeCategory("Key Binding");
category.addCrashSection("Key Code", keyCode);
category.addCrashSectionCallable("Handler", new Callable() {
@Override
public Object call() throws Exception {
return runnable;
}
});
category.setDetail("Handler", runnable::toString);
throw new ReportedException(crashReport);
}
}

View File

@@ -4,7 +4,7 @@ import net.minecraftforge.fml.relauncher.CoreModManager;
import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin;
import org.apache.logging.log4j.LogManager;
import org.spongepowered.asm.launch.MixinBootstrap;
import org.spongepowered.asm.mixin.MixinEnvironment;
import org.spongepowered.asm.mixin.Mixins;
import java.io.File;
import java.net.URISyntaxException;
@@ -16,10 +16,9 @@ public class LoadingPlugin implements IFMLLoadingPlugin {
public LoadingPlugin() {
MixinBootstrap.init();
MixinEnvironment.getDefaultEnvironment().addConfiguration("mixins.recording.replaymod.json");
MixinEnvironment.getDefaultEnvironment().addConfiguration("mixins.render.replaymod.json");
MixinEnvironment.getDefaultEnvironment().addConfiguration("mixins.replay.replaymod.json");
MixinEnvironment.getDefaultEnvironment().addConfiguration("mixins.compat.shaders.replaymod.json");
Mixins.addConfiguration("mixins.recording.replaymod.json");
Mixins.addConfiguration("mixins.render.replaymod.json");
Mixins.addConfiguration("mixins.replay.replaymod.json");
CodeSource codeSource = getClass().getProtectionDomain().getCodeSource();
if (codeSource != null) {
@@ -29,7 +28,7 @@ public class LoadingPlugin implements IFMLLoadingPlugin {
if (file.isFile()) {
// This forces forge to reexamine the jar file for FML mods
// Should eventually be handled by Mixin itself, maybe?
CoreModManager.getLoadedCoremods().remove(file.getName());
CoreModManager.getIgnoredMods().remove(file.getName());
}
} catch (URISyntaxException e) {
e.printStackTrace();

View File

@@ -6,7 +6,6 @@ import com.replaymod.core.gui.GuiReplaySettings;
import com.replaymod.core.gui.RestoreReplayGui;
import com.replaymod.core.handler.MainMenuHandler;
import com.replaymod.core.utils.OpenGLUtils;
import com.replaymod.render.utils.SoundHandler;
import com.replaymod.replaystudio.util.I18n;
import de.johni0702.minecraft.gui.container.GuiScreen;
import lombok.Getter;
@@ -14,10 +13,11 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory;
import net.minecraft.util.*;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.*;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
@@ -31,11 +31,9 @@ import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Queue;
@Mod(modid = ReplayMod.MOD_ID,
useMetadata = true,
updateJSON = "https://raw.githubusercontent.com/ReplayMod/ReplayMod/master/versions.json",
guiFactory = "com.replaymod.core.gui.GuiFactory")
public class ReplayMod {
@@ -66,8 +64,6 @@ public class ReplayMod {
@Deprecated
public static Configuration config;
@Deprecated
public static SoundHandler soundHandler = new SoundHandler();
private final KeyBindingRegistry keyBindingRegistry = new KeyBindingRegistry();
private final SettingsRegistry settingsRegistry = new SettingsRegistry();
@@ -109,7 +105,7 @@ public class ReplayMod {
new MainMenuHandler().register();
FMLCommonHandler.instance().bus().register(keyBindingRegistry);
MinecraftForge.EVENT_BUS.register(keyBindingRegistry);
getKeyBindingRegistry().registerKeyBinding("replaymod.input.settings", 0, () -> {
new GuiReplaySettings(null, settingsRegistry).display();
@@ -123,168 +119,9 @@ public class ReplayMod {
if(!FMLClientHandler.instance().hasOptifine())
GameSettings.Options.RENDER_DISTANCE.setValueMax(64f);
if (System.getProperty("replaymod.render.file") != null) {
final File file = new File(System.getProperty("replaymod.render.file"));
if (!file.exists()) {
throw new IOException("File \"" + file.getPath() + "\" not found.");
}
final String path = System.getProperty("replaymod.render.path");
String type = System.getProperty("replaymod.render.type");
String bitrate = System.getProperty("replaymod.render.bitrate");
String fps = System.getProperty("replaymod.render.fps");
String waitForChunks = System.getProperty("replaymod.render.waitforchunks");
String linearMovement = System.getProperty("replaymod.render.linearmovement");
String skyColor = System.getProperty("replaymod.render.skycolor");
String width = System.getProperty("replaymod.render.width");
String height = System.getProperty("replaymod.render.height");
String exportCommand = System.getProperty("replaymod.render.exportcommand");
String exportCommandArgs = System.getProperty("replaymod.render.exportcommandargs");
/*
final RenderOptions options = new RenderOptions();
if (bitrate != null) {
options.setBitrate(bitrate);
}
if (fps != null) {
options.setFps(Integer.parseInt(fps));
}
if (waitForChunks != null) {
options.setWaitForChunks(Boolean.parseBoolean(waitForChunks));
}
if (linearMovement != null) {
options.setLinearMovement(Boolean.parseBoolean(linearMovement));
}
if (skyColor != null) {
if (skyColor.startsWith("0x")) {
options.setSkyColor(Integer.parseInt(skyColor.substring(2), 16));
} else {
options.setSkyColor(Integer.parseInt(skyColor));
}
}
if (width != null) {
options.setWidth(Integer.parseInt(width));
}
if (height != null) {
options.setHeight(Integer.parseInt(height));
}
if (exportCommand != null) {
options.setExportCommand(exportCommand);
}
if (exportCommandArgs != null) {
options.setExportCommandArgs(exportCommandArgs);
} else {
options.setExportCommandArgs(EncodingPreset.MP4DEFAULT.getCommandLineArgs());
}
options.setOutputFile(new File(String.valueOf(System.currentTimeMillis())));
Pipelines.Preset pipelinePreset = Pipelines.Preset.DEFAULT;
if (type != null) {
String[] parts = type.split(":");
type = parts[0].toUpperCase();
if ("NORMAL".equals(type) || "DEFAULT".equals(type)) {
pipelinePreset = Pipelines.Preset.DEFAULT;
} else if ("STEREO".equals(type) || "STEREOSCOPIC".equals(type)) {
pipelinePreset = Pipelines.Preset.STEREOSCOPIC;
} else if ("CUBIC".equals(type)) {
if (parts.length < 2) {
throw new IllegalArgumentException("Cubic renderer requires boolean for whether it's stable.");
}
pipelinePreset = Pipelines.Preset.CUBIC;
} else if ("EQUIRECTANGULAR".equals(type)) {
if (parts.length < 2) {
throw new IllegalArgumentException("Equirectangular renderer requires boolean for whether it's stable.");
}
pipelinePreset = Pipelines.Preset.EQUIRECTANGULAR;
} else if ("ODS".equals(type)) {
if (parts.length < 2) {
throw new IllegalArgumentException("ODS renderer requires boolean for whether it's stable.");
}
pipelinePreset = Pipelines.Preset.ODS;
} else {
throw new IllegalArgumentException("Unknown type: " + parts[0]);
}
}
options.setMode(pipelinePreset);
*/
@SuppressWarnings("unchecked")
Queue<ListenableFutureTask> tasks = mc.scheduledTasks;
synchronized (mc.scheduledTasks) {
tasks.add(ListenableFutureTask.create(new Runnable() {
@Override
public void run() {
String renderDistance = System.getProperty("replaymod.render.mc.renderdistance");
String clouds = System.getProperty("replaymod.render.mc.clouds");
if (renderDistance != null) {
mc.gameSettings.renderDistanceChunks = Integer.parseInt(renderDistance);
}
if (clouds != null) {
mc.gameSettings.clouds = Boolean.parseBoolean(clouds);
}
System.out.println("Loading replay...");
// TODO
// try {
// ReplayHandler.startReplay(file, false);
// } catch (Throwable t) {
// t.printStackTrace();
// FMLCommonHandler.instance().exitJava(1, false);
// }
//
// int index = 0;
// if (path != null) {
// for (KeyframeSet set : ReplayHandler.getKeyframeRepository()) {
// if (set.getName().equals(path)) {
// break;
// }
// index++;
// }
// if (index >= ReplayHandler.getKeyframeRepository().length) {
// throw new IllegalArgumentException("No path named \"" + path + "\".");
// }
// } else if (ReplayHandler.getKeyframeRepository().length == 0) {
// throw new IllegalArgumentException("Replay file has no paths defined.");
// }
// ReplayHandler.useKeyframePresetFromRepository(index);
//
// System.out.println("Rendering started...");
// try {
// ReplayProcess.startReplayProcess(options, true);
// } catch (Throwable t) {
// t.printStackTrace();
// FMLCommonHandler.instance().exitJava(1, false);
// }
// if (mc.hasCrashed) {
// System.out.println(mc.crashReporter.getCompleteReport());
// }
// System.out.println("Rendering done. Shutting down...");
// mc.shutdown();
}
}, null));
}
testIfMoeshAndExitMinecraft();
}
testIfMoeshAndExitMinecraft();
runLater(() -> {
// Cleanup deleted corrupted replays
try {
File[] files = getReplayFolder().listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory() && file.getName().endsWith(".mcpr.del")) {
if (file.lastModified() + 2 * 24 * 60 * 60 * 1000 < System.currentTimeMillis()) {
FileUtils.deleteDirectory(file);
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
// Restore corrupted replays
try {
File[] files = getReplayFolder().listFiles();
@@ -303,10 +140,8 @@ public class ReplayMod {
}
public void runLater(Runnable runnable) {
@SuppressWarnings("unchecked")
Queue<ListenableFutureTask> tasks = mc.scheduledTasks;
synchronized (mc.scheduledTasks) {
tasks.add(ListenableFutureTask.create(runnable, null));
mc.scheduledTasks.add(ListenableFutureTask.create(runnable, null));
}
}
@@ -335,13 +170,13 @@ public class ReplayMod {
private void printToChat(boolean warning, String message, Object... args) {
if (getSettingsRegistry().get(Setting.NOTIFICATIONS)) {
// Some nostalgia: "§8[§6Replay Mod§8]§r Your message goes here"
ChatStyle coloredDarkGray = new ChatStyle().setColor(EnumChatFormatting.DARK_GRAY);
ChatStyle coloredGold = new ChatStyle().setColor(EnumChatFormatting.GOLD);
IChatComponent text = new ChatComponentText("[").setChatStyle(coloredDarkGray)
.appendSibling(new ChatComponentTranslation("replaymod.title").setChatStyle(coloredGold))
.appendSibling(new ChatComponentText("] "))
.appendSibling(new ChatComponentTranslation(message, args).setChatStyle(new ChatStyle()
.setColor(warning ? EnumChatFormatting.RED : EnumChatFormatting.DARK_GREEN)));
Style coloredDarkGray = new Style().setColor(TextFormatting.DARK_GRAY);
Style coloredGold = new Style().setColor(TextFormatting.GOLD);
ITextComponent text = new TextComponentString("[").setStyle(coloredDarkGray)
.appendSibling(new TextComponentTranslation("replaymod.title").setStyle(coloredGold))
.appendSibling(new TextComponentString("] "))
.appendSibling(new TextComponentTranslation(message, args).setStyle(new Style()
.setColor(warning ? TextFormatting.RED : TextFormatting.DARK_GREEN)));
// Send message to chat GUI
// The ingame GUI is initialized at startup, therefore this is possible before the client is connected
mc.ingameGUI.getChatGUI().printChatMessage(text);

View File

@@ -2,8 +2,8 @@ package com.replaymod.core;
import com.replaymod.core.events.SettingsChangedEvent;
import net.minecraft.client.resources.I18n;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.fml.common.FMLCommonHandler;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
@@ -83,7 +83,7 @@ public class SettingsRegistry {
throw new IllegalArgumentException("Default type " + key.getDefault().getClass() + " not supported.");
}
settings.put(key, value);
FMLCommonHandler.instance().bus().post(new SettingsChangedEvent(this, key));
MinecraftForge.EVENT_BUS.post(new SettingsChangedEvent(this, key));
}
public void save() {

View File

@@ -6,8 +6,6 @@ import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import java.util.List;
/**
* Moves certain buttons on the main menu upwards so we can inject our own.
*/
@@ -18,14 +16,12 @@ public class MainMenuHandler {
@SubscribeEvent
public void onInit(GuiScreenEvent.InitGuiEvent.Post event) {
if (event.gui instanceof GuiMainMenu) {
@SuppressWarnings("unchecked")
List<GuiButton> buttonList = event.buttonList;
for (GuiButton button : buttonList) {
if (event.getGui() instanceof GuiMainMenu) {
for (GuiButton button : event.getButtonList()) {
// Buttons that aren't in a rectangle directly above our space don't need moving
if (button.xPosition + button.width < event.gui.width / 2 - 100
|| button.xPosition > event.gui.width / 2 + 100
|| button.yPosition > event.gui.height / 4 + 10 + 4 * 24) continue;
if (button.xPosition + button.width < event.getGui().width / 2 - 100
|| button.xPosition > event.getGui().width / 2 + 100
|| button.yPosition > event.getGui().height / 4 + 10 + 4 * 24) continue;
// Move button up to make space for two rows of buttons
// and then move back down by 10 to compensate for the space to the exit button that was already there
button.yPosition -= 2 * 24 - 10;

View File

@@ -2,7 +2,8 @@ package com.replaymod.core.utils;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.VertexBuffer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
@@ -34,14 +35,14 @@ public class OpenGLUtils {
float f5 = 1.0F / textureHeight;
Tessellator tessellator = Tessellator.getInstance();
WorldRenderer worldrenderer = tessellator.getWorldRenderer();
VertexBuffer vertexBuffer = tessellator.getBuffer();
GlStateManager.translate(x+(width/2), y+(width/2), 0);
GlStateManager.rotate(rotation, 0, 0, 1);
worldrenderer.startDrawingQuads();
worldrenderer.addVertexWithUV(-width / 2, height / 2, 0.0D, (double) (u * f4), (double) ((v + (float) height) * f5));
worldrenderer.addVertexWithUV(width/2, height/2, 0.0D, (double)((u + (float)width) * f4), (double)((v + (float)height) * f5));
worldrenderer.addVertexWithUV(width/2, -height/2, 0.0D, (double)((u + (float)width) * f4), (double)(v * f5));
worldrenderer.addVertexWithUV(-width/2, -height/2, 0.0D, (double)(u * f4), (double)(v * f5));
vertexBuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
vertexBuffer.pos(-width / 2, height / 2, 0.0D).tex((double) (u * f4), (double) ((v + (float) height) * f5)).endVertex();
vertexBuffer.pos(width/2, height/2, 0.0D).tex((double)((u + (float)width) * f4), (double)((v + (float)height) * f5)).endVertex();
vertexBuffer.pos(width/2, -height/2, 0.0D).tex((double)((u + (float)width) * f4), (double)(v * f5)).endVertex();
vertexBuffer.pos(-width/2, -height/2, 0.0D).tex((double)(u * f4), (double)(v * f5)).endVertex();
tessellator.draw();
GlStateManager.popMatrix();

View File

@@ -1,7 +1,7 @@
package com.replaymod.core.utils;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.play.server.S3FPacketCustomPayload;
import net.minecraft.network.play.server.SPacketCustomPayload;
/**
* Restrictions set by the server,
@@ -14,7 +14,7 @@ public class Restrictions {
private boolean onlyFirstPerson;
private boolean onlyRecordingPlayer;
public String handle(S3FPacketCustomPayload packet) {
public String handle(SPacketCustomPayload packet) {
PacketBuffer buffer = packet.getBufferData();
while (buffer.isReadable()) {
String name = buffer.readStringFromBuffer(64);

View File

@@ -63,7 +63,7 @@ public class Utils {
}
public static ResourceLocation getResourceLocationForPlayerUUID(UUID uuid) {
NetworkPlayerInfo info = Minecraft.getMinecraft().getNetHandler().getPlayerInfo(uuid);
NetworkPlayerInfo info = Minecraft.getMinecraft().getConnection().getPlayerInfo(uuid);
ResourceLocation skinLocation;
if (info != null && info.hasLocationSkin()) {
skinLocation = info.getLocationSkin();

View File

@@ -27,7 +27,7 @@ public class WrappedTimer extends Timer {
to.elapsedPartialTicks = from.elapsedPartialTicks;
to.lastSyncSysClock = from.lastSyncSysClock;
to.lastSyncHRClock = from.lastSyncHRClock;
to.field_74285_i = from.field_74285_i;
to.counter = from.counter;
to.timeSyncAdjustment = from.timeSyncAdjustment;
}
}

View File

@@ -9,7 +9,7 @@ import de.johni0702.minecraft.gui.element.GuiImage;
import de.johni0702.minecraft.gui.element.IGuiImage;
import de.johni0702.minecraft.gui.layout.HorizontalLayout;
import net.minecraft.client.settings.GameSettings;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
@@ -41,7 +41,7 @@ public class FullBrightness implements Extra {
}
});
FMLCommonHandler.instance().bus().register(this);
MinecraftForge.EVENT_BUS.register(this);
}
@SubscribeEvent

View File

@@ -17,7 +17,7 @@ import de.johni0702.minecraft.gui.layout.GridLayout;
import de.johni0702.minecraft.gui.layout.HorizontalLayout;
import de.johni0702.minecraft.gui.layout.LayoutData;
import net.minecraft.client.resources.I18n;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.lwjgl.input.Keyboard;
import org.lwjgl.util.Dimension;
@@ -35,7 +35,7 @@ public class HotkeyButtons implements Extra {
public void register(ReplayMod mod) throws Exception {
this.mod = mod;
FMLCommonHandler.instance().bus().register(this);
MinecraftForge.EVENT_BUS.register(this);
}
@SubscribeEvent

View File

@@ -10,7 +10,7 @@ import lombok.RequiredArgsConstructor;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.IResourcePack;
import net.minecraft.client.resources.data.IMetadataSection;
import net.minecraft.client.resources.data.IMetadataSerializer;
import net.minecraft.client.resources.data.MetadataSerializer;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.Mod;
import org.apache.commons.lang3.StringEscapeUtils;
@@ -95,12 +95,12 @@ public class LocalizationExtra implements Extra {
}
@Override
public Set getResourceDomains() {
public Set<String> getResourceDomains() {
return ImmutableSet.of("minecraft", "replaymod");
}
@Override
public IMetadataSection getPackMetadata(IMetadataSerializer p_135058_1_, String p_135058_2_) throws IOException {
public <T extends IMetadataSection> T getPackMetadata(MetadataSerializer metadataSerializer, String metadataSectionName) throws IOException {
return null;
}

View File

@@ -1,142 +0,0 @@
package com.replaymod.extras;
import com.replaymod.core.ReplayMod;
import com.replaymod.core.Setting;
import de.johni0702.minecraft.gui.container.AbstractGuiScreen;
import de.johni0702.minecraft.gui.container.GuiContainer;
import de.johni0702.minecraft.gui.container.GuiPanel;
import de.johni0702.minecraft.gui.container.GuiScreen;
import de.johni0702.minecraft.gui.element.GuiButton;
import de.johni0702.minecraft.gui.element.GuiLabel;
import de.johni0702.minecraft.gui.function.Tickable;
import de.johni0702.minecraft.gui.layout.CustomLayout;
import de.johni0702.minecraft.gui.layout.HorizontalLayout;
import de.johni0702.minecraft.gui.layout.VerticalLayout;
import de.johni0702.minecraft.gui.popup.AbstractGuiPopup;
import de.johni0702.minecraft.gui.utils.Colors;
import net.minecraftforge.fml.common.Loader;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
public class OpenEyeExtra implements Extra {
private static final String DOWNLOAD_URL = "http://www.replaymod.com/dl/openeye/" + Loader.MC_VERSION;
private static final Setting<Boolean> ASK_FOR_OPEN_EYE = new Setting<>("advanced", "askForOpenEye", null, true);
private ReplayMod mod;
@Override
public void register(ReplayMod mod) throws Exception {
this.mod = mod;
mod.getSettingsRegistry().register(ASK_FOR_OPEN_EYE);
if (!Loader.isModLoaded("OpenEye") && mod.getSettingsRegistry().get(ASK_FOR_OPEN_EYE)) {
mod.runLater(() -> new OfferGui(GuiScreen.wrap(mod.getMinecraft().currentScreen)).display());
}
}
private class OfferGui extends AbstractGuiScreen<OfferGui> {
public final GuiScreen parent;
public final GuiPanel textPanel = new GuiPanel().setLayout(new VerticalLayout().setSpacing(3))
.addElements(new VerticalLayout.Data(0.5),
new GuiLabel().setI18nText("replaymod.gui.offeropeneye1"),
new GuiLabel().setI18nText("replaymod.gui.offeropeneye2"),
new GuiLabel().setI18nText("replaymod.gui.offeropeneye3"),
new GuiLabel().setI18nText("replaymod.gui.offeropeneye4"),
new GuiLabel().setI18nText("replaymod.gui.offeropeneye5"),
new GuiLabel().setI18nText("replaymod.gui.offeropeneye6"),
new GuiLabel().setI18nText("replaymod.gui.offeropeneye7"),
new GuiLabel().setI18nText("replaymod.gui.offeropeneye8"));
public final GuiPanel buttonPanel = new GuiPanel()
.setLayout(new HorizontalLayout(HorizontalLayout.Alignment.CENTER).setSpacing(5));
public final GuiPanel contentPanel = new GuiPanel(this).setLayout(new VerticalLayout().setSpacing(20))
.addElements(new VerticalLayout.Data(0.5), textPanel, buttonPanel);
public final GuiButton yesButton = new GuiButton(buttonPanel).setSize(150, 20).setI18nLabel("gui.yes");
public final GuiButton noButton = new GuiButton(buttonPanel).setSize(150, 20).setI18nLabel("gui.no");
public OfferGui(GuiScreen parent) {
this.parent = parent;
yesButton.onClick(() -> {
GuiPopup popup = new GuiPopup(OfferGui.this);
new Thread(() -> {
try {
File targetFile = new File("mods/" + Loader.MC_VERSION, "OpenEye.jar");
FileUtils.forceMkdir(targetFile.getParentFile());
ReadableByteChannel in = Channels.newChannel(new URL(DOWNLOAD_URL).openStream());
FileChannel out = new FileOutputStream(targetFile).getChannel();
out.transferFrom(in, 0, Long.MAX_VALUE);
} catch (Throwable e) {
e.printStackTrace();
} finally {
mod.runLater(() -> {
popup.close();
parent.display();
});
}
}).start();
});
noButton.onClick(() -> {
mod.getSettingsRegistry().set(ASK_FOR_OPEN_EYE, false);
mod.getSettingsRegistry().save();
parent.display();
});
setLayout(new CustomLayout<OfferGui>() {
@Override
protected void layout(OfferGui container, int width, int height) {
pos(contentPanel, width / 2 - width(contentPanel) / 2, height / 2 - height(contentPanel) / 2);
}
});
}
@Override
protected OfferGui getThis() {
return this;
}
}
private static final class GuiPopup extends AbstractGuiPopup<GuiPopup> {
GuiPopup(GuiContainer container) {
super(container);
popup.addElements(null, new GuiIndicator().setColor(Colors.BLACK));
setBackgroundColor(Colors.DARK_TRANSPARENT);
open();
}
@Override
public void close() {
super.close();
}
@Override
protected GuiPopup getThis() {
return this;
}
private static final class GuiIndicator extends GuiLabel implements Tickable {
private int tick;
@Override
public void tick() {
tick++;
setText(new String[]{
"Ooooo",
"oOooo",
"ooOoo",
"oooOo",
"ooooO",
"oooOo",
"ooOoo",
"oOooo",
}[tick / 5 % 8]);
}
}
}
}

View File

@@ -29,7 +29,7 @@ public class ReplayModExtras {
FullBrightness.class,
HotkeyButtons.class,
LocalizationExtra.class,
OpenEyeExtra.class
VersionChecker.class
);
private Logger logger;

View File

@@ -0,0 +1,66 @@
package com.replaymod.extras;
import com.replaymod.core.ReplayMod;
import com.replaymod.online.ReplayModOnline;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.GuiMainMenu;
import net.minecraft.client.resources.I18n;
import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import java.awt.*;
import java.util.List;
public class VersionChecker implements Extra {
@Mod.Instance(ReplayModOnline.MOD_ID)
private static ReplayModOnline module;
@Override
public void register(ReplayMod mod) throws Exception {
final String currentVersion = mod.getVersion();
new Thread(new Runnable() {
@Override
public void run() {
try {
boolean upToDate = module.getApiClient().isVersionUpToDate(currentVersion);
if (!upToDate) {
MinecraftForge.EVENT_BUS.register(VersionChecker.this);
}
} catch(Exception e) {
e.printStackTrace();
}
}
}, "ReplayMod-VersionChecker").start();
}
@SubscribeEvent
public void onDrawScreen(GuiScreenEvent.DrawScreenEvent.Post event) {
if (!(event.getGui() instanceof GuiMainMenu)) {
return;
}
int width = Math.max(100, event.getGui().width / 2 - 100 - 10);
@SuppressWarnings("unchecked") List<String> lines =
event.getGui().mc.fontRendererObj.listFormattedStringToWidth(I18n.format("replaymod.gui.outdated"), width);
int maxLineWidth = 0;
for(String line : lines) {
int lineWidth = event.getGui().mc.fontRendererObj.getStringWidth(line);
if(lineWidth > maxLineWidth) {
maxLineWidth = lineWidth;
}
}
Gui.drawRect(2, 77, 5 + maxLineWidth + 3, 80 + (lines.size() * 10), 0x80FF0000);
int i = 0;
for(String line : lines) {
event.getGui().mc.fontRendererObj.drawStringWithShadow(line, 5, 80 + (i * 10), Color.WHITE.getRGB());
i++;
}
}
}

View File

@@ -11,7 +11,7 @@ import com.replaymod.replay.events.ReplayOpenEvent;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.entity.RenderPlayer;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.lwjgl.input.Keyboard;
@@ -44,7 +44,7 @@ public class PlayerOverview implements Extra {
}
});
FMLCommonHandler.instance().bus().register(this);
MinecraftForge.EVENT_BUS.register(this);
RenderManager renderManager = mod.getMinecraft().getRenderManager();
@SuppressWarnings("unchecked")

View File

@@ -16,7 +16,8 @@ import de.johni0702.minecraft.gui.utils.Colors;
import net.minecraft.client.audio.PositionedSoundRecord;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EnumPlayerModelParts;
import net.minecraft.potion.Potion;
import net.minecraft.init.MobEffects;
import net.minecraft.init.SoundEvents;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.util.Dimension;
import org.lwjgl.util.ReadableDimension;
@@ -40,14 +41,14 @@ public class PlayerOverviewGui extends GuiScreen implements Closeable {
public final GuiCheckbox checkAll = new GuiCheckbox(contentPanel){
@Override
public void onClick() {
getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(BUTTON_SOUND, 1.0F));
getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1.0F));
playersScrollable.forEach(IGuiCheckbox.class).setChecked(true);
}
}.setLabel("").setChecked(true);
public final GuiCheckbox uncheckAll = new GuiCheckbox(contentPanel){
@Override
public void onClick() {
getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(BUTTON_SOUND, 1.0F));
getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1.0F));
playersScrollable.forEach(IGuiCheckbox.class).setChecked(false);
}
}.setLabel("").setChecked(false);
@@ -90,7 +91,7 @@ public class PlayerOverviewGui extends GuiScreen implements Closeable {
public void draw(GuiRenderer renderer, ReadableDimension size, RenderInfo renderInfo) {
renderer.bindTexture(texture);
renderer.drawTexturedRect(0, 0, 8, 8, 16, 16, 8, 8, 64, 64);
if (p.func_175148_a(EnumPlayerModelParts.HAT)) {
if (p.isWearing(EnumPlayerModelParts.HAT)) {
renderer.drawTexturedRect(0, 0, 40, 8, size.getWidth(), size.getHeight(), 8, 8, 64, 64);
}
}
@@ -139,7 +140,7 @@ public class PlayerOverviewGui extends GuiScreen implements Closeable {
}
private static boolean isSpectator(EntityPlayer e) {
return e.isInvisible() && e.getActivePotionEffect(Potion.invisibility) == null;
return e.isInvisible() && e.getActivePotionEffect(MobEffects.INVISIBILITY) == null;
}
private static final class PlayerComparator implements Comparator<EntityPlayer> {

View File

@@ -1,9 +1,9 @@
package com.replaymod.extras.playeroverview;
import net.minecraft.client.entity.AbstractClientPlayer;
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 PlayerRenderHook extends RenderPlayer {
private final PlayerOverview extra;
@@ -14,7 +14,7 @@ public class PlayerRenderHook extends RenderPlayer {
}
@Override
public boolean shouldRender(Entity entity, ICamera camera, double camX, double camY, double camZ) {
public boolean shouldRender(AbstractClientPlayer entity, ICamera camera, double camX, double camY, double camZ) {
return !extra.isHidden(entity.getUniqueID()) && super.shouldRender(entity, camera, camX, camY, camZ);
}
}

View File

@@ -17,8 +17,8 @@ public class YoutubeUpload implements Extra {
@SubscribeEvent
public void onGuiOpen(GuiScreenEvent.InitGuiEvent.Post event) {
if (GuiScreen.from(event.gui) instanceof GuiRenderingDone) {
GuiRenderingDone gui = (GuiRenderingDone) GuiScreen.from(event.gui);
if (GuiScreen.from(event.getGui()) instanceof GuiRenderingDone) {
GuiRenderingDone gui = (GuiRenderingDone) GuiScreen.from(event.getGui());
// Check if there already is a youtube button
if (gui.actionsPanel.getChildren().stream().anyMatch(it -> it instanceof YoutubeButton)) {
return; // Button already added

View File

@@ -8,12 +8,12 @@ import com.replaymod.online.gui.GuiSaveModifiedReplay;
import com.replaymod.online.handler.GuiHandler;
import com.replaymod.replay.ReplayModReplay;
import com.replaymod.replay.events.ReplayCloseEvent;
import de.johni0702.minecraft.gui.container.GuiScreen;
import com.replaymod.replaystudio.replay.ReplayFile;
import com.replaymod.replaystudio.replay.ZipReplayFile;
import com.replaymod.replaystudio.studio.ReplayStudio;
import de.johni0702.minecraft.gui.container.GuiScreen;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
@@ -67,7 +67,7 @@ public class ReplayModOnline {
}
new GuiHandler(this).register();
FMLCommonHandler.instance().bus().register(this);
MinecraftForge.EVENT_BUS.register(this);
}
@Mod.EventHandler

View File

@@ -2,7 +2,8 @@ package com.replaymod.online.api.replay.holders;
public enum MinecraftVersion {
MC_1_8("Minecraft 1.8", "1.8");
MC_1_8("Minecraft 1.8", "1.8"),
MC_1_9_4("Minecraft 1.9.4", "1.9.4");
private String niceName, apiName;

View File

@@ -11,18 +11,15 @@ import de.johni0702.minecraft.gui.element.GuiLabel;
import de.johni0702.minecraft.gui.element.GuiTextField;
import de.johni0702.minecraft.gui.element.GuiToggleButton;
import de.johni0702.minecraft.gui.element.advanced.GuiDropdownMenu;
import de.johni0702.minecraft.gui.function.Typeable;
import de.johni0702.minecraft.gui.layout.GridLayout;
import de.johni0702.minecraft.gui.popup.AbstractGuiPopup;
import de.johni0702.minecraft.gui.utils.Colors;
import net.minecraft.client.resources.I18n;
import org.lwjgl.input.Keyboard;
import org.lwjgl.util.ReadablePoint;
import java.util.ArrayList;
import java.util.List;
public class GuiReplayCenterSearch extends AbstractGuiPopup<GuiReplayCenterSearch> implements Typeable {
public class GuiReplayCenterSearch extends AbstractGuiPopup<GuiReplayCenterSearch> {
private final GuiReplayCenter replayCenter;
private final ApiClient apiClient;
public final GuiLabel title = new GuiLabel().setI18nText("replaymod.gui.center.search.filters").setColor(Colors.BLACK);
@@ -103,13 +100,4 @@ public class GuiReplayCenterSearch extends AbstractGuiPopup<GuiReplayCenterSearc
protected GuiReplayCenterSearch getThis() {
return this;
}
@Override
public boolean typeKey(ReadablePoint mousePosition, int keyCode, char keyChar, boolean ctrlDown, boolean shiftDown) {
if (keyCode == Keyboard.KEY_ESCAPE) {
cancelButton.onClick();
return true;
}
return false;
}
}

View File

@@ -14,11 +14,9 @@ import net.minecraft.client.gui.GuiMainMenu;
import net.minecraft.client.resources.I18n;
import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import java.io.File;
import java.util.List;
public class GuiHandler {
private static final int BUTTON_REPLAY_CENTER = 17890236;
@@ -30,26 +28,23 @@ public class GuiHandler {
}
public void register() {
FMLCommonHandler.instance().bus().register(this);
MinecraftForge.EVENT_BUS.register(this);
}
@SubscribeEvent
public void injectIntoMainMenu(GuiScreenEvent.InitGuiEvent event) {
if (!(event.gui instanceof GuiMainMenu)) {
if (!(event.getGui() instanceof GuiMainMenu)) {
return;
}
@SuppressWarnings("unchecked")
List<GuiButton> buttonList = event.buttonList;
GuiButton button = new GuiButton(BUTTON_REPLAY_CENTER, event.gui.width / 2 - 100,
event.gui.height / 4 + 10 + 4 * 24, I18n.format("replaymod.gui.replaycenter"));
buttonList.add(button);
GuiButton button = new GuiButton(BUTTON_REPLAY_CENTER, event.getGui().width / 2 - 100,
event.getGui().height / 4 + 10 + 4 * 24, I18n.format("replaymod.gui.replaycenter"));
event.getButtonList().add(button);
}
@SubscribeEvent
public void injectIntoReplayViewer(GuiScreenEvent.InitGuiEvent.Post event) {
AbstractGuiScreen guiScreen = GuiScreen.from(event.gui);
AbstractGuiScreen guiScreen = GuiScreen.from(event.getGui());
if (!(guiScreen instanceof GuiReplayViewer)) {
return;
}
@@ -75,15 +70,15 @@ public class GuiHandler {
@SubscribeEvent
public void onButton(GuiScreenEvent.ActionPerformedEvent.Pre event) {
if(!event.button.enabled) return;
if(!event.getButton().enabled) return;
if (event.gui instanceof GuiMainMenu) {
if (event.button.id == BUTTON_REPLAY_CENTER) {
if (event.getGui() instanceof GuiMainMenu) {
if (event.getButton().id == BUTTON_REPLAY_CENTER) {
GuiReplayCenter replayCenter = new GuiReplayCenter(mod);
if (mod.isLoggedIn()) {
replayCenter.display();
} else {
new GuiLoginPrompt(mod.getApiClient(), GuiScreen.wrap(event.gui), replayCenter, true).display();
new GuiLoginPrompt(mod.getApiClient(), GuiScreen.wrap(event.getGui()), replayCenter, true).display();
}
}
}

View File

@@ -11,7 +11,7 @@ import com.replaymod.replaystudio.pathing.path.Keyframe;
import com.replaymod.replaystudio.pathing.path.Path;
import com.replaymod.replaystudio.pathing.path.Timeline;
import net.minecraft.client.Minecraft;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import javax.annotation.Nullable;
@@ -24,7 +24,6 @@ public abstract class AbstractTimelinePlayer {
private final Minecraft mc = Minecraft.getMinecraft();
private final ReplayHandler replayHandler;
private Timeline timeline;
protected long startOffset;
private long lastTime;
private long lastTimestamp;
private ListenableFuture<Void> future;
@@ -34,11 +33,6 @@ public abstract class AbstractTimelinePlayer {
this.replayHandler = replayHandler;
}
public ListenableFuture<Void> start(Timeline timeline, long from) {
startOffset = from;
return start(timeline);
}
public ListenableFuture<Void> start(Timeline timeline) {
this.timeline = timeline;
@@ -65,7 +59,7 @@ public abstract class AbstractTimelinePlayer {
}
replayHandler.getReplaySender().setSyncModeAndWait();
FMLCommonHandler.instance().bus().register(this);
MinecraftForge.EVENT_BUS.register(this);
lastTime = 0;
mc.timer = new ReplayTimer(mc.timer);
mc.timer.timerSpeed = 1;
@@ -85,9 +79,8 @@ public abstract class AbstractTimelinePlayer {
public void onTick(ReplayTimer.UpdatedEvent event) {
if (future.isDone()) {
mc.timer = ((ReplayTimer) mc.timer).getWrapped();
replayHandler.getReplaySender().setReplaySpeed(0);
replayHandler.getReplaySender().setAsyncMode(true);
FMLCommonHandler.instance().bus().unregister(this);
MinecraftForge.EVENT_BUS.unregister(this);
return;
}
long time = getTimePassed();

View File

@@ -46,6 +46,6 @@ public class RealtimeTimelinePlayer extends AbstractTimelinePlayer {
@Override
public long getTimePassed() {
return startOffset + (firstFrame ? 0 : System.currentTimeMillis() - startTime);
return firstFrame ? 0 : System.currentTimeMillis() - startTime;
}
}

View File

@@ -2,7 +2,7 @@ package com.replaymod.pathing.player;
import com.replaymod.core.utils.WrappedTimer;
import net.minecraft.util.Timer;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.Event;
/**
@@ -20,7 +20,7 @@ public class ReplayTimer extends WrappedTimer {
copy(this, state); // Save our current state
super.updateTimer(); // Update current state
copy(state, this); // Restore our old state
FMLCommonHandler.instance().bus().post(new UpdatedEvent());
MinecraftForge.EVENT_BUS.post(new UpdatedEvent());
}
public Timer getWrapped() {

View File

@@ -1,15 +1,13 @@
package com.replaymod.recording;
import com.replaymod.core.ReplayMod;
import com.replaymod.core.utils.Restrictions;
import com.replaymod.recording.handler.ConnectionEventHandler;
import com.replaymod.recording.packet.PacketListener;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.EventBus;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import org.apache.logging.log4j.Logger;
import org.lwjgl.input.Keyboard;
@@ -44,9 +42,7 @@ public class ReplayModRecording {
@Mod.EventHandler
public void init(FMLInitializationEvent event) {
EventBus bus = FMLCommonHandler.instance().bus();
EventBus bus = MinecraftForge.EVENT_BUS;
bus.register(connectionEventHandler = new ConnectionEventHandler(logger, core));
NetworkRegistry.INSTANCE.newSimpleChannel(Restrictions.PLUGIN_CHANNEL);
}
}

View File

@@ -40,7 +40,7 @@ public class GuiRecordingOverlay {
*/
@SubscribeEvent
public void renderRecordingIndicator(RenderGameOverlayEvent.Post event) {
if (event.type != RenderGameOverlayEvent.ElementType.ALL) return;
if (event.getType() != RenderGameOverlayEvent.ElementType.ALL) return;
if (settingsRegistry.get(Setting.INDICATOR)) {
FontRenderer fontRenderer = mc.fontRendererObj;
fontRenderer.drawString(I18n.format("replaymod.gui.recording").toUpperCase(), 30, 18 - (fontRenderer.FONT_HEIGHT / 2), 0xffffffff);

View File

@@ -13,7 +13,6 @@ import io.netty.channel.Channel;
import io.netty.channel.ChannelPipeline;
import net.minecraft.client.Minecraft;
import net.minecraft.network.NetworkManager;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.WorldType;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientConnectedToServerEvent;
@@ -49,8 +48,8 @@ public class ConnectionEventHandler {
@SubscribeEvent
public void onConnectedToServerEvent(ClientConnectedToServerEvent event) {
try {
if(event.isLocal) {
if (MinecraftServer.getServer().getEntityWorld().getWorldType() == WorldType.DEBUG_WORLD) {
if(event.isLocal()) {
if (mc.getIntegratedServer().getEntityWorld().getWorldType() == WorldType.DEBUG_WORLD) {
logger.info("Debug World recording is not supported.");
return;
}
@@ -65,16 +64,17 @@ public class ConnectionEventHandler {
}
}
NetworkManager nm = event.manager;
NetworkManager nm = event.getManager();
String worldName;
if(event.isLocal) {
worldName = MinecraftServer.getServer().getWorldName();
if(event.isLocal()) {
worldName = mc.getIntegratedServer().getWorldName();
} else if (Minecraft.getMinecraft().getCurrentServerData() != null) {
worldName = Minecraft.getMinecraft().getCurrentServerData().serverIP;
} else {
logger.info("Recording not started as the world is neither local nor remote (probably a replay).");
return;
}
Channel channel = nm.channel();
ChannelPipeline pipeline = channel.pipeline();
@@ -87,7 +87,7 @@ public class ConnectionEventHandler {
replayFile.writeModInfo(ModCompat.getInstalledNetworkMods());
ReplayMetaData metaData = new ReplayMetaData();
metaData.setSingleplayer(event.isLocal);
metaData.setSingleplayer(event.isLocal());
metaData.setServerName(worldName);
metaData.setGenerator("ReplayMod v" + ReplayMod.getContainer().getVersion());
metaData.setDate(System.currentTimeMillis());

View File

@@ -1,24 +1,20 @@
package com.replaymod.recording.handler;
import com.replaymod.recording.packet.PacketListener;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraft.network.Packet;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.network.play.server.*;
import net.minecraft.network.play.server.S14PacketEntity.S17PacketEntityLookMove;
import net.minecraft.server.integrated.IntegratedServer;
import net.minecraft.util.BlockPos;
import net.minecraft.util.MathHelper;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.minecart.MinecartInteractEvent;
import net.minecraftforge.event.entity.player.PlayerSleepInBedEvent;
import net.minecraftforge.event.entity.player.PlayerUseItemEvent;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent.ItemPickupEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
@@ -32,24 +28,24 @@ public class RecordingEventHandler {
private final PacketListener packetListener;
private Double lastX, lastY, lastZ;
private ItemStack[] playerItems = new ItemStack[5];
private ItemStack[] playerItems = new ItemStack[6];
private int ticksSinceLastCorrection;
private boolean wasSleeping;
private int lastRiding = -1;
private Integer rotationYawHeadBefore;
private boolean wasHandActive;
private EnumHand lastActiveHand;
public RecordingEventHandler(PacketListener packetListener) {
this.packetListener = packetListener;
}
public void register() {
FMLCommonHandler.instance().bus().register(this);
MinecraftForge.EVENT_BUS.register(this);
((RecordingEventSender) mc.renderGlobal).setRecordingEventHandler(this);
}
public void unregister() {
FMLCommonHandler.instance().bus().unregister(this);
MinecraftForge.EVENT_BUS.unregister(this);
RecordingEventSender recordingEventSender = ((RecordingEventSender) mc.renderGlobal);
if (recordingEventSender.getRecordingEventHandler() == this) {
@@ -59,7 +55,7 @@ public class RecordingEventHandler {
public void onPlayerJoin() {
try {
packetListener.save(spawnPlayer(mc.thePlayer));
packetListener.save(new SPacketSpawnPlayer(mc.thePlayer));
} catch(Exception e1) {
e1.printStackTrace();
}
@@ -67,42 +63,12 @@ public class RecordingEventHandler {
public void onPlayerRespawn() {
try {
packetListener.save(spawnPlayer(mc.thePlayer));
packetListener.save(new SPacketSpawnPlayer(mc.thePlayer));
} catch(Exception e) {
e.printStackTrace();
}
}
private S0CPacketSpawnPlayer spawnPlayer(EntityPlayer player) {
try {
S0CPacketSpawnPlayer packet = new S0CPacketSpawnPlayer();
ByteBuf bb = Unpooled.buffer();
PacketBuffer pb = new PacketBuffer(bb);
pb.writeVarIntToBuffer(player.getEntityId());
pb.writeUuid(EntityPlayer.getUUID(player.getGameProfile()));
pb.writeInt(MathHelper.floor_double(player.posX * 32.0D));
pb.writeInt(MathHelper.floor_double(player.posY * 32.0D));
pb.writeInt(MathHelper.floor_double(player.posZ * 32.0D));
pb.writeByte((byte) ((int) (player.rotationYaw * 256.0F / 360.0F)));
pb.writeByte((byte) ((int) (player.rotationPitch * 256.0F / 360.0F)));
ItemStack itemstack = player.inventory.getCurrentItem();
pb.writeShort(itemstack == null ? 0 : Item.getIdFromItem(itemstack.getItem()));
player.getDataWatcher().writeTo(pb);
packet.readPacketData(pb);
return packet;
} catch(Exception e) {
e.printStackTrace();
return null;
}
}
@SubscribeEvent
public void onPlayerTick(PlayerTickEvent e) {
try {
@@ -131,19 +97,14 @@ public class RecordingEventHandler {
lastZ = e.player.posZ;
Packet packet;
if(force || Math.abs(dx) > 4.0 || Math.abs(dy) > 4.0 || Math.abs(dz) > 4.0) {
int x = MathHelper.floor_double(e.player.posX * 32.0D);
int y = MathHelper.floor_double(e.player.posY * 32.0D);
int z = MathHelper.floor_double(e.player.posZ * 32.0D);
byte yaw = (byte) ((int) (e.player.rotationYaw * 256.0F / 360.0F));
byte pitch = (byte) ((int) (e.player.rotationPitch * 256.0F / 360.0F));
packet = new S18PacketEntityTeleport(e.player.getEntityId(), x, y, z, yaw, pitch, e.player.onGround);
if (force || Math.abs(dx) > 8.0 || Math.abs(dy) > 8.0 || Math.abs(dz) > 8.0) {
packet = new SPacketEntityTeleport(e.player);
} else {
byte newYaw = (byte) ((int) (e.player.rotationYaw * 256.0F / 360.0F));
byte newPitch = (byte) ((int) (e.player.rotationPitch * 256.0F / 360.0F));
packet = new S17PacketEntityLookMove(e.player.getEntityId(),
(byte) Math.round(dx * 32), (byte) Math.round(dy * 32), (byte) Math.round(dz * 32),
packet = new SPacketEntity.S17PacketEntityLookMove(e.player.getEntityId(),
(short) Math.round(dx * 4096), (short) Math.round(dy * 4096), (short) Math.round(dz * 4096),
newYaw, newPitch, e.player.onGround);
}
@@ -153,37 +114,16 @@ public class RecordingEventHandler {
int rotationYawHead = ((int)(e.player.rotationYawHead * 256.0F / 360.0F));
if(!Objects.equals(rotationYawHead, rotationYawHeadBefore)) {
S19PacketEntityHeadLook head = new S19PacketEntityHeadLook();
ByteBuf bb1 = Unpooled.buffer();
PacketBuffer pb1 = new PacketBuffer(bb1);
pb1.writeVarIntToBuffer(e.player.getEntityId());
pb1.writeByte(rotationYawHead);
head.readPacketData(pb1);
packetListener.save(head);
packetListener.save(new SPacketEntityHeadLook(e.player, (byte) rotationYawHead));
rotationYawHeadBefore = rotationYawHead;
}
S12PacketEntityVelocity vel = new S12PacketEntityVelocity(e.player.getEntityId(), e.player.motionX, e.player.motionY, e.player.motionZ);
packetListener.save(vel);
packetListener.save(new SPacketEntityVelocity(e.player.getEntityId(), e.player.motionX, e.player.motionY, e.player.motionZ));
//Animation Packets
//Swing Animation
if(e.player.swingProgressInt == 1) {
S0BPacketAnimation pac = new S0BPacketAnimation();
ByteBuf bb = Unpooled.buffer();
PacketBuffer pb = new PacketBuffer(bb);
pb.writeVarIntToBuffer(e.player.getEntityId());
pb.writeByte(0);
pac.readPacketData(pb);
packetListener.save(pac);
if (e.player.isSwingInProgress && e.player.swingProgressInt == -1) {
packetListener.save(new SPacketAnimation(e.player, e.player.swingingHand == EnumHand.MAIN_HAND ? 0 : 3));
}
/*
@@ -207,77 +147,64 @@ public class RecordingEventHandler {
*/
//Inventory Handling
if(playerItems[0] != mc.thePlayer.getHeldItem()) {
playerItems[0] = mc.thePlayer.getHeldItem();
S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 0, playerItems[0]);
packetListener.save(pee);
if (playerItems[0] != mc.thePlayer.getHeldItem(EnumHand.MAIN_HAND)) {
playerItems[0] = mc.thePlayer.getHeldItem(EnumHand.MAIN_HAND);
packetListener.save(new SPacketEntityEquipment(e.player.getEntityId(), EntityEquipmentSlot.MAINHAND, playerItems[0]));
}
if(playerItems[1] != mc.thePlayer.inventory.armorInventory[0]) {
playerItems[1] = mc.thePlayer.inventory.armorInventory[0];
S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 1, playerItems[1]);
packetListener.save(pee);
if (playerItems[1] != mc.thePlayer.getHeldItem(EnumHand.OFF_HAND)) {
playerItems[1] = mc.thePlayer.getHeldItem(EnumHand.OFF_HAND);
packetListener.save(new SPacketEntityEquipment(e.player.getEntityId(), EntityEquipmentSlot.OFFHAND, playerItems[1]));
}
if(playerItems[2] != mc.thePlayer.inventory.armorInventory[1]) {
playerItems[2] = mc.thePlayer.inventory.armorInventory[1];
S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 2, playerItems[2]);
packetListener.save(pee);
if (playerItems[2] != mc.thePlayer.inventory.armorInventory[0]) {
playerItems[2] = mc.thePlayer.inventory.armorInventory[0];
packetListener.save(new SPacketEntityEquipment(e.player.getEntityId(), EntityEquipmentSlot.FEET, playerItems[2]));
}
if(playerItems[3] != mc.thePlayer.inventory.armorInventory[2]) {
playerItems[3] = mc.thePlayer.inventory.armorInventory[2];
S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 3, playerItems[3]);
packetListener.save(pee);
if (playerItems[3] != mc.thePlayer.inventory.armorInventory[1]) {
playerItems[3] = mc.thePlayer.inventory.armorInventory[1];
packetListener.save(new SPacketEntityEquipment(e.player.getEntityId(), EntityEquipmentSlot.LEGS, playerItems[3]));
}
if(playerItems[4] != mc.thePlayer.inventory.armorInventory[3]) {
playerItems[4] = mc.thePlayer.inventory.armorInventory[3];
S04PacketEntityEquipment pee = new S04PacketEntityEquipment(e.player.getEntityId(), 4, playerItems[4]);
packetListener.save(pee);
if (playerItems[4] != mc.thePlayer.inventory.armorInventory[2]) {
playerItems[4] = mc.thePlayer.inventory.armorInventory[2];
packetListener.save(new SPacketEntityEquipment(e.player.getEntityId(), EntityEquipmentSlot.CHEST, playerItems[4]));
}
if (playerItems[5] != mc.thePlayer.inventory.armorInventory[3]) {
playerItems[5] = mc.thePlayer.inventory.armorInventory[3];
packetListener.save(new SPacketEntityEquipment(e.player.getEntityId(), EntityEquipmentSlot.HEAD, playerItems[5]));
}
//Leaving Ride
if((!mc.thePlayer.isRiding() && lastRiding != -1) ||
(mc.thePlayer.isRiding() && lastRiding != mc.thePlayer.ridingEntity.getEntityId())) {
(mc.thePlayer.isRiding() && lastRiding != mc.thePlayer.getRidingEntity().getEntityId())) {
if(!mc.thePlayer.isRiding()) {
lastRiding = -1;
} else {
lastRiding = mc.thePlayer.ridingEntity.getEntityId();
lastRiding = mc.thePlayer.getRidingEntity().getEntityId();
}
S1BPacketEntityAttach pea = new S1BPacketEntityAttach();
ByteBuf buf = Unpooled.buffer();
PacketBuffer pbuf = new PacketBuffer(buf);
pbuf.writeInt(e.player.getEntityId());
pbuf.writeInt(lastRiding);
pbuf.writeBoolean(false);
pea.readPacketData(pbuf);
packetListener.save(pea);
packetListener.save(new SPacketEntityAttach(e.player, e.player.getRidingEntity()));
}
//Sleeping
if(!mc.thePlayer.isPlayerSleeping() && wasSleeping) {
S0BPacketAnimation pac = new S0BPacketAnimation();
ByteBuf bb = Unpooled.buffer();
PacketBuffer pb = new PacketBuffer(bb);
pb.writeVarIntToBuffer(e.player.getEntityId());
pb.writeByte(2);
pac.readPacketData(pb);
packetListener.save(pac);
packetListener.save(new SPacketAnimation(e.player, 2));
wasSleeping = false;
}
// Active hand (e.g. eating, drinking, blocking)
if (mc.thePlayer.isHandActive() ^ wasHandActive || mc.thePlayer.getActiveHand() != lastActiveHand) {
wasHandActive = mc.thePlayer.isHandActive();
lastActiveHand = mc.thePlayer.getActiveHand();
EntityDataManager dataManager = new EntityDataManager(null);
int state = (wasHandActive ? 1 : 0) | (lastActiveHand == EnumHand.OFF_HAND ? 2 : 0);
dataManager.register(EntityLiving.HAND_STATES, (byte) state);
packetListener.save(new SPacketEntityMetadata(mc.thePlayer.getEntityId(), dataManager, true));
}
} catch(Exception e1) {
e1.printStackTrace();
}
@@ -286,27 +213,7 @@ public class RecordingEventHandler {
@SubscribeEvent
public void onPickupItem(ItemPickupEvent event) {
try {
packetListener.save(new S0DPacketCollectItem(event.pickedUp.getEntityId(), event.player.getEntityId()));
} catch(Exception e) {
e.printStackTrace();
}
}
@SubscribeEvent
public void onStartEating(PlayerUseItemEvent.Start event) {
try {
if(!event.entityPlayer.isEating()) return;
S0BPacketAnimation packet = new S0BPacketAnimation();
ByteBuf bb = Unpooled.buffer();
PacketBuffer pb = new PacketBuffer(bb);
pb.writeVarIntToBuffer(event.entityPlayer.getEntityId());
pb.writeByte(3);
packet.readPacketData(pb);
packetListener.save(packet);
packetListener.save(new SPacketCollectItem(event.pickedUp.getEntityId(), event.player.getEntityId()));
} catch(Exception e) {
e.printStackTrace();
}
@@ -315,21 +222,11 @@ public class RecordingEventHandler {
@SubscribeEvent
public void onSleep(PlayerSleepInBedEvent event) {
try {
if(event.entityPlayer != mc.thePlayer) {
if (event.getEntityPlayer() != mc.thePlayer) {
return;
}
S0APacketUseBed pub = new S0APacketUseBed();
ByteBuf buf = Unpooled.buffer();
PacketBuffer pbuf = new PacketBuffer(buf);
pbuf.writeVarIntToBuffer(event.entityPlayer.getEntityId());
pbuf.writeBlockPos(event.pos);
pub.readPacketData(pbuf);
packetListener.save(pub);
packetListener.save(new SPacketUseBed(event.getEntityPlayer(), event.getPos()));
wasSleeping = true;
@@ -341,24 +238,13 @@ public class RecordingEventHandler {
@SubscribeEvent
public void enterMinecart(MinecartInteractEvent event) {
try {
if(event.player != mc.thePlayer) {
if(event.getEntity() != mc.thePlayer) {
return;
}
S1BPacketEntityAttach pea = new S1BPacketEntityAttach();
packetListener.save(new SPacketEntityAttach(event.getPlayer(), event.getMinecart()));
ByteBuf buf = Unpooled.buffer();
PacketBuffer pbuf = new PacketBuffer(buf);
pbuf.writeInt(event.player.getEntityId());
pbuf.writeInt(event.minecart.getEntityId());
pbuf.writeBoolean(false);
pea.readPacketData(pbuf);
packetListener.save(pea);
lastRiding = event.minecart.getEntityId();
lastRiding = event.getMinecart().getEntityId();
} catch(Exception e) {
e.printStackTrace();
}
@@ -367,7 +253,7 @@ public class RecordingEventHandler {
public void onBlockBreakAnim(int breakerId, BlockPos pos, int progress) {
EntityPlayer thePlayer = mc.thePlayer;
if (thePlayer != null && breakerId == thePlayer.getEntityId()) {
packetListener.save(new S25PacketBlockBreakAnim(breakerId, pos, progress));
packetListener.save(new SPacketBlockBreakAnim(breakerId, pos, progress));
}
}

View File

@@ -3,16 +3,14 @@ package com.replaymod.recording.mixin;
import com.replaymod.recording.handler.RecordingEventHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.network.play.server.S07PacketRespawn;
import net.minecraft.network.play.server.S38PacketPlayerListItem;
import net.minecraft.network.play.server.SPacketPlayerListItem;
import net.minecraft.network.play.server.SPacketRespawn;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.List;
@Mixin(NetHandlerPlayClient.class)
public abstract class MixinNetHandlerPlayClient {
@@ -31,13 +29,11 @@ public abstract class MixinNetHandlerPlayClient {
* @param ci Callback info
*/
@Inject(method = "handlePlayerListItem", at=@At("RETURN"))
public void recordOwnJoin(S38PacketPlayerListItem packet, CallbackInfo ci) {
public void recordOwnJoin(SPacketPlayerListItem packet, CallbackInfo ci) {
RecordingEventHandler handler = getRecordingEventHandler();
if (handler != null && packet.func_179768_b() == S38PacketPlayerListItem.Action.ADD_PLAYER) {
@SuppressWarnings("unchecked")
List<S38PacketPlayerListItem.AddPlayerData> dataList = packet.func_179767_a();
for (S38PacketPlayerListItem.AddPlayerData data : dataList) {
if (data.func_179962_a().getId().equals(Minecraft.getMinecraft().thePlayer.getGameProfile().getId())) {
if (handler != null && packet.getAction() == SPacketPlayerListItem.Action.ADD_PLAYER) {
for (SPacketPlayerListItem.AddPlayerData data : packet.getEntries()) {
if (data.getProfile().getId().equals(gameController.thePlayer.getGameProfile().getId())) {
handler.onPlayerJoin();
}
}
@@ -47,12 +43,12 @@ public abstract class MixinNetHandlerPlayClient {
/**
* Record the own player entity respawning.
* We cannot use the {@link net.minecraftforge.event.entity.EntityJoinWorldEvent} because that would also include
* the first spawn which is already handled by {@link #recordOwnJoin(S38PacketPlayerListItem, CallbackInfo)}.
* the first spawn which is already handled by {@link #recordOwnJoin(SPacketPlayerListItem, CallbackInfo)}.
* @param packet The packet
* @param ci Callback info
*/
@Inject(method = "handleRespawn", at=@At("RETURN"))
public void recordOwnRespawn(S07PacketRespawn packet, CallbackInfo ci) {
public void recordOwnRespawn(SPacketRespawn packet, CallbackInfo ci) {
RecordingEventHandler handler = getRecordingEventHandler();
if (handler != null) {
handler.onPlayerRespawn();

View File

@@ -2,7 +2,7 @@ package com.replaymod.recording.mixin;
import com.replaymod.recording.handler.RecordingEventHandler;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.util.BlockPos;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;

View File

@@ -9,21 +9,24 @@ import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.DataWatcher;
import net.minecraft.entity.Entity;
import net.minecraft.network.EnumConnectionState;
import net.minecraft.network.EnumPacketDirection;
import net.minecraft.network.Packet;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.network.play.server.*;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.text.TextComponentString;
import net.minecraftforge.fml.common.network.internal.FMLProxyPacket;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@@ -84,8 +87,8 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
public void save(Packet packet) {
try {
if(packet instanceof S0CPacketSpawnPlayer) {
UUID uuid = ((S0CPacketSpawnPlayer) packet).func_179819_c();
if(packet instanceof SPacketSpawnPlayer) {
UUID uuid = ((SPacketSpawnPlayer) packet).getUniqueId();
Set<String> uuids = new HashSet<>(Arrays.asList(metaData.getPlayers()));
uuids.add(uuid.toString());
metaData.setPlayers(uuids.toArray(new String[uuids.size()]));
@@ -150,16 +153,16 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
try {
Packet packet = (Packet) msg;
if(packet instanceof S0DPacketCollectItem) {
if(packet instanceof SPacketCollectItem) {
if(mc.thePlayer != null ||
((S0DPacketCollectItem) packet).func_149353_d() == mc.thePlayer.getEntityId()) {
((SPacketCollectItem) packet).getEntityID() == mc.thePlayer.getEntityId()) {
super.channelRead(ctx, msg);
return;
}
}
if (packet instanceof S48PacketResourcePackSend) {
save(resourcePackRecorder.handleResourcePack((S48PacketResourcePackSend) packet));
if (packet instanceof SPacketResourcePackSend) {
save(resourcePackRecorder.handleResourcePack((SPacketResourcePackSend) packet));
return;
}
@@ -172,10 +175,10 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
save(packet);
if (packet instanceof S3FPacketCustomPayload) {
S3FPacketCustomPayload p = (S3FPacketCustomPayload) packet;
if (packet instanceof SPacketCustomPayload) {
SPacketCustomPayload p = (SPacketCustomPayload) packet;
if (Restrictions.PLUGIN_CHANNEL.equals(p.getChannelName())) {
packet = new S40PacketDisconnect(new ChatComponentText("Please update to view this replay."));
packet = new SPacketDisconnect(new TextComponentString("Please update to view this replay."));
save(packet);
}
}
@@ -188,27 +191,31 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
super.channelRead(ctx, msg);
}
private <T> void DataManager_set(EntityDataManager dataManager, EntityDataManager.DataEntry<T> entry) {
dataManager.register(entry.getKey(), entry.getValue());
}
@SuppressWarnings("unchecked")
private byte[] getPacketData(Packet packet) throws IOException {
if(packet instanceof S0FPacketSpawnMob) {
S0FPacketSpawnMob p = (S0FPacketSpawnMob) packet;
if (p.field_149043_l == null) {
p.field_149043_l = new DataWatcher(null);
if(p.func_149027_c() != null) {
for(DataWatcher.WatchableObject wo : (List<DataWatcher.WatchableObject>) p.func_149027_c()) {
p.field_149043_l.addObject(wo.getDataValueId(), wo.getObject());
if (packet instanceof SPacketSpawnMob) {
SPacketSpawnMob p = (SPacketSpawnMob) packet;
if (p.dataManager == null) {
p.dataManager = new EntityDataManager(null);
if (p.getDataManagerEntries() != null) {
for (EntityDataManager.DataEntry<?> entry : p.getDataManagerEntries()) {
DataManager_set(p.dataManager, entry);
}
}
}
}
if(packet instanceof S0CPacketSpawnPlayer) {
S0CPacketSpawnPlayer p = (S0CPacketSpawnPlayer) packet;
if (p.field_148960_i == null) {
p.field_148960_i = new DataWatcher(null);
if(p.func_148944_c() != null) {
for(DataWatcher.WatchableObject wo : (List<DataWatcher.WatchableObject>) p.func_148944_c()) {
p.field_148960_i.addObject(wo.getDataValueId(), wo.getObject());
if (packet instanceof SPacketSpawnPlayer) {
SPacketSpawnPlayer p = (SPacketSpawnPlayer) packet;
if (p.watcher == null) {
p.watcher = new EntityDataManager(null);
if (p.getDataManagerEntries() != null) {
for (EntityDataManager.DataEntry<?> entry : p.getDataManagerEntries()) {
DataManager_set(p.watcher, entry);
}
}
}

View File

@@ -15,8 +15,8 @@ import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.client.resources.I18n;
import net.minecraft.client.resources.ResourcePackRepository;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.play.client.C19PacketResourcePackStatus;
import net.minecraft.network.play.server.S48PacketResourcePackSend;
import net.minecraft.network.play.client.CPacketResourcePackStatus;
import net.minecraft.network.play.server.SPacketResourcePackSend;
import net.minecraft.util.HttpUtil;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager;
@@ -70,12 +70,12 @@ public class ResourcePackRecorder {
}
}
public synchronized S48PacketResourcePackSend handleResourcePack(S48PacketResourcePackSend packet) {
public synchronized SPacketResourcePackSend handleResourcePack(SPacketResourcePackSend packet) {
final int requestId = nextRequestId++;
final NetHandlerPlayClient netHandler = mc.getNetHandler();
final NetHandlerPlayClient netHandler = mc.getConnection();
final NetworkManager netManager = netHandler.getNetworkManager();
final String url = packet.func_179783_a();
final String hash = packet.func_179784_b();
final String url = packet.getURL();
final String hash = packet.getHash();
if (url.startsWith("level://")) {
String levelName = url.substring("level://".length());
@@ -83,60 +83,60 @@ public class ResourcePackRecorder {
final File levelDir = new File(savesDir, levelName);
if (levelDir.isFile()) {
netManager.sendPacket(new C19PacketResourcePackStatus(hash, C19PacketResourcePackStatus.Action.ACCEPTED));
Futures.addCallback(mc.getResourcePackRepository().func_177319_a(levelDir), new FutureCallback() {
netManager.sendPacket(new CPacketResourcePackStatus(hash, CPacketResourcePackStatus.Action.ACCEPTED));
Futures.addCallback(mc.getResourcePackRepository().setResourcePackInstance(levelDir), new FutureCallback<Object>() {
@Override
public void onSuccess(Object result) {
recordResourcePack(levelDir, requestId);
netManager.sendPacket(new C19PacketResourcePackStatus(hash, C19PacketResourcePackStatus.Action.SUCCESSFULLY_LOADED));
netManager.sendPacket(new CPacketResourcePackStatus(hash, CPacketResourcePackStatus.Action.SUCCESSFULLY_LOADED));
}
@Override
public void onFailure(@Nonnull Throwable throwable) {
netManager.sendPacket(new C19PacketResourcePackStatus(hash, C19PacketResourcePackStatus.Action.FAILED_DOWNLOAD));
netManager.sendPacket(new CPacketResourcePackStatus(hash, CPacketResourcePackStatus.Action.FAILED_DOWNLOAD));
}
});
} else {
netManager.sendPacket(new C19PacketResourcePackStatus(hash, C19PacketResourcePackStatus.Action.FAILED_DOWNLOAD));
netManager.sendPacket(new CPacketResourcePackStatus(hash, CPacketResourcePackStatus.Action.FAILED_DOWNLOAD));
}
} else {
final ServerData serverData = mc.getCurrentServerData();
if (serverData != null && serverData.getResourceMode() == ServerData.ServerResourceMode.ENABLED) {
netManager.sendPacket(new C19PacketResourcePackStatus(hash, C19PacketResourcePackStatus.Action.ACCEPTED));
netManager.sendPacket(new CPacketResourcePackStatus(hash, CPacketResourcePackStatus.Action.ACCEPTED));
downloadResourcePackFuture(requestId, url, hash);
} else if (serverData != null && serverData.getResourceMode() != ServerData.ServerResourceMode.PROMPT) {
netManager.sendPacket(new C19PacketResourcePackStatus(hash, C19PacketResourcePackStatus.Action.DECLINED));
netManager.sendPacket(new CPacketResourcePackStatus(hash, CPacketResourcePackStatus.Action.DECLINED));
} else {
mc.addScheduledTask(() -> mc.displayGuiScreen(new GuiYesNo((result, id) -> {
if (serverData != null) {
serverData.setResourceMode(result ? ServerData.ServerResourceMode.ENABLED : ServerData.ServerResourceMode.DISABLED);
}
if (result) {
netManager.sendPacket(new C19PacketResourcePackStatus(hash, C19PacketResourcePackStatus.Action.ACCEPTED));
netManager.sendPacket(new CPacketResourcePackStatus(hash, CPacketResourcePackStatus.Action.ACCEPTED));
downloadResourcePackFuture(requestId, url, hash);
} else {
netManager.sendPacket(new C19PacketResourcePackStatus(hash, C19PacketResourcePackStatus.Action.DECLINED));
netManager.sendPacket(new CPacketResourcePackStatus(hash, CPacketResourcePackStatus.Action.DECLINED));
}
ServerList.func_147414_b(serverData);
ServerList.saveSingleServer(serverData);
mc.displayGuiScreen(null);
}, I18n.format("multiplayer.texturePrompt.line1"), I18n.format("multiplayer.texturePrompt.line2"), 0)));
}
}
return new S48PacketResourcePackSend("replay://" + requestId, "");
return new SPacketResourcePackSend("replay://" + requestId, "");
}
private void downloadResourcePackFuture(int requestId, String url, final String hash) {
Futures.addCallback(downloadResourcePack(requestId, url, hash), new FutureCallback() {
@Override
public void onSuccess(Object result) {
mc.getNetHandler().addToSendQueue(new C19PacketResourcePackStatus(hash, C19PacketResourcePackStatus.Action.SUCCESSFULLY_LOADED));
mc.getConnection().sendPacket(new CPacketResourcePackStatus(hash, CPacketResourcePackStatus.Action.SUCCESSFULLY_LOADED));
}
@Override
public void onFailure(@Nonnull Throwable throwable) {
mc.getNetHandler().addToSendQueue(new C19PacketResourcePackStatus(hash, C19PacketResourcePackStatus.Action.FAILED_DOWNLOAD));
mc.getConnection().sendPacket(new CPacketResourcePackStatus(hash, CPacketResourcePackStatus.Action.FAILED_DOWNLOAD));
}
});
}
@@ -161,16 +161,16 @@ public class ResourcePackRecorder {
}
final File file = new File(repo.dirServerResourcepacks, fileName);
repo.field_177321_h.lock();
repo.lock.lock();
try {
repo.func_148529_f();
repo.clearResourcePack();
if (file.exists() && hash.length() == 40) {
try {
String fileHash = Hashing.sha1().hashBytes(Files.toByteArray(file)).toString();
if (fileHash.equals(hash)) {
recordResourcePack(file, requestId);
return repo.func_177319_a(file);
return repo.setResourcePackInstance(file);
}
logger.warn("File " + file + " had wrong hash (expected " + hash + ", found " + fileHash + "). Deleting it.");
@@ -186,13 +186,13 @@ public class ResourcePackRecorder {
Futures.getUnchecked(mc.addScheduledTask(() -> mc.displayGuiScreen(guiScreen)));
Map sessionInfo = Minecraft.getSessionInfo();
repo.field_177322_i = HttpUtil.func_180192_a(file, url, sessionInfo, 50 * 1024 * 1024, guiScreen, mc.getProxy());
Futures.addCallback(repo.field_177322_i, new FutureCallback() {
Map<String, String> sessionInfo = Minecraft.getSessionInfo();
repo.downloadingPacks = HttpUtil.downloadResourcePack(file, url, sessionInfo, 50 * 1024 * 1024, guiScreen, mc.getProxy());
Futures.addCallback(repo.downloadingPacks, new FutureCallback<Object>() {
@Override
public void onSuccess(Object value) {
recordResourcePack(file, requestId);
repo.func_177319_a(file);
repo.setResourcePackInstance(file);
}
@Override
@@ -200,9 +200,9 @@ public class ResourcePackRecorder {
throwable.printStackTrace();
}
});
return repo.field_177322_i;
return repo.downloadingPacks;
} finally {
repo.field_177321_h.unlock();
repo.lock.unlock();
}
}

View File

@@ -8,7 +8,6 @@ import net.minecraft.client.Minecraft;
import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.TeeOutputStream;
import org.lwjgl.util.ReadableDimension;
@@ -35,7 +34,6 @@ public class VideoWriter implements FrameConsumer<RGBFrame> {
this.settings = settings;
File outputFolder = settings.getOutputFile().getParentFile();
FileUtils.forceMkdir(outputFolder);
String fileName = settings.getOutputFile().getName();
commandArgs = settings.getExportArguments()

View File

@@ -6,11 +6,11 @@ import com.replaymod.render.frame.ODSOpenGlFrame;
import com.replaymod.render.frame.OpenGlFrame;
import com.replaymod.render.rendering.FrameCapturer;
import com.replaymod.render.shader.Program;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.crash.CrashReport;
import net.minecraft.util.ReportedException;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.util.Dimension;
import org.lwjgl.util.ReadableDimension;
import java.io.IOException;
@@ -31,8 +31,6 @@ public class ODSFrameCapturer implements FrameCapturer<ODSOpenGlFrame> {
private final BooleanState[] previousStates = new BooleanState[3];
private final BooleanState previousFogState;
private final Minecraft mc = Minecraft.getMinecraft();
public ODSFrameCapturer(WorldRenderer worldRenderer, final RenderInfo renderInfo, int frameSize) {
RenderInfo fakeInfo = new RenderInfo() {
private int call;
@@ -75,9 +73,9 @@ public class ODSFrameCapturer implements FrameCapturer<ODSOpenGlFrame> {
linkState(1, "lightMapEnabled");
linkState(2, "hurtTextureEnabled");
final Program.Uniform uniform = shaderProgram.getUniformVariable("fogEnabled");
previousFogState = GlStateManager.fogState.field_179049_a;
previousFogState = GlStateManager.fogState.fog;
uniform.set(previousFogState.currentState);
GlStateManager.fogState.field_179049_a = new BooleanState(previousFogState.capability) {
GlStateManager.fogState.fog = new BooleanState(previousFogState.capability) {
@Override
public void setState(boolean state) {
super.setState(state);
@@ -135,7 +133,7 @@ public class ODSFrameCapturer implements FrameCapturer<ODSOpenGlFrame> {
for (int i = 0; i < 3; i++) {
GlStateManager.textureState[i].texture2DState = previousStates[i];
}
GlStateManager.fogState.field_179049_a = previousFogState;
GlStateManager.fogState.fog = previousFogState;
}
private class CubicStereoFrameCapturer extends CubicPboOpenGlFrameCapturer {
@@ -145,8 +143,6 @@ public class ODSFrameCapturer implements FrameCapturer<ODSOpenGlFrame> {
@Override
protected OpenGlFrame renderFrame(int frameId, float partialTicks, CubicOpenGlFrameCapturer.Data captureData) {
resize(getFrameWidth(), getFrameHeight());
pushMatrix();
frameBuffer().bindFramebuffer(true);
@@ -154,7 +150,7 @@ public class ODSFrameCapturer implements FrameCapturer<ODSOpenGlFrame> {
enableTexture2D();
directionVariable.set(captureData.ordinal());
worldRenderer.renderWorld(partialTicks, null);
worldRenderer.renderWorld(new Dimension(getFrameWidth(), getFrameHeight()), partialTicks, null);
frameBuffer().unbindFramebuffer();
popMatrix();

View File

@@ -4,7 +4,6 @@ import com.replaymod.render.frame.OpenGlFrame;
import com.replaymod.render.rendering.Frame;
import com.replaymod.render.rendering.FrameCapturer;
import com.replaymod.render.utils.ByteBufferPool;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.shader.Framebuffer;
import org.lwjgl.opengl.GL11;
@@ -25,8 +24,6 @@ public abstract class OpenGlFrameCapturer<F extends Frame, D extends CaptureData
protected int framesDone;
private Framebuffer frameBuffer;
private final Minecraft mc = Minecraft.getMinecraft();
public OpenGlFrameCapturer(WorldRenderer worldRenderer, RenderInfo renderInfo) {
this.worldRenderer = worldRenderer;
this.renderInfo = renderInfo;
@@ -59,7 +56,7 @@ public abstract class OpenGlFrameCapturer<F extends Frame, D extends CaptureData
protected Framebuffer frameBuffer() {
if (frameBuffer == null) {
frameBuffer = Minecraft.getMinecraft().getFramebuffer();
frameBuffer = new Framebuffer(getFrameWidth(), getFrameHeight(), true);
}
return frameBuffer;
}
@@ -74,15 +71,13 @@ public abstract class OpenGlFrameCapturer<F extends Frame, D extends CaptureData
}
protected OpenGlFrame renderFrame(int frameId, float partialTicks, D captureData) {
resize(getFrameWidth(), getFrameHeight());
pushMatrix();
frameBuffer().bindFramebuffer(true);
clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
enableTexture2D();
worldRenderer.renderWorld(partialTicks, captureData);
worldRenderer.renderWorld(frameSize, partialTicks, captureData);
frameBuffer().unbindFramebuffer();
popMatrix();
@@ -107,18 +102,11 @@ public abstract class OpenGlFrameCapturer<F extends Frame, D extends CaptureData
return new OpenGlFrame(frameId, new Dimension(getFrameWidth(), getFrameHeight()), buffer);
}
protected void resize(int width, int height) {
if (width != mc.displayWidth || height != mc.displayHeight) {
setWindowSize(width, height);
}
}
private void setWindowSize(int width, int height) {
mc.resize(width, height);
}
@Override
public void close() throws IOException {
worldRenderer.close();
if (frameBuffer != null) {
frameBuffer.deleteFramebuffer();
}
}
}

View File

@@ -1,8 +1,10 @@
package com.replaymod.render.capturer;
import org.lwjgl.util.ReadableDimension;
import java.io.Closeable;
public interface WorldRenderer extends Closeable {
void renderWorld(float partialTicks, CaptureData data);
void renderWorld(ReadableDimension displaySize, float partialTicks, CaptureData data);
void setOmnidirectional(boolean omnidirectional);
}

View File

@@ -91,7 +91,7 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
}).setSize(122, 20).setSteps(110);
public final GuiPanel videoResolutionPanel = new GuiPanel()
.setLayout(new HorizontalLayout(HorizontalLayout.Alignment.RIGHT).setSpacing(2))
.addElements(new HorizontalLayout.Data(0.5), videoWidth, new GuiLabel().setText("*"), videoHeight);
.addElements(null, videoWidth, new GuiLabel().setText("*"), videoHeight);
public final GuiNumberField bitRateField = new GuiNumberField().setValue(10).setSize(50, 20);
public final GuiDropdownMenu<String> bitRateUnit = new GuiDropdownMenu<String>()
@@ -130,7 +130,7 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
new GuiPanel().addElements(null, bitRateField, bitRateUnit).setLayout(new HorizontalLayout()),
frameRateSlider).setLayout(new HorizontalLayout(HorizontalLayout.Alignment.RIGHT).setSpacing(3)),
new GuiLabel().setI18nText("replaymod.gui.rendersettings.outputfile"), outputFileButton)
.setLayout(new GridLayout().setCellsEqualSize(false).setColumns(2).setSpacingX(5).setSpacingY(5));
.setLayout(new GridLayout().setCellsEqualSize(false).setColumns(2).setSpacingX(5).setSpacingY(3));
public final GuiCheckbox nametagCheckbox = new GuiCheckbox()
.setI18nLabel("replaymod.gui.rendersettings.nametags");
@@ -186,7 +186,7 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
// Closing this GUI ensures that settings are saved
getMinecraft().displayGuiScreen(null);
try {
VideoRenderer videoRenderer = new VideoRenderer(save(false), replayHandler, timeline);
VideoRenderer videoRenderer = new VideoRenderer(save(true), replayHandler, timeline);
videoRenderer.renderVideo();
} catch (IOException e) {
e.printStackTrace();
@@ -284,15 +284,6 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
videoHeight.setTextColor(Colors.RED);
}
// Enable/Disable bitrate input field and dropdown
if (encodingPresetDropdown.getSelectedValue().hasBitrateSetting()) {
bitRateField.setEnabled();
bitRateUnit.setEnabled();
} else {
bitRateField.setDisabled();
bitRateUnit.setDisabled();
}
// Enable/Disable camera stabilization checkboxes
switch (renderMethodDropdown.getSelectedValue()) {
case CUBIC:
@@ -387,7 +378,7 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
updateInputs();
}
public RenderSettings save(boolean serialize) {
public RenderSettings save(boolean saveOutputFile) {
return new RenderSettings(
renderMethodDropdown.getSelectedValue(),
encodingPresetDropdown.getSelectedValue(),
@@ -395,13 +386,13 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
videoHeight.getInteger(),
frameRateSlider.getValue() + 10,
bitRateField.getInteger() << (10 * bitRateUnit.getSelected()),
serialize ? null : outputFile,
saveOutputFile ? outputFile : null,
nametagCheckbox.isChecked(),
stabilizeYaw.isChecked() && (serialize || stabilizeYaw.isEnabled()),
stabilizePitch.isChecked() && (serialize || stabilizePitch.isEnabled()),
stabilizeRoll.isChecked() && (serialize || stabilizeRoll.isEnabled()),
stabilizeYaw.isChecked(),
stabilizePitch.isChecked(),
stabilizeRoll.isChecked(),
chromaKeyingCheckbox.isChecked() ? chromaKeyingColor.getColor() : null,
inject360Metadata.isChecked() && (serialize || inject360Metadata.isEnabled()),
inject360Metadata.isChecked(),
exportCommand.getText(),
exportArguments.getText(),
net.minecraft.client.gui.GuiScreen.isCtrlKeyDown()
@@ -421,7 +412,7 @@ public class GuiRenderSettings extends GuiScreen implements Closeable {
@Override
public void close() {
RenderSettings settings = save(true);
RenderSettings settings = save(false);
String json = new Gson().toJson(settings);
Configuration config = ReplayModRender.instance.getConfiguration();
getConfigProperty(config).set(json);

View File

@@ -14,6 +14,7 @@ import de.johni0702.minecraft.gui.element.advanced.GuiProgressBar;
import de.johni0702.minecraft.gui.layout.CustomLayout;
import de.johni0702.minecraft.gui.layout.HorizontalLayout;
import net.minecraft.client.renderer.texture.DynamicTexture;
import net.minecraft.client.renderer.texture.TextureUtil;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.util.Dimension;
@@ -22,6 +23,8 @@ import org.lwjgl.util.ReadablePoint;
import java.nio.ByteBuffer;
import static net.minecraft.client.renderer.GlStateManager.bindTexture;
public class GuiVideoRenderer extends GuiScreen {
private static final ResourceLocation NO_PREVIEW_TEXTURE = new ResourceLocation("replaymod", "logo.jpg");
@@ -229,7 +232,13 @@ public class GuiVideoRenderer extends GuiScreen {
final int videoHeight = videoSize.getHeight();
if (previewTexture == null) {
previewTexture = new DynamicTexture(videoWidth, videoHeight);
previewTexture = new DynamicTexture(videoWidth, videoHeight) {
@Override
public void updateDynamicTexture() {
bindTexture(getGlTextureId());
TextureUtil.uploadTextureSub(0, getTextureData(), videoWidth, videoHeight, 0, 0, true, false, false);
}
};
}
if (previewTextureDirty) {
@@ -264,10 +273,7 @@ public class GuiVideoRenderer extends GuiScreen {
buffer.mark();
synchronized (this) {
int[] data = previewTexture.getTextureData();
// Optifine changes the texture data array to be three times as long (for use by shaders),
// we only want to initialize the first third which is why we use the length of the buffer instead
// of the length of the data array
for (int i = 0; buffer.remaining() > 0; i++) {
for (int i = 0; i < data.length; i++) {
data[i] = 0xff << 24 | (buffer.get() & 0xff) << 16 | (buffer.get() & 0xff) << 8 | (buffer.get() & 0xff);
}
previewTextureDirty = true;

View File

@@ -10,13 +10,13 @@ import net.minecraft.client.renderer.chunk.RenderChunk;
import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
public class ChunkLoadingRenderGlobal {
private final RenderGlobal hooked;
private final ChunkRenderDispatcher renderDispatcher;
private final JailingQueue<?> workerJailingQueue;
private final JailingQueue<ChunkCompileTaskGenerator> workerJailingQueue;
private final CustomChunkRenderWorker renderWorker;
private int frame;
@@ -27,10 +27,10 @@ public class ChunkLoadingRenderGlobal {
this.renderWorker = new CustomChunkRenderWorker(renderDispatcher, new RegionRenderCacheBuilder());
int workerThreads = renderDispatcher.listThreadedWorkers.size();
BlockingQueue<Object> queueChunkUpdates = renderDispatcher.queueChunkUpdates;
PriorityBlockingQueue<ChunkCompileTaskGenerator> queueChunkUpdates = renderDispatcher.queueChunkUpdates;
workerJailingQueue = new JailingQueue<>(queueChunkUpdates);
renderDispatcher.queueChunkUpdates = workerJailingQueue;
ChunkCompileTaskGenerator element = new ChunkCompileTaskGenerator(null, null);
ChunkCompileTaskGenerator element = new ChunkCompileTaskGenerator(null, null, 0);
element.finish();
for (int i = 0; i < workerThreads; i++) {
queueChunkUpdates.add(element);
@@ -51,7 +51,6 @@ public class ChunkLoadingRenderGlobal {
}
}
@SuppressWarnings("unchecked")
public void updateChunks() {
while (renderDispatcher.runChunkUploads(0)) {
hooked.displayListEntitiesDirty = true;
@@ -59,7 +58,7 @@ public class ChunkLoadingRenderGlobal {
while (!renderDispatcher.queueChunkUpdates.isEmpty()) {
try {
renderWorker.processTask((ChunkCompileTaskGenerator) renderDispatcher.queueChunkUpdates.poll());
renderWorker.processTask(renderDispatcher.queueChunkUpdates.poll());
} catch (InterruptedException ignored) { }
}
@@ -69,7 +68,7 @@ public class ChunkLoadingRenderGlobal {
renderDispatcher.updateChunkNow(renderchunk);
renderchunk.setNeedsUpdate(false);
renderchunk.clearNeedsUpdate();
iterator.remove();
}
}

View File

@@ -5,11 +5,14 @@ import com.replaymod.render.capturer.CaptureData;
import com.replaymod.render.capturer.WorldRenderer;
import lombok.Getter;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.culling.ClippingHelper;
import net.minecraftforge.fml.common.FMLCommonHandler;
import org.lwjgl.util.ReadableDimension;
import java.io.IOException;
import static net.minecraft.client.renderer.GlStateManager.*;
public class EntityRendererHandler implements WorldRenderer {
public final Minecraft mc = Minecraft.getMinecraft();
@@ -26,10 +29,27 @@ public class EntityRendererHandler implements WorldRenderer {
((IEntityRenderer) mc.entityRenderer).replayModRender_setHandler(this);
}
public void withDisplaySize(int displayWidth, int displayHeight, Runnable runnable) {
final int prevWidth = mc.displayWidth;
final int prevHeight = mc.displayHeight;
mc.displayWidth = displayWidth;
mc.displayHeight = displayHeight;
runnable.run();
mc.displayWidth = prevWidth;
mc.displayHeight = prevHeight;
}
@Override
public void renderWorld(final float partialTicks, CaptureData data) {
public void renderWorld(ReadableDimension displaySize, final float partialTicks, CaptureData data) {
this.data = data;
renderWorld(partialTicks, 0);
withDisplaySize(displaySize.getWidth(), displaySize.getHeight(), new Runnable() {
@Override
public void run() {
renderWorld(partialTicks, 0);
}
});
}
public void renderWorld(float partialTicks, long finishTimeNano) {
@@ -37,9 +57,9 @@ public class EntityRendererHandler implements WorldRenderer {
mc.entityRenderer.updateLightmap(partialTicks);
GlStateManager.enableDepth();
GlStateManager.enableAlpha();
GlStateManager.alphaFunc(516, 0.5F);
enableDepth();
enableAlpha();
alphaFunc(516, 0.5F);
mc.entityRenderer.renderWorldPass(2, partialTicks, finishTimeNano);
@@ -56,6 +76,13 @@ public class EntityRendererHandler implements WorldRenderer {
this.omnidirectional = omnidirectional;
}
public static final class NoCullingClippingHelper extends ClippingHelper {
@Override
public boolean isBoxInFrustum(double p_78553_1_, double p_78553_3_, double p_78553_5_, double p_78553_7_, double p_78553_9_, double p_78553_11_) {
return true;
}
}
public interface GluPerspective {
void replayModRender_gluPerspective(float fovY, float aspect, float zNear, float zFar);
}

View File

@@ -1,47 +0,0 @@
package com.replaymod.render.mixin;
import com.replaymod.render.hooks.EntityRendererHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.EffectRenderer;
import net.minecraft.client.particle.EntityFX;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(EffectRenderer.class)
public abstract class MixinEffectRenderer {
@Redirect(method = "renderParticles", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/EntityFX;func_180434_a(Lnet/minecraft/client/renderer/WorldRenderer;Lnet/minecraft/entity/Entity;FFFFFF)V"))
private void renderNormalParticle(EntityFX fx, WorldRenderer worldRenderer, Entity view, float partialTicks,
float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) {
renderParticle(fx, worldRenderer, view, partialTicks, rotX, rotXZ, rotZ, rotYZ, rotXY);
}
@Redirect(method = "renderLitParticles", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/EntityFX;func_180434_a(Lnet/minecraft/client/renderer/WorldRenderer;Lnet/minecraft/entity/Entity;FFFFFF)V"))
private void renderLitParticle(EntityFX fx, WorldRenderer worldRenderer, Entity view, float partialTicks,
float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) {
renderParticle(fx, worldRenderer, view, partialTicks, rotX, rotXZ, rotZ, rotYZ, rotXY);
}
private void renderParticle(EntityFX fx, WorldRenderer worldRenderer, Entity view, float partialTicks,
float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) {
EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) Minecraft.getMinecraft().entityRenderer).replayModRender_getHandler();
if (handler != null && handler.omnidirectional) {
// Align all particles towards the camera
double dx = fx.prevPosX + (fx.posX - fx.prevPosX) * partialTicks - view.posX;
double dy = fx.prevPosY + (fx.posY - fx.prevPosY) * partialTicks - view.posY;
double dz = fx.prevPosZ + (fx.posZ - fx.prevPosZ) * partialTicks - view.posZ;
double pitch = -Math.atan2(dy, Math.sqrt(dx * dx + dz * dz));
double yaw = -Math.atan2(dx, dz);
rotX = (float) Math.cos(yaw);
rotZ = (float) Math.sin(yaw);
rotXZ = (float) Math.cos(pitch);
rotYZ = (float) (-rotZ * Math.sin(pitch));
rotXY = (float) (rotX * Math.sin(pitch));
}
fx.func_180434_a(worldRenderer, view, partialTicks, rotX, rotXZ, rotZ, rotYZ, rotXY);
}
}

View File

@@ -9,10 +9,11 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.EntityRenderer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.client.renderer.culling.Frustum;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.math.RayTraceResult;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.ReadableColor;
import org.lwjgl.util.glu.Project;
@@ -48,6 +49,14 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
}
}
@Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/culling/Frustum;setPosition(DDD)V"))
public void replayModRender_createNoCullingFrustum(Frustum frustum, double x, double y, double z) {
if (replayModRender_handler != null) {
frustum.clippingHelper = new EntityRendererHandler.NoCullingClippingHelper();
}
frustum.setPosition(x, y, z);
}
@Inject(method = "orientCamera", at = @At("HEAD"))
private void replayModRender_resetRotationIfNeeded(float partialTicks, CallbackInfo ci) {
if (replayModRender_handler != null) {
@@ -118,10 +127,10 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
@Shadow
public abstract void renderHand(float partialTicks, int renderPass);
@Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;drawSelectionBox(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/util/MovingObjectPosition;IF)V"))
private void replayModRender_drawSelectionBox(RenderGlobal instance, EntityPlayer player, MovingObjectPosition mop, int alwaysZero, float partialTicks) {
@Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;drawSelectionBox(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/util/math/RayTraceResult;IF)V"))
private void replayModRender_drawSelectionBox(RenderGlobal instance, EntityPlayer player, RayTraceResult rtr, int alwaysZero, float partialTicks) {
if (replayModRender_handler == null) {
instance.drawSelectionBox(player, mop, alwaysZero, partialTicks);
instance.drawSelectionBox(player, rtr, alwaysZero, partialTicks);
}
}

View File

@@ -0,0 +1,47 @@
package com.replaymod.render.mixin;
import com.replaymod.render.hooks.EntityRendererHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.particle.ParticleManager;
import net.minecraft.client.renderer.VertexBuffer;
import net.minecraft.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(ParticleManager.class)
public abstract class MixinParticleManager {
@Redirect(method = "renderParticles", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/Particle;renderParticle(Lnet/minecraft/client/renderer/VertexBuffer;Lnet/minecraft/entity/Entity;FFFFFF)V"))
private void renderNormalParticle(Particle particle, VertexBuffer vertexBuffer, Entity view, float partialTicks,
float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) {
renderParticle(particle, vertexBuffer, view, partialTicks, rotX, rotXZ, rotZ, rotYZ, rotXY);
}
@Redirect(method = "renderLitParticles", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/Particle;renderParticle(Lnet/minecraft/client/renderer/VertexBuffer;Lnet/minecraft/entity/Entity;FFFFFF)V"))
private void renderLitParticle(Particle particle, VertexBuffer vertexBuffer, Entity view, float partialTicks,
float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) {
renderParticle(particle, vertexBuffer, view, partialTicks, rotX, rotXZ, rotZ, rotYZ, rotXY);
}
private void renderParticle(Particle particle, VertexBuffer vertexBuffer, Entity view, float partialTicks,
float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) {
EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) Minecraft.getMinecraft().entityRenderer).replayModRender_getHandler();
if (handler != null && handler.omnidirectional) {
// Align all particles towards the camera
double dx = particle.prevPosX + (particle.posX - particle.prevPosX) * partialTicks - view.posX;
double dy = particle.prevPosY + (particle.posY - particle.prevPosY) * partialTicks - view.posY;
double dz = particle.prevPosZ + (particle.posZ - particle.prevPosZ) * partialTicks - view.posZ;
double pitch = -Math.atan2(dy, Math.sqrt(dx * dx + dz * dz));
double yaw = -Math.atan2(dx, dz);
rotX = (float) Math.cos(yaw);
rotZ = (float) Math.sin(yaw);
rotXZ = (float) Math.cos(pitch);
rotYZ = (float) (-rotZ * Math.sin(pitch));
rotXY = (float) (rotX * Math.sin(pitch));
}
particle.renderParticle(vertexBuffer, view, partialTicks, rotX, rotXZ, rotZ, rotYZ, rotXY);
}
}

View File

@@ -3,16 +3,13 @@ package com.replaymod.render.mixin;
import com.replaymod.render.hooks.ChunkLoadingRenderGlobal;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher;
import net.minecraft.client.renderer.chunk.RenderChunk;
import net.minecraft.client.renderer.culling.ICamera;
import net.minecraft.entity.Entity;
import net.minecraft.util.BlockPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(RenderGlobal.class)
public abstract class MixinRenderGlobal {
@@ -37,22 +34,15 @@ public abstract class MixinRenderGlobal {
do {
setupTerrain(viewEntity, partialTicks, camera, replayModRender_hook.nextFrameId(), playerSpectator);
} while (displayListEntitiesDirty);
displayListEntitiesDirty = true;
replayModRender_hook.updateChunks();
} while (displayListEntitiesDirty);
replayModRender_passThroughSetupTerrain = false;
ci.cancel();
}
}
@Inject(method = "isPositionInRenderChunk", at = @At("HEAD"), cancellable = true)
public void replayModRender_isPositionInRenderChunk(BlockPos pos, RenderChunk chunk, CallbackInfoReturnable<Boolean> ci) {
if (replayModRender_hook != null) {
ci.setReturnValue(true);
}
}
@Inject(method = "updateChunks", at = @At("HEAD"), cancellable = true)
public void replayModRender_updateChunks(long finishTimeNano, CallbackInfo ci) {
if (replayModRender_hook != null) {

View File

@@ -2,17 +2,17 @@ package com.replaymod.render.mixin;
import com.replaymod.render.hooks.EntityRendererHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.entity.RendererLivingEntity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.client.renderer.entity.RenderLiving;
import net.minecraft.entity.EntityLiving;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(RendererLivingEntity.class)
public abstract class MixinRendererLivingEntity {
@Mixin(RenderLiving.class)
public abstract class MixinRenderLiving {
@Inject(method = "canRenderName", at = @At("HEAD"), cancellable = true)
private void replayModRender_areAllNamesHidden(EntityLivingBase entity, CallbackInfoReturnable<Boolean> ci) {
private void replayModRender_areAllNamesHidden(EntityLiving entity, CallbackInfoReturnable<Boolean> ci) {
EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) Minecraft.getMinecraft().entityRenderer).replayModRender_getHandler();
if (handler != null && !handler.getSettings().isRenderNameTags()) {
ci.setReturnValue(false); //this calls the cancel method

View File

@@ -8,7 +8,7 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(RenderManager.class)
public abstract class MixinRenderManager {
@@ -19,7 +19,7 @@ public abstract class MixinRenderManager {
private float playerViewY;
@Inject(method = "doRenderEntity", at = @At("HEAD"))
private void replayModRender_reorientForCubicRendering(Entity entity, double dx, double dy, double dz, float iDoNotKnow, float partialTicks, boolean iDoNotCare, CallbackInfoReturnable ci) {
private void replayModRender_reorientForCubicRendering(Entity entity, double dx, double dy, double dz, float iDoNotKnow, float partialTicks, boolean iDoNotCare, CallbackInfo ci) {
EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) Minecraft.getMinecraft().entityRenderer).replayModRender_getHandler();
if (handler != null && handler.omnidirectional) {
double pitch = -Math.atan2(dy, Math.sqrt(dx * dx + dz * dz));

View File

@@ -1,6 +1,5 @@
package com.replaymod.render.rendering;
import com.replaymod.core.ReplayMod;
import com.replaymod.pathing.player.AbstractTimelinePlayer;
import com.replaymod.pathing.properties.TimestampProperty;
import com.replaymod.render.RenderSettings;
@@ -12,15 +11,15 @@ import com.replaymod.render.gui.GuiRenderingDone;
import com.replaymod.render.gui.GuiVideoRenderer;
import com.replaymod.render.hooks.ChunkLoadingRenderGlobal;
import com.replaymod.render.metadata.MetadataInjector;
import com.replaymod.render.utils.SoundHandler;
import com.replaymod.replay.ReplayHandler;
import com.replaymod.replaystudio.pathing.path.Keyframe;
import com.replaymod.replaystudio.pathing.path.Path;
import com.replaymod.replaystudio.pathing.path.Timeline;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.SoundCategory;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.shader.Framebuffer;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.Timer;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
@@ -51,7 +50,7 @@ public class VideoRenderer implements RenderInfo {
private int fps;
private boolean mouseWasGrabbed;
private boolean debugInfoWasShown;
private Map originalSoundLevels;
private Map<SoundCategory, Float> originalSoundLevels;
private Future<Void> timelinePlayerFuture;
private ChunkLoadingRenderGlobal chunkLoadingRenderGlobal;
@@ -63,9 +62,6 @@ public class VideoRenderer implements RenderInfo {
private boolean paused;
private boolean cancelled;
private Framebuffer guiFramebuffer;
private int displayWidth, displayHeight;
public VideoRenderer(RenderSettings settings, ReplayHandler replayHandler, Timeline timeline) throws IOException {
this.settings = settings;
this.replayHandler = replayHandler;
@@ -134,13 +130,6 @@ public class VideoRenderer implements RenderInfo {
@Override
public float updateForNextFrame() {
// because the jGui lib uses Minecraft's displayWidth and displayHeight values, update these temporarily
int displayWidthBefore = mc.displayWidth;
int displayHeightBefore = mc.displayHeight;
mc.displayWidth = displayWidth;
mc.displayHeight = displayHeight;
if (!settings.isHighPerformance() || framesDone % fps == 0) {
drawGui();
}
@@ -153,10 +142,6 @@ public class VideoRenderer implements RenderInfo {
tick();
}
// change Minecraft's display size back
mc.displayWidth = displayWidthBefore;
mc.displayHeight = displayHeightBefore;
framesDone++;
return mc.timer.renderPartialTicks;
}
@@ -186,9 +171,9 @@ public class VideoRenderer implements RenderInfo {
for (SoundCategory category : SoundCategory.values()) {
mutedSounds.put(category, 0f);
}
originalSoundLevels = mc.gameSettings.mapSoundLevels;
mutedSounds.put(SoundCategory.MASTER, (Float) originalSoundLevels.get(SoundCategory.MASTER));
mc.gameSettings.mapSoundLevels = mutedSounds;
originalSoundLevels = mc.gameSettings.soundLevels;
mutedSounds.put(SoundCategory.MASTER, originalSoundLevels.get(SoundCategory.MASTER));
mc.gameSettings.soundLevels = mutedSounds;
fps = settings.getFramesPerSecond();
@@ -207,15 +192,10 @@ public class VideoRenderer implements RenderInfo {
totalFrames = (int) (duration*fps/1000);
updateDisplaySize();
ScaledResolution scaled = new ScaledResolution(mc, displayWidth, displayHeight);
ScaledResolution scaled = new ScaledResolution(mc);
gui.toMinecraft().setWorldAndResolution(mc, scaled.getScaledWidth(), scaled.getScaledHeight());
chunkLoadingRenderGlobal = new ChunkLoadingRenderGlobal(mc.renderGlobal);
// Set up our own framebuffer to render the GUI to
guiFramebuffer = new Framebuffer(displayWidth, displayHeight, true);
}
private void finish() {
@@ -230,18 +210,15 @@ public class VideoRenderer implements RenderInfo {
if (mouseWasGrabbed) {
mc.mouseHelper.grabMouseCursor();
}
mc.gameSettings.mapSoundLevels = originalSoundLevels;
mc.gameSettings.soundLevels = originalSoundLevels;
mc.displayGuiScreen(null);
if (chunkLoadingRenderGlobal != null) {
chunkLoadingRenderGlobal.uninstall();
}
ReplayMod.soundHandler.playRenderSuccessSound();
new SoundHandler().playRenderSuccessSound();
new GuiRenderingDone(ReplayModRender.instance, videoWriter.getVideoFile(), totalFrames, settings).display();
// Finally, resize the Minecraft framebuffer to the actual width/height of the window
mc.resize(displayWidth, displayHeight);
}
private void tick() {
@@ -261,22 +238,12 @@ public class VideoRenderer implements RenderInfo {
public void drawGui() {
do {
// Resize the GUI framebuffer if the display size changed
if (!settings.isHighPerformance() && displaySizeChanged()) {
updateDisplaySize();
guiFramebuffer.createBindFramebuffer(mc.displayWidth, mc.displayHeight);
}
pushMatrix();
clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
enableTexture2D();
guiFramebuffer.bindFramebuffer(true);
mc.getFramebuffer().bindFramebuffer(true);
mc.entityRenderer.setupOverlayRendering();
ScaledResolution scaled = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight);
gui.toMinecraft().setWorldAndResolution(mc, scaled.getScaledWidth(), scaled.getScaledHeight());
try {
gui.toMinecraft().handleInput();
} catch (IOException e) {
@@ -285,17 +252,18 @@ public class VideoRenderer implements RenderInfo {
throw new RuntimeException(e);
}
ScaledResolution scaled = new ScaledResolution(mc);
int mouseX = Mouse.getX() * scaled.getScaledWidth() / mc.displayWidth;
int mouseY = scaled.getScaledHeight() - Mouse.getY() * scaled.getScaledHeight() / mc.displayHeight - 1;
gui.toMinecraft().drawScreen(mouseX, mouseY, 0);
guiFramebuffer.unbindFramebuffer();
mc.getFramebuffer().unbindFramebuffer();
popMatrix();
pushMatrix();
guiFramebuffer.framebufferRender(displayWidth, displayHeight);
mc.getFramebuffer().framebufferRender(mc.displayWidth, mc.displayHeight);
popMatrix();
// if not in high performance mode, update the gui size if screen size changed
// otherwise just swap the progress gui to screen
if (settings.isHighPerformance()) {
@@ -317,15 +285,6 @@ public class VideoRenderer implements RenderInfo {
} while (paused);
}
private boolean displaySizeChanged() {
return displayWidth != Display.getWidth() || displayHeight != Display.getHeight();
}
private void updateDisplaySize() {
displayWidth = Display.getWidth();
displayHeight = Display.getHeight();
}
public int getFramesDone() {
return framesDone;
}

View File

@@ -2,15 +2,18 @@ package com.replaymod.render.utils;
import com.google.common.base.Preconditions;
import java.util.*;
import java.util.concurrent.BlockingQueue;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;
public class JailingQueue<T> extends AbstractQueue<T> implements BlockingQueue<T> {
private final BlockingQueue<T> delegate;
public class JailingQueue<T> extends PriorityBlockingQueue<T> {
private final PriorityBlockingQueue<T> delegate;
private final Set<Thread> jailed = new HashSet<Thread>();
public JailingQueue(BlockingQueue<T> delegate) {
public JailingQueue(PriorityBlockingQueue<T> delegate) {
this.delegate = delegate;
}
@@ -59,13 +62,13 @@ public class JailingQueue<T> extends AbstractQueue<T> implements BlockingQueue<T
}
@Override
public void put(T t) throws InterruptedException {
public void put(T t) {
tryAccess();
delegate.put(t);
}
@Override
public boolean offer(T t, long timeout, TimeUnit unit) throws InterruptedException {
public boolean offer(T t, long timeout, TimeUnit unit) {
tryAccess();
return delegate.offer(t, timeout, unit);
}

View File

@@ -143,6 +143,7 @@ public class InputReplayTimer extends WrappedTimer {
// Following are a ton of vanilla keyboard shortcuts, some are removed as they're useless in the
// replay viewer as of now
// TODO Update maybe add new key bindings
// TODO: Translate magic values to Keyboard.KEY_ constants
if (key == 32 && Keyboard.isKeyDown(61) && mc.ingameGUI != null) {

View File

@@ -16,8 +16,6 @@ import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Queue;
import java.util.concurrent.FutureTask;
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
@Getter
@@ -45,7 +43,7 @@ public class NoGuiScreenshot {
mc.getFramebuffer().bindFramebuffer(true);
GlStateManager.enableTexture2D();
mc.entityRenderer.updateCameraAndRender(mc.timer.renderPartialTicks);
mc.entityRenderer.updateCameraAndRender(mc.timer.renderPartialTicks, System.nanoTime());
mc.getFramebuffer().unbindFramebuffer();
GlStateManager.popMatrix();
@@ -101,9 +99,7 @@ public class NoGuiScreenshot {
// of the game loop. We cannot use the addScheduledTask method as it'll run the task if called
// from the minecraft thread which is exactly what we want to avoid.
synchronized (mc.scheduledTasks) {
@SuppressWarnings("unchecked")
Queue<FutureTask> queue = mc.scheduledTasks;
queue.add(ListenableFutureTask.create(runnable, null));
mc.scheduledTasks.add(ListenableFutureTask.create(runnable, null));
}
return future;
}

View File

@@ -23,13 +23,16 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.EnumPacketDirection;
import net.minecraft.network.NetworkManager;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.network.handshake.NetworkDispatcher;
import org.lwjgl.opengl.Display;
import java.io.IOException;
import java.util.*;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import static net.minecraft.client.renderer.GlStateManager.*;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
@@ -59,7 +62,7 @@ public class ReplayHandler {
*/
private boolean suppressCameraMovements;
private final List<Marker> markers;
private final Set<Marker> markers;
private final GuiReplayOverlay overlay;
@@ -76,9 +79,9 @@ public class ReplayHandler {
Preconditions.checkState(mc.isCallingFromMinecraftThread(), "Must be called from Minecraft thread.");
this.replayFile = replayFile;
FMLCommonHandler.instance().bus().post(new ReplayOpenEvent.Pre(this));
MinecraftForge.EVENT_BUS.post(new ReplayOpenEvent.Pre(this));
markers = new ArrayList<>(replayFile.getMarkers().or(Collections.emptySet()));
markers = new HashSet<>(replayFile.getMarkers().or(Collections.<Marker>emptySet()));
replaySender = new ReplaySender(this, replayFile, asyncMode);
@@ -87,7 +90,7 @@ public class ReplayHandler {
overlay = new GuiReplayOverlay(this);
overlay.setVisible(true);
FMLCommonHandler.instance().bus().post(new ReplayOpenEvent.Post(this));
MinecraftForge.EVENT_BUS.post(new ReplayOpenEvent.Post(this));
}
void restartedReplay() {
@@ -101,7 +104,7 @@ public class ReplayHandler {
public void endReplay() throws IOException {
Preconditions.checkState(mc.isCallingFromMinecraftThread(), "Must be called from Minecraft thread.");
FMLCommonHandler.instance().bus().post(new ReplayCloseEvent.Pre(this));
MinecraftForge.EVENT_BUS.post(new ReplayCloseEvent.Pre(this));
replaySender.terminateReplay();
@@ -124,7 +127,7 @@ public class ReplayHandler {
ReplayModReplay.instance.replayHandler = null;
FMLCommonHandler.instance().bus().post(new ReplayCloseEvent.Post(this));
MinecraftForge.EVENT_BUS.post(new ReplayCloseEvent.Post(this));
}
private void setup() {
@@ -185,9 +188,9 @@ public class ReplayHandler {
/**
* Returns all markers.
* When changed, {@link #saveMarkers()} should be called to save the changes.
* @return Collection of markers in no particular order
* @return Set of markers
*/
public Collection<Marker> getMarkers() {
public Set<Marker> getMarkers() {
return markers;
}
@@ -196,7 +199,7 @@ public class ReplayHandler {
*/
public void saveMarkers() {
try {
replayFile.writeMarkers(new HashSet<>(markers));
replayFile.writeMarkers(markers);
} catch (IOException e) {
e.printStackTrace();
}
@@ -311,7 +314,7 @@ public class ReplayHandler {
mc.getFramebuffer().bindFramebuffer(true);
mc.entityRenderer.setupOverlayRendering();
ScaledResolution resolution = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight);
ScaledResolution resolution = new ScaledResolution(mc);
guiScreen.setWorldAndResolution(mc, resolution.getScaledWidth(), resolution.getScaledHeight());
guiScreen.drawScreen(0, 0, 0);
@@ -328,10 +331,8 @@ public class ReplayHandler {
replaySender.setAsyncMode(true);
replaySender.setReplaySpeed(0);
mc.getNetHandler().getNetworkManager().processReceivedPackets();
@SuppressWarnings("unchecked")
List<Entity> entities = (List<Entity>) mc.theWorld.loadedEntityList;
for (Entity entity : entities) {
mc.getConnection().getNetworkManager().processReceivedPackets();
for (Entity entity : mc.theWorld.loadedEntityList) {
if (entity instanceof EntityOtherPlayerMP) {
EntityOtherPlayerMP e = (EntityOtherPlayerMP) entity;
e.setPosition(e.otherPlayerMPX, e.otherPlayerMPY, e.otherPlayerMPZ);

View File

@@ -12,17 +12,22 @@ import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityOtherPlayerMP;
import net.minecraft.client.gui.GuiDownloadTerrain;
import net.minecraft.client.gui.GuiErrorScreen;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.*;
import net.minecraft.network.play.server.*;
import net.minecraft.util.IChatComponent;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.World;
import net.minecraft.world.WorldSettings.GameType;
import net.minecraft.world.WorldType;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
@@ -39,30 +44,22 @@ import java.util.concurrent.Callable;
*/
@Sharable
public class ReplaySender extends ChannelInboundHandlerAdapter {
/**
* Previously packets for the client player were inserted using one fixed entity id (this one).
* This is no longer the case however to provide backwards compatibility, we have to convert
* these old packets to use the normal entity id.
* Need to punch someone? -> CrushedPixel
*/
public static final int LEGACY_ENTITY_ID = Integer.MIN_VALUE + 9001;
/**
* These packets are ignored completely during replay.
*/
private static final List<Class> BAD_PACKETS = Arrays.<Class>asList(
S06PacketUpdateHealth.class,
S2DPacketOpenWindow.class,
S2EPacketCloseWindow.class,
S2FPacketSetSlot.class,
S30PacketWindowItems.class,
S36PacketSignEditorOpen.class,
S37PacketStatistics.class,
S1FPacketSetExperience.class,
S43PacketCamera.class,
S39PacketPlayerAbilities.class,
S45PacketTitle.class);
// TODO Update possibly more?
SPacketUpdateHealth.class,
SPacketOpenWindow.class,
SPacketCloseWindow.class,
SPacketSetSlot.class,
SPacketWindowItems.class,
SPacketSignEditorOpen.class,
SPacketStatistics.class,
SPacketSetExperience.class,
SPacketCamera.class,
SPacketPlayerAbilities.class,
SPacketTitle.class);
private static int TP_DISTANCE_LIMIT = 128;
@@ -171,6 +168,8 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
this.asyncMode = asyncMode;
this.replayLength = file.getMetaData().getDuration();
MinecraftForge.EVENT_BUS.register(this);
if (asyncMode) {
new Thread(asyncSender, "replaymod-async-sender").start();
}
@@ -239,6 +238,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
*/
public void terminateReplay() {
terminate = true;
MinecraftForge.EVENT_BUS.unregister(this);
try {
channelInactive(ctx);
ctx.channel().pipeline().close();
@@ -247,6 +247,25 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
}
}
@SubscribeEvent
public void onWorldTick(TickEvent.ClientTickEvent event) {
// Unfortunately the WorldTickEvent doesn't seem to be emitted on the CLIENT side
if (event.phase != TickEvent.Phase.START) return;
// Spawning a player into an empty chunk (which we might do with the recording player)
// prevents it from being moved by teleport packets (it essentially gets stuck) because
// Entity#addedToChunk is not set and it is therefore not updated every tick.
// To counteract this, we need to manually update it's position if it hasn't been added
// to any chunk yet.
if (mc.theWorld != null) {
for (EntityPlayer playerEntity : mc.theWorld.playerEntities) {
if (!playerEntity.addedToChunk && playerEntity instanceof EntityOtherPlayerMP) {
playerEntity.onLivingUpdate();
}
}
}
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
@@ -274,21 +293,21 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
// Therefore we have to remove all loaded, dead entities manually if we are in sync mode.
// We do this after every SpawnX packet and after the destroy entities packet.
if (!asyncMode && mc.theWorld != null) {
if (p instanceof S0CPacketSpawnPlayer
|| p instanceof S0EPacketSpawnObject
|| p instanceof S0FPacketSpawnMob
|| p instanceof S2CPacketSpawnGlobalEntity
|| p instanceof S10PacketSpawnPainting
|| p instanceof S11PacketSpawnExperienceOrb
|| p instanceof S13PacketDestroyEntities) {
if (p instanceof SPacketSpawnPlayer
|| p instanceof SPacketSpawnObject
|| p instanceof SPacketSpawnMob
|| p instanceof SPacketSpawnGlobalEntity
|| p instanceof SPacketSpawnPainting
|| p instanceof SPacketSpawnExperienceOrb
|| p instanceof SPacketDestroyEntities) {
World world = mc.theWorld;
for (int i = 0; i < world.loadedEntityList.size(); ++i) {
Entity entity = (Entity) world.loadedEntityList.get(i);
Entity entity = world.loadedEntityList.get(i);
if (entity.isDead) {
int chunkX = entity.chunkCoordX;
int chunkY = entity.chunkCoordZ;
if (entity.addedToChunk && world.getChunkProvider().chunkExists(chunkX, chunkY)) {
if (entity.addedToChunk && world.getChunkProvider().getLoadedChunk(chunkX, chunkY) != null) {
world.getChunkFromChunkCoords(chunkX, chunkY).removeEntity(entity);
}
@@ -326,8 +345,8 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
* @return The processed packet or {@code null} if no packet shall be sent
*/
protected Packet processPacket(Packet p) throws Exception {
if (p instanceof S3FPacketCustomPayload) {
S3FPacketCustomPayload packet = (S3FPacketCustomPayload) p;
if (p instanceof SPacketCustomPayload) {
SPacketCustomPayload packet = (SPacketCustomPayload) p;
if (Restrictions.PLUGIN_CHANNEL.equals(packet.getChannelName())) {
final String unknown = replayHandler.getRestrictions().handle(packet);
if (unknown == null) {
@@ -353,8 +372,8 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
}
}
}
if (p instanceof S40PacketDisconnect) {
IChatComponent reason = ((S40PacketDisconnect) p).func_149165_c();
if (p instanceof SPacketDisconnect) {
ITextComponent reason = ((SPacketDisconnect) p).getReason();
if ("Please update to view this replay.".equals(reason.getUnformattedText())) {
// This version of the mod supports replay restrictions so we are allowed
// to remove this packet.
@@ -364,11 +383,9 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
if(BAD_PACKETS.contains(p.getClass())) return null;
convertLegacyEntityIds(p);
if(p instanceof S48PacketResourcePackSend) {
S48PacketResourcePackSend packet = (S48PacketResourcePackSend) p;
String url = packet.func_179783_a();
if(p instanceof SPacketResourcePackSend) {
SPacketResourcePackSend packet = (SPacketResourcePackSend) p;
String url = packet.getURL();
if (url.startsWith("replay://")) {
int id = Integer.parseInt(url.substring("replay://".length()));
Map<Integer, String> index = replayFile.getResourcePackIndex();
@@ -379,17 +396,17 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
if (!file.exists()) {
IOUtils.copy(replayFile.getResourcePack(hash).get(), new FileOutputStream(file));
}
mc.getResourcePackRepository().func_177319_a(file);
mc.getResourcePackRepository().setResourcePackInstance(file);
}
}
return null;
}
}
if(p instanceof S01PacketJoinGame) {
S01PacketJoinGame packet = (S01PacketJoinGame) p;
if(p instanceof SPacketJoinGame) {
SPacketJoinGame packet = (SPacketJoinGame) p;
allowMovement = true;
int entId = packet.getEntityId();
int entId = packet.getPlayerId();
actualID = entId;
entId = -1789435; // Camera entity id should be negative which is an invalid id and can't be used by servers
int dimension = packet.getDimension();
@@ -397,21 +414,21 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
int maxPlayers = packet.getMaxPlayers();
WorldType worldType = packet.getWorldType();
p = new S01PacketJoinGame(entId, GameType.SPECTATOR, false, dimension,
p = new SPacketJoinGame(entId, GameType.SPECTATOR, false, dimension,
difficulty, maxPlayers, worldType, false);
}
if(p instanceof S07PacketRespawn) {
S07PacketRespawn respawn = (S07PacketRespawn) p;
p = new S07PacketRespawn(respawn.func_149082_c(),
respawn.func_149081_d(), respawn.func_149080_f(), GameType.SPECTATOR);
if(p instanceof SPacketRespawn) {
SPacketRespawn respawn = (SPacketRespawn) p;
p = new SPacketRespawn(respawn.getDimensionID(),
respawn.getDifficulty(), respawn.getWorldType(), GameType.SPECTATOR);
allowMovement = true;
}
if(p instanceof S08PacketPlayerPosLook) {
if(p instanceof SPacketPlayerPosLook) {
if(!hasWorldLoaded) hasWorldLoaded = true;
final S08PacketPlayerPosLook ppl = (S08PacketPlayerPosLook) p;
final SPacketPlayerPosLook ppl = (SPacketPlayerPosLook) p;
if (mc.currentScreen instanceof GuiDownloadTerrain) {
// Close the world loading screen manually in case we swallow the packet
@@ -422,17 +439,17 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
CameraEntity cent = replayHandler.getCameraEntity();
for (Object relative : ppl.func_179834_f()) {
if (relative == S08PacketPlayerPosLook.EnumFlags.X
|| relative == S08PacketPlayerPosLook.EnumFlags.Y
|| relative == S08PacketPlayerPosLook.EnumFlags.Z) {
for (SPacketPlayerPosLook.EnumFlags relative : ppl.getFlags()) {
if (relative == SPacketPlayerPosLook.EnumFlags.X
|| relative == SPacketPlayerPosLook.EnumFlags.Y
|| relative == SPacketPlayerPosLook.EnumFlags.Z) {
return null; // At least one of the coordinates is relative, so we don't care
}
}
if(cent != null) {
if(!allowMovement && !((Math.abs(cent.posX - ppl.func_148932_c()) > TP_DISTANCE_LIMIT) ||
(Math.abs(cent.posZ - ppl.func_148933_e()) > TP_DISTANCE_LIMIT))) {
if(!allowMovement && !((Math.abs(cent.posX - ppl.getX()) > TP_DISTANCE_LIMIT) ||
(Math.abs(cent.posZ - ppl.getZ()) > TP_DISTANCE_LIMIT))) {
return null;
} else {
allowMovement = false;
@@ -451,15 +468,15 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
}
CameraEntity cent = replayHandler.getCameraEntity();
cent.setCameraPosition(ppl.func_148932_c(), ppl.func_148928_d(), ppl.func_148933_e());
cent.setCameraPosition(ppl.getX(), ppl.getY(), ppl.getZ());
return null;
}
}.call();
}
if(p instanceof S2BPacketChangeGameState) {
S2BPacketChangeGameState pg = (S2BPacketChangeGameState)p;
int reason = pg.func_149138_c();
if(p instanceof SPacketChangeGameState) {
SPacketChangeGameState pg = (SPacketChangeGameState)p;
int reason = pg.getGameState();
// only allow the following packets:
// 1 - End raining
@@ -473,7 +490,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
}
}
if (p instanceof S02PacketChat) {
if (p instanceof SPacketChat) {
if (!ReplayModReplay.instance.getCore().getSettingsRegistry().get(Setting.SHOW_CHAT)) {
return null;
}
@@ -486,7 +503,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
@SuppressWarnings("unchecked")
public void channelActive(ChannelHandlerContext ctx) throws Exception {
this.ctx = ctx;
ctx.attr(NetworkManager.attrKeyConnectionState).set(EnumConnectionState.PLAY);
ctx.attr(NetworkManager.PROTOCOL_ATTRIBUTE_KEY).set(EnumConnectionState.PLAY);
super.channelActive(ctx);
}
@@ -691,11 +708,11 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
protected Packet processPacketAsync(Packet p) {
//If hurrying, ignore some packets, except for short durations
if(desiredTimeStamp - lastTimeStamp > 1000) {
if(p instanceof S2APacketParticles) return null;
if(p instanceof SPacketParticles) return null;
if(p instanceof S0EPacketSpawnObject) {
S0EPacketSpawnObject pso = (S0EPacketSpawnObject)p;
int type = pso.func_148993_l();
if(p instanceof SPacketSpawnObject) {
SPacketSpawnObject pso = (SPacketSpawnObject)p;
int type = pso.getType();
if(type == 76) { // Firework rocket
return null;
}
@@ -781,68 +798,6 @@ public class ReplaySender extends ChannelInboundHandlerAdapter {
return p; // During synchronous playback everything is sent normally
}
/**
* This is necessary to convert packets from old replays to new replays.
* @param packet The packet to be transformed.
* @see #LEGACY_ENTITY_ID
*/
private void convertLegacyEntityIds(Packet packet) {
if (packet instanceof S0CPacketSpawnPlayer) {
S0CPacketSpawnPlayer p = (S0CPacketSpawnPlayer) packet;
if (p.field_148957_a == LEGACY_ENTITY_ID) {
p.field_148957_a = actualID;
}
} else if (packet instanceof S18PacketEntityTeleport) {
S18PacketEntityTeleport p = (S18PacketEntityTeleport) packet;
if (p.field_149458_a == LEGACY_ENTITY_ID) {
p.field_149458_a = actualID;
}
} else if (packet instanceof S14PacketEntity.S17PacketEntityLookMove) {
S14PacketEntity.S17PacketEntityLookMove p = (S14PacketEntity.S17PacketEntityLookMove) packet;
if (p.field_149074_a == LEGACY_ENTITY_ID) {
p.field_149074_a = actualID;
}
} else if (packet instanceof S19PacketEntityHeadLook) {
S19PacketEntityHeadLook p = (S19PacketEntityHeadLook) packet;
if (p.field_149384_a == LEGACY_ENTITY_ID) {
p.field_149384_a = actualID;
}
} else if (packet instanceof S12PacketEntityVelocity) {
S12PacketEntityVelocity p = (S12PacketEntityVelocity) packet;
if (p.field_149417_a == LEGACY_ENTITY_ID) {
p.field_149417_a = actualID;
}
} else if (packet instanceof S0BPacketAnimation) {
S0BPacketAnimation p = (S0BPacketAnimation) packet;
if (p.entityId == LEGACY_ENTITY_ID) {
p.entityId = actualID;
}
} else if (packet instanceof S04PacketEntityEquipment) {
S04PacketEntityEquipment p = (S04PacketEntityEquipment) packet;
if (p.field_149394_a == LEGACY_ENTITY_ID) {
p.field_149394_a = actualID;
}
} else if (packet instanceof S1BPacketEntityAttach) {
S1BPacketEntityAttach p = (S1BPacketEntityAttach) packet;
if (p.field_149408_a == LEGACY_ENTITY_ID) {
p.field_149408_a = actualID;
}
if (p.field_149406_b == LEGACY_ENTITY_ID) {
p.field_149406_b = actualID;
}
} else if (packet instanceof S0DPacketCollectItem) {
S0DPacketCollectItem p = (S0DPacketCollectItem) packet;
if (p.field_149356_b == LEGACY_ENTITY_ID) {
p.field_149356_b = actualID;
}
} else if (packet instanceof S13PacketDestroyEntities) {
S13PacketDestroyEntities p = (S13PacketDestroyEntities) packet;
if (p.field_149100_a.length == 1 && p.field_149100_a[0] == LEGACY_ENTITY_ID) {
p.field_149100_a[0] = actualID;
}
}
}
private static final class PacketData {
private final int timestamp;
private final byte[] bytes;

View File

@@ -10,7 +10,6 @@ import lombok.Getter;
import lombok.Setter;
import net.minecraft.block.material.Material;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.AbstractClientPlayer;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.client.settings.KeyBinding;
@@ -18,16 +17,17 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.item.EntityItemFrame;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.stats.StatFileWriter;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.stats.StatisticsManager;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
import net.minecraftforge.client.event.EntityViewRenderEvent;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.client.event.RenderHandEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
@@ -65,9 +65,8 @@ public class CameraEntity extends EntityPlayerSP {
*/
private final EventHandler eventHandler = new EventHandler();
public CameraEntity(Minecraft mcIn, World worldIn, NetHandlerPlayClient netHandlerPlayClient, StatFileWriter statFileWriter) {
super(mcIn, worldIn, netHandlerPlayClient, statFileWriter);
FMLCommonHandler.instance().bus().register(eventHandler);
public CameraEntity(Minecraft mcIn, World worldIn, NetHandlerPlayClient netHandlerPlayClient, StatisticsManager statisticsManager) {
super(mcIn, worldIn, netHandlerPlayClient, statisticsManager);
MinecraftForge.EVENT_BUS.register(eventHandler);
cameraController = ReplayModReplay.instance.createCameraController(this);
}
@@ -238,14 +237,6 @@ public class CameraEntity extends EntityPlayerSP {
return ReplayModReplay.instance.getReplayHandler().isCameraView(); // Make sure we're treated as spectator
}
@Override
public boolean shouldRenderInPass(int pass) {
// Never render the camera
// This is necessary to hide the player head in third person mode and to not
// cause any unwanted shadows when rendering with shaders.
return false;
}
@Override
public ResourceLocation getLocationSkin() {
Entity view = mc.getRenderViewEntity();
@@ -255,15 +246,6 @@ public class CameraEntity extends EntityPlayerSP {
return super.getLocationSkin();
}
@Override
public String getSkinType() {
Entity view = mc.getRenderViewEntity();
if (view != this && view instanceof AbstractClientPlayer) {
return ((AbstractClientPlayer) view).getSkinType();
}
return super.getSkinType();
}
@Override
public float getSwingProgress(float renderPartialTicks) {
Entity view = mc.getRenderViewEntity();
@@ -274,12 +256,49 @@ public class CameraEntity extends EntityPlayerSP {
}
@Override
public MovingObjectPosition rayTrace(double p_174822_1_, float p_174822_3_) {
MovingObjectPosition pos = super.rayTrace(p_174822_1_, 1f);
public float getCooldownPeriod() {
Entity view = mc.getRenderViewEntity();
if (view != this && view instanceof EntityPlayer) {
return ((EntityPlayer) view).getCooldownPeriod();
}
return 1;
}
@Override
public float getCooledAttackStrength(float adjustTicks) {
Entity view = mc.getRenderViewEntity();
if (view != this && view instanceof EntityPlayer) {
return ((EntityPlayer) view).getCooledAttackStrength(adjustTicks);
}
// Default to 1 as to not render the cooldown indicator (renders for < 1)
return 1;
}
@Override
public EnumHand getActiveHand() {
Entity view = mc.getRenderViewEntity();
if (view != this && view instanceof EntityPlayer) {
return ((EntityPlayer) view).getActiveHand();
}
return super.getActiveHand();
}
@Override
public boolean isHandActive() {
Entity view = mc.getRenderViewEntity();
if (view != this && view instanceof EntityPlayer) {
return ((EntityPlayer) view).isHandActive();
}
return super.isHandActive();
}
@Override
public RayTraceResult rayTrace(double p_174822_1_, float p_174822_3_) {
RayTraceResult pos = super.rayTrace(p_174822_1_, 1f);
// Make sure we can never look at blocks (-> no outline)
if(pos != null && pos.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
pos.typeOfHit = MovingObjectPosition.MovingObjectType.MISS;
if(pos != null && pos.typeOfHit == RayTraceResult.Type.BLOCK) {
pos.typeOfHit = RayTraceResult.Type.MISS;
}
return pos;
@@ -288,7 +307,6 @@ public class CameraEntity extends EntityPlayerSP {
@Override
public void setDead() {
super.setDead();
FMLCommonHandler.instance().bus().unregister(eventHandler);
MinecraftForge.EVENT_BUS.unregister(eventHandler);
}
@@ -346,9 +364,13 @@ public class CameraEntity extends EntityPlayerSP {
@SubscribeEvent
public void preCrosshairRender(RenderGameOverlayEvent.Pre event) {
// The crosshair should only render if targeted entity can actually be spectated
if (event.type == RenderGameOverlayEvent.ElementType.CROSSHAIRS) {
if (event.getType() == RenderGameOverlayEvent.ElementType.CROSSHAIRS) {
event.setCanceled(!canSpectate(mc.pointedEntity));
}
// Hotbar should never be rendered
if (event.getType() == RenderGameOverlayEvent.ElementType.HOTBAR) {
event.setCanceled(true);
}
}
@SubscribeEvent
@@ -375,10 +397,13 @@ public class CameraEntity extends EntityPlayerSP {
if (lastHandRendered != player) {
lastHandRendered = player;
mc.entityRenderer.itemRenderer.prevEquippedProgress = 1;
mc.entityRenderer.itemRenderer.equippedProgress = 1;
mc.entityRenderer.itemRenderer.itemToRender = player.inventory.getCurrentItem();
mc.entityRenderer.itemRenderer.equippedItemSlot = player.inventory.currentItem;
mc.entityRenderer.itemRenderer.prevEquippedProgressMainHand = 1;
mc.entityRenderer.itemRenderer.prevEquippedProgressOffHand = 1;
mc.entityRenderer.itemRenderer.equippedProgressMainHand = 1;
mc.entityRenderer.itemRenderer.equippedProgressOffHand = 1;
mc.entityRenderer.itemRenderer.itemStackMainHand = player.getItemStackFromSlot(EntityEquipmentSlot.MAINHAND);
mc.entityRenderer.itemRenderer.itemStackOffHand = player.getItemStackFromSlot(EntityEquipmentSlot.OFFHAND);
mc.thePlayer.renderArmYaw = mc.thePlayer.prevRenderArmYaw = player.rotationYaw;
mc.thePlayer.renderArmPitch = mc.thePlayer.prevRenderArmPitch = player.rotationPitch;
@@ -389,7 +414,7 @@ public class CameraEntity extends EntityPlayerSP {
@SubscribeEvent
public void onEntityViewRenderEvent(EntityViewRenderEvent.CameraSetup event) {
if (mc.getRenderViewEntity() == CameraEntity.this) {
event.roll = roll;
event.setRoll(roll);
}
}
}

View File

@@ -2,8 +2,8 @@ package com.replaymod.replay.camera;
import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.util.MathHelper;
import net.minecraft.util.Vec3;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import org.lwjgl.Sys;
// TODO: Marius is responsible for this. Please, someone clean it up.
@@ -18,8 +18,8 @@ public class ClassicCameraController implements CameraController {
private double THRESHOLD = MAX_SPEED / 20;
private double DECAY = MAX_SPEED/3;
private Vec3 direction;
private Vec3 dirBefore;
private Vec3d direction;
private Vec3d dirBefore;
private double motion;
private long lastCall = Sys.getTime();
@@ -129,7 +129,7 @@ public class ClassicCameraController implements CameraController {
return;
}
Vec3 movement = direction.normalize();
Vec3d movement = direction.normalize();
double factor = motion * (frac / 1000D);
camera.moveCamera(movement.xCoord * factor, movement.yCoord * factor, movement.zCoord * factor);
@@ -158,7 +158,7 @@ public class ClassicCameraController implements CameraController {
break;
}
Vec3 dbf = direction;
Vec3d dbf = direction;
if(dirBefore != null) {
direction = dirBefore.normalize().add(direction);
@@ -169,12 +169,12 @@ public class ClassicCameraController implements CameraController {
updateMovement();
}
private Vec3 getVectorForRotation(float pitch, float yaw) {
private Vec3d getVectorForRotation(float pitch, float yaw) {
float f2 = MathHelper.cos(-yaw * 0.017453292F - (float) Math.PI);
float f3 = MathHelper.sin(-yaw * 0.017453292F - (float)Math.PI);
float f4 = -MathHelper.cos(-pitch * 0.017453292F);
float f5 = MathHelper.sin(-pitch * 0.017453292F);
return new Vec3((double)(f3 * f4), (double)f5, (double)(f2 * f4));
return new Vec3d((double)(f3 * f4), (double)f5, (double)(f2 * f4));
}
public enum MoveDirection {

View File

@@ -41,8 +41,9 @@ public class SpectatorCameraController implements CameraController {
if (view instanceof EntityPlayer) {
EntityPlayer viewPlayer = (EntityPlayer) view;
camera.inventory = viewPlayer.inventory;
camera.itemInUse = viewPlayer.itemInUse;
camera.itemInUseCount = viewPlayer.itemInUseCount;
camera.itemStackMainHand = viewPlayer.itemStackMainHand;
camera.swingingHand = viewPlayer.swingingHand;
camera.activeItemStackUseCount = viewPlayer.activeItemStackUseCount;
}
}
}

View File

@@ -5,17 +5,14 @@ import com.replaymod.replay.ReplayHandler;
import de.johni0702.minecraft.gui.container.GuiContainer;
import de.johni0702.minecraft.gui.container.GuiPanel;
import de.johni0702.minecraft.gui.element.*;
import de.johni0702.minecraft.gui.function.Typeable;
import de.johni0702.minecraft.gui.layout.GridLayout;
import de.johni0702.minecraft.gui.layout.HorizontalLayout;
import de.johni0702.minecraft.gui.layout.VerticalLayout;
import de.johni0702.minecraft.gui.popup.AbstractGuiPopup;
import de.johni0702.minecraft.gui.utils.Colors;
import com.replaymod.replaystudio.data.Marker;
import org.lwjgl.input.Keyboard;
import org.lwjgl.util.ReadablePoint;
public class GuiEditMarkerPopup extends AbstractGuiPopup<GuiEditMarkerPopup> implements Typeable {
public class GuiEditMarkerPopup extends AbstractGuiPopup<GuiEditMarkerPopup> {
private final ReplayHandler replayHandler;
private final Marker marker;
@@ -110,13 +107,4 @@ public class GuiEditMarkerPopup extends AbstractGuiPopup<GuiEditMarkerPopup> imp
protected GuiEditMarkerPopup getThis() {
return this;
}
@Override
public boolean typeKey(ReadablePoint mousePosition, int keyCode, char keyChar, boolean ctrlDown, boolean shiftDown) {
if (keyCode == Keyboard.KEY_ESCAPE) {
cancelButton.onClick();
return true;
}
return false;
}
}

View File

@@ -2,14 +2,14 @@ package com.replaymod.replay.gui.overlay;
import com.replaymod.core.ReplayMod;
import com.replaymod.replay.ReplayHandler;
import com.replaymod.replaystudio.data.Marker;
import com.replaymod.replaystudio.util.Location;
import de.johni0702.minecraft.gui.GuiRenderer;
import de.johni0702.minecraft.gui.RenderInfo;
import de.johni0702.minecraft.gui.element.advanced.AbstractGuiTimeline;
import de.johni0702.minecraft.gui.function.Draggable;
import com.replaymod.replaystudio.data.Marker;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.MathHelper;
import net.minecraft.util.math.MathHelper;
import org.lwjgl.util.Point;
import org.lwjgl.util.ReadableDimension;
import org.lwjgl.util.ReadablePoint;
@@ -133,8 +133,6 @@ public class GuiMarkerTimeline extends AbstractGuiTimeline<GuiMarkerTimeline> im
replayHandler.doJump(marker.getTime(), false);
}
return true;
} else {
selectedMarker = null;
}
return super.mouseClick(position, button);
}

View File

@@ -7,16 +7,14 @@ 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.GuiElement;
import de.johni0702.minecraft.gui.element.GuiSlider;
import de.johni0702.minecraft.gui.element.GuiTexturedButton;
import de.johni0702.minecraft.gui.element.GuiTooltip;
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.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.InputEvent;
import org.lwjgl.util.ReadableDimension;
@@ -29,20 +27,8 @@ public class GuiReplayOverlay extends AbstractGuiOverlay<GuiReplayOverlay> {
public final GuiPanel topPanel = new GuiPanel(this)
.setLayout(new HorizontalLayout(HorizontalLayout.Alignment.LEFT).setSpacing(5));
public final GuiTexturedButton playPauseButton = new GuiTexturedButton() {
@Override
public GuiElement getTooltip(RenderInfo renderInfo) {
GuiTooltip tooltip = (GuiTooltip) super.getTooltip(renderInfo);
if (tooltip != null) {
if (getTextureNormal().getY() == 0) { // Play button
tooltip.setI18nText("replaymod.gui.ingame.menu.unpause");
} else { // Pause button
tooltip.setI18nText("replaymod.gui.ingame.menu.pause");
}
}
return tooltip;
}
}.setSize(20, 20).setTexture(ReplayMod.TEXTURE, TEXTURE_SIZE).setTooltip(new GuiTooltip());
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 GuiMarkerTimeline timeline;
@@ -137,9 +123,9 @@ public class GuiReplayOverlay extends AbstractGuiOverlay<GuiReplayOverlay> {
public void setVisible(boolean visible) {
if (isVisible() != visible) {
if (visible) {
FMLCommonHandler.instance().bus().register(this);
MinecraftForge.EVENT_BUS.register(this);
} else {
FMLCommonHandler.instance().bus().unregister(this);
MinecraftForge.EVENT_BUS.unregister(this);
}
}
super.setVisible(visible);

View File

@@ -6,12 +6,7 @@ import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.mojang.realmsclient.gui.ChatFormatting;
import com.replaymod.core.gui.GuiReplaySettings;
import com.replaymod.core.utils.Utils;
import com.replaymod.replay.ReplayModReplay;
import com.replaymod.replaystudio.replay.ReplayFile;
import com.replaymod.replaystudio.replay.ReplayMetaData;
import com.replaymod.replaystudio.replay.ZipReplayFile;
import com.replaymod.replaystudio.studio.ReplayStudio;
import de.johni0702.minecraft.gui.container.AbstractGuiContainer;
import de.johni0702.minecraft.gui.container.GuiContainer;
import de.johni0702.minecraft.gui.container.GuiPanel;
@@ -25,6 +20,11 @@ import de.johni0702.minecraft.gui.layout.VerticalLayout;
import de.johni0702.minecraft.gui.popup.GuiYesNoPopup;
import de.johni0702.minecraft.gui.utils.Colors;
import de.johni0702.minecraft.gui.utils.Consumer;
import com.replaymod.replaystudio.replay.ReplayFile;
import com.replaymod.replaystudio.replay.ReplayMetaData;
import com.replaymod.replaystudio.replay.ZipReplayFile;
import com.replaymod.replaystudio.studio.ReplayStudio;
import com.replaymod.core.utils.Utils;
import net.minecraft.client.gui.GuiErrorScreen;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.Util;
@@ -54,9 +54,6 @@ public class GuiReplayViewer extends GuiScreen {
@Override
public void run() {
replayButtonPanel.forEach(IGuiButton.class).setEnabled(list.getSelected() != null);
if (list.getSelected() != null && list.getSelected().incompatible) {
loadButton.setDisabled();
}
}
}).onLoad(new Consumer<Consumer<Supplier<GuiReplayEntry>>> () {
@Override
@@ -98,12 +95,6 @@ public class GuiReplayViewer extends GuiScreen {
e.printStackTrace();
}
}
}).onSelectionDoubleClicked(() -> {
if (this.loadButton.isEnabled()) {
this.loadButton.onClick();
// Disable load button to prevent the player from opening the replay twice at the same time
this.loadButton.setDisabled();
}
}).setDrawShadow(true).setDrawSlider(true);
public final GuiButton loadButton = new GuiButton().onClick(new Runnable() {
@@ -279,7 +270,6 @@ public class GuiReplayViewer extends GuiScreen {
public final GuiLabel date = new GuiLabel().setColor(Colors.LIGHT_GRAY);
public final GuiPanel infoPanel = new GuiPanel(this).setLayout(new VerticalLayout().setSpacing(2))
.addElements(null, name, server, date);
public final GuiLabel version = new GuiLabel(this).setColor(Colors.RED);
public final GuiImage thumbnail;
public final GuiLabel duration = new GuiLabel();
public final GuiPanel durationPanel = new GuiPanel().setBackgroundColor(Colors.HALF_TRANSPARENT)
@@ -297,7 +287,6 @@ public class GuiReplayViewer extends GuiScreen {
});
private final long dateMillis;
private final boolean incompatible;
public GuiReplayEntry(File file, ReplayMetaData metaData, BufferedImage thumbImage) {
this.file = file;
@@ -308,10 +297,6 @@ public class GuiReplayViewer extends GuiScreen {
} else {
server.setText(metaData.getServerName());
}
incompatible = !new ReplayStudio().isCompatible(metaData.getFileFormatVersion());
if (incompatible) {
version.setText("Minecraft " + metaData.getMcVersion());
}
dateMillis = metaData.getDate();
date.setText(new SimpleDateFormat().format(new Date(dateMillis)));
if (thumbImage == null) {
@@ -331,7 +316,6 @@ public class GuiReplayViewer extends GuiScreen {
y(durationPanel, height(thumbnail) - height(durationPanel));
pos(infoPanel, width(thumbnail) + 5, 0);
pos(version, width - width(version), 0);
}
@Override

View File

@@ -9,12 +9,10 @@ import net.minecraft.client.gui.GuiMainMenu;
import net.minecraft.client.resources.I18n;
import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class GuiHandler {
private static final int BUTTON_EXIT_SERVER = 1;
@@ -35,13 +33,12 @@ public class GuiHandler {
}
public void register() {
FMLCommonHandler.instance().bus().register(this);
MinecraftForge.EVENT_BUS.register(this);
}
@SubscribeEvent
public void injectIntoIngameMenu(GuiScreenEvent.InitGuiEvent.Post event) {
if (!(event.gui instanceof GuiIngameMenu)) {
if (!(event.getGui() instanceof GuiIngameMenu)) {
return;
}
@@ -49,9 +46,7 @@ public class GuiHandler {
// Pause replay when menu is opened
mod.getReplayHandler().getReplaySender().setReplaySpeed(0);
@SuppressWarnings("unchecked")
List<GuiButton> buttonList = event.buttonList;
for(GuiButton b : new ArrayList<>(buttonList)) {
for(GuiButton b : new ArrayList<>(event.getButtonList())) {
switch (b.id) {
// Replace "Exit Server" button with "Exit Replay" button
case BUTTON_EXIT_SERVER:
@@ -62,7 +57,7 @@ public class GuiHandler {
case BUTTON_ACHIEVEMENTS:
case BUTTON_STATS:
case BUTTON_OPEN_TO_LAN:
buttonList.remove(b);
event.getButtonList().remove(b);
}
// Move all buttons except the "Return to game" button upwards
if (b.id != BUTTON_RETURN_TO_GAME) {
@@ -74,31 +69,29 @@ public class GuiHandler {
@SubscribeEvent
public void injectIntoMainMenu(GuiScreenEvent.InitGuiEvent event) {
if (!(event.gui instanceof GuiMainMenu)) {
if (!(event.getGui() instanceof GuiMainMenu)) {
return;
}
@SuppressWarnings("unchecked")
List<GuiButton> buttonList = event.buttonList;
GuiButton button = new GuiButton(BUTTON_REPLAY_VIEWER, event.gui.width / 2 - 100,
event.gui.height / 4 + 10 + 3 * 24, I18n.format("replaymod.gui.replayviewer"));
GuiButton button = new GuiButton(BUTTON_REPLAY_VIEWER, event.getGui().width / 2 - 100,
event.getGui().height / 4 + 10 + 3 * 24, I18n.format("replaymod.gui.replayviewer"));
button.width = button.width / 2 - 2;
buttonList.add(button);
event.getButtonList().add(button);
}
@SubscribeEvent
public void onButton(GuiScreenEvent.ActionPerformedEvent.Pre event) {
if(!event.button.enabled) return;
if(!event.getButton().enabled) return;
if (event.gui instanceof GuiMainMenu) {
if (event.button.id == BUTTON_REPLAY_VIEWER) {
if (event.getGui() instanceof GuiMainMenu) {
if (event.getButton().id == BUTTON_REPLAY_VIEWER) {
new GuiReplayViewer(mod).display();
}
}
if (event.gui instanceof GuiIngameMenu && mod.getReplayHandler() != null) {
if (event.button.id == BUTTON_EXIT_REPLAY) {
event.button.enabled = false;
if (event.getGui() instanceof GuiIngameMenu && mod.getReplayHandler() != null) {
if (event.getButton().id == BUTTON_EXIT_REPLAY) {
event.getButton().enabled = false;
mc.displayGuiScreen(new GuiMainMenu());
try {
mod.getReplayHandler().endReplay();

View File

@@ -12,12 +12,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(GuiSpectator.class)
public abstract class MixinGuiSpectator {
@Shadow
private Minecraft field_175268_g;
private Minecraft mc;
@Inject(method = "func_175260_a", at = @At("HEAD"), cancellable = true)
@Inject(method = "onHotbarSelected", at = @At("HEAD"), cancellable = true)
public void isInReplay(int i, CallbackInfo ci) {
// Prevent spectator gui from opening while in a replay
if (field_175268_g.thePlayer instanceof CameraEntity) {
if (mc.thePlayer instanceof CameraEntity) {
ci.cancel();
}
}

View File

@@ -1,12 +1,12 @@
package com.replaymod.replay.mixin;
import com.replaymod.replay.camera.CameraEntity;
import com.replaymod.replay.ReplayModReplay;
import com.replaymod.replay.camera.CameraEntity;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.multiplayer.PlayerControllerMP;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.stats.StatFileWriter;
import net.minecraft.stats.StatisticsManager;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -21,12 +21,12 @@ public abstract class MixinPlayerControllerMP {
private Minecraft mc;
@Shadow
private NetHandlerPlayClient netClientHandler;
private NetHandlerPlayClient connection;
@Inject(method = "func_178892_a", at=@At("HEAD"), cancellable = true)
private void replayModReplay_createReplayCamera(World worldIn, StatFileWriter statFileWriter, CallbackInfoReturnable<EntityPlayerSP> ci) {
@Inject(method = "createClientPlayer", at=@At("HEAD"), cancellable = true)
private void replayModReplay_createReplayCamera(World worldIn, StatisticsManager statisticsManager, CallbackInfoReturnable<EntityPlayerSP> ci) {
if (ReplayModReplay.instance.getReplayHandler() != null) {
ci.setReturnValue(new CameraEntity(mc, worldIn, netClientHandler, statFileWriter));
ci.setReturnValue(new CameraEntity(mc, worldIn, connection, statisticsManager));
ci.cancel();
}
}

View File

@@ -2,7 +2,7 @@ package com.replaymod.replay.mixin;
import com.replaymod.replay.camera.CameraEntity;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.entity.ArmorStandRenderer;
import net.minecraft.client.renderer.entity.RenderArmorStand;
import net.minecraft.entity.item.EntityArmorStand;
import net.minecraft.entity.player.EntityPlayer;
import org.spongepowered.asm.mixin.Mixin;
@@ -10,9 +10,9 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ArmorStandRenderer.class)
public abstract class MixinArmorStandRenderer {
@Inject(method = "func_177099_b", at = @At("HEAD"), cancellable = true)
@Mixin(RenderArmorStand.class)
public abstract class MixinRenderArmorStand {
@Inject(method = "canRenderName", at = @At("HEAD"), cancellable = true)
private void replayModReplay_canRenderInvisibleName(EntityArmorStand entity, CallbackInfoReturnable<Boolean> ci) {
EntityPlayer thePlayer = Minecraft.getMinecraft().thePlayer;
if (thePlayer instanceof CameraEntity && entity.isInvisible()) {

View File

@@ -14,6 +14,7 @@ public abstract class MixinRenderArrow extends Render {
super(renderManager);
}
@SuppressWarnings("unchecked")
@Override
public boolean shouldRender(Entity entity, ICamera camera, double camX, double camY, double camZ) {
// Force arrows to always render, otherwise they stop rendering when you get close to them

View File

@@ -3,7 +3,7 @@ package com.replaymod.replay.mixin;
import com.replaymod.replay.ReplayHandler;
import com.replaymod.replay.ReplayModReplay;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.entity.RenderItem;
import net.minecraft.client.renderer.RenderItem;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

View File

@@ -2,7 +2,7 @@ package com.replaymod.replay.mixin;
import com.replaymod.replay.camera.CameraEntity;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.entity.RendererLivingEntity;
import net.minecraft.client.renderer.entity.RenderLivingBase;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import org.spongepowered.asm.mixin.Mixin;
@@ -11,8 +11,8 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(RendererLivingEntity.class)
public abstract class MixinRendererLivingEntity {
@Mixin(RenderLivingBase.class)
public abstract class MixinRenderLivingBase {
@Inject(method = "canRenderName", at = @At("HEAD"), cancellable = true)
private void replayModReplay_canRenderInvisibleName(EntityLivingBase entity, CallbackInfoReturnable<Boolean> ci) {
EntityPlayer thePlayer = Minecraft.getMinecraft().thePlayer;

View File

@@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(TileEntityEndPortalRenderer.class)
public class MixinTileEntityEndPortalRenderer {
@Redirect(method = "func_180544_a", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;getSystemTime()J"))
@Redirect(method = "renderTileEntityAt", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;getSystemTime()J"))
private long replayModReplay_getEnchantmentTime() {
ReplayHandler replayHandler = ReplayModReplay.instance.getReplayHandler();
if (replayHandler != null) {

View File

@@ -5,8 +5,8 @@ import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.client.renderer.ViewFrustum;
import net.minecraft.client.renderer.chunk.IRenderChunkFactory;
import net.minecraft.client.renderer.chunk.RenderChunk;
import net.minecraft.util.BlockPos;
import net.minecraft.util.MathHelper;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -31,7 +31,7 @@ public abstract class MixinViewFrustum {
}
/**
* Instead of calling {@link RenderChunk#setPosition(BlockPos)} we recreate the render chunk
* Instead of calling {@link RenderChunk#setOrigin(int, int, int)} we recreate the render chunk
* which seems to solve the problem that chunks are invisible when you leave an area and return
* to it.
* Any better fixes are welcome.
@@ -48,17 +48,18 @@ public abstract class MixinViewFrustum {
int k = this.countChunksX * 16;
for (int l = 0; l < this.countChunksX; ++l) {
int i1 = this.func_178157_a(i, k, l);
int i1 = this.getBaseCoordinate(i, k, l);
for (int j1 = 0; j1 < this.countChunksZ; ++j1) {
int k1 = this.func_178157_a(j, k, j1);
int k1 = this.getBaseCoordinate(j, k, j1);
for (int l1 = 0; l1 < this.countChunksY; ++l1) {
int i2 = l1 * 16;
RenderChunk renderchunk = this.renderChunks[(j1 * this.countChunksY + l1) * this.countChunksX + l];
BlockPos blockpos = new BlockPos(i1, i2, k1);
if (!blockpos.equals(renderchunk.getPosition())) {
// Recreate render chunk instead of setting its position
renderChunks[(j1 * this.countChunksY + l1) * this.countChunksX + l] =
renderChunkFactory.makeRenderChunk(world, renderGlobal, blockpos, 0);
(renderChunks[(j1 * this.countChunksY + l1) * this.countChunksX + l] =
renderChunkFactory.create(world, renderGlobal, 0)
).setOrigin(blockpos.getX(), blockpos.getY(), blockpos.getZ());
}
}
}
@@ -66,5 +67,5 @@ public abstract class MixinViewFrustum {
ci.cancel();
}
@Shadow abstract int func_178157_a(int p_178157_1_, int p_178157_2_, int p_178157_3_);
@Shadow abstract int getBaseCoordinate(int p_178157_1_, int p_178157_2_, int p_178157_3_);
}

View File

@@ -18,7 +18,7 @@ import com.replaymod.replaystudio.pathing.path.Keyframe;
import com.replaymod.replaystudio.pathing.path.Timeline;
import com.replaymod.simplepathing.gui.GuiPathing;
import com.replaymod.simplepathing.preview.PathPreview;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
@@ -43,7 +43,7 @@ public class ReplayModSimplePathing implements PathingRegistry {
core.getSettingsRegistry().register(Setting.class);
FMLCommonHandler.instance().bus().register(this);
MinecraftForge.EVENT_BUS.register(this);
PathPreview pathPreview = new PathPreview(this);
pathPreview.register();
@@ -84,9 +84,6 @@ public class ReplayModSimplePathing implements PathingRegistry {
}
public void setCurrentTimeline(Timeline currentTimeline) {
if (this.currentTimeline != currentTimeline) {
selectedKeyframe = null;
}
this.currentTimeline = currentTimeline;
}

View File

@@ -13,20 +13,16 @@ import de.johni0702.minecraft.gui.element.GuiButton;
import de.johni0702.minecraft.gui.element.GuiLabel;
import de.johni0702.minecraft.gui.element.GuiNumberField;
import de.johni0702.minecraft.gui.element.IGuiLabel;
import de.johni0702.minecraft.gui.function.Typeable;
import de.johni0702.minecraft.gui.layout.GridLayout;
import de.johni0702.minecraft.gui.layout.HorizontalLayout;
import de.johni0702.minecraft.gui.layout.VerticalLayout;
import de.johni0702.minecraft.gui.popup.AbstractGuiPopup;
import de.johni0702.minecraft.gui.utils.Colors;
import de.johni0702.minecraft.gui.utils.Consumer;
import org.apache.commons.lang3.tuple.Triple;
import org.lwjgl.input.Keyboard;
import org.lwjgl.util.ReadablePoint;
import static de.johni0702.minecraft.gui.utils.Utils.link;
public abstract class GuiEditKeyframe<T extends GuiEditKeyframe<T>> extends AbstractGuiPopup<T> implements Typeable {
public abstract class GuiEditKeyframe<T extends GuiEditKeyframe<T>> extends AbstractGuiPopup<T> {
private static GuiNumberField newGuiNumberField() {
return new GuiNumberField().setPrecision(0).setValidateOnFocusChange(true);
}
@@ -72,10 +68,9 @@ public abstract class GuiEditKeyframe<T extends GuiEditKeyframe<T>> extends Abst
this.path = path;
long time = keyframe.getTime();
Consumer<String> updateSaveButtonState = s -> saveButton.setEnabled(canSave());
timeMinField.setValue(time / 1000 / 60).onTextChanged(updateSaveButtonState);
timeSecField.setValue(time / 1000 % 60).onTextChanged(updateSaveButtonState);
timeMSecField.setValue(time % 1000).onTextChanged(updateSaveButtonState);
timeMinField.setValue(time / 1000 / 60);
timeSecField.setValue(time / 1000 % 60);
timeMSecField.setValue(time % 1000);
title.setI18nText("replaymod.gui.editkeyframe.title." + type);
saveButton.onClick(() -> {
@@ -89,23 +84,6 @@ public abstract class GuiEditKeyframe<T extends GuiEditKeyframe<T>> extends Abst
});
}
private boolean canSave() {
long newTime = (timeMinField.getInteger() * 60 + timeSecField.getInteger()) * 1000 + timeMSecField.getInteger();
if (newTime != keyframe.getTime() && path.getKeyframe(newTime) != null) {
return false;
}
return true;
}
@Override
public boolean typeKey(ReadablePoint mousePosition, int keyCode, char keyChar, boolean ctrlDown, boolean shiftDown) {
if (keyCode == Keyboard.KEY_ESCAPE) {
cancelButton.onClick();
return true;
}
return false;
}
@Override
public void open() {
super.open();

View File

@@ -121,42 +121,24 @@ public class GuiKeyframeTimeline extends AbstractGuiTimeline<GuiKeyframeTimeline
|| !segment.getInterpolator().getKeyframeProperties().contains(SpectatorProperty.PROPERTY)) {
continue; // Not a spectator segment
}
drawQuadOnSegment(renderer, visibleWidth, segment, BORDER_TOP + 1, 0xFF0088FF);
}
// Draw red quads on time path segments that would require time going backwards
for (PathSegment segment : mod.getCurrentTimeline().getPaths().get(GuiPathing.TIME_PATH).getSegments()) {
long startTimestamp = segment.getStartKeyframe().getValue(TimestampProperty.PROPERTY).orElseThrow(IllegalStateException::new);
long endTimestamp = segment.getEndKeyframe().getValue(TimestampProperty.PROPERTY).orElseThrow(IllegalStateException::new);
if (endTimestamp >= startTimestamp) {
continue; // All is fine, time is not moving backwards
long startFrameTime = segment.getStartKeyframe().getTime();
long endFrameTime = segment.getEndKeyframe().getTime();
if (startFrameTime >= endTime || endFrameTime <= startTime) {
continue; // Segment out of display range
}
double relativeStart = startFrameTime - startTime;
double relativeEnd = endFrameTime - startTime;
int startX = BORDER_LEFT + Math.max(0, (int) (relativeStart / visibleTime * visibleWidth) + KEYFRAME_SIZE / 2 + 1);
int endX = BORDER_LEFT + Math.min(visibleWidth, (int) (relativeEnd / visibleTime * visibleWidth) - KEYFRAME_SIZE / 2);
if (startX < endX) {
renderer.drawRect(startX + 1, BORDER_TOP + 1, endX - startX - 2, KEYFRAME_SIZE - 2, 0xFF0088FF);
}
drawQuadOnSegment(renderer, visibleWidth, segment, BORDER_TOP + KEYFRAME_SIZE + 1, 0xFFFF0000);
}
super.drawTimelineCursor(renderer, size);
}
private void drawQuadOnSegment(GuiRenderer renderer, int visibleWidth, PathSegment segment, int y, int color) {
int startTime = getOffset();
int visibleTime = (int) (getZoom() * getLength());
int endTime = getOffset() + visibleTime;
long startFrameTime = segment.getStartKeyframe().getTime();
long endFrameTime = segment.getEndKeyframe().getTime();
if (startFrameTime >= endTime || endFrameTime <= startTime) {
return; // Segment out of display range
}
double relativeStart = startFrameTime - startTime;
double relativeEnd = endFrameTime - startTime;
int startX = BORDER_LEFT + Math.max(0, (int) (relativeStart / visibleTime * visibleWidth) + KEYFRAME_SIZE / 2 + 1);
int endX = BORDER_LEFT + Math.min(visibleWidth, (int) (relativeEnd / visibleTime * visibleWidth) - KEYFRAME_SIZE / 2);
if (startX < endX) {
renderer.drawRect(startX + 1, y, endX - startX - 2, KEYFRAME_SIZE - 2, color);
}
}
/**
* Returns the keyframe at the specified position.
* @param position The raw position
@@ -226,7 +208,6 @@ public class GuiKeyframeTimeline extends AbstractGuiTimeline<GuiKeyframeTimeline
// Clicked on timeline but not on any keyframe
if (button == 0) { // Left click
setCursorPosition(time);
gui.getMod().setSelectedKeyframe(null);
} else if (button == 1) { // Right click
if (pathKeyframePair.getLeft() != null) {
// Apply the value of the clicked path at the clicked position
@@ -261,15 +242,6 @@ public class GuiKeyframeTimeline extends AbstractGuiTimeline<GuiKeyframeTimeline
@Override
public boolean mouseDrag(ReadablePoint position, int button, long timeSinceLastCall) {
if (!dragging) {
if (button == 0) {
// Left click, the user might try to move the cursor by clicking and holding
int time = getTimeAt(position.getX(), position.getY());
if (time != -1) {
// and they are still on the timeline, so update the time appropriately
setCursorPosition(time);
return true;
}
}
return false;
}

View File

@@ -38,7 +38,6 @@ import de.johni0702.minecraft.gui.layout.CustomLayout;
import de.johni0702.minecraft.gui.layout.HorizontalLayout;
import de.johni0702.minecraft.gui.layout.VerticalLayout;
import de.johni0702.minecraft.gui.popup.AbstractGuiPopup;
import de.johni0702.minecraft.gui.popup.GuiInfoPopup;
import de.johni0702.minecraft.gui.popup.GuiYesNoPopup;
import de.johni0702.minecraft.gui.utils.Colors;
import net.minecraft.entity.Entity;
@@ -70,69 +69,22 @@ public class GuiPathing {
private static final Logger logger = LogManager.getLogger();
public final GuiTexturedButton playPauseButton = new GuiTexturedButton() {
@Override
public GuiElement getTooltip(RenderInfo renderInfo) {
GuiTooltip tooltip = (GuiTooltip) super.getTooltip(renderInfo);
if (tooltip != null) {
if (player.isActive()) {
tooltip.setI18nText("replaymod.gui.ingame.menu.pausepath");
} else if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) {
tooltip.setI18nText("replaymod.gui.ingame.menu.playpathfromstart");
} else {
tooltip.setI18nText("replaymod.gui.ingame.menu.playpath");
}
}
return tooltip;
}
}.setSize(20, 20).setTexture(ReplayMod.TEXTURE, ReplayMod.TEXTURE_SIZE).setTooltip(new GuiTooltip());
public final GuiTexturedButton playPauseButton = new GuiTexturedButton().setSize(20, 20)
.setTexture(ReplayMod.TEXTURE, ReplayMod.TEXTURE_SIZE);
public final GuiTexturedButton renderButton = new GuiTexturedButton().onClick(new Runnable() {
@Override
public void run() {
if (!preparePathsForPlayback()) return;
preparePathsForPlayback();
new GuiRenderSettings(replayHandler, mod.getCurrentTimeline()).display();
}
}).setSize(20, 20).setTexture(ReplayMod.TEXTURE, ReplayMod.TEXTURE_SIZE).setTexturePosH(40, 0)
.setTooltip(new GuiTooltip().setI18nText("replaymod.gui.ingame.menu.renderpath"));
}).setSize(20, 20).setTexture(ReplayMod.TEXTURE, ReplayMod.TEXTURE_SIZE).setTexturePosH(40, 0);
public final GuiTexturedButton positionKeyframeButton = new GuiTexturedButton() {
@Override
public GuiElement getTooltip(RenderInfo renderInfo) {
GuiTooltip tooltip = (GuiTooltip) super.getTooltip(renderInfo);
if (tooltip != null) {
if (getTextureNormal().getY() == 40) { // Add keyframe
if (getTextureNormal().getX() == 0) { // Position
tooltip.setI18nText("replaymod.gui.ingame.menu.addposkeyframe");
} else { // Spectator
tooltip.setI18nText("replaymod.gui.ingame.menu.addspeckeyframe");
}
} else { // Remove keyframe
if (getTextureNormal().getX() == 0) { // Position
tooltip.setI18nText("replaymod.gui.ingame.menu.removeposkeyframe");
} else { // Spectator
tooltip.setI18nText("replaymod.gui.ingame.menu.removespeckeyframe");
}
}
}
return tooltip;
}
}.setSize(20, 20).setTexture(ReplayMod.TEXTURE, ReplayMod.TEXTURE_SIZE).setTooltip(new GuiTooltip());
public final GuiTexturedButton positionKeyframeButton = new GuiTexturedButton().setSize(20, 20)
.setTexture(ReplayMod.TEXTURE, ReplayMod.TEXTURE_SIZE);
public final GuiTexturedButton timeKeyframeButton = new GuiTexturedButton() {
@Override
public GuiElement getTooltip(RenderInfo renderInfo) {
GuiTooltip tooltip = (GuiTooltip) super.getTooltip(renderInfo);
if (tooltip != null) {
if (getTextureNormal().getY() == 80) { // Add time keyframe
tooltip.setI18nText("replaymod.gui.ingame.menu.addtimekeyframe");
} else { // Remove time keyframe
tooltip.setI18nText("replaymod.gui.ingame.menu.removetimekeyframe");
}
}
return tooltip;
}
}.setSize(20, 20).setTexture(ReplayMod.TEXTURE, ReplayMod.TEXTURE_SIZE).setTooltip(new GuiTooltip());
public final GuiTexturedButton timeKeyframeButton = new GuiTexturedButton().setSize(20, 20)
.setTexture(ReplayMod.TEXTURE, ReplayMod.TEXTURE_SIZE);
public final GuiKeyframeTimeline timeline = new GuiKeyframeTimeline(this){
@Override
@@ -161,16 +113,14 @@ public class GuiPathing {
public void run() {
zoomTimeline(2d / 3d);
}
}).setTexture(ReplayMod.TEXTURE, ReplayMod.TEXTURE_SIZE).setTexturePosH(40, 20)
.setTooltip(new GuiTooltip().setI18nText("replaymod.gui.ingame.menu.zoomin"));
}).setTexture(ReplayMod.TEXTURE, ReplayMod.TEXTURE_SIZE).setTexturePosH(40, 20);
public final GuiTexturedButton zoomOutButton = new GuiTexturedButton().setSize(9, 9).onClick(new Runnable() {
@Override
public void run() {
zoomTimeline(3d / 2d);
}
}).setTexture(ReplayMod.TEXTURE, ReplayMod.TEXTURE_SIZE).setTexturePosH(40, 30)
.setTooltip(new GuiTooltip().setI18nText("replaymod.gui.ingame.menu.zoomout"));
}).setTexture(ReplayMod.TEXTURE, ReplayMod.TEXTURE_SIZE).setTexturePosH(40, 30);
public final GuiPanel zoomButtonPanel = new GuiPanel()
.setLayout(new VerticalLayout(VerticalLayout.Alignment.CENTER).setSpacing(2))
@@ -281,12 +231,10 @@ public class GuiPathing {
Timeline timeline = mod.getCurrentTimeline();
Path timePath = timeline.getPaths().get(TIME_PATH);
if (!preparePathsForPlayback()) return;
preparePathsForPlayback();
timePath.setActive(!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT));
// Start from cursor time unless the control key is pressed (then start from beginning)
int startTime = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)? 0 : GuiPathing.this.timeline.getCursorPosition();
ListenableFuture<Void> future = player.start(timeline, startTime);
ListenableFuture<Void> future = player.start(timeline);
overlay.setCloseable(false);
overlay.setMouseVisible(true);
Futures.addCallback(future, new FutureCallback<Void>() {
@@ -455,15 +403,6 @@ public class GuiPathing {
});
});
core.getKeyBindingRegistry().registerRaw(Keyboard.KEY_DELETE, () -> {
if (!overlay.isVisible()) {
return;
}
if (mod.getSelectedKeyframe() != null) {
updateKeyframe(mod.getSelectedKeyframe().getValue(TimestampProperty.PROPERTY).isPresent());
}
});
// Start loading entity tracker
entityTrackerFuture = SettableFuture.create();
new Thread(() -> {
@@ -490,27 +429,10 @@ public class GuiPathing {
}).start();
}
private boolean preparePathsForPlayback() {
private void preparePathsForPlayback() {
Timeline timeline = mod.getCurrentTimeline();
timeline.getPaths().get(TIME_PATH).updateAll();
timeline.getPaths().get(POSITION_PATH).updateAll();
// Make sure time keyframes's values are monotonically increasing
int lastTime = 0;
for (Keyframe keyframe : timeline.getPaths().get(TIME_PATH).getKeyframes()) {
int time = keyframe.getValue(TimestampProperty.PROPERTY).orElseThrow(IllegalStateException::new);
if (time < lastTime) {
// We are going backwards in time
GuiInfoPopup.open(replayHandler.getOverlay(),
"replaymod.error.negativetime1",
"replaymod.error.negativetime2",
"replaymod.error.negativetime3");
return false;
}
lastTime = time;
}
return true;
}
public void zoomTimeline(double factor) {

View File

@@ -8,7 +8,7 @@ import com.replaymod.replay.events.ReplayCloseEvent;
import com.replaymod.replay.events.ReplayOpenEvent;
import com.replaymod.simplepathing.ReplayModSimplePathing;
import com.replaymod.simplepathing.Setting;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.lwjgl.input.Keyboard;
@@ -23,7 +23,7 @@ public class PathPreview {
}
public void register() {
FMLCommonHandler.instance().bus().register(this);
MinecraftForge.EVENT_BUS.register(this);
ReplayMod core = mod.getCore();
mod.getCore().getKeyBindingRegistry().registerKeyBinding("replaymod.input.pathpreview", Keyboard.KEY_H, () -> {

View File

@@ -17,7 +17,8 @@ import com.replaymod.simplepathing.gui.GuiPathing;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.VertexBuffer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.Entity;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.RenderWorldLastEvent;
@@ -203,26 +204,35 @@ public class PathPreviewRenderer {
if (distanceSquared(view, pos2) > renderDistanceSquared) return;
Tessellator tessellator = Tessellator.getInstance();
WorldRenderer renderer = tessellator.getWorldRenderer();
renderer.setTranslation(-view.getLeft(), -view.getMiddle(), -view.getRight());
VertexBuffer vertexBuffer = tessellator.getBuffer();
vertexBuffer.setTranslation(-view.getLeft(), -view.getMiddle(), -view.getRight());
renderer.startDrawing(GL11.GL_LINES);
renderer.setColorRGBA_I(color, 255);
vertexBuffer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR);
renderer.addVertex(pos1.getLeft(), pos1.getMiddle(), pos1.getRight());
renderer.addVertex(pos2.getLeft(), pos2.getMiddle(), pos2.getRight());
vertexBuffer.pos(pos1.getLeft(), pos1.getMiddle(), pos1.getRight()).color(
color >> 16 & 0xff,
color >> 8 & 0xff,
color & 0xff,
255
).endVertex();
vertexBuffer.pos(pos2.getLeft(), pos2.getMiddle(), pos2.getRight()).color(
color >> 16 & 0xff,
color >> 8 & 0xff,
color & 0xff,
255
).endVertex();
GL11.glLineWidth(3);
tessellator.draw();
renderer.setTranslation(0, 0, 0);
vertexBuffer.setTranslation(0, 0, 0);
}
private void drawPoint(Triple<Double, Double, Double> view,
Triple<Double, Double, Double> pos,
Keyframe keyframe) {
Tessellator tessellator = Tessellator.getInstance();
WorldRenderer renderer = tessellator.getWorldRenderer();
renderer.setTranslation(0, 0, 0);
VertexBuffer vertexBuffer = tessellator.getBuffer();
vertexBuffer.setTranslation(0, 0, 0);
mc.renderEngine.bindTexture(TEXTURE);
@@ -243,12 +253,12 @@ public class PathPreviewRenderer {
float maxX = 0.5f;
float maxY = 0.5f;
renderer.startDrawingQuads();
vertexBuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
renderer.addVertexWithUV(minX, minY, 0, posX + size, posY + size);
renderer.addVertexWithUV(minX, maxY, 0, posX + size, posY);
renderer.addVertexWithUV(maxX, maxY, 0, posX, posY);
renderer.addVertexWithUV(maxX, minY, 0, posX, posY + size);
vertexBuffer.pos(minX, minY, 0).tex(posX + size, posY + size).endVertex();
vertexBuffer.pos(minX, maxY, 0).tex(posX + size, posY).endVertex();
vertexBuffer.pos(maxX, maxY, 0).tex(posX, posY).endVertex();
vertexBuffer.pos(maxX, minY, 0).tex(posX, posY + size).endVertex();
GL11.glPushMatrix();
@@ -270,8 +280,8 @@ public class PathPreviewRenderer {
Triple<Double, Double, Double> pos,
Triple<Float, Float, Float> rot) {
Tessellator tessellator = Tessellator.getInstance();
WorldRenderer renderer = tessellator.getWorldRenderer();
renderer.setTranslation(0, 0, 0);
VertexBuffer vertexBuffer = tessellator.getBuffer();
vertexBuffer.setTranslation(0, 0, 0);
mc.renderEngine.bindTexture(CAMERA_HEAD);
@@ -289,12 +299,10 @@ public class PathPreviewRenderer {
//draw the position line
GL11.glDisable(GL11.GL_TEXTURE_2D);
renderer.startDrawing(GL11.GL_LINES);
vertexBuffer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR);
renderer.setColorRGBA_I(0x00ff00, 170);
renderer.addVertex(0, 0, 0);
renderer.addVertex(0, 0, 2);
vertexBuffer.pos(0, 0, 0).color(0, 255, 0, 170).endVertex();
vertexBuffer.pos(0, 0, 2).color(0, 255, 0, 170).endVertex();
tessellator.draw();
@@ -305,45 +313,43 @@ public class PathPreviewRenderer {
double r = -cubeSize/2;
renderer.startDrawingQuads();
renderer.setColorRGBA_I(0xffffff, 200);
vertexBuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);
//back
renderer.addVertexWithUV(r, r + cubeSize, r, 3 * 8 / 64f, 8 / 64f);
renderer.addVertexWithUV(r + cubeSize, r + cubeSize, r, 4*8/64f, 8/64f);
renderer.addVertexWithUV(r + cubeSize, r, r, 4*8/64f, 2*8/64f);
renderer.addVertexWithUV(r, r, r, 3*8/64f, 2*8/64f);
vertexBuffer.pos(r, r + cubeSize, r).tex(3 * 8 / 64f, 8 / 64f).color(255, 255, 255, 200).endVertex();
vertexBuffer.pos(r + cubeSize, r + cubeSize, r).tex(4*8/64f, 8/64f).color(255, 255, 255, 200).endVertex();
vertexBuffer.pos(r + cubeSize, r, r).tex(4*8/64f, 2*8/64f).color(255, 255, 255, 200).endVertex();
vertexBuffer.pos(r, r, r).tex(3*8/64f, 2*8/64f).color(255, 255, 255, 200).endVertex();
//front
renderer.addVertexWithUV(r + cubeSize, r, r + cubeSize, 2 * 8 / 64f, 2*8/64f);
renderer.addVertexWithUV(r + cubeSize, r + cubeSize, r + cubeSize, 2 * 8 / 64f, 8/64f);
renderer.addVertexWithUV(r, r + cubeSize, r + cubeSize, 8 / 64f, 8 / 64f);
renderer.addVertexWithUV(r, r, r + cubeSize, 8 / 64f, 2*8/64f);
vertexBuffer.pos(r + cubeSize, r, r + cubeSize).tex(2 * 8 / 64f, 2*8/64f).color(255, 255, 255, 200).endVertex();
vertexBuffer.pos(r + cubeSize, r + cubeSize, r + cubeSize).tex(2 * 8 / 64f, 8/64f).color(255, 255, 255, 200).endVertex();
vertexBuffer.pos(r, r + cubeSize, r + cubeSize).tex(8 / 64f, 8 / 64f).color(255, 255, 255, 200).endVertex();
vertexBuffer.pos(r, r, r + cubeSize).tex(8 / 64f, 2*8/64f).color(255, 255, 255, 200).endVertex();
//left
renderer.addVertexWithUV(r + cubeSize, r + cubeSize, r, 0, 8/64f);
renderer.addVertexWithUV(r + cubeSize, r + cubeSize, r + cubeSize, 8/64f, 8/64f);
renderer.addVertexWithUV(r + cubeSize, r, r + cubeSize, 8/64f, 2*8/64f);
renderer.addVertexWithUV(r+cubeSize, r, r, 0, 2*8/64f);
vertexBuffer.pos(r + cubeSize, r + cubeSize, r).tex(0, 8/64f).color(255, 255, 255, 200).endVertex();
vertexBuffer.pos(r + cubeSize, r + cubeSize, r + cubeSize).tex(8/64f, 8/64f).color(255, 255, 255, 200).endVertex();
vertexBuffer.pos(r + cubeSize, r, r + cubeSize).tex(8/64f, 2*8/64f).color(255, 255, 255, 200).endVertex();
vertexBuffer.pos(r+cubeSize, r, r).tex(0, 2*8/64f).color(255, 255, 255, 200).endVertex();
//right
renderer.addVertexWithUV(r, r + cubeSize, r + cubeSize, 2*8/64f, 8/64f);
renderer.addVertexWithUV(r, r + cubeSize, r, 3*8/64f, 8/64f);
renderer.addVertexWithUV(r, r, r, 3*8/64f, 2*8/64f);
renderer.addVertexWithUV(r, r, r + cubeSize, 2 * 8 / 64f, 2 * 8 / 64f);
vertexBuffer.pos(r, r + cubeSize, r + cubeSize).tex(2*8/64f, 8/64f).color(255, 255, 255, 200).endVertex();
vertexBuffer.pos(r, r + cubeSize, r).tex(3*8/64f, 8/64f).color(255, 255, 255, 200).endVertex();
vertexBuffer.pos(r, r, r).tex(3*8/64f, 2*8/64f).color(255, 255, 255, 200).endVertex();
vertexBuffer.pos(r, r, r + cubeSize).tex(2 * 8 / 64f, 2 * 8 / 64f).color(255, 255, 255, 200).endVertex();
//bottom
renderer.addVertexWithUV(r + cubeSize, r, r, 3*8/64f, 0);
renderer.addVertexWithUV(r + cubeSize, r, r + cubeSize, 3*8/64f, 8/64f);
renderer.addVertexWithUV(r, r, r + cubeSize, 2*8/64f, 8/64f);
renderer.addVertexWithUV(r, r, r, 2 * 8 / 64f, 0);
vertexBuffer.pos(r + cubeSize, r, r).tex(3*8/64f, 0).color(255, 255, 255, 200).endVertex();
vertexBuffer.pos(r + cubeSize, r, r + cubeSize).tex(3*8/64f, 8/64f).color(255, 255, 255, 200).endVertex();
vertexBuffer.pos(r, r, r + cubeSize).tex(2*8/64f, 8/64f).color(255, 255, 255, 200).endVertex();
vertexBuffer.pos(r, r, r).tex(2 * 8 / 64f, 0).color(255, 255, 255, 200).endVertex();
//top
renderer.addVertexWithUV(r, r + cubeSize, r, 8/64f, 0);
renderer.addVertexWithUV(r, r + cubeSize, r + cubeSize, 8/64f, 8/64f);
renderer.addVertexWithUV(r + cubeSize, r + cubeSize, r + cubeSize, 2*8/64f, 8/64f);
renderer.addVertexWithUV(r + cubeSize, r + cubeSize, r, 2 * 8 / 64f, 0);
vertexBuffer.pos(r, r + cubeSize, r).tex(8/64f, 0).color(255, 255, 255, 200).endVertex();
vertexBuffer.pos(r, r + cubeSize, r + cubeSize).tex(8/64f, 8/64f).color(255, 255, 255, 200).endVertex();
vertexBuffer.pos(r + cubeSize, r + cubeSize, r + cubeSize).tex(2*8/64f, 8/64f).color(255, 255, 255, 200).endVertex();
vertexBuffer.pos(r + cubeSize, r + cubeSize, r).tex(2 * 8 / 64f, 0).color(255, 255, 255, 200).endVertex();
tessellator.draw();

View File

@@ -21,23 +21,23 @@ public net.minecraft.client.Minecraft func_147112_ai()V # middleClickMouse
public net.minecraft.client.Minecraft func_147115_a(Z)V # sendClickBlockToController
# Packets
public net.minecraft.network.play.server.S0FPacketSpawnMob field_149043_l # dataWatcher
public net.minecraft.network.play.server.SPacketSpawnMob field_149043_l # dataManager
public net.minecraft.network.play.server.SPacketSpawnPlayer field_148960_i # watcher
#public net.minecraft.network.play.server.S38PacketPlayerListItem field_179964_d # profile
public net.minecraft.network.play.server.S1DPacketEntityEffect field_149434_a # entityId
public net.minecraft.network.play.server.S1CPacketEntityMetadata field_149379_a # entityId
public net.minecraft.network.play.server.S1CPacketEntityMetadata field_149378_b # list
public net.minecraft.network.play.server.S0BPacketAnimation field_148981_a # entityId
public net.minecraft.network.play.server.S02PacketChat field_179842_b # position
public net.minecraft.network.play.server.S19PacketEntityStatus field_149164_a # entityId
public net.minecraft.network.play.server.S0CPacketSpawnPlayer *
public net.minecraft.network.play.server.S18PacketEntityTeleport *
public net.minecraft.network.play.server.S14PacketEntity *
public net.minecraft.network.play.server.S19PacketEntityHeadLook *
public net.minecraft.network.play.server.S12PacketEntityVelocity *
public net.minecraft.network.play.server.S04PacketEntityEquipment *
public net.minecraft.network.play.server.S1BPacketEntityAttach *
public net.minecraft.network.play.server.S0DPacketCollectItem *
public net.minecraft.network.play.server.S13PacketDestroyEntities *
# public net.minecraft.network.play.server.S1DPacketEntityEffect field_149434_a # entityId
# public net.minecraft.network.play.server.S1CPacketEntityMetadata field_149379_a # entityId
# public net.minecraft.network.play.server.S1CPacketEntityMetadata field_149378_b # list
# public net.minecraft.network.play.server.S0BPacketAnimation field_148981_a # entityId
# public net.minecraft.network.play.server.S02PacketChat field_179842_b # position
# public net.minecraft.network.play.server.S19PacketEntityStatus field_149164_a # entityId
# public net.minecraft.network.play.server.S18PacketEntityTeleport *
# public net.minecraft.network.play.server.S14PacketEntity *
# public net.minecraft.network.play.server.S19PacketEntityHeadLook *
# public net.minecraft.network.play.server.S12PacketEntityVelocity *
# public net.minecraft.network.play.server.S04PacketEntityEquipment *
# public net.minecraft.network.play.server.S1BPacketEntityAttach *
# public net.minecraft.network.play.server.S0DPacketCollectItem *
# public net.minecraft.network.play.server.S13PacketDestroyEntities *
# GuiTextField
public net.minecraft.client.gui.GuiTextField field_146216_j # text
@@ -61,7 +61,7 @@ public net.minecraft.client.renderer.RenderGlobal field_175009_l # chunksToUpdat
public net.minecraft.client.renderer.RenderGlobal field_72755_R # renderInfos
public net.minecraft.client.renderer.RenderGlobal field_175009_l # chunksToUpdate
public net.minecraft.client.renderer.RenderGlobal field_72740_G # renderEntitiesStartupCounter
public net.minecraft.client.renderer.RenderGlobal func_174983_a(Lnet.minecraft.util.BlockPos;Lnet.minecraft.client.renderer.chunk.RenderChunk;)Z # isPositionInRenderChunk
# public net.minecraft.client.renderer.RenderGlobal func_174983_a(Lnet.minecraft.util.BlockPos;Lnet.minecraft.client.renderer.chunk.RenderChunk;)Z # isPositionInRenderChunk
public net.minecraft.client.renderer.RenderGlobal$ContainerLocalRenderInformation
#public net.minecraft.client.renderer.RenderGlobal$ContainerLocalRenderInformation field_178553_a # renderChunk
@@ -88,14 +88,14 @@ public net.minecraft.entity.player.EntityPlayer *
public net.minecraft.client.entity.EntityOtherPlayerMP *
# EffectRenderer
public net.minecraft.client.particle.EffectRenderer field_110737_b # particleTextures
public net.minecraft.client.particle.EffectRenderer field_78876_b # fxLayers
# public net.minecraft.client.particle.EffectRenderer field_110737_b # particleTextures
# public net.minecraft.client.particle.EffectRenderer field_78876_b # fxLayers
# IntegratedServer
public net.minecraft.server.integrated.IntegratedServer field_71348_o # isGamePaused
# GameSettings
public net.minecraft.client.settings.GameSettings field_151446_aD # mapSoundLevels
public net.minecraft.client.settings.GameSettings field_186714_aM # soundLevels
# Frustum
public net.minecraft.client.renderer.culling.Frustum field_78552_a # clippingHelper
@@ -117,5 +117,12 @@ public net.minecraft.client.renderer.GlStateManager$FogState
public net.minecraft.client.renderer.GlStateManager$BooleanState
public net.minecraft.client.renderer.GlStateManager$BooleanState *
# EntityLivingBase
public net.minecraft.entity.EntityLivingBase field_184621_as # HAND_STATES
public net.minecraft.entity.EntityLivingBase field_184628_bn # activeItemStackUseCount
# EntityLivingBase
public net.minecraft.client.particle.Particle *
# Example
# public net.minecraft.package.ClassName func_some_id(Ljava/lang/Class;IZS)V # methodName

View File

@@ -485,9 +485,6 @@ replaymod.gui.objects=Custom Objects
#Errors
replaymod.error.unknownrestriction1=This replay cannot be played with your current version.
replaymod.error.unknownrestriction2=It tried to enforce %s which is unknown.
replaymod.error.negativetime1=Some of your time keyframes are out of order.
replaymod.error.negativetime2=Going backwards in time is not supported.
replaymod.error.negativetime3=The invalid parts are marked in red.
#Replay Mod Incompatibility Warning
replaymod.gui.modwarning.title=Incompatibility detected
@@ -499,14 +496,4 @@ replaymod.gui.modwarning.id=Mod Id:
replaymod.gui.modwarning.missing=Missing Mods
replaymod.gui.modwarning.version=Different Mod Versions
replaymod.gui.modwarning.version.expected=Expected
replaymod.gui.modwarning.version.found=Found
#OpenEye
replaymod.gui.offeropeneye1=Do you want to install OpenEye?
replaymod.gui.offeropeneye2=OpenEye is a mod that collects anonymous information
replaymod.gui.offeropeneye3=about the mods being run and any crashes that happen.
replaymod.gui.offeropeneye4=
replaymod.gui.offeropeneye5=OpenEye can be disabled at any time and is completely optional.
replaymod.gui.offeropeneye6=More information is available at https://openeye.openmods.info/faq
replaymod.gui.offeropeneye7=Clicking Yes will download OpenEye and place it in your mods folder.
replaymod.gui.offeropeneye8=It will then be active the next time you start Minecraft.
replaymod.gui.modwarning.version.found=Found

View File

@@ -48,7 +48,7 @@
"parent": "replaymod",
"screenshots": [],
"dependencies": []
},
}/*,
{
"modid": "replaymod-online",
"name": "Replay Mod - Online",
@@ -116,22 +116,5 @@
"parent": "replaymod",
"screenshots": [],
"dependencies": []
},
{
"modid": "replaymod-compat",
"name": "Replay Mod - Compatibility",
"description": "Compatibility Module of the ReplayMod - Adds compatibility with other mods",
"version": "${version}",
"mcversion": "${mcversion}",
"url": "https://replaymod.com",
"updateUrl": "https://replaymod.com/download",
"authorList": [
"CrushedPixel",
"johni0702"
],
"logoFile": "replaymod_logo.png",
"parent": "replaymod",
"screenshots": [],
"dependencies": []
}
}*/
]

View File

@@ -1,12 +0,0 @@
{
"required": false,
"package": "com.replaymod.compat.shaders.mixin",
"mixins": [],
"server": [],
"client": [
"MixinShaderEntityRenderer",
"MixinShaderRenderChunk",
"MixinShaderRenderGlobal"
],
"refmap": "mixins.replaymod.refmap.json"
}

View File

@@ -7,5 +7,6 @@
"MixinNetHandlerPlayClient",
"MixinRenderGlobal"
],
"compatibilityLevel": "JAVA_8",
"refmap": "mixins.replaymod.refmap.json"
}

View File

@@ -2,14 +2,15 @@
"required": true,
"package": "com.replaymod.render.mixin",
"mixins": [
"MixinEffectRenderer",
"MixinEntityRenderer",
"MixinParticleManager",
"MixinRender",
"MixinRendererLivingEntity",
"MixinRenderGlobal",
"MixinRenderLiving",
"MixinRenderManager"
],
"server": [],
"client": [],
"compatibilityLevel": "JAVA_8",
"refmap": "mixins.replaymod.refmap.json"
}

View File

@@ -2,17 +2,18 @@
"required": true,
"package": "com.replaymod.replay.mixin",
"mixins": [
"MixinArmorStandRenderer",
"MixinGuiSpectator",
"MixinPlayerControllerMP",
"MixinRenderArmorStand",
"MixinRenderArrow",
"MixinRendererLivingEntity",
"MixinRenderItem",
"MixinRenderLivingBase",
"MixinRenderManager",
"MixinTileEntityEndPortalRenderer",
"MixinViewFrustum"
],
"server": [],
"client": [],
"compatibilityLevel": "JAVA_8",
"refmap": "mixins.replaymod.refmap.json"
}