diff --git a/build.gradle.kts b/build.gradle.kts index 261015d5..5dd08053 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -91,6 +91,7 @@ dependencies { 12104 -> "0.111.0+1.21.4" 12105 -> "0.119.9+1.21.5" 12107 -> "0.128.1+1.21.7" + 12110 -> "0.135.0+1.21.10" else -> throw UnsupportedOperationException() } val fabricApiModules = mutableListOf( @@ -169,6 +170,7 @@ dependencies { if (platform.isFabric) { val modMenuVersion = when { + mcVersion >= 12110 -> "16.0.0-rc.1" mcVersion >= 12107 -> "15.0.0-beta.3" mcVersion >= 12105 -> "14.0.0-rc.2" mcVersion >= 12104 -> "13.0.0-beta.1" diff --git a/gradle.properties b/gradle.properties index 5307edab..ac4cbd2a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ essential.defaults.loom=0 -essential.defaults.loom.fabric-loader=net.fabricmc:fabric-loader:0.16.14 +essential.defaults.loom.fabric-loader=net.fabricmc:fabric-loader:0.17.3 # Sets default memory used for gradle commands. Can be overridden by user or command line properties. # This is required to provide enough memory for the Minecraft decompilation process. diff --git a/jGui b/jGui index 31106f5d..84a8c543 160000 --- a/jGui +++ b/jGui @@ -1 +1 @@ -Subproject commit 31106f5dae476e766306c20fc85d5fc7c1ea26eb +Subproject commit 84a8c5438db578f5f7445bfe852770cc004af29a diff --git a/libs/ReplayStudio b/libs/ReplayStudio index 3fdc6c42..03d5609f 160000 --- a/libs/ReplayStudio +++ b/libs/ReplayStudio @@ -1 +1 @@ -Subproject commit 3fdc6c42e36041ae666bcba174a638569dc2791d +Subproject commit 03d5609f7729d735acb875e0e40371026f7fef0c diff --git a/root.gradle.kts b/root.gradle.kts index f11f809c..cdf2af2e 100755 --- a/root.gradle.kts +++ b/root.gradle.kts @@ -3,7 +3,7 @@ import java.io.ByteArrayOutputStream plugins { id("gg.essential.multi-version.root") - id("gg.essential.loom") version "1.7.28" apply false + id("gg.essential.loom") version "1.7.35" apply false id("com.github.hierynomus.license") version "0.15.0" } @@ -204,6 +204,7 @@ defaultTasks("bundleJar") preprocess { strictExtraMappings.set(true) + val mc12110 = createNode("1.21.10", 12110, "yarn") val mc12107 = createNode("1.21.7", 12107, "yarn") val mc12105 = createNode("1.21.5", 12105, "yarn") val mc12104 = createNode("1.21.4", 12104, "yarn") @@ -237,6 +238,7 @@ preprocess { val mc10800 = createNode("1.8", 10800, "srg") val mc10710 = createNode("1.7.10", 10710, "srg") + mc12110.link(mc12107, file("versions/mapping-fabric-1.21.10-1.21.7.txt")) mc12107.link(mc12105) mc12105.link(mc12104, file("versions/mapping-fabric-1.21.5-1.21.4.txt")) mc12104.link(mc12102) diff --git a/settings.gradle.kts b/settings.gradle.kts index 0c43f946..6a8fe27c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -44,6 +44,7 @@ val jGuiVersions = listOf( "1.21.4", "1.21.5", "1.21.7", + "1.21.10", ) val replayModVersions = listOf( // "1.7.10", @@ -78,6 +79,7 @@ val replayModVersions = listOf( "1.21.4", "1.21.5", "1.21.7", + "1.21.10", ) rootProject.buildFileName = "root.gradle.kts" diff --git a/src/main/java/com/replaymod/core/KeyBindingRegistry.java b/src/main/java/com/replaymod/core/KeyBindingRegistry.java index 0b671c79..2211d667 100644 --- a/src/main/java/com/replaymod/core/KeyBindingRegistry.java +++ b/src/main/java/com/replaymod/core/KeyBindingRegistry.java @@ -4,6 +4,7 @@ import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import com.replaymod.core.events.PreRenderCallback; import com.replaymod.core.mixin.KeyBindingAccessor; +import de.johni0702.minecraft.gui.function.KeyInput; import de.johni0702.minecraft.gui.utils.EventRegistrations; import com.replaymod.core.events.KeyBindingEventCallback; import com.replaymod.core.events.KeyEventCallback; @@ -36,17 +37,21 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Consumer; -import java.util.function.Supplier; +import java.util.function.Function; public class KeyBindingRegistry extends EventRegistrations { + //#if MC>=12109 + //$$ private static final KeyBinding.Category CATEGORY = KeyBinding.Category.create(identifier(MOD_ID, "general")); + //#else private static final String CATEGORY = "replaymod.title"; //#if FABRIC>=1 && MC<11600 //$$ static { net.fabricmc.fabric.api.client.keybinding.KeyBindingRegistry.INSTANCE.addCategory(CATEGORY); } //#endif + //#endif private final Map bindings = new HashMap<>(); private Set onlyInReplay = new HashSet<>(); - private Multimap> rawHandlers = ArrayListMultimap.create(); + private Multimap> rawHandlers = ArrayListMultimap.create(); public Binding registerKeyBinding(String name, int keyCode, Runnable whenPressed, boolean onlyInRepay) { Binding binding = registerKeyBinding(name, keyCode, onlyInRepay); @@ -92,7 +97,7 @@ public class KeyBindingRegistry extends EventRegistrations { return binding; } - public void registerRaw(int keyCode, Supplier whenPressed) { + public void registerRaw(int keyCode, Function whenPressed) { rawHandlers.put(keyCode, whenPressed); } @@ -138,18 +143,18 @@ public class KeyBindingRegistry extends EventRegistrations { } } - { on(KeyEventCallback.EVENT, (keyCode, scanCode, action, modifiers) -> handleRaw(keyCode, action)); } - private boolean handleRaw(int keyCode, int action) { + { on(KeyEventCallback.EVENT, this::handleRaw); } + private boolean handleRaw(KeyInput keyInput, int action) { if (action != KeyEventCallback.ACTION_PRESS) return false; - for (final Supplier handler : rawHandlers.get(keyCode)) { + for (final Function handler : rawHandlers.get(keyInput.key)) { try { - if (handler.get()) { + if (handler.apply(keyInput)) { return true; } } catch (Throwable cause) { CrashReport crashReport = CrashReport.create(cause, "Handling Raw Key Binding"); CrashReportSection category = crashReport.addElement("Key Binding"); - category.add("Key Code", () -> "" + keyCode); + category.add("Key Code", () -> "" + keyInput.key); category.add("Handler", handler::toString); throw new CrashException(crashReport); } diff --git a/src/main/java/com/replaymod/core/ReplayMod.java b/src/main/java/com/replaymod/core/ReplayMod.java index ed1535dc..ad8a8e53 100644 --- a/src/main/java/com/replaymod/core/ReplayMod.java +++ b/src/main/java/com/replaymod/core/ReplayMod.java @@ -258,6 +258,10 @@ public class ReplayMod implements Module, Scheduler { } private void printToChat(boolean warning, String message, Object... args) { + if (!mc.isOnThread()) { + runLater(() -> printToChat(warning, message, args)); + return; + } if (getSettingsRegistry().get(Setting.NOTIFICATIONS)) { // Some nostalgia: "§8[§6Replay Mod§8]§r Your message goes here" //#if MC>=10904 diff --git a/src/main/java/com/replaymod/core/events/KeyEventCallback.java b/src/main/java/com/replaymod/core/events/KeyEventCallback.java index 894f822a..3a243386 100644 --- a/src/main/java/com/replaymod/core/events/KeyEventCallback.java +++ b/src/main/java/com/replaymod/core/events/KeyEventCallback.java @@ -1,12 +1,13 @@ package com.replaymod.core.events; +import de.johni0702.minecraft.gui.function.KeyInput; import de.johni0702.minecraft.gui.utils.Event; public interface KeyEventCallback { Event EVENT = Event.create((listeners) -> - (key, scanCode, action, modifiers) -> { + (keyInput, action) -> { for (KeyEventCallback listener : listeners) { - if (listener.onKeyEvent(key, scanCode, action, modifiers)) { + if (listener.onKeyEvent(keyInput, action)) { return true; } } @@ -22,5 +23,5 @@ public interface KeyEventCallback { //$$ int ACTION_PRESS = 1; //#endif - boolean onKeyEvent(int key, int scanCode, int action, int modifiers); + boolean onKeyEvent(KeyInput keyInput, int action); } diff --git a/src/main/java/com/replaymod/core/mixin/MinecraftAccessor.java b/src/main/java/com/replaymod/core/mixin/MinecraftAccessor.java index 14a720bd..2dec6328 100644 --- a/src/main/java/com/replaymod/core/mixin/MinecraftAccessor.java +++ b/src/main/java/com/replaymod/core/mixin/MinecraftAccessor.java @@ -8,8 +8,6 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.gen.Accessor; -import java.util.Queue; - //#if MC>=11800 //$$ import java.util.function.Supplier; //#endif @@ -25,6 +23,7 @@ import java.util.concurrent.CompletableFuture; //#if MC<11400 //$$ import net.minecraft.client.resources.IResourcePack; //$$ import java.util.List; +//$$ import java.util.Queue; //#endif @Mixin(MinecraftClient.class) @@ -53,8 +52,6 @@ public interface MinecraftAccessor { //#endif //#if MC>=11400 - @Accessor - Queue getRenderTaskQueue(); //#else //$$ @Accessor //$$ Queue> getScheduledTasks(); diff --git a/src/main/java/com/replaymod/core/mixin/MixinKeyboardListener.java b/src/main/java/com/replaymod/core/mixin/MixinKeyboardListener.java index 3c218b89..1092592f 100644 --- a/src/main/java/com/replaymod/core/mixin/MixinKeyboardListener.java +++ b/src/main/java/com/replaymod/core/mixin/MixinKeyboardListener.java @@ -2,6 +2,7 @@ package com.replaymod.core.mixin; import com.replaymod.core.events.KeyBindingEventCallback; import com.replaymod.core.events.KeyEventCallback; +import de.johni0702.minecraft.gui.function.KeyInput; import net.minecraft.client.Keyboard; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -13,14 +14,20 @@ public class MixinKeyboardListener { private static final String ON_KEY_PRESSED = "Lnet/minecraft/client/options/KeyBinding;onKeyPressed(Lnet/minecraft/client/util/InputUtil$Key;)V"; @Inject(method = "onKey", at = @At(value = "INVOKE", target = ON_KEY_PRESSED), cancellable = true) + //#if MC>=12109 + //$$ private void beforeKeyBindingTick(long window, int action, net.minecraft.client.input.KeyInput mcKeyInput, CallbackInfo ci) { + //$$ KeyInput keyInput = new KeyInput(mcKeyInput); + //#else private void beforeKeyBindingTick(long windowPointer, int key, int scanCode, int action, int modifiers, CallbackInfo ci) { - if (KeyEventCallback.EVENT.invoker().onKeyEvent(key, scanCode, action, modifiers)) { + KeyInput keyInput = new KeyInput(key, scanCode, modifiers); + //#endif + if (KeyEventCallback.EVENT.invoker().onKeyEvent(keyInput, action)) { ci.cancel(); } } @Inject(method = "onKey", at = @At(value = "INVOKE", target = ON_KEY_PRESSED, shift = At.Shift.AFTER)) - private void afterKeyBindingTick(long windowPointer, int key, int scanCode, int action, int modifiers, CallbackInfo ci) { + private void afterKeyBindingTick(CallbackInfo ci) { KeyBindingEventCallback.EVENT.invoker().onKeybindingEvent(); } } diff --git a/src/main/java/com/replaymod/core/mixin/MixinMinecraft.java b/src/main/java/com/replaymod/core/mixin/MixinMinecraft.java index f9f93277..2ed8c67e 100644 --- a/src/main/java/com/replaymod/core/mixin/MixinMinecraft.java +++ b/src/main/java/com/replaymod/core/mixin/MixinMinecraft.java @@ -8,6 +8,11 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +//#if MC>=12109 +//$$ import net.minecraft.network.PacketApplyBatcher; +//$$ import org.spongepowered.asm.mixin.Final; +//#endif + //#if MC>=11400 import com.replaymod.core.events.PostRenderCallback; import com.replaymod.core.events.PreRenderCallback; @@ -42,8 +47,14 @@ public abstract class MixinMinecraft } //#if MC>=11400 + //#if MC>=12109 + //$$ @Shadow @Final private PacketApplyBatcher packetApplyBatcher; + //#endif @Override public void replayModExecuteTaskQueue() { + //#if MC>=12109 + //$$ this.packetApplyBatcher.apply(); + //#endif runTasks(); } //#endif diff --git a/src/main/java/com/replaymod/core/utils/Utils.java b/src/main/java/com/replaymod/core/utils/Utils.java index 061598fe..21b55739 100644 --- a/src/main/java/com/replaymod/core/utils/Utils.java +++ b/src/main/java/com/replaymod/core/utils/Utils.java @@ -68,6 +68,11 @@ import java.util.function.Consumer; import static com.replaymod.core.versions.MCVer.getMinecraft; +//#if MC>=12109 +//$$ import com.replaymod.core.versions.MCVer.Keyboard; +//$$ import net.minecraft.client.input.SystemKeycodes; +//#endif + //#if MC>=12100 //$$ import net.minecraft.util.crash.ReportType; //#endif @@ -229,7 +234,9 @@ public class Utils { } public static boolean isCtrlDown() { - //#if MC>=11400 + //#if MC>=12109 + //$$ return Keyboard.isKeyDown(SystemKeycodes.LEFT_CTRL) || Keyboard.isKeyDown(SystemKeycodes.RIGHT_CTRL); + //#elseif MC>=11400 return Screen.hasControlDown(); //#else //$$ return Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL); diff --git a/src/main/java/com/replaymod/core/versions/LangResourcePack.java b/src/main/java/com/replaymod/core/versions/LangResourcePack.java index 03c0c74d..2bb31a29 100644 --- a/src/main/java/com/replaymod/core/versions/LangResourcePack.java +++ b/src/main/java/com/replaymod/core/versions/LangResourcePack.java @@ -190,6 +190,11 @@ public class LangResourcePack extends AbstractFileResourcePack { key = String.format(FABRIC_KEY_FORMAT, key.substring(LEGACY_KEY_PREFIX.length())); } //#endif + //#if MC>=12109 + if (key.equals("replaymod.title")) { + properties.put("key.category.replaymod.general", value); + } + //#endif properties.put(key, value); } diff --git a/src/main/java/com/replaymod/core/versions/MCVer.java b/src/main/java/com/replaymod/core/versions/MCVer.java index 53ba8446..5945b188 100644 --- a/src/main/java/com/replaymod/core/versions/MCVer.java +++ b/src/main/java/com/replaymod/core/versions/MCVer.java @@ -621,12 +621,10 @@ public class MCVer { //$$ public static final int KEY_Z = org.lwjgl.input.Keyboard.KEY_Z; //#endif - public static boolean hasControlDown() { - return Screen.hasControlDown(); - } - public static boolean isKeyDown(int keyCode) { - //#if MC>=11500 + //#if MC>=12109 + //$$ return InputUtil.isKeyPressed(getMinecraft().getWindow(), keyCode); + //#elseif MC>=11500 return InputUtil.isKeyPressed(getMinecraft().getWindow().getHandle(), keyCode); //#else //#if MC>=11400 diff --git a/src/main/java/com/replaymod/core/versions/Patterns.java b/src/main/java/com/replaymod/core/versions/Patterns.java index fb998515..ba8b193e 100644 --- a/src/main/java/com/replaymod/core/versions/Patterns.java +++ b/src/main/java/com/replaymod/core/versions/Patterns.java @@ -982,7 +982,9 @@ class Patterns { @Pattern public Identifier getSkinTexture(AbstractClientPlayerEntity player) { - //#if MC>=12002 + //#if MC>=12109 + //$$ return player.getSkin().body().texturePath(); + //#elseif MC>=12002 //$$ return player.getSkinTextures().texture(); //#else return player.getSkinTexture(); diff --git a/src/main/java/com/replaymod/core/versions/scheduler/SchedulerImpl.java b/src/main/java/com/replaymod/core/versions/scheduler/SchedulerImpl.java index 0d204264..3329f24e 100644 --- a/src/main/java/com/replaymod/core/versions/scheduler/SchedulerImpl.java +++ b/src/main/java/com/replaymod/core/versions/scheduler/SchedulerImpl.java @@ -5,6 +5,8 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.util.crash.CrashException; import net.minecraft.util.thread.ReentrantThreadExecutor; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -82,10 +84,13 @@ public class SchedulerImpl implements Scheduler { } } public final ReplayModExecutor executor = new ReplayModExecutor("Client/ReplayMod"); + private final List delayedTasks = new ArrayList<>(); @Override public void runTasks() { executor.runTasks(); + delayedTasks.forEach(executor::send); + delayedTasks.clear(); } @Override @@ -100,15 +105,8 @@ public class SchedulerImpl implements Scheduler { } private void runLater(Runnable runnable, Runnable defer) { - if (mc.isOnThread() && inRunLater && !inRenderTaskQueue) { - ((MinecraftAccessor) mc).getRenderTaskQueue().offer(() -> { - inRenderTaskQueue = true; - try { - defer.run(); - } finally { - inRenderTaskQueue = false; - } - }); + if (mc.isOnThread() && inRunLater) { + delayedTasks.add(defer); } else { executor.send(() -> { inRunLater = true; diff --git a/src/main/java/com/replaymod/extras/HotkeyButtons.java b/src/main/java/com/replaymod/extras/HotkeyButtons.java index 41829207..8fe7ef6a 100644 --- a/src/main/java/com/replaymod/extras/HotkeyButtons.java +++ b/src/main/java/com/replaymod/extras/HotkeyButtons.java @@ -85,8 +85,8 @@ public class HotkeyButtons extends EventRegistrations implements Extra { super.draw(renderer, size, renderInfo); } - }.onClick(() -> { - if (keyBinding.supportsAutoActivation() && Screen.hasControlDown()) { + }.onClick(click -> { + if (keyBinding.supportsAutoActivation() && click.hasCtrl()) { keyBinding.setAutoActivating(!keyBinding.isAutoActivating()); } else { keyBinding.trigger(); diff --git a/src/main/java/com/replaymod/extras/advancedscreenshots/GuiCreateScreenshot.java b/src/main/java/com/replaymod/extras/advancedscreenshots/GuiCreateScreenshot.java index c102d433..496334f1 100644 --- a/src/main/java/com/replaymod/extras/advancedscreenshots/GuiCreateScreenshot.java +++ b/src/main/java/com/replaymod/extras/advancedscreenshots/GuiCreateScreenshot.java @@ -49,13 +49,13 @@ public class GuiCreateScreenshot extends GuiRenderSettings implements Loadable { exportArguments.setText(""); // To disable any preset-based checks buttonPanel.removeElement(queueButton); - renderButton.setI18nLabel("replaymod.gui.advancedscreenshots.create").onClick(() -> { + renderButton.setI18nLabel("replaymod.gui.advancedscreenshots.create").onClick(click -> { // Closing this GUI ensures that settings are saved close(); mod.runLater(() -> { try { - RenderSettings settings = save(false); + RenderSettings settings = save(false, click.hasCtrl()); boolean success = new ScreenshotRenderer(settings).renderScreenshot(); if (success) { diff --git a/src/main/java/com/replaymod/extras/playeroverview/PlayerOverviewGui.java b/src/main/java/com/replaymod/extras/playeroverview/PlayerOverviewGui.java index 78ed336e..751609fe 100644 --- a/src/main/java/com/replaymod/extras/playeroverview/PlayerOverviewGui.java +++ b/src/main/java/com/replaymod/extras/playeroverview/PlayerOverviewGui.java @@ -13,6 +13,7 @@ import de.johni0702.minecraft.gui.element.GuiImage; import de.johni0702.minecraft.gui.element.GuiLabel; import de.johni0702.minecraft.gui.element.GuiTooltip; import de.johni0702.minecraft.gui.element.IGuiCheckbox; +import de.johni0702.minecraft.gui.function.Click; import de.johni0702.minecraft.gui.function.Closeable; import de.johni0702.minecraft.gui.layout.CustomLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout; @@ -52,13 +53,13 @@ public class PlayerOverviewGui extends GuiScreen implements Closeable { .setI18nLabel("replaymod.gui.playeroverview.remembersettings"); public final GuiCheckbox checkAll = new GuiCheckbox(contentPanel){ @Override - public void onClick() { + public void onClick(Click click) { playersScrollable.invokeAll(IGuiCheckbox.class, e -> e.setChecked(true)); } }.setLabel("").setChecked(true).setTooltip(new GuiTooltip().setI18nText("replaymod.gui.playeroverview.showall")); public final GuiCheckbox uncheckAll = new GuiCheckbox(contentPanel){ @Override - public void onClick() { + public void onClick(Click click) { playersScrollable.invokeAll(IGuiCheckbox.class, e -> e.setChecked(false)); } }.setLabel("").setChecked(false).setTooltip(new GuiTooltip().setI18nText("replaymod.gui.playeroverview.hideall")); diff --git a/src/main/java/com/replaymod/pathing/gui/GuiKeyframeRepository.java b/src/main/java/com/replaymod/pathing/gui/GuiKeyframeRepository.java index 6ac40e61..c6f5dbcc 100644 --- a/src/main/java/com/replaymod/pathing/gui/GuiKeyframeRepository.java +++ b/src/main/java/com/replaymod/pathing/gui/GuiKeyframeRepository.java @@ -1,7 +1,5 @@ package com.replaymod.pathing.gui; -import com.google.common.util.concurrent.FutureCallback; -import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.SettableFuture; import com.replaymod.core.ReplayMod; import com.replaymod.core.utils.Utils; @@ -26,8 +24,10 @@ import de.johni0702.minecraft.gui.element.GuiButton; import de.johni0702.minecraft.gui.element.GuiElement; import de.johni0702.minecraft.gui.element.GuiLabel; import de.johni0702.minecraft.gui.element.GuiTextField; +import de.johni0702.minecraft.gui.function.Click; import de.johni0702.minecraft.gui.function.Closeable; -import de.johni0702.minecraft.gui.function.Typeable; +import de.johni0702.minecraft.gui.function.KeyHandler; +import de.johni0702.minecraft.gui.function.KeyInput; import de.johni0702.minecraft.gui.layout.CustomLayout; import de.johni0702.minecraft.gui.layout.GridLayout; import de.johni0702.minecraft.gui.layout.VerticalLayout; @@ -36,7 +36,6 @@ import de.johni0702.minecraft.gui.utils.Colors; import de.johni0702.minecraft.gui.utils.Consumer; import de.johni0702.minecraft.gui.utils.lwjgl.Dimension; import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension; -import de.johni0702.minecraft.gui.utils.lwjgl.ReadablePoint; import net.minecraft.util.crash.CrashReport; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -56,7 +55,7 @@ import static de.johni0702.minecraft.gui.versions.MCVer.setClipboardString; /** * Gui for loading and saving {@link Timeline Timelines}. */ -public class GuiKeyframeRepository extends GuiScreen implements Closeable, Typeable { +public class GuiKeyframeRepository extends GuiScreen implements Closeable, KeyHandler { private static final Logger LOGGER = LogManager.getLogger(); public final GuiPanel contentPanel = new GuiPanel(this).setBackgroundColor(Colors.DARK_TRANSPARENT); @@ -90,7 +89,7 @@ public class GuiKeyframeRepository extends GuiScreen implements Closeable, Typea @Override public void run() { if (popup.getYesButton().isEnabled()) { - popup.getYesButton().onClick(); + popup.getYesButton().onClick(new Click(-1, -1, 0, 0)); } } }).onTextChanged(new Consumer() { @@ -138,7 +137,7 @@ public class GuiKeyframeRepository extends GuiScreen implements Closeable, Typea @Override public void run() { if (popup.getYesButton().isEnabled()) { - popup.getYesButton().onClick(); + popup.getYesButton().onClick(new Click(-1, -1, 0, 0)); } } }).onTextChanged(new Consumer() { @@ -244,9 +243,9 @@ public class GuiKeyframeRepository extends GuiScreen implements Closeable, Typea GuiRenderSettings settingsGui = queue.addJob(timeline); settingsGui.buttonPanel.removeElement(settingsGui.renderButton); settingsGui.setOutputFileBaseName(name); - Runnable orgOnClick = settingsGui.queueButton.getOnClick(); - settingsGui.queueButton.onClick(() -> { - orgOnClick.run(); + Consumer orgOnClick = settingsGui.queueButton.getOnClick(); + settingsGui.queueButton.onClick(click -> { + orgOnClick.consume(click); this.run(); }); settingsGui.open(); @@ -348,9 +347,9 @@ public class GuiKeyframeRepository extends GuiScreen implements Closeable, Typea } @Override - public boolean typeKey(ReadablePoint mousePosition, int keyCode, char keyChar, boolean ctrlDown, boolean shiftDown) { - if (MCVer.Keyboard.hasControlDown()) { - switch (keyCode) { + public boolean handleKey(KeyInput keyInput) { + if (keyInput.hasCtrl()) { + switch (keyInput.key) { case MCVer.Keyboard.KEY_A: if (selectedEntries.size() < timelines.size()) { for (GuiElement child : list.getListPanel().getChildren()) { @@ -364,10 +363,10 @@ public class GuiKeyframeRepository extends GuiScreen implements Closeable, Typea updateButtons(); return true; case MCVer.Keyboard.KEY_C: - copyButton.onClick(); + copyButton.onClick(new Click(-1, -1, 0, 0)); return true; case MCVer.Keyboard.KEY_V: - pasteButton.onClick(); + pasteButton.onClick(new Click(-1, -1, 0, 0)); return true; } } @@ -396,8 +395,8 @@ public class GuiKeyframeRepository extends GuiScreen implements Closeable, Typea } @Override - protected void onClick() { - if (!MCVer.Keyboard.hasControlDown()) { + protected void onClick(Click click) { + if (!click.hasCtrl()) { selectedEntries.clear(); } if (selectedEntries.contains(this)) { diff --git a/src/main/java/com/replaymod/recording/packet/PacketListener.java b/src/main/java/com/replaymod/recording/packet/PacketListener.java index 59a0d26a..99adeb71 100644 --- a/src/main/java/com/replaymod/recording/packet/PacketListener.java +++ b/src/main/java/com/replaymod/recording/packet/PacketListener.java @@ -191,7 +191,21 @@ public class PacketListener extends ChannelInboundHandlerAdapter { // Otherwise, injected packets may end up further down the packet stream than they were supposed to and other // inbound packets which may rely on the injected packet would behave incorrectly when played back. if (!mc.isOnThread()) { + // Note that we must use the same queue as regular packets, otherwise stuff will be out of order! + //#if MC>=12109 + //$$ mc.getPacketApplyBatcher().add(channel.pipeline().get(ClientConnection.class).getPacketListener(), new net.minecraft.network.packet.Packet<>() { + //$$ @Override + //$$ public net.minecraft.network.packet.PacketType> getPacketType() { + //$$ return null; + //$$ } + //$$ @Override + //$$ public void apply(net.minecraft.network.listener.PacketListener listener) { + //$$ save(packet); + //$$ } + //$$ }); + //#else mc.send(() -> save(packet)); + //#endif return; } try { diff --git a/src/main/java/com/replaymod/render/gui/GuiRenderQueue.java b/src/main/java/com/replaymod/render/gui/GuiRenderQueue.java index 86ca19dc..6f7a8d70 100644 --- a/src/main/java/com/replaymod/render/gui/GuiRenderQueue.java +++ b/src/main/java/com/replaymod/render/gui/GuiRenderQueue.java @@ -26,7 +26,9 @@ import de.johni0702.minecraft.gui.element.GuiButton; import de.johni0702.minecraft.gui.element.GuiElement; import de.johni0702.minecraft.gui.element.GuiLabel; import de.johni0702.minecraft.gui.element.GuiTooltip; -import de.johni0702.minecraft.gui.function.Typeable; +import de.johni0702.minecraft.gui.function.Click; +import de.johni0702.minecraft.gui.function.KeyHandler; +import de.johni0702.minecraft.gui.function.KeyInput; import de.johni0702.minecraft.gui.layout.CustomLayout; import de.johni0702.minecraft.gui.layout.GridLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout; @@ -35,7 +37,6 @@ import de.johni0702.minecraft.gui.popup.GuiInfoPopup; import de.johni0702.minecraft.gui.utils.Colors; import de.johni0702.minecraft.gui.utils.lwjgl.Dimension; import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension; -import de.johni0702.minecraft.gui.utils.lwjgl.ReadablePoint; import net.minecraft.client.MinecraftClient; import net.minecraft.util.crash.CrashReport; import org.apache.commons.io.IOUtils; @@ -59,7 +60,7 @@ import net.minecraft.text.TranslatableText; //$$ import com.replaymod.replaystudio.util.I18n; //#endif -public class GuiRenderQueue extends AbstractGuiPopup implements Typeable { +public class GuiRenderQueue extends AbstractGuiPopup implements KeyHandler { private final GuiLabel title = new GuiLabel().setI18nText("replaymod.gui.renderqueue.title").setColor(Colors.BLACK); private final GuiVerticalList list = new GuiVerticalList().setDrawShadow(true).setDrawSlider(true); private final GuiButton addButton = new GuiButton().setI18nLabel("replaymod.gui.renderqueue.add").setSize(150, 20); @@ -272,8 +273,8 @@ public class GuiRenderQueue extends AbstractGuiPopup implements if (!jobs.isEmpty()) { buttonPanel.removeElement(renderButton); } - queueButton.onClick(() -> { - RenderSettings settings = save(false); + queueButton.onClick(click -> { + RenderSettings settings = save(false, click.hasCtrl()); RenderJob newJob = new RenderJob(); newJob.setSettings(settings); @@ -342,8 +343,8 @@ public class GuiRenderQueue extends AbstractGuiPopup implements } @Override - public boolean typeKey(ReadablePoint mousePosition, int keyCode, char keyChar, boolean ctrlDown, boolean shiftDown) { - if (MCVer.Keyboard.hasControlDown() && keyCode == MCVer.Keyboard.KEY_A) { + public boolean handleKey(KeyInput keyInput) { + if (keyInput.hasCtrl() && keyInput.key == MCVer.Keyboard.KEY_A) { if (selectedEntries.size() < list.getListPanel().getChildren().size()) { for (GuiElement child : list.getListPanel().getChildren()) { if (child instanceof Entry) { @@ -381,8 +382,8 @@ public class GuiRenderQueue extends AbstractGuiPopup implements } @Override - protected void onClick() { - if (!MCVer.Keyboard.hasControlDown()) { + protected void onClick(Click click) { + if (!click.hasCtrl()) { selectedEntries.clear(); } if (selectedEntries.contains(this)) { @@ -410,8 +411,8 @@ public class GuiRenderQueue extends AbstractGuiPopup implements public GuiRenderSettings edit() { GuiRenderSettings gui = new GuiRenderSettings(container, replayHandler, job.getTimeline()); gui.buttonPanel.removeElement(gui.renderButton); - gui.queueButton.setI18nLabel("replaymod.gui.done").onClick(() -> { - job.setSettings(gui.save(false)); + gui.queueButton.setI18nLabel("replaymod.gui.done").onClick(click -> { + job.setSettings(gui.save(false, click.hasCtrl())); label.setText(job.getName()); mod.saveRenderQueue(); gui.close(); diff --git a/src/main/java/com/replaymod/render/gui/GuiRenderSettings.java b/src/main/java/com/replaymod/render/gui/GuiRenderSettings.java index 170aa21a..18f4375f 100644 --- a/src/main/java/com/replaymod/render/gui/GuiRenderSettings.java +++ b/src/main/java/com/replaymod/render/gui/GuiRenderSettings.java @@ -18,6 +18,7 @@ import de.johni0702.minecraft.gui.container.GuiVerticalList; import de.johni0702.minecraft.gui.element.*; import de.johni0702.minecraft.gui.element.advanced.GuiColorPicker; import de.johni0702.minecraft.gui.element.advanced.GuiDropdownMenu; +import de.johni0702.minecraft.gui.function.Click; import de.johni0702.minecraft.gui.layout.CustomLayout; import de.johni0702.minecraft.gui.layout.GridLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout; @@ -232,13 +233,13 @@ public class GuiRenderSettings extends AbstractGuiPopup { public final GuiButton queueButton = new GuiButton(buttonPanel) .setSize(100, 20) .setI18nLabel("replaymod.gui.rendersettings.addtoqueue"); - public final GuiButton renderButton = new GuiButton(buttonPanel).onClick(() -> ReplayMod.instance.runLaterWithoutLock(new Runnable() { + public final GuiButton renderButton = new GuiButton(buttonPanel).onClick(click -> ReplayMod.instance.runLaterWithoutLock(new Runnable() { @Override public void run() { // Closing this GUI ensures that settings are saved close(); try { - VideoRenderer videoRenderer = new VideoRenderer(save(false), replayHandler, timeline); + VideoRenderer videoRenderer = new VideoRenderer(save(false, click.hasCtrl()), replayHandler, timeline); videoRenderer.renderVideo(); } catch (FFmpegWriter.NoFFmpegException e) { LOGGER.error("Rendering video:", e); @@ -248,7 +249,7 @@ public class GuiRenderSettings extends AbstractGuiPopup { // Update settings with fixed ffmpeg arguments exportArguments.setText(newSettings.getExportArguments()); // Restart rendering, this will also save the changed ffmpeg arguments - renderButton.onClick(); + renderButton.onClick(click); }); } catch (Throwable t) { error(LOGGER, GuiRenderSettings.this, CrashReport.create(t, "Rendering video"), () -> {}); @@ -349,7 +350,7 @@ public class GuiRenderSettings extends AbstractGuiPopup { videoHeight.setTextColor(Colors.RED); } - String[] compatError = VideoRenderer.checkCompat(save(false)); + String[] compatError = VideoRenderer.checkCompat(save(false, false)); if (resolutionError != null) { renderButton.setDisabled().setTooltip(new GuiTooltip().setI18nText(resolutionError)); } else if (compatError != null) { @@ -552,7 +553,7 @@ public class GuiRenderSettings extends AbstractGuiPopup { updateInputs(); } - public RenderSettings save(boolean serialize) { + public RenderSettings save(boolean serialize, boolean highPerformance) { int sphericalFov = MIN_SPHERICAL_FOV + sphericalFovSlider.getValue() * SPHERICAL_FOV_STEP_SIZE; return new RenderSettings( @@ -576,7 +577,7 @@ public class GuiRenderSettings extends AbstractGuiPopup { serialize || antiAliasingDropdown.isEnabled() ? antiAliasingDropdown.getSelectedValue() : RenderSettings.AntiAliasing.NONE, exportCommand.getText(), exportArguments.getText(), - net.minecraft.client.gui.screen.Screen.hasControlDown() + highPerformance ); } @@ -623,7 +624,7 @@ public class GuiRenderSettings extends AbstractGuiPopup { @Override public void close() { - RenderSettings settings = save(true); + RenderSettings settings = save(true, false); String json = new Gson().toJson(settings); try { Files.write(getSettingsPath(), json.getBytes(StandardCharsets.UTF_8)); diff --git a/src/main/java/com/replaymod/render/gui/GuiVideoRenderer.java b/src/main/java/com/replaymod/render/gui/GuiVideoRenderer.java index a9f7d23d..452e0779 100644 --- a/src/main/java/com/replaymod/render/gui/GuiVideoRenderer.java +++ b/src/main/java/com/replaymod/render/gui/GuiVideoRenderer.java @@ -11,6 +11,7 @@ import de.johni0702.minecraft.gui.element.GuiButton; import de.johni0702.minecraft.gui.element.GuiCheckbox; import de.johni0702.minecraft.gui.element.GuiLabel; import de.johni0702.minecraft.gui.element.advanced.GuiProgressBar; +import de.johni0702.minecraft.gui.function.Click; import de.johni0702.minecraft.gui.function.Tickable; import de.johni0702.minecraft.gui.layout.CustomLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout; @@ -67,8 +68,8 @@ public class GuiVideoRenderer extends GuiScreen implements Tickable { boolean waitingForConfirmation; @Override - public boolean mouseClick(ReadablePoint position, int button) { - boolean result = super.mouseClick(position, button); + public boolean mouseClick(Click click) { + boolean result = super.mouseClick(click); if (waitingForConfirmation && !result) { setI18nLabel("replaymod.gui.rendering.cancel"); waitingForConfirmation = false; @@ -77,8 +78,8 @@ public class GuiVideoRenderer extends GuiScreen implements Tickable { } @Override - public void onClick() { - super.onClick(); + public void onClick(Click click) { + super.onClick(click); if (!waitingForConfirmation) { setI18nLabel("replaymod.gui.rendering.cancel.callback"); waitingForConfirmation = true; diff --git a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java index d3c5d21f..c872d550 100644 --- a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java +++ b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java @@ -40,6 +40,10 @@ import net.minecraft.util.crash.CrashException; import net.minecraft.sound.SoundCategory; import org.lwjgl.glfw.GLFW; +//#if MC>=12109 +//$$ import net.minecraft.client.gui.screen.Overlay; +//#endif + //#if MC>=12106 //$$ import com.replaymod.render.mixin.GameRendererAccessor; //$$ import net.minecraft.client.gui.render.GuiRenderer; @@ -335,13 +339,18 @@ public class VideoRenderer implements RenderInfo { //$$ Display.setResizable(false); //$$ } //#endif + //#if MC>=12109 + //$$ if (mc.debugHudEntryList.isF3Enabled()) { + //$$ mc.debugHudEntryList.setF3Enabled(false); + //#else if (mc.options.debugEnabled) { - debugInfoWasShown = true; //#if MC>=12002 //$$ mc.getDebugHud().toggleDebugHud(); //#else mc.options.debugEnabled = false; //#endif + //#endif + debugInfoWasShown = true; } //#if MC>=11400 if (mc.mouse.isCursorLocked()) { @@ -406,7 +415,9 @@ public class VideoRenderer implements RenderInfo { //$$ } //#endif if (debugInfoWasShown) { - //#if MC>=12002 + //#if MC>=12109 + //$$ mc.debugHudEntryList.setF3Enabled(true); + //#elseif MC>=12002 //$$ mc.getDebugHud().toggleDebugHud(); //#else mc.options.debugEnabled = true; @@ -453,6 +464,15 @@ public class VideoRenderer implements RenderInfo { while (mc.getOverlay() != null) { drawGui(); ((MinecraftMethodAccessor) mc).replayModExecuteTaskQueue(); + + //#if MC>=12109 + //$$ // The SplashOverlay now only closes on `tick`, but there are no ticks while we're waiting, + //$$ // so we need to manually tick it to not get stuck. + //$$ Overlay overlay = mc.getOverlay(); + //$$ if (overlay != null) { + //$$ overlay.tick(); + //$$ } + //#endif } CompletableFuture resourceReloadFuture = ((MinecraftAccessor) mc).getResourceReloadFuture(); diff --git a/src/main/java/com/replaymod/replay/FullReplaySender.java b/src/main/java/com/replaymod/replay/FullReplaySender.java index 6202afbc..521078e2 100644 --- a/src/main/java/com/replaymod/replay/FullReplaySender.java +++ b/src/main/java/com/replaymod/replay/FullReplaySender.java @@ -23,7 +23,6 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.OtherClientPlayerEntity; -import net.minecraft.client.gui.screen.DownloadingTerrainScreen; import net.minecraft.client.gui.screen.NoticeScreen; import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.Entity; @@ -56,6 +55,17 @@ import net.minecraft.util.math.Vec3d; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; +//#if MC>=12109 +//$$ import net.minecraft.network.ClientConnection; +//$$ import net.minecraft.network.listener.PacketListener; +//#endif + +//#if MC>=12109 +//$$ import net.minecraft.client.gui.screen.world.LevelLoadingScreen; +//#else +import net.minecraft.client.gui.screen.DownloadingTerrainScreen; +//#endif + //#if MC>=12105 //#else import net.minecraft.network.packet.s2c.play.ExperienceOrbSpawnS2CPacket; @@ -853,7 +863,11 @@ public class FullReplaySender extends ChannelInboundHandlerAdapter implements Re if(!hasWorldLoaded) hasWorldLoaded = true; ReplayMod.instance.runLater(() -> { + //#if MC>=12109 + //$$ if (mc.currentScreen instanceof LevelLoadingScreen) { + //#else if (mc.currentScreen instanceof DownloadingTerrainScreen) { + //#endif // Close the world loading screen manually in case we swallow the packet mc.openScreen(null); } @@ -969,7 +983,7 @@ public class FullReplaySender extends ChannelInboundHandlerAdapter implements Re return processPacketAsync(p); } else { Packet fp = p; - mc.send(() -> processPacketSync(fp)); + schedulePacketHandler(() -> processPacketSync(fp)); return p; } } @@ -1383,7 +1397,18 @@ public class FullReplaySender extends ChannelInboundHandlerAdapter implements Re if (mc.isOnThread()) { runnable.run(); } else { - //#if MC>=11400 + //#if MC>=12109 + //$$ mc.getPacketApplyBatcher().add(channel.pipeline().get(ClientConnection.class).getPacketListener(), new Packet<>() { + //$$ @Override + //$$ public net.minecraft.network.packet.PacketType> getPacketType() { + //$$ return null; + //$$ } + //$$ @Override + //$$ public void apply(PacketListener listener) { + //$$ runnable.run(); + //$$ } + //$$ }); + //#elseif MC>=11400 mc.execute(runnable); //#else //$$ mc.addScheduledTask(runnable); diff --git a/src/main/java/com/replaymod/replay/InputReplayTimer.java b/src/main/java/com/replaymod/replay/InputReplayTimer.java index dd64014f..cf577ad7 100644 --- a/src/main/java/com/replaymod/replay/InputReplayTimer.java +++ b/src/main/java/com/replaymod/replay/InputReplayTimer.java @@ -7,9 +7,17 @@ import com.replaymod.replay.camera.CameraEntity; import de.johni0702.minecraft.gui.versions.ScreenExt; import net.minecraft.client.MinecraftClient; +//#if MC>=12109 +//$$ import net.minecraft.client.gui.screen.Overlay; +//#endif + +//#if MC>=12109 +//$$ import net.minecraft.client.gui.screen.world.LevelLoadingScreen; +//#else //#if MC>=11802 //$$ import net.minecraft.client.gui.screen.DownloadingTerrainScreen; //#endif +//#endif //#if MC>=11400 import org.lwjgl.glfw.GLFW; @@ -92,11 +100,23 @@ public class InputReplayTimer { //#if MC>=11802 //$$ // As of 1.18.2, this screen always stays open for at least two seconds, and requires ticking to close. //$$ // Thanks, but we'll have none of that (at least while in a replay). + //#if MC>=12109 + //$$ if (mc.currentScreen instanceof LevelLoadingScreen) { + //#else //$$ if (mc.currentScreen instanceof DownloadingTerrainScreen) { + //#endif //$$ mc.currentScreen.close(); //$$ } //#endif + //#if MC>=12109 + //$$ // The SplashOverlay now only closes on `tick`, but there are no ticks while the replay is paused. + //$$ // so we need to manually tick it to not get stuck. + //$$ Overlay overlay = mc.getOverlay(); + //$$ if (overlay != null) { + //$$ overlay.tick(); + //$$ } + //#endif } } diff --git a/src/main/java/com/replaymod/replay/ReplayHandler.java b/src/main/java/com/replaymod/replay/ReplayHandler.java index 5b6454df..c6675484 100644 --- a/src/main/java/com/replaymod/replay/ReplayHandler.java +++ b/src/main/java/com/replaymod/replay/ReplayHandler.java @@ -31,7 +31,6 @@ import io.netty.channel.ChannelOutboundHandlerAdapter; import io.netty.channel.ChannelPromise; import io.netty.channel.embedded.EmbeddedChannel; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.DownloadingTerrainScreen; import net.minecraft.client.network.ClientLoginNetworkHandler; import net.minecraft.client.util.Window; import net.minecraft.network.DecoderHandler; @@ -45,6 +44,12 @@ import net.minecraft.network.ClientConnection; import java.io.IOException; import java.util.*; +//#if MC>=12109 +//$$ import net.minecraft.client.gui.screen.world.LevelLoadingScreen; +//#else +import net.minecraft.client.gui.screen.DownloadingTerrainScreen; +//#endif + //#if MC>=12106 //$$ import com.replaymod.render.mixin.GameRendererAccessor; //$$ import net.minecraft.client.gui.render.state.GuiRenderState; @@ -373,7 +378,11 @@ public class ReplayHandler { // We don't send any packets (there is no server to receive them), so we need to switch manually. //#if MC>=12006 //$$ networkManager.transitionInbound(LoginStates.S2C, new ClientLoginNetworkHandler( - //$$ networkManager, mc, null, null, false, null, it -> {}, null + //$$ networkManager, mc, null, null, false, null, it -> {}, + //#if MC>=12109 + //$$ new net.minecraft.client.world.ClientChunkLoadProgress(), + //#endif + //$$ null //$$ )); //$$ networkManager.transitionOutbound(LoginStates.C2S); //#else @@ -697,7 +706,11 @@ public class ReplayHandler { do { replaySender.sendPacketsTill(targetTime); targetTime += 500; + //#if MC>=12109 + //$$ } while (mc.player == null || mc.currentScreen instanceof LevelLoadingScreen); + //#else } while (mc.player == null || mc.currentScreen instanceof DownloadingTerrainScreen); + //#endif replaySender.setAsyncMode(true); for (int i = 0; i < Math.min(diff / 50, 3); i++) { @@ -852,7 +865,11 @@ public class ReplayHandler { do { replaySender.sendPacketsTill(targetTime); targetTime += 500; + //#if MC>=12109 + //$$ } while (mc.player == null || mc.currentScreen instanceof LevelLoadingScreen); + //#else } while (mc.player == null || mc.currentScreen instanceof DownloadingTerrainScreen); + //#endif replaySender.setAsyncMode(true); replaySender.setReplaySpeed(0); diff --git a/src/main/java/com/replaymod/replay/ReplayModReplay.java b/src/main/java/com/replaymod/replay/ReplayModReplay.java index 11459bd2..73259694 100644 --- a/src/main/java/com/replaymod/replay/ReplayModReplay.java +++ b/src/main/java/com/replaymod/replay/ReplayModReplay.java @@ -19,6 +19,7 @@ import com.replaymod.replay.gui.screen.GuiModCompatWarning; import com.replaymod.replay.handler.GuiHandler; import com.replaymod.replaystudio.data.Marker; import com.replaymod.replaystudio.replay.ReplayFile; +import de.johni0702.minecraft.gui.function.Click; import net.minecraft.client.MinecraftClient; import net.minecraft.client.options.KeyBinding; import org.apache.logging.log4j.LogManager; @@ -116,7 +117,7 @@ public class ReplayModReplay implements Module { @Override public void run() { if (replayHandler != null) { - replayHandler.getOverlay().playPauseButton.onClick(); + replayHandler.getOverlay().playPauseButton.onClick(new Click(-1, -1, 0, 0)); } } }, true); diff --git a/src/main/java/com/replaymod/replay/camera/CameraEntity.java b/src/main/java/com/replaymod/replay/camera/CameraEntity.java index 1e16cf61..e6d5acac 100644 --- a/src/main/java/com/replaymod/replay/camera/CameraEntity.java +++ b/src/main/java/com/replaymod/replay/camera/CameraEntity.java @@ -30,6 +30,12 @@ import net.minecraft.item.ItemStack; import net.minecraft.stat.StatHandler; import net.minecraft.util.Identifier; import net.minecraft.util.math.Box; +import net.minecraft.world.World; + +//#if MC>=12109 +//$$ import net.minecraft.client.network.ClientPlayerLikeEntity; +//$$ import net.minecraft.entity.PlayerLikeEntity; +//#endif //#if MC>=12106 //$$ import net.minecraft.util.PlayerInput; @@ -322,15 +328,18 @@ public class CameraEntity // This is important if the spectated player respawns as their // entity is recreated and we have to spectate a new entity UUID spectating = ReplayModReplay.instance.getReplayHandler().getSpectatedUUID(); + // FIXME remap bug: Pattern doesn't work when these two are inlined + World cameraWorld = this.world; + World viewWorld = view.world; if (spectating != null && (view.getUuid() != spectating - || view.world != this.world) - || this.world.getEntityById(view.getEntityId()) != view) { + || viewWorld != cameraWorld) + || cameraWorld.getEntityById(view.getEntityId()) != view) { if (spectating == null) { // Entity (non-player) died, stop spectating ReplayModReplay.instance.getReplayHandler().spectateEntity(this); return; } - view = this.world.getPlayerByUuid(spectating); + view = cameraWorld.getPlayerByUuid(spectating); if (view != null) { this.client.setCameraEntity(view); } else { @@ -502,7 +511,16 @@ public class CameraEntity return super.isInvisible(); } - //#if MC>=12002 + //#if MC>=12109 + //$$ @Override + //$$ public SkinTextures getSkin() { + //$$ Entity view = this.client.getCameraEntity(); + //$$ if (view != this && view instanceof ClientPlayerLikeEntity) { + //$$ return ((ClientPlayerLikeEntity) view).getSkin(); + //$$ } + //$$ return super.getSkin(); + //$$ } + //#elseif MC>=12002 //$$ @Override //$$ public SkinTextures getSkinTextures() { //$$ Entity view = this.client.getCameraEntity(); @@ -533,7 +551,16 @@ public class CameraEntity //#endif //#endif - //#if MC>=10800 + //#if MC>=12109 + //$$ @Override + //$$ public boolean isModelPartVisible(PlayerModelPart modelPart) { + //$$ Entity view = this.client.getCameraEntity(); + //$$ if (view != this && view instanceof PlayerLikeEntity) { + //$$ return ((PlayerLikeEntity) view).isModelPartVisible(modelPart); + //$$ } + //$$ return super.isModelPartVisible(modelPart); + //$$ } + //#elseif MC>=10800 @Override public boolean isPartVisible(PlayerModelPart modelPart) { Entity view = this.client.getCameraEntity(); diff --git a/src/main/java/com/replaymod/replay/gui/overlay/GuiEditMarkerPopup.java b/src/main/java/com/replaymod/replay/gui/overlay/GuiEditMarkerPopup.java index ab2a3d78..e8d66fb3 100644 --- a/src/main/java/com/replaymod/replay/gui/overlay/GuiEditMarkerPopup.java +++ b/src/main/java/com/replaymod/replay/gui/overlay/GuiEditMarkerPopup.java @@ -4,19 +4,19 @@ import com.google.common.base.Strings; import de.johni0702.minecraft.gui.container.GuiContainer; import de.johni0702.minecraft.gui.container.GuiPanel; import de.johni0702.minecraft.gui.element.*; -import de.johni0702.minecraft.gui.function.Typeable; +import de.johni0702.minecraft.gui.function.Click; +import de.johni0702.minecraft.gui.function.KeyHandler; +import de.johni0702.minecraft.gui.function.KeyInput; import de.johni0702.minecraft.gui.layout.GridLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout; import de.johni0702.minecraft.gui.layout.VerticalLayout; import de.johni0702.minecraft.gui.popup.AbstractGuiPopup; import de.johni0702.minecraft.gui.utils.Colors; -import com.replaymod.core.versions.MCVer.Keyboard; import com.replaymod.replaystudio.data.Marker; -import de.johni0702.minecraft.gui.utils.lwjgl.ReadablePoint; import java.util.function.Consumer; -public class GuiEditMarkerPopup extends AbstractGuiPopup implements Typeable { +public class GuiEditMarkerPopup extends AbstractGuiPopup implements KeyHandler { private static GuiNumberField newGuiNumberField() { return new GuiNumberField().setSize(150, 20).setValidateOnFocusChange(true); } @@ -116,9 +116,9 @@ public class GuiEditMarkerPopup extends AbstractGuiPopup imp } @Override - public boolean typeKey(ReadablePoint mousePosition, int keyCode, char keyChar, boolean ctrlDown, boolean shiftDown) { - if (keyCode == Keyboard.KEY_ESCAPE) { - cancelButton.onClick(); + public boolean handleKey(KeyInput keyInput) { + if (keyInput.isEscape()) { + cancelButton.onClick(new Click(-1, -1, 0, keyInput.modifiers)); return true; } return false; diff --git a/src/main/java/com/replaymod/replay/gui/overlay/GuiMarkerTimeline.java b/src/main/java/com/replaymod/replay/gui/overlay/GuiMarkerTimeline.java index 8954652a..e2a6ed98 100644 --- a/src/main/java/com/replaymod/replay/gui/overlay/GuiMarkerTimeline.java +++ b/src/main/java/com/replaymod/replay/gui/overlay/GuiMarkerTimeline.java @@ -10,8 +10,10 @@ import com.replaymod.replaystudio.util.Location; import de.johni0702.minecraft.gui.GuiRenderer; import de.johni0702.minecraft.gui.RenderInfo; import de.johni0702.minecraft.gui.element.advanced.AbstractGuiTimeline; +import de.johni0702.minecraft.gui.function.Click; import de.johni0702.minecraft.gui.function.Draggable; -import de.johni0702.minecraft.gui.function.Typeable; +import de.johni0702.minecraft.gui.function.KeyHandler; +import de.johni0702.minecraft.gui.function.KeyInput; import de.johni0702.minecraft.gui.utils.lwjgl.Point; import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension; import de.johni0702.minecraft.gui.utils.lwjgl.ReadablePoint; @@ -27,7 +29,7 @@ import java.util.function.Consumer; import static de.johni0702.minecraft.gui.utils.Utils.clamp; -public class GuiMarkerTimeline extends AbstractGuiTimeline implements Draggable, Typeable { +public class GuiMarkerTimeline extends AbstractGuiTimeline implements Draggable, KeyHandler { protected static final int TEXTURE_MARKER_X = 109; protected static final int TEXTURE_MARKER_Y = 20; protected static final int TEXTURE_MARKER_SELECTED_X = 114; @@ -149,15 +151,15 @@ public class GuiMarkerTimeline extends AbstractGuiTimeline im } @Override - public boolean mouseClick(ReadablePoint position, int button) { - Marker marker = getMarkerAt(position.getX(), position.getY()); + public boolean mouseClick(Click click) { + Marker marker = getMarkerAt(click.x, click.y); if (marker != null) { - if (button == 0) { // Left click + if (click.button == 0) { // Left click long now = System.currentTimeMillis(); selectedMarker = marker; if (Math.abs(lastClickTime - now) > 500) { // Single click - draggingStartX = position.getX(); - draggingTimeDelta = marker.getTime() - getTimeAt(position.getX(), position.getY()); + draggingStartX = click.x; + draggingTimeDelta = marker.getTime() - getTimeAt(click.x, click.y); } else { // Double click new GuiEditMarkerPopup(getContainer(), marker, (updatedMarker) -> { markers.remove(marker); @@ -166,7 +168,7 @@ public class GuiMarkerTimeline extends AbstractGuiTimeline im }).open(); } lastClickTime = now; - } else if (button == 1) { // Right click + } else if (click.button == 1) { // Right click selectedMarker = null; if (replayHandler != null) { CameraEntity cameraEntity = replayHandler.getCameraEntity(); @@ -185,18 +187,18 @@ public class GuiMarkerTimeline extends AbstractGuiTimeline im } else { selectedMarker = null; } - return super.mouseClick(position, button); + return super.mouseClick(click); } @Override - public boolean mouseDrag(ReadablePoint position, int button, long timeSinceLastCall) { + public boolean mouseDrag(Click click) { if (selectedMarker != null) { - int diff = position.getX() - draggingStartX; + int diff = click.y - draggingStartX; if (Math.abs(diff) > MARKER_SIZE) { dragging = true; } if (dragging) { - int timeAt = getTimeAt(position.getX(), position.getY()); + int timeAt = getTimeAt(click.x, click.y); if (timeAt != -1) { selectedMarker.setTime(draggingTimeDelta + timeAt); } @@ -207,9 +209,9 @@ public class GuiMarkerTimeline extends AbstractGuiTimeline im } @Override - public boolean mouseRelease(ReadablePoint position, int button) { + public boolean mouseRelease(Click click) { if (selectedMarker != null) { - mouseDrag(position, button, 0); + mouseDrag(click); if (dragging) { dragging = false; saveMarkers.accept(markers); @@ -237,8 +239,8 @@ public class GuiMarkerTimeline extends AbstractGuiTimeline im } @Override - public boolean typeKey(ReadablePoint mousePosition, int keyCode, char keyChar, boolean ctrlDown, boolean shiftDown) { - if (keyCode == Keyboard.KEY_DELETE && selectedMarker != null) { + public boolean handleKey(KeyInput keyInput) { + if (keyInput.key == Keyboard.KEY_DELETE && selectedMarker != null) { markers.remove(selectedMarker); saveMarkers.accept(markers); return 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 14bef7b1..0738256a 100644 --- a/src/main/java/com/replaymod/replay/gui/overlay/GuiReplayOverlay.java +++ b/src/main/java/com/replaymod/replay/gui/overlay/GuiReplayOverlay.java @@ -16,6 +16,7 @@ import de.johni0702.minecraft.gui.element.GuiElement; import de.johni0702.minecraft.gui.element.GuiSlider; import de.johni0702.minecraft.gui.element.GuiTooltip; import de.johni0702.minecraft.gui.element.advanced.IGuiTimeline; +import de.johni0702.minecraft.gui.function.KeyInput; import de.johni0702.minecraft.gui.layout.CustomLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout; import de.johni0702.minecraft.gui.utils.EventRegistrations; @@ -181,13 +182,15 @@ public class GuiReplayOverlay extends AbstractGuiOverlay { } } - { on(KeyEventCallback.EVENT, (int key, int scanCode, int action, int modifiers) -> { onKeyInput(key, action); return false; }); } - private void onKeyInput(int key, int action) { - if (action != KeyEventCallback.ACTION_PRESS) return; + { on(KeyEventCallback.EVENT, this::onKeyInput); } + private boolean onKeyInput(KeyInput keyInput, int action) { + if (action != KeyEventCallback.ACTION_PRESS) return false; // Allow F1 to be used to hide the replay gui (e.g. for recording with OBS) - if (isMouseVisible() && key == Keyboard.KEY_F1) { + if (isMouseVisible() && keyInput.key == Keyboard.KEY_F1) { hidden = !hidden; + return true; } + return false; } } } 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 9a2dec3c..7ea996de 100644 --- a/src/main/java/com/replaymod/replay/gui/screen/GuiReplayViewer.java +++ b/src/main/java/com/replaymod/replay/gui/screen/GuiReplayViewer.java @@ -6,6 +6,11 @@ import com.replaymod.render.rendering.VideoRenderer; import com.replaymod.render.utils.RenderJob; import de.johni0702.minecraft.gui.GuiRenderer; import de.johni0702.minecraft.gui.RenderInfo; +import de.johni0702.minecraft.gui.function.CharHandler; +import de.johni0702.minecraft.gui.function.CharInput; +import de.johni0702.minecraft.gui.function.Click; +import de.johni0702.minecraft.gui.function.KeyHandler; +import de.johni0702.minecraft.gui.function.KeyInput; import de.johni0702.minecraft.gui.versions.Image; import net.minecraft.client.font.TextRenderer; import net.minecraft.util.Formatting; @@ -25,7 +30,6 @@ import de.johni0702.minecraft.gui.container.GuiPanel; import de.johni0702.minecraft.gui.container.GuiScreen; import de.johni0702.minecraft.gui.element.*; import de.johni0702.minecraft.gui.element.advanced.AbstractGuiResourceLoadingList; -import de.johni0702.minecraft.gui.function.Typeable; import de.johni0702.minecraft.gui.layout.CustomLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout; import de.johni0702.minecraft.gui.layout.VerticalLayout; @@ -35,7 +39,6 @@ import de.johni0702.minecraft.gui.utils.Colors; import de.johni0702.minecraft.gui.utils.Consumer; import de.johni0702.minecraft.gui.utils.lwjgl.Dimension; import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension; -import de.johni0702.minecraft.gui.utils.lwjgl.ReadablePoint; import net.minecraft.client.gui.screen.NoticeScreen; import net.minecraft.util.crash.CrashReport; import net.minecraft.util.crash.CrashException; @@ -79,7 +82,7 @@ public class GuiReplayViewer extends GuiScreen { public final GuiReplayList list = new GuiReplayList(this).onSelectionChanged(this::updateButtons).onSelectionDoubleClicked(() -> { if (this.loadButton.isEnabled()) { - this.loadButton.onClick(); + this.loadButton.onClick(new Click(-1, -1, 0, 0)); } }); @@ -146,7 +149,7 @@ public class GuiReplayViewer extends GuiScreen { @Override public void run() { if (popup.getYesButton().isEnabled()) { - popup.getYesButton().onClick(); + popup.getYesButton().onClick(new Click(-1, -1, 0, 0)); } } }).onTextChanged(obj -> { @@ -352,7 +355,7 @@ public class GuiReplayViewer extends GuiScreen { } } - public static class GuiReplayList extends AbstractGuiResourceLoadingList implements Typeable { + public static class GuiReplayList extends AbstractGuiResourceLoadingList implements KeyHandler, CharHandler { private File folder = null; // Not actually a child of this element, we just use it for text manipulation @@ -417,8 +420,8 @@ public class GuiReplayViewer extends GuiScreen { } @Override - public boolean typeKey(ReadablePoint mousePosition, int keyCode, char keyChar, boolean ctrlDown, boolean shiftDown) { - if (keyCode == Keyboard.KEY_F1) { + public boolean handleKey(KeyInput keyInput) { + if (keyInput.key == Keyboard.KEY_F1) { SettingsRegistry reg = ReplayMod.instance.getSettingsRegistry(); reg.set(Setting.SHOW_SERVER_IPS, !reg.get(Setting.SHOW_SERVER_IPS)); reg.save(); @@ -426,16 +429,26 @@ public class GuiReplayViewer extends GuiScreen { } boolean filterHasPriority = !filterTextField.getText().isEmpty(); - if (filterHasPriority && filterTextField.typeKey(mousePosition, keyCode, keyChar, ctrlDown, shiftDown)) { + if (filterHasPriority && filterTextField.handleKey(keyInput)) { scrollY(0); // ensure we scroll to top if most entries are filtered return true; } - if (super.typeKey(mousePosition, keyCode, keyChar, ctrlDown, shiftDown)) { + if (super.handleKey(keyInput)) { return true; } - if (!filterHasPriority && filterTextField.typeKey(mousePosition, keyCode, keyChar, ctrlDown, shiftDown)) { + if (!filterHasPriority && filterTextField.handleKey(keyInput)) { + scrollY(0); // ensure we scroll to top if most entries are filtered + return true; + } + + return false; + } + + @Override + public boolean handleChar(CharInput charInput) { + if (filterTextField.handleChar(charInput)) { scrollY(0); // ensure we scroll to top if most entries are filtered return true; } diff --git a/src/main/java/com/replaymod/simplepathing/ReplayModSimplePathing.java b/src/main/java/com/replaymod/simplepathing/ReplayModSimplePathing.java index aaa839e8..599ea6ee 100644 --- a/src/main/java/com/replaymod/simplepathing/ReplayModSimplePathing.java +++ b/src/main/java/com/replaymod/simplepathing/ReplayModSimplePathing.java @@ -98,7 +98,7 @@ public class ReplayModSimplePathing extends EventRegistrations implements Module settingsRegistry.set(Setting.AUTO_SYNC, active); settingsRegistry.save(); }); - core.getKeyBindingRegistry().registerRaw(Keyboard.KEY_DELETE, () -> + core.getKeyBindingRegistry().registerRaw(Keyboard.KEY_DELETE, keyInput -> guiPathing != null && guiPathing.deleteButtonPressed()); keyPositionKeyframe = core.getKeyBindingRegistry().registerKeyBinding("replaymod.input.positionkeyframe", Keyboard.KEY_I, () -> { if (guiPathing != null) guiPathing.toggleKeyframe(SPPath.POSITION, false); @@ -115,10 +115,10 @@ public class ReplayModSimplePathing extends EventRegistrations implements Module guiPathing.toggleKeyframe(SPPath.POSITION, false); } }, true); - core.getKeyBindingRegistry().registerRaw(Keyboard.KEY_Z, () -> { - if (Screen.hasControlDown() && currentTimeline != null) { + core.getKeyBindingRegistry().registerRaw(Keyboard.KEY_Z, keyInput -> { + if (keyInput.hasCtrl() && currentTimeline != null) { Timeline timeline = currentTimeline.getTimeline(); - if (Screen.hasShiftDown()) { + if (keyInput.hasShift()) { if (timeline.peekRedoStack() != null) { timeline.redoLastChange(); } @@ -131,8 +131,8 @@ public class ReplayModSimplePathing extends EventRegistrations implements Module } return false; }); - core.getKeyBindingRegistry().registerRaw(Keyboard.KEY_Y, () -> { - if (Screen.hasControlDown() && currentTimeline != null) { + core.getKeyBindingRegistry().registerRaw(Keyboard.KEY_Y, keyInput -> { + if (keyInput.hasCtrl() && currentTimeline != null) { Timeline timeline = currentTimeline.getTimeline(); if (timeline.peekRedoStack() != null) { timeline.redoLastChange(); diff --git a/src/main/java/com/replaymod/simplepathing/gui/GuiEditKeyframe.java b/src/main/java/com/replaymod/simplepathing/gui/GuiEditKeyframe.java index eb3561ec..cd417bcf 100644 --- a/src/main/java/com/replaymod/simplepathing/gui/GuiEditKeyframe.java +++ b/src/main/java/com/replaymod/simplepathing/gui/GuiEditKeyframe.java @@ -26,14 +26,15 @@ import de.johni0702.minecraft.gui.element.GuiTooltip; import de.johni0702.minecraft.gui.element.IGuiClickable; import de.johni0702.minecraft.gui.element.IGuiLabel; import de.johni0702.minecraft.gui.element.advanced.GuiDropdownMenu; -import de.johni0702.minecraft.gui.function.Typeable; +import de.johni0702.minecraft.gui.function.Click; +import de.johni0702.minecraft.gui.function.KeyHandler; +import de.johni0702.minecraft.gui.function.KeyInput; import de.johni0702.minecraft.gui.layout.GridLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout; import de.johni0702.minecraft.gui.layout.VerticalLayout; import de.johni0702.minecraft.gui.popup.AbstractGuiPopup; import de.johni0702.minecraft.gui.utils.Colors; import de.johni0702.minecraft.gui.utils.Consumer; -import de.johni0702.minecraft.gui.utils.lwjgl.ReadablePoint; import net.minecraft.client.resource.language.I18n; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -41,15 +42,9 @@ import org.apache.logging.log4j.Logger; import java.util.Map; import java.util.Optional; -//#if MC>=11400 -import com.replaymod.core.versions.MCVer.Keyboard; -//#else -//$$ import org.lwjgl.input.Keyboard; -//#endif - import static de.johni0702.minecraft.gui.utils.Utils.link; -public abstract class GuiEditKeyframe> extends AbstractGuiPopup implements Typeable { +public abstract class GuiEditKeyframe> extends AbstractGuiPopup implements KeyHandler { private static GuiNumberField newGuiNumberField() { return new GuiNumberField().setPrecision(0).setValidateOnFocusChange(true); } @@ -134,9 +129,9 @@ public abstract class GuiEditKeyframe> extends Abst } @Override - public boolean typeKey(ReadablePoint mousePosition, int keyCode, char keyChar, boolean ctrlDown, boolean shiftDown) { - if (keyCode == Keyboard.KEY_ESCAPE) { - cancelButton.onClick(); + public boolean handleKey(KeyInput keyInput) { + if (keyInput.isEscape()) { + cancelButton.onClick(new Click(-1, -1, 0, keyInput.modifiers)); return true; } return false; diff --git a/src/main/java/com/replaymod/simplepathing/gui/GuiKeyframeTimeline.java b/src/main/java/com/replaymod/simplepathing/gui/GuiKeyframeTimeline.java index ace2201f..3a4ad6e6 100644 --- a/src/main/java/com/replaymod/simplepathing/gui/GuiKeyframeTimeline.java +++ b/src/main/java/com/replaymod/simplepathing/gui/GuiKeyframeTimeline.java @@ -17,6 +17,7 @@ import com.replaymod.simplepathing.SPTimeline; import com.replaymod.simplepathing.SPTimeline.SPPath; import de.johni0702.minecraft.gui.GuiRenderer; import de.johni0702.minecraft.gui.element.advanced.AbstractGuiTimeline; +import de.johni0702.minecraft.gui.function.Click; import de.johni0702.minecraft.gui.function.Draggable; import de.johni0702.minecraft.gui.utils.lwjgl.vector.Vector2f; import net.minecraft.client.render.BufferBuilder; @@ -407,14 +408,14 @@ public class GuiKeyframeTimeline extends AbstractGuiTimeline pathKeyframePair = getKeyframe(position); + public boolean mouseClick(Click click) { + int time = getTimeAt(click.x, click.y); + Pair pathKeyframePair = getKeyframe(click); if (pathKeyframePair.getRight() != null) { SPPath path = pathKeyframePair.getLeft(); // Clicked on keyframe long keyframeTime = pathKeyframePair.getRight(); - if (button == 0) { // Left click + if (click.button == 0) { // Left click long now = MCVer.milliTime(); if (lastClickedKeyframe == keyframeTime) { // Clicked the same keyframe again, potentially a double click @@ -430,9 +431,9 @@ public class GuiKeyframeTimeline extends AbstractGuiTimeline= DRAGGING_THRESHOLD) { + if (Math.abs(click.x - draggingStartX) >= DRAGGING_THRESHOLD) { actuallyDragging = true; } } if (actuallyDragging) { - if (!gui.loadEntityTracker(() -> mouseDrag(position, button, timeSinceLastCall))) return true; + if (!gui.loadEntityTracker(() -> mouseDrag(click))) return true; // Threshold passed SPTimeline timeline = gui.getMod().getCurrentTimeline(); - Point mouse = new Point(position); + Point mouse = new Point(click); getContainer().convertFor(this, mouse); int mouseX = mouse.getX(); int width = getLastSize().getWidth(); @@ -532,7 +533,7 @@ public class GuiKeyframeTimeline extends AbstractGuiTimeline=12109 + //$$ private static final String SETUP_TERRAIN = "Lnet/minecraft/client/render/WorldRenderer;method_74752(Lnet/minecraft/client/render/Camera;Lnet/minecraft/client/render/Frustum;Z)V"; + //#else + private static final String SETUP_TERRAIN = "Lnet/minecraft/client/render/WorldRenderer;setupTerrain(Lnet/minecraft/client/render/Camera;Lnet/minecraft/client/render/Frustum;ZZ)V"; + //#endif + @Override public void replayModRender_setHook(ForceChunkLoadingHook hook) { this.replayModRender_hook = hook; @@ -40,18 +46,28 @@ public abstract class Mixin_ForceChunkLoading implements IForceChunkLoading { @Shadow @Final private ChunkRenderingDataPreparer field_45615; + //#if MC>=12109 + //$$ @Shadow protected abstract void method_74752(Camera par1, Frustum par2, boolean par3); + //#else @Shadow protected abstract void setupTerrain(Camera par1, Frustum par2, boolean par3, boolean par4); @Shadow private Frustum frustum; @Shadow private Frustum capturedFrustum; + //#endif @Shadow @Final private MinecraftClient client; @Shadow protected abstract void applyFrustum(Frustum par1); - @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;setupTerrain(Lnet/minecraft/client/render/Camera;Lnet/minecraft/client/render/Frustum;ZZ)V")) - private void forceAllChunks(CallbackInfo ci, @Local(argsOnly = true) Camera camera) { + @Inject(method = "render", at = @At(value = "INVOKE", target = SETUP_TERRAIN)) + private void forceAllChunks( + CallbackInfo ci, + //#if MC>=12109 + //$$ @Local Frustum frustum, + //#endif + @Local(argsOnly = true) Camera camera + ) { if (replayModRender_hook == null) { return; } @@ -69,7 +85,11 @@ public abstract class Mixin_ForceChunkLoading implements IForceChunkLoading { boolean areWeDoneYet = true; // Determine which chunks shall be visible + //#if MC>=12109 + //$$ method_74752(camera, frustum, this.client.player.isSpectator()); + //#else setupTerrain(camera, this.frustum, this.capturedFrustum != null, this.client.player.isSpectator()); + //#endif // Wait for async processing to be complete Future fullUpdateFuture = renderingDataAcc.fullUpdateFuture(); diff --git a/versions/1.21.10/.gitkeep b/versions/1.21.10/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/versions/1.21.10/gradle.properties b/versions/1.21.10/gradle.properties new file mode 100644 index 00000000..e48a92a5 --- /dev/null +++ b/versions/1.21.10/gradle.properties @@ -0,0 +1,3 @@ +essential.defaults.loom.minecraft=com.mojang:minecraft:1.21.10 +essential.defaults.loom.mappings=net.fabricmc:yarn:1.21.10+build.2:v2 +essential.loom.disableUnpick=true diff --git a/versions/1.21.10/src/main/java/com/replaymod/render/mixin/MixinParticleManager.java b/versions/1.21.10/src/main/java/com/replaymod/render/mixin/MixinParticleManager.java new file mode 100644 index 00000000..1e3c87e9 --- /dev/null +++ b/versions/1.21.10/src/main/java/com/replaymod/render/mixin/MixinParticleManager.java @@ -0,0 +1,60 @@ +package com.replaymod.render.mixin; + +import com.llamalad7.mixinextras.sugar.Local; +import com.llamalad7.mixinextras.sugar.Share; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; +import com.replaymod.core.versions.MCVer; +import com.replaymod.render.hooks.EntityRendererHandler; +import net.minecraft.client.particle.BillboardParticle; +import net.minecraft.client.particle.BillboardParticleSubmittable; +import net.minecraft.client.render.Camera; +import net.minecraft.util.math.Vec3d; +import org.joml.Quaternionf; +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(BillboardParticle.class) +public abstract class MixinParticleManager { + @Shadow public abstract void render(BillboardParticleSubmittable par1, Camera par2, float par3); + + @Inject(method = "render(Lnet/minecraft/client/particle/BillboardParticleSubmittable;Lnet/minecraft/client/render/Camera;F)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/BillboardParticle$Rotator;setRotation(Lorg/joml/Quaternionf;Lnet/minecraft/client/render/Camera;F)V")) + private void faceCameraAtParticle( + CallbackInfo ci, + @Local(argsOnly = true) float partialTicks, + @Local(argsOnly = true) Camera camera, + @Share("orgRotation") LocalRef orgRotationRef + ) { + EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) MCVer.getMinecraft().gameRenderer).replayModRender_getHandler(); + if (handler == null || !handler.omnidirectional) { + return; + } + + Quaternionf rotation = camera.getRotation(); + orgRotationRef.set(new Quaternionf(rotation)); + + Vec3d from = new Vec3d(0, 0, -1); + Vec3d to = MCVer.getPosition((BillboardParticle)(Object) this, partialTicks) + .subtract(camera.getPos()) + .normalize(); + Vec3d axis = from.crossProduct(to); + rotation.set((float) axis.x, (float) axis.y, (float) axis.z, (float) (1 + from.dotProduct(to))); + rotation.normalize(); + } + + @Inject(method = "render(Lnet/minecraft/client/particle/BillboardParticleSubmittable;Lnet/minecraft/client/render/Camera;F)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/BillboardParticle$Rotator;setRotation(Lorg/joml/Quaternionf;Lnet/minecraft/client/render/Camera;F)V", shift = At.Shift.AFTER)) + private void faceCameraAtParticleCleanup( + CallbackInfo ci, + @Local(argsOnly = true) Camera camera, + @Share("orgRotation") LocalRef orgRotationRef + ) { + Quaternionf orgRotation = orgRotationRef.get(); + if (orgRotation == null) { + return; + } + + camera.getRotation().set(orgRotation.x, orgRotation.y, orgRotation.z, orgRotation.w); + } +} diff --git a/versions/1.21.10/src/main/java/com/replaymod/render/mixin/MixinRenderManager.java b/versions/1.21.10/src/main/java/com/replaymod/render/mixin/MixinRenderManager.java new file mode 100644 index 00000000..d23609d7 --- /dev/null +++ b/versions/1.21.10/src/main/java/com/replaymod/render/mixin/MixinRenderManager.java @@ -0,0 +1,38 @@ +package com.replaymod.render.mixin; + +import com.llamalad7.mixinextras.sugar.Local; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; +import com.replaymod.core.versions.MCVer; +import com.replaymod.render.hooks.EntityRendererHandler; +import net.minecraft.client.render.entity.EntityRenderManager; +import net.minecraft.client.render.state.CameraRenderState; +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(EntityRenderManager.class) +public abstract class MixinRenderManager { + @Inject(method = "render", at = @At("HEAD")) + private void replayModRender_reorientForCubicRendering( + CallbackInfo ci, + @Local(argsOnly = true, ordinal = 0) double dx, + @Local(argsOnly = true, ordinal = 1) double dy, + @Local(argsOnly = true, ordinal = 2) double dz, + @Local(argsOnly = true) LocalRef cameraRenderStateRef + ) { + EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) MCVer.getMinecraft().gameRenderer).replayModRender_getHandler(); + if (handler == null || !handler.omnidirectional) { + return; + } + + CameraRenderState org = cameraRenderStateRef.get(); + CameraRenderState copy = new CameraRenderState(); + copy.blockPos = org.blockPos; + copy.pos = org.pos; + copy.initialized = org.initialized; + copy.entityPos = org.entityPos; + copy.orientation.lookAlong((float) dx, (float) dy, (float) dz, 0f, 1f, 0f); + cameraRenderStateRef.set(copy); + } +} diff --git a/versions/mapping-fabric-1.21.10-1.21.7.txt b/versions/mapping-fabric-1.21.10-1.21.7.txt new file mode 100644 index 00000000..38a54161 --- /dev/null +++ b/versions/mapping-fabric-1.21.10-1.21.7.txt @@ -0,0 +1,9 @@ +net.minecraft.util.HeldItemContext getEntityWorld() net.minecraft.entity.Entity getWorld() +net.minecraft.util.HeldItemContext getEntityPos() net.minecraft.entity.Entity getPos() +net.minecraft.client.network.ClientPlayerLikeEntity getSkin() net.minecraft.client.network.AbstractClientPlayerEntity getSkinTextures() +net.minecraft.entity.PlayerLikeEntity isModelPartVisible() net.minecraft.entity.player.PlayerEntity isPartVisible() + +com.mojang.authlib.GameProfile com.mojang.authlib.GameProfile +com.mojang.authlib.GameProfile id() getId()Ljava/util/UUID; +com.mojang.authlib.GameProfile name() getName()Ljava/lang/String; +com.mojang.authlib.GameProfile properties() getProperties()Lcom/mojang/authlib/properties/PropertyMap;