diff --git a/build.gradle b/build.gradle index 45749588..dfb8e6a0 100755 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ buildscript { } } dependencies { - classpath 'net.minecraftforge.gradle:ForgeGradle:2.2-SNAPSHOT' + classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT' classpath 'org.spongepowered:mixingradle:0.4-SNAPSHOT' } } @@ -34,9 +34,9 @@ archivesBaseName = "replaymod" minecraft { coreMod = 'com.replaymod.core.LoadingPlugin' - version = '1.11.2-13.20.0.2216' + version = '1.12-14.21.1.2387' runDir = "eclipse" - mappings = "snapshot_20161220" + mappings = "snapshot_20170615" replace '@MOD_VERSION@', project.version // 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) @@ -69,7 +69,7 @@ dependencies { shade 'org.aspectj:aspectjrt:1.8.2' - shade 'com.github.replaymod:ReplayStudio:a4a75b3' + shade 'com.github.replaymod:ReplayStudio:21626be' testCompile 'junit:junit:4.11' } diff --git a/jGui b/jGui index bd3fa93d..e5fcc650 160000 --- a/jGui +++ b/jGui @@ -1 +1 @@ -Subproject commit bd3fa93d7d531792c97958795eddd27438d1635a +Subproject commit e5fcc65032e6b3ed53f3013db091c71f9c2e2ca7 diff --git a/src/integration-test/java/com/replaymod/core/AbstractTask.java b/src/integration-test/java/com/replaymod/core/AbstractTask.java index c6abf8f5..7320023b 100644 --- a/src/integration-test/java/com/replaymod/core/AbstractTask.java +++ b/src/integration-test/java/com/replaymod/core/AbstractTask.java @@ -299,7 +299,7 @@ public abstract class AbstractTask implements Task { return; } - clickNow(button.xPosition + 5, button.yPosition + 5); + clickNow(button.x + 5, button.y + 5); } catch (IllegalAccessException | NoSuchFieldException e) { future.setException(e); } diff --git a/src/integration-test/java/com/replaymod/core/ReplayModIntegrationTest.java b/src/integration-test/java/com/replaymod/core/ReplayModIntegrationTest.java index 3fc0d00f..3733e302 100644 --- a/src/integration-test/java/com/replaymod/core/ReplayModIntegrationTest.java +++ b/src/integration-test/java/com/replaymod/core/ReplayModIntegrationTest.java @@ -36,6 +36,11 @@ public class ReplayModIntegrationTest { // Make sure the game window doesn't have to remain in focus during the test mc.gameSettings.pauseOnLostFocus = false; + // Vanilla uses our keys + mc.gameSettings.keyBindAdvancements.setKeyCode(0); + mc.gameSettings.keyBindLoadToolbar.setKeyCode(0); + mc.gameSettings.keyBindSaveToolbar.setKeyCode(0); + runTasks( new SkipLogin(), new DownloadOpenEye(), diff --git a/src/integration-test/java/com/replaymod/extra/DownloadOpenEye.java b/src/integration-test/java/com/replaymod/extra/DownloadOpenEye.java index 753090c0..257a56fd 100644 --- a/src/integration-test/java/com/replaymod/extra/DownloadOpenEye.java +++ b/src/integration-test/java/com/replaymod/extra/DownloadOpenEye.java @@ -10,6 +10,10 @@ import java.nio.file.NoSuchFileException; public class DownloadOpenEye extends AbstractTask { @Override protected void init() { + if ("1".equals(System.getenv("RM_INTEGRATION_TEST_NO_OPENEYE"))) { + runLater(() -> future.set(null)); + return; + } expectGui(OpenEyeExtra.OfferGui.class, offerGui -> { click(offerGui.yesButton); expectGuiClosed(20 * 1000, () -> { diff --git a/src/main/java/com/replaymod/compat/shaders/ShaderBeginRender.java b/src/main/java/com/replaymod/compat/shaders/ShaderBeginRender.java index 8404801b..d74d570c 100644 --- a/src/main/java/com/replaymod/compat/shaders/ShaderBeginRender.java +++ b/src/main/java/com/replaymod/compat/shaders/ShaderBeginRender.java @@ -30,7 +30,7 @@ public class ShaderBeginRender { // check if Shaders are enabled if (!(boolean) (ShaderReflection.config_isShaders.invoke(null))) return; - ShaderReflection.shaders_beginRender.invoke(null, mc, mc.timer.elapsedPartialTicks, 0); + ShaderReflection.shaders_beginRender.invoke(null, mc, mc.timer.renderPartialTicks, 0); } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } diff --git a/src/main/java/com/replaymod/compat/shaders/mixin/MixinShaderRenderChunk.java b/src/main/java/com/replaymod/compat/shaders/mixin/MixinShaderRenderChunk.java index 3b4e9bc2..986e8025 100644 --- a/src/main/java/com/replaymod/compat/shaders/mixin/MixinShaderRenderChunk.java +++ b/src/main/java/com/replaymod/compat/shaders/mixin/MixinShaderRenderChunk.java @@ -20,6 +20,7 @@ public abstract class MixinShaderRenderChunk { */ @Inject(method = "isPlayerUpdate", at = @At("HEAD"), cancellable = true) private void replayModCompat_disableIsPlayerUpdate(CallbackInfoReturnable ci) { + // TODO: Update to 1.12 once optifine is available if (((EntityRendererHandler.IEntityRenderer) mc.entityRenderer).replayModRender_getHandler() == null) return; ci.setReturnValue(true); } diff --git a/src/main/java/com/replaymod/core/KeyBindingRegistry.java b/src/main/java/com/replaymod/core/KeyBindingRegistry.java index 9d792864..52e134d8 100644 --- a/src/main/java/com/replaymod/core/KeyBindingRegistry.java +++ b/src/main/java/com/replaymod/core/KeyBindingRegistry.java @@ -85,7 +85,7 @@ public class KeyBindingRegistry { CrashReport crashReport = CrashReport.makeCrashReport(cause, "Handling Key Binding"); CrashReportCategory category = crashReport.makeCategory("Key Binding"); category.addCrashSection("Key Binding", keyBinding); - category.setDetail("Handler", runnable::toString); + category.addDetail("Handler", runnable::toString); throw new ReportedException(crashReport); } } @@ -100,7 +100,7 @@ public class KeyBindingRegistry { CrashReport crashReport = CrashReport.makeCrashReport(cause, "Handling Raw Key Binding"); CrashReportCategory category = crashReport.makeCategory("Key Binding"); category.addCrashSection("Key Code", keyCode); - category.setDetail("Handler", runnable::toString); + category.addDetail("Handler", runnable::toString); throw new ReportedException(crashReport); } } diff --git a/src/main/java/com/replaymod/core/gui/GuiFactory.java b/src/main/java/com/replaymod/core/gui/GuiFactory.java index ca770c82..d29ebb84 100644 --- a/src/main/java/com/replaymod/core/gui/GuiFactory.java +++ b/src/main/java/com/replaymod/core/gui/GuiFactory.java @@ -15,30 +15,17 @@ public class GuiFactory implements IModGuiFactory { } @Override - public Class mainConfigGuiClass() { - return ConfigGuiWrapper.class; + public boolean hasConfigGui() { + return true; + } + + @Override + public GuiScreen createConfigGui(GuiScreen parentScreen) { + return new GuiReplaySettings(parentScreen, ReplayMod.instance.getSettingsRegistry()).toMinecraft(); } @Override public Set runtimeGuiCategories() { return null; } - - @Override - public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element) { - return null; - } - - public static class ConfigGuiWrapper extends GuiScreen { - private final GuiScreen parent; - - public ConfigGuiWrapper(GuiScreen parent) { - this.parent = parent; - } - - @Override - public void initGui() { - new GuiReplaySettings(parent, ReplayMod.instance.getSettingsRegistry()).display(); - } - } } diff --git a/src/main/java/com/replaymod/core/handler/MainMenuHandler.java b/src/main/java/com/replaymod/core/handler/MainMenuHandler.java index 475f02ea..d3fd3cab 100644 --- a/src/main/java/com/replaymod/core/handler/MainMenuHandler.java +++ b/src/main/java/com/replaymod/core/handler/MainMenuHandler.java @@ -19,12 +19,12 @@ public class MainMenuHandler { if (event.getGui() instanceof GuiMainMenu) { for (GuiButton button : event.getButtonList()) { // Buttons that aren't in a rectangle directly above our space don't need moving - if (button.xPosition + button.width < event.getGui().width / 2 - 100 - || button.xPosition > event.getGui().width / 2 + 100 - || button.yPosition > event.getGui().height / 4 + 10 + 4 * 24) continue; + if (button.x + button.width < event.getGui().width / 2 - 100 + || button.x > event.getGui().width / 2 + 100 + || button.y > event.getGui().height / 4 + 10 + 4 * 24) continue; // Move button up to make space for two rows of buttons // and then move back down by 10 to compensate for the space to the exit button that was already there - button.yPosition -= 2 * 24 - 10; + button.y -= 2 * 24 - 10; } } } diff --git a/src/main/java/com/replaymod/core/utils/ModCompat.java b/src/main/java/com/replaymod/core/utils/ModCompat.java index 876c05fe..e87a26e2 100644 --- a/src/main/java/com/replaymod/core/utils/ModCompat.java +++ b/src/main/java/com/replaymod/core/utils/ModCompat.java @@ -4,22 +4,22 @@ import com.replaymod.replaystudio.data.ModInfo; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.ModContainer; -import net.minecraftforge.fml.common.registry.GameData; +import net.minecraftforge.registries.ForgeRegistry; +import net.minecraftforge.registries.RegistryManager; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; -import java.util.stream.Stream; public class ModCompat { @SuppressWarnings("unchecked") public static Collection getInstalledNetworkMods() { Map ignoreCaseMap = Loader.instance().getModList().stream() .collect(Collectors.toMap(m -> m.getModId().toLowerCase(), Function.identity())); - return Stream.concat( - ((Set) GameData.getBlockRegistry().getKeys()).stream(), - ((Set) GameData.getItemRegistry().getKeys()).stream() - ).map(ResourceLocation::getResourceDomain).filter(s -> !s.equals("minecraft")).distinct() + return RegistryManager.ACTIVE.takeSnapshot(false).keySet().stream() + .map(RegistryManager.ACTIVE::getRegistry) + .map(ForgeRegistry::getKeys).flatMap(Set::stream) + .map(ResourceLocation::getResourceDomain).filter(s -> !s.equals("minecraft")).distinct() .map(String::toLowerCase).map(ignoreCaseMap::get).filter(mod -> mod != null) .map(mod -> new ModInfo(mod.getModId(), mod.getName(), mod.getVersion())) .collect(Collectors.toList()); diff --git a/src/main/java/com/replaymod/core/utils/OpenGLUtils.java b/src/main/java/com/replaymod/core/utils/OpenGLUtils.java index b7260b7a..a6982739 100644 --- a/src/main/java/com/replaymod/core/utils/OpenGLUtils.java +++ b/src/main/java/com/replaymod/core/utils/OpenGLUtils.java @@ -1,8 +1,8 @@ package com.replaymod.core.utils; +import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.VertexBuffer; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL11; @@ -35,7 +35,7 @@ public class OpenGLUtils { float f5 = 1.0F / textureHeight; Tessellator tessellator = Tessellator.getInstance(); - VertexBuffer vertexBuffer = tessellator.getBuffer(); + BufferBuilder vertexBuffer = tessellator.getBuffer(); GlStateManager.translate(x+(width/2), y+(width/2), 0); GlStateManager.rotate(rotation, 0, 0, 1); vertexBuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); diff --git a/src/main/java/com/replaymod/core/utils/WrappedTimer.java b/src/main/java/com/replaymod/core/utils/WrappedTimer.java index 93d2bebf..5b6c16e7 100644 --- a/src/main/java/com/replaymod/core/utils/WrappedTimer.java +++ b/src/main/java/com/replaymod/core/utils/WrappedTimer.java @@ -3,6 +3,8 @@ package com.replaymod.core.utils; import net.minecraft.util.Timer; public class WrappedTimer extends Timer { + public static final float DEFAULT_MS_PER_TICK = 1000 / 20; + protected final Timer wrapped; public WrappedTimer(Timer wrapped) { @@ -19,15 +21,10 @@ public class WrappedTimer extends Timer { } protected void copy(Timer from, Timer to) { - to.ticksPerSecond = from.ticksPerSecond; - to.lastHRTime = from.lastHRTime; to.elapsedTicks = from.elapsedTicks; to.renderPartialTicks = from.renderPartialTicks; - to.timerSpeed = from.timerSpeed; - to.elapsedPartialTicks = from.elapsedPartialTicks; to.lastSyncSysClock = from.lastSyncSysClock; - to.lastSyncHRClock = from.lastSyncHRClock; - to.counter = from.counter; - to.timeSyncAdjustment = from.timeSyncAdjustment; + to.elapsedPartialTicks = from.elapsedPartialTicks; + to.tickLength = from.tickLength; } } diff --git a/src/main/java/com/replaymod/extras/OpenEyeExtra.java b/src/main/java/com/replaymod/extras/OpenEyeExtra.java index ba0575fb..bc13e23d 100644 --- a/src/main/java/com/replaymod/extras/OpenEyeExtra.java +++ b/src/main/java/com/replaymod/extras/OpenEyeExtra.java @@ -26,6 +26,7 @@ import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; import static com.replaymod.core.utils.Utils.SSL_SOCKET_FACTORY; +import static com.replaymod.extras.ReplayModExtras.LOGGER; public class OpenEyeExtra implements Extra { private static final String DOWNLOAD_URL = "https://www.replaymod.com/dl/openeye/" + Loader.MC_VERSION; @@ -39,7 +40,25 @@ public class OpenEyeExtra implements Extra { mod.getSettingsRegistry().register(ASK_FOR_OPEN_EYE); if (!Loader.isModLoaded("OpenEye") && mod.getSettingsRegistry().get(ASK_FOR_OPEN_EYE)) { - mod.runLater(() -> new OfferGui(GuiScreen.wrap(mod.getMinecraft().currentScreen)).display()); + new Thread(() -> { + try { + LOGGER.trace("Checking for OpenEye availability"); + HttpsURLConnection connection = (HttpsURLConnection) new URL(DOWNLOAD_URL).openConnection(); + connection.setSSLSocketFactory(SSL_SOCKET_FACTORY); + connection.setRequestMethod("HEAD"); + connection.connect(); + LOGGER.trace("Got response code: {}", connection.getResponseCode()); + if (connection.getResponseCode() == 200) { + mod.runLater(() -> new OfferGui(GuiScreen.wrap(mod.getMinecraft().currentScreen)).display()); + } else { + LOGGER.info("Cannot offer OpenEye, server returned: {} {}", + connection.getResponseCode(), connection.getResponseMessage()); + } + connection.disconnect(); + } catch (Throwable e) { + LOGGER.error("Failed to check for OpenEye availability:", e); + } + }).start(); } } diff --git a/src/main/java/com/replaymod/online/api/replay/holders/MinecraftVersion.java b/src/main/java/com/replaymod/online/api/replay/holders/MinecraftVersion.java index 065a7439..4499866e 100644 --- a/src/main/java/com/replaymod/online/api/replay/holders/MinecraftVersion.java +++ b/src/main/java/com/replaymod/online/api/replay/holders/MinecraftVersion.java @@ -6,7 +6,8 @@ public enum MinecraftVersion { MC_1_9_4("Minecraft 1.9.4", "1.9.4"), MC_1_10_2("Minecraft 1.10.2", "1.10.2"), MC_1_11("Minecraft 1.11", "1.11"), - MC_1_11_2("Minecraft 1.11.2", "1.11.2"); + MC_1_11_2("Minecraft 1.11.2", "1.11.2"), + MC_1_12("Minecraft 1.12", "1.12"); private String niceName, apiName; diff --git a/src/main/java/com/replaymod/online/gui/GuiRegister.java b/src/main/java/com/replaymod/online/gui/GuiRegister.java index 574a6c05..af39e944 100644 --- a/src/main/java/com/replaymod/online/gui/GuiRegister.java +++ b/src/main/java/com/replaymod/online/gui/GuiRegister.java @@ -55,7 +55,7 @@ public class GuiRegister extends AbstractGuiScreen { pos(cancelButton, width / 2 + 2, 170); pos(statusLabel, width / 2 - statusLabel.getMinSize().getWidth() / 2, 152); - FontRenderer font = getMinecraft().fontRendererObj; + FontRenderer font = getMinecraft().fontRenderer; int lineCount = font.listFormattedStringToWidth(disclaimerLabel.getText(), width - 10).size(); Dimension dim = new Dimension(width - 10, font.FONT_HEIGHT * lineCount); disclaimerLabel.setSize(dim); diff --git a/src/main/java/com/replaymod/online/gui/GuiReplayCenter.java b/src/main/java/com/replaymod/online/gui/GuiReplayCenter.java index 252eaf41..aa646150 100644 --- a/src/main/java/com/replaymod/online/gui/GuiReplayCenter.java +++ b/src/main/java/com/replaymod/online/gui/GuiReplayCenter.java @@ -37,7 +37,7 @@ import de.johni0702.minecraft.gui.layout.VerticalLayout; import de.johni0702.minecraft.gui.popup.GuiYesNoPopup; import de.johni0702.minecraft.gui.utils.Colors; import de.johni0702.minecraft.gui.utils.Consumer; -import org.apache.logging.log4j.core.helpers.Strings; +import org.apache.logging.log4j.util.Strings; import org.lwjgl.util.Dimension; import org.lwjgl.util.ReadableDimension; diff --git a/src/main/java/com/replaymod/pathing/player/AbstractTimelinePlayer.java b/src/main/java/com/replaymod/pathing/player/AbstractTimelinePlayer.java index 367d28ee..e6f28449 100644 --- a/src/main/java/com/replaymod/pathing/player/AbstractTimelinePlayer.java +++ b/src/main/java/com/replaymod/pathing/player/AbstractTimelinePlayer.java @@ -6,6 +6,7 @@ import com.google.common.collect.Ordering; import com.google.common.primitives.Longs; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; +import com.replaymod.core.utils.WrappedTimer; import com.replaymod.replay.ReplayHandler; import com.replaymod.replaystudio.pathing.path.Keyframe; import com.replaymod.replaystudio.pathing.path.Path; @@ -68,8 +69,8 @@ public abstract class AbstractTimelinePlayer { MinecraftForge.EVENT_BUS.register(this); lastTime = 0; mc.timer = new ReplayTimer(mc.timer); - mc.timer.timerSpeed = 1; - mc.timer.elapsedPartialTicks = mc.timer.elapsedTicks = 0; + mc.timer.tickLength = WrappedTimer.DEFAULT_MS_PER_TICK; + mc.timer.renderPartialTicks = mc.timer.elapsedTicks = 0; return future = settableFuture = SettableFuture.create(); } @@ -107,10 +108,9 @@ public abstract class AbstractTimelinePlayer { float timeInTicks = replayTime / 50f; float previousTimeInTicks = lastTime / 50f; float passedTicks = timeInTicks - previousTimeInTicks; - mc.timer.elapsedPartialTicks += passedTicks; - mc.timer.elapsedTicks = (int) mc.timer.elapsedPartialTicks; - mc.timer.elapsedPartialTicks -= mc.timer.elapsedTicks; - mc.timer.renderPartialTicks = mc.timer.elapsedPartialTicks; + mc.timer.renderPartialTicks += passedTicks; + mc.timer.elapsedTicks = (int) mc.timer.renderPartialTicks; + mc.timer.renderPartialTicks -= mc.timer.elapsedTicks; lastTime = replayTime; diff --git a/src/main/java/com/replaymod/recording/gui/GuiRecordingOverlay.java b/src/main/java/com/replaymod/recording/gui/GuiRecordingOverlay.java index 9a5a5e41..79737bdd 100644 --- a/src/main/java/com/replaymod/recording/gui/GuiRecordingOverlay.java +++ b/src/main/java/com/replaymod/recording/gui/GuiRecordingOverlay.java @@ -42,7 +42,7 @@ public class GuiRecordingOverlay { public void renderRecordingIndicator(RenderGameOverlayEvent.Post event) { if (event.getType() != RenderGameOverlayEvent.ElementType.ALL) return; if (settingsRegistry.get(Setting.INDICATOR)) { - FontRenderer fontRenderer = mc.fontRendererObj; + FontRenderer fontRenderer = mc.fontRenderer; fontRenderer.drawString(I18n.format("replaymod.gui.recording").toUpperCase(), 30, 18 - (fontRenderer.FONT_HEIGHT / 2), 0xffffffff); mc.renderEngine.bindTexture(TEXTURE); GlStateManager.resetColor(); diff --git a/src/main/java/com/replaymod/recording/handler/ConnectionEventHandler.java b/src/main/java/com/replaymod/recording/handler/ConnectionEventHandler.java index 62357999..2f4debd7 100755 --- a/src/main/java/com/replaymod/recording/handler/ConnectionEventHandler.java +++ b/src/main/java/com/replaymod/recording/handler/ConnectionEventHandler.java @@ -47,7 +47,7 @@ public class ConnectionEventHandler { try { boolean local = networkManager.isLocalChannel(); if (local) { - if (mc.getIntegratedServer().getEntityWorld().getWorldType() == WorldType.DEBUG_WORLD) { + if (mc.getIntegratedServer().getEntityWorld().getWorldType() == WorldType.DEBUG_ALL_BLOCK_STATES) { logger.info("Debug World recording is not supported."); return; } diff --git a/src/main/java/com/replaymod/recording/handler/RecordingEventHandler.java b/src/main/java/com/replaymod/recording/handler/RecordingEventHandler.java index cc237ac8..c5319c2a 100755 --- a/src/main/java/com/replaymod/recording/handler/RecordingEventHandler.java +++ b/src/main/java/com/replaymod/recording/handler/RecordingEventHandler.java @@ -235,7 +235,7 @@ public class RecordingEventHandler { public void onPickupItem(ItemPickupEvent event) { try { packetListener.save(new SPacketCollectItem(event.pickedUp.getEntityId(), event.player.getEntityId(), - event.pickedUp.getEntityItem().getMaxStackSize())); + event.pickedUp.getItem().getMaxStackSize())); } catch(Exception e) { e.printStackTrace(); } diff --git a/src/main/java/com/replaymod/recording/mixin/MixinNetHandlerLoginClient.java b/src/main/java/com/replaymod/recording/mixin/MixinNetHandlerLoginClient.java index 5cbe64bc..74322b0c 100644 --- a/src/main/java/com/replaymod/recording/mixin/MixinNetHandlerLoginClient.java +++ b/src/main/java/com/replaymod/recording/mixin/MixinNetHandlerLoginClient.java @@ -24,4 +24,9 @@ public abstract class MixinNetHandlerLoginClient { public void replayModRecording_initiateRecording(CallbackInfo cb) { ReplayModRecording.instance.initiateRecording(networkManager); } + + @Inject(method = "handleLoginSuccess", at=@At("RETURN")) + public void replayModRecording_raceConditionWorkAround(CallbackInfo cb) { + networkManager.channel().config().setAutoRead(true); + } } diff --git a/src/main/java/com/replaymod/recording/mixin/MixinNetworkDispatcher.java b/src/main/java/com/replaymod/recording/mixin/MixinNetworkDispatcher.java index c6e2e4d5..f9f5cda5 100644 --- a/src/main/java/com/replaymod/recording/mixin/MixinNetworkDispatcher.java +++ b/src/main/java/com/replaymod/recording/mixin/MixinNetworkDispatcher.java @@ -1,8 +1,11 @@ package com.replaymod.recording.mixin; import com.replaymod.recording.handler.FMLHandshakeFilter; +import io.netty.channel.ChannelConfig; import io.netty.channel.ChannelPipeline; import io.netty.channel.embedded.EmbeddedChannel; +import net.minecraft.network.EnumConnectionState; +import net.minecraft.network.NetworkManager; import net.minecraftforge.fml.common.network.handshake.FMLHandshakeCodec; import net.minecraftforge.fml.common.network.handshake.NetworkDispatcher; import net.minecraftforge.fml.relauncher.Side; @@ -10,6 +13,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(value = NetworkDispatcher.class, remap = false) @@ -43,4 +47,17 @@ public abstract class MixinNetworkDispatcher { "replaymod_filter", new FMLHandshakeFilter()); } } + + @Redirect(method = "clientListenForServerHandshake", at = @At(value = "INVOKE", remap = true, target = + "Lnet/minecraft/network/NetworkManager;setConnectionState(Lnet/minecraft/network/EnumConnectionState;)V")) + public void replayModRecording_raceConditionWorkAround1(NetworkManager self, EnumConnectionState ignored) { } + + @Redirect(method = "insertIntoChannel", at = @At(value = "INVOKE", target = + "Lio/netty/channel/ChannelConfig;setAutoRead(Z)Lio/netty/channel/ChannelConfig;")) + public ChannelConfig replayModRecording_raceConditionWorkAround2(ChannelConfig self, boolean autoRead) { + if (side == Side.CLIENT) { + autoRead = false; + } + return self.setAutoRead(autoRead); + } } diff --git a/src/main/java/com/replaymod/recording/packet/PacketListener.java b/src/main/java/com/replaymod/recording/packet/PacketListener.java index f41c9e8d..f981c14c 100755 --- a/src/main/java/com/replaymod/recording/packet/PacketListener.java +++ b/src/main/java/com/replaymod/recording/packet/PacketListener.java @@ -202,7 +202,7 @@ public class PacketListener extends ChannelInboundHandlerAdapter { } @SuppressWarnings("unchecked") - private byte[] getPacketData(Packet packet) throws IOException { + private byte[] getPacketData(Packet packet) throws Exception { if (packet instanceof SPacketSpawnMob) { SPacketSpawnMob p = (SPacketSpawnMob) packet; if (p.dataManager == null) { diff --git a/src/main/java/com/replaymod/recording/packet/ResourcePackRecorder.java b/src/main/java/com/replaymod/recording/packet/ResourcePackRecorder.java index 9b02105c..7cec0542 100644 --- a/src/main/java/com/replaymod/recording/packet/ResourcePackRecorder.java +++ b/src/main/java/com/replaymod/recording/packet/ResourcePackRecorder.java @@ -88,7 +88,7 @@ public class ResourcePackRecorder { if (levelDir.isFile()) { netManager.sendPacket(new CPacketResourcePackStatus(CPacketResourcePackStatus.Action.ACCEPTED)); - Futures.addCallback(mc.getResourcePackRepository().setResourcePackInstance(levelDir), new FutureCallback() { + Futures.addCallback(mc.getResourcePackRepository().setServerResourcePack(levelDir), new FutureCallback() { @Override public void onSuccess(Object result) { recordResourcePack(levelDir, requestId); @@ -174,7 +174,7 @@ public class ResourcePackRecorder { String fileHash = Hashing.sha1().hashBytes(Files.toByteArray(file)).toString(); if (fileHash.equals(hash)) { recordResourcePack(file, requestId); - return repo.setResourcePackInstance(file); + return repo.setServerResourcePack(file); } logger.warn("File " + file + " had wrong hash (expected " + hash + ", found " + fileHash + "). Deleting it."); @@ -196,7 +196,7 @@ public class ResourcePackRecorder { @Override public void onSuccess(Object value) { recordResourcePack(file, requestId); - repo.setResourcePackInstance(file); + repo.setServerResourcePack(file); } @Override diff --git a/src/main/java/com/replaymod/render/mixin/MixinParticleManager.java b/src/main/java/com/replaymod/render/mixin/MixinParticleManager.java index 867cf624..5f7f846d 100644 --- a/src/main/java/com/replaymod/render/mixin/MixinParticleManager.java +++ b/src/main/java/com/replaymod/render/mixin/MixinParticleManager.java @@ -4,7 +4,7 @@ import com.replaymod.render.hooks.EntityRendererHandler; import net.minecraft.client.Minecraft; import net.minecraft.client.particle.Particle; import net.minecraft.client.particle.ParticleManager; -import net.minecraft.client.renderer.VertexBuffer; +import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.entity.Entity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -12,19 +12,19 @@ import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(ParticleManager.class) public abstract class MixinParticleManager { - @Redirect(method = "renderParticles", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/Particle;renderParticle(Lnet/minecraft/client/renderer/VertexBuffer;Lnet/minecraft/entity/Entity;FFFFFF)V")) - private void renderNormalParticle(Particle particle, VertexBuffer vertexBuffer, Entity view, float partialTicks, + @Redirect(method = "renderParticles", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/Particle;renderParticle(Lnet/minecraft/client/renderer/BufferBuilder;Lnet/minecraft/entity/Entity;FFFFFF)V")) + private void renderNormalParticle(Particle particle, BufferBuilder vertexBuffer, Entity view, float partialTicks, float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) { renderParticle(particle, vertexBuffer, view, partialTicks, rotX, rotXZ, rotZ, rotYZ, rotXY); } - @Redirect(method = "renderLitParticles", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/Particle;renderParticle(Lnet/minecraft/client/renderer/VertexBuffer;Lnet/minecraft/entity/Entity;FFFFFF)V")) - private void renderLitParticle(Particle particle, VertexBuffer vertexBuffer, Entity view, float partialTicks, + @Redirect(method = "renderLitParticles", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/Particle;renderParticle(Lnet/minecraft/client/renderer/BufferBuilder;Lnet/minecraft/entity/Entity;FFFFFF)V")) + private void renderLitParticle(Particle particle, BufferBuilder vertexBuffer, Entity view, float partialTicks, float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) { renderParticle(particle, vertexBuffer, view, partialTicks, rotX, rotXZ, rotZ, rotYZ, rotXY); } - private void renderParticle(Particle particle, VertexBuffer vertexBuffer, Entity view, float partialTicks, + private void renderParticle(Particle particle, BufferBuilder vertexBuffer, Entity view, float partialTicks, float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) { EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) Minecraft.getMinecraft().entityRenderer).replayModRender_getHandler(); if (handler != null && handler.omnidirectional) { diff --git a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java index 0a0d8726..ff8a6270 100644 --- a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java +++ b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java @@ -1,5 +1,6 @@ package com.replaymod.render.rendering; +import com.replaymod.core.utils.WrappedTimer; import com.replaymod.pathing.player.AbstractTimelinePlayer; import com.replaymod.pathing.player.ReplayTimer; import com.replaymod.pathing.properties.TimestampProperty; @@ -113,8 +114,8 @@ public class VideoRenderer implements RenderInfo { if (videoStart > 1000) { int replayTime = videoStart - 1000; - timer.elapsedPartialTicks = timer.renderPartialTicks = 0; - timer.timerSpeed = 1; + timer.renderPartialTicks = 0; + timer.tickLength = WrappedTimer.DEFAULT_MS_PER_TICK; while (replayTime < videoStart) { timer.elapsedTicks = 1; replayTime += 50; diff --git a/src/main/java/com/replaymod/replay/ReplayHandler.java b/src/main/java/com/replaymod/replay/ReplayHandler.java index 9beaf95d..61af53ad 100755 --- a/src/main/java/com/replaymod/replay/ReplayHandler.java +++ b/src/main/java/com/replaymod/replay/ReplayHandler.java @@ -3,6 +3,7 @@ package com.replaymod.replay; import com.google.common.base.Preconditions; import com.mojang.authlib.GameProfile; import com.replaymod.core.utils.Restrictions; +import com.replaymod.core.utils.WrappedTimer; import com.replaymod.replay.camera.CameraEntity; import com.replaymod.replay.camera.SpectatorCameraController; import com.replaymod.replay.events.ReplayCloseEvent; @@ -119,7 +120,7 @@ public class ReplayHandler { mc.loadWorld(null); } - mc.timer.timerSpeed = 1; + mc.timer.tickLength = WrappedTimer.DEFAULT_MS_PER_TICK; overlay.setVisible(false); ReplayModReplay.instance.replayHandler = null; @@ -143,13 +144,14 @@ public class ReplayHandler { networkManager.setNetHandler(netHandlerPlayClient); FMLClientHandler.instance().setPlayClient(netHandlerPlayClient); - channel = new EmbeddedChannel(networkManager); + channel = new EmbeddedChannel(); NetworkDispatcher networkDispatcher = new NetworkDispatcher(networkManager); channel.attr(NetworkDispatcher.FML_DISPATCHER).set(networkDispatcher); channel.pipeline().addFirst("ReplayModReplay_replaySender", replaySender); - channel.pipeline().addAfter("ReplayModReplay_replaySender", "fml:packet_handler", networkDispatcher); + channel.pipeline().addLast("packet_handler", networkManager); channel.pipeline().fireChannelActive(); + networkDispatcher.clientToServerHandshake(); } public ReplayFile getReplayFile() { @@ -301,7 +303,7 @@ public class ReplayHandler { @Override public void drawScreen(int mouseX, int mouseY, float partialTicks) { drawBackground(0); - drawCenteredString(fontRendererObj, I18n.format("replaymod.gui.pleasewait"), + drawCenteredString(fontRenderer, I18n.format("replaymod.gui.pleasewait"), width / 2, height / 2, 0xffffffff); } }; diff --git a/src/main/java/com/replaymod/replay/ReplaySender.java b/src/main/java/com/replaymod/replay/ReplaySender.java index eb2146f2..4ccc4f72 100755 --- a/src/main/java/com/replaymod/replay/ReplaySender.java +++ b/src/main/java/com/replaymod/replay/ReplaySender.java @@ -4,6 +4,7 @@ import com.google.common.base.Preconditions; import com.google.common.io.Files; import com.replaymod.core.ReplayMod; import com.replaymod.core.utils.Restrictions; +import com.replaymod.core.utils.WrappedTimer; import com.replaymod.replay.camera.CameraEntity; import com.replaymod.replaystudio.replay.ReplayFile; import io.netty.buffer.ByteBuf; @@ -54,6 +55,9 @@ public class ReplaySender extends ChannelDuplexHandler { */ private static final List BAD_PACKETS = Arrays.asList( // TODO Update possibly more? + SPacketRecipeBook.class, + SPacketAdvancementInfo.class, + SPacketSelectAdvancementsTab.class, SPacketUpdateHealth.class, SPacketOpenWindow.class, SPacketCloseWindow.class, @@ -409,7 +413,7 @@ public class ReplaySender extends ChannelDuplexHandler { if (!file.exists()) { IOUtils.copy(replayFile.getResourcePack(hash).get(), new FileOutputStream(file)); } - mc.getResourcePackRepository().setResourcePackInstance(file); + mc.getResourcePackRepository().setServerResourcePack(file); } } return null; @@ -513,7 +517,7 @@ public class ReplaySender extends ChannelDuplexHandler { @SuppressWarnings("unchecked") public void channelActive(ChannelHandlerContext ctx) throws Exception { this.ctx = ctx; - ctx.attr(NetworkManager.PROTOCOL_ATTRIBUTE_KEY).set(EnumConnectionState.PLAY); + ctx.channel().attr(NetworkManager.PROTOCOL_ATTRIBUTE_KEY).set(EnumConnectionState.PLAY); super.channelActive(ctx); } @@ -541,7 +545,7 @@ public class ReplaySender extends ChannelDuplexHandler { * @return {@code true} if it is paused, {@code false} otherwise */ public boolean paused() { - return mc.timer.timerSpeed == 0; + return mc.timer.tickLength == Float.POSITIVE_INFINITY; } /** @@ -561,7 +565,7 @@ public class ReplaySender extends ChannelDuplexHandler { */ public void setReplaySpeed(final double d) { if(d != 0) this.replaySpeed = d; - mc.timer.timerSpeed = (float) d; + mc.timer.tickLength = WrappedTimer.DEFAULT_MS_PER_TICK / (float) d; } ///////////////////////////////////////////////////////// diff --git a/src/main/java/com/replaymod/replay/camera/CameraEntity.java b/src/main/java/com/replaymod/replay/camera/CameraEntity.java index c6726c38..48ebf3a8 100755 --- a/src/main/java/com/replaymod/replay/camera/CameraEntity.java +++ b/src/main/java/com/replaymod/replay/camera/CameraEntity.java @@ -20,6 +20,7 @@ import net.minecraft.entity.EntityLiving; import net.minecraft.entity.item.EntityItemFrame; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.stats.RecipeBook; import net.minecraft.stats.StatisticsManager; import net.minecraft.util.EnumHand; import net.minecraft.util.ResourceLocation; @@ -68,8 +69,8 @@ public class CameraEntity extends EntityPlayerSP { */ private final EventHandler eventHandler = new EventHandler(); - public CameraEntity(Minecraft mcIn, World worldIn, NetHandlerPlayClient netHandlerPlayClient, StatisticsManager statisticsManager) { - super(mcIn, worldIn, netHandlerPlayClient, statisticsManager); + public CameraEntity(Minecraft mcIn, World worldIn, NetHandlerPlayClient netHandlerPlayClient, StatisticsManager statisticsManager, RecipeBook recipeBook) { + super(mcIn, worldIn, netHandlerPlayClient, statisticsManager, recipeBook); MinecraftForge.EVENT_BUS.register(eventHandler); if (ReplayModReplay.instance.getReplayHandler().getSpectatedUUID() == null) { cameraController = ReplayModReplay.instance.createCameraController(this); diff --git a/src/main/java/com/replaymod/replay/camera/ClassicCameraController.java b/src/main/java/com/replaymod/replay/camera/ClassicCameraController.java index 57bfa770..1690cef5 100644 --- a/src/main/java/com/replaymod/replay/camera/ClassicCameraController.java +++ b/src/main/java/com/replaymod/replay/camera/ClassicCameraController.java @@ -132,7 +132,7 @@ public class ClassicCameraController implements CameraController { Vec3d movement = direction.normalize(); double factor = motion * (frac / 1000D); - camera.moveCamera(movement.xCoord * factor, movement.yCoord * factor, movement.zCoord * factor); + camera.moveCamera(movement.x * factor, movement.y * factor, movement.z * factor); } private void setMovement(MoveDirection dir) { diff --git a/src/main/java/com/replaymod/replay/gui/screen/GuiReplayViewer.java b/src/main/java/com/replaymod/replay/gui/screen/GuiReplayViewer.java index e9bd1d4e..db28685f 100755 --- a/src/main/java/com/replaymod/replay/gui/screen/GuiReplayViewer.java +++ b/src/main/java/com/replaymod/replay/gui/screen/GuiReplayViewer.java @@ -32,7 +32,7 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOCase; import org.apache.commons.io.filefilter.SuffixFileFilter; import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.core.helpers.Strings; +import org.apache.logging.log4j.util.Strings; import org.lwjgl.Sys; import org.lwjgl.util.Dimension; import org.lwjgl.util.ReadableDimension; diff --git a/src/main/java/com/replaymod/replay/handler/GuiHandler.java b/src/main/java/com/replaymod/replay/handler/GuiHandler.java index 25af1b22..bdc1d4d0 100644 --- a/src/main/java/com/replaymod/replay/handler/GuiHandler.java +++ b/src/main/java/com/replaymod/replay/handler/GuiHandler.java @@ -17,7 +17,7 @@ import java.util.List; public class GuiHandler { private static final int BUTTON_EXIT_SERVER = 1; - private static final int BUTTON_ACHIEVEMENTS = 5; + private static final int BUTTON_ADVANCEMENTS = 5; private static final int BUTTON_STATS = 6; private static final int BUTTON_OPEN_TO_LAN = 7; @@ -55,8 +55,8 @@ public class GuiHandler { b.displayString = I18n.format("replaymod.gui.exit"); b.id = BUTTON_EXIT_REPLAY; break; - // Remove "Achievements", "Stats" and "Open to LAN" buttons - case BUTTON_ACHIEVEMENTS: + // Remove "Advancements", "Stats" and "Open to LAN" buttons + case BUTTON_ADVANCEMENTS: buttonList.remove(achievements = b); break; case BUTTON_STATS: @@ -68,12 +68,12 @@ public class GuiHandler { } } if (achievements != null && stats != null) { - moveAllButtonsDirectlyBelowUpwards(buttonList, achievements.yPosition, - achievements.xPosition, stats.xPosition + stats.width); + moveAllButtonsDirectlyBelowUpwards(buttonList, achievements.y, + achievements.x, stats.x + stats.width); } if (openToLan != null) { - moveAllButtonsDirectlyBelowUpwards(buttonList, openToLan.yPosition, - openToLan.xPosition, openToLan.xPosition + openToLan.width); + moveAllButtonsDirectlyBelowUpwards(buttonList, openToLan.y, + openToLan.x, openToLan.x + openToLan.width); } } } @@ -87,8 +87,8 @@ public class GuiHandler { */ private void moveAllButtonsDirectlyBelowUpwards(List buttons, int belowY, int xStart, int xEnd) { for (GuiButton button : buttons) { - if (button.yPosition >= belowY && button.xPosition <= xEnd && button.xPosition + button.width >= xStart) { - button.yPosition -= 24; + if (button.y >= belowY && button.x <= xEnd && button.x + button.width >= xStart) { + button.y -= 24; } } } diff --git a/src/main/java/com/replaymod/replay/mixin/MixinPlayerControllerMP.java b/src/main/java/com/replaymod/replay/mixin/MixinPlayerControllerMP.java index 9aefe1ac..2cb82659 100644 --- a/src/main/java/com/replaymod/replay/mixin/MixinPlayerControllerMP.java +++ b/src/main/java/com/replaymod/replay/mixin/MixinPlayerControllerMP.java @@ -6,6 +6,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.multiplayer.PlayerControllerMP; import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.stats.RecipeBook; import net.minecraft.stats.StatisticsManager; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; @@ -23,10 +24,10 @@ public abstract class MixinPlayerControllerMP { @Shadow private NetHandlerPlayClient connection; - @Inject(method = "createClientPlayer", at=@At("HEAD"), cancellable = true) - private void replayModReplay_createReplayCamera(World worldIn, StatisticsManager statisticsManager, CallbackInfoReturnable ci) { + @Inject(method = "func_192830_a", at=@At("HEAD"), cancellable = true) + private void replayModReplay_createReplayCamera(World worldIn, StatisticsManager statisticsManager, RecipeBook recipeBook, CallbackInfoReturnable ci) { if (ReplayModReplay.instance.getReplayHandler() != null) { - ci.setReturnValue(new CameraEntity(mc, worldIn, connection, statisticsManager)); + ci.setReturnValue(new CameraEntity(mc, worldIn, connection, statisticsManager, recipeBook)); ci.cancel(); } } diff --git a/src/main/java/com/replaymod/simplepathing/SPTimeline.java b/src/main/java/com/replaymod/simplepathing/SPTimeline.java index a41c6079..f0f05c1f 100644 --- a/src/main/java/com/replaymod/simplepathing/SPTimeline.java +++ b/src/main/java/com/replaymod/simplepathing/SPTimeline.java @@ -658,7 +658,7 @@ public class SPTimeline implements PathingRegistry { } catch (IOException e) { CrashReport crash = CrashReport.makeCrashReport(e, "Serializing interpolator"); CrashReportCategory category = crash.makeCategory("Serializing interpolator"); - category.setDetail("Interpolator", interpolator::toString); + category.addDetail("Interpolator", interpolator::toString); throw new ReportedException(crash); } diff --git a/src/main/java/com/replaymod/simplepathing/preview/PathPreviewRenderer.java b/src/main/java/com/replaymod/simplepathing/preview/PathPreviewRenderer.java index 092c861a..3cfe26f4 100644 --- a/src/main/java/com/replaymod/simplepathing/preview/PathPreviewRenderer.java +++ b/src/main/java/com/replaymod/simplepathing/preview/PathPreviewRenderer.java @@ -15,9 +15,9 @@ import com.replaymod.simplepathing.ReplayModSimplePathing; import com.replaymod.simplepathing.SPTimeline; import com.replaymod.simplepathing.gui.GuiPathing; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.VertexBuffer; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.entity.Entity; import net.minecraft.util.ResourceLocation; @@ -204,7 +204,7 @@ public class PathPreviewRenderer { if (distanceSquared(view, pos2) > renderDistanceSquared) return; Tessellator tessellator = Tessellator.getInstance(); - VertexBuffer vertexBuffer = tessellator.getBuffer(); + BufferBuilder vertexBuffer = tessellator.getBuffer(); vertexBuffer.setTranslation(-view.getLeft(), -view.getMiddle(), -view.getRight()); vertexBuffer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR); @@ -231,7 +231,7 @@ public class PathPreviewRenderer { Triple pos, Keyframe keyframe) { Tessellator tessellator = Tessellator.getInstance(); - VertexBuffer vertexBuffer = tessellator.getBuffer(); + BufferBuilder vertexBuffer = tessellator.getBuffer(); vertexBuffer.setTranslation(0, 0, 0); mc.renderEngine.bindTexture(TEXTURE); @@ -280,7 +280,7 @@ public class PathPreviewRenderer { Triple pos, Triple rot) { Tessellator tessellator = Tessellator.getInstance(); - VertexBuffer vertexBuffer = tessellator.getBuffer(); + BufferBuilder vertexBuffer = tessellator.getBuffer(); vertexBuffer.setTranslation(0, 0, 0); mc.renderEngine.bindTexture(CAMERA_HEAD);