Release 2.6.24

This commit is contained in:
Jonas Herzig
2025-10-20 19:43:35 +02:00
46 changed files with 482 additions and 169 deletions

View File

@@ -91,6 +91,7 @@ dependencies {
12104 -> "0.111.0+1.21.4" 12104 -> "0.111.0+1.21.4"
12105 -> "0.119.9+1.21.5" 12105 -> "0.119.9+1.21.5"
12107 -> "0.128.1+1.21.7" 12107 -> "0.128.1+1.21.7"
12110 -> "0.135.0+1.21.10"
else -> throw UnsupportedOperationException() else -> throw UnsupportedOperationException()
} }
val fabricApiModules = mutableListOf( val fabricApiModules = mutableListOf(
@@ -169,6 +170,7 @@ dependencies {
if (platform.isFabric) { if (platform.isFabric) {
val modMenuVersion = when { val modMenuVersion = when {
mcVersion >= 12110 -> "16.0.0-rc.1"
mcVersion >= 12107 -> "15.0.0-beta.3" mcVersion >= 12107 -> "15.0.0-beta.3"
mcVersion >= 12105 -> "14.0.0-rc.2" mcVersion >= 12105 -> "14.0.0-rc.2"
mcVersion >= 12104 -> "13.0.0-beta.1" mcVersion >= 12104 -> "13.0.0-beta.1"

View File

@@ -1,5 +1,5 @@
essential.defaults.loom=0 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. # 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. # This is required to provide enough memory for the Minecraft decompilation process.

2
jGui

Submodule jGui updated: 31106f5dae...84a8c5438d

View File

@@ -3,7 +3,7 @@ import java.io.ByteArrayOutputStream
plugins { plugins {
id("gg.essential.multi-version.root") 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" id("com.github.hierynomus.license") version "0.15.0"
} }
@@ -204,6 +204,7 @@ defaultTasks("bundleJar")
preprocess { preprocess {
strictExtraMappings.set(true) strictExtraMappings.set(true)
val mc12110 = createNode("1.21.10", 12110, "yarn")
val mc12107 = createNode("1.21.7", 12107, "yarn") val mc12107 = createNode("1.21.7", 12107, "yarn")
val mc12105 = createNode("1.21.5", 12105, "yarn") val mc12105 = createNode("1.21.5", 12105, "yarn")
val mc12104 = createNode("1.21.4", 12104, "yarn") val mc12104 = createNode("1.21.4", 12104, "yarn")
@@ -237,6 +238,7 @@ preprocess {
val mc10800 = createNode("1.8", 10800, "srg") val mc10800 = createNode("1.8", 10800, "srg")
val mc10710 = createNode("1.7.10", 10710, "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) mc12107.link(mc12105)
mc12105.link(mc12104, file("versions/mapping-fabric-1.21.5-1.21.4.txt")) mc12105.link(mc12104, file("versions/mapping-fabric-1.21.5-1.21.4.txt"))
mc12104.link(mc12102) mc12104.link(mc12102)

View File

@@ -44,6 +44,7 @@ val jGuiVersions = listOf(
"1.21.4", "1.21.4",
"1.21.5", "1.21.5",
"1.21.7", "1.21.7",
"1.21.10",
) )
val replayModVersions = listOf( val replayModVersions = listOf(
// "1.7.10", // "1.7.10",
@@ -78,6 +79,7 @@ val replayModVersions = listOf(
"1.21.4", "1.21.4",
"1.21.5", "1.21.5",
"1.21.7", "1.21.7",
"1.21.10",
) )
rootProject.buildFileName = "root.gradle.kts" rootProject.buildFileName = "root.gradle.kts"

View File

@@ -4,6 +4,7 @@ import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.replaymod.core.events.PreRenderCallback; import com.replaymod.core.events.PreRenderCallback;
import com.replaymod.core.mixin.KeyBindingAccessor; import com.replaymod.core.mixin.KeyBindingAccessor;
import de.johni0702.minecraft.gui.function.KeyInput;
import de.johni0702.minecraft.gui.utils.EventRegistrations; import de.johni0702.minecraft.gui.utils.EventRegistrations;
import com.replaymod.core.events.KeyBindingEventCallback; import com.replaymod.core.events.KeyBindingEventCallback;
import com.replaymod.core.events.KeyEventCallback; import com.replaymod.core.events.KeyEventCallback;
@@ -36,17 +37,21 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier; import java.util.function.Function;
public class KeyBindingRegistry extends EventRegistrations { 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"; private static final String CATEGORY = "replaymod.title";
//#if FABRIC>=1 && MC<11600 //#if FABRIC>=1 && MC<11600
//$$ static { net.fabricmc.fabric.api.client.keybinding.KeyBindingRegistry.INSTANCE.addCategory(CATEGORY); } //$$ static { net.fabricmc.fabric.api.client.keybinding.KeyBindingRegistry.INSTANCE.addCategory(CATEGORY); }
//#endif //#endif
//#endif
private final Map<String, Binding> bindings = new HashMap<>(); private final Map<String, Binding> bindings = new HashMap<>();
private Set<KeyBinding> onlyInReplay = new HashSet<>(); private Set<KeyBinding> onlyInReplay = new HashSet<>();
private Multimap<Integer, Supplier<Boolean>> rawHandlers = ArrayListMultimap.create(); private Multimap<Integer, Function<KeyInput, Boolean>> rawHandlers = ArrayListMultimap.create();
public Binding registerKeyBinding(String name, int keyCode, Runnable whenPressed, boolean onlyInRepay) { public Binding registerKeyBinding(String name, int keyCode, Runnable whenPressed, boolean onlyInRepay) {
Binding binding = registerKeyBinding(name, keyCode, onlyInRepay); Binding binding = registerKeyBinding(name, keyCode, onlyInRepay);
@@ -92,7 +97,7 @@ public class KeyBindingRegistry extends EventRegistrations {
return binding; return binding;
} }
public void registerRaw(int keyCode, Supplier<Boolean> whenPressed) { public void registerRaw(int keyCode, Function<KeyInput, Boolean> whenPressed) {
rawHandlers.put(keyCode, whenPressed); rawHandlers.put(keyCode, whenPressed);
} }
@@ -138,18 +143,18 @@ public class KeyBindingRegistry extends EventRegistrations {
} }
} }
{ on(KeyEventCallback.EVENT, (keyCode, scanCode, action, modifiers) -> handleRaw(keyCode, action)); } { on(KeyEventCallback.EVENT, this::handleRaw); }
private boolean handleRaw(int keyCode, int action) { private boolean handleRaw(KeyInput keyInput, int action) {
if (action != KeyEventCallback.ACTION_PRESS) return false; if (action != KeyEventCallback.ACTION_PRESS) return false;
for (final Supplier<Boolean> handler : rawHandlers.get(keyCode)) { for (final Function<KeyInput, Boolean> handler : rawHandlers.get(keyInput.key)) {
try { try {
if (handler.get()) { if (handler.apply(keyInput)) {
return true; return true;
} }
} catch (Throwable cause) { } catch (Throwable cause) {
CrashReport crashReport = CrashReport.create(cause, "Handling Raw Key Binding"); CrashReport crashReport = CrashReport.create(cause, "Handling Raw Key Binding");
CrashReportSection category = crashReport.addElement("Key Binding"); CrashReportSection category = crashReport.addElement("Key Binding");
category.add("Key Code", () -> "" + keyCode); category.add("Key Code", () -> "" + keyInput.key);
category.add("Handler", handler::toString); category.add("Handler", handler::toString);
throw new CrashException(crashReport); throw new CrashException(crashReport);
} }

View File

@@ -258,6 +258,10 @@ public class ReplayMod implements Module, Scheduler {
} }
private void printToChat(boolean warning, String message, Object... args) { private void printToChat(boolean warning, String message, Object... args) {
if (!mc.isOnThread()) {
runLater(() -> printToChat(warning, message, args));
return;
}
if (getSettingsRegistry().get(Setting.NOTIFICATIONS)) { if (getSettingsRegistry().get(Setting.NOTIFICATIONS)) {
// Some nostalgia: "§8[§6Replay Mod§8]§r Your message goes here" // Some nostalgia: "§8[§6Replay Mod§8]§r Your message goes here"
//#if MC>=10904 //#if MC>=10904

View File

@@ -1,12 +1,13 @@
package com.replaymod.core.events; package com.replaymod.core.events;
import de.johni0702.minecraft.gui.function.KeyInput;
import de.johni0702.minecraft.gui.utils.Event; import de.johni0702.minecraft.gui.utils.Event;
public interface KeyEventCallback { public interface KeyEventCallback {
Event<KeyEventCallback> EVENT = Event.create((listeners) -> Event<KeyEventCallback> EVENT = Event.create((listeners) ->
(key, scanCode, action, modifiers) -> { (keyInput, action) -> {
for (KeyEventCallback listener : listeners) { for (KeyEventCallback listener : listeners) {
if (listener.onKeyEvent(key, scanCode, action, modifiers)) { if (listener.onKeyEvent(keyInput, action)) {
return true; return true;
} }
} }
@@ -22,5 +23,5 @@ public interface KeyEventCallback {
//$$ int ACTION_PRESS = 1; //$$ int ACTION_PRESS = 1;
//#endif //#endif
boolean onKeyEvent(int key, int scanCode, int action, int modifiers); boolean onKeyEvent(KeyInput keyInput, int action);
} }

View File

@@ -8,8 +8,6 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.Queue;
//#if MC>=11800 //#if MC>=11800
//$$ import java.util.function.Supplier; //$$ import java.util.function.Supplier;
//#endif //#endif
@@ -25,6 +23,7 @@ import java.util.concurrent.CompletableFuture;
//#if MC<11400 //#if MC<11400
//$$ import net.minecraft.client.resources.IResourcePack; //$$ import net.minecraft.client.resources.IResourcePack;
//$$ import java.util.List; //$$ import java.util.List;
//$$ import java.util.Queue;
//#endif //#endif
@Mixin(MinecraftClient.class) @Mixin(MinecraftClient.class)
@@ -53,8 +52,6 @@ public interface MinecraftAccessor {
//#endif //#endif
//#if MC>=11400 //#if MC>=11400
@Accessor
Queue<Runnable> getRenderTaskQueue();
//#else //#else
//$$ @Accessor //$$ @Accessor
//$$ Queue<FutureTask<?>> getScheduledTasks(); //$$ Queue<FutureTask<?>> getScheduledTasks();

View File

@@ -2,6 +2,7 @@ package com.replaymod.core.mixin;
import com.replaymod.core.events.KeyBindingEventCallback; import com.replaymod.core.events.KeyBindingEventCallback;
import com.replaymod.core.events.KeyEventCallback; import com.replaymod.core.events.KeyEventCallback;
import de.johni0702.minecraft.gui.function.KeyInput;
import net.minecraft.client.Keyboard; import net.minecraft.client.Keyboard;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@@ -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"; 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) @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) { 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(); ci.cancel();
} }
} }
@Inject(method = "onKey", at = @At(value = "INVOKE", target = ON_KEY_PRESSED, shift = At.Shift.AFTER)) @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(); KeyBindingEventCallback.EVENT.invoker().onKeybindingEvent();
} }
} }

View File

@@ -8,6 +8,11 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
//#if MC>=12109
//$$ import net.minecraft.network.PacketApplyBatcher;
//$$ import org.spongepowered.asm.mixin.Final;
//#endif
//#if MC>=11400 //#if MC>=11400
import com.replaymod.core.events.PostRenderCallback; import com.replaymod.core.events.PostRenderCallback;
import com.replaymod.core.events.PreRenderCallback; import com.replaymod.core.events.PreRenderCallback;
@@ -42,8 +47,14 @@ public abstract class MixinMinecraft
} }
//#if MC>=11400 //#if MC>=11400
//#if MC>=12109
//$$ @Shadow @Final private PacketApplyBatcher packetApplyBatcher;
//#endif
@Override @Override
public void replayModExecuteTaskQueue() { public void replayModExecuteTaskQueue() {
//#if MC>=12109
//$$ this.packetApplyBatcher.apply();
//#endif
runTasks(); runTasks();
} }
//#endif //#endif

View File

@@ -68,6 +68,11 @@ import java.util.function.Consumer;
import static com.replaymod.core.versions.MCVer.getMinecraft; 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 //#if MC>=12100
//$$ import net.minecraft.util.crash.ReportType; //$$ import net.minecraft.util.crash.ReportType;
//#endif //#endif
@@ -229,7 +234,9 @@ public class Utils {
} }
public static boolean isCtrlDown() { 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(); return Screen.hasControlDown();
//#else //#else
//$$ return Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL); //$$ return Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL);

View File

@@ -190,6 +190,11 @@ public class LangResourcePack extends AbstractFileResourcePack {
key = String.format(FABRIC_KEY_FORMAT, key.substring(LEGACY_KEY_PREFIX.length())); key = String.format(FABRIC_KEY_FORMAT, key.substring(LEGACY_KEY_PREFIX.length()));
} }
//#endif //#endif
//#if MC>=12109
if (key.equals("replaymod.title")) {
properties.put("key.category.replaymod.general", value);
}
//#endif
properties.put(key, value); properties.put(key, value);
} }

View File

@@ -621,12 +621,10 @@ public class MCVer {
//$$ public static final int KEY_Z = org.lwjgl.input.Keyboard.KEY_Z; //$$ public static final int KEY_Z = org.lwjgl.input.Keyboard.KEY_Z;
//#endif //#endif
public static boolean hasControlDown() {
return Screen.hasControlDown();
}
public static boolean isKeyDown(int keyCode) { 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); return InputUtil.isKeyPressed(getMinecraft().getWindow().getHandle(), keyCode);
//#else //#else
//#if MC>=11400 //#if MC>=11400

View File

@@ -982,7 +982,9 @@ class Patterns {
@Pattern @Pattern
public Identifier getSkinTexture(AbstractClientPlayerEntity player) { public Identifier getSkinTexture(AbstractClientPlayerEntity player) {
//#if MC>=12002 //#if MC>=12109
//$$ return player.getSkin().body().texturePath();
//#elseif MC>=12002
//$$ return player.getSkinTextures().texture(); //$$ return player.getSkinTextures().texture();
//#else //#else
return player.getSkinTexture(); return player.getSkinTexture();

View File

@@ -5,6 +5,8 @@ import net.minecraft.client.MinecraftClient;
import net.minecraft.util.crash.CrashException; import net.minecraft.util.crash.CrashException;
import net.minecraft.util.thread.ReentrantThreadExecutor; import net.minecraft.util.thread.ReentrantThreadExecutor;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
@@ -82,10 +84,13 @@ public class SchedulerImpl implements Scheduler {
} }
} }
public final ReplayModExecutor executor = new ReplayModExecutor("Client/ReplayMod"); public final ReplayModExecutor executor = new ReplayModExecutor("Client/ReplayMod");
private final List<Runnable> delayedTasks = new ArrayList<>();
@Override @Override
public void runTasks() { public void runTasks() {
executor.runTasks(); executor.runTasks();
delayedTasks.forEach(executor::send);
delayedTasks.clear();
} }
@Override @Override
@@ -100,15 +105,8 @@ public class SchedulerImpl implements Scheduler {
} }
private void runLater(Runnable runnable, Runnable defer) { private void runLater(Runnable runnable, Runnable defer) {
if (mc.isOnThread() && inRunLater && !inRenderTaskQueue) { if (mc.isOnThread() && inRunLater) {
((MinecraftAccessor) mc).getRenderTaskQueue().offer(() -> { delayedTasks.add(defer);
inRenderTaskQueue = true;
try {
defer.run();
} finally {
inRenderTaskQueue = false;
}
});
} else { } else {
executor.send(() -> { executor.send(() -> {
inRunLater = true; inRunLater = true;

View File

@@ -85,8 +85,8 @@ public class HotkeyButtons extends EventRegistrations implements Extra {
super.draw(renderer, size, renderInfo); super.draw(renderer, size, renderInfo);
} }
}.onClick(() -> { }.onClick(click -> {
if (keyBinding.supportsAutoActivation() && Screen.hasControlDown()) { if (keyBinding.supportsAutoActivation() && click.hasCtrl()) {
keyBinding.setAutoActivating(!keyBinding.isAutoActivating()); keyBinding.setAutoActivating(!keyBinding.isAutoActivating());
} else { } else {
keyBinding.trigger(); keyBinding.trigger();

View File

@@ -49,13 +49,13 @@ public class GuiCreateScreenshot extends GuiRenderSettings implements Loadable {
exportArguments.setText(""); // To disable any preset-based checks exportArguments.setText(""); // To disable any preset-based checks
buttonPanel.removeElement(queueButton); 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 // Closing this GUI ensures that settings are saved
close(); close();
mod.runLater(() -> { mod.runLater(() -> {
try { try {
RenderSettings settings = save(false); RenderSettings settings = save(false, click.hasCtrl());
boolean success = new ScreenshotRenderer(settings).renderScreenshot(); boolean success = new ScreenshotRenderer(settings).renderScreenshot();
if (success) { if (success) {

View File

@@ -13,6 +13,7 @@ import de.johni0702.minecraft.gui.element.GuiImage;
import de.johni0702.minecraft.gui.element.GuiLabel; import de.johni0702.minecraft.gui.element.GuiLabel;
import de.johni0702.minecraft.gui.element.GuiTooltip; import de.johni0702.minecraft.gui.element.GuiTooltip;
import de.johni0702.minecraft.gui.element.IGuiCheckbox; 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.function.Closeable;
import de.johni0702.minecraft.gui.layout.CustomLayout; import de.johni0702.minecraft.gui.layout.CustomLayout;
import de.johni0702.minecraft.gui.layout.HorizontalLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout;
@@ -52,13 +53,13 @@ public class PlayerOverviewGui extends GuiScreen implements Closeable {
.setI18nLabel("replaymod.gui.playeroverview.remembersettings"); .setI18nLabel("replaymod.gui.playeroverview.remembersettings");
public final GuiCheckbox checkAll = new GuiCheckbox(contentPanel){ public final GuiCheckbox checkAll = new GuiCheckbox(contentPanel){
@Override @Override
public void onClick() { public void onClick(Click click) {
playersScrollable.invokeAll(IGuiCheckbox.class, e -> e.setChecked(true)); playersScrollable.invokeAll(IGuiCheckbox.class, e -> e.setChecked(true));
} }
}.setLabel("").setChecked(true).setTooltip(new GuiTooltip().setI18nText("replaymod.gui.playeroverview.showall")); }.setLabel("").setChecked(true).setTooltip(new GuiTooltip().setI18nText("replaymod.gui.playeroverview.showall"));
public final GuiCheckbox uncheckAll = new GuiCheckbox(contentPanel){ public final GuiCheckbox uncheckAll = new GuiCheckbox(contentPanel){
@Override @Override
public void onClick() { public void onClick(Click click) {
playersScrollable.invokeAll(IGuiCheckbox.class, e -> e.setChecked(false)); playersScrollable.invokeAll(IGuiCheckbox.class, e -> e.setChecked(false));
} }
}.setLabel("").setChecked(false).setTooltip(new GuiTooltip().setI18nText("replaymod.gui.playeroverview.hideall")); }.setLabel("").setChecked(false).setTooltip(new GuiTooltip().setI18nText("replaymod.gui.playeroverview.hideall"));

View File

@@ -1,7 +1,5 @@
package com.replaymod.pathing.gui; 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.google.common.util.concurrent.SettableFuture;
import com.replaymod.core.ReplayMod; import com.replaymod.core.ReplayMod;
import com.replaymod.core.utils.Utils; 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.GuiElement;
import de.johni0702.minecraft.gui.element.GuiLabel; import de.johni0702.minecraft.gui.element.GuiLabel;
import de.johni0702.minecraft.gui.element.GuiTextField; 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.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.CustomLayout;
import de.johni0702.minecraft.gui.layout.GridLayout; import de.johni0702.minecraft.gui.layout.GridLayout;
import de.johni0702.minecraft.gui.layout.VerticalLayout; 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.Consumer;
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension; import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension; import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
import de.johni0702.minecraft.gui.utils.lwjgl.ReadablePoint;
import net.minecraft.util.crash.CrashReport; import net.minecraft.util.crash.CrashReport;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; 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}. * 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(); private static final Logger LOGGER = LogManager.getLogger();
public final GuiPanel contentPanel = new GuiPanel(this).setBackgroundColor(Colors.DARK_TRANSPARENT); public final GuiPanel contentPanel = new GuiPanel(this).setBackgroundColor(Colors.DARK_TRANSPARENT);
@@ -90,7 +89,7 @@ public class GuiKeyframeRepository extends GuiScreen implements Closeable, Typea
@Override @Override
public void run() { public void run() {
if (popup.getYesButton().isEnabled()) { if (popup.getYesButton().isEnabled()) {
popup.getYesButton().onClick(); popup.getYesButton().onClick(new Click(-1, -1, 0, 0));
} }
} }
}).onTextChanged(new Consumer<String>() { }).onTextChanged(new Consumer<String>() {
@@ -138,7 +137,7 @@ public class GuiKeyframeRepository extends GuiScreen implements Closeable, Typea
@Override @Override
public void run() { public void run() {
if (popup.getYesButton().isEnabled()) { if (popup.getYesButton().isEnabled()) {
popup.getYesButton().onClick(); popup.getYesButton().onClick(new Click(-1, -1, 0, 0));
} }
} }
}).onTextChanged(new Consumer<String>() { }).onTextChanged(new Consumer<String>() {
@@ -244,9 +243,9 @@ public class GuiKeyframeRepository extends GuiScreen implements Closeable, Typea
GuiRenderSettings settingsGui = queue.addJob(timeline); GuiRenderSettings settingsGui = queue.addJob(timeline);
settingsGui.buttonPanel.removeElement(settingsGui.renderButton); settingsGui.buttonPanel.removeElement(settingsGui.renderButton);
settingsGui.setOutputFileBaseName(name); settingsGui.setOutputFileBaseName(name);
Runnable orgOnClick = settingsGui.queueButton.getOnClick(); Consumer<Click> orgOnClick = settingsGui.queueButton.getOnClick();
settingsGui.queueButton.onClick(() -> { settingsGui.queueButton.onClick(click -> {
orgOnClick.run(); orgOnClick.consume(click);
this.run(); this.run();
}); });
settingsGui.open(); settingsGui.open();
@@ -348,9 +347,9 @@ public class GuiKeyframeRepository extends GuiScreen implements Closeable, Typea
} }
@Override @Override
public boolean typeKey(ReadablePoint mousePosition, int keyCode, char keyChar, boolean ctrlDown, boolean shiftDown) { public boolean handleKey(KeyInput keyInput) {
if (MCVer.Keyboard.hasControlDown()) { if (keyInput.hasCtrl()) {
switch (keyCode) { switch (keyInput.key) {
case MCVer.Keyboard.KEY_A: case MCVer.Keyboard.KEY_A:
if (selectedEntries.size() < timelines.size()) { if (selectedEntries.size() < timelines.size()) {
for (GuiElement<?> child : list.getListPanel().getChildren()) { for (GuiElement<?> child : list.getListPanel().getChildren()) {
@@ -364,10 +363,10 @@ public class GuiKeyframeRepository extends GuiScreen implements Closeable, Typea
updateButtons(); updateButtons();
return true; return true;
case MCVer.Keyboard.KEY_C: case MCVer.Keyboard.KEY_C:
copyButton.onClick(); copyButton.onClick(new Click(-1, -1, 0, 0));
return true; return true;
case MCVer.Keyboard.KEY_V: case MCVer.Keyboard.KEY_V:
pasteButton.onClick(); pasteButton.onClick(new Click(-1, -1, 0, 0));
return true; return true;
} }
} }
@@ -396,8 +395,8 @@ public class GuiKeyframeRepository extends GuiScreen implements Closeable, Typea
} }
@Override @Override
protected void onClick() { protected void onClick(Click click) {
if (!MCVer.Keyboard.hasControlDown()) { if (!click.hasCtrl()) {
selectedEntries.clear(); selectedEntries.clear();
} }
if (selectedEntries.contains(this)) { if (selectedEntries.contains(this)) {

View File

@@ -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 // 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. // inbound packets which may rely on the injected packet would behave incorrectly when played back.
if (!mc.isOnThread()) { 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<? extends net.minecraft.network.packet.Packet<net.minecraft.network.listener.PacketListener>> getPacketType() {
//$$ return null;
//$$ }
//$$ @Override
//$$ public void apply(net.minecraft.network.listener.PacketListener listener) {
//$$ save(packet);
//$$ }
//$$ });
//#else
mc.send(() -> save(packet)); mc.send(() -> save(packet));
//#endif
return; return;
} }
try { try {

View File

@@ -26,7 +26,9 @@ import de.johni0702.minecraft.gui.element.GuiButton;
import de.johni0702.minecraft.gui.element.GuiElement; import de.johni0702.minecraft.gui.element.GuiElement;
import de.johni0702.minecraft.gui.element.GuiLabel; import de.johni0702.minecraft.gui.element.GuiLabel;
import de.johni0702.minecraft.gui.element.GuiTooltip; 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.CustomLayout;
import de.johni0702.minecraft.gui.layout.GridLayout; import de.johni0702.minecraft.gui.layout.GridLayout;
import de.johni0702.minecraft.gui.layout.HorizontalLayout; 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.Colors;
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension; import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension; import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
import de.johni0702.minecraft.gui.utils.lwjgl.ReadablePoint;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.util.crash.CrashReport; import net.minecraft.util.crash.CrashReport;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
@@ -59,7 +60,7 @@ import net.minecraft.text.TranslatableText;
//$$ import com.replaymod.replaystudio.util.I18n; //$$ import com.replaymod.replaystudio.util.I18n;
//#endif //#endif
public class GuiRenderQueue extends AbstractGuiPopup<GuiRenderQueue> implements Typeable { public class GuiRenderQueue extends AbstractGuiPopup<GuiRenderQueue> implements KeyHandler {
private final GuiLabel title = new GuiLabel().setI18nText("replaymod.gui.renderqueue.title").setColor(Colors.BLACK); 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 GuiVerticalList list = new GuiVerticalList().setDrawShadow(true).setDrawSlider(true);
private final GuiButton addButton = new GuiButton().setI18nLabel("replaymod.gui.renderqueue.add").setSize(150, 20); private final GuiButton addButton = new GuiButton().setI18nLabel("replaymod.gui.renderqueue.add").setSize(150, 20);
@@ -272,8 +273,8 @@ public class GuiRenderQueue extends AbstractGuiPopup<GuiRenderQueue> implements
if (!jobs.isEmpty()) { if (!jobs.isEmpty()) {
buttonPanel.removeElement(renderButton); buttonPanel.removeElement(renderButton);
} }
queueButton.onClick(() -> { queueButton.onClick(click -> {
RenderSettings settings = save(false); RenderSettings settings = save(false, click.hasCtrl());
RenderJob newJob = new RenderJob(); RenderJob newJob = new RenderJob();
newJob.setSettings(settings); newJob.setSettings(settings);
@@ -342,8 +343,8 @@ public class GuiRenderQueue extends AbstractGuiPopup<GuiRenderQueue> implements
} }
@Override @Override
public boolean typeKey(ReadablePoint mousePosition, int keyCode, char keyChar, boolean ctrlDown, boolean shiftDown) { public boolean handleKey(KeyInput keyInput) {
if (MCVer.Keyboard.hasControlDown() && keyCode == MCVer.Keyboard.KEY_A) { if (keyInput.hasCtrl() && keyInput.key == MCVer.Keyboard.KEY_A) {
if (selectedEntries.size() < list.getListPanel().getChildren().size()) { if (selectedEntries.size() < list.getListPanel().getChildren().size()) {
for (GuiElement<?> child : list.getListPanel().getChildren()) { for (GuiElement<?> child : list.getListPanel().getChildren()) {
if (child instanceof Entry) { if (child instanceof Entry) {
@@ -381,8 +382,8 @@ public class GuiRenderQueue extends AbstractGuiPopup<GuiRenderQueue> implements
} }
@Override @Override
protected void onClick() { protected void onClick(Click click) {
if (!MCVer.Keyboard.hasControlDown()) { if (!click.hasCtrl()) {
selectedEntries.clear(); selectedEntries.clear();
} }
if (selectedEntries.contains(this)) { if (selectedEntries.contains(this)) {
@@ -410,8 +411,8 @@ public class GuiRenderQueue extends AbstractGuiPopup<GuiRenderQueue> implements
public GuiRenderSettings edit() { public GuiRenderSettings edit() {
GuiRenderSettings gui = new GuiRenderSettings(container, replayHandler, job.getTimeline()); GuiRenderSettings gui = new GuiRenderSettings(container, replayHandler, job.getTimeline());
gui.buttonPanel.removeElement(gui.renderButton); gui.buttonPanel.removeElement(gui.renderButton);
gui.queueButton.setI18nLabel("replaymod.gui.done").onClick(() -> { gui.queueButton.setI18nLabel("replaymod.gui.done").onClick(click -> {
job.setSettings(gui.save(false)); job.setSettings(gui.save(false, click.hasCtrl()));
label.setText(job.getName()); label.setText(job.getName());
mod.saveRenderQueue(); mod.saveRenderQueue();
gui.close(); gui.close();

View File

@@ -18,6 +18,7 @@ import de.johni0702.minecraft.gui.container.GuiVerticalList;
import de.johni0702.minecraft.gui.element.*; import de.johni0702.minecraft.gui.element.*;
import de.johni0702.minecraft.gui.element.advanced.GuiColorPicker; import de.johni0702.minecraft.gui.element.advanced.GuiColorPicker;
import de.johni0702.minecraft.gui.element.advanced.GuiDropdownMenu; 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.CustomLayout;
import de.johni0702.minecraft.gui.layout.GridLayout; import de.johni0702.minecraft.gui.layout.GridLayout;
import de.johni0702.minecraft.gui.layout.HorizontalLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout;
@@ -232,13 +233,13 @@ public class GuiRenderSettings extends AbstractGuiPopup<GuiRenderSettings> {
public final GuiButton queueButton = new GuiButton(buttonPanel) public final GuiButton queueButton = new GuiButton(buttonPanel)
.setSize(100, 20) .setSize(100, 20)
.setI18nLabel("replaymod.gui.rendersettings.addtoqueue"); .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 @Override
public void run() { public void run() {
// Closing this GUI ensures that settings are saved // Closing this GUI ensures that settings are saved
close(); close();
try { try {
VideoRenderer videoRenderer = new VideoRenderer(save(false), replayHandler, timeline); VideoRenderer videoRenderer = new VideoRenderer(save(false, click.hasCtrl()), replayHandler, timeline);
videoRenderer.renderVideo(); videoRenderer.renderVideo();
} catch (FFmpegWriter.NoFFmpegException e) { } catch (FFmpegWriter.NoFFmpegException e) {
LOGGER.error("Rendering video:", e); LOGGER.error("Rendering video:", e);
@@ -248,7 +249,7 @@ public class GuiRenderSettings extends AbstractGuiPopup<GuiRenderSettings> {
// Update settings with fixed ffmpeg arguments // Update settings with fixed ffmpeg arguments
exportArguments.setText(newSettings.getExportArguments()); exportArguments.setText(newSettings.getExportArguments());
// Restart rendering, this will also save the changed ffmpeg arguments // Restart rendering, this will also save the changed ffmpeg arguments
renderButton.onClick(); renderButton.onClick(click);
}); });
} catch (Throwable t) { } catch (Throwable t) {
error(LOGGER, GuiRenderSettings.this, CrashReport.create(t, "Rendering video"), () -> {}); error(LOGGER, GuiRenderSettings.this, CrashReport.create(t, "Rendering video"), () -> {});
@@ -349,7 +350,7 @@ public class GuiRenderSettings extends AbstractGuiPopup<GuiRenderSettings> {
videoHeight.setTextColor(Colors.RED); videoHeight.setTextColor(Colors.RED);
} }
String[] compatError = VideoRenderer.checkCompat(save(false)); String[] compatError = VideoRenderer.checkCompat(save(false, false));
if (resolutionError != null) { if (resolutionError != null) {
renderButton.setDisabled().setTooltip(new GuiTooltip().setI18nText(resolutionError)); renderButton.setDisabled().setTooltip(new GuiTooltip().setI18nText(resolutionError));
} else if (compatError != null) { } else if (compatError != null) {
@@ -552,7 +553,7 @@ public class GuiRenderSettings extends AbstractGuiPopup<GuiRenderSettings> {
updateInputs(); updateInputs();
} }
public RenderSettings save(boolean serialize) { public RenderSettings save(boolean serialize, boolean highPerformance) {
int sphericalFov = MIN_SPHERICAL_FOV + sphericalFovSlider.getValue() * SPHERICAL_FOV_STEP_SIZE; int sphericalFov = MIN_SPHERICAL_FOV + sphericalFovSlider.getValue() * SPHERICAL_FOV_STEP_SIZE;
return new RenderSettings( return new RenderSettings(
@@ -576,7 +577,7 @@ public class GuiRenderSettings extends AbstractGuiPopup<GuiRenderSettings> {
serialize || antiAliasingDropdown.isEnabled() ? antiAliasingDropdown.getSelectedValue() : RenderSettings.AntiAliasing.NONE, serialize || antiAliasingDropdown.isEnabled() ? antiAliasingDropdown.getSelectedValue() : RenderSettings.AntiAliasing.NONE,
exportCommand.getText(), exportCommand.getText(),
exportArguments.getText(), exportArguments.getText(),
net.minecraft.client.gui.screen.Screen.hasControlDown() highPerformance
); );
} }
@@ -623,7 +624,7 @@ public class GuiRenderSettings extends AbstractGuiPopup<GuiRenderSettings> {
@Override @Override
public void close() { public void close() {
RenderSettings settings = save(true); RenderSettings settings = save(true, false);
String json = new Gson().toJson(settings); String json = new Gson().toJson(settings);
try { try {
Files.write(getSettingsPath(), json.getBytes(StandardCharsets.UTF_8)); Files.write(getSettingsPath(), json.getBytes(StandardCharsets.UTF_8));

View File

@@ -11,6 +11,7 @@ import de.johni0702.minecraft.gui.element.GuiButton;
import de.johni0702.minecraft.gui.element.GuiCheckbox; import de.johni0702.minecraft.gui.element.GuiCheckbox;
import de.johni0702.minecraft.gui.element.GuiLabel; import de.johni0702.minecraft.gui.element.GuiLabel;
import de.johni0702.minecraft.gui.element.advanced.GuiProgressBar; 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.function.Tickable;
import de.johni0702.minecraft.gui.layout.CustomLayout; import de.johni0702.minecraft.gui.layout.CustomLayout;
import de.johni0702.minecraft.gui.layout.HorizontalLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout;
@@ -67,8 +68,8 @@ public class GuiVideoRenderer extends GuiScreen implements Tickable {
boolean waitingForConfirmation; boolean waitingForConfirmation;
@Override @Override
public boolean mouseClick(ReadablePoint position, int button) { public boolean mouseClick(Click click) {
boolean result = super.mouseClick(position, button); boolean result = super.mouseClick(click);
if (waitingForConfirmation && !result) { if (waitingForConfirmation && !result) {
setI18nLabel("replaymod.gui.rendering.cancel"); setI18nLabel("replaymod.gui.rendering.cancel");
waitingForConfirmation = false; waitingForConfirmation = false;
@@ -77,8 +78,8 @@ public class GuiVideoRenderer extends GuiScreen implements Tickable {
} }
@Override @Override
public void onClick() { public void onClick(Click click) {
super.onClick(); super.onClick(click);
if (!waitingForConfirmation) { if (!waitingForConfirmation) {
setI18nLabel("replaymod.gui.rendering.cancel.callback"); setI18nLabel("replaymod.gui.rendering.cancel.callback");
waitingForConfirmation = true; waitingForConfirmation = true;

View File

@@ -40,6 +40,10 @@ import net.minecraft.util.crash.CrashException;
import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundCategory;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
//#if MC>=12109
//$$ import net.minecraft.client.gui.screen.Overlay;
//#endif
//#if MC>=12106 //#if MC>=12106
//$$ import com.replaymod.render.mixin.GameRendererAccessor; //$$ import com.replaymod.render.mixin.GameRendererAccessor;
//$$ import net.minecraft.client.gui.render.GuiRenderer; //$$ import net.minecraft.client.gui.render.GuiRenderer;
@@ -335,13 +339,18 @@ public class VideoRenderer implements RenderInfo {
//$$ Display.setResizable(false); //$$ Display.setResizable(false);
//$$ } //$$ }
//#endif //#endif
//#if MC>=12109
//$$ if (mc.debugHudEntryList.isF3Enabled()) {
//$$ mc.debugHudEntryList.setF3Enabled(false);
//#else
if (mc.options.debugEnabled) { if (mc.options.debugEnabled) {
debugInfoWasShown = true;
//#if MC>=12002 //#if MC>=12002
//$$ mc.getDebugHud().toggleDebugHud(); //$$ mc.getDebugHud().toggleDebugHud();
//#else //#else
mc.options.debugEnabled = false; mc.options.debugEnabled = false;
//#endif //#endif
//#endif
debugInfoWasShown = true;
} }
//#if MC>=11400 //#if MC>=11400
if (mc.mouse.isCursorLocked()) { if (mc.mouse.isCursorLocked()) {
@@ -406,7 +415,9 @@ public class VideoRenderer implements RenderInfo {
//$$ } //$$ }
//#endif //#endif
if (debugInfoWasShown) { if (debugInfoWasShown) {
//#if MC>=12002 //#if MC>=12109
//$$ mc.debugHudEntryList.setF3Enabled(true);
//#elseif MC>=12002
//$$ mc.getDebugHud().toggleDebugHud(); //$$ mc.getDebugHud().toggleDebugHud();
//#else //#else
mc.options.debugEnabled = true; mc.options.debugEnabled = true;
@@ -453,6 +464,15 @@ public class VideoRenderer implements RenderInfo {
while (mc.getOverlay() != null) { while (mc.getOverlay() != null) {
drawGui(); drawGui();
((MinecraftMethodAccessor) mc).replayModExecuteTaskQueue(); ((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<Void> resourceReloadFuture = ((MinecraftAccessor) mc).getResourceReloadFuture(); CompletableFuture<Void> resourceReloadFuture = ((MinecraftAccessor) mc).getResourceReloadFuture();

View File

@@ -23,7 +23,6 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInboundHandlerAdapter;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.OtherClientPlayerEntity; import net.minecraft.client.network.OtherClientPlayerEntity;
import net.minecraft.client.gui.screen.DownloadingTerrainScreen;
import net.minecraft.client.gui.screen.NoticeScreen; import net.minecraft.client.gui.screen.NoticeScreen;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity; 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.FileUtils;
import org.apache.commons.io.IOUtils; 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 //#if MC>=12105
//#else //#else
import net.minecraft.network.packet.s2c.play.ExperienceOrbSpawnS2CPacket; import net.minecraft.network.packet.s2c.play.ExperienceOrbSpawnS2CPacket;
@@ -853,7 +863,11 @@ public class FullReplaySender extends ChannelInboundHandlerAdapter implements Re
if(!hasWorldLoaded) hasWorldLoaded = true; if(!hasWorldLoaded) hasWorldLoaded = true;
ReplayMod.instance.runLater(() -> { ReplayMod.instance.runLater(() -> {
//#if MC>=12109
//$$ if (mc.currentScreen instanceof LevelLoadingScreen) {
//#else
if (mc.currentScreen instanceof DownloadingTerrainScreen) { if (mc.currentScreen instanceof DownloadingTerrainScreen) {
//#endif
// Close the world loading screen manually in case we swallow the packet // Close the world loading screen manually in case we swallow the packet
mc.openScreen(null); mc.openScreen(null);
} }
@@ -969,7 +983,7 @@ public class FullReplaySender extends ChannelInboundHandlerAdapter implements Re
return processPacketAsync(p); return processPacketAsync(p);
} else { } else {
Packet fp = p; Packet fp = p;
mc.send(() -> processPacketSync(fp)); schedulePacketHandler(() -> processPacketSync(fp));
return p; return p;
} }
} }
@@ -1383,7 +1397,18 @@ public class FullReplaySender extends ChannelInboundHandlerAdapter implements Re
if (mc.isOnThread()) { if (mc.isOnThread()) {
runnable.run(); runnable.run();
} else { } 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<? extends Packet<PacketListener>> getPacketType() {
//$$ return null;
//$$ }
//$$ @Override
//$$ public void apply(PacketListener listener) {
//$$ runnable.run();
//$$ }
//$$ });
//#elseif MC>=11400
mc.execute(runnable); mc.execute(runnable);
//#else //#else
//$$ mc.addScheduledTask(runnable); //$$ mc.addScheduledTask(runnable);

View File

@@ -7,9 +7,17 @@ import com.replaymod.replay.camera.CameraEntity;
import de.johni0702.minecraft.gui.versions.ScreenExt; import de.johni0702.minecraft.gui.versions.ScreenExt;
import net.minecraft.client.MinecraftClient; 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 //#if MC>=11802
//$$ import net.minecraft.client.gui.screen.DownloadingTerrainScreen; //$$ import net.minecraft.client.gui.screen.DownloadingTerrainScreen;
//#endif //#endif
//#endif
//#if MC>=11400 //#if MC>=11400
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
@@ -92,11 +100,23 @@ public class InputReplayTimer {
//#if MC>=11802 //#if MC>=11802
//$$ // As of 1.18.2, this screen always stays open for at least two seconds, and requires ticking to close. //$$ // 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). //$$ // 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) { //$$ if (mc.currentScreen instanceof DownloadingTerrainScreen) {
//#endif
//$$ mc.currentScreen.close(); //$$ mc.currentScreen.close();
//$$ } //$$ }
//#endif //#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
} }
} }

View File

@@ -31,7 +31,6 @@ import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise; import io.netty.channel.ChannelPromise;
import io.netty.channel.embedded.EmbeddedChannel; import io.netty.channel.embedded.EmbeddedChannel;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.DownloadingTerrainScreen;
import net.minecraft.client.network.ClientLoginNetworkHandler; import net.minecraft.client.network.ClientLoginNetworkHandler;
import net.minecraft.client.util.Window; import net.minecraft.client.util.Window;
import net.minecraft.network.DecoderHandler; import net.minecraft.network.DecoderHandler;
@@ -45,6 +44,12 @@ import net.minecraft.network.ClientConnection;
import java.io.IOException; import java.io.IOException;
import java.util.*; 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 //#if MC>=12106
//$$ import com.replaymod.render.mixin.GameRendererAccessor; //$$ import com.replaymod.render.mixin.GameRendererAccessor;
//$$ import net.minecraft.client.gui.render.state.GuiRenderState; //$$ 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. // We don't send any packets (there is no server to receive them), so we need to switch manually.
//#if MC>=12006 //#if MC>=12006
//$$ networkManager.transitionInbound(LoginStates.S2C, new ClientLoginNetworkHandler( //$$ 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); //$$ networkManager.transitionOutbound(LoginStates.C2S);
//#else //#else
@@ -697,7 +706,11 @@ public class ReplayHandler {
do { do {
replaySender.sendPacketsTill(targetTime); replaySender.sendPacketsTill(targetTime);
targetTime += 500; targetTime += 500;
//#if MC>=12109
//$$ } while (mc.player == null || mc.currentScreen instanceof LevelLoadingScreen);
//#else
} while (mc.player == null || mc.currentScreen instanceof DownloadingTerrainScreen); } while (mc.player == null || mc.currentScreen instanceof DownloadingTerrainScreen);
//#endif
replaySender.setAsyncMode(true); replaySender.setAsyncMode(true);
for (int i = 0; i < Math.min(diff / 50, 3); i++) { for (int i = 0; i < Math.min(diff / 50, 3); i++) {
@@ -852,7 +865,11 @@ public class ReplayHandler {
do { do {
replaySender.sendPacketsTill(targetTime); replaySender.sendPacketsTill(targetTime);
targetTime += 500; targetTime += 500;
//#if MC>=12109
//$$ } while (mc.player == null || mc.currentScreen instanceof LevelLoadingScreen);
//#else
} while (mc.player == null || mc.currentScreen instanceof DownloadingTerrainScreen); } while (mc.player == null || mc.currentScreen instanceof DownloadingTerrainScreen);
//#endif
replaySender.setAsyncMode(true); replaySender.setAsyncMode(true);
replaySender.setReplaySpeed(0); replaySender.setReplaySpeed(0);

View File

@@ -19,6 +19,7 @@ import com.replaymod.replay.gui.screen.GuiModCompatWarning;
import com.replaymod.replay.handler.GuiHandler; import com.replaymod.replay.handler.GuiHandler;
import com.replaymod.replaystudio.data.Marker; import com.replaymod.replaystudio.data.Marker;
import com.replaymod.replaystudio.replay.ReplayFile; import com.replaymod.replaystudio.replay.ReplayFile;
import de.johni0702.minecraft.gui.function.Click;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.options.KeyBinding; import net.minecraft.client.options.KeyBinding;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
@@ -116,7 +117,7 @@ public class ReplayModReplay implements Module {
@Override @Override
public void run() { public void run() {
if (replayHandler != null) { if (replayHandler != null) {
replayHandler.getOverlay().playPauseButton.onClick(); replayHandler.getOverlay().playPauseButton.onClick(new Click(-1, -1, 0, 0));
} }
} }
}, true); }, true);

View File

@@ -30,6 +30,12 @@ import net.minecraft.item.ItemStack;
import net.minecraft.stat.StatHandler; import net.minecraft.stat.StatHandler;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.Box; 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 //#if MC>=12106
//$$ import net.minecraft.util.PlayerInput; //$$ import net.minecraft.util.PlayerInput;
@@ -322,15 +328,18 @@ public class CameraEntity
// This is important if the spectated player respawns as their // This is important if the spectated player respawns as their
// entity is recreated and we have to spectate a new entity // entity is recreated and we have to spectate a new entity
UUID spectating = ReplayModReplay.instance.getReplayHandler().getSpectatedUUID(); 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 if (spectating != null && (view.getUuid() != spectating
|| view.world != this.world) || viewWorld != cameraWorld)
|| this.world.getEntityById(view.getEntityId()) != view) { || cameraWorld.getEntityById(view.getEntityId()) != view) {
if (spectating == null) { if (spectating == null) {
// Entity (non-player) died, stop spectating // Entity (non-player) died, stop spectating
ReplayModReplay.instance.getReplayHandler().spectateEntity(this); ReplayModReplay.instance.getReplayHandler().spectateEntity(this);
return; return;
} }
view = this.world.getPlayerByUuid(spectating); view = cameraWorld.getPlayerByUuid(spectating);
if (view != null) { if (view != null) {
this.client.setCameraEntity(view); this.client.setCameraEntity(view);
} else { } else {
@@ -502,7 +511,16 @@ public class CameraEntity
return super.isInvisible(); 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 //$$ @Override
//$$ public SkinTextures getSkinTextures() { //$$ public SkinTextures getSkinTextures() {
//$$ Entity view = this.client.getCameraEntity(); //$$ Entity view = this.client.getCameraEntity();
@@ -533,7 +551,16 @@ public class CameraEntity
//#endif //#endif
//#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 @Override
public boolean isPartVisible(PlayerModelPart modelPart) { public boolean isPartVisible(PlayerModelPart modelPart) {
Entity view = this.client.getCameraEntity(); Entity view = this.client.getCameraEntity();

View File

@@ -4,19 +4,19 @@ import com.google.common.base.Strings;
import de.johni0702.minecraft.gui.container.GuiContainer; import de.johni0702.minecraft.gui.container.GuiContainer;
import de.johni0702.minecraft.gui.container.GuiPanel; import de.johni0702.minecraft.gui.container.GuiPanel;
import de.johni0702.minecraft.gui.element.*; 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.GridLayout;
import de.johni0702.minecraft.gui.layout.HorizontalLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout;
import de.johni0702.minecraft.gui.layout.VerticalLayout; import de.johni0702.minecraft.gui.layout.VerticalLayout;
import de.johni0702.minecraft.gui.popup.AbstractGuiPopup; import de.johni0702.minecraft.gui.popup.AbstractGuiPopup;
import de.johni0702.minecraft.gui.utils.Colors; import de.johni0702.minecraft.gui.utils.Colors;
import com.replaymod.core.versions.MCVer.Keyboard;
import com.replaymod.replaystudio.data.Marker; import com.replaymod.replaystudio.data.Marker;
import de.johni0702.minecraft.gui.utils.lwjgl.ReadablePoint;
import java.util.function.Consumer; import java.util.function.Consumer;
public class GuiEditMarkerPopup extends AbstractGuiPopup<GuiEditMarkerPopup> implements Typeable { public class GuiEditMarkerPopup extends AbstractGuiPopup<GuiEditMarkerPopup> implements KeyHandler {
private static GuiNumberField newGuiNumberField() { private static GuiNumberField newGuiNumberField() {
return new GuiNumberField().setSize(150, 20).setValidateOnFocusChange(true); return new GuiNumberField().setSize(150, 20).setValidateOnFocusChange(true);
} }
@@ -116,9 +116,9 @@ public class GuiEditMarkerPopup extends AbstractGuiPopup<GuiEditMarkerPopup> imp
} }
@Override @Override
public boolean typeKey(ReadablePoint mousePosition, int keyCode, char keyChar, boolean ctrlDown, boolean shiftDown) { public boolean handleKey(KeyInput keyInput) {
if (keyCode == Keyboard.KEY_ESCAPE) { if (keyInput.isEscape()) {
cancelButton.onClick(); cancelButton.onClick(new Click(-1, -1, 0, keyInput.modifiers));
return true; return true;
} }
return false; return false;

View File

@@ -10,8 +10,10 @@ import com.replaymod.replaystudio.util.Location;
import de.johni0702.minecraft.gui.GuiRenderer; import de.johni0702.minecraft.gui.GuiRenderer;
import de.johni0702.minecraft.gui.RenderInfo; import de.johni0702.minecraft.gui.RenderInfo;
import de.johni0702.minecraft.gui.element.advanced.AbstractGuiTimeline; 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.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.Point;
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension; import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
import de.johni0702.minecraft.gui.utils.lwjgl.ReadablePoint; 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; import static de.johni0702.minecraft.gui.utils.Utils.clamp;
public class GuiMarkerTimeline extends AbstractGuiTimeline<GuiMarkerTimeline> implements Draggable, Typeable { public class GuiMarkerTimeline extends AbstractGuiTimeline<GuiMarkerTimeline> implements Draggable, KeyHandler {
protected static final int TEXTURE_MARKER_X = 109; protected static final int TEXTURE_MARKER_X = 109;
protected static final int TEXTURE_MARKER_Y = 20; protected static final int TEXTURE_MARKER_Y = 20;
protected static final int TEXTURE_MARKER_SELECTED_X = 114; protected static final int TEXTURE_MARKER_SELECTED_X = 114;
@@ -149,15 +151,15 @@ public class GuiMarkerTimeline extends AbstractGuiTimeline<GuiMarkerTimeline> im
} }
@Override @Override
public boolean mouseClick(ReadablePoint position, int button) { public boolean mouseClick(Click click) {
Marker marker = getMarkerAt(position.getX(), position.getY()); Marker marker = getMarkerAt(click.x, click.y);
if (marker != null) { if (marker != null) {
if (button == 0) { // Left click if (click.button == 0) { // Left click
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
selectedMarker = marker; selectedMarker = marker;
if (Math.abs(lastClickTime - now) > 500) { // Single click if (Math.abs(lastClickTime - now) > 500) { // Single click
draggingStartX = position.getX(); draggingStartX = click.x;
draggingTimeDelta = marker.getTime() - getTimeAt(position.getX(), position.getY()); draggingTimeDelta = marker.getTime() - getTimeAt(click.x, click.y);
} else { // Double click } else { // Double click
new GuiEditMarkerPopup(getContainer(), marker, (updatedMarker) -> { new GuiEditMarkerPopup(getContainer(), marker, (updatedMarker) -> {
markers.remove(marker); markers.remove(marker);
@@ -166,7 +168,7 @@ public class GuiMarkerTimeline extends AbstractGuiTimeline<GuiMarkerTimeline> im
}).open(); }).open();
} }
lastClickTime = now; lastClickTime = now;
} else if (button == 1) { // Right click } else if (click.button == 1) { // Right click
selectedMarker = null; selectedMarker = null;
if (replayHandler != null) { if (replayHandler != null) {
CameraEntity cameraEntity = replayHandler.getCameraEntity(); CameraEntity cameraEntity = replayHandler.getCameraEntity();
@@ -185,18 +187,18 @@ public class GuiMarkerTimeline extends AbstractGuiTimeline<GuiMarkerTimeline> im
} else { } else {
selectedMarker = null; selectedMarker = null;
} }
return super.mouseClick(position, button); return super.mouseClick(click);
} }
@Override @Override
public boolean mouseDrag(ReadablePoint position, int button, long timeSinceLastCall) { public boolean mouseDrag(Click click) {
if (selectedMarker != null) { if (selectedMarker != null) {
int diff = position.getX() - draggingStartX; int diff = click.y - draggingStartX;
if (Math.abs(diff) > MARKER_SIZE) { if (Math.abs(diff) > MARKER_SIZE) {
dragging = true; dragging = true;
} }
if (dragging) { if (dragging) {
int timeAt = getTimeAt(position.getX(), position.getY()); int timeAt = getTimeAt(click.x, click.y);
if (timeAt != -1) { if (timeAt != -1) {
selectedMarker.setTime(draggingTimeDelta + timeAt); selectedMarker.setTime(draggingTimeDelta + timeAt);
} }
@@ -207,9 +209,9 @@ public class GuiMarkerTimeline extends AbstractGuiTimeline<GuiMarkerTimeline> im
} }
@Override @Override
public boolean mouseRelease(ReadablePoint position, int button) { public boolean mouseRelease(Click click) {
if (selectedMarker != null) { if (selectedMarker != null) {
mouseDrag(position, button, 0); mouseDrag(click);
if (dragging) { if (dragging) {
dragging = false; dragging = false;
saveMarkers.accept(markers); saveMarkers.accept(markers);
@@ -237,8 +239,8 @@ public class GuiMarkerTimeline extends AbstractGuiTimeline<GuiMarkerTimeline> im
} }
@Override @Override
public boolean typeKey(ReadablePoint mousePosition, int keyCode, char keyChar, boolean ctrlDown, boolean shiftDown) { public boolean handleKey(KeyInput keyInput) {
if (keyCode == Keyboard.KEY_DELETE && selectedMarker != null) { if (keyInput.key == Keyboard.KEY_DELETE && selectedMarker != null) {
markers.remove(selectedMarker); markers.remove(selectedMarker);
saveMarkers.accept(markers); saveMarkers.accept(markers);
return true; return true;

View File

@@ -16,6 +16,7 @@ import de.johni0702.minecraft.gui.element.GuiElement;
import de.johni0702.minecraft.gui.element.GuiSlider; import de.johni0702.minecraft.gui.element.GuiSlider;
import de.johni0702.minecraft.gui.element.GuiTooltip; import de.johni0702.minecraft.gui.element.GuiTooltip;
import de.johni0702.minecraft.gui.element.advanced.IGuiTimeline; 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.CustomLayout;
import de.johni0702.minecraft.gui.layout.HorizontalLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout;
import de.johni0702.minecraft.gui.utils.EventRegistrations; import de.johni0702.minecraft.gui.utils.EventRegistrations;
@@ -181,13 +182,15 @@ public class GuiReplayOverlay extends AbstractGuiOverlay<GuiReplayOverlay> {
} }
} }
{ on(KeyEventCallback.EVENT, (int key, int scanCode, int action, int modifiers) -> { onKeyInput(key, action); return false; }); } { on(KeyEventCallback.EVENT, this::onKeyInput); }
private void onKeyInput(int key, int action) { private boolean onKeyInput(KeyInput keyInput, int action) {
if (action != KeyEventCallback.ACTION_PRESS) return; if (action != KeyEventCallback.ACTION_PRESS) return false;
// Allow F1 to be used to hide the replay gui (e.g. for recording with OBS) // 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; hidden = !hidden;
return true;
} }
return false;
} }
} }
} }

View File

@@ -6,6 +6,11 @@ import com.replaymod.render.rendering.VideoRenderer;
import com.replaymod.render.utils.RenderJob; import com.replaymod.render.utils.RenderJob;
import de.johni0702.minecraft.gui.GuiRenderer; import de.johni0702.minecraft.gui.GuiRenderer;
import de.johni0702.minecraft.gui.RenderInfo; import de.johni0702.minecraft.gui.RenderInfo;
import de.johni0702.minecraft.gui.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 de.johni0702.minecraft.gui.versions.Image;
import net.minecraft.client.font.TextRenderer; import net.minecraft.client.font.TextRenderer;
import net.minecraft.util.Formatting; 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.container.GuiScreen;
import de.johni0702.minecraft.gui.element.*; import de.johni0702.minecraft.gui.element.*;
import de.johni0702.minecraft.gui.element.advanced.AbstractGuiResourceLoadingList; 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.CustomLayout;
import de.johni0702.minecraft.gui.layout.HorizontalLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout;
import de.johni0702.minecraft.gui.layout.VerticalLayout; 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.Consumer;
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension; import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension; 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.client.gui.screen.NoticeScreen;
import net.minecraft.util.crash.CrashReport; import net.minecraft.util.crash.CrashReport;
import net.minecraft.util.crash.CrashException; 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(() -> { public final GuiReplayList list = new GuiReplayList(this).onSelectionChanged(this::updateButtons).onSelectionDoubleClicked(() -> {
if (this.loadButton.isEnabled()) { 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 @Override
public void run() { public void run() {
if (popup.getYesButton().isEnabled()) { if (popup.getYesButton().isEnabled()) {
popup.getYesButton().onClick(); popup.getYesButton().onClick(new Click(-1, -1, 0, 0));
} }
} }
}).onTextChanged(obj -> { }).onTextChanged(obj -> {
@@ -352,7 +355,7 @@ public class GuiReplayViewer extends GuiScreen {
} }
} }
public static class GuiReplayList extends AbstractGuiResourceLoadingList<GuiReplayList, GuiReplayEntry> implements Typeable { public static class GuiReplayList extends AbstractGuiResourceLoadingList<GuiReplayList, GuiReplayEntry> implements KeyHandler, CharHandler {
private File folder = null; private File folder = null;
// Not actually a child of this element, we just use it for text manipulation // Not actually a child of this element, we just use it for text manipulation
@@ -417,8 +420,8 @@ public class GuiReplayViewer extends GuiScreen {
} }
@Override @Override
public boolean typeKey(ReadablePoint mousePosition, int keyCode, char keyChar, boolean ctrlDown, boolean shiftDown) { public boolean handleKey(KeyInput keyInput) {
if (keyCode == Keyboard.KEY_F1) { if (keyInput.key == Keyboard.KEY_F1) {
SettingsRegistry reg = ReplayMod.instance.getSettingsRegistry(); SettingsRegistry reg = ReplayMod.instance.getSettingsRegistry();
reg.set(Setting.SHOW_SERVER_IPS, !reg.get(Setting.SHOW_SERVER_IPS)); reg.set(Setting.SHOW_SERVER_IPS, !reg.get(Setting.SHOW_SERVER_IPS));
reg.save(); reg.save();
@@ -426,16 +429,26 @@ public class GuiReplayViewer extends GuiScreen {
} }
boolean filterHasPriority = !filterTextField.getText().isEmpty(); 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 scrollY(0); // ensure we scroll to top if most entries are filtered
return true; return true;
} }
if (super.typeKey(mousePosition, keyCode, keyChar, ctrlDown, shiftDown)) { if (super.handleKey(keyInput)) {
return true; 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 scrollY(0); // ensure we scroll to top if most entries are filtered
return true; return true;
} }

View File

@@ -98,7 +98,7 @@ public class ReplayModSimplePathing extends EventRegistrations implements Module
settingsRegistry.set(Setting.AUTO_SYNC, active); settingsRegistry.set(Setting.AUTO_SYNC, active);
settingsRegistry.save(); settingsRegistry.save();
}); });
core.getKeyBindingRegistry().registerRaw(Keyboard.KEY_DELETE, () -> core.getKeyBindingRegistry().registerRaw(Keyboard.KEY_DELETE, keyInput ->
guiPathing != null && guiPathing.deleteButtonPressed()); guiPathing != null && guiPathing.deleteButtonPressed());
keyPositionKeyframe = core.getKeyBindingRegistry().registerKeyBinding("replaymod.input.positionkeyframe", Keyboard.KEY_I, () -> { keyPositionKeyframe = core.getKeyBindingRegistry().registerKeyBinding("replaymod.input.positionkeyframe", Keyboard.KEY_I, () -> {
if (guiPathing != null) guiPathing.toggleKeyframe(SPPath.POSITION, false); if (guiPathing != null) guiPathing.toggleKeyframe(SPPath.POSITION, false);
@@ -115,10 +115,10 @@ public class ReplayModSimplePathing extends EventRegistrations implements Module
guiPathing.toggleKeyframe(SPPath.POSITION, false); guiPathing.toggleKeyframe(SPPath.POSITION, false);
} }
}, true); }, true);
core.getKeyBindingRegistry().registerRaw(Keyboard.KEY_Z, () -> { core.getKeyBindingRegistry().registerRaw(Keyboard.KEY_Z, keyInput -> {
if (Screen.hasControlDown() && currentTimeline != null) { if (keyInput.hasCtrl() && currentTimeline != null) {
Timeline timeline = currentTimeline.getTimeline(); Timeline timeline = currentTimeline.getTimeline();
if (Screen.hasShiftDown()) { if (keyInput.hasShift()) {
if (timeline.peekRedoStack() != null) { if (timeline.peekRedoStack() != null) {
timeline.redoLastChange(); timeline.redoLastChange();
} }
@@ -131,8 +131,8 @@ public class ReplayModSimplePathing extends EventRegistrations implements Module
} }
return false; return false;
}); });
core.getKeyBindingRegistry().registerRaw(Keyboard.KEY_Y, () -> { core.getKeyBindingRegistry().registerRaw(Keyboard.KEY_Y, keyInput -> {
if (Screen.hasControlDown() && currentTimeline != null) { if (keyInput.hasCtrl() && currentTimeline != null) {
Timeline timeline = currentTimeline.getTimeline(); Timeline timeline = currentTimeline.getTimeline();
if (timeline.peekRedoStack() != null) { if (timeline.peekRedoStack() != null) {
timeline.redoLastChange(); timeline.redoLastChange();

View File

@@ -26,14 +26,15 @@ import de.johni0702.minecraft.gui.element.GuiTooltip;
import de.johni0702.minecraft.gui.element.IGuiClickable; import de.johni0702.minecraft.gui.element.IGuiClickable;
import de.johni0702.minecraft.gui.element.IGuiLabel; import de.johni0702.minecraft.gui.element.IGuiLabel;
import de.johni0702.minecraft.gui.element.advanced.GuiDropdownMenu; 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.GridLayout;
import de.johni0702.minecraft.gui.layout.HorizontalLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout;
import de.johni0702.minecraft.gui.layout.VerticalLayout; import de.johni0702.minecraft.gui.layout.VerticalLayout;
import de.johni0702.minecraft.gui.popup.AbstractGuiPopup; import de.johni0702.minecraft.gui.popup.AbstractGuiPopup;
import de.johni0702.minecraft.gui.utils.Colors; import de.johni0702.minecraft.gui.utils.Colors;
import de.johni0702.minecraft.gui.utils.Consumer; import de.johni0702.minecraft.gui.utils.Consumer;
import de.johni0702.minecraft.gui.utils.lwjgl.ReadablePoint;
import net.minecraft.client.resource.language.I18n; import net.minecraft.client.resource.language.I18n;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@@ -41,15 +42,9 @@ import org.apache.logging.log4j.Logger;
import java.util.Map; import java.util.Map;
import java.util.Optional; 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; import static de.johni0702.minecraft.gui.utils.Utils.link;
public abstract class GuiEditKeyframe<T extends GuiEditKeyframe<T>> extends AbstractGuiPopup<T> implements Typeable { public abstract class GuiEditKeyframe<T extends GuiEditKeyframe<T>> extends AbstractGuiPopup<T> implements KeyHandler {
private static GuiNumberField newGuiNumberField() { private static GuiNumberField newGuiNumberField() {
return new GuiNumberField().setPrecision(0).setValidateOnFocusChange(true); return new GuiNumberField().setPrecision(0).setValidateOnFocusChange(true);
} }
@@ -134,9 +129,9 @@ public abstract class GuiEditKeyframe<T extends GuiEditKeyframe<T>> extends Abst
} }
@Override @Override
public boolean typeKey(ReadablePoint mousePosition, int keyCode, char keyChar, boolean ctrlDown, boolean shiftDown) { public boolean handleKey(KeyInput keyInput) {
if (keyCode == Keyboard.KEY_ESCAPE) { if (keyInput.isEscape()) {
cancelButton.onClick(); cancelButton.onClick(new Click(-1, -1, 0, keyInput.modifiers));
return true; return true;
} }
return false; return false;

View File

@@ -17,6 +17,7 @@ import com.replaymod.simplepathing.SPTimeline;
import com.replaymod.simplepathing.SPTimeline.SPPath; import com.replaymod.simplepathing.SPTimeline.SPPath;
import de.johni0702.minecraft.gui.GuiRenderer; import de.johni0702.minecraft.gui.GuiRenderer;
import de.johni0702.minecraft.gui.element.advanced.AbstractGuiTimeline; 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.Draggable;
import de.johni0702.minecraft.gui.utils.lwjgl.vector.Vector2f; import de.johni0702.minecraft.gui.utils.lwjgl.vector.Vector2f;
import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.BufferBuilder;
@@ -407,14 +408,14 @@ public class GuiKeyframeTimeline extends AbstractGuiTimeline<GuiKeyframeTimeline
} }
@Override @Override
public boolean mouseClick(ReadablePoint position, int button) { public boolean mouseClick(Click click) {
int time = getTimeAt(position.getX(), position.getY()); int time = getTimeAt(click.x, click.y);
Pair<SPPath, Long> pathKeyframePair = getKeyframe(position); Pair<SPPath, Long> pathKeyframePair = getKeyframe(click);
if (pathKeyframePair.getRight() != null) { if (pathKeyframePair.getRight() != null) {
SPPath path = pathKeyframePair.getLeft(); SPPath path = pathKeyframePair.getLeft();
// Clicked on keyframe // Clicked on keyframe
long keyframeTime = pathKeyframePair.getRight(); long keyframeTime = pathKeyframePair.getRight();
if (button == 0) { // Left click if (click.button == 0) { // Left click
long now = MCVer.milliTime(); long now = MCVer.milliTime();
if (lastClickedKeyframe == keyframeTime) { if (lastClickedKeyframe == keyframeTime) {
// Clicked the same keyframe again, potentially a double click // Clicked the same keyframe again, potentially a double click
@@ -430,9 +431,9 @@ public class GuiKeyframeTimeline extends AbstractGuiTimeline<GuiKeyframeTimeline
lastClickedPath = path; lastClickedPath = path;
gui.getMod().setSelected(lastClickedPath, lastClickedKeyframe); gui.getMod().setSelected(lastClickedPath, lastClickedKeyframe);
// We might be dragging // We might be dragging
draggingStartX = position.getX(); draggingStartX = click.x;
dragging = true; dragging = true;
} else if (button == 1) { // Right click } else if (click.button == 1) { // Right click
Keyframe keyframe = gui.getMod().getCurrentTimeline().getKeyframe(path, keyframeTime); Keyframe keyframe = gui.getMod().getCurrentTimeline().getKeyframe(path, keyframeTime);
for (Property property : keyframe.getProperties()) { for (Property property : keyframe.getProperties()) {
applyPropertyToGame(property, keyframe); applyPropertyToGame(property, keyframe);
@@ -441,10 +442,10 @@ public class GuiKeyframeTimeline extends AbstractGuiTimeline<GuiKeyframeTimeline
return true; return true;
} else if (time != -1) { } else if (time != -1) {
// Clicked on timeline but not on any keyframe // Clicked on timeline but not on any keyframe
if (button == 0) { // Left click if (click.button == 0) { // Left click
setCursorPosition(time); setCursorPosition(time);
gui.getMod().setSelected(null, 0); gui.getMod().setSelected(null, 0);
} else if (button == 1) { // Right click } else if (click.button == 1) { // Right click
if (pathKeyframePair.getLeft() != null) { if (pathKeyframePair.getLeft() != null) {
// Apply the value of the clicked path at the clicked position // Apply the value of the clicked path at the clicked position
Path path = gui.getMod().getCurrentTimeline().getPath(pathKeyframePair.getLeft()); Path path = gui.getMod().getCurrentTimeline().getPath(pathKeyframePair.getLeft());
@@ -475,11 +476,11 @@ public class GuiKeyframeTimeline extends AbstractGuiTimeline<GuiKeyframeTimeline
} }
@Override @Override
public boolean mouseDrag(ReadablePoint position, int button, long timeSinceLastCall) { public boolean mouseDrag(Click click) {
if (!dragging) { if (!dragging) {
if (button == 0) { if (click.button == 0) {
// Left click, the user might try to move the cursor by clicking and holding // Left click, the user might try to move the cursor by clicking and holding
int time = getTimeAt(position.getX(), position.getY()); int time = getTimeAt(click.x, click.y);
if (time != -1) { if (time != -1) {
// and they are still on the timeline, so update the time appropriately // and they are still on the timeline, so update the time appropriately
setCursorPosition(time); setCursorPosition(time);
@@ -491,15 +492,15 @@ public class GuiKeyframeTimeline extends AbstractGuiTimeline<GuiKeyframeTimeline
if (!actuallyDragging) { if (!actuallyDragging) {
// Check if threshold has been passed by now // Check if threshold has been passed by now
if (Math.abs(position.getX() - draggingStartX) >= DRAGGING_THRESHOLD) { if (Math.abs(click.x - draggingStartX) >= DRAGGING_THRESHOLD) {
actuallyDragging = true; actuallyDragging = true;
} }
} }
if (actuallyDragging) { if (actuallyDragging) {
if (!gui.loadEntityTracker(() -> mouseDrag(position, button, timeSinceLastCall))) return true; if (!gui.loadEntityTracker(() -> mouseDrag(click))) return true;
// Threshold passed // Threshold passed
SPTimeline timeline = gui.getMod().getCurrentTimeline(); SPTimeline timeline = gui.getMod().getCurrentTimeline();
Point mouse = new Point(position); Point mouse = new Point(click);
getContainer().convertFor(this, mouse); getContainer().convertFor(this, mouse);
int mouseX = mouse.getX(); int mouseX = mouse.getX();
int width = getLastSize().getWidth(); int width = getLastSize().getWidth();
@@ -532,7 +533,7 @@ public class GuiKeyframeTimeline extends AbstractGuiTimeline<GuiKeyframeTimeline
} }
@Override @Override
public boolean mouseRelease(ReadablePoint position, int button) { public boolean mouseRelease(Click click) {
if (dragging) { if (dragging) {
if (actuallyDragging) { if (actuallyDragging) {
gui.getMod().getCurrentTimeline().getTimeline().pushChange(draggingChange); gui.getMod().getCurrentTimeline().getTimeline().pushChange(draggingChange);

View File

@@ -1 +1 @@
2.6.23 2.6.24

View File

@@ -2,6 +2,7 @@ package com.replaymod.core.mixin;
import com.replaymod.core.events.KeyBindingEventCallback; import com.replaymod.core.events.KeyBindingEventCallback;
import com.replaymod.core.events.KeyEventCallback; import com.replaymod.core.events.KeyEventCallback;
import de.johni0702.minecraft.gui.function.KeyInput;
import net.minecraft.client.settings.KeyBinding; import net.minecraft.client.settings.KeyBinding;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@@ -15,7 +16,7 @@ public class MixinKeyboardListener {
private static void beforeKeyBindingTick(CallbackInfo ci) { private static void beforeKeyBindingTick(CallbackInfo ci) {
int keyCode = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey(); int keyCode = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey();
int action = Keyboard.getEventKeyState() ? KeyEventCallback.ACTION_PRESS : KeyEventCallback.ACTION_RELEASE; int action = Keyboard.getEventKeyState() ? KeyEventCallback.ACTION_PRESS : KeyEventCallback.ACTION_RELEASE;
if (KeyEventCallback.EVENT.invoker().onKeyEvent(keyCode, 0, action, 0)) { if (KeyEventCallback.EVENT.invoker().onKeyEvent(new KeyInput(keyCode), action)) {
ci.cancel(); ci.cancel();
} }
} }

View File

@@ -31,6 +31,12 @@ import java.util.concurrent.TimeoutException;
public abstract class Mixin_ForceChunkLoading implements IForceChunkLoading { public abstract class Mixin_ForceChunkLoading implements IForceChunkLoading {
private ForceChunkLoadingHook replayModRender_hook; private ForceChunkLoadingHook replayModRender_hook;
//#if MC>=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 @Override
public void replayModRender_setHook(ForceChunkLoadingHook hook) { public void replayModRender_setHook(ForceChunkLoadingHook hook) {
this.replayModRender_hook = hook; this.replayModRender_hook = hook;
@@ -40,18 +46,28 @@ public abstract class Mixin_ForceChunkLoading implements IForceChunkLoading {
@Shadow @Final private ChunkRenderingDataPreparer field_45615; @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 protected abstract void setupTerrain(Camera par1, Frustum par2, boolean par3, boolean par4);
@Shadow private Frustum frustum; @Shadow private Frustum frustum;
@Shadow private Frustum capturedFrustum; @Shadow private Frustum capturedFrustum;
//#endif
@Shadow @Final private MinecraftClient client; @Shadow @Final private MinecraftClient client;
@Shadow protected abstract void applyFrustum(Frustum par1); @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")) @Inject(method = "render", at = @At(value = "INVOKE", target = SETUP_TERRAIN))
private void forceAllChunks(CallbackInfo ci, @Local(argsOnly = true) Camera camera) { private void forceAllChunks(
CallbackInfo ci,
//#if MC>=12109
//$$ @Local Frustum frustum,
//#endif
@Local(argsOnly = true) Camera camera
) {
if (replayModRender_hook == null) { if (replayModRender_hook == null) {
return; return;
} }
@@ -69,7 +85,11 @@ public abstract class Mixin_ForceChunkLoading implements IForceChunkLoading {
boolean areWeDoneYet = true; boolean areWeDoneYet = true;
// Determine which chunks shall be visible // 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()); setupTerrain(camera, this.frustum, this.capturedFrustum != null, this.client.player.isSpectator());
//#endif
// Wait for async processing to be complete // Wait for async processing to be complete
Future<?> fullUpdateFuture = renderingDataAcc.fullUpdateFuture(); Future<?> fullUpdateFuture = renderingDataAcc.fullUpdateFuture();

View File

View File

@@ -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

View File

@@ -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<Quaternionf> 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<Quaternionf> orgRotationRef
) {
Quaternionf orgRotation = orgRotationRef.get();
if (orgRotation == null) {
return;
}
camera.getRotation().set(orgRotation.x, orgRotation.y, orgRotation.z, orgRotation.w);
}
}

View File

@@ -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<CameraRenderState> 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);
}
}

View File

@@ -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;