diff --git a/src/main/java/com/replaymod/replay/QuickReplaySender.java b/src/main/java/com/replaymod/replay/QuickReplaySender.java index 161b1794..133beb94 100644 --- a/src/main/java/com/replaymod/replay/QuickReplaySender.java +++ b/src/main/java/com/replaymod/replay/QuickReplaySender.java @@ -124,6 +124,10 @@ public class QuickReplaySender extends ChannelHandlerAdapter implements ReplaySe this.ctx = ctx; } + public ListenableFuture getInitializationPromise() { + return initPromise; + } + public ListenableFuture initialize(Consumer progress) { if (initPromise != null) { return initPromise; @@ -148,9 +152,9 @@ public class QuickReplaySender extends ChannelHandlerAdapter implements ReplaySe return promise; } - public void ensureInitialized(Runnable body) { + private void ensureInitialized(Runnable body) { if (initPromise == null) { - // TODO progress popup + LOGGER.warn("QuickReplaySender used without prior initialization!", new Throwable()); initialize(progress -> {}); } Futures.addCallback(initPromise, new FutureCallback() { diff --git a/src/main/java/com/replaymod/replay/ReplayHandler.java b/src/main/java/com/replaymod/replay/ReplayHandler.java index 33ba056b..81d70521 100755 --- a/src/main/java/com/replaymod/replay/ReplayHandler.java +++ b/src/main/java/com/replaymod/replay/ReplayHandler.java @@ -1,7 +1,11 @@ package com.replaymod.replay; import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; import com.replaymod.core.utils.Restrictions; +import com.replaymod.core.utils.Utils; import com.replaymod.core.utils.WrappedTimer; import com.replaymod.replay.camera.CameraEntity; import com.replaymod.replay.camera.SpectatorCameraController; @@ -11,6 +15,9 @@ import com.replaymod.replay.gui.overlay.GuiReplayOverlay; import com.replaymod.replaystudio.data.Marker; import com.replaymod.replaystudio.replay.ReplayFile; import com.replaymod.replaystudio.util.Location; +import de.johni0702.minecraft.gui.container.GuiContainer; +import de.johni0702.minecraft.gui.element.advanced.GuiProgressBar; +import de.johni0702.minecraft.gui.popup.AbstractGuiPopup; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.embedded.EmbeddedChannel; import net.minecraft.client.Minecraft; @@ -18,6 +25,7 @@ import net.minecraft.client.entity.EntityOtherPlayerMP; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.resources.I18n; +import net.minecraft.crash.CrashReport; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.network.NetworkManager; @@ -47,10 +55,13 @@ import static net.minecraft.client.renderer.GlStateManager.*; //$$ import java.net.SocketAddress; //$$ //$$ import static com.replaymod.core.versions.MCVer.GlStateManager.*; -//$$ import static com.replaymod.replay.ReplayModReplay.LOGGER; //#endif +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + import static com.replaymod.core.versions.MCVer.*; +import static com.replaymod.replay.ReplayModReplay.LOGGER; import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT; import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT; @@ -262,6 +273,57 @@ public class ReplayHandler { return overlay; } + public void ensureQuickModeInitialized(Runnable andThen) { + ListenableFuture future = quickReplaySender.getInitializationPromise(); + if (future == null) { + InitializingQuickModePopup popup = new InitializingQuickModePopup(overlay); + future = quickReplaySender.initialize(progress -> popup.progressBar.setProgress(progress.floatValue())); + Futures.addCallback(future, new FutureCallback() { + @Override + public void onSuccess(@Nullable Void result) { + popup.close(); + } + + @Override + public void onFailure(@Nonnull Throwable t) { + String message = "Failed to initialize quick mode. It will not be available."; + Utils.error(LOGGER, overlay, CrashReport.makeCrashReport(t, message), popup::close); + } + }); + } + Futures.addCallback(future, new FutureCallback() { + @Override + public void onSuccess(@Nullable Void result) { + andThen.run(); + } + + @Override + public void onFailure(@Nonnull Throwable t) { + // Exception already printed in callback added above + } + }); + } + + private class InitializingQuickModePopup extends AbstractGuiPopup { + private final GuiProgressBar progressBar = new GuiProgressBar(popup).setSize(300, 20) + .setI18nLabel("replaymod.gui.loadquickmode"); + + public InitializingQuickModePopup(GuiContainer container) { + super(container); + open(); + } + + @Override + public void close() { + super.close(); + } + + @Override + protected InitializingQuickModePopup getThis() { + return this; + } + } + public void setQuickMode(boolean quickMode) { if (quickMode == this.quickMode) return; if (quickMode && !fullReplaySender.isAsyncMode()) return; // Cannot activate quick mode when already in sync mode diff --git a/src/main/java/com/replaymod/replay/ReplayModReplay.java b/src/main/java/com/replaymod/replay/ReplayModReplay.java index af18a138..5ff5a373 100644 --- a/src/main/java/com/replaymod/replay/ReplayModReplay.java +++ b/src/main/java/com/replaymod/replay/ReplayModReplay.java @@ -144,7 +144,8 @@ public class ReplayModReplay { core.getKeyBindingRegistry().registerKeyBinding("replaymod.input.quickmode", Keyboard.KEY_Q, () -> { if (replayHandler != null) { - replayHandler.setQuickMode(!replayHandler.isQuickMode()); + replayHandler.ensureQuickModeInitialized(() -> + replayHandler.setQuickMode(!replayHandler.isQuickMode())); } });