Backport to 1.7.10

This commit is contained in:
Jonas Herzig
2017-09-14 16:06:49 +02:00
parent adfe6a2bfc
commit 1283a39ffa
109 changed files with 1170 additions and 1505 deletions

4
.gitmodules vendored
View File

@@ -2,10 +2,6 @@
path = jGui path = jGui
url = https://github.com/ReplayMod/jGui url = https://github.com/ReplayMod/jGui
[submodule "ReplayStudio"]
path = ReplayStudio
url = https://github.com/ReplayMod/ReplayStudio
[submodule "src/main/resources/assets/replaymod/lang"] [submodule "src/main/resources/assets/replaymod/lang"]
path = src/main/resources/assets/replaymod/lang path = src/main/resources/assets/replaymod/lang
url = https://github.com/ReplayMod/Translations url = https://github.com/ReplayMod/Translations

Submodule ReplayStudio deleted from 44109f11b1

View File

@@ -7,23 +7,17 @@ buildscript {
name = "forge" name = "forge"
url = "http://files.minecraftforge.net/maven" url = "http://files.minecraftforge.net/maven"
} }
maven {
name = "sponge"
url = "https://repo.spongepowered.org/maven"
}
maven { maven {
name = "sonatype" name = "sonatype"
url = "https://oss.sonatype.org/content/repositories/snapshots/" url = "https://oss.sonatype.org/content/repositories/snapshots/"
} }
} }
dependencies { dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:2.0-SNAPSHOT' classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT'
classpath 'org.spongepowered:mixingradle:0.3-SNAPSHOT'
} }
} }
apply plugin: 'net.minecraftforge.gradle.forge' apply plugin: 'forge'
apply plugin: 'org.spongepowered.mixin'
sourceCompatibility = 1.8 sourceCompatibility = 1.8
targetCompatibility = 1.8 targetCompatibility = 1.8
@@ -32,11 +26,18 @@ version = gitDescribe()
group= "com.replaymod" group= "com.replaymod"
archivesBaseName = "replaymod" archivesBaseName = "replaymod"
ext {
mixinConfigs = [
'compat.shaders', 'extras.playeroverview', 'recording', 'render', 'replay'
].collect {"mixins.${it}.replaymod.json"}
mixinSrg = new File(project.buildDir, 'tmp/mixins/mixins.srg')
mixinRefMap = new File(project.buildDir, 'tmp/mixins/mixins.replaymod.refmap.json')
}
minecraft { minecraft {
coreMod = 'com.replaymod.core.LoadingPlugin' version = '1.7.10-10.13.4.1558-1.7.10'
version = '1.8-11.14.4.1563'
runDir = "eclipse" runDir = "eclipse"
mappings = "snapshot_nodoc_20141130" mappings = "stable_12"
replace '@MOD_VERSION@', project.version replace '@MOD_VERSION@', project.version
// Includes intentional whitespace to stop Forge from declaring the mod to be compatible with // Includes intentional whitespace to stop Forge from declaring the mod to be compatible with
// a newer srg-compatible MC version (that may be using a different protocol version) // a newer srg-compatible MC version (that may be using a different protocol version)
@@ -49,7 +50,7 @@ repositories {
url = "http://repo.spongepowered.org/maven/" url = "http://repo.spongepowered.org/maven/"
} }
maven { maven {
url 'https://repo.spacehq.org/content/repositories/snapshots/' url 'https://jitpack.io'
} }
} }
@@ -71,24 +72,22 @@ dependencies {
shade 'org.aspectj:aspectjrt:1.8.2' shade 'org.aspectj:aspectjrt:1.8.2'
compile project(':ReplayStudio') shade 'com.github.replaymod:ReplayStudio:181140c'
testCompile 'junit:junit:4.11' testCompile 'junit:junit:4.11'
} }
tasks['idea'].dependsOn ':ReplayStudio:preshadowJar'
jar { jar {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE duplicatesStrategy = DuplicatesStrategy.EXCLUDE
dependsOn configurations.compile dependsOn configurations.compile
dependsOn configurations.shade dependsOn configurations.shade
dependsOn ':ReplayStudio:shadowJar'
from project.mixinRefMap
def shade = {files( def shade = {files(
configurations.compile.findAll {it.name.startsWith 'mixin-'} configurations.compile.findAll {it.name.startsWith 'mixin-'}
+ configurations.shade + configurations.shade
+ getTasks().getByPath(':ReplayStudio:shadowJar').outputs.files
)} )}
def noticeDir = file("$buildDir/NOTICE") def noticeDir = file("$buildDir/NOTICE")
@@ -117,6 +116,8 @@ jar {
manifest { manifest {
attributes 'TweakClass': 'org.spongepowered.asm.launch.MixinTweaker', attributes 'TweakClass': 'org.spongepowered.asm.launch.MixinTweaker',
'TweakOrder': '0', 'TweakOrder': '0',
'MixinConfigs': project.mixinConfigs.join(','),
'FMLCorePlugin': 'com.replaymod.core.LoadingPlugin',
'FMLAT': 'replaymod_at.cfg' 'FMLAT': 'replaymod_at.cfg'
} }
} }
@@ -156,6 +157,8 @@ processResources
sourceSets { sourceSets {
main { main {
// Required so resources are loaded correctly in dev env
output.resourcesDir = output.classesDir
// Directly include jGui into main build // Directly include jGui into main build
// This could also be done by including it as a gradle subproject, however // This could also be done by including it as a gradle subproject, however
// doing so caused classpath issues on some IntelliJ versions. // doing so caused classpath issues on some IntelliJ versions.
@@ -165,7 +168,6 @@ sourceSets {
resources { resources {
srcDir 'jGui/src/main/resources' srcDir 'jGui/src/main/resources'
} }
refMap = "mixins.replaymod.refmap.json"
} }
integrationTest { integrationTest {
compileClasspath += main.runtimeClasspath + main.output compileClasspath += main.runtimeClasspath + main.output
@@ -181,6 +183,21 @@ task copySrg(type: Copy, dependsOn: 'genSrgs') {
into 'build' into 'build'
} }
reobf.doFirst {
if (project.mixinSrg.exists()) {
addExtraSrgFile project.mixinSrg
}
}
compileJava.dependsOn copySrg
compileJava {
options.compilerArgs += [
"-AoutSrgFile=${project.mixinSrg.canonicalPath}",
"-AoutRefMapFile=${project.mixinRefMap.canonicalPath}",
"-AreobfSrgFile=${project.file('build/mcp-srg.srg').canonicalPath}"
]
}
setupDecompWorkspace.dependsOn copySrg setupDecompWorkspace.dependsOn copySrg
setupDevWorkspace.dependsOn copySrg setupDevWorkspace.dependsOn copySrg
project.tasks.idea.dependsOn copySrg project.tasks.idea.dependsOn copySrg

2
jGui

Submodule jGui updated: 9e84e724aa...042e1c6e50

View File

@@ -1 +0,0 @@
include 'ReplayStudio'

View File

@@ -3,6 +3,9 @@ package com.replaymod.core;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture; import com.google.common.util.concurrent.SettableFuture;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.TickEvent;
import de.johni0702.minecraft.gui.container.AbstractGuiOverlay; import de.johni0702.minecraft.gui.container.AbstractGuiOverlay;
import de.johni0702.minecraft.gui.container.AbstractGuiScreen; import de.johni0702.minecraft.gui.container.AbstractGuiScreen;
import de.johni0702.minecraft.gui.container.GuiContainer; import de.johni0702.minecraft.gui.container.GuiContainer;
@@ -16,9 +19,6 @@ import de.johni0702.minecraft.gui.utils.Consumer;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.KeyBinding; import net.minecraft.client.settings.KeyBinding;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
import java.lang.reflect.Field; import java.lang.reflect.Field;
@@ -84,10 +84,21 @@ public abstract class AbstractTask implements Task {
private void expectGuiClosed0(int timeout, Runnable onClosed) { private void expectGuiClosed0(int timeout, Runnable onClosed) {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
class EventHandler { FMLCommonHandler.instance().bus().register(new GuiEventHandler(timeout, stackTrace, onClosed));
}
public class GuiEventHandler {
final net.minecraft.client.gui.GuiScreen currentScreen = mc.currentScreen; final net.minecraft.client.gui.GuiScreen currentScreen = mc.currentScreen;
private final int timeout;
private final StackTraceElement[] stackTrace;
private final Runnable onClosed;
int framesPassed; int framesPassed;
public GuiEventHandler(int timeout, StackTraceElement[] stackTrace, Runnable onClosed) {
this.timeout = timeout;
this.stackTrace = stackTrace;
this.onClosed = onClosed;
}
@SubscribeEvent @SubscribeEvent
public void onGuiOpen(TickEvent.RenderTickEvent event) { public void onGuiOpen(TickEvent.RenderTickEvent event) {
if (event.phase != TickEvent.Phase.START) return; if (event.phase != TickEvent.Phase.START) return;
@@ -106,8 +117,6 @@ public abstract class AbstractTask implements Task {
} }
} }
} }
FMLCommonHandler.instance().bus().register(new EventHandler());
}
public void expectPopupClosed(Runnable onClosed) { public void expectPopupClosed(Runnable onClosed) {
expectPopupClosed0(10, onClosed); expectPopupClosed0(10, onClosed);
@@ -119,12 +128,24 @@ public abstract class AbstractTask implements Task {
private void expectPopupClosed0(int timeout, Runnable onClosed) { private void expectPopupClosed0(int timeout, Runnable onClosed) {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
AbstractGuiPopup popup = getPopup(mc.currentScreen); FMLCommonHandler.instance().bus().register(new PopupEventHandler(timeout, stackTrace, onClosed));
if (popup == null) { }
public class PopupEventHandler {
private final int timeout;
private final StackTraceElement[] stackTrace;
private final Runnable onClosed;
private final AbstractGuiPopup popup;
int framesPassed;
public PopupEventHandler(int timeout, StackTraceElement[] stackTrace, Runnable onClosed) {
this.timeout = timeout;
this.stackTrace = stackTrace;
this.onClosed = onClosed;
this.popup = getPopup(mc.currentScreen);
if (this.popup == null) {
throw new IllegalStateException("No popup found."); throw new IllegalStateException("No popup found.");
} }
class EventHandler { }
int framesPassed;
@SubscribeEvent @SubscribeEvent
public void onGuiOpen(TickEvent.RenderTickEvent event) { public void onGuiOpen(TickEvent.RenderTickEvent event) {
@@ -143,8 +164,6 @@ public abstract class AbstractTask implements Task {
} }
} }
} }
FMLCommonHandler.instance().bus().register(new EventHandler());
}
private AbstractGuiPopup getPopup(net.minecraft.client.gui.GuiScreen minecraft) { private AbstractGuiPopup getPopup(net.minecraft.client.gui.GuiScreen minecraft) {
GuiContainer<?> container = GuiOverlay.from(minecraft); GuiContainer<?> container = GuiOverlay.from(minecraft);
@@ -165,10 +184,21 @@ public abstract class AbstractTask implements Task {
public <T> void expectGui(Class<T> guiClass, Consumer<T> onOpen) { public <T> void expectGui(Class<T> guiClass, Consumer<T> onOpen) {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
class EventHandler { FMLCommonHandler.instance().bus().register(new ExpectGuiEventHandler<T>(guiClass, stackTrace, onOpen));
}
public class ExpectGuiEventHandler<T> {
private final Class<T> guiClass;
private final StackTraceElement[] stackTrace;
private final Consumer<T> onOpen;
net.minecraft.client.gui.GuiScreen currentScreen; net.minecraft.client.gui.GuiScreen currentScreen;
int framesPassed; int framesPassed;
public ExpectGuiEventHandler(Class<T> guiClass, StackTraceElement[] stackTrace, Consumer<T> onOpen) {
this.guiClass = guiClass;
this.stackTrace = stackTrace;
this.onOpen = onOpen;
}
@SubscribeEvent @SubscribeEvent
public void onGuiOpen(TickEvent.RenderTickEvent event) { public void onGuiOpen(TickEvent.RenderTickEvent event) {
if (event.phase != TickEvent.Phase.START) return; if (event.phase != TickEvent.Phase.START) return;
@@ -210,17 +240,16 @@ public abstract class AbstractTask implements Task {
return; return;
} }
} }
future.setException(new UnexpectedGuiException(guiClass, stackTrace,
foundGui == null ? currentScreen : foundGui));
}
}
class UnexpectedGuiException extends Exception { class UnexpectedGuiException extends Exception {
UnexpectedGuiException(Object foundGui) { UnexpectedGuiException(Class<?> guiClass, StackTraceElement[] stackTrace, Object foundGui) {
super("Expected instance of " + guiClass + " but found " + foundGui); super("Expected instance of " + guiClass + " but found " + foundGui);
setStackTrace(Arrays.copyOfRange(stackTrace, 2, stackTrace.length)); setStackTrace(Arrays.copyOfRange(stackTrace, 2, stackTrace.length));
} }
} }
future.setException(new UnexpectedGuiException(foundGui == null ? currentScreen : foundGui));
}
}
FMLCommonHandler.instance().bus().register(new EventHandler());
}
private void clickNow(int x, int y) { private void clickNow(int x, int y) {
try { try {

View File

@@ -10,10 +10,10 @@ import com.replaymod.recording.ExitSPWorld;
import com.replaymod.replay.ExitReplay; import com.replaymod.replay.ExitReplay;
import com.replaymod.replay.LoadReplay; import com.replaymod.replay.LoadReplay;
import com.replaymod.replay.OpenReplayViewer; import com.replaymod.replay.OpenReplayViewer;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import static com.replaymod.core.AbstractTask.mc; import static com.replaymod.core.AbstractTask.mc;

View File

@@ -2,7 +2,7 @@ package com.replaymod.extra;
import com.replaymod.core.AbstractTask; import com.replaymod.core.AbstractTask;
import com.replaymod.extras.OpenEyeExtra; import com.replaymod.extras.OpenEyeExtra;
import net.minecraftforge.fml.common.Loader; import cpw.mods.fml.common.Loader;
import java.io.File; import java.io.File;
import java.nio.file.NoSuchFileException; import java.nio.file.NoSuchFileException;

View File

@@ -1,12 +1,12 @@
package com.replaymod.recording; package com.replaymod.recording;
import com.replaymod.core.AbstractTask; import com.replaymod.core.AbstractTask;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraft.client.gui.GuiCreateWorld; import net.minecraft.client.gui.GuiCreateWorld;
import net.minecraft.client.gui.GuiMainMenu; import net.minecraft.client.gui.GuiMainMenu;
import net.minecraft.client.gui.GuiSelectWorld; import net.minecraft.client.gui.GuiSelectWorld;
import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
public class CreateSPWorld extends AbstractTask { public class CreateSPWorld extends AbstractTask {
@Override @Override
@@ -17,16 +17,17 @@ public class CreateSPWorld extends AbstractTask {
click("Create New World"); click("Create New World");
expectGui(GuiCreateWorld.class, createWorld -> { expectGui(GuiCreateWorld.class, createWorld -> {
click("Create New World"); click("Create New World");
class EventHandler { MinecraftForge.EVENT_BUS.register(new EventHandler());
});
});
});
}
public class EventHandler {
@SubscribeEvent @SubscribeEvent
public void onRenderIngame(RenderGameOverlayEvent.Pre event) { public void onRenderIngame(RenderGameOverlayEvent.Pre event) {
MinecraftForge.EVENT_BUS.unregister(this); MinecraftForge.EVENT_BUS.unregister(this);
runLater(() -> future.set(null)); runLater(() -> future.set(null));
} }
} }
MinecraftForge.EVENT_BUS.register(new EventHandler());
});
});
});
}
} }

View File

@@ -2,10 +2,10 @@ package com.replaymod.replay;
import com.replaymod.core.AbstractTask; import com.replaymod.core.AbstractTask;
import com.replaymod.replay.gui.screen.GuiReplayViewer; import com.replaymod.replay.gui.screen.GuiReplayViewer;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import de.johni0702.minecraft.gui.function.Clickable; import de.johni0702.minecraft.gui.function.Clickable;
import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.lwjgl.util.Point; import org.lwjgl.util.Point;
import org.lwjgl.util.ReadableDimension; import org.lwjgl.util.ReadableDimension;
@@ -19,14 +19,15 @@ public class LoadReplay extends AbstractTask {
// Load first replay // Load first replay
click(replayViewer.loadButton); click(replayViewer.loadButton);
class EventHandler { MinecraftForge.EVENT_BUS.register(new EventHandler());
}));
}
public class EventHandler {
@SubscribeEvent @SubscribeEvent
public void onRenderIngame(RenderGameOverlayEvent.Pre event) { public void onRenderIngame(RenderGameOverlayEvent.Pre event) {
MinecraftForge.EVENT_BUS.unregister(this); MinecraftForge.EVENT_BUS.unregister(this);
runLater(() -> future.set(null)); runLater(() -> future.set(null));
} }
} }
MinecraftForge.EVENT_BUS.register(new EventHandler());
}));
}
} }

View File

@@ -2,8 +2,8 @@ package com.replaymod.replay;
import com.replaymod.core.AbstractTask; import com.replaymod.core.AbstractTask;
import com.replaymod.extras.playeroverview.PlayerOverviewGui; import com.replaymod.extras.playeroverview.PlayerOverviewGui;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent; import cpw.mods.fml.common.gameevent.TickEvent;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
@@ -34,7 +34,7 @@ public class SpectatePlayer extends AbstractTask {
future.setException(new TimeoutException("Camera hasn't stopped spectating.")); future.setException(new TimeoutException("Camera hasn't stopped spectating."));
return; return;
} }
if (mc.getRenderViewEntity() == mc.thePlayer) { if (mc.renderViewEntity == mc.thePlayer) {
future.set(null); future.set(null);
} }
} }

View File

@@ -3,11 +3,10 @@ package com.replaymod.compat;
import com.replaymod.compat.bettersprinting.DisableBetterSprinting; import com.replaymod.compat.bettersprinting.DisableBetterSprinting;
import com.replaymod.compat.optifine.DisableFastRender; import com.replaymod.compat.optifine.DisableFastRender;
import com.replaymod.compat.oranges17animations.HideInvisibleEntities; import com.replaymod.compat.oranges17animations.HideInvisibleEntities;
import com.replaymod.compat.shaders.ShaderBeginRender; import cpw.mods.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLCommonHandler; import cpw.mods.fml.common.Mod;
import net.minecraftforge.fml.common.Mod; import cpw.mods.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.eventhandler.EventBus;
import net.minecraftforge.fml.common.eventhandler.EventBus;
@Mod(modid = ReplayModCompat.MOD_ID, @Mod(modid = ReplayModCompat.MOD_ID,
version = "@MOD_VERSION@", version = "@MOD_VERSION@",
@@ -20,7 +19,6 @@ public class ReplayModCompat {
@Mod.EventHandler @Mod.EventHandler
public void init(FMLInitializationEvent event) { public void init(FMLInitializationEvent event) {
EventBus bus = FMLCommonHandler.instance().bus(); EventBus bus = FMLCommonHandler.instance().bus();
bus.register(new ShaderBeginRender());
bus.register(new DisableFastRender()); bus.register(new DisableFastRender());
bus.register(new HideInvisibleEntities()); bus.register(new HideInvisibleEntities());
DisableBetterSprinting.register(); DisableBetterSprinting.register();

View File

@@ -2,21 +2,20 @@ package com.replaymod.compat.bettersprinting;
import com.replaymod.replay.ReplayModReplay; import com.replaymod.replay.ReplayModReplay;
import com.replaymod.replay.events.ReplayChatMessageEvent; import com.replaymod.replay.events.ReplayChatMessageEvent;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.eventhandler.EventPriority;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
import cpw.mods.fml.common.versioning.Restriction;
import cpw.mods.fml.common.versioning.VersionRange;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.PlayerControllerMP; import net.minecraft.client.multiplayer.PlayerControllerMP;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.BlockPos;
import net.minecraft.world.IWorldAccess; import net.minecraft.world.IWorldAccess;
import net.minecraftforge.client.event.GuiOpenEvent; import net.minecraftforge.client.event.GuiOpenEvent;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.ModContainer;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.versioning.DefaultArtifactVersion;
import net.minecraftforge.fml.common.versioning.Restriction;
import net.minecraftforge.fml.common.versioning.VersionRange;
import java.util.Collections; import java.util.Collections;
@@ -74,7 +73,7 @@ public class DisableBetterSprinting {
private class BetterSprintingWorldAccess implements IWorldAccess { private class BetterSprintingWorldAccess implements IWorldAccess {
@Override @Override
public void onEntityRemoved(Entity entityIn) { public void onEntityDestroy(Entity entityIn) {
if (mc.playerController != null && mc.playerController.getClass().getName().equals(CONTROLLER_OVERRIDE_CLASS_NAME)) { if (mc.playerController != null && mc.playerController.getClass().getName().equals(CONTROLLER_OVERRIDE_CLASS_NAME)) {
// Someone has secretly swapped out the player controller and is about to substitute their own player entity. // Someone has secretly swapped out the player controller and is about to substitute their own player entity.
// This is the right time to destroy their plan. // This is the right time to destroy their plan.
@@ -82,16 +81,17 @@ public class DisableBetterSprinting {
} }
} }
@Override public void markBlockForUpdate(BlockPos pos) {} @Override public void markBlockForUpdate(int x, int y, int z) {}
@Override public void notifyLightSet(BlockPos pos) {} @Override public void markBlockForRenderUpdate(int p_147588_1_, int p_147588_2_, int p_147588_3_) {}
@Override public void markBlockRangeForRenderUpdate(int x1, int y1, int z1, int x2, int y2, int z2) {} @Override public void markBlockRangeForRenderUpdate(int x1, int y1, int z1, int x2, int y2, int z2) {}
@Override public void playSound(String soundName, double x, double y, double z, float volume, float pitch) {} @Override public void playSound(String soundName, double x, double y, double z, float volume, float pitch) {}
@Override public void playSoundToNearExcept(EntityPlayer except, String soundName, double x, double y, double z, float volume, float pitch) {} @Override public void playSoundToNearExcept(EntityPlayer except, String soundName, double x, double y, double z, float volume, float pitch) {}
@Override public void spawnParticle(int p_180442_1_, boolean p_180442_2_, double p_180442_3_, double p_180442_5_, double p_180442_7_, double p_180442_9_, double p_180442_11_, double p_180442_13_, int... p_180442_15_) {} @Override public void spawnParticle(String p_180442_1_, double p_180442_2_, double p_180442_3_, double p_180442_5_, double p_180442_7_, double p_180442_9_, double p_180442_11_) {}
@Override public void onEntityAdded(Entity entityIn) {} @Override public void onEntityCreate(Entity p_72703_1_) {}
@Override public void playRecord(String recordName, BlockPos blockPosIn) {} @Override public void playRecord(String recordName, int x, int y, int z) {}
@Override public void broadcastSound(int p_180440_1_, BlockPos p_180440_2_, int p_180440_3_) {} @Override public void broadcastSound(int p_180440_1_, int x, int y, int z, int p_180440_3_) {}
@Override public void playAusSFX(EntityPlayer p_180439_1_, int p_180439_2_, BlockPos blockPosIn, int p_180439_4_) {} @Override public void playAuxSFX(EntityPlayer p_72706_1_, int p_72706_2_, int p_72706_3_, int p_72706_4_, int p_72706_5_, int p_72706_6_) {}
@Override public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) {} @Override public void destroyBlockPartially(int p_147587_1_, int p_147587_2_, int p_147587_3_, int p_147587_4_, int p_147587_5_) {}
@Override public void onStaticEntitiesChanged() {}
} }
} }

View File

@@ -1,10 +1,11 @@
package com.replaymod.compat.optifine; package com.replaymod.compat.optifine;
import com.replaymod.render.events.ReplayRenderEvent; import com.replaymod.render.events.ReplayRenderEvent;
import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
// TODO 1.7.10: Is this still necessary (probably, but needs checking)?
public class DisableFastRender { public class DisableFastRender {
private final Minecraft mc = Minecraft.getMinecraft(); private final Minecraft mc = Minecraft.getMinecraft();

View File

@@ -1,11 +1,11 @@
package com.replaymod.compat.oranges17animations; package com.replaymod.compat.oranges17animations;
import com.replaymod.replay.camera.CameraEntity; import com.replaymod.replay.camera.CameraEntity;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.eventhandler.EventPriority;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraftforge.client.event.RenderLivingEvent; import net.minecraftforge.client.event.RenderLivingEvent;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
/** /**
* Orange seems to have copied vast parts of the RendererLivingEntity into their ArmorAnimation class which cancels the RenderLivingEvent.Pre and calls its own code instead. * Orange seems to have copied vast parts of the RendererLivingEntity into their ArmorAnimation class which cancels the RenderLivingEvent.Pre and calls its own code instead.

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

@@ -0,0 +1,50 @@
package com.replaymod.compat.shaders.mixin;
import com.replaymod.render.hooks.EntityRendererHandler;
import com.replaymod.replay.ReplayHandler;
import com.replaymod.replay.ReplayModReplay;
import net.minecraft.client.Minecraft;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Pseudo;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Pseudo
@Mixin(targets = "shadersmod/client/Shaders", remap = false)
public abstract class MixinShaders {
@Shadow static Minecraft mc;
@Shadow static long systemTime;
@Shadow static long lastSystemTime;
@Shadow static long diffSystemTime;
@Shadow static int frameCounter;
@Shadow static float frameTime;
@Shadow static float frameTimeCounter;
@Redirect(method = "beginRender", at = @At(value = "INVOKE", target = "Ljava/lang/System;currentTimeMillis()J"))
private static long replayModCompat_currentTimeMillis() {
ReplayHandler replayHandler = ReplayModReplay.instance.getReplayHandler();
if (replayHandler != null) {
systemTime = replayHandler.getReplaySender().currentTimeStamp();
// We need to manipulate all the other previous-frame-time-based variables too
lastSystemTime = 0; // Draw all frames as if they were the first ones
// diffSystemTime will be set to 0 by Shaders
// frameTime will be set to 0 by Shaders
frameTimeCounter = systemTime / 1000f; // will be %= 3600f by Shaders
// Set frameCounter only if rendering is in progress
EntityRendererHandler entityRendererHandler =
((EntityRendererHandler.IEntityRenderer) mc.entityRenderer).replayModRender_getHandler();
if (entityRendererHandler != null) {
frameCounter = entityRendererHandler.getRenderInfo().getFramesDone();
}
return systemTime;
}
return System.currentTimeMillis();
}
}

View File

@@ -0,0 +1,94 @@
package com.replaymod.core;
import net.minecraft.launchwrapper.IClassTransformer;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
/**
* Insert glGetError checks after all calls to any method in any GL*, ARB* and EXT* classes
*/
public class GLErrorTransformer implements IClassTransformer {
private static final String GL_CLASS = "org.lwjgl.opengl.GL";
private static final String GL = GL_CLASS.replace('.', '/');
private static final String ARB_CLASS = "org.lwjgl.opengl.ARB";
private static final String ARB = ARB_CLASS.replace('.', '/');
private static final String EXT_CLASS = "org.lwjgl.opengl.EXT";
private static final String EXT = EXT_CLASS.replace('.', '/');
private static final String GLErrorTransformer_CLASS = GLErrorTransformer.class.getName();
private static final String GLErrorTransformer = GLErrorTransformer_CLASS.replace('.', '/');
@Override
public byte[] transform(String name, String transformedName, byte[] basicClass) {
// Ignore (anonymous) inner classes of this transformer
if (name.startsWith(GLErrorTransformer_CLASS)) return basicClass;
ClassReader reader = new ClassReader(basicClass);
ClassWriter writer = new ClassWriter(reader, 0);
reader.accept(new ClassVisitor(Opcodes.ASM5, writer) {
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
return new MethodVisitor(Opcodes.ASM5, mv) {
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
super.visitMethodInsn(opcode, owner, name, desc, itf);
if (owner.startsWith(GL) || owner.startsWith(ARB) || owner.startsWith(EXT)) {
visitLdcInsn(owner.replace('/', '.'));
visitLdcInsn(name);
super.visitMethodInsn(Opcodes.INVOKESTATIC, GLErrorTransformer, "glErrorCheck", "(Ljava/lang/String;Ljava/lang/String;)V", false);
}
}
@Override
public void visitMaxs(int maxStack, int maxLocals) {
super.visitMaxs(maxStack + 2, maxLocals);
}
};
}
}, 0);
return writer.toByteArray();
}
private static boolean inGlBegin;
@SuppressWarnings("unused") // Called via ASM
public static void glErrorCheck(String cls, String method) {
if (method.equals("glBegin") && cls.equals(GL_CLASS + "11")) {
if (inGlBegin) {
// glBegin within glBegin
throw new GLError(GL11.GL_INVALID_OPERATION, cls, method);
}
inGlBegin = true;
return;
}
if (inGlBegin && method.equals("glEnd") && cls.equals(GL_CLASS + "11")) {
inGlBegin = false;
}
if (inGlBegin) {
return; // Cannot call glGetError in between of glBegin and glEnd
}
int err = GL11.glGetError();
if (err != 0) {
GLError e = new GLError(err, cls, method);
if ("true".equals(System.getProperty("replaymod.glerrors.throw", "true"))) {
throw e;
} else {
e.printStackTrace();
}
}
}
public static class GLError extends RuntimeException {
private GLError(int err, String cls, String method) {
super(GLU.gluErrorString(err) + " (" + err + ")");
StackTraceElement[] stack = getStackTrace();
stack[0] = new StackTraceElement(cls, method, stack[0].getFileName(), stack[0].getLineNumber());
setStackTrace(stack);
}
}
}

View File

@@ -0,0 +1,105 @@
package com.replaymod.core;
import net.minecraft.launchwrapper.IClassTransformer;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import java.util.HashSet;
import java.util.Set;
/**
* Redirect all calls to GL11.glEnable and GL11.glDisable to the GLStateTracker (excluding that class itself).
*/
public class GLStateTrackerTransformer implements IClassTransformer {
private static final String GL11_CLASS = "org.lwjgl.opengl.GL11";
private static final String GL11 = GL11_CLASS.replace('.', '/');
private static final String glEnable = "glEnable";
private static final String glDisable = "glDisable";
private static final String GLStateTracker_CLASS = "com.replaymod.render.hooks.GLStateTracker";
private static final String GLStateTracker = GLStateTracker_CLASS.replace('.', '/');
private static final String hook_glEnable = "hook_glEnable";
private static final String hook_glDisable = "hook_glDisable";
@Override
public byte[] transform(String name, String transformedName, byte[] basicClass) {
// Ignore (anonymous) inner classes of this transformer
if (name.startsWith(GLStateTrackerTransformer.class.getName())) return basicClass;
// Ignore the state tracker itself
if (name.equals(GLStateTracker_CLASS)) return basicClass;
ClassReader reader = new ClassReader(basicClass);
Set<Method> eligibleMethods = findEligibleMethods(reader);
if (eligibleMethods.isEmpty()) {
return basicClass;
}
ClassWriter writer = new ClassWriter(reader, 0);
reader.accept(new ClassVisitor(Opcodes.ASM5, writer) {
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
if (!eligibleMethods.contains(new Method(name, desc))) {
return mv;
}
return new MethodVisitor(Opcodes.ASM5, mv) {
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
if (owner.equals(GL11)) {
if (name.equals(glEnable)) {
owner = GLStateTracker;
name = hook_glEnable;
} else if (name.equals(glDisable)) {
owner = GLStateTracker;
name = hook_glDisable;
}
}
super.visitMethodInsn(opcode, owner, name, desc, itf);
}
};
}
}, 0);
return writer.toByteArray();
}
private Set<Method> findEligibleMethods(ClassReader reader) {
Set<Method> eligibleMethods = new HashSet<>();
reader.accept(new ClassVisitor(Opcodes.ASM5) {
@Override
public MethodVisitor visitMethod(int access, String methodName, String methodDesc, String signature, String[] exceptions) {
return new MethodVisitor(Opcodes.ASM5) {
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
if (owner.equals(GL11) && (name.equals(glEnable) || name.equals(glDisable))) {
eligibleMethods.add(new Method(methodName, methodDesc));
}
}
};
}
}, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
return eligibleMethods;
}
private static class Method {
private final String name, desc;
private Method(String name, String desc) {
this.name = name;
this.desc = desc;
}
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
Method method = (Method) o;
return name.equals(method.name) && desc.equals(method.desc);
}
@Override
public int hashCode() {
return name.hashCode() ^ desc.hashCode();
}
}
}

View File

@@ -2,14 +2,14 @@ package com.replaymod.core;
import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import cpw.mods.fml.client.registry.ClientRegistry;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.InputEvent;
import cpw.mods.fml.common.gameevent.TickEvent;
import net.minecraft.client.settings.KeyBinding; import net.minecraft.client.settings.KeyBinding;
import net.minecraft.crash.CrashReport; import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory; import net.minecraft.crash.CrashReportCategory;
import net.minecraft.util.ReportedException; import net.minecraft.util.ReportedException;
import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.InputEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
import java.util.Collection; import java.util.Collection;
@@ -64,7 +64,7 @@ public class KeyBindingRegistry {
public void handleRepeatedKeyBindings() { public void handleRepeatedKeyBindings() {
for (Map.Entry<KeyBinding, Collection<Runnable>> entry : repeatedKeyBindingHandlers.asMap().entrySet()) { for (Map.Entry<KeyBinding, Collection<Runnable>> entry : repeatedKeyBindingHandlers.asMap().entrySet()) {
if (entry.getKey().isKeyDown()) { if (entry.getKey().getIsKeyPressed()) {
invokeKeyBindingHandlers(entry.getKey(), entry.getValue()); invokeKeyBindingHandlers(entry.getKey(), entry.getValue());
} }
} }

View File

@@ -1,7 +1,7 @@
package com.replaymod.core; package com.replaymod.core;
import net.minecraftforge.fml.relauncher.CoreModManager; import cpw.mods.fml.relauncher.CoreModManager;
import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.spongepowered.asm.launch.MixinBootstrap; import org.spongepowered.asm.launch.MixinBootstrap;
import org.spongepowered.asm.mixin.Mixins; import org.spongepowered.asm.mixin.Mixins;
@@ -10,6 +10,8 @@ import java.io.File;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.security.CodeSource; import java.security.CodeSource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;
public class LoadingPlugin implements IFMLLoadingPlugin { public class LoadingPlugin implements IFMLLoadingPlugin {
@@ -31,6 +33,7 @@ public class LoadingPlugin implements IFMLLoadingPlugin {
// This forces forge to reexamine the jar file for FML mods // This forces forge to reexamine the jar file for FML mods
// Should eventually be handled by Mixin itself, maybe? // Should eventually be handled by Mixin itself, maybe?
CoreModManager.getLoadedCoremods().remove(file.getName()); CoreModManager.getLoadedCoremods().remove(file.getName());
CoreModManager.getReparseableCoremods().add(file.getName());
} }
} catch (URISyntaxException e) { } catch (URISyntaxException e) {
e.printStackTrace(); e.printStackTrace();
@@ -43,8 +46,12 @@ public class LoadingPlugin implements IFMLLoadingPlugin {
@Override @Override
public String[] getASMTransformerClass() { public String[] getASMTransformerClass() {
return new String[]{ List<String> transformers = new ArrayList<>();
}; if ("true".equals(System.getProperty("replaymod.glerrors", "false"))) {
transformers.add(GLErrorTransformer.class.getName());
}
transformers.add(GLStateTrackerTransformer.class.getName());
return transformers.stream().toArray(String[]::new);
} }
@Override @Override

View File

@@ -7,32 +7,38 @@ import com.replaymod.core.gui.RestoreReplayGui;
import com.replaymod.core.handler.MainMenuHandler; import com.replaymod.core.handler.MainMenuHandler;
import com.replaymod.core.utils.OpenGLUtils; import com.replaymod.core.utils.OpenGLUtils;
import com.replaymod.render.utils.SoundHandler; import com.replaymod.render.utils.SoundHandler;
import com.replaymod.replay.InputReplayTimer;
import com.replaymod.replaystudio.util.I18n; import com.replaymod.replaystudio.util.I18n;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.Mod.Instance;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.eventhandler.EventBus;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.TickEvent;
import de.johni0702.minecraft.gui.container.GuiScreen; import de.johni0702.minecraft.gui.container.GuiScreen;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.crash.CrashReport; import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory; import net.minecraft.crash.CrashReportCategory;
import net.minecraft.util.*; import net.minecraft.util.ChatComponentText;
import net.minecraft.util.ChatComponentTranslation;
import net.minecraft.util.ChatStyle;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.IChatComponent;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.config.Configuration; 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;
import net.minecraftforge.fml.common.Mod.Instance;
import net.minecraftforge.fml.common.ModContainer;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.EventBus;
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.FileUtils;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayDeque;
import java.util.List; import java.util.List;
import java.util.Queue; import java.util.Queue;
@@ -41,7 +47,6 @@ import java.util.Queue;
version = "@MOD_VERSION@", version = "@MOD_VERSION@",
acceptedMinecraftVersions = "@MC_VERSION@", acceptedMinecraftVersions = "@MC_VERSION@",
acceptableRemoteVersions = "*", acceptableRemoteVersions = "*",
updateJSON = "https://raw.githubusercontent.com/ReplayMod/ReplayMod/master/versions.json",
guiFactory = "com.replaymod.core.gui.GuiFactory") guiFactory = "com.replaymod.core.gui.GuiFactory")
public class ReplayMod { public class ReplayMod {
@@ -54,10 +59,10 @@ public class ReplayMod {
private static String parseMinecraftVersion() { private static String parseMinecraftVersion() {
CrashReport crashReport = new CrashReport("", new Throwable()); CrashReport crashReport = new CrashReport("", new Throwable());
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<CrashReportCategory.Entry> list = crashReport.getCategory().children; List<CrashReportCategory.Entry> list = crashReport.getCategory().field_85077_c;
for (CrashReportCategory.Entry entry : list) { for (CrashReportCategory.Entry entry : list) {
if ("Minecraft Version".equals(entry.getKey())) { if ("Minecraft Version".equals(entry.func_85089_a())) {
return entry.getValue(); return entry.func_85090_b();
} }
} }
return "Unknown"; return "Unknown";
@@ -116,6 +121,7 @@ public class ReplayMod {
new MainMenuHandler().register(); new MainMenuHandler().register();
FMLCommonHandler.instance().bus().register(this);
FMLCommonHandler.instance().bus().register(keyBindingRegistry); FMLCommonHandler.instance().bus().register(keyBindingRegistry);
getKeyBindingRegistry().registerKeyBinding("replaymod.input.settings", 0, () -> { getKeyBindingRegistry().registerKeyBinding("replaymod.input.settings", 0, () -> {
@@ -127,8 +133,10 @@ public class ReplayMod {
public void postInit(FMLPostInitializationEvent event) throws IOException { public void postInit(FMLPostInitializationEvent event) throws IOException {
settingsRegistry.save(); // Save default values to disk settingsRegistry.save(); // Save default values to disk
/* TODO 1.7.10: MC crashes when setting render distance to > 16
if(!FMLClientHandler.instance().hasOptifine()) if(!FMLClientHandler.instance().hasOptifine())
GameSettings.Options.RENDER_DISTANCE.setValueMax(64f); GameSettings.Options.RENDER_DISTANCE.setValueMax(64f);
*/
if (System.getProperty("replaymod.render.file") != null) { if (System.getProperty("replaymod.render.file") != null) {
final File file = new File(System.getProperty("replaymod.render.file")); final File file = new File(System.getProperty("replaymod.render.file"));
@@ -316,24 +324,17 @@ public class ReplayMod {
*/ */
private boolean inRunLater = false; private boolean inRunLater = false;
// 1.7.10: Cannot use MC's because it is processed only during ticks (so not at all when replay is paused)
private final Queue<ListenableFutureTask<?>> scheduledTasks = new ArrayDeque<>();
public void runLater(Runnable runnable) { public void runLater(Runnable runnable) {
if (mc.isCallingFromMinecraftThread() && inRunLater) { if (mc.isCallingFromMinecraftThread() && inRunLater) {
EventBus bus = FMLCommonHandler.instance().bus(); EventBus bus = FMLCommonHandler.instance().bus();
bus.register(new Object() { bus.register(new RunLaterHelper(runnable));
@SubscribeEvent
public void onRenderTick(TickEvent.RenderTickEvent event) {
if (event.phase == TickEvent.Phase.START) {
runLater(runnable);
bus.unregister(this);
}
}
});
return; return;
} }
@SuppressWarnings("unchecked") synchronized (scheduledTasks) {
Queue<ListenableFutureTask> tasks = mc.scheduledTasks; scheduledTasks.add(ListenableFutureTask.create(() -> {
synchronized (mc.scheduledTasks) {
tasks.add(ListenableFutureTask.create(() -> {
inRunLater = true; inRunLater = true;
try { try {
runnable.run(); runnable.run();
@@ -344,6 +345,28 @@ public class ReplayMod {
} }
} }
// in 1.7.10 apparently events can't be delivered to anonymous classes
@RequiredArgsConstructor
public class RunLaterHelper {
private final Runnable runnable;
@SubscribeEvent
public void onRenderTick(TickEvent.RenderTickEvent event) {
if (event.phase == TickEvent.Phase.START) {
runLater(runnable);
FMLCommonHandler.instance().bus().unregister(this);
}
}
}
@SubscribeEvent
public void runScheduledTasks(InputReplayTimer.RunScheduledTasks event) {
synchronized (scheduledTasks) {
while (!scheduledTasks.isEmpty()) {
scheduledTasks.poll().run();
}
}
}
public String getVersion() { public String getVersion() {
return getContainer().getVersion(); return getContainer().getVersion();
} }

View File

@@ -1,9 +1,9 @@
package com.replaymod.core; package com.replaymod.core;
import com.replaymod.core.events.SettingsChangedEvent; import com.replaymod.core.events.SettingsChangedEvent;
import cpw.mods.fml.common.FMLCommonHandler;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
import net.minecraftforge.common.config.Configuration; import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.fml.common.FMLCommonHandler;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;

View File

@@ -1,9 +1,9 @@
package com.replaymod.core.events; package com.replaymod.core.events;
import com.replaymod.core.SettingsRegistry; import com.replaymod.core.SettingsRegistry;
import cpw.mods.fml.common.eventhandler.Event;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import net.minecraftforge.fml.common.eventhandler.Event;
@RequiredArgsConstructor @RequiredArgsConstructor
public class SettingsChangedEvent extends Event { public class SettingsChangedEvent extends Event {

View File

@@ -1,9 +1,9 @@
package com.replaymod.core.gui; package com.replaymod.core.gui;
import com.replaymod.core.ReplayMod; import com.replaymod.core.ReplayMod;
import cpw.mods.fml.client.IModGuiFactory;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraftforge.fml.client.IModGuiFactory;
import java.util.Set; import java.util.Set;

View File

@@ -1,10 +1,10 @@
package com.replaymod.core.handler; package com.replaymod.core.handler;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiMainMenu; import net.minecraft.client.gui.GuiMainMenu;
import net.minecraftforge.client.event.GuiScreenEvent; import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import java.util.List; import java.util.List;

View File

@@ -1,10 +1,9 @@
package com.replaymod.core.utils; package com.replaymod.core.utils;
import com.replaymod.replaystudio.data.ModInfo; import com.replaymod.replaystudio.data.ModInfo;
import net.minecraft.util.ResourceLocation; import cpw.mods.fml.common.Loader;
import net.minecraftforge.fml.common.Loader; import cpw.mods.fml.common.ModContainer;
import net.minecraftforge.fml.common.ModContainer; import cpw.mods.fml.common.registry.GameData;
import net.minecraftforge.fml.common.registry.GameData;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.function.Function;
@@ -17,14 +16,19 @@ public class ModCompat {
Map<String, ModContainer> ignoreCaseMap = Loader.instance().getModList().stream() Map<String, ModContainer> ignoreCaseMap = Loader.instance().getModList().stream()
.collect(Collectors.toMap(m -> m.getModId().toLowerCase(), Function.identity())); .collect(Collectors.toMap(m -> m.getModId().toLowerCase(), Function.identity()));
return Stream.concat( return Stream.concat(
((Set<ResourceLocation>) GameData.getBlockRegistry().getKeys()).stream(), ((Set<String>) GameData.getBlockRegistry().getKeys()).stream(),
((Set<ResourceLocation>) GameData.getItemRegistry().getKeys()).stream() ((Set<String>) GameData.getItemRegistry().getKeys()).stream()
).map(ResourceLocation::getResourceDomain).filter(s -> !s.equals("minecraft")).distinct() ).map(ModCompat::getResourceDomain).filter(s -> !s.equals("minecraft")).distinct()
.map(String::toLowerCase).map(ignoreCaseMap::get).filter(mod -> mod != null) .map(String::toLowerCase).map(ignoreCaseMap::get).filter(mod -> mod != null)
.map(mod -> new ModInfo(mod.getModId(), mod.getName(), mod.getVersion())) .map(mod -> new ModInfo(mod.getModId(), mod.getName(), mod.getVersion()))
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
private static String getResourceDomain(String name) {
if (!name.contains(":")) return null; // Still using old names without namespace, can't do anything, ignore
return name.split(":", 2)[0];
}
public static final class ModInfoDifference { public static final class ModInfoDifference {
private final Set<ModInfo> missing = new HashSet<>(); private final Set<ModInfo> missing = new HashSet<>();
private final Map<ModInfo, String> differing = new HashMap<>(); private final Map<ModInfo, String> differing = new HashMap<>();

View File

@@ -1,8 +1,6 @@
package com.replaymod.core.utils; package com.replaymod.core.utils;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import org.lwjgl.BufferUtils; import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
@@ -28,22 +26,21 @@ public class OpenGLUtils {
} }
public static void drawRotatedRectWithCustomSizedTexture(int x, int y, float rotation, float u, float v, int width, int height, float textureWidth, float textureHeight) { public static void drawRotatedRectWithCustomSizedTexture(int x, int y, float rotation, float u, float v, int width, int height, float textureWidth, float textureHeight) {
GlStateManager.pushMatrix(); GL11.glPushMatrix();
float f4 = 1.0F / textureWidth; float f4 = 1.0F / textureWidth;
float f5 = 1.0F / textureHeight; float f5 = 1.0F / textureHeight;
Tessellator tessellator = Tessellator.getInstance(); Tessellator tessellator = Tessellator.instance;
WorldRenderer worldrenderer = tessellator.getWorldRenderer(); GL11.glTranslatef(x+(width/2), y+(width/2), 0);
GlStateManager.translate(x+(width/2), y+(width/2), 0); GL11.glRotatef(rotation, 0, 0, 1);
GlStateManager.rotate(rotation, 0, 0, 1); tessellator.startDrawingQuads();
worldrenderer.startDrawingQuads(); tessellator.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 * f4), (double) ((v + (float) height) * f5)); tessellator.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 + (float)height) * f5)); tessellator.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 + (float)width) * f4), (double)(v * f5)); tessellator.addVertexWithUV(-width/2, -height/2, 0.0D, (double)(u * f4), (double)(v * f5));
worldrenderer.addVertexWithUV(-width/2, -height/2, 0.0D, (double)(u * f4), (double)(v * f5));
tessellator.draw(); tessellator.draw();
GlStateManager.popMatrix(); GL11.glPopMatrix();
} }
} }

View File

@@ -1,8 +1,11 @@
package com.replaymod.core.utils; package com.replaymod.core.utils;
import io.netty.buffer.Unpooled;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraft.network.play.server.S3FPacketCustomPayload; import net.minecraft.network.play.server.S3FPacketCustomPayload;
import java.io.IOException;
/** /**
* Restrictions set by the server, * Restrictions set by the server,
* @see <a href="https://gist.github.com/Johni0702/2547c463e51f65f312cb">Replay Restrictions Gist</a> * @see <a href="https://gist.github.com/Johni0702/2547c463e51f65f312cb">Replay Restrictions Gist</a>
@@ -14,8 +17,8 @@ public class Restrictions {
private boolean onlyFirstPerson; private boolean onlyFirstPerson;
private boolean onlyRecordingPlayer; private boolean onlyRecordingPlayer;
public String handle(S3FPacketCustomPayload packet) { public String handle(S3FPacketCustomPayload packet) throws IOException {
PacketBuffer buffer = packet.getBufferData(); PacketBuffer buffer = new PacketBuffer(Unpooled.wrappedBuffer(packet.func_149168_d()));
while (buffer.isReadable()) { while (buffer.isReadable()) {
String name = buffer.readStringFromBuffer(64); String name = buffer.readStringFromBuffer(64);
boolean active = buffer.readBoolean(); boolean active = buffer.readBoolean();

View File

@@ -18,10 +18,11 @@ import de.johni0702.minecraft.gui.layout.VerticalLayout;
import de.johni0702.minecraft.gui.popup.GuiInfoPopup; import de.johni0702.minecraft.gui.popup.GuiInfoPopup;
import de.johni0702.minecraft.gui.utils.Colors; import de.johni0702.minecraft.gui.utils.Colors;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.AbstractClientPlayer;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.network.NetworkPlayerInfo;
import net.minecraft.client.resources.DefaultPlayerSkin;
import net.minecraft.crash.CrashReport; import net.minecraft.crash.CrashReport;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import org.apache.commons.io.Charsets; import org.apache.commons.io.Charsets;
import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.FilenameUtils;
@@ -160,14 +161,11 @@ public class Utils {
} }
public static ResourceLocation getResourceLocationForPlayerUUID(UUID uuid) { public static ResourceLocation getResourceLocationForPlayerUUID(UUID uuid) {
NetworkPlayerInfo info = getMinecraft().getNetHandler().getPlayerInfo(uuid); EntityPlayer player = Minecraft.getMinecraft().theWorld.getPlayerEntityByUUID(uuid);
ResourceLocation skinLocation; if (player == null || !(player instanceof AbstractClientPlayer)) {
if (info != null && info.hasLocationSkin()) { return AbstractClientPlayer.locationStevePng;
skinLocation = info.getLocationSkin();
} else {
skinLocation = DefaultPlayerSkin.getDefaultSkin(uuid);
} }
return skinLocation; return ((AbstractClientPlayer) player).getLocationSkin();
} }
public static boolean isCtrlDown() { public static boolean isCtrlDown() {

View File

@@ -3,9 +3,9 @@ package com.replaymod.editor;
import com.replaymod.core.ReplayMod; import com.replaymod.core.ReplayMod;
import com.replaymod.editor.handler.GuiHandler; import com.replaymod.editor.handler.GuiHandler;
import com.replaymod.online.Setting; import com.replaymod.online.Setting;
import net.minecraftforge.fml.common.Mod; import cpw.mods.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@Mod(modid = ReplayModEditor.MOD_ID, @Mod(modid = ReplayModEditor.MOD_ID,

View File

@@ -2,14 +2,14 @@ package com.replaymod.editor.handler;
import com.replaymod.editor.ReplayModEditor; import com.replaymod.editor.ReplayModEditor;
import com.replaymod.editor.gui.GuiReplayEditor; import com.replaymod.editor.gui.GuiReplayEditor;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import de.johni0702.minecraft.gui.container.GuiScreen; import de.johni0702.minecraft.gui.container.GuiScreen;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiMainMenu; import net.minecraft.client.gui.GuiMainMenu;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
import net.minecraftforge.client.event.GuiScreenEvent; import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import java.util.List; import java.util.List;

View File

@@ -5,13 +5,13 @@ import com.replaymod.replay.ReplayHandler;
import com.replaymod.replay.ReplayModReplay; import com.replaymod.replay.ReplayModReplay;
import com.replaymod.replay.events.ReplayOpenEvent; import com.replaymod.replay.events.ReplayOpenEvent;
import com.replaymod.replay.gui.overlay.GuiReplayOverlay; import com.replaymod.replay.gui.overlay.GuiReplayOverlay;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.TickEvent;
import de.johni0702.minecraft.gui.element.GuiImage; import de.johni0702.minecraft.gui.element.GuiImage;
import de.johni0702.minecraft.gui.element.IGuiImage; import de.johni0702.minecraft.gui.element.IGuiImage;
import de.johni0702.minecraft.gui.layout.HorizontalLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout;
import net.minecraft.client.settings.GameSettings; import net.minecraft.client.settings.GameSettings;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
public class FullBrightness implements Extra { public class FullBrightness implements Extra {

View File

@@ -4,6 +4,8 @@ import com.replaymod.core.KeyBindingRegistry;
import com.replaymod.core.ReplayMod; import com.replaymod.core.ReplayMod;
import com.replaymod.replay.events.ReplayOpenEvent; import com.replaymod.replay.events.ReplayOpenEvent;
import com.replaymod.replay.gui.overlay.GuiReplayOverlay; import com.replaymod.replay.gui.overlay.GuiReplayOverlay;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import de.johni0702.minecraft.gui.GuiRenderer; import de.johni0702.minecraft.gui.GuiRenderer;
import de.johni0702.minecraft.gui.RenderInfo; import de.johni0702.minecraft.gui.RenderInfo;
import de.johni0702.minecraft.gui.container.GuiContainer; import de.johni0702.minecraft.gui.container.GuiContainer;
@@ -17,8 +19,6 @@ import de.johni0702.minecraft.gui.layout.GridLayout;
import de.johni0702.minecraft.gui.layout.HorizontalLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout;
import de.johni0702.minecraft.gui.layout.LayoutData; import de.johni0702.minecraft.gui.layout.LayoutData;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
import org.lwjgl.util.Dimension; import org.lwjgl.util.Dimension;
import org.lwjgl.util.ReadableDimension; import org.lwjgl.util.ReadableDimension;

View File

@@ -2,6 +2,7 @@ package com.replaymod.extras;
import com.replaymod.core.ReplayMod; import com.replaymod.core.ReplayMod;
import com.replaymod.core.Setting; import com.replaymod.core.Setting;
import cpw.mods.fml.common.Loader;
import de.johni0702.minecraft.gui.container.AbstractGuiScreen; import de.johni0702.minecraft.gui.container.AbstractGuiScreen;
import de.johni0702.minecraft.gui.container.GuiContainer; import de.johni0702.minecraft.gui.container.GuiContainer;
import de.johni0702.minecraft.gui.container.GuiPanel; import de.johni0702.minecraft.gui.container.GuiPanel;
@@ -14,7 +15,6 @@ import de.johni0702.minecraft.gui.layout.HorizontalLayout;
import de.johni0702.minecraft.gui.layout.VerticalLayout; import de.johni0702.minecraft.gui.layout.VerticalLayout;
import de.johni0702.minecraft.gui.popup.AbstractGuiPopup; import de.johni0702.minecraft.gui.popup.AbstractGuiPopup;
import de.johni0702.minecraft.gui.utils.Colors; import de.johni0702.minecraft.gui.utils.Colors;
import net.minecraftforge.fml.common.Loader;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.HttpsURLConnection;

View File

@@ -4,9 +4,9 @@ import com.replaymod.core.ReplayMod;
import com.replaymod.extras.playeroverview.PlayerOverview; import com.replaymod.extras.playeroverview.PlayerOverview;
import com.replaymod.extras.urischeme.UriSchemeExtra; import com.replaymod.extras.urischeme.UriSchemeExtra;
import com.replaymod.extras.youtube.YoutubeUpload; import com.replaymod.extras.youtube.YoutubeUpload;
import net.minecraftforge.fml.common.Mod; import cpw.mods.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.util.Arrays; import java.util.Arrays;

View File

@@ -1,7 +1,6 @@
package com.replaymod.extras.playeroverview; package com.replaymod.extras.playeroverview;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.replaymod.core.ReplayMod; import com.replaymod.core.ReplayMod;
import com.replaymod.core.utils.Utils; import com.replaymod.core.utils.Utils;
import com.replaymod.extras.Extra; import com.replaymod.extras.Extra;
@@ -9,16 +8,23 @@ import com.replaymod.replay.ReplayModReplay;
import com.replaymod.replay.camera.CameraEntity; import com.replaymod.replay.camera.CameraEntity;
import com.replaymod.replay.events.ReplayCloseEvent; import com.replaymod.replay.events.ReplayCloseEvent;
import com.replaymod.replay.events.ReplayOpenEvent; import com.replaymod.replay.events.ReplayOpenEvent;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.EventPriority;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.client.event.RenderHandEvent; import net.minecraftforge.client.event.RenderHandEvent;
import net.minecraftforge.client.event.RenderPlayerEvent;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
public class PlayerOverview implements Extra { public class PlayerOverview implements Extra {
private ReplayModReplay module; private ReplayModReplay module;
@@ -35,12 +41,10 @@ public class PlayerOverview implements Extra {
public void run() { public void run() {
if (module.getReplayHandler() != null) { if (module.getReplayHandler() != null) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<EntityPlayer> players = mod.getMinecraft().theWorld.getPlayers(EntityPlayer.class, new Predicate() { List<EntityPlayer> players = mod.getMinecraft().theWorld.playerEntities;
@Override players = players.stream()
public boolean apply(Object input) { .filter(it -> !(it instanceof CameraEntity)) // Exclude the camera entity
return !(input instanceof CameraEntity); // Exclude the camera entity .collect(Collectors.toList());
}
});
if (!Utils.isCtrlDown()) { if (!Utils.isCtrlDown()) {
// Hide all players that have an UUID v2 (commonly used for NPCs) // Hide all players that have an UUID v2 (commonly used for NPCs)
Iterator<EntityPlayer> iter = players.iterator(); Iterator<EntityPlayer> iter = players.iterator();
@@ -90,12 +94,19 @@ public class PlayerOverview implements Extra {
@SubscribeEvent @SubscribeEvent
public void oRenderHand(RenderHandEvent event) { public void oRenderHand(RenderHandEvent event) {
Entity view = module.getCore().getMinecraft().getRenderViewEntity(); Entity view = module.getCore().getMinecraft().renderViewEntity;
if (view != null && isHidden(view.getUniqueID())) { if (view != null && isHidden(view.getUniqueID())) {
event.setCanceled(true); event.setCanceled(true);
} }
} }
@SubscribeEvent(priority = EventPriority.HIGHEST)
public void preRenderPlayer(RenderPlayerEvent.Pre event) {
if (isHidden(event.entityPlayer.getUniqueID())) {
event.setCanceled(true);
}
}
public boolean isSavingEnabled() { public boolean isSavingEnabled() {
return savingEnabled; return savingEnabled;
} }

View File

@@ -20,7 +20,6 @@ import de.johni0702.minecraft.gui.layout.HorizontalLayout;
import de.johni0702.minecraft.gui.utils.Colors; import de.johni0702.minecraft.gui.utils.Colors;
import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.audio.PositionedSoundRecord;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EnumPlayerModelParts;
import net.minecraft.potion.Potion; import net.minecraft.potion.Potion;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import org.lwjgl.util.Dimension; import org.lwjgl.util.Dimension;
@@ -46,14 +45,14 @@ public class PlayerOverviewGui extends GuiScreen implements Closeable {
public final GuiCheckbox checkAll = new GuiCheckbox(contentPanel){ public final GuiCheckbox checkAll = new GuiCheckbox(contentPanel){
@Override @Override
public void onClick() { public void onClick() {
getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(BUTTON_SOUND, 1.0F)); getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.createPositionedSoundRecord(BUTTON_SOUND, 1.0F));
playersScrollable.forEach(IGuiCheckbox.class).setChecked(true); playersScrollable.forEach(IGuiCheckbox.class).setChecked(true);
} }
}.setLabel("").setChecked(true).setTooltip(new GuiTooltip().setI18nText("replaymod.gui.playeroverview.showall")); }.setLabel("").setChecked(true).setTooltip(new GuiTooltip().setI18nText("replaymod.gui.playeroverview.showall"));
public final GuiCheckbox uncheckAll = new GuiCheckbox(contentPanel){ public final GuiCheckbox uncheckAll = new GuiCheckbox(contentPanel){
@Override @Override
public void onClick() { public void onClick() {
getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(BUTTON_SOUND, 1.0F)); getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.createPositionedSoundRecord(BUTTON_SOUND, 1.0F));
playersScrollable.forEach(IGuiCheckbox.class).setChecked(false); playersScrollable.forEach(IGuiCheckbox.class).setChecked(false);
} }
}.setLabel("").setChecked(false).setTooltip(new GuiTooltip().setI18nText("replaymod.gui.playeroverview.hideall")); }.setLabel("").setChecked(false).setTooltip(new GuiTooltip().setI18nText("replaymod.gui.playeroverview.hideall"));
@@ -96,12 +95,10 @@ public class PlayerOverviewGui extends GuiScreen implements Closeable {
public void draw(GuiRenderer renderer, ReadableDimension size, RenderInfo renderInfo) { public void draw(GuiRenderer renderer, ReadableDimension size, RenderInfo renderInfo) {
renderer.bindTexture(texture); renderer.bindTexture(texture);
renderer.drawTexturedRect(0, 0, 8, 8, 16, 16, 8, 8, 64, 64); renderer.drawTexturedRect(0, 0, 8, 8, 16, 16, 8, 8, 64, 64);
if (p.func_175148_a(EnumPlayerModelParts.HAT)) {
renderer.drawTexturedRect(0, 0, 40, 8, size.getWidth(), size.getHeight(), 8, 8, 64, 64); renderer.drawTexturedRect(0, 0, 40, 8, size.getWidth(), size.getHeight(), 8, 8, 64, 64);
} }
}
}.setSize(16, 16), }.setSize(16, 16),
new GuiLabel().setText(p.getName()).setColor(isSpectator(p) ? Colors.DKGREY : Colors.WHITE) new GuiLabel().setText(p.getDisplayName()).setColor(isSpectator(p) ? Colors.DKGREY : Colors.WHITE)
).onClick(new Runnable() { ).onClick(new Runnable() {
@Override @Override
public void run() { public void run() {
@@ -153,7 +150,7 @@ public class PlayerOverviewGui extends GuiScreen implements Closeable {
public int compare(EntityPlayer o1, EntityPlayer o2) { public int compare(EntityPlayer o1, EntityPlayer o2) {
if (isSpectator(o1) && !isSpectator(o2)) return 1; if (isSpectator(o1) && !isSpectator(o2)) return 1;
if (isSpectator(o2) && !isSpectator(o1)) return -1; if (isSpectator(o2) && !isSpectator(o1)) return -1;
return o1.getName().compareToIgnoreCase(o2.getName()); return o1.getDisplayName().compareToIgnoreCase(o2.getDisplayName());
} }
} }
} }

View File

@@ -2,14 +2,13 @@ package com.replaymod.extras.playeroverview.mixin;
import com.replaymod.extras.ReplayModExtras; import com.replaymod.extras.ReplayModExtras;
import com.replaymod.extras.playeroverview.PlayerOverview; import com.replaymod.extras.playeroverview.PlayerOverview;
import net.minecraft.client.renderer.culling.ICamera; import net.minecraft.client.model.ModelBase;
import net.minecraft.client.renderer.entity.Render; import net.minecraft.client.renderer.entity.RenderPlayer;
import net.minecraft.client.renderer.entity.RendererLivingEntity;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import java.util.UUID;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
/** /**
* This mixin prevents players that are hidden in the PlayerOverview from being rendered. * This mixin prevents players that are hidden in the PlayerOverview from being rendered.
@@ -19,22 +18,22 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
* *
* The previous solution was to overwrite the RenderPlayer instances which has been dropped in favor of this one * The previous solution was to overwrite the RenderPlayer instances which has been dropped in favor of this one
* because it is less compatible with other mods whereas this one should be fine as long as no other mod completely * because it is less compatible with other mods whereas this one should be fine as long as no other mod completely
* overwrites the shouldRender method. * overwrites the methods we modify in this mixin.
* One example of the previous solution breaking is when used with VanillaEnhancements because it replaces the * One example of the previous solution breaking is when used with VanillaEnhancements because it replaces the
* RenderManager with a new custom one which in turn will reset our registered RenderPlayer instances because * RenderManager with a new custom one which in turn will reset our registered RenderPlayer instances because
* it does so after we have already registered with the old RenderManager. * it does so after we have already registered with the old RenderManager.
*/ */
@Mixin(value = Render.class, priority = 1200) @Mixin(value = RenderPlayer.class, priority = 1200)
public abstract class MixinRender { public abstract class MixinRenderPlayer extends RendererLivingEntity {
@Inject(method = "shouldRender", at=@At("HEAD"), cancellable = true) public MixinRenderPlayer(ModelBase p_i1261_1_, float p_i1261_2_) {
public void replayModExtras_isPlayerHidden(Entity entity, ICamera camera, double camX, double camY, double camZ, CallbackInfoReturnable<Boolean> ci) { super(p_i1261_1_, p_i1261_2_);
ReplayModExtras.instance.get(PlayerOverview.class).ifPresent(playerOverview -> { }
if (entity instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) entity; @Override
if (playerOverview.isHidden(player.getUniqueID())) { public void doRenderShadowAndFire(Entity entity, double d1, double d2, double d3, float f1, float f2) {
ci.setReturnValue(false); UUID uuid = entity.getUniqueID();
if (!ReplayModExtras.instance.get(PlayerOverview.class).map(po -> po.isHidden(uuid)).orElse(false)) {
super.doRenderShadowAndFire(entity, d1, d2, d3, f1, f2);
} }
} }
});
}
} }

View File

@@ -3,11 +3,11 @@ package com.replaymod.extras.youtube;
import com.replaymod.core.ReplayMod; import com.replaymod.core.ReplayMod;
import com.replaymod.extras.Extra; import com.replaymod.extras.Extra;
import com.replaymod.render.gui.GuiRenderingDone; import com.replaymod.render.gui.GuiRenderingDone;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import de.johni0702.minecraft.gui.container.GuiScreen; import de.johni0702.minecraft.gui.container.GuiScreen;
import de.johni0702.minecraft.gui.element.GuiButton; import de.johni0702.minecraft.gui.element.GuiButton;
import net.minecraftforge.client.event.GuiScreenEvent; import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
public class YoutubeUpload implements Extra { public class YoutubeUpload implements Extra {
@Override @Override

View File

@@ -11,14 +11,14 @@ import com.replaymod.replay.events.ReplayCloseEvent;
import com.replaymod.replaystudio.replay.ReplayFile; import com.replaymod.replaystudio.replay.ReplayFile;
import com.replaymod.replaystudio.replay.ZipReplayFile; import com.replaymod.replaystudio.replay.ZipReplayFile;
import com.replaymod.replaystudio.studio.ReplayStudio; import com.replaymod.replaystudio.studio.ReplayStudio;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import de.johni0702.minecraft.gui.container.GuiScreen; import de.johni0702.minecraft.gui.container.GuiScreen;
import net.minecraftforge.common.config.Configuration; 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;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.io.File; import java.io.File;

View File

@@ -5,6 +5,8 @@ import com.replaymod.online.gui.GuiLoginPrompt;
import com.replaymod.online.gui.GuiReplayCenter; import com.replaymod.online.gui.GuiReplayCenter;
import com.replaymod.online.gui.GuiUploadReplay; import com.replaymod.online.gui.GuiUploadReplay;
import com.replaymod.replay.gui.screen.GuiReplayViewer; import com.replaymod.replay.gui.screen.GuiReplayViewer;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import de.johni0702.minecraft.gui.container.AbstractGuiScreen; import de.johni0702.minecraft.gui.container.AbstractGuiScreen;
import de.johni0702.minecraft.gui.container.GuiPanel; import de.johni0702.minecraft.gui.container.GuiPanel;
import de.johni0702.minecraft.gui.container.GuiScreen; import de.johni0702.minecraft.gui.container.GuiScreen;
@@ -14,8 +16,6 @@ import net.minecraft.client.gui.GuiMainMenu;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
import net.minecraftforge.client.event.GuiScreenEvent; import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import java.io.File; import java.io.File;
import java.util.List; import java.util.List;

View File

@@ -10,9 +10,9 @@ import com.replaymod.replay.ReplayHandler;
import com.replaymod.replaystudio.pathing.path.Keyframe; import com.replaymod.replaystudio.pathing.path.Keyframe;
import com.replaymod.replaystudio.pathing.path.Path; import com.replaymod.replaystudio.pathing.path.Path;
import com.replaymod.replaystudio.pathing.path.Timeline; import com.replaymod.replaystudio.pathing.path.Timeline;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Iterator; import java.util.Iterator;

View File

@@ -3,6 +3,7 @@ package com.replaymod.pathing.player;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import com.replaymod.replay.ReplayHandler; import com.replaymod.replay.ReplayHandler;
import com.replaymod.replaystudio.pathing.path.Timeline; import com.replaymod.replaystudio.pathing.path.Timeline;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
/** /**
* Timeline player using the system time. * Timeline player using the system time.
@@ -32,6 +33,7 @@ public class RealtimeTimelinePlayer extends AbstractTimelinePlayer {
} }
@Override @Override
@SubscribeEvent // 1.7.10 doesn't yet deal properly with inherited, overridden event handlers
public void onTick(ReplayTimer.UpdatedEvent event) { public void onTick(ReplayTimer.UpdatedEvent event) {
if (secondFrame) { if (secondFrame) {
secondFrame = false; secondFrame = false;

View File

@@ -1,9 +1,9 @@
package com.replaymod.pathing.player; package com.replaymod.pathing.player;
import com.replaymod.core.utils.WrappedTimer; import com.replaymod.core.utils.WrappedTimer;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraft.util.Timer; import net.minecraft.util.Timer;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.Event;
/** /**
* Wrapper around the current timer that prevents the timer from advancing by itself. * Wrapper around the current timer that prevents the timer from advancing by itself.

View File

@@ -8,6 +8,7 @@ import com.replaymod.replaystudio.pathing.property.PropertyPart;
import com.replaymod.replaystudio.pathing.property.PropertyParts; import com.replaymod.replaystudio.pathing.property.PropertyParts;
import lombok.NonNull; import lombok.NonNull;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.world.World; import net.minecraft.world.World;
import java.io.IOException; import java.io.IOException;
@@ -36,7 +37,9 @@ public class SpectatorProperty extends AbstractProperty<Integer> {
// Lookup entity by id, returns null if an entity with the id does not exists // Lookup entity by id, returns null if an entity with the id does not exists
Entity target = world.getEntityByID(value); Entity target = world.getEntityByID(value);
// Spectate entity, when called with null, returns to camera // Spectate entity, when called with null, returns to camera
handler.spectateEntity(target); if (target instanceof EntityLivingBase) {
handler.spectateEntity((EntityLivingBase) target);
}
} }
@Override @Override

View File

@@ -4,15 +4,15 @@ import com.replaymod.core.ReplayMod;
import com.replaymod.core.utils.Restrictions; import com.replaymod.core.utils.Restrictions;
import com.replaymod.recording.handler.ConnectionEventHandler; import com.replaymod.recording.handler.ConnectionEventHandler;
import com.replaymod.recording.packet.PacketListener; import com.replaymod.recording.packet.PacketListener;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.eventhandler.EventBus;
import cpw.mods.fml.common.network.NetworkRegistry;
import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler;
import net.minecraft.network.NetworkManager; import net.minecraft.network.NetworkManager;
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.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.EventBus;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;

View File

@@ -2,14 +2,14 @@ package com.replaymod.recording.gui;
import com.replaymod.core.SettingsRegistry; import com.replaymod.core.SettingsRegistry;
import com.replaymod.recording.Setting; import com.replaymod.recording.Setting;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.Gui;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import org.lwjgl.opengl.GL11;
import static com.replaymod.core.ReplayMod.TEXTURE; import static com.replaymod.core.ReplayMod.TEXTURE;
import static com.replaymod.core.ReplayMod.TEXTURE_SIZE; import static com.replaymod.core.ReplayMod.TEXTURE_SIZE;
@@ -45,8 +45,7 @@ public class GuiRecordingOverlay {
FontRenderer fontRenderer = mc.fontRendererObj; FontRenderer fontRenderer = mc.fontRendererObj;
fontRenderer.drawString(I18n.format("replaymod.gui.recording").toUpperCase(), 30, 18 - (fontRenderer.FONT_HEIGHT / 2), 0xffffffff); fontRenderer.drawString(I18n.format("replaymod.gui.recording").toUpperCase(), 30, 18 - (fontRenderer.FONT_HEIGHT / 2), 0xffffffff);
mc.renderEngine.bindTexture(TEXTURE); mc.renderEngine.bindTexture(TEXTURE);
GlStateManager.resetColor(); GL11.glEnable(GL11.GL_ALPHA_TEST);
GlStateManager.enableAlpha();
Gui.drawModalRectWithCustomSizedTexture(10, 10, 58, 20, 16, 16, TEXTURE_SIZE, TEXTURE_SIZE); Gui.drawModalRectWithCustomSizedTexture(10, 10, 58, 20, 16, 16, TEXTURE_SIZE, TEXTURE_SIZE);
} }
} }

View File

@@ -10,11 +10,10 @@ import com.replaymod.replaystudio.replay.ReplayFile;
import com.replaymod.replaystudio.replay.ReplayMetaData; import com.replaymod.replaystudio.replay.ReplayMetaData;
import com.replaymod.replaystudio.replay.ZipReplayFile; import com.replaymod.replaystudio.replay.ZipReplayFile;
import com.replaymod.replaystudio.studio.ReplayStudio; import com.replaymod.replaystudio.studio.ReplayStudio;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.network.FMLNetworkEvent;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.network.NetworkManager; import net.minecraft.network.NetworkManager;
import net.minecraft.world.WorldType;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientDisconnectionFromServerEvent;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.io.File; import java.io.File;
@@ -47,10 +46,6 @@ public class ConnectionEventHandler {
try { try {
boolean local = networkManager.isLocalChannel(); boolean local = networkManager.isLocalChannel();
if (local) { if (local) {
if (mc.getIntegratedServer().getEntityWorld().getWorldType() == WorldType.DEBUG_WORLD) {
logger.info("Debug World recording is not supported.");
return;
}
if(!core.getSettingsRegistry().get(Setting.RECORD_SINGLEPLAYER)) { if(!core.getSettingsRegistry().get(Setting.RECORD_SINGLEPLAYER)) {
logger.info("Singleplayer Recording is disabled"); logger.info("Singleplayer Recording is disabled");
return; return;
@@ -96,14 +91,14 @@ public class ConnectionEventHandler {
guiOverlay.register(); guiOverlay.register();
core.printInfoToChat("replaymod.chat.recordingstarted"); core.printInfoToChat("replaymod.chat.recordingstarted");
} catch(Exception e) { } catch(Throwable e) {
e.printStackTrace(); e.printStackTrace();
core.printWarningToChat("replaymod.chat.recordingfailed"); core.printWarningToChat("replaymod.chat.recordingfailed");
} }
} }
@SubscribeEvent @SubscribeEvent
public void onDisconnectedFromServerEvent(ClientDisconnectionFromServerEvent event) { public void onDisconnectedFromServerEvent(FMLNetworkEvent.ClientDisconnectionFromServerEvent event) {
if (packetListener != null) { if (packetListener != null) {
guiOverlay.unregister(); guiOverlay.unregister();
guiOverlay = null; guiOverlay = null;

View File

@@ -1,8 +1,8 @@
package com.replaymod.recording.handler; package com.replaymod.recording.handler;
import cpw.mods.fml.common.network.handshake.FMLHandshakeMessage;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.SimpleChannelInboundHandler;
import net.minecraftforge.fml.common.network.handshake.FMLHandshakeMessage;
/** /**
* Filters out all handshake packets that were sent for recording but must * Filters out all handshake packets that were sent for recording but must
@@ -17,7 +17,7 @@ import net.minecraftforge.fml.common.network.handshake.FMLHandshakeMessage;
public class FMLHandshakeFilter extends SimpleChannelInboundHandler<FMLHandshakeMessage> { public class FMLHandshakeFilter extends SimpleChannelInboundHandler<FMLHandshakeMessage> {
@Override @Override
protected void channelRead0(ChannelHandlerContext ctx, FMLHandshakeMessage msg) throws Exception { protected void channelRead0(ChannelHandlerContext ctx, FMLHandshakeMessage msg) throws Exception {
if (!(msg instanceof FMLHandshakeMessage.RegistryData)) { if (!(msg instanceof FMLHandshakeMessage.ModIdData)) {
// Pass on everything but RegistryData messages // Pass on everything but RegistryData messages
ctx.fireChannelRead(msg); ctx.fireChannelRead(msg);
} }

View File

@@ -1,28 +1,34 @@
package com.replaymod.recording.handler; package com.replaymod.recording.handler;
import com.replaymod.recording.packet.PacketListener; import com.replaymod.recording.packet.PacketListener;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.PlayerEvent;
import cpw.mods.fml.common.gameevent.TickEvent;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.network.Packet; import net.minecraft.network.Packet;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraft.network.play.server.*; import net.minecraft.network.play.server.S04PacketEntityEquipment;
import net.minecraft.network.play.server.S0APacketUseBed;
import net.minecraft.network.play.server.S0BPacketAnimation;
import net.minecraft.network.play.server.S0CPacketSpawnPlayer;
import net.minecraft.network.play.server.S0DPacketCollectItem;
import net.minecraft.network.play.server.S12PacketEntityVelocity;
import net.minecraft.network.play.server.S14PacketEntity.S17PacketEntityLookMove; import net.minecraft.network.play.server.S14PacketEntity.S17PacketEntityLookMove;
import net.minecraft.network.play.server.S18PacketEntityTeleport;
import net.minecraft.network.play.server.S19PacketEntityHeadLook;
import net.minecraft.network.play.server.S1BPacketEntityAttach;
import net.minecraft.network.play.server.S25PacketBlockBreakAnim;
import net.minecraft.server.integrated.IntegratedServer; import net.minecraft.server.integrated.IntegratedServer;
import net.minecraft.util.BlockPos;
import net.minecraft.util.MathHelper; import net.minecraft.util.MathHelper;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.minecart.MinecartInteractEvent; import net.minecraftforge.event.entity.minecart.MinecartInteractEvent;
import net.minecraftforge.event.entity.player.PlayerSleepInBedEvent; import net.minecraftforge.event.entity.player.PlayerSleepInBedEvent;
import net.minecraftforge.event.entity.player.PlayerUseItemEvent; 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;
import net.minecraftforge.fml.common.gameevent.TickEvent.PlayerTickEvent;
import java.util.Objects; import java.util.Objects;
@@ -74,37 +80,11 @@ public class RecordingEventHandler {
} }
private S0CPacketSpawnPlayer spawnPlayer(EntityPlayer player) { private S0CPacketSpawnPlayer spawnPlayer(EntityPlayer player) {
try { return new S0CPacketSpawnPlayer(player);
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 @SubscribeEvent
public void onPlayerTick(PlayerTickEvent e) { public void onPlayerTick(TickEvent.PlayerTickEvent e) {
try { try {
if(e.player != mc.thePlayer) return; if(e.player != mc.thePlayer) return;
@@ -112,7 +92,7 @@ public class RecordingEventHandler {
if(lastX == null || lastY == null || lastZ == null) { if(lastX == null || lastY == null || lastZ == null) {
force = true; force = true;
lastX = e.player.posX; lastX = e.player.posX;
lastY = e.player.posY; lastY = e.player.boundingBox.minY;
lastZ = e.player.posZ; lastZ = e.player.posZ;
} }
@@ -123,28 +103,28 @@ public class RecordingEventHandler {
} }
double dx = e.player.posX - lastX; double dx = e.player.posX - lastX;
double dy = e.player.posY - lastY; double dy = e.player.boundingBox.minY - lastY;
double dz = e.player.posZ - lastZ; double dz = e.player.posZ - lastZ;
lastX = e.player.posX; lastX = e.player.posX;
lastY = e.player.posY; lastY = e.player.boundingBox.minY;
lastZ = e.player.posZ; lastZ = e.player.posZ;
Packet packet; Packet packet;
if(force || Math.abs(dx) > 4.0 || Math.abs(dy) > 4.0 || Math.abs(dz) > 4.0) { 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 x = MathHelper.floor_double(e.player.posX * 32.0D);
int y = MathHelper.floor_double(e.player.posY * 32.0D); int y = MathHelper.floor_double(e.player.boundingBox.minY * 32.0D);
int z = MathHelper.floor_double(e.player.posZ * 32.0D); int z = MathHelper.floor_double(e.player.posZ * 32.0D);
byte yaw = (byte) ((int) (e.player.rotationYaw * 256.0F / 360.0F)); byte yaw = (byte) ((int) (e.player.rotationYaw * 256.0F / 360.0F));
byte pitch = (byte) ((int) (e.player.rotationPitch * 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); packet = new S18PacketEntityTeleport(e.player.getEntityId(), x, y, z, yaw, pitch);
} else { } else {
byte newYaw = (byte) ((int) (e.player.rotationYaw * 256.0F / 360.0F)); byte newYaw = (byte) ((int) (e.player.rotationYaw * 256.0F / 360.0F));
byte newPitch = (byte) ((int) (e.player.rotationPitch * 256.0F / 360.0F)); byte newPitch = (byte) ((int) (e.player.rotationPitch * 256.0F / 360.0F));
packet = new S17PacketEntityLookMove(e.player.getEntityId(), packet = new S17PacketEntityLookMove(e.player.getEntityId(),
(byte) Math.round(dx * 32), (byte) Math.round(dy * 32), (byte) Math.round(dz * 32), (byte) Math.round(dx * 32), (byte) Math.round(dy * 32), (byte) Math.round(dz * 32),
newYaw, newPitch, e.player.onGround); newYaw, newPitch);
} }
packetListener.save(packet); packetListener.save(packet);
@@ -153,16 +133,7 @@ public class RecordingEventHandler {
int rotationYawHead = ((int)(e.player.rotationYawHead * 256.0F / 360.0F)); int rotationYawHead = ((int)(e.player.rotationYawHead * 256.0F / 360.0F));
if(!Objects.equals(rotationYawHead, rotationYawHeadBefore)) { if(!Objects.equals(rotationYawHead, rotationYawHeadBefore)) {
S19PacketEntityHeadLook head = new S19PacketEntityHeadLook(); packetListener.save(new S19PacketEntityHeadLook(e.player, (byte) rotationYawHead));
ByteBuf bb1 = Unpooled.buffer();
PacketBuffer pb1 = new PacketBuffer(bb1);
pb1.writeVarIntToBuffer(e.player.getEntityId());
pb1.writeByte(rotationYawHead);
head.readPacketData(pb1);
packetListener.save(head);
rotationYawHeadBefore = rotationYawHead; rotationYawHeadBefore = rotationYawHead;
} }
@@ -173,17 +144,7 @@ public class RecordingEventHandler {
//Animation Packets //Animation Packets
//Swing Animation //Swing Animation
if(e.player.swingProgressInt == 1) { if(e.player.swingProgressInt == 1) {
S0BPacketAnimation pac = new S0BPacketAnimation(); packetListener.save(new S0BPacketAnimation(e.player, 0));
ByteBuf bb = Unpooled.buffer();
PacketBuffer pb = new PacketBuffer(bb);
pb.writeVarIntToBuffer(e.player.getEntityId());
pb.writeByte(0);
pac.readPacketData(pb);
packetListener.save(pac);
} }
/* /*
@@ -263,17 +224,7 @@ public class RecordingEventHandler {
//Sleeping //Sleeping
if(!mc.thePlayer.isPlayerSleeping() && wasSleeping) { if(!mc.thePlayer.isPlayerSleeping() && wasSleeping) {
S0BPacketAnimation pac = new S0BPacketAnimation(); packetListener.save(new S0BPacketAnimation(e.player, 2));
ByteBuf bb = Unpooled.buffer();
PacketBuffer pb = new PacketBuffer(bb);
pb.writeVarIntToBuffer(e.player.getEntityId());
pb.writeByte(2);
pac.readPacketData(pb);
packetListener.save(pac);
wasSleeping = false; wasSleeping = false;
} }
@@ -284,7 +235,7 @@ public class RecordingEventHandler {
} }
@SubscribeEvent @SubscribeEvent
public void onPickupItem(ItemPickupEvent event) { public void onPickupItem(PlayerEvent.ItemPickupEvent event) {
try { try {
packetListener.save(new S0DPacketCollectItem(event.pickedUp.getEntityId(), event.player.getEntityId())); packetListener.save(new S0DPacketCollectItem(event.pickedUp.getEntityId(), event.player.getEntityId()));
} catch(Exception e) { } catch(Exception e) {
@@ -294,80 +245,33 @@ public class RecordingEventHandler {
@SubscribeEvent @SubscribeEvent
public void onStartEating(PlayerUseItemEvent.Start event) { public void onStartEating(PlayerUseItemEvent.Start event) {
try {
if(!event.entityPlayer.isEating()) return; if(!event.entityPlayer.isEating()) return;
S0BPacketAnimation packet = new S0BPacketAnimation(); packetListener.save(new S0BPacketAnimation(event.entityPlayer, 3));
ByteBuf bb = Unpooled.buffer();
PacketBuffer pb = new PacketBuffer(bb);
pb.writeVarIntToBuffer(event.entityPlayer.getEntityId());
pb.writeByte(3);
packet.readPacketData(pb);
packetListener.save(packet);
} catch(Exception e) {
e.printStackTrace();
}
} }
@SubscribeEvent @SubscribeEvent
public void onSleep(PlayerSleepInBedEvent event) { public void onSleep(PlayerSleepInBedEvent event) {
try {
if(event.entityPlayer != mc.thePlayer) { if(event.entityPlayer != mc.thePlayer) {
return; return;
} }
S0APacketUseBed pub = new S0APacketUseBed(); packetListener.save(new S0APacketUseBed(event.entityPlayer, event.x, event.y, event.z));
ByteBuf buf = Unpooled.buffer();
PacketBuffer pbuf = new PacketBuffer(buf);
pbuf.writeVarIntToBuffer(event.entityPlayer.getEntityId());
pbuf.writeBlockPos(event.pos);
pub.readPacketData(pbuf);
packetListener.save(pub);
wasSleeping = true; wasSleeping = true;
} catch(Exception e) {
e.printStackTrace();
}
} }
@SubscribeEvent @SubscribeEvent
public void enterMinecart(MinecartInteractEvent event) { public void enterMinecart(MinecartInteractEvent event) {
try {
if(event.player != mc.thePlayer) { if(event.player != mc.thePlayer) {
return; return;
} }
packetListener.save(new S1BPacketEntityAttach(0, event.player, event.minecart));
S1BPacketEntityAttach pea = new S1BPacketEntityAttach();
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.minecart.getEntityId();
} catch(Exception e) {
e.printStackTrace();
}
} }
public void onBlockBreakAnim(int breakerId, BlockPos pos, int progress) { public void onBlockBreakAnim(int breakerId, int x, int y, int z, int progress) {
EntityPlayer thePlayer = mc.thePlayer; EntityPlayer thePlayer = mc.thePlayer;
if (thePlayer != null && breakerId == thePlayer.getEntityId()) { if (thePlayer != null && breakerId == thePlayer.getEntityId()) {
packetListener.save(new S25PacketBlockBreakAnim(breakerId, pos, progress)); packetListener.save(new S25PacketBlockBreakAnim(breakerId, x, y, z, progress));
} }
} }

View File

@@ -1,8 +1,10 @@
package com.replaymod.recording.mixin; package com.replaymod.recording.mixin;
import com.replaymod.recording.ReplayModRecording; import com.replaymod.recording.ReplayModRecording;
import cpw.mods.fml.common.network.FMLNetworkEvent;
import net.minecraft.client.network.NetHandlerLoginClient; import net.minecraft.client.network.NetHandlerLoginClient;
import net.minecraft.network.NetworkManager; import net.minecraft.network.NetworkManager;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@@ -13,15 +15,15 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
public abstract class MixinNetHandlerLoginClient { public abstract class MixinNetHandlerLoginClient {
@Shadow @Shadow
private NetworkManager networkManager; private @Final NetworkManager field_147393_d;
/** /**
* Starts the recording right before switching into PLAY state. * Starts the recording right before switching into PLAY state.
* We cannot use the {@link net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientConnectedToServerEvent} * We cannot use the {@link FMLNetworkEvent.ClientConnectedToServerEvent}
* as it only fires after the forge handshake. * as it only fires after the forge handshake.
*/ */
@Inject(method = "handleLoginSuccess", at=@At("HEAD")) @Inject(method = "handleLoginSuccess", at=@At("HEAD"))
public void replayModRecording_initiateRecording(CallbackInfo cb) { public void replayModRecording_initiateRecording(CallbackInfo cb) {
ReplayModRecording.instance.initiateRecording(networkManager); ReplayModRecording.instance.initiateRecording(field_147393_d);
} }
} }

View File

@@ -3,28 +3,20 @@ package com.replaymod.recording.mixin;
import com.replaymod.recording.handler.RecordingEventHandler; import com.replaymod.recording.handler.RecordingEventHandler;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.network.NetHandlerPlayClient; import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.client.network.NetworkPlayerInfo; import net.minecraft.network.play.server.S01PacketJoinGame;
import net.minecraft.network.play.server.S07PacketRespawn; import net.minecraft.network.play.server.S07PacketRespawn;
import net.minecraft.network.play.server.S38PacketPlayerListItem;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@Mixin(NetHandlerPlayClient.class) @Mixin(NetHandlerPlayClient.class)
public abstract class MixinNetHandlerPlayClient { public abstract class MixinNetHandlerPlayClient {
@Shadow @Shadow
private Minecraft gameController; private Minecraft gameController;
@Shadow
private Map<UUID, NetworkPlayerInfo> playerInfoMap;
public RecordingEventHandler getRecordingEventHandler() { public RecordingEventHandler getRecordingEventHandler() {
return ((RecordingEventHandler.RecordingEventSender) gameController.renderGlobal).getRecordingEventHandler(); return ((RecordingEventHandler.RecordingEventSender) gameController.renderGlobal).getRecordingEventHandler();
} }
@@ -32,33 +24,22 @@ public abstract class MixinNetHandlerPlayClient {
/** /**
* Record the own player entity joining the world. * Record the own player entity joining the world.
* We cannot use the {@link net.minecraftforge.event.entity.EntityJoinWorldEvent} because the entity id * We cannot use the {@link net.minecraftforge.event.entity.EntityJoinWorldEvent} because the entity id
* of the player is set afterwards and the tablist entry might not yet be sent. * of the player is set afterwards
* @param packet The packet * @param packet The packet
* @param ci Callback info * @param ci Callback info
*/ */
@Inject(method = "handlePlayerListItem", at=@At("HEAD")) @Inject(method = "handleJoinGame", at=@At("RETURN"))
public void recordOwnJoin(S38PacketPlayerListItem packet, CallbackInfo ci) { public void recordOwnJoin(S01PacketJoinGame packet, CallbackInfo ci) {
if (gameController.thePlayer == null) return;
RecordingEventHandler handler = getRecordingEventHandler(); RecordingEventHandler handler = getRecordingEventHandler();
if (handler != null && packet.func_179768_b() == S38PacketPlayerListItem.Action.ADD_PLAYER) { if (handler != null) {
@SuppressWarnings("unchecked")
List<S38PacketPlayerListItem.AddPlayerData> dataList = packet.func_179767_a();
for (S38PacketPlayerListItem.AddPlayerData data : dataList) {
if (data.func_179962_a() == null || data.func_179962_a().getId() == null) continue;
// Only add spawn packet for our own player and only if he isn't known yet
if (data.func_179962_a().getId().equals(Minecraft.getMinecraft().thePlayer.getGameProfile().getId())
&& !playerInfoMap.containsKey(data.func_179962_a().getId())) {
handler.onPlayerJoin(); handler.onPlayerJoin();
} }
} }
}
}
/** /**
* Record the own player entity respawning. * Record the own player entity respawning.
* We cannot use the {@link net.minecraftforge.event.entity.EntityJoinWorldEvent} because that would also include * 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(S01PacketJoinGame, CallbackInfo)}.
* @param packet The packet * @param packet The packet
* @param ci Callback info * @param ci Callback info
*/ */

View File

@@ -1,11 +1,11 @@
package com.replaymod.recording.mixin; package com.replaymod.recording.mixin;
import com.replaymod.recording.handler.FMLHandshakeFilter; import com.replaymod.recording.handler.FMLHandshakeFilter;
import cpw.mods.fml.common.network.handshake.FMLHandshakeCodec;
import cpw.mods.fml.common.network.handshake.NetworkDispatcher;
import cpw.mods.fml.relauncher.Side;
import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPipeline;
import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.embedded.EmbeddedChannel;
import net.minecraftforge.fml.common.network.handshake.FMLHandshakeCodec;
import net.minecraftforge.fml.common.network.handshake.NetworkDispatcher;
import net.minecraftforge.fml.relauncher.Side;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;

View File

@@ -2,7 +2,6 @@ package com.replaymod.recording.mixin;
import com.replaymod.recording.handler.RecordingEventHandler; import com.replaymod.recording.handler.RecordingEventHandler;
import net.minecraft.client.renderer.RenderGlobal; import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.util.BlockPos;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
@@ -23,10 +22,10 @@ public abstract class MixinRenderGlobal implements RecordingEventHandler.Recordi
return recordingEventHandler; return recordingEventHandler;
} }
@Inject(method = "sendBlockBreakProgress", at = @At("HEAD")) @Inject(method = "destroyBlockPartially", at = @At("HEAD"))
public void saveBlockBreakProgressPacket(int breakerId, BlockPos pos, int progress, CallbackInfo info) { public void saveBlockBreakProgressPacket(int breakerId, int x, int y, int z, int progress, CallbackInfo info) {
if (recordingEventHandler != null) { if (recordingEventHandler != null) {
recordingEventHandler.onBlockBreakAnim(breakerId, pos, progress); recordingEventHandler.onBlockBreakAnim(breakerId, x, y, z, progress);
} }
} }
} }

View File

@@ -4,6 +4,7 @@ import com.replaymod.core.utils.Restrictions;
import com.replaymod.replaystudio.data.Marker; import com.replaymod.replaystudio.data.Marker;
import com.replaymod.replaystudio.replay.ReplayFile; import com.replaymod.replaystudio.replay.ReplayFile;
import com.replaymod.replaystudio.replay.ReplayMetaData; import com.replaymod.replaystudio.replay.ReplayMetaData;
import cpw.mods.fml.common.network.internal.FMLProxyPacket;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
@@ -12,12 +13,10 @@ import net.minecraft.client.Minecraft;
import net.minecraft.entity.DataWatcher; import net.minecraft.entity.DataWatcher;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.network.EnumConnectionState; import net.minecraft.network.EnumConnectionState;
import net.minecraft.network.EnumPacketDirection;
import net.minecraft.network.Packet; import net.minecraft.network.Packet;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraft.network.play.server.*; import net.minecraft.network.play.server.*;
import net.minecraft.util.ChatComponentText; import net.minecraft.util.ChatComponentText;
import net.minecraftforge.fml.common.network.internal.FMLProxyPacket;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@@ -85,15 +84,12 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
public void save(Packet packet) { public void save(Packet packet) {
try { try {
if(packet instanceof S0CPacketSpawnPlayer) { if(packet instanceof S0CPacketSpawnPlayer) {
UUID uuid = ((S0CPacketSpawnPlayer) packet).func_179819_c(); UUID uuid = ((S0CPacketSpawnPlayer) packet).field_148955_b.getId();
Set<String> uuids = new HashSet<>(Arrays.asList(metaData.getPlayers())); Set<String> uuids = new HashSet<>(Arrays.asList(metaData.getPlayers()));
uuids.add(uuid.toString()); uuids.add(uuid.toString());
metaData.setPlayers(uuids.toArray(new String[uuids.size()])); metaData.setPlayers(uuids.toArray(new String[uuids.size()]));
saveMetaData(); saveMetaData();
} }
if (packet instanceof S46PacketSetCompressionLevel) {
return; // Replay data is never compressed on the packet level
}
byte[] bytes = getPacketData(packet); byte[] bytes = getPacketData(packet);
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
@@ -162,14 +158,17 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
} }
} }
if (packet instanceof S48PacketResourcePackSend) { if (packet instanceof S3FPacketCustomPayload) {
save(resourcePackRecorder.handleResourcePack((S48PacketResourcePackSend) packet)); S3FPacketCustomPayload p = (S3FPacketCustomPayload) packet;
if ("MC|RPack".equals(p.func_149169_c())) {
save(resourcePackRecorder.handleResourcePack(p));
return; return;
} }
}
if (packet instanceof FMLProxyPacket) { if (packet instanceof FMLProxyPacket) {
// This packet requires special handling // This packet requires special handling
((FMLProxyPacket) packet).toS3FPackets().forEach(this::save); save(((FMLProxyPacket) packet).toS3FPacket());
super.channelRead(ctx, msg); super.channelRead(ctx, msg);
return; return;
} }
@@ -178,7 +177,7 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
if (packet instanceof S3FPacketCustomPayload) { if (packet instanceof S3FPacketCustomPayload) {
S3FPacketCustomPayload p = (S3FPacketCustomPayload) packet; S3FPacketCustomPayload p = (S3FPacketCustomPayload) packet;
if (Restrictions.PLUGIN_CHANNEL.equals(p.getChannelName())) { if (Restrictions.PLUGIN_CHANNEL.equals(p.func_149169_c())) {
packet = new S40PacketDisconnect(new ChatComponentText("Please update to view this replay.")); packet = new S40PacketDisconnect(new ChatComponentText("Please update to view this replay."));
save(packet); save(packet);
} }
@@ -218,7 +217,7 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
} }
} }
Integer packetId = EnumConnectionState.PLAY.getPacketId(EnumPacketDirection.CLIENTBOUND, packet); Integer packetId = (Integer) EnumConnectionState.PLAY.func_150755_b().inverse().get(packet.getClass());
if (packetId == null) { if (packetId == null) {
throw new IOException("Unknown packet type:" + packet.getClass()); throw new IOException("Unknown packet type:" + packet.getClass());
} }
@@ -236,7 +235,7 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
} }
public void addMarker() { public void addMarker() {
Entity view = Minecraft.getMinecraft().getRenderViewEntity(); Entity view = Minecraft.getMinecraft().renderViewEntity;
int timestamp = (int) (System.currentTimeMillis() - startTime); int timestamp = (int) (System.currentTimeMillis() - startTime);
Marker marker = new Marker(); Marker marker = new Marker();

View File

@@ -2,28 +2,23 @@ package com.replaymod.recording.packet;
import com.google.common.hash.Hashing; import com.google.common.hash.Hashing;
import com.google.common.io.Files; import com.google.common.io.Files;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.replaymod.replaystudio.replay.ReplayFile; import com.replaymod.replaystudio.replay.ReplayFile;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreenWorking; import net.minecraft.client.gui.GuiScreenWorking;
import net.minecraft.client.gui.GuiYesNo; import net.minecraft.client.gui.GuiYesNo;
import net.minecraft.client.gui.GuiYesNoCallback; import net.minecraft.client.gui.GuiYesNoCallback;
import net.minecraft.client.multiplayer.ServerData; import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.client.multiplayer.ServerData.ServerResourceMode;
import net.minecraft.client.multiplayer.ServerList; import net.minecraft.client.multiplayer.ServerList;
import net.minecraft.client.network.NetHandlerPlayClient; import net.minecraft.client.resources.FileResourcePack;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
import net.minecraft.client.resources.ResourcePackRepository; import net.minecraft.client.resources.ResourcePackRepository;
import net.minecraft.network.NetworkManager; import net.minecraft.network.play.server.S3FPacketCustomPayload;
import net.minecraft.network.play.client.C19PacketResourcePackStatus;
import net.minecraft.network.play.server.S48PacketResourcePackSend;
import net.minecraft.util.HttpUtil; import net.minecraft.util.HttpUtil;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.Charsets;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import javax.annotation.Nonnull;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
@@ -75,145 +70,75 @@ public class ResourcePackRecorder {
} }
} }
public synchronized S48PacketResourcePackSend handleResourcePack(S48PacketResourcePackSend packet) { public synchronized S3FPacketCustomPayload handleResourcePack(S3FPacketCustomPayload packet) {
final int requestId = nextRequestId++; final int requestId = nextRequestId++;
final NetHandlerPlayClient netHandler = mc.getNetHandler(); final String url = new String(packet.func_149168_d(), Charsets.UTF_8);
final NetworkManager netManager = netHandler.getNetworkManager();
final String url = packet.func_179783_a();
final String hash = packet.func_179784_b();
if (url.startsWith("level://")) { ServerData serverData = mc.getCurrentServerData();
String levelName = url.substring("level://".length()); ServerResourceMode resourceMode = serverData == null ? ServerResourceMode.PROMPT : serverData.getResourceMode();
File savesDir = new File(mc.mcDataDir, "saves"); if (resourceMode == ServerResourceMode.ENABLED) {
final File levelDir = new File(savesDir, levelName); downloadResourcePack(requestId, url);
mc.getResourcePackRepository().obtainResourcePack(url);
if (levelDir.isFile()) { } else if (resourceMode == ServerResourceMode.PROMPT) {
netManager.sendPacket(new C19PacketResourcePackStatus(hash, C19PacketResourcePackStatus.Action.ACCEPTED));
Futures.addCallback(mc.getResourcePackRepository().func_177319_a(levelDir), new FutureCallback() {
@Override
public void onSuccess(Object result) {
recordResourcePack(levelDir, requestId);
netManager.sendPacket(new C19PacketResourcePackStatus(hash, C19PacketResourcePackStatus.Action.SUCCESSFULLY_LOADED));
}
@Override
public void onFailure(@Nonnull Throwable throwable) {
netManager.sendPacket(new C19PacketResourcePackStatus(hash, C19PacketResourcePackStatus.Action.FAILED_DOWNLOAD));
}
});
} else {
netManager.sendPacket(new C19PacketResourcePackStatus(hash, C19PacketResourcePackStatus.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));
downloadResourcePackFuture(requestId, url, hash);
} else if (serverData != null && serverData.getResourceMode() != ServerData.ServerResourceMode.PROMPT) {
netManager.sendPacket(new C19PacketResourcePackStatus(hash, C19PacketResourcePackStatus.Action.DECLINED));
} else {
// Lambdas MUST NOT be used with methods that need re-obfuscation in FG prior to 2.2 (will result in AbstractMethodError) // Lambdas MUST NOT be used with methods that need re-obfuscation in FG prior to 2.2 (will result in AbstractMethodError)
//noinspection Convert2Lambda //noinspection Convert2Lambda
mc.addScheduledTask(() -> mc.displayGuiScreen(new GuiYesNo(new GuiYesNoCallback() { mc.displayGuiScreen(new GuiYesNo(new GuiYesNoCallback() {
@Override @Override
public void confirmClicked(boolean result, int id) { public void confirmClicked(boolean result, int id) {
if (serverData != null) { if (serverData != null) {
serverData.setResourceMode(result ? ServerData.ServerResourceMode.ENABLED : ServerData.ServerResourceMode.DISABLED); serverData.setResourceMode(ServerResourceMode.ENABLED);
}
if (result) {
netManager.sendPacket(new C19PacketResourcePackStatus(hash, C19PacketResourcePackStatus.Action.ACCEPTED));
ResourcePackRecorder.this.downloadResourcePackFuture(requestId, url, hash);
} else {
netManager.sendPacket(new C19PacketResourcePackStatus(hash, C19PacketResourcePackStatus.Action.DECLINED));
}
ServerList.func_147414_b(serverData); ServerList.func_147414_b(serverData);
}
mc.displayGuiScreen(null); mc.displayGuiScreen(null);
if (result) {
downloadResourcePack(requestId, url);
} }
}, I18n.format("multiplayer.texturePrompt.line1"), I18n.format("multiplayer.texturePrompt.line2"), 0)));
} }
}, I18n.format("multiplayer.texturePrompt.line1"), I18n.format("multiplayer.texturePrompt.line2"), 0));
} }
return new S48PacketResourcePackSend("replay://" + requestId, ""); return new S3FPacketCustomPayload(packet.func_149169_c(), ("replay://" + requestId).getBytes(Charsets.UTF_8));
} }
private void downloadResourcePackFuture(int requestId, String url, final String hash) { private void downloadResourcePack(final int requestId, String url) {
Futures.addCallback(downloadResourcePack(requestId, url, hash), new FutureCallback() {
@Override
public void onSuccess(Object result) {
mc.getNetHandler().addToSendQueue(new C19PacketResourcePackStatus(hash, C19PacketResourcePackStatus.Action.SUCCESSFULLY_LOADED));
}
@Override
public void onFailure(@Nonnull Throwable throwable) {
mc.getNetHandler().addToSendQueue(new C19PacketResourcePackStatus(hash, C19PacketResourcePackStatus.Action.FAILED_DOWNLOAD));
}
});
}
private ListenableFuture downloadResourcePack(final int requestId, String url, String hash) {
final ResourcePackRepository repo = mc.mcResourcePackRepository; final ResourcePackRepository repo = mc.mcResourcePackRepository;
String fileName;
if (hash.matches("^[a-f0-9]{40}$")) { String fileName = url.substring(url.lastIndexOf("/") + 1);
fileName = hash;
} else {
fileName = url.substring(url.lastIndexOf("/") + 1);
if (fileName.contains("?")) { if (fileName.contains("?")) {
fileName = fileName.substring(0, fileName.indexOf("?")); fileName = fileName.substring(0, fileName.indexOf("?"));
} }
if (!fileName.endsWith(".zip")) { if (!fileName.endsWith(".zip")) {
return Futures.immediateFailedFuture(new IllegalArgumentException("Invalid filename; must end in .zip")); return;
} }
fileName = "legacy_" + fileName.replaceAll("\\W", ""); fileName = fileName.replaceAll("\\W", "");
}
final File file = new File(repo.dirServerResourcepacks, fileName); File file = new File(repo.field_148534_e, fileName);
repo.field_177321_h.lock();
try { HashMap<String, String> hashmap = new HashMap<>();
hashmap.put("X-Minecraft-Username", mc.getSession().getUsername());
hashmap.put("X-Minecraft-UUID", mc.getSession().getPlayerID());
hashmap.put("X-Minecraft-Version", "1.7.10");
GuiScreenWorking guiScreen = new GuiScreenWorking();
Minecraft.getMinecraft().displayGuiScreen(guiScreen);
repo.func_148529_f(); repo.func_148529_f();
repo.field_148533_g = true;
if (file.exists() && hash.length() == 40) { // Lambdas MUST NOT be used with methods that need re-obfuscation in FG prior to 2.2 (will result in AbstractMethodError)
try { //noinspection Convert2Lambda
String fileHash = Hashing.sha1().hashBytes(Files.toByteArray(file)).toString(); HttpUtil.downloadResourcePack(file, url, new HttpUtil.DownloadListener() {
if (fileHash.equals(hash)) { public void onDownloadComplete(File file) {
if (repo.field_148533_g) {
repo.field_148533_g = false;
repo.field_148532_f = new FileResourcePack(file);
Minecraft.getMinecraft().scheduleResourcesRefresh();
recordResourcePack(file, requestId); recordResourcePack(file, requestId);
return repo.func_177319_a(file);
}
logger.warn("File " + file + " had wrong hash (expected " + hash + ", found " + fileHash + "). Deleting it.");
FileUtils.deleteQuietly(file);
} catch (IOException ioexception) {
logger.warn("File " + file + " couldn\'t be hashed. Deleting it.", ioexception);
FileUtils.deleteQuietly(file);
} }
} }
}, hashmap, 50*1024*1024, guiScreen, Minecraft.getMinecraft().getProxy());
final GuiScreenWorking guiScreen = new GuiScreenWorking();
final Minecraft mc = Minecraft.getMinecraft();
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() {
@Override
public void onSuccess(Object value) {
recordResourcePack(file, requestId);
repo.func_177319_a(file);
}
@Override
public void onFailure(@Nonnull Throwable throwable) {
throwable.printStackTrace();
}
});
return repo.field_177322_i;
} finally {
repo.field_177321_h.unlock();
} }
} }
}

View File

@@ -3,13 +3,13 @@ package com.replaymod.render;
import com.replaymod.core.ReplayMod; import com.replaymod.core.ReplayMod;
import com.replaymod.render.utils.RenderJob; import com.replaymod.render.utils.RenderJob;
import com.replaymod.replay.events.ReplayCloseEvent; import com.replaymod.replay.events.ReplayCloseEvent;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraft.crash.CrashReport; import net.minecraft.crash.CrashReport;
import net.minecraft.util.ReportedException; import net.minecraft.util.ReportedException;
import net.minecraftforge.common.config.Configuration; import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;

View File

@@ -5,11 +5,11 @@ import com.replaymod.render.rendering.FrameConsumer;
import com.replaymod.render.rendering.VideoRenderer; import com.replaymod.render.rendering.VideoRenderer;
import com.replaymod.render.utils.ByteBufferPool; import com.replaymod.render.utils.ByteBufferPool;
import com.replaymod.render.utils.StreamPipe; import com.replaymod.render.utils.StreamPipe;
import cpw.mods.fml.common.versioning.ComparableVersion;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.crash.CrashReport; import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory; import net.minecraft.crash.CrashReportCategory;
import net.minecraft.util.Util; import net.minecraft.util.Util;
import net.minecraftforge.fml.common.versioning.ComparableVersion;
import org.apache.commons.exec.CommandLine; import org.apache.commons.exec.CommandLine;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;

View File

@@ -4,10 +4,10 @@ import com.replaymod.render.RenderSettings;
import com.replaymod.render.frame.CubicOpenGlFrame; import com.replaymod.render.frame.CubicOpenGlFrame;
import com.replaymod.render.frame.ODSOpenGlFrame; import com.replaymod.render.frame.ODSOpenGlFrame;
import com.replaymod.render.frame.OpenGlFrame; import com.replaymod.render.frame.OpenGlFrame;
import com.replaymod.render.hooks.GLStateTracker;
import com.replaymod.render.rendering.FrameCapturer; import com.replaymod.render.rendering.FrameCapturer;
import com.replaymod.render.shader.Program; import com.replaymod.render.shader.Program;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.crash.CrashReport; import net.minecraft.crash.CrashReport;
import net.minecraft.util.ReportedException; import net.minecraft.util.ReportedException;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
@@ -15,9 +15,13 @@ import org.lwjgl.util.ReadableDimension;
import java.io.IOException; import java.io.IOException;
import static net.minecraft.client.renderer.GlStateManager.*;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT; import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT; import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL11.glPopMatrix;
import static org.lwjgl.opengl.GL11.glPushMatrix;
public class ODSFrameCapturer implements FrameCapturer<ODSOpenGlFrame> { public class ODSFrameCapturer implements FrameCapturer<ODSOpenGlFrame> {
private static final ResourceLocation vertexResource = new ResourceLocation("replaymod", "shader/ods.vert"); private static final ResourceLocation vertexResource = new ResourceLocation("replaymod", "shader/ods.vert");
@@ -28,8 +32,8 @@ public class ODSFrameCapturer implements FrameCapturer<ODSOpenGlFrame> {
private final Program.Uniform directionVariable; private final Program.Uniform directionVariable;
private final Program.Uniform leftEyeVariable; private final Program.Uniform leftEyeVariable;
private final BooleanState[] previousStates = new BooleanState[3]; private final GLStateTracker.EnabledState[] previousStates = new GLStateTracker.EnabledState[2];
private final BooleanState previousFogState; private final GLStateTracker.EnabledState previousFogState;
private final Minecraft mc = Minecraft.getMinecraft(); private final Minecraft mc = Minecraft.getMinecraft();
@@ -42,6 +46,11 @@ public class ODSFrameCapturer implements FrameCapturer<ODSOpenGlFrame> {
return renderInfo.getFrameSize(); return renderInfo.getFrameSize();
} }
@Override
public int getFramesDone() {
return renderInfo.getFramesDone();
}
@Override @Override
public int getTotalFrames() { public int getTotalFrames() {
return renderInfo.getTotalFrames(); return renderInfo.getTotalFrames();
@@ -73,15 +82,14 @@ public class ODSFrameCapturer implements FrameCapturer<ODSOpenGlFrame> {
setTexture("lightMap", 1); setTexture("lightMap", 1);
linkState(0, "textureEnabled"); linkState(0, "textureEnabled");
linkState(1, "lightMapEnabled"); linkState(1, "lightMapEnabled");
linkState(2, "hurtTextureEnabled");
final Program.Uniform uniform = shaderProgram.getUniformVariable("fogEnabled"); final Program.Uniform uniform = shaderProgram.getUniformVariable("fogEnabled");
previousFogState = GlStateManager.fogState.field_179049_a; previousFogState = GLStateTracker.getInstance().fog;
uniform.set(previousFogState.currentState); uniform.set(previousFogState.isEnabled());
GlStateManager.fogState.field_179049_a = new BooleanState(previousFogState.capability) { GLStateTracker.getInstance().fog = new GLStateTracker.EnabledState() {
@Override @Override
public void setState(boolean state) { public void setEnabled(boolean enabled) {
super.setState(state); super.setEnabled(enabled);
uniform.set(state); uniform.set(enabled);
} }
}; };
shaderProgram.stopUsing(); shaderProgram.stopUsing();
@@ -96,13 +104,13 @@ public class ODSFrameCapturer implements FrameCapturer<ODSOpenGlFrame> {
private void linkState(int id, String var) { private void linkState(int id, String var) {
final Program.Uniform uniform = shaderProgram.getUniformVariable(var); final Program.Uniform uniform = shaderProgram.getUniformVariable(var);
previousStates[id] = GlStateManager.textureState[id].texture2DState; previousStates[id] = GLStateTracker.getInstance().texture[id];
uniform.set(previousStates[id].currentState); uniform.set(previousStates[id].isEnabled());
GlStateManager.textureState[id].texture2DState = new BooleanState(previousStates[id].capability) { GLStateTracker.getInstance().texture[id] = new GLStateTracker.EnabledState() {
@Override @Override
public void setState(boolean state) { public void setEnabled(boolean enabled) {
super.setState(state); super.setEnabled(enabled);
uniform.set(state); uniform.set(enabled);
} }
}; };
} }
@@ -132,10 +140,10 @@ public class ODSFrameCapturer implements FrameCapturer<ODSOpenGlFrame> {
left.close(); left.close();
right.close(); right.close();
shaderProgram.delete(); shaderProgram.delete();
for (int i = 0; i < 3; i++) { for (int i = 0; i < previousStates.length; i++) {
GlStateManager.textureState[i].texture2DState = previousStates[i]; GLStateTracker.getInstance().texture[i] = previousStates[i];
} }
GlStateManager.fogState.field_179049_a = previousFogState; GLStateTracker.getInstance().fog = previousFogState;
} }
private class CubicStereoFrameCapturer extends CubicPboOpenGlFrameCapturer { private class CubicStereoFrameCapturer extends CubicPboOpenGlFrameCapturer {
@@ -147,17 +155,17 @@ public class ODSFrameCapturer implements FrameCapturer<ODSOpenGlFrame> {
protected OpenGlFrame renderFrame(int frameId, float partialTicks, CubicOpenGlFrameCapturer.Data captureData) { protected OpenGlFrame renderFrame(int frameId, float partialTicks, CubicOpenGlFrameCapturer.Data captureData) {
resize(getFrameWidth(), getFrameHeight()); resize(getFrameWidth(), getFrameHeight());
pushMatrix(); glPushMatrix();
frameBuffer().bindFramebuffer(true); frameBuffer().bindFramebuffer(true);
clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
enableTexture2D(); glEnable(GL_TEXTURE_2D);
directionVariable.set(captureData.ordinal()); directionVariable.set(captureData.ordinal());
worldRenderer.renderWorld(partialTicks, null); worldRenderer.renderWorld(partialTicks, null);
frameBuffer().unbindFramebuffer(); frameBuffer().unbindFramebuffer();
popMatrix(); glPopMatrix();
return captureFrame(frameId, captureData); return captureFrame(frameId, captureData);
} }

View File

@@ -15,9 +15,9 @@ import org.lwjgl.util.WritableDimension;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import static net.minecraft.client.renderer.GlStateManager.*;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT; import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT; import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
public abstract class OpenGlFrameCapturer<F extends Frame, D extends CaptureData> implements FrameCapturer<F> { public abstract class OpenGlFrameCapturer<F extends Frame, D extends CaptureData> implements FrameCapturer<F> {
protected final WorldRenderer worldRenderer; protected final WorldRenderer worldRenderer;
@@ -76,16 +76,16 @@ public abstract class OpenGlFrameCapturer<F extends Frame, D extends CaptureData
protected OpenGlFrame renderFrame(int frameId, float partialTicks, D captureData) { protected OpenGlFrame renderFrame(int frameId, float partialTicks, D captureData) {
resize(getFrameWidth(), getFrameHeight()); resize(getFrameWidth(), getFrameHeight());
pushMatrix(); GL11.glPushMatrix();
frameBuffer().bindFramebuffer(true); frameBuffer().bindFramebuffer(true);
clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GL11.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
enableTexture2D(); GL11.glEnable(GL_TEXTURE_2D);
worldRenderer.renderWorld(partialTicks, captureData); worldRenderer.renderWorld(partialTicks, captureData);
frameBuffer().unbindFramebuffer(); frameBuffer().unbindFramebuffer();
popMatrix(); GL11.glPopMatrix();
return captureFrame(frameId, captureData); return captureFrame(frameId, captureData);
} }

View File

@@ -6,6 +6,8 @@ import org.lwjgl.util.ReadableDimension;
public interface RenderInfo { public interface RenderInfo {
ReadableDimension getFrameSize(); ReadableDimension getFrameSize();
int getFramesDone();
int getTotalFrames(); int getTotalFrames();
float updateForNextFrame(); float updateForNextFrame();

View File

@@ -1,9 +1,9 @@
package com.replaymod.render.events; package com.replaymod.render.events;
import com.replaymod.render.rendering.VideoRenderer; import com.replaymod.render.rendering.VideoRenderer;
import cpw.mods.fml.common.eventhandler.Event;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import net.minecraftforge.fml.common.eventhandler.Event;
@RequiredArgsConstructor @RequiredArgsConstructor
public abstract class ReplayRenderEvent extends Event { public abstract class ReplayRenderEvent extends Event {

View File

@@ -1,105 +0,0 @@
package com.replaymod.render.hooks;
import com.replaymod.render.utils.JailingQueue;
import net.minecraft.client.renderer.RegionRenderCacheBuilder;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.client.renderer.chunk.ChunkCompileTaskGenerator;
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher;
import net.minecraft.client.renderer.chunk.ChunkRenderWorker;
import net.minecraft.client.renderer.chunk.RenderChunk;
import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.concurrent.BlockingQueue;
public class ChunkLoadingRenderGlobal {
private final RenderGlobal hooked;
private final ChunkRenderDispatcher renderDispatcher;
private final JailingQueue<?> workerJailingQueue;
private final CustomChunkRenderWorker renderWorker;
private int frame;
@SuppressWarnings("unchecked")
public ChunkLoadingRenderGlobal(RenderGlobal renderGlobal) {
this.hooked = renderGlobal;
this.renderDispatcher = renderGlobal.renderDispatcher;
this.renderWorker = new CustomChunkRenderWorker(renderDispatcher, new RegionRenderCacheBuilder());
int workerThreads = renderDispatcher.listThreadedWorkers.size();
BlockingQueue<Object> queueChunkUpdates = renderDispatcher.queueChunkUpdates;
workerJailingQueue = new JailingQueue<>(queueChunkUpdates);
renderDispatcher.queueChunkUpdates = workerJailingQueue;
ChunkCompileTaskGenerator element = new ChunkCompileTaskGenerator(null, null);
element.finish();
for (int i = 0; i < workerThreads; i++) {
queueChunkUpdates.add(element);
}
// Temporary workaround for dead lock, will be replaced by a new (ShaderMod compatible) mechanism later
//noinspection StatementWithEmptyBody
while (renderDispatcher.runChunkUploads(0)) {}
workerJailingQueue.jail(workerThreads);
renderDispatcher.queueChunkUpdates = queueChunkUpdates;
try {
Field hookField = RenderGlobal.class.getField("replayModRender_hook");
hookField.set(hooked, this);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new Error(e);
}
}
@SuppressWarnings("unchecked")
public void updateChunks() {
while (renderDispatcher.runChunkUploads(0)) {
hooked.displayListEntitiesDirty = true;
}
while (!renderDispatcher.queueChunkUpdates.isEmpty()) {
try {
renderWorker.processTask((ChunkCompileTaskGenerator) renderDispatcher.queueChunkUpdates.poll());
} catch (InterruptedException ignored) { }
}
Iterator<RenderChunk> iterator = hooked.chunksToUpdate.iterator();
while (iterator.hasNext()) {
RenderChunk renderchunk = iterator.next();
renderDispatcher.updateChunkNow(renderchunk);
renderchunk.setNeedsUpdate(false);
iterator.remove();
}
}
public void uninstall() {
workerJailingQueue.freeAll();
try {
Field hookField = RenderGlobal.class.getField("replayModRender_hook");
hookField.set(hooked, null);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new Error(e);
}
}
public int nextFrameId() {
return frame++;
}
/**
* Custom ChunkRenderWorker class providing access to the protected processTask method
*/
private static class CustomChunkRenderWorker extends ChunkRenderWorker {
public CustomChunkRenderWorker(ChunkRenderDispatcher p_i46202_1_, RegionRenderCacheBuilder p_i46202_2_) {
super(p_i46202_1_, p_i46202_2_);
}
@Override
protected void processTask(ChunkCompileTaskGenerator p_178474_1_) throws InterruptedException {
super.processTask(p_178474_1_);
}
}
}

View File

@@ -2,11 +2,12 @@ package com.replaymod.render.hooks;
import com.replaymod.render.RenderSettings; import com.replaymod.render.RenderSettings;
import com.replaymod.render.capturer.CaptureData; import com.replaymod.render.capturer.CaptureData;
import com.replaymod.render.capturer.RenderInfo;
import com.replaymod.render.capturer.WorldRenderer; import com.replaymod.render.capturer.WorldRenderer;
import cpw.mods.fml.common.FMLCommonHandler;
import lombok.Getter; import lombok.Getter;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager; import org.lwjgl.opengl.GL11;
import net.minecraftforge.fml.common.FMLCommonHandler;
import java.io.IOException; import java.io.IOException;
@@ -16,12 +17,16 @@ public class EntityRendererHandler implements WorldRenderer {
@Getter @Getter
protected final RenderSettings settings; protected final RenderSettings settings;
@Getter
private final RenderInfo renderInfo;
public CaptureData data; public CaptureData data;
public boolean omnidirectional; public boolean omnidirectional;
public EntityRendererHandler(RenderSettings settings) { public EntityRendererHandler(RenderSettings settings, RenderInfo renderInfo) {
this.settings = settings; this.settings = settings;
this.renderInfo = renderInfo;
((IEntityRenderer) mc.entityRenderer).replayModRender_setHandler(this); ((IEntityRenderer) mc.entityRenderer).replayModRender_setHandler(this);
} }
@@ -37,11 +42,11 @@ public class EntityRendererHandler implements WorldRenderer {
mc.entityRenderer.updateLightmap(partialTicks); mc.entityRenderer.updateLightmap(partialTicks);
GlStateManager.enableDepth(); GL11.glEnable(GL11.GL_DEPTH_TEST);
GlStateManager.enableAlpha(); GL11.glEnable(GL11.GL_ALPHA_TEST);
GlStateManager.alphaFunc(516, 0.5F); GL11.glAlphaFunc(516, 0.5F);
mc.entityRenderer.renderWorldPass(2, partialTicks, finishTimeNano); mc.entityRenderer.renderWorld(partialTicks, finishTimeNano);
FMLCommonHandler.instance().onRenderTickEnd(partialTicks); FMLCommonHandler.instance().onRenderTickEnd(partialTicks);
} }

View File

@@ -0,0 +1,63 @@
package com.replaymod.render.hooks;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
/**
* Tracks OpenGL state for use in the ODS shader.
* All methods should be called from the GL mixins only.
*/
public class GLStateTracker {
private static ThreadLocal<GLStateTracker> stateTracker = ThreadLocal.withInitial(GLStateTracker::new);
public static GLStateTracker getInstance() {
return stateTracker.get();
}
public int activeTexture;
public EnabledState fog = new EnabledState();
public EnabledState[] texture = new EnabledState[32];
{
for (int i = 0; i < texture.length; i++) {
texture[i] = new EnabledState();
}
}
public void updateActiveTexture(int magic) {
this.activeTexture = magic - GL13.GL_TEXTURE0;
}
public void updateEnabledState(int magic, boolean enabled) {
switch (magic) {
case GL11.GL_FOG: fog.setEnabled(enabled); break;
case GL11.GL_TEXTURE_2D: texture[activeTexture].setEnabled(enabled); break;
}
}
public static class EnabledState {
private boolean enabled;
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isEnabled() {
return enabled;
}
}
// Called via ASM (see GLStateTrackerTransformer)
@Deprecated
@SuppressWarnings("unused")
public static void hook_glEnable(int magic) {
GL11.glEnable(magic);
getInstance().updateEnabledState(magic, true);
}
// Called via ASM (see GLStateTrackerTransformer)
@Deprecated
@SuppressWarnings("unused")
public static void hook_glDisable(int magic) {
GL11.glDisable(magic);
getInstance().updateEnabledState(magic, false);
}
}

View File

@@ -4,7 +4,7 @@ import com.replaymod.render.hooks.EntityRendererHandler;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.EffectRenderer; import net.minecraft.client.particle.EffectRenderer;
import net.minecraft.client.particle.EntityFX; import net.minecraft.client.particle.EntityFX;
import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.Tessellator;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@@ -12,22 +12,23 @@ import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(EffectRenderer.class) @Mixin(EffectRenderer.class)
public abstract class MixinEffectRenderer { 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")) @Redirect(method = "renderParticles", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/EntityFX;renderParticle(Lnet/minecraft/client/renderer/Tesselator;FFFFFF)V"))
private void renderNormalParticle(EntityFX fx, WorldRenderer worldRenderer, Entity view, float partialTicks, private void renderNormalParticle(EntityFX fx, Tessellator tesselator, float partialTicks,
float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) { float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) {
renderParticle(fx, worldRenderer, view, partialTicks, rotX, rotXZ, rotZ, rotYZ, rotXY); renderParticle(fx, tesselator, 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")) @Redirect(method = "renderLitParticles", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/EntityFX;renderParticle(Lnet/minecraft/client/renderer/Tesselator;FFFFFF)V"))
private void renderLitParticle(EntityFX fx, WorldRenderer worldRenderer, Entity view, float partialTicks, private void renderLitParticle(EntityFX fx, Tessellator tesselator, float partialTicks,
float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) { float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) {
renderParticle(fx, worldRenderer, view, partialTicks, rotX, rotXZ, rotZ, rotYZ, rotXY); renderParticle(fx, tesselator, partialTicks, rotX, rotXZ, rotZ, rotYZ, rotXY);
} }
private void renderParticle(EntityFX fx, WorldRenderer worldRenderer, Entity view, float partialTicks, private void renderParticle(EntityFX fx, Tessellator tessellator, float partialTicks,
float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) { float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) {
EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) Minecraft.getMinecraft().entityRenderer).replayModRender_getHandler(); EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) Minecraft.getMinecraft().entityRenderer).replayModRender_getHandler();
if (handler != null && handler.omnidirectional) { if (handler != null && handler.omnidirectional) {
Entity view = Minecraft.getMinecraft().renderViewEntity;
// Align all particles towards the camera // Align all particles towards the camera
double dx = fx.prevPosX + (fx.posX - fx.prevPosX) * partialTicks - view.posX; double dx = fx.prevPosX + (fx.posX - fx.prevPosX) * partialTicks - view.posX;
double dy = fx.prevPosY + (fx.posY - fx.prevPosY) * partialTicks - view.posY; double dy = fx.prevPosY + (fx.posY - fx.prevPosY) * partialTicks - view.posY;
@@ -42,6 +43,6 @@ public abstract class MixinEffectRenderer {
rotYZ = (float) (-rotZ * Math.sin(pitch)); rotYZ = (float) (-rotZ * Math.sin(pitch));
rotXY = (float) (rotX * Math.sin(pitch)); rotXY = (float) (rotX * Math.sin(pitch));
} }
fx.func_180434_a(worldRenderer, view, partialTicks, rotX, rotXZ, rotZ, rotYZ, rotXY); fx.renderParticle(tessellator, partialTicks, rotX, rotXZ, rotZ, rotYZ, rotXY);
} }
} }

View File

@@ -7,10 +7,10 @@ import com.replaymod.render.hooks.EntityRendererHandler;
import com.replaymod.replay.camera.CameraEntity; import com.replaymod.replay.camera.CameraEntity;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.EntityRenderer; import net.minecraft.client.renderer.EntityRenderer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderGlobal; import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.client.settings.GameSettings; import net.minecraft.client.settings.GameSettings;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.MovingObjectPosition;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
@@ -40,6 +40,15 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
return replayModRender_handler; return replayModRender_handler;
} }
@Redirect(method = "renderWorld", at = @At(value = "INVOKE",target =
"Lnet/minecraft/client/renderer/RenderGlobal;updateRenderers(Lnet/minecraft/entity/EntityLivingBase;Z)Z"))
private boolean replayModRender_updateAllChunks(RenderGlobal self, EntityLivingBase view, boolean renderAllChunks) {
if (replayModRender_handler != null) {
renderAllChunks = true;
}
return self.updateRenderers(view, renderAllChunks);
}
@Inject(method = "setupFog", at = @At("HEAD"), cancellable = true) @Inject(method = "setupFog", at = @At("HEAD"), cancellable = true)
private void replayModRender_onSetupFog(int fogDistanceFlag, float partialTicks, CallbackInfo ci) { private void replayModRender_onSetupFog(int fogDistanceFlag, float partialTicks, CallbackInfo ci) {
if (replayModRender_handler == null) return; if (replayModRender_handler == null) return;
@@ -51,7 +60,7 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
@Inject(method = "orientCamera", at = @At("HEAD")) @Inject(method = "orientCamera", at = @At("HEAD"))
private void replayModRender_resetRotationIfNeeded(float partialTicks, CallbackInfo ci) { private void replayModRender_resetRotationIfNeeded(float partialTicks, CallbackInfo ci) {
if (replayModRender_handler != null) { if (replayModRender_handler != null) {
Entity entity = Minecraft.getMinecraft().getRenderViewEntity(); Entity entity = Minecraft.getMinecraft().renderViewEntity;
RenderSettings settings = replayModRender_handler.getSettings(); RenderSettings settings = replayModRender_handler.getSettings();
if (settings.isStabilizeYaw()) { if (settings.isStabilizeYaw()) {
entity.prevRotationYaw = entity.rotationYaw = 0; entity.prevRotationYaw = entity.rotationYaw = 0;
@@ -74,7 +83,7 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
@Inject(method = "setupCameraTransform", at = @At("HEAD")) @Inject(method = "setupCameraTransform", at = @At("HEAD"))
private void replayModRender_beforeSetupCameraTransform(float partialTicks, int renderPass, CallbackInfo ci) { private void replayModRender_beforeSetupCameraTransform(float partialTicks, int renderPass, CallbackInfo ci) {
if (replayModRender_handler != null) { if (replayModRender_handler != null) {
Entity entity = Minecraft.getMinecraft().getRenderViewEntity(); Entity entity = Minecraft.getMinecraft().renderViewEntity;
orgYaw = entity.rotationYaw; orgYaw = entity.rotationYaw;
orgPitch = entity.rotationPitch; orgPitch = entity.rotationPitch;
orgPrevYaw = entity.prevRotationYaw; orgPrevYaw = entity.prevRotationYaw;
@@ -86,7 +95,7 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
@Inject(method = "setupCameraTransform", at = @At("RETURN")) @Inject(method = "setupCameraTransform", at = @At("RETURN"))
private void replayModRender_afterSetupCameraTransform(float partialTicks, int renderPass, CallbackInfo ci) { private void replayModRender_afterSetupCameraTransform(float partialTicks, int renderPass, CallbackInfo ci) {
if (replayModRender_handler != null) { if (replayModRender_handler != null) {
Entity entity = Minecraft.getMinecraft().getRenderViewEntity(); Entity entity = Minecraft.getMinecraft().renderViewEntity;
entity.rotationYaw = orgYaw; entity.rotationYaw = orgYaw;
entity.rotationPitch = orgPitch; entity.rotationPitch = orgPitch;
entity.prevRotationYaw = orgPrevYaw; entity.prevRotationYaw = orgPrevYaw;
@@ -104,7 +113,7 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
ci.cancel(); ci.cancel();
return; // No spectator hands during 360° view, we wouldn't even know where to put it return; // No spectator hands during 360° view, we wouldn't even know where to put it
} }
Entity currentEntity = Minecraft.getMinecraft().getRenderViewEntity(); Entity currentEntity = Minecraft.getMinecraft().renderViewEntity;
if (currentEntity instanceof EntityPlayer && !(currentEntity instanceof CameraEntity)) { if (currentEntity instanceof EntityPlayer && !(currentEntity instanceof CameraEntity)) {
if (renderPass == 2) { // Need to update render pass if (renderPass == 2) { // Need to update render pass
renderPass = replayModRender_handler.data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE ? 1 : 0; renderPass = replayModRender_handler.data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE ? 1 : 0;
@@ -118,7 +127,7 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
@Shadow @Shadow
public abstract void renderHand(float partialTicks, int renderPass); 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")) @Redirect(method = "renderWorld", 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) { private void replayModRender_drawSelectionBox(RenderGlobal instance, EntityPlayer player, MovingObjectPosition mop, int alwaysZero, float partialTicks) {
if (replayModRender_handler == null) { if (replayModRender_handler == null) {
instance.drawSelectionBox(player, mop, alwaysZero, partialTicks); instance.drawSelectionBox(player, mop, alwaysZero, partialTicks);
@@ -127,7 +136,8 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
private int orgRenderDistanceChunks; private int orgRenderDistanceChunks;
@Inject(method = "renderWorldPass", at = @At(value = "JUMP", ordinal = 0)) @Inject(method = "renderWorld", at = @At(value = "INVOKE", ordinal = 0, shift = At.Shift.AFTER,
target = "Lnet/minecraft/client/renderer/culling/ClippingHelperImpl;getInstance()Lnet/minecraft/client/renderer/culling/ClippingHelper;"))
private void replayModRender_beforeRenderSky(CallbackInfo ci) { private void replayModRender_beforeRenderSky(CallbackInfo ci) {
if (replayModRender_handler != null && replayModRender_handler.getSettings().getChromaKeyingColor() != null) { if (replayModRender_handler != null && replayModRender_handler.getSettings().getChromaKeyingColor() != null) {
GameSettings settings = Minecraft.getMinecraft().gameSettings; GameSettings settings = Minecraft.getMinecraft().gameSettings;
@@ -136,15 +146,15 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
} }
} }
@Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;renderSky(FI)V")) @Redirect(method = "renderWorld", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;renderSky(F)V"))
private void replayModRender_renderSky(RenderGlobal instance, float partialTicks, int renderPass) { private void replayModRender_renderSky(RenderGlobal instance, float partialTicks) {
if (replayModRender_handler != null && replayModRender_handler.getSettings().getChromaKeyingColor() != null) { if (replayModRender_handler != null && replayModRender_handler.getSettings().getChromaKeyingColor() != null) {
Minecraft.getMinecraft().gameSettings.renderDistanceChunks = orgRenderDistanceChunks; Minecraft.getMinecraft().gameSettings.renderDistanceChunks = orgRenderDistanceChunks;
ReadableColor color = replayModRender_handler.getSettings().getChromaKeyingColor(); ReadableColor color = replayModRender_handler.getSettings().getChromaKeyingColor();
GlStateManager.clearColor(color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, 1); GL11.glClearColor(color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, 1);
GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT); GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
} else { } else {
instance.renderSky(partialTicks, renderPass); instance.renderSky(partialTicks);
} }
} }
@@ -152,24 +162,24 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
* Stereoscopic Renderer * Stereoscopic Renderer
*/ */
@Inject(method = "setupCameraTransform", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GlStateManager;loadIdentity()V", shift = At.Shift.AFTER, ordinal = 0)) @Inject(method = "setupCameraTransform", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glLoadIdentity()V", shift = At.Shift.AFTER, ordinal = 0, remap = false))
private void replayModRender_setupStereoscopicProjection(float partialTicks, int renderPass, CallbackInfo ci) { private void replayModRender_setupStereoscopicProjection(float partialTicks, int renderPass, CallbackInfo ci) {
if (replayModRender_getHandler() != null) { if (replayModRender_getHandler() != null) {
if (replayModRender_getHandler().data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE) { if (replayModRender_getHandler().data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE) {
GlStateManager.translate(0.07, 0, 0); GL11.glTranslatef(0.07f, 0, 0);
} else if (replayModRender_getHandler().data == StereoscopicOpenGlFrameCapturer.Data.RIGHT_EYE) { } else if (replayModRender_getHandler().data == StereoscopicOpenGlFrameCapturer.Data.RIGHT_EYE) {
GlStateManager.translate(-0.07, 0, 0); GL11.glTranslatef(-0.07f, 0, 0);
} }
} }
} }
@Inject(method = "setupCameraTransform", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GlStateManager;loadIdentity()V", shift = At.Shift.AFTER, ordinal = 1)) @Inject(method = "setupCameraTransform", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glLoadIdentity()V", shift = At.Shift.AFTER, ordinal = 1, remap = false))
private void replayModRender_setupStereoscopicModelView(float partialTicks, int renderPass, CallbackInfo ci) { private void replayModRender_setupStereoscopicModelView(float partialTicks, int renderPass, CallbackInfo ci) {
if (replayModRender_getHandler() != null) { if (replayModRender_getHandler() != null) {
if (replayModRender_getHandler().data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE) { if (replayModRender_getHandler().data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE) {
GlStateManager.translate(0.1, 0, 0); GL11.glTranslatef(0.1f, 0, 0);
} else if (replayModRender_getHandler().data == StereoscopicOpenGlFrameCapturer.Data.RIGHT_EYE) { } else if (replayModRender_getHandler().data == StereoscopicOpenGlFrameCapturer.Data.RIGHT_EYE) {
GlStateManager.translate(-0.1, 0, 0); GL11.glTranslatef(-0.1f, 0, 0);
} }
} }
} }
@@ -183,16 +193,11 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
replayModRender_gluPerspective(fovY, aspect, zNear, zFar); replayModRender_gluPerspective(fovY, aspect, zNear, zFar);
} }
@Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lorg/lwjgl/util/glu/Project;gluPerspective(FFFF)V", remap = false)) @Redirect(method = "renderHand", at = @At(value = "INVOKE", target = "Lorg/lwjgl/util/glu/Project;gluPerspective(FFFF)V", remap = false))
private void replayModRender_gluPerspective$1(float fovY, float aspect, float zNear, float zFar) { private void replayModRender_gluPerspective$1(float fovY, float aspect, float zNear, float zFar) {
replayModRender_gluPerspective(fovY, aspect, zNear, zFar); replayModRender_gluPerspective(fovY, aspect, zNear, zFar);
} }
@Redirect(method = "renderCloudsCheck", at = @At(value = "INVOKE", target = "Lorg/lwjgl/util/glu/Project;gluPerspective(FFFF)V", remap = false))
private void replayModRender_gluPerspective$2(float fovY, float aspect, float zNear, float zFar) {
replayModRender_gluPerspective(fovY, aspect, zNear, zFar);
}
@Override @Override
public void replayModRender_gluPerspective(float fovY, float aspect, float zNear, float zFar) { public void replayModRender_gluPerspective(float fovY, float aspect, float zNear, float zFar) {
if (replayModRender_getHandler() != null && replayModRender_getHandler().omnidirectional) { if (replayModRender_getHandler() != null && replayModRender_getHandler().omnidirectional) {
@@ -207,28 +212,28 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti
if (replayModRender_getHandler() != null && replayModRender_getHandler().data instanceof CubicOpenGlFrameCapturer.Data) { if (replayModRender_getHandler() != null && replayModRender_getHandler().data instanceof CubicOpenGlFrameCapturer.Data) {
switch ((CubicOpenGlFrameCapturer.Data) replayModRender_getHandler().data) { switch ((CubicOpenGlFrameCapturer.Data) replayModRender_getHandler().data) {
case FRONT: case FRONT:
GlStateManager.rotate(0, 0.0F, 1.0F, 0.0F); GL11.glRotatef(0, 0.0F, 1.0F, 0.0F);
break; break;
case RIGHT: case RIGHT:
GlStateManager.rotate(90, 0.0F, 1.0F, 0.0F); GL11.glRotatef(90, 0.0F, 1.0F, 0.0F);
break; break;
case BACK: case BACK:
GlStateManager.rotate(180, 0.0F, 1.0F, 0.0F); GL11.glRotatef(180, 0.0F, 1.0F, 0.0F);
break; break;
case LEFT: case LEFT:
GlStateManager.rotate(-90, 0.0F, 1.0F, 0.0F); GL11.glRotatef(-90, 0.0F, 1.0F, 0.0F);
break; break;
case BOTTOM: case BOTTOM:
GlStateManager.rotate(90, 1.0F, 0.0F, 0.0F); GL11.glRotatef(90, 1.0F, 0.0F, 0.0F);
break; break;
case TOP: case TOP:
GlStateManager.rotate(-90, 1.0F, 0.0F, 0.0F); GL11.glRotatef(-90, 1.0F, 0.0F, 0.0F);
break; break;
} }
} }
if (replayModRender_getHandler() != null && replayModRender_getHandler().omnidirectional) { if (replayModRender_getHandler() != null && replayModRender_getHandler().omnidirectional) {
// Minecraft goes back a little so we have to revert that // Minecraft goes back a little so we have to revert that
GlStateManager.translate(0.0F, 0.0F, 0.1F); GL11.glTranslatef(0.0F, 0.0F, 0.1F);
} }
} }
} }

View File

@@ -2,13 +2,13 @@ package com.replaymod.render.mixin;
import com.replaymod.render.hooks.EntityRendererHandler; import com.replaymod.render.hooks.EntityRendererHandler;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.culling.Frustum; import net.minecraft.client.renderer.culling.Frustrum;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(Frustum.class) @Mixin(Frustrum.class)
public abstract class MixinFrustum { public abstract class MixinFrustum {
@Inject(method = "isBoxInFrustum", at = @At("HEAD"), cancellable = true) @Inject(method = "isBoxInFrustum", at = @At("HEAD"), cancellable = true)
public void isBoxInFrustum(double minX, double minY, double minZ, double maxX, double maxY, double maxZ, CallbackInfoReturnable<Boolean> ci) { public void isBoxInFrustum(double minX, double minY, double minZ, double maxX, double maxY, double maxZ, CallbackInfoReturnable<Boolean> ci) {

View File

@@ -0,0 +1,16 @@
package com.replaymod.render.mixin;
import com.replaymod.render.hooks.GLStateTracker;
import net.minecraft.client.renderer.OpenGlHelper;
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(OpenGlHelper.class)
public abstract class MixinOpenGlHelper {
@Inject(method = "setActiveTexture", at = @At("RETURN"))
private static void replayModRender_trackActiveTexture(int magic, CallbackInfo ci) {
GLStateTracker.getInstance().updateActiveTexture(magic);
}
}

View File

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

View File

@@ -1,63 +0,0 @@
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 {
public ChunkLoadingRenderGlobal replayModRender_hook;
private boolean replayModRender_passThroughSetupTerrain;
@Shadow
public boolean displayListEntitiesDirty;
@Shadow
public ChunkRenderDispatcher renderDispatcher;
@Shadow
public abstract void setupTerrain(Entity viewEntity, double partialTicks, ICamera camera,
int frameCount, boolean playerSpectator);
@Inject(method = "setupTerrain", at = @At("HEAD"), cancellable = true)
public void replayModRender_setupTerrain(Entity viewEntity, double partialTicks, ICamera camera,
int frameCount, boolean playerSpectator, CallbackInfo ci) {
if (replayModRender_hook != null && !replayModRender_passThroughSetupTerrain) {
replayModRender_passThroughSetupTerrain = true;
do {
setupTerrain(viewEntity, partialTicks, camera, replayModRender_hook.nextFrameId(), playerSpectator);
} while (displayListEntitiesDirty);
displayListEntitiesDirty = true;
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) {
replayModRender_hook.updateChunks();
ci.cancel();
}
}
}

View File

@@ -30,9 +30,9 @@ public class Pipelines {
RenderSettings settings = renderInfo.getRenderSettings(); RenderSettings settings = renderInfo.getRenderSettings();
FrameCapturer<OpenGlFrame> capturer; FrameCapturer<OpenGlFrame> capturer;
if (PixelBufferObject.SUPPORTED) { if (PixelBufferObject.SUPPORTED) {
capturer = new SimplePboOpenGlFrameCapturer(new EntityRendererHandler(settings), renderInfo); capturer = new SimplePboOpenGlFrameCapturer(new EntityRendererHandler(settings, renderInfo), renderInfo);
} else { } else {
capturer = new SimpleOpenGlFrameCapturer(new EntityRendererHandler(settings), renderInfo); capturer = new SimpleOpenGlFrameCapturer(new EntityRendererHandler(settings, renderInfo), renderInfo);
} }
return new Pipeline<>(capturer, new OpenGlToRGBProcessor(), consumer); return new Pipeline<>(capturer, new OpenGlToRGBProcessor(), consumer);
} }
@@ -41,9 +41,9 @@ public class Pipelines {
RenderSettings settings = renderInfo.getRenderSettings(); RenderSettings settings = renderInfo.getRenderSettings();
FrameCapturer<StereoscopicOpenGlFrame> capturer; FrameCapturer<StereoscopicOpenGlFrame> capturer;
if (PixelBufferObject.SUPPORTED) { if (PixelBufferObject.SUPPORTED) {
capturer = new StereoscopicPboOpenGlFrameCapturer(new EntityRendererHandler(settings), renderInfo); capturer = new StereoscopicPboOpenGlFrameCapturer(new EntityRendererHandler(settings, renderInfo), renderInfo);
} else { } else {
capturer = new StereoscopicOpenGlFrameCapturer(new EntityRendererHandler(settings), renderInfo); capturer = new StereoscopicOpenGlFrameCapturer(new EntityRendererHandler(settings, renderInfo), renderInfo);
} }
return new Pipeline<>(capturer, new StereoscopicToRGBProcessor(), consumer); return new Pipeline<>(capturer, new StereoscopicToRGBProcessor(), consumer);
} }
@@ -52,9 +52,9 @@ public class Pipelines {
RenderSettings settings = renderInfo.getRenderSettings(); RenderSettings settings = renderInfo.getRenderSettings();
FrameCapturer<CubicOpenGlFrame> capturer; FrameCapturer<CubicOpenGlFrame> capturer;
if (PixelBufferObject.SUPPORTED) { if (PixelBufferObject.SUPPORTED) {
capturer = new CubicPboOpenGlFrameCapturer(new EntityRendererHandler(settings), renderInfo, settings.getVideoWidth() / 4); capturer = new CubicPboOpenGlFrameCapturer(new EntityRendererHandler(settings, renderInfo), renderInfo, settings.getVideoWidth() / 4);
} else { } else {
capturer = new CubicOpenGlFrameCapturer(new EntityRendererHandler(settings), renderInfo, settings.getVideoWidth() / 4); capturer = new CubicOpenGlFrameCapturer(new EntityRendererHandler(settings, renderInfo), renderInfo, settings.getVideoWidth() / 4);
} }
return new Pipeline<>(capturer, new CubicToRGBProcessor(), consumer); return new Pipeline<>(capturer, new CubicToRGBProcessor(), consumer);
} }
@@ -63,9 +63,9 @@ public class Pipelines {
RenderSettings settings = renderInfo.getRenderSettings(); RenderSettings settings = renderInfo.getRenderSettings();
FrameCapturer<CubicOpenGlFrame> capturer; FrameCapturer<CubicOpenGlFrame> capturer;
if (PixelBufferObject.SUPPORTED) { if (PixelBufferObject.SUPPORTED) {
capturer = new CubicPboOpenGlFrameCapturer(new EntityRendererHandler(settings), renderInfo, settings.getVideoWidth() / 4); capturer = new CubicPboOpenGlFrameCapturer(new EntityRendererHandler(settings, renderInfo), renderInfo, settings.getVideoWidth() / 4);
} else { } else {
capturer = new CubicOpenGlFrameCapturer(new EntityRendererHandler(settings), renderInfo, settings.getVideoWidth() / 4); capturer = new CubicOpenGlFrameCapturer(new EntityRendererHandler(settings, renderInfo), renderInfo, settings.getVideoWidth() / 4);
} }
return new Pipeline<>(capturer, new EquirectangularToRGBProcessor(settings.getVideoWidth() / 4), consumer); return new Pipeline<>(capturer, new EquirectangularToRGBProcessor(settings.getVideoWidth() / 4), consumer);
} }
@@ -73,7 +73,7 @@ public class Pipelines {
public static Pipeline<ODSOpenGlFrame, RGBFrame> newODSPipeline(RenderInfo renderInfo, FrameConsumer<RGBFrame> consumer) { public static Pipeline<ODSOpenGlFrame, RGBFrame> newODSPipeline(RenderInfo renderInfo, FrameConsumer<RGBFrame> consumer) {
RenderSettings settings = renderInfo.getRenderSettings(); RenderSettings settings = renderInfo.getRenderSettings();
FrameCapturer<ODSOpenGlFrame> capturer = FrameCapturer<ODSOpenGlFrame> capturer =
new ODSFrameCapturer(new EntityRendererHandler(settings), renderInfo, settings.getVideoWidth() / 4); new ODSFrameCapturer(new EntityRendererHandler(settings, renderInfo), renderInfo, settings.getVideoWidth() / 4);
return new Pipeline<>(capturer, new ODSToRGBProcessor(settings.getVideoWidth() / 4), consumer); return new Pipeline<>(capturer, new ODSToRGBProcessor(settings.getVideoWidth() / 4), consumer);
} }
} }

View File

@@ -12,21 +12,21 @@ import com.replaymod.render.events.ReplayRenderEvent;
import com.replaymod.render.frame.RGBFrame; import com.replaymod.render.frame.RGBFrame;
import com.replaymod.render.gui.GuiRenderingDone; import com.replaymod.render.gui.GuiRenderingDone;
import com.replaymod.render.gui.GuiVideoRenderer; import com.replaymod.render.gui.GuiVideoRenderer;
import com.replaymod.render.hooks.ChunkLoadingRenderGlobal;
import com.replaymod.render.metadata.MetadataInjector; import com.replaymod.render.metadata.MetadataInjector;
import com.replaymod.replay.ReplayHandler; import com.replaymod.replay.ReplayHandler;
import com.replaymod.replaystudio.pathing.path.Keyframe; import com.replaymod.replaystudio.pathing.path.Keyframe;
import com.replaymod.replaystudio.pathing.path.Path; import com.replaymod.replaystudio.pathing.path.Path;
import com.replaymod.replaystudio.pathing.path.Timeline; import com.replaymod.replaystudio.pathing.path.Timeline;
import cpw.mods.fml.common.FMLCommonHandler;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.SoundCategory; import net.minecraft.client.audio.SoundCategory;
import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.shader.Framebuffer; import net.minecraft.client.shader.Framebuffer;
import net.minecraft.util.Timer; import net.minecraft.util.Timer;
import net.minecraftforge.fml.common.FMLCommonHandler;
import org.lwjgl.input.Mouse; import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display; import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.Dimension; import org.lwjgl.util.Dimension;
import org.lwjgl.util.ReadableDimension; import org.lwjgl.util.ReadableDimension;
@@ -40,9 +40,9 @@ import java.util.concurrent.FutureTask;
import static com.google.common.collect.Iterables.getLast; import static com.google.common.collect.Iterables.getLast;
import static com.replaymod.render.ReplayModRender.LOGGER; import static com.replaymod.render.ReplayModRender.LOGGER;
import static net.minecraft.client.renderer.GlStateManager.*;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT; import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT; import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
public class VideoRenderer implements RenderInfo { public class VideoRenderer implements RenderInfo {
private final Minecraft mc = Minecraft.getMinecraft(); private final Minecraft mc = Minecraft.getMinecraft();
@@ -59,7 +59,6 @@ public class VideoRenderer implements RenderInfo {
private TimelinePlayer timelinePlayer; private TimelinePlayer timelinePlayer;
private Future<Void> timelinePlayerFuture; private Future<Void> timelinePlayerFuture;
private ChunkLoadingRenderGlobal chunkLoadingRenderGlobal;
private int framesDone; private int framesDone;
private int totalFrames; private int totalFrames;
@@ -228,8 +227,6 @@ public class VideoRenderer implements RenderInfo {
ScaledResolution scaled = new ScaledResolution(mc, displayWidth, displayHeight); ScaledResolution scaled = new ScaledResolution(mc, displayWidth, displayHeight);
gui.toMinecraft().setWorldAndResolution(mc, scaled.getScaledWidth(), scaled.getScaledHeight()); gui.toMinecraft().setWorldAndResolution(mc, scaled.getScaledWidth(), scaled.getScaledHeight());
chunkLoadingRenderGlobal = new ChunkLoadingRenderGlobal(mc.renderGlobal);
// Set up our own framebuffer to render the GUI to // Set up our own framebuffer to render the GUI to
guiFramebuffer = new Framebuffer(displayWidth, displayHeight, true); guiFramebuffer = new Framebuffer(displayWidth, displayHeight, true);
} }
@@ -250,9 +247,6 @@ public class VideoRenderer implements RenderInfo {
} }
mc.gameSettings.mapSoundLevels = originalSoundLevels; mc.gameSettings.mapSoundLevels = originalSoundLevels;
mc.displayGuiScreen(null); mc.displayGuiScreen(null);
if (chunkLoadingRenderGlobal != null) {
chunkLoadingRenderGlobal.uninstall();
}
ReplayMod.soundHandler.playRenderSuccessSound(); ReplayMod.soundHandler.playRenderSuccessSound();
@@ -276,11 +270,7 @@ public class VideoRenderer implements RenderInfo {
} }
mc.currentScreen = gui.toMinecraft(); mc.currentScreen = gui.toMinecraft();
try {
mc.runTick(); mc.runTick();
} catch (IOException e) {
throw new RuntimeException(e);
}
} }
public void drawGui() { public void drawGui() {
@@ -291,9 +281,9 @@ public class VideoRenderer implements RenderInfo {
guiFramebuffer.createBindFramebuffer(mc.displayWidth, mc.displayHeight); guiFramebuffer.createBindFramebuffer(mc.displayWidth, mc.displayHeight);
} }
pushMatrix(); GL11.glPushMatrix();
clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GL11.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
enableTexture2D(); GL11.glEnable(GL_TEXTURE_2D);
guiFramebuffer.bindFramebuffer(true); guiFramebuffer.bindFramebuffer(true);
mc.entityRenderer.setupOverlayRendering(); mc.entityRenderer.setupOverlayRendering();
@@ -301,13 +291,7 @@ public class VideoRenderer implements RenderInfo {
ScaledResolution scaled = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight); ScaledResolution scaled = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight);
gui.toMinecraft().setWorldAndResolution(mc, scaled.getScaledWidth(), scaled.getScaledHeight()); gui.toMinecraft().setWorldAndResolution(mc, scaled.getScaledWidth(), scaled.getScaledHeight());
try {
gui.toMinecraft().handleInput(); gui.toMinecraft().handleInput();
} catch (IOException e) {
// That's a strange exception from this kind of method O_o
// It isn't actually thrown here, so we'll deal with it the easy way
throw new RuntimeException(e);
}
int mouseX = Mouse.getX() * scaled.getScaledWidth() / mc.displayWidth; int mouseX = Mouse.getX() * scaled.getScaledWidth() / mc.displayWidth;
int mouseY = scaled.getScaledHeight() - Mouse.getY() * scaled.getScaledHeight() / mc.displayHeight - 1; int mouseY = scaled.getScaledHeight() - Mouse.getY() * scaled.getScaledHeight() / mc.displayHeight - 1;
@@ -315,17 +299,17 @@ public class VideoRenderer implements RenderInfo {
gui.toMinecraft().drawScreen(mouseX, mouseY, 0); gui.toMinecraft().drawScreen(mouseX, mouseY, 0);
guiFramebuffer.unbindFramebuffer(); guiFramebuffer.unbindFramebuffer();
popMatrix(); GL11.glPopMatrix();
pushMatrix(); GL11.glPushMatrix();
guiFramebuffer.framebufferRender(displayWidth, displayHeight); guiFramebuffer.framebufferRender(displayWidth, displayHeight);
popMatrix(); GL11.glPopMatrix();
// if not in high performance mode, update the gui size if screen size changed // if not in high performance mode, update the gui size if screen size changed
// otherwise just swap the progress gui to screen // otherwise just swap the progress gui to screen
if (settings.isHighPerformance()) { if (settings.isHighPerformance()) {
Display.update(); Display.update();
} else { } else {
mc.updateDisplay(); mc.resetSize();
} }
if (Mouse.isGrabbed()) { if (Mouse.isGrabbed()) {
Mouse.setGrabbed(false); Mouse.setGrabbed(false);

View File

@@ -3,20 +3,20 @@ package com.replaymod.replay;
import com.replaymod.core.utils.WrappedTimer; import com.replaymod.core.utils.WrappedTimer;
import com.replaymod.replay.camera.CameraController; import com.replaymod.replay.camera.CameraController;
import com.replaymod.replay.camera.CameraEntity; import com.replaymod.replay.camera.CameraEntity;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.settings.GameSettings; import net.minecraft.client.settings.GameSettings;
import net.minecraft.client.settings.KeyBinding; import net.minecraft.client.settings.KeyBinding;
import net.minecraft.crash.CrashReport; import net.minecraft.crash.CrashReport;
import net.minecraft.util.ReportedException; import net.minecraft.util.ReportedException;
import net.minecraft.util.Timer; import net.minecraft.util.Timer;
import net.minecraftforge.client.ForgeHooksClient; import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.fml.common.FMLCommonHandler;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse; import org.lwjgl.input.Mouse;
import java.io.IOException;
public class InputReplayTimer extends WrappedTimer { public class InputReplayTimer extends WrappedTimer {
private final ReplayModReplay mod; private final ReplayModReplay mod;
private final Minecraft mc; private final Minecraft mc;
@@ -31,6 +31,9 @@ public class InputReplayTimer extends WrappedTimer {
public void updateTimer() { public void updateTimer() {
super.updateTimer(); super.updateTimer();
// 1.7.10: We have to run the scheduled executables (ours only) because MC would only run them every tick
FMLCommonHandler.instance().bus().post(new RunScheduledTasks());
// If we are in a replay, we have to manually process key and mouse events as the // If we are in a replay, we have to manually process key and mouse events as the
// tick speed may vary or there may not be any ticks at all (when the replay is paused) // tick speed may vary or there may not be any ticks at all (when the replay is paused)
if (mod.getReplayHandler() != null) { if (mod.getReplayHandler() != null) {
@@ -43,11 +46,7 @@ public class InputReplayTimer extends WrappedTimer {
handleKeyEvent(); handleKeyEvent();
} }
} else { } else {
try {
mc.currentScreen.handleInput(); mc.currentScreen.handleInput();
} catch (IOException e) { // *SIGH*
e.printStackTrace();
}
} }
} }
} }
@@ -89,17 +88,14 @@ public class InputReplayTimer extends WrappedTimer {
mc.setIngameFocus(); mc.setIngameFocus();
} }
} else { } else {
try {
mc.currentScreen.handleMouseInput(); mc.currentScreen.handleMouseInput();
} catch (IOException e) { // WHO IS RESPONSIBLE FOR THIS MESS?!?
e.printStackTrace();
}
} }
FMLCommonHandler.instance().fireMouseInput(); FMLCommonHandler.instance().fireMouseInput();
} }
protected void handleKeyEvent() { protected void handleKeyEvent() {
// TODO 1.7.10: This might be missing some 1.7.10-only key bindings or implement some of them incorrectly
int key = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey(); int key = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey();
boolean pressed = Keyboard.getEventKeyState(); boolean pressed = Keyboard.getEventKeyState();
@@ -127,15 +123,11 @@ public class InputReplayTimer extends WrappedTimer {
if (pressed) { if (pressed) {
// This might be subject to change as vanilla shaders are still kinda unused in 1.8 // This might be subject to change as vanilla shaders are still kinda unused in 1.8
if (key == Keyboard.KEY_F4 && mc.entityRenderer != null) { if (key == Keyboard.KEY_F4 && mc.entityRenderer != null) {
mc.entityRenderer.switchUseShader(); mc.entityRenderer.activateNextShader();
} }
if (mc.currentScreen != null) { if (mc.currentScreen != null) {
try {
mc.currentScreen.handleKeyboardInput(); mc.currentScreen.handleKeyboardInput();
} catch (IOException e) { // AND WHO THOUGHT THIS WAS A GREAT IDEA?
e.printStackTrace();
}
} else { } else {
if (key == Keyboard.KEY_ESCAPE) { if (key == Keyboard.KEY_ESCAPE) {
mc.displayInGameMenu(); mc.displayInGameMenu();
@@ -167,7 +159,7 @@ public class InputReplayTimer extends WrappedTimer {
} }
if (key == 48 && Keyboard.isKeyDown(61)) { if (key == 48 && Keyboard.isKeyDown(61)) {
mc.getRenderManager().setDebugBoundingBox(!mc.getRenderManager().isDebugBoundingBox()); RenderManager.debugBoundingBox = !RenderManager.debugBoundingBox;
} }
if (key == 25 && Keyboard.isKeyDown(61)) { if (key == 25 && Keyboard.isKeyDown(61)) {
@@ -186,14 +178,6 @@ public class InputReplayTimer extends WrappedTimer {
if (mc.gameSettings.keyBindTogglePerspective.isPressed()) { if (mc.gameSettings.keyBindTogglePerspective.isPressed()) {
mc.gameSettings.thirdPersonView = (mc.gameSettings.thirdPersonView + 1) % 3; mc.gameSettings.thirdPersonView = (mc.gameSettings.thirdPersonView + 1) % 3;
if (mc.entityRenderer != null) { // Extra check, not in vanilla code
if (mc.gameSettings.thirdPersonView == 0) {
mc.entityRenderer.loadEntityShader(mc.getRenderViewEntity());
} else if (mc.gameSettings.thirdPersonView == 1) {
mc.entityRenderer.loadEntityShader(null);
}
}
} }
} }
@@ -213,4 +197,6 @@ public class InputReplayTimer extends WrappedTimer {
FMLCommonHandler.instance().fireKeyInput(); FMLCommonHandler.instance().fireKeyInput();
} }
public static class RunScheduledTasks extends Event {}
} }

View File

@@ -8,9 +8,9 @@ import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.util.ScreenShotHelper; import net.minecraft.util.ScreenShotHelper;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.lwjgl.opengl.GL11;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.*; import java.awt.*;
@@ -40,18 +40,18 @@ public class NoGuiScreenshot {
mc.gameSettings.hideGUI = true; mc.gameSettings.hideGUI = true;
// Render frame without GUI // Render frame without GUI
GlStateManager.pushMatrix(); GL11.glPushMatrix();
GlStateManager.clear(16640); GL11.glClear(16640);
mc.getFramebuffer().bindFramebuffer(true); mc.getFramebuffer().bindFramebuffer(true);
GlStateManager.enableTexture2D(); GL11.glEnable(GL11.GL_TEXTURE_2D);
mc.entityRenderer.updateCameraAndRender(mc.timer.renderPartialTicks); mc.entityRenderer.updateCameraAndRender(mc.timer.renderPartialTicks);
mc.getFramebuffer().unbindFramebuffer(); mc.getFramebuffer().unbindFramebuffer();
GlStateManager.popMatrix(); GL11.glPopMatrix();
GlStateManager.pushMatrix(); GL11.glPushMatrix();
mc.getFramebuffer().framebufferRender(mc.displayWidth, mc.displayHeight); mc.getFramebuffer().framebufferRender(mc.displayWidth, mc.displayHeight);
GlStateManager.popMatrix(); GL11.glPopMatrix();
} catch (Throwable t) { } catch (Throwable t) {
future.setException(t); future.setException(t);
return; return;

View File

@@ -1,39 +1,41 @@
package com.replaymod.replay; package com.replaymod.replay;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.mojang.authlib.GameProfile;
import com.replaymod.core.utils.Restrictions; import com.replaymod.core.utils.Restrictions;
import com.replaymod.replay.camera.CameraEntity; import com.replaymod.replay.camera.CameraEntity;
import com.replaymod.replay.camera.SpectatorCameraController; import com.replaymod.replay.camera.SpectatorCameraController;
import com.replaymod.replay.events.ReplayCloseEvent; import com.replaymod.replay.events.ReplayCloseEvent;
import com.replaymod.replay.events.ReplayOpenEvent; import com.replaymod.replay.events.ReplayOpenEvent;
import com.replaymod.replay.gui.overlay.GuiReplayOverlay; import com.replaymod.replay.gui.overlay.GuiReplayOverlay;
import com.replaymod.replay.gui.screen.GuiOpeningReplay;
import com.replaymod.replaystudio.data.Marker; import com.replaymod.replaystudio.data.Marker;
import com.replaymod.replaystudio.replay.ReplayFile; import com.replaymod.replaystudio.replay.ReplayFile;
import com.replaymod.replaystudio.util.Location; import com.replaymod.replaystudio.util.Location;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.network.internal.FMLNetworkHandler;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.embedded.EmbeddedChannel;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityOtherPlayerMP; import net.minecraft.client.entity.EntityOtherPlayerMP;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.network.NetHandlerPlayClient; import net.minecraft.client.network.NetHandlerLoginClient;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.EnumPacketDirection; import net.minecraft.network.EnumConnectionState;
import net.minecraft.network.NetworkManager; import net.minecraft.network.NetworkManager;
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 org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
import static net.minecraft.client.renderer.GlStateManager.*;
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT; import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT; import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
public class ReplayHandler { public class ReplayHandler {
@@ -132,24 +134,29 @@ public class ReplayHandler {
private void setup() { private void setup() {
mc.ingameGUI.getChatGUI().clearChatMessages(); mc.ingameGUI.getChatGUI().clearChatMessages();
NetworkManager networkManager = new NetworkManager(EnumPacketDirection.CLIENTBOUND) { NetworkManager networkManager = new NetworkManager(true) {
@Override @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable t) { public void exceptionCaught(ChannelHandlerContext ctx, Throwable t) {
t.printStackTrace(); t.printStackTrace();
} }
}; };
NetHandlerPlayClient netHandlerPlayClient = networkManager.setNetHandler(new NetHandlerLoginClient(networkManager, mc, null));
new NetHandlerPlayClient(mc, null, networkManager, new GameProfile(UUID.randomUUID(), "Player"));
networkManager.setNetHandler(netHandlerPlayClient);
FMLClientHandler.instance().setPlayClient(netHandlerPlayClient);
channel = new EmbeddedChannel(networkManager); mc.displayGuiScreen(new GuiOpeningReplay(networkManager));
NetworkDispatcher networkDispatcher = new NetworkDispatcher(networkManager);
channel.attr(NetworkDispatcher.FML_DISPATCHER).set(networkDispatcher);
ChannelOutboundHandlerAdapter dummyHandler = new ChannelOutboundHandlerAdapter();
channel = new EmbeddedChannel(dummyHandler);
channel.pipeline().remove(dummyHandler);
channel.pipeline().addFirst("ReplayModReplay_replaySender", replaySender); channel.pipeline().addFirst("ReplayModReplay_replaySender", replaySender);
channel.pipeline().addAfter("ReplayModReplay_replaySender", "fml:packet_handler", networkDispatcher); channel.pipeline().addAfter("ReplayModReplay_replaySender", "packet_handler", networkManager);
channel.pipeline().fireChannelActive(); channel.pipeline().fireChannelActive();
// Call twice to force-overwrite the NetworkManager's internal state
networkManager.setConnectionState(EnumConnectionState.PLAY);
networkManager.getNetHandler().onConnectionStateTransition(EnumConnectionState.LOGIN, EnumConnectionState.PLAY);
networkManager.setConnectionState(EnumConnectionState.PLAY);
FMLNetworkHandler.fmlClientHandshake(networkManager);
} }
public ReplayFile getReplayFile() { public ReplayFile getReplayFile() {
@@ -209,7 +216,7 @@ public class ReplayHandler {
* When the entity is {@code null} or the camera entity, the camera becomes the view entity. * When the entity is {@code null} or the camera entity, the camera becomes the view entity.
* @param e The entity to spectate * @param e The entity to spectate
*/ */
public void spectateEntity(Entity e) { public void spectateEntity(EntityLivingBase e) {
CameraEntity cameraEntity = getCameraEntity(); CameraEntity cameraEntity = getCameraEntity();
if (cameraEntity == null) { if (cameraEntity == null) {
return; // Cannot spectate if we have no camera return; // Cannot spectate if we have no camera
@@ -227,15 +234,15 @@ public class ReplayHandler {
cameraEntity.setCameraController(new SpectatorCameraController(cameraEntity)); cameraEntity.setCameraController(new SpectatorCameraController(cameraEntity));
} }
if (mc.getRenderViewEntity() != e) { if (mc.renderViewEntity != e) {
mc.setRenderViewEntity(e); mc.renderViewEntity = e;
cameraEntity.setCameraPosRot(e); cameraEntity.setCameraPosRot(e);
} }
} }
/** /**
* Set the camera as the view entity. * Set the camera as the view entity.
* This is equivalent to {@link #spectateEntity(Entity) spectateEntity(null)}. * This is equivalent to {@link #spectateEntity(EntityLivingBase) spectateEntity(null)}.
*/ */
public void spectateCamera() { public void spectateCamera() {
spectateEntity(null); spectateEntity(null);
@@ -246,7 +253,7 @@ public class ReplayHandler {
* @return {@code true} if the camera is the view entity, {@code false} otherwise * @return {@code true} if the camera is the view entity, {@code false} otherwise
*/ */
public boolean isCameraView() { public boolean isCameraView() {
return mc.thePlayer instanceof CameraEntity && mc.thePlayer == mc.getRenderViewEntity(); return mc.thePlayer instanceof CameraEntity && mc.thePlayer == mc.renderViewEntity;
} }
/** /**
@@ -310,9 +317,9 @@ public class ReplayHandler {
replaySender.setSyncModeAndWait(); replaySender.setSyncModeAndWait();
// Perform the rendering using OpenGL // Perform the rendering using OpenGL
pushMatrix(); GL11.glPushMatrix();
clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GL11.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
enableTexture2D(); GL11.glEnable(GL_TEXTURE_2D);
mc.getFramebuffer().bindFramebuffer(true); mc.getFramebuffer().bindFramebuffer(true);
mc.entityRenderer.setupOverlayRendering(); mc.entityRenderer.setupOverlayRendering();
@@ -321,10 +328,10 @@ public class ReplayHandler {
guiScreen.drawScreen(0, 0, 0); guiScreen.drawScreen(0, 0, 0);
mc.getFramebuffer().unbindFramebuffer(); mc.getFramebuffer().unbindFramebuffer();
popMatrix(); GL11.glPopMatrix();
pushMatrix(); GL11.glPushMatrix();
mc.getFramebuffer().framebufferRender(mc.displayWidth, mc.displayHeight); mc.getFramebuffer().framebufferRender(mc.displayWidth, mc.displayHeight);
popMatrix(); GL11.glPopMatrix();
Display.update(); Display.update();
@@ -349,11 +356,7 @@ public class ReplayHandler {
entity.prevRotationYaw = entity.rotationYaw; entity.prevRotationYaw = entity.rotationYaw;
entity.prevRotationPitch = entity.rotationPitch; entity.prevRotationPitch = entity.rotationPitch;
} }
try {
mc.runTick(); mc.runTick();
} catch (IOException e) {
e.printStackTrace(); // This should never be thrown but whatever
}
//finally, updating the camera's position (which is not done by the sync jumping) //finally, updating the camera's position (which is not done by the sync jumping)
moveCameraToTargetPosition(); moveCameraToTargetPosition();

View File

@@ -18,11 +18,11 @@ import com.replaymod.replaystudio.data.Marker;
import com.replaymod.replaystudio.replay.ReplayFile; import com.replaymod.replaystudio.replay.ReplayFile;
import com.replaymod.replaystudio.replay.ZipReplayFile; import com.replaymod.replaystudio.replay.ZipReplayFile;
import com.replaymod.replaystudio.studio.ReplayStudio; import com.replaymod.replaystudio.studio.ReplayStudio;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;

View File

@@ -15,11 +15,38 @@ import io.netty.channel.ChannelPromise;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiDownloadTerrain; import net.minecraft.client.gui.GuiDownloadTerrain;
import net.minecraft.client.gui.GuiErrorScreen; import net.minecraft.client.gui.GuiErrorScreen;
import net.minecraft.client.resources.FileResourcePack;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
import net.minecraft.client.resources.ResourcePackRepository;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.network.*; import net.minecraft.network.EnumConnectionState;
import net.minecraft.network.play.server.*; import net.minecraft.network.Packet;
import net.minecraft.util.ClassInheritanceMultiMap; import net.minecraft.network.PacketBuffer;
import net.minecraft.network.play.server.S01PacketJoinGame;
import net.minecraft.network.play.server.S02PacketChat;
import net.minecraft.network.play.server.S06PacketUpdateHealth;
import net.minecraft.network.play.server.S07PacketRespawn;
import net.minecraft.network.play.server.S08PacketPlayerPosLook;
import net.minecraft.network.play.server.S0CPacketSpawnPlayer;
import net.minecraft.network.play.server.S0EPacketSpawnObject;
import net.minecraft.network.play.server.S0FPacketSpawnMob;
import net.minecraft.network.play.server.S10PacketSpawnPainting;
import net.minecraft.network.play.server.S11PacketSpawnExperienceOrb;
import net.minecraft.network.play.server.S13PacketDestroyEntities;
import net.minecraft.network.play.server.S1FPacketSetExperience;
import net.minecraft.network.play.server.S21PacketChunkData;
import net.minecraft.network.play.server.S2APacketParticles;
import net.minecraft.network.play.server.S2BPacketChangeGameState;
import net.minecraft.network.play.server.S2CPacketSpawnGlobalEntity;
import net.minecraft.network.play.server.S2DPacketOpenWindow;
import net.minecraft.network.play.server.S2EPacketCloseWindow;
import net.minecraft.network.play.server.S2FPacketSetSlot;
import net.minecraft.network.play.server.S30PacketWindowItems;
import net.minecraft.network.play.server.S36PacketSignEditorOpen;
import net.minecraft.network.play.server.S37PacketStatistics;
import net.minecraft.network.play.server.S39PacketPlayerAbilities;
import net.minecraft.network.play.server.S3FPacketCustomPayload;
import net.minecraft.network.play.server.S40PacketDisconnect;
import net.minecraft.util.IChatComponent; import net.minecraft.util.IChatComponent;
import net.minecraft.util.MathHelper; import net.minecraft.util.MathHelper;
import net.minecraft.world.EnumDifficulty; import net.minecraft.world.EnumDifficulty;
@@ -28,10 +55,15 @@ import net.minecraft.world.WorldSettings.GameType;
import net.minecraft.world.WorldType; import net.minecraft.world.WorldType;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.IChunkProvider; import net.minecraft.world.chunk.IChunkProvider;
import org.apache.commons.io.Charsets;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import java.io.*; import java.io.DataInputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@@ -46,14 +78,6 @@ import java.util.Map;
@Sharable @Sharable
public class ReplaySender extends ChannelDuplexHandler { public class ReplaySender extends ChannelDuplexHandler {
/**
* 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. * These packets are ignored completely during replay.
*/ */
@@ -66,9 +90,7 @@ public class ReplaySender extends ChannelDuplexHandler {
S36PacketSignEditorOpen.class, S36PacketSignEditorOpen.class,
S37PacketStatistics.class, S37PacketStatistics.class,
S1FPacketSetExperience.class, S1FPacketSetExperience.class,
S43PacketCamera.class, S39PacketPlayerAbilities.class);
S39PacketPlayerAbilities.class,
S45PacketTitle.class);
private static int TP_DISTANCE_LIMIT = 128; private static int TP_DISTANCE_LIMIT = 128;
@@ -123,7 +145,7 @@ public class ReplaySender extends ChannelDuplexHandler {
/** /**
* Whether we need to restart the current replay. E.g. when jumping backwards in time * Whether we need to restart the current replay. E.g. when jumping backwards in time
*/ */
protected boolean startFromBeginning = true; protected boolean startFromBeginning;
/** /**
* Whether to terminate the replay. This only has an effect on the async mode and is {@code true} during sync mode. * Whether to terminate the replay. This only has an effect on the async mode and is {@code true} during sync mode.
@@ -321,7 +343,7 @@ public class ReplaySender extends ChannelDuplexHandler {
int i = pb.readVarIntFromBuffer(); int i = pb.readVarIntFromBuffer();
Packet p = EnumConnectionState.PLAY.getPacket(EnumPacketDirection.CLIENTBOUND, i); Packet p = Packet.generatePacket(EnumConnectionState.PLAY.func_150755_b(), i);
p.readPacketData(pb); p.readPacketData(pb);
return p; return p;
@@ -335,7 +357,7 @@ public class ReplaySender extends ChannelDuplexHandler {
protected Packet processPacket(Packet p) throws Exception { protected Packet processPacket(Packet p) throws Exception {
if (p instanceof S3FPacketCustomPayload) { if (p instanceof S3FPacketCustomPayload) {
S3FPacketCustomPayload packet = (S3FPacketCustomPayload) p; S3FPacketCustomPayload packet = (S3FPacketCustomPayload) p;
if (Restrictions.PLUGIN_CHANNEL.equals(packet.getChannelName())) { if (Restrictions.PLUGIN_CHANNEL.equals(packet.func_149169_c())) {
final String unknown = replayHandler.getRestrictions().handle(packet); final String unknown = replayHandler.getRestrictions().handle(packet);
if (unknown == null) { if (unknown == null) {
return null; return null;
@@ -373,16 +395,11 @@ public class ReplaySender extends ChannelDuplexHandler {
if (p instanceof S3FPacketCustomPayload) { if (p instanceof S3FPacketCustomPayload) {
S3FPacketCustomPayload packet = (S3FPacketCustomPayload) p; S3FPacketCustomPayload packet = (S3FPacketCustomPayload) p;
if ("MC|BOpen".equals(packet.getChannelName())) { if ("MC|BOpen".equals(packet.func_149169_c())) {
return null; return null;
} }
} if ("MC|RPack".equals(packet.func_149169_c())) {
String url = new String(packet.func_149168_d(), Charsets.UTF_8);
convertLegacyEntityIds(p);
if(p instanceof S48PacketResourcePackSend) {
S48PacketResourcePackSend packet = (S48PacketResourcePackSend) p;
String url = packet.func_179783_a();
if (url.startsWith("replay://")) { if (url.startsWith("replay://")) {
int id = Integer.parseInt(url.substring("replay://".length())); int id = Integer.parseInt(url.substring("replay://".length()));
Map<Integer, String> index = replayFile.getResourcePackIndex(); Map<Integer, String> index = replayFile.getResourcePackIndex();
@@ -393,32 +410,36 @@ public class ReplaySender extends ChannelDuplexHandler {
if (!file.exists()) { if (!file.exists()) {
IOUtils.copy(replayFile.getResourcePack(hash).get(), new FileOutputStream(file)); IOUtils.copy(replayFile.getResourcePack(hash).get(), new FileOutputStream(file));
} }
mc.getResourcePackRepository().func_177319_a(file); ResourcePackRepository repo = mc.getResourcePackRepository();
repo.field_148533_g = false;
repo.field_148532_f = new FileResourcePack(file);
Minecraft.getMinecraft().scheduleResourcesRefresh();
} }
} }
return null; return null;
} }
} }
}
if(p instanceof S01PacketJoinGame) { if(p instanceof S01PacketJoinGame) {
S01PacketJoinGame packet = (S01PacketJoinGame) p; S01PacketJoinGame packet = (S01PacketJoinGame) p;
allowMovement = true; allowMovement = true;
int entId = packet.getEntityId(); int entId = packet.func_149197_c();
actualID = entId; actualID = entId;
entId = -1789435; // Camera entity id should be negative which is an invalid id and can't be used by servers entId = -1789435; // Camera entity id should be negative which is an invalid id and can't be used by servers
int dimension = packet.getDimension(); int dimension = packet.func_149194_f();
EnumDifficulty difficulty = packet.getDifficulty(); EnumDifficulty difficulty = packet.func_149192_g();
int maxPlayers = packet.getMaxPlayers(); int maxPlayers = packet.func_149193_h();
WorldType worldType = packet.getWorldType(); WorldType worldType = packet.func_149196_i();
p = new S01PacketJoinGame(entId, GameType.SPECTATOR, false, dimension, p = new S01PacketJoinGame(entId, GameType.ADVENTURE, false, dimension,
difficulty, maxPlayers, worldType, false); difficulty, maxPlayers, worldType);
} }
if(p instanceof S07PacketRespawn) { if(p instanceof S07PacketRespawn) {
S07PacketRespawn respawn = (S07PacketRespawn) p; S07PacketRespawn respawn = (S07PacketRespawn) p;
p = new S07PacketRespawn(respawn.func_149082_c(), p = new S07PacketRespawn(respawn.func_149082_c(),
respawn.func_149081_d(), respawn.func_149080_f(), GameType.SPECTATOR); respawn.func_149081_d(), respawn.func_149080_f(), GameType.ADVENTURE);
allowMovement = true; allowMovement = true;
} }
@@ -436,14 +457,6 @@ public class ReplaySender extends ChannelDuplexHandler {
CameraEntity cent = replayHandler.getCameraEntity(); CameraEntity cent = replayHandler.getCameraEntity();
for (Object relative : ppl.func_179834_f()) {
if (relative == S08PacketPlayerPosLook.EnumFlags.X
|| relative == S08PacketPlayerPosLook.EnumFlags.Y
|| relative == S08PacketPlayerPosLook.EnumFlags.Z) {
return null; // At least one of the coordinates is relative, so we don't care
}
}
if(cent != null) { if(cent != null) {
if(!allowMovement && !((Math.abs(cent.posX - ppl.func_148932_c()) > TP_DISTANCE_LIMIT) || if(!allowMovement && !((Math.abs(cent.posX - ppl.func_148932_c()) > TP_DISTANCE_LIMIT) ||
(Math.abs(cent.posZ - ppl.func_148933_e()) > TP_DISTANCE_LIMIT))) { (Math.abs(cent.posZ - ppl.func_148933_e()) > TP_DISTANCE_LIMIT))) {
@@ -497,7 +510,6 @@ public class ReplaySender extends ChannelDuplexHandler {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void channelActive(ChannelHandlerContext ctx) throws Exception { public void channelActive(ChannelHandlerContext ctx) throws Exception {
this.ctx = ctx; this.ctx = ctx;
ctx.attr(NetworkManager.attrKeyConnectionState).set(EnumConnectionState.PLAY);
super.channelActive(ctx); super.channelActive(ctx);
} }
@@ -821,7 +833,7 @@ public class ReplaySender extends ChannelDuplexHandler {
if (!chunk.isEmpty()) { if (!chunk.isEmpty()) {
List<Entity> entitiesInChunk = new ArrayList<>(); List<Entity> entitiesInChunk = new ArrayList<>();
// Gather all entities in that chunk // Gather all entities in that chunk
for (ClassInheritanceMultiMap entityList : chunk.getEntityLists()) { for (List entityList : chunk.entityLists) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Collection<Entity> typedEntityList = entityList; Collection<Entity> typedEntityList = entityList;
entitiesInChunk.addAll(typedEntityList); entitiesInChunk.addAll(typedEntityList);
@@ -851,68 +863,6 @@ public class ReplaySender extends ChannelDuplexHandler {
return p; // During synchronous playback everything is sent normally 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 static final class PacketData {
private final int timestamp; private final int timestamp;
private final byte[] bytes; private final byte[] bytes;

View File

@@ -7,32 +7,29 @@ import com.replaymod.replay.ReplayModReplay;
import com.replaymod.replay.Setting; import com.replaymod.replay.Setting;
import com.replaymod.replay.events.ReplayChatMessageEvent; import com.replaymod.replay.events.ReplayChatMessageEvent;
import com.replaymod.replaystudio.util.Location; import com.replaymod.replaystudio.util.Location;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.EventPriority;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.TickEvent;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import net.minecraft.block.material.Material; import net.minecraft.block.material.Material;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.AbstractClientPlayer; import net.minecraft.client.entity.EntityClientPlayerMP;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.network.NetHandlerPlayClient; import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.client.settings.KeyBinding; import net.minecraft.client.settings.KeyBinding;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItemFrame;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.stats.StatFileWriter; import net.minecraft.stats.StatFileWriter;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.IChatComponent; import net.minecraft.util.IChatComponent;
import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Session;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.client.event.EntityViewRenderEvent;
import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.client.event.RenderHandEvent; import net.minecraftforge.client.event.RenderHandEvent;
import net.minecraftforge.common.MinecraftForge; 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;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
@@ -43,7 +40,7 @@ import java.util.function.Function;
* During a replay {@link Minecraft#thePlayer} should be an instance of this class. * During a replay {@link Minecraft#thePlayer} should be an instance of this class.
* Camera movement is controlled by a separate {@link CameraController}. * Camera movement is controlled by a separate {@link CameraController}.
*/ */
public class CameraEntity extends EntityPlayerSP { public class CameraEntity extends EntityClientPlayerMP {
/** /**
* Roll of this camera in degrees. * Roll of this camera in degrees.
*/ */
@@ -67,8 +64,9 @@ public class CameraEntity extends EntityPlayerSP {
*/ */
private final EventHandler eventHandler = new EventHandler(); private final EventHandler eventHandler = new EventHandler();
public CameraEntity(Minecraft mcIn, World worldIn, NetHandlerPlayClient netHandlerPlayClient, StatFileWriter statFileWriter) { public CameraEntity(Minecraft mcIn, World worldIn, Session session, NetHandlerPlayClient netHandlerPlayClient, StatFileWriter statFileWriter) {
super(mcIn, worldIn, netHandlerPlayClient, statFileWriter); super(mcIn, worldIn, session, netHandlerPlayClient, statFileWriter);
entityUniqueID = UUID.randomUUID(); // Need to not have the same UUID as the player who recorded the replay
FMLCommonHandler.instance().bus().register(eventHandler); FMLCommonHandler.instance().bus().register(eventHandler);
MinecraftForge.EVENT_BUS.register(eventHandler); MinecraftForge.EVENT_BUS.register(eventHandler);
if (ReplayModReplay.instance.getReplayHandler().getSpectatedUUID() == null) { if (ReplayModReplay.instance.getReplayHandler().getSpectatedUUID() == null) {
@@ -127,31 +125,33 @@ public class CameraEntity extends EntityPlayerSP {
* @param to The entity whose position to copy * @param to The entity whose position to copy
*/ */
public void setCameraPosRot(Entity to) { public void setCameraPosRot(Entity to) {
if (to == this) return;
float yOffset = 1.62f; // Magic value (eye height) from EntityRenderer#orientCamera
prevPosX = to.prevPosX; prevPosX = to.prevPosX;
prevPosY = to.prevPosY; prevPosY = to.prevPosY + yOffset;
prevPosZ = to.prevPosZ; prevPosZ = to.prevPosZ;
prevRotationYaw = to.prevRotationYaw; prevRotationYaw = to.prevRotationYaw;
prevRotationPitch = to.prevRotationPitch; prevRotationPitch = to.prevRotationPitch;
posX = to.posX; posX = to.posX;
posY = to.posY; posY = to.posY + yOffset;
posZ = to.posZ; posZ = to.posZ;
rotationYaw = to.rotationYaw; rotationYaw = to.rotationYaw;
rotationPitch = to.rotationPitch; rotationPitch = to.rotationPitch;
lastTickPosX = to.lastTickPosX; lastTickPosX = to.lastTickPosX;
lastTickPosY = to.lastTickPosY; lastTickPosY = to.lastTickPosY + yOffset;
lastTickPosZ = to.lastTickPosZ; lastTickPosZ = to.lastTickPosZ;
updateBoundingBox(); updateBoundingBox();
} }
private void updateBoundingBox() { private void updateBoundingBox() {
setEntityBoundingBox(new AxisAlignedBB( this.boundingBox.setBounds(
posX - width / 2, posY, posZ - width / 2, posX - width / 2, posY, posZ - width / 2,
posX + width / 2, posY + height, posZ + width / 2)); posX + width / 2, posY + height, posZ + width / 2);
} }
@Override @Override
public void onUpdate() { public void onUpdate() {
Entity view = mc.getRenderViewEntity(); EntityLivingBase view = mc.renderViewEntity;
if (view != null) { if (view != null) {
// Make sure we're always spectating the right entity // Make sure we're always spectating the right entity
// This is important if the spectated player respawns as their // This is important if the spectated player respawns as their
@@ -167,9 +167,9 @@ public class CameraEntity extends EntityPlayerSP {
} }
view = worldObj.getPlayerEntityByUUID(spectating); view = worldObj.getPlayerEntityByUUID(spectating);
if (view != null) { if (view != null) {
mc.setRenderViewEntity(view); mc.renderViewEntity = view;
} else { } else {
mc.setRenderViewEntity(this); mc.renderViewEntity = this;
return; return;
} }
} }
@@ -192,7 +192,7 @@ public class CameraEntity extends EntityPlayerSP {
@Override @Override
public void setAngles(float yaw, float pitch) { public void setAngles(float yaw, float pitch) {
if (mc.getRenderViewEntity() == this) { if (mc.renderViewEntity == this) {
// Only update camera rotation when the camera is the view // Only update camera rotation when the camera is the view
super.setAngles(yaw, pitch); super.setAngles(yaw, pitch);
} }
@@ -209,8 +209,8 @@ public class CameraEntity extends EntityPlayerSP {
} }
@Override @Override
public boolean isInLava() { public boolean handleLavaMovement() {
return falseUnlessSpectating(Entity::isInLava); // Make sure no lava overlay is rendered return falseUnlessSpectating(Entity::handleLavaMovement); // Make sure no lava overlay is rendered
} }
@Override @Override
@@ -224,7 +224,7 @@ public class CameraEntity extends EntityPlayerSP {
} }
private boolean falseUnlessSpectating(Function<Entity, Boolean> property) { private boolean falseUnlessSpectating(Function<Entity, Boolean> property) {
Entity view = mc.getRenderViewEntity(); Entity view = mc.renderViewEntity;
if (view != null && view != this) { if (view != null && view != this) {
return property.apply(view); return property.apply(view);
} }
@@ -236,20 +236,17 @@ public class CameraEntity extends EntityPlayerSP {
return false; // We are in full control of ourselves return false; // We are in full control of ourselves
} }
@Override
protected void createRunningParticles() {
// We do not produce any particles, we are a camera
}
@Override @Override
public boolean canBeCollidedWith() { public boolean canBeCollidedWith() {
return false; // We are a camera, we cannot collide return false; // We are a camera, we cannot collide
} }
/* TODO 1.7.10: isSpectator has been added in 1.8, this is probably going to require lots of manual changes
@Override @Override
public boolean isSpectator() { public boolean isSpectator() {
return ReplayModReplay.instance.getReplayHandler().isCameraView(); // Make sure we're treated as spectator return ReplayModReplay.instance.getReplayHandler().isCameraView(); // Make sure we're treated as spectator
} }
*/
@Override @Override
public boolean shouldRenderInPass(int pass) { public boolean shouldRenderInPass(int pass) {
@@ -261,7 +258,7 @@ public class CameraEntity extends EntityPlayerSP {
@Override @Override
public boolean isInvisible() { public boolean isInvisible() {
Entity view = mc.getRenderViewEntity(); Entity view = mc.renderViewEntity;
if (view != this) { if (view != this) {
return view.isInvisible(); return view.isInvisible();
} }
@@ -270,25 +267,16 @@ public class CameraEntity extends EntityPlayerSP {
@Override @Override
public ResourceLocation getLocationSkin() { public ResourceLocation getLocationSkin() {
Entity view = mc.getRenderViewEntity(); Entity view = mc.renderViewEntity;
if (view != this && view instanceof EntityPlayer) { if (view != this && view instanceof EntityPlayer) {
return Utils.getResourceLocationForPlayerUUID(view.getUniqueID()); return Utils.getResourceLocationForPlayerUUID(view.getUniqueID());
} }
return super.getLocationSkin(); 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 @Override
public float getSwingProgress(float renderPartialTicks) { public float getSwingProgress(float renderPartialTicks) {
Entity view = mc.getRenderViewEntity(); Entity view = mc.renderViewEntity;
if (view != this && view instanceof EntityPlayer) { if (view != this && view instanceof EntityPlayer) {
return ((EntityPlayer) view).getSwingProgress(renderPartialTicks); return ((EntityPlayer) view).getSwingProgress(renderPartialTicks);
} }
@@ -328,17 +316,17 @@ public class CameraEntity extends EntityPlayerSP {
if (mc.gameSettings.keyBindAttack.isPressed() || mc.gameSettings.keyBindUseItem.isPressed()) { if (mc.gameSettings.keyBindAttack.isPressed() || mc.gameSettings.keyBindUseItem.isPressed()) {
if (canSpectate(mc.pointedEntity)) { if (canSpectate(mc.pointedEntity)) {
ReplayModReplay.instance.getReplayHandler().spectateEntity(mc.pointedEntity); ReplayModReplay.instance.getReplayHandler().spectateEntity((EntityLivingBase) mc.pointedEntity);
// Make sure we don't exit right away // Make sure we don't exit right away
mc.gameSettings.keyBindSneak.pressTime = 0; mc.gameSettings.keyBindSneak.pressTime = 0;
} }
} }
Map<String, KeyBinding> keyBindings = ReplayMod.instance.getKeyBindingRegistry().getKeyBindings(); Map<String, KeyBinding> keyBindings = ReplayMod.instance.getKeyBindingRegistry().getKeyBindings();
if (keyBindings.get("replaymod.input.rollclockwise").isKeyDown()) { if (keyBindings.get("replaymod.input.rollclockwise").getIsKeyPressed()) {
roll += Utils.isCtrlDown() ? 0.2 : 1; roll += Utils.isCtrlDown() ? 0.2 : 1;
} }
if (keyBindings.get("replaymod.input.rollcounterclockwise").isKeyDown()) { if (keyBindings.get("replaymod.input.rollcounterclockwise").getIsKeyPressed()) {
roll -= Utils.isCtrlDown() ? 0.2 : 1; roll -= Utils.isCtrlDown() ? 0.2 : 1;
} }
} }
@@ -352,7 +340,7 @@ public class CameraEntity extends EntityPlayerSP {
public boolean canSpectate(Entity e) { public boolean canSpectate(Entity e) {
return e != null && !e.isInvisible() return e != null && !e.isInvisible()
&& (e instanceof EntityPlayer || e instanceof EntityLiving || e instanceof EntityItemFrame); && e instanceof EntityPlayer; // 1.7.10 has no general concept of eye height
} }
@Override @Override
@@ -361,7 +349,10 @@ public class CameraEntity extends EntityPlayerSP {
super.addChatMessage(message); super.addChatMessage(message);
} }
private class EventHandler { // All event handlers need to be public in 1.7.10
public class EventHandler {
private EventHandler() {}
@SubscribeEvent @SubscribeEvent
public void onPreClientTick(TickEvent.ClientTickEvent event) { public void onPreClientTick(TickEvent.ClientTickEvent event) {
if (event.phase == TickEvent.Phase.START) { if (event.phase == TickEvent.Phase.START) {
@@ -399,14 +390,14 @@ public class CameraEntity extends EntityPlayerSP {
@SubscribeEvent @SubscribeEvent
public void onRenderHand(RenderHandEvent event) { public void onRenderHand(RenderHandEvent event) {
// Unless we are spectating another player, don't render our hand // Unless we are spectating another player, don't render our hand
if (mc.getRenderViewEntity() == CameraEntity.this || !(mc.getRenderViewEntity() instanceof EntityPlayer)) { if (mc.renderViewEntity == CameraEntity.this || !(mc.renderViewEntity instanceof EntityPlayer)) {
event.setCanceled(true); event.setCanceled(true);
} }
} }
@SubscribeEvent(priority = EventPriority.LOWEST) @SubscribeEvent(priority = EventPriority.LOWEST)
public void onRenderHandMonitor(RenderHandEvent event) { public void onRenderHandMonitor(RenderHandEvent event) {
Entity view = mc.getRenderViewEntity(); Entity view = mc.renderViewEntity;
if (view instanceof EntityPlayer) { if (view instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) view; EntityPlayer player = (EntityPlayer) view;
// When the spectated player has changed, force equip their items to prevent the equip animation // When the spectated player has changed, force equip their items to prevent the equip animation
@@ -424,12 +415,14 @@ public class CameraEntity extends EntityPlayerSP {
} }
} }
/* TODO 1.7.10: This event has been added in 1.8, has to be replaced with mixin
@SubscribeEvent @SubscribeEvent
public void onEntityViewRenderEvent(EntityViewRenderEvent.CameraSetup event) { public void onEntityViewRenderEvent(EntityViewRenderEvent.CameraSetup event) {
if (mc.getRenderViewEntity() == CameraEntity.this) { if (mc.getRenderViewEntity() == CameraEntity.this) {
event.roll = roll; event.roll = roll;
} }
} }
*/
private boolean heldItemTooltipsWasTrue; private boolean heldItemTooltipsWasTrue;

View File

@@ -34,7 +34,7 @@ public class ClassicCameraController implements CameraController {
boolean forward = false, backward = false, left = false, right = false, up = false, down = false; boolean forward = false, backward = false, left = false, right = false, up = false, down = false;
speedup = false; speedup = false;
for(KeyBinding kb : Minecraft.getMinecraft().gameSettings.keyBindings) { for(KeyBinding kb : Minecraft.getMinecraft().gameSettings.keyBindings) {
if(!kb.isKeyDown()) continue; if(!kb.getIsKeyPressed()) continue;
if(kb.getKeyDescription().equals("key.forward")) { if(kb.getKeyDescription().equals("key.forward")) {
forward = true; forward = true;
speedup = true; speedup = true;
@@ -161,7 +161,7 @@ public class ClassicCameraController implements CameraController {
Vec3 dbf = direction; Vec3 dbf = direction;
if(dirBefore != null) { if(dirBefore != null) {
direction = dirBefore.normalize().add(direction); direction = dirBefore.normalize().addVector(direction.xCoord, direction.yCoord, direction.zCoord);
} }
dirBefore = dbf; dirBefore = dbf;
@@ -174,7 +174,7 @@ public class ClassicCameraController implements CameraController {
float f3 = MathHelper.sin(-yaw * 0.017453292F - (float)Math.PI); float f3 = MathHelper.sin(-yaw * 0.017453292F - (float)Math.PI);
float f4 = -MathHelper.cos(-pitch * 0.017453292F); float f4 = -MathHelper.cos(-pitch * 0.017453292F);
float f5 = MathHelper.sin(-pitch * 0.017453292F); float f5 = MathHelper.sin(-pitch * 0.017453292F);
return new Vec3((double)(f3 * f4), (double)f5, (double)(f2 * f4)); return Vec3.createVectorHelper((double)(f3 * f4), (double)f5, (double)(f2 * f4));
} }
public enum MoveDirection { public enum MoveDirection {

View File

@@ -34,9 +34,9 @@ public class SpectatorCameraController implements CameraController {
// Always make sure the camera is in the exact same spot as the spectated entity // Always make sure the camera is in the exact same spot as the spectated entity
// This is necessary as some rendering code for the hand doesn't respect the view entity // This is necessary as some rendering code for the hand doesn't respect the view entity
// and always uses mc.thePlayer // and always uses mc.thePlayer
Entity view = mc.getRenderViewEntity(); Entity view = mc.renderViewEntity;
if (view != null && view != camera) { if (view != null && view != camera) {
camera.setCameraPosRot(mc.getRenderViewEntity()); camera.setCameraPosRot(mc.renderViewEntity);
// If it's a player, also 'steal' its inventory so the rendering code knows what item to render // If it's a player, also 'steal' its inventory so the rendering code knows what item to render
if (view instanceof EntityPlayer) { if (view instanceof EntityPlayer) {
EntityPlayer viewPlayer = (EntityPlayer) view; EntityPlayer viewPlayer = (EntityPlayer) view;

View File

@@ -39,7 +39,7 @@ public class VanillaCameraController implements CameraController {
if (partialTicksPassed == 0) return; if (partialTicksPassed == 0) return;
Vector3f direction = new Vector3f(0, 0, 0); Vector3f direction = new Vector3f(0, 0, 0);
for (int i = 0; i < 6; i++) { // First, get movement direction depending on keys pressed for (int i = 0; i < 6; i++) { // First, get movement direction depending on keys pressed
if (bindings[i].isKeyDown()) { if (bindings[i].getIsKeyPressed()) {
Vector3f.add(direction, DIRECTIONS[i], direction); Vector3f.add(direction, DIRECTIONS[i], direction);
} }
} }

View File

@@ -1,10 +1,10 @@
package com.replaymod.replay.events; package com.replaymod.replay.events;
import com.replaymod.replay.camera.CameraEntity; import com.replaymod.replay.camera.CameraEntity;
import cpw.mods.fml.common.eventhandler.Cancelable;
import cpw.mods.fml.common.eventhandler.Event;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Event;
@Cancelable @Cancelable
@RequiredArgsConstructor @RequiredArgsConstructor

View File

@@ -1,9 +1,9 @@
package com.replaymod.replay.events; package com.replaymod.replay.events;
import com.replaymod.replay.ReplayHandler; import com.replaymod.replay.ReplayHandler;
import cpw.mods.fml.common.eventhandler.Event;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import net.minecraftforge.fml.common.eventhandler.Event;
@RequiredArgsConstructor @RequiredArgsConstructor
public abstract class ReplayCloseEvent extends Event { public abstract class ReplayCloseEvent extends Event {

View File

@@ -1,9 +1,9 @@
package com.replaymod.replay.events; package com.replaymod.replay.events;
import com.replaymod.replay.ReplayHandler; import com.replaymod.replay.ReplayHandler;
import cpw.mods.fml.common.eventhandler.Event;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import net.minecraftforge.fml.common.eventhandler.Event;
@RequiredArgsConstructor @RequiredArgsConstructor
public abstract class ReplayOpenEvent extends Event { public abstract class ReplayOpenEvent extends Event {

View File

@@ -3,6 +3,9 @@ package com.replaymod.replay.gui.overlay;
import com.replaymod.core.ReplayMod; import com.replaymod.core.ReplayMod;
import com.replaymod.replay.ReplayHandler; import com.replaymod.replay.ReplayHandler;
import com.replaymod.replay.ReplaySender; import com.replaymod.replay.ReplaySender;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.InputEvent;
import de.johni0702.minecraft.gui.GuiRenderer; import de.johni0702.minecraft.gui.GuiRenderer;
import de.johni0702.minecraft.gui.RenderInfo; import de.johni0702.minecraft.gui.RenderInfo;
import de.johni0702.minecraft.gui.container.AbstractGuiOverlay; import de.johni0702.minecraft.gui.container.AbstractGuiOverlay;
@@ -16,9 +19,6 @@ import de.johni0702.minecraft.gui.layout.CustomLayout;
import de.johni0702.minecraft.gui.layout.HorizontalLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
import net.minecraft.client.settings.GameSettings; import net.minecraft.client.settings.GameSettings;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.InputEvent;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
import org.lwjgl.util.ReadableDimension; import org.lwjgl.util.ReadableDimension;
import org.lwjgl.util.ReadablePoint; import org.lwjgl.util.ReadablePoint;

View File

@@ -0,0 +1,17 @@
package com.replaymod.replay.gui.screen;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.network.NetworkManager;
public class GuiOpeningReplay extends GuiScreen {
private final NetworkManager networkManager;
public GuiOpeningReplay(NetworkManager networkManager) {
this.networkManager = networkManager;
}
@Override
public void handleInput() {
networkManager.processReceivedPackets();
}
}

View File

@@ -2,6 +2,8 @@ package com.replaymod.replay.handler;
import com.replaymod.replay.ReplayModReplay; import com.replaymod.replay.ReplayModReplay;
import com.replaymod.replay.gui.screen.GuiReplayViewer; import com.replaymod.replay.gui.screen.GuiReplayViewer;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiIngameMenu; import net.minecraft.client.gui.GuiIngameMenu;
@@ -9,8 +11,6 @@ import net.minecraft.client.gui.GuiMainMenu;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.I18n;
import net.minecraftforge.client.event.GuiScreenEvent; import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;

View File

@@ -1,24 +0,0 @@
package com.replaymod.replay.mixin;
import com.replaymod.replay.camera.CameraEntity;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiSpectator;
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(GuiSpectator.class)
public abstract class MixinGuiSpectator {
@Shadow
private Minecraft field_175268_g;
@Inject(method = "func_175260_a", 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) {
ci.cancel();
}
}
}

View File

@@ -1,9 +1,9 @@
package com.replaymod.replay.mixin; package com.replaymod.replay.mixin;
import com.replaymod.replay.camera.CameraEntity;
import com.replaymod.replay.ReplayModReplay; import com.replaymod.replay.ReplayModReplay;
import com.replaymod.replay.camera.CameraEntity;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.entity.EntityClientPlayerMP;
import net.minecraft.client.multiplayer.PlayerControllerMP; import net.minecraft.client.multiplayer.PlayerControllerMP;
import net.minecraft.client.network.NetHandlerPlayClient; import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.stats.StatFileWriter; import net.minecraft.stats.StatFileWriter;
@@ -12,6 +12,7 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(PlayerControllerMP.class) @Mixin(PlayerControllerMP.class)
@@ -23,18 +24,23 @@ public abstract class MixinPlayerControllerMP {
@Shadow @Shadow
private NetHandlerPlayClient netClientHandler; private NetHandlerPlayClient netClientHandler;
@Inject(method = "func_178892_a", at=@At("HEAD"), cancellable = true) @Inject(method = "createPlayer", at=@At("HEAD"), cancellable = true)
private void replayModReplay_createReplayCamera(World worldIn, StatFileWriter statFileWriter, CallbackInfoReturnable<EntityPlayerSP> ci) { private void replayModReplay_createReplayCamera(World worldIn, StatFileWriter statFileWriter, CallbackInfoReturnable<EntityClientPlayerMP> ci) {
if (ReplayModReplay.instance.getReplayHandler() != null) { if (ReplayModReplay.instance.getReplayHandler() != null) {
ci.setReturnValue(new CameraEntity(mc, worldIn, netClientHandler, statFileWriter)); ci.setReturnValue(new CameraEntity(mc, worldIn, mc.getSession(), netClientHandler, statFileWriter));
ci.cancel(); ci.cancel();
} }
} }
@Inject(method = "isSpectator", at=@At("HEAD"), cancellable = true) // Prevent the disconnect GUI from being opened during the short time when the replay is restarted
private void replayModReplay_isSpectator(CallbackInfoReturnable<Boolean> ci) { // at which the old network manager is closed but still getting ticked (hence the disconnect GUI opening).
if (mc.thePlayer instanceof CameraEntity) { // this check should in theory not be required @Inject(method = "updateController", at = @At("HEAD"), cancellable = true)
ci.setReturnValue(mc.thePlayer.isSpectator()); private void replayModReplay_onlyTickNeverDisconnect(CallbackInfo ci) {
if (ReplayModReplay.instance.getReplayHandler() != null) {
if (netClientHandler.getNetworkManager().isChannelOpen()) {
netClientHandler.getNetworkManager().processReceivedPackets();
}
ci.cancel();
} }
} }
} }

View File

@@ -1,22 +0,0 @@
package com.replaymod.replay.mixin;
import com.replaymod.replay.ReplayModReplay;
import net.minecraft.client.renderer.culling.ICamera;
import net.minecraft.client.renderer.entity.Render;
import net.minecraft.client.renderer.entity.RenderArrow;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(RenderArrow.class)
public abstract class MixinRenderArrow extends Render {
protected MixinRenderArrow(RenderManager renderManager) {
super(renderManager);
}
@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
return ReplayModReplay.instance.getReplayHandler() != null || super.shouldRender(entity, camera, camX, camY, camZ);
}
}

View File

@@ -1,27 +0,0 @@
package com.replaymod.replay.mixin;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.entity.Entity;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.world.World;
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(RenderManager.class)
public class MixinRenderManager {
@Shadow
private float playerViewY;
@Inject(method = "cacheActiveRenderInfo", at = @At("RETURN"))
public void fixHeadRotationForAnimals(World world, FontRenderer font, Entity view, Entity target, GameSettings settings, float partialRenderTick, CallbackInfo ci) {
if (view instanceof EntityAnimal && !((EntityAnimal) view).isPlayerSleeping()) {
EntityAnimal e = (EntityAnimal) view;
this.playerViewY = e.prevRotationYawHead + (e.rotationYawHead - e.prevRotationYawHead) * partialRenderTick;
}
}
}

View File

@@ -3,14 +3,14 @@ package com.replaymod.replay.mixin;
import com.replaymod.replay.ReplayHandler; import com.replaymod.replay.ReplayHandler;
import com.replaymod.replay.ReplayModReplay; import com.replaymod.replay.ReplayModReplay;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.tileentity.TileEntityEndPortalRenderer; import net.minecraft.client.renderer.tileentity.RenderEndPortal;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(TileEntityEndPortalRenderer.class) @Mixin(RenderEndPortal.class)
public class MixinTileEntityEndPortalRenderer { 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() { private long replayModReplay_getEnchantmentTime() {
ReplayHandler replayHandler = ReplayModReplay.instance.getReplayHandler(); ReplayHandler replayHandler = ReplayModReplay.instance.getReplayHandler();
if (replayHandler != null) { if (replayHandler != null) {

View File

@@ -1,70 +0,0 @@
package com.replaymod.replay.mixin;
import com.replaymod.replay.ReplayModReplay;
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.world.World;
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(ViewFrustum.class)
public abstract class MixinViewFrustum {
private IRenderChunkFactory renderChunkFactory;
@Shadow protected RenderGlobal renderGlobal;
@Shadow protected World world;
@Shadow protected int countChunksY;
@Shadow protected int countChunksX;
@Shadow protected int countChunksZ;
@Shadow public RenderChunk[] renderChunks;
@Inject(method = "<init>", at = @At("RETURN"))
private void setRenderChunkFactory(World a1, int a2, RenderGlobal a3, IRenderChunkFactory rcf, CallbackInfo ci) {
this.renderChunkFactory = rcf;
}
/**
* Instead of calling {@link RenderChunk#setPosition(BlockPos)} 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.
* Note: Most of this code is copied from {@link ViewFrustum#updateChunkPositions(double, double)}
*/
@Inject(method = "updateChunkPositions", at = @At("HEAD"), cancellable = true)
public void fixedUpdateChunkPositions(double viewEntityX, double viewEntityZ, CallbackInfo ci) {
if (ReplayModReplay.instance.getReplayHandler() == null) {
return;
}
int i = MathHelper.floor_double(viewEntityX) - 8;
int j = MathHelper.floor_double(viewEntityZ) - 8;
int k = this.countChunksX * 16;
for (int l = 0; l < this.countChunksX; ++l) {
int i1 = this.func_178157_a(i, k, l);
for (int j1 = 0; j1 < this.countChunksZ; ++j1) {
int k1 = this.func_178157_a(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);
}
}
}
}
ci.cancel();
}
@Shadow abstract int func_178157_a(int p_178157_1_, int p_178157_2_, int p_178157_3_);
}

View File

@@ -8,11 +8,11 @@ import com.replaymod.replaystudio.pathing.path.Keyframe;
import com.replaymod.simplepathing.SPTimeline.SPPath; import com.replaymod.simplepathing.SPTimeline.SPPath;
import com.replaymod.simplepathing.gui.GuiPathing; import com.replaymod.simplepathing.gui.GuiPathing;
import com.replaymod.simplepathing.preview.PathPreview; import com.replaymod.simplepathing.preview.PathPreview;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import lombok.Getter; import lombok.Getter;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;

Some files were not shown because too many files have changed in this diff Show More