diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..176a458f --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/build.gradle.kts b/build.gradle.kts index baf02eec..effee147 100755 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -178,20 +178,22 @@ val doRelease by tasks.registering { defaultTasks("shadowJar") preprocess { - "1.16.1"(11601, "yarn") { - "1.15.2"(11502, "yarn") { - "1.14.4"(11404, "yarn", file("versions/mapping-fabric-1.15.2-1.14.4.txt")) { - "1.14.4-forge"(11404, "srg", file("versions/mapping-1.14.4-fabric-forge.txt")) { - "1.12.2"(11202, "srg", file("versions/1.14.4-forge/mapping.txt")) { - "1.12.1"(11201, "srg") { - "1.12"(11200, "srg") { - "1.11.2"(11102, "srg", file("versions/1.12/mapping.txt")) { - "1.11"(11100, "srg", file("versions/1.11.2/mapping.txt")) { - "1.10.2"(11002, "srg", file("versions/1.11/mapping.txt")) { - "1.9.4"(10904, "srg") { - "1.8.9"(10809, "srg", file("versions/1.9.4/mapping.txt")) { - "1.8"(10800, "srg", file("versions/1.8.9/mapping.txt")) { - "1.7.10"(10710, "srg", file("versions/1.8/mapping.txt")) + "1.16.2"(11602, "yarn") { + "1.16.1"(11601, "yarn") { + "1.15.2"(11502, "yarn") { + "1.14.4"(11404, "yarn", file("versions/mapping-fabric-1.15.2-1.14.4.txt")) { + "1.14.4-forge"(11404, "srg", file("versions/mapping-1.14.4-fabric-forge.txt")) { + "1.12.2"(11202, "srg", file("versions/1.14.4-forge/mapping.txt")) { + "1.12.1"(11201, "srg") { + "1.12"(11200, "srg") { + "1.11.2"(11102, "srg", file("versions/1.12/mapping.txt")) { + "1.11"(11100, "srg", file("versions/1.11.2/mapping.txt")) { + "1.10.2"(11002, "srg", file("versions/1.11/mapping.txt")) { + "1.9.4"(10904, "srg") { + "1.8.9"(10809, "srg", file("versions/1.9.4/mapping.txt")) { + "1.8"(10800, "srg", file("versions/1.8.9/mapping.txt")) { + "1.7.10"(10710, "srg", file("versions/1.8/mapping.txt")) + } } } } diff --git a/docs/content.md b/docs/content.md index 8d89465d..fd5e039b 100755 --- a/docs/content.md +++ b/docs/content.md @@ -46,7 +46,7 @@ To access the **Replay Mod Settings** from the Main Menu click the **"Replay Vie While playing, you can click the 'Mods' button in the Pause screen to reach **Replay Mod Settings** if you use Minecraft 1.12.2 and below, or have the mod [Mod Menu](https://www.curseforge.com/minecraft/mc-mods/modmenu) installed. When in a Replay, you can either bind a hotkey to the **Replay Mod Settings** in Minecraft's Control settings -or use the hotkey GUI by clicking on the arrow button in the lower left corner. +or use the hotkey GUI by clicking on the hamburger button in the lower left corner. ## Accounts [accounts] In previous versions of ReplayMod we used accounts to deliver videos to the **Replay Center**. This has since been discontinued and with that, so have the accounts. @@ -439,6 +439,9 @@ If you have a Replay in a dark setting (for example at nighttime, or in a cave) This works as a replacement for the **Night Vision Potion Effect**, without the side effect of a weird sky color. ## Quick Mode [quickmode] (Minecraft 1.9 and up) +![](img/quickmode-icon.jpg) +In **Quick Mode**, this clock symbol is displayed in the lower right corner of the screen. + When you first enable **Quick Mode** in a replay, an internal reference of certain entity and block properties is stored for quick access, allowing for faster navigation in the **Replay Timeline**. As a side effect, certain features like particles and second skin layers will not be rendered in the preview. By default, **Quick Mode** is toggled with `Q`. diff --git a/docs/img/quickmode-icon.jpg b/docs/img/quickmode-icon.jpg new file mode 100644 index 00000000..004a00b7 Binary files /dev/null and b/docs/img/quickmode-icon.jpg differ diff --git a/docs/img/quickmode-icon.png b/docs/img/quickmode-icon.png new file mode 100644 index 00000000..bd5215c0 Binary files /dev/null and b/docs/img/quickmode-icon.png differ diff --git a/jGui b/jGui index 037d54f8..bf00dcf2 160000 --- a/jGui +++ b/jGui @@ -1 +1 @@ -Subproject commit 037d54f83a736123a7b834f2485b0adc08744033 +Subproject commit bf00dcf2ce6cec358f08ff80bc4cfa3c289a988a diff --git a/settings.gradle.kts b/settings.gradle.kts index 1f50c264..4cc0c4dc 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -28,7 +28,8 @@ val jGuiVersions = listOf( "1.14.4-forge", "1.14.4", "1.15.2", - "1.16.1" + "1.16.1", + "1.16.2" ) val replayModVersions = listOf( "1.7.10", @@ -44,7 +45,8 @@ val replayModVersions = listOf( "1.14.4-forge", "1.14.4", "1.15.2", - "1.16.1" + "1.16.1", + "1.16.2" ) include(":jGui") diff --git a/src/main/java/com/replaymod/core/DummyChainLoadEntryPoint.java b/src/main/java/com/replaymod/core/DummyChainLoadEntryPoint.java new file mode 100644 index 00000000..3917859d --- /dev/null +++ b/src/main/java/com/replaymod/core/DummyChainLoadEntryPoint.java @@ -0,0 +1,18 @@ +//#if FABRIC>=1 +package com.replaymod.core; + +import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint; + +// Required for ReplayModMMLauncher. +// +// Chain-loading mixin configurations only works when the first class that is loaded doesn't have any mixins which +// target it. The first class would ordinarily be MC's Main but there are valid use cases for targeting it, see +// e.g. https://github.com/ReplayMod/ReplayMod/issues/327 +// So, instead of relying on the bad assumption that Main doesn't have any mixins, we'll instead register this +// dummy pre-launch entry point which is practically guaranteed to not have any mixins and gets called before Main. +public class DummyChainLoadEntryPoint implements PreLaunchEntrypoint { + @Override + public void onPreLaunch() { + } +} +//#endif diff --git a/src/main/java/com/replaymod/extras/FullBrightness.java b/src/main/java/com/replaymod/extras/FullBrightness.java index 2459af5b..4f1fa7c5 100644 --- a/src/main/java/com/replaymod/extras/FullBrightness.java +++ b/src/main/java/com/replaymod/extras/FullBrightness.java @@ -23,7 +23,7 @@ import com.replaymod.core.events.PostRenderCallback; public class FullBrightness extends EventRegistrations implements Extra { private ReplayModReplay module; - private final IGuiImage indicator = new GuiImage().setTexture(ReplayMod.TEXTURE, 90, 20, 19, 13).setSize(19, 13); + private final IGuiImage indicator = new GuiImage().setTexture(ReplayMod.TEXTURE, 90, 20, 19, 16).setSize(19, 16); private MinecraftClient mc; private boolean active; diff --git a/src/main/java/com/replaymod/extras/HotkeyButtons.java b/src/main/java/com/replaymod/extras/HotkeyButtons.java index cbd204cd..69b0b709 100644 --- a/src/main/java/com/replaymod/extras/HotkeyButtons.java +++ b/src/main/java/com/replaymod/extras/HotkeyButtons.java @@ -52,7 +52,7 @@ public class HotkeyButtons extends EventRegistrations implements Extra { public Gui(ReplayMod mod, GuiReplayOverlay overlay) { toggleButton = new GuiTexturedButton(overlay).setSize(20, 20) - .setTexture(ReplayMod.TEXTURE, ReplayMod.TEXTURE_SIZE).setTexturePosH(0, 0) + .setTexture(ReplayMod.TEXTURE, ReplayMod.TEXTURE_SIZE).setTexturePosH(0, 120) .onClick(new Runnable() { @Override public void run() { diff --git a/src/main/java/com/replaymod/extras/QuickMode.java b/src/main/java/com/replaymod/extras/QuickMode.java new file mode 100644 index 00000000..454d20be --- /dev/null +++ b/src/main/java/com/replaymod/extras/QuickMode.java @@ -0,0 +1,52 @@ +package com.replaymod.extras; + +import com.replaymod.core.ReplayMod; +import com.replaymod.core.versions.MCVer.Keyboard; +import com.replaymod.replay.ReplayHandler; +import com.replaymod.replay.ReplayModReplay; +import com.replaymod.replay.events.ReplayOpenedCallback; +import com.replaymod.replay.gui.overlay.GuiReplayOverlay; +import de.johni0702.minecraft.gui.element.GuiImage; +import de.johni0702.minecraft.gui.layout.HorizontalLayout; +import de.johni0702.minecraft.gui.utils.EventRegistrations; + +public class QuickMode extends EventRegistrations implements Extra { + private ReplayModReplay module; + + private final GuiImage indicator = new GuiImage().setTexture(ReplayMod.TEXTURE, 40, 100, 16, 16).setSize(16, 16); + + @Override + public void register(final ReplayMod mod) { + this.module = ReplayModReplay.instance; + + mod.getKeyBindingRegistry().registerKeyBinding("replaymod.input.quickmode", Keyboard.KEY_Q, () -> { + ReplayHandler replayHandler = module.getReplayHandler(); + if (replayHandler == null) { + return; + } + replayHandler.getReplaySender().setSyncModeAndWait(); + mod.runLater(() -> { + replayHandler.ensureQuickModeInitialized(() -> { + boolean enabled = !replayHandler.isQuickMode(); + updateIndicator(replayHandler.getOverlay(), enabled); + replayHandler.setQuickMode(enabled); + replayHandler.getReplaySender().setAsyncMode(true); + }); + }); + }, true); + + register(); + } + + { + on(ReplayOpenedCallback.EVENT, replayHandler -> updateIndicator(replayHandler.getOverlay(), replayHandler.isQuickMode())); + } + + private void updateIndicator(GuiReplayOverlay overlay, boolean enabled) { + if (enabled) { + overlay.statusIndicatorPanel.addElements(new HorizontalLayout.Data(1), indicator); + } else { + overlay.statusIndicatorPanel.removeElement(indicator); + } + } +} diff --git a/src/main/java/com/replaymod/extras/ReplayModExtras.java b/src/main/java/com/replaymod/extras/ReplayModExtras.java index 5a53c707..d22ed045 100644 --- a/src/main/java/com/replaymod/extras/ReplayModExtras.java +++ b/src/main/java/com/replaymod/extras/ReplayModExtras.java @@ -23,6 +23,7 @@ public class ReplayModExtras implements Module { PlayerOverview.class, YoutubeUpload.class, FullBrightness.class, + QuickMode.class, HotkeyButtons.class, OpenEyeExtra.class ); diff --git a/src/main/java/com/replaymod/recording/mixin/MixinWorldClient.java b/src/main/java/com/replaymod/recording/mixin/MixinWorldClient.java index 4186d2f7..29ae5cba 100644 --- a/src/main/java/com/replaymod/recording/mixin/MixinWorldClient.java +++ b/src/main/java/com/replaymod/recording/mixin/MixinWorldClient.java @@ -48,8 +48,16 @@ public abstract class MixinWorldClient extends World implements RecordingEventHa private MinecraftClient client; //#if MC>=11600 - //$$ protected MixinWorldClient(MutableWorldProperties mutableWorldProperties, RegistryKey registryKey, RegistryKey registryKey2, DimensionType dimensionType, Supplier profiler, boolean bl, boolean bl2, long l) { - //$$ super(mutableWorldProperties, registryKey, registryKey2, dimensionType, profiler, bl, bl2, l); + //$$ protected MixinWorldClient(MutableWorldProperties mutableWorldProperties, RegistryKey registryKey, + //#if MC<11602 + //$$ RegistryKey registryKey2, + //#endif + //$$ DimensionType dimensionType, Supplier profiler, boolean bl, boolean bl2, long l) { + //$$ super(mutableWorldProperties, registryKey, + //#if MC<11602 + //$$ registryKey2, + //#endif + //$$ dimensionType, profiler, bl, bl2, l); //$$ } //#else //#if MC>=11400 @@ -109,7 +117,11 @@ public abstract class MixinWorldClient extends World implements RecordingEventHa // Same goes for level events (also called effects). E.g. door open, block break, etc. //#if MC>=11400 + //#if MC>=11600 + //$$ @Inject(method = "syncWorldEvent", at = @At("HEAD")) + //#else @Inject(method = "playLevelEvent", at = @At("HEAD")) + //#endif private void playLevelEvent (PlayerEntity player, int type, BlockPos pos, int data, CallbackInfo ci) { //#else //$$ // These are handled in the World class, so we override the method in WorldClient and add our special handling. diff --git a/src/main/java/com/replaymod/replay/FullReplaySender.java b/src/main/java/com/replaymod/replay/FullReplaySender.java index 45034056..fb2c13ec 100644 --- a/src/main/java/com/replaymod/replay/FullReplaySender.java +++ b/src/main/java/com/replaymod/replay/FullReplaySender.java @@ -625,7 +625,11 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend false, //#if MC>=11600 //$$ packet.method_29443(), + //#if MC>=11602 + //$$ (net.minecraft.util.registry.DynamicRegistryManager.Impl) packet.getRegistryManager(), + //#else //$$ (net.minecraft.util.registry.RegistryTracker.Modifiable) packet.getDimension(), + //#endif //$$ packet.method_29444(), //$$ packet.getDimensionId(), //#else diff --git a/src/main/java/com/replaymod/replay/QuickReplaySender.java b/src/main/java/com/replaymod/replay/QuickReplaySender.java index 5fa12715..90ab72f5 100644 --- a/src/main/java/com/replaymod/replay/QuickReplaySender.java +++ b/src/main/java/com/replaymod/replay/QuickReplaySender.java @@ -39,6 +39,11 @@ import java.io.IOException; import java.util.Collections; import java.util.function.Consumer; +//#if MC>=11602 +//$$ import net.minecraft.util.registry.DynamicRegistryManager; +//$$ import net.minecraft.util.registry.Registry; +//#endif + //#if MC>=11600 //$$ import net.minecraft.world.World; //#else @@ -195,7 +200,11 @@ public class QuickReplaySender extends ChannelHandlerAdapter implements ReplaySe replay.reset(); ctx.fireChannelRead(new PlayerRespawnS2CPacket( //#if MC>=11600 + //#if MC>=11602 + //$$ DimensionType.addRegistryDefaults(new DynamicRegistryManager.Impl()).get(Registry.DIMENSION_TYPE_KEY).get(DimensionType.OVERWORLD_REGISTRY_KEY), + //#else //$$ DimensionType.OVERWORLD_REGISTRY_KEY, + //#endif //$$ World.OVERWORLD, //$$ 0, //$$ GameMode.SPECTATOR, diff --git a/src/main/java/com/replaymod/replay/ReplayModReplay.java b/src/main/java/com/replaymod/replay/ReplayModReplay.java index cd484740..6bc20a29 100644 --- a/src/main/java/com/replaymod/replay/ReplayModReplay.java +++ b/src/main/java/com/replaymod/replay/ReplayModReplay.java @@ -125,17 +125,6 @@ public class ReplayModReplay implements Module { } }, true); - registry.registerKeyBinding("replaymod.input.quickmode", Keyboard.KEY_Q, () -> { - if (replayHandler != null) { - replayHandler.getReplaySender().setSyncModeAndWait(); - core.runLater(() -> - replayHandler.ensureQuickModeInitialized(() -> { - replayHandler.setQuickMode(!replayHandler.isQuickMode()); - replayHandler.getReplaySender().setAsyncMode(true); - })); - } - }, true); - core.getKeyBindingRegistry().registerKeyBinding("replaymod.input.rollclockwise", Keyboard.KEY_L, () -> { // Noop, actual handling logic in CameraEntity#update }, true); diff --git a/src/main/java/com/replaymod/replay/gui/overlay/GuiReplayOverlay.java b/src/main/java/com/replaymod/replay/gui/overlay/GuiReplayOverlay.java index c9b924f5..0ef7cec4 100644 --- a/src/main/java/com/replaymod/replay/gui/overlay/GuiReplayOverlay.java +++ b/src/main/java/com/replaymod/replay/gui/overlay/GuiReplayOverlay.java @@ -57,7 +57,7 @@ public class GuiReplayOverlay extends AbstractGuiOverlay { * This is not used by the replay module itself but may be used by other modules/extras to show * when they're active. */ - public final GuiPanel statusIndicatorPanel = new GuiPanel(this).setSize(100, 20) + public final GuiPanel statusIndicatorPanel = new GuiPanel(this).setSize(100, 16) .setLayout(new HorizontalLayout(HorizontalLayout.Alignment.RIGHT).setSpacing(5)); private final EventHandler eventHandler = new EventHandler(); @@ -78,7 +78,7 @@ public class GuiReplayOverlay extends AbstractGuiOverlay { pos(topPanel, 10, 10); size(topPanel, width - 20, 20); - pos(statusIndicatorPanel, width / 2, height - 25); + pos(statusIndicatorPanel, width / 2, height - 21); width(statusIndicatorPanel, width / 2 - 5); } }); diff --git a/src/main/java/com/replaymod/replay/mixin/MixinPlayerControllerMP.java b/src/main/java/com/replaymod/replay/mixin/MixinPlayerControllerMP.java index c1a358de..8a01ea1d 100644 --- a/src/main/java/com/replaymod/replay/mixin/MixinPlayerControllerMP.java +++ b/src/main/java/com/replaymod/replay/mixin/MixinPlayerControllerMP.java @@ -51,7 +51,11 @@ public abstract class MixinPlayerControllerMP { //#endif //#if MC>=11400 + //#if MC>=11602 + //$$ @Inject(method = "createPlayer(Lnet/minecraft/client/world/ClientWorld;Lnet/minecraft/stat/StatHandler;Lnet/minecraft/client/recipebook/ClientRecipeBook;ZZ)Lnet/minecraft/client/network/ClientPlayerEntity;", at=@At("HEAD"), cancellable = true) + //#else @Inject(method = "createPlayer", at=@At("HEAD"), cancellable = true) + //#endif private void replayModReplay_createReplayCamera( //#if MC>=11400 ClientWorld worldIn, diff --git a/src/main/resources/assets/replaymod/replay_gui.png b/src/main/resources/assets/replaymod/replay_gui.png index 8a10a721..0e47861d 100644 Binary files a/src/main/resources/assets/replaymod/replay_gui.png and b/src/main/resources/assets/replaymod/replay_gui.png differ diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 3f30a5c9..6bc530eb 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -25,6 +25,9 @@ "modmenu": [ "com.replaymod.core.gui.ModMenuApiImpl" ], + "preLaunch": [ + "com.replaymod.core.DummyChainLoadEntryPoint" + ], "mm:early_risers": [ "com.replaymod.core.ReplayModMMLauncher" ] diff --git a/version.txt b/version.txt index 8e8299dc..35cee72d 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -2.4.2 +2.4.3 diff --git a/versions/1.16.2/.gitkeep b/versions/1.16.2/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/versions/common.gradle b/versions/common.gradle index 2fa6b247..02aada14 100644 --- a/versions/common.gradle +++ b/versions/common.gradle @@ -226,21 +226,25 @@ dependencies { 11404: '1.14.4', 11502: '1.15.2', 11601: '1.16.1', + 11602: '1.16.2', ][mcVersion] mappings 'net.fabricmc:yarn:' + [ 11404: '1.14.4+build.16', 11502: '1.15.2+build.14', 11601: '1.16.1+build.17:v2', + 11602: '1.16.2+build.1:v2', ][mcVersion] modCompile 'net.fabricmc:fabric-loader:' + [ 11404: '0.7.8+build.189', 11502: '0.7.8+build.189', 11601: '0.8.8+build.202', + 11602: '0.9.1+build.205', ][mcVersion] def fabricApiVersion = [ 11404: '0.4.3+build.247-1.14', 11502: '0.5.1+build.294-1.15', 11601: '0.14.0+build.371-1.16', + 11602: '0.17.1+build.394-1.16', ][mcVersion] def fabricApiModules = [ "api-base", @@ -292,7 +296,7 @@ dependencies { shadow 'com.github.ReplayMod.JavaBlend:2.79.0:a0696f8' - shadow "com.github.ReplayMod:ReplayStudio:20b5183", shadeExclusions + shadow "com.github.ReplayMod:ReplayStudio:bc8baba", shadeExclusions implementation(jGui){ transitive = false // FG 1.2 puts all MC deps into the compile configuration and we don't want to shade those @@ -301,7 +305,10 @@ dependencies { shadow 'com.github.ReplayMod:lwjgl-utils:27dcd66' if (FABRIC) { - if (mcVersion >= 11600) { + if (mcVersion >= 11602) { + // TODO re-add to runtime once available + modCompileOnly 'io.github.prospector:modmenu:1.14.0+build.24' + } else if (mcVersion >= 11600) { modCompile 'io.github.prospector:modmenu:1.14.0+build.24' } else { modCompile 'io.github.prospector.modmenu:ModMenu:1.6.2-92'