From 7dfbbdc959685d4f3b932f26c19f8e9a8809cbc5 Mon Sep 17 00:00:00 2001 From: MeexReay <127148610+MeexReay@users.noreply.github.com> Date: Wed, 31 May 2023 22:42:20 +0300 Subject: [PATCH] ms -> ticks --- .../themixray/repeating/mod/RepeatingMod.java | 98 ++++++++++++------- .../repeating/mod/RepeatingScreen.java | 4 +- .../themixray/repeating/mod/TickTask.java | 94 ++++++++++++++++++ .../repeating/mod/mixin/ClientMixin.java | 24 +++++ .../repeating/mod/mixin/EntityMixin.java | 36 +++++++ .../repeating/mod/mixin/MovementMixin.java | 35 ++----- .../repeating/mod/mixin/RendererMixin.java | 12 ++- .../assets/repeating-mod/lang/en_us.json | 6 +- .../assets/repeating-mod/lang/ru_ru.json | 6 +- src/main/resources/fabric.mod.json | 2 +- src/main/resources/repeating-mod.mixins.json | 5 +- 11 files changed, 245 insertions(+), 77 deletions(-) create mode 100644 src/main/java/themixray/repeating/mod/TickTask.java create mode 100644 src/main/java/themixray/repeating/mod/mixin/ClientMixin.java create mode 100644 src/main/java/themixray/repeating/mod/mixin/EntityMixin.java diff --git a/src/main/java/themixray/repeating/mod/RepeatingMod.java b/src/main/java/themixray/repeating/mod/RepeatingMod.java index 0c92ab7..4ed30dd 100644 --- a/src/main/java/themixray/repeating/mod/RepeatingMod.java +++ b/src/main/java/themixray/repeating/mod/RepeatingMod.java @@ -19,7 +19,6 @@ import org.lwjgl.glfw.GLFW; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; import java.util.*; public class RepeatingMod implements ClientModInitializer { @@ -28,22 +27,24 @@ public class RepeatingMod implements ClientModInitializer { public static final FabricLoader loader = FabricLoader.getInstance(); public static RepeatingMod me; - public Thread move_tick = null; public List record = new ArrayList<>(); public boolean is_recording = false; - public Date last_record = null; + public long last_record = -1; + public TickTask move_tick = null; - public Thread replay = null; + public TickTask replay_tick = null; public boolean is_replaying = false; public boolean loop_replay = false; public static RecordInputEvent input_replay = null; + public long living_ticks = 0; + public static RepeatingScreen menu; private static KeyBinding menu_key; private static KeyBinding toggle_replay_key; private static KeyBinding toggle_record_key; - public long record_pos_delay = 1000; + public long record_pos_delay = 20; public EasyConfig conf; @@ -90,6 +91,13 @@ public class RepeatingMod implements ClientModInitializer { } } }); + + new TickTask(0,0) { + @Override + public void run() { + living_ticks++; + } + }; } public RecordEvent getLastRecord(String t) { @@ -111,31 +119,30 @@ public class RepeatingMod implements ClientModInitializer { client.player.getHeadYaw(), client.player.getPitch())); if (record_pos_delay > 0) { - move_tick = new Thread(() -> { - while (is_recording) { - try { - Thread.sleep(record_pos_delay); - } catch (InterruptedException e) { - e.printStackTrace(); - } + move_tick = new TickTask( + record_pos_delay, + record_pos_delay) { + @Override + public void run() { record.add(new RecordMoveEvent(client.player.getPos(), client.player.getHeadYaw(), client.player.getPitch())); } - }); - move_tick.start(); + }; } sendMessage(Text.translatable("message.repeating-mod.record_start")); } public void recordTick(RecordEvent e) { - Date now = new Date(); - if (last_record != null) { - long diff = now.getTime() - last_record.getTime(); - if (diff >= 0) record.add(new RecordDelayEvent(diff)); + if (is_recording) { + long now = living_ticks; + if (last_record != -1) { + long diff = now - last_record - 2; + if (diff > 0) record.add(new RecordDelayEvent(diff)); + } + record.add(e); + last_record = now; } - record.add(e); - last_record = now; } public void recordAllInput() { @@ -219,9 +226,12 @@ public class RepeatingMod implements ClientModInitializer { public void stopRecording() { is_recording = false; - move_tick = null; + if (move_tick != null) { + move_tick.cancel(); + move_tick = null; + } menu.update_btns(); - last_record = null; + last_record = -1; sendMessage(Text.translatable("message.repeating-mod.record_stop")); } @@ -230,25 +240,41 @@ public class RepeatingMod implements ClientModInitializer { is_recording = false; is_replaying = true; menu.update_btns(); - replay = new Thread(() -> { - while (true) { - for (RecordEvent e : record) { - if (is_replaying) { - e.callback(); - } + replay_tick = new TickTask(0,0, TickTask.TickAt.CLIENT_TAIL) { + public int replay_index = 0; + + @Override + public void run() { + if (!is_replaying) cancel(); + RecordEvent e = record.get(replay_index); + if (e instanceof RecordDelayEvent) { + setDelay(((RecordDelayEvent) e).delay); + } else { + e.callback(); + } + + replay_index++; + if (!loop_replay) { + if (replay_index == record.size()) { + stopReplay(); + cancel(); + } + } else if (replay_index == record.size()) { + replay_index = 0; } - if (!loop_replay || !is_replaying) break; } - stopReplay(); - }); - replay.start(); + }; + sendMessage(Text.translatable("message.repeating-mod.replay_start")); } public void stopReplay() { is_recording = false; is_replaying = false; - replay = null; + if (replay_tick != null) { + replay_tick.cancel(); + replay_tick = null; + } menu.update_btns(); sendMessage(Text.translatable("message.repeating-mod.replay_stop")); } @@ -265,6 +291,10 @@ public class RepeatingMod implements ClientModInitializer { .append("] ").append(text)); } + public static void sendDebug(String s) { + client.player.sendMessage(Text.literal("[DEBUG] ").append(Text.of(s))); + } + public static abstract class RecordEvent { abstract void callback(); abstract String toText(); @@ -305,7 +335,7 @@ public class RepeatingMod implements ClientModInitializer { public void callback() { try { - Thread.sleep(delay); + Thread.sleep(delay/20*1000); } catch (InterruptedException e) { e.printStackTrace(); } diff --git a/src/main/java/themixray/repeating/mod/RepeatingScreen.java b/src/main/java/themixray/repeating/mod/RepeatingScreen.java index 4e57b8d..5fe187e 100644 --- a/src/main/java/themixray/repeating/mod/RepeatingScreen.java +++ b/src/main/java/themixray/repeating/mod/RepeatingScreen.java @@ -169,7 +169,7 @@ public class RepeatingScreen extends BaseOwoScreen { .horizontalAlignment(HorizontalAlignment.CENTER) .margins(Insets.of(1))) .child(Containers.verticalFlow(Sizing.content(), Sizing.content()) - .child(Components.discreteSlider(Sizing.fixed(120),-24,5000) + .child(Components.discreteSlider(Sizing.fixed(120),-20,100) .setFromDiscreteValue(mod.record_pos_delay) .message((String s)->{ mod.record_pos_delay = Long.parseLong(s); @@ -177,7 +177,7 @@ public class RepeatingScreen extends BaseOwoScreen { mod.conf.save(); if (mod.record_pos_delay > -1) return Text.translatable("text.repeating-mod.pos_delay", s); - return Text.translatable("text.repeating-mod.nan_pos_delay", s); + return Text.translatable("text.repeating-mod.nan_pos_delay"); }).scrollStep(25) .margins(Insets.of(1)) .tooltip(Text.translatable("text.repeating-mod.pos_delay_text"))) diff --git a/src/main/java/themixray/repeating/mod/TickTask.java b/src/main/java/themixray/repeating/mod/TickTask.java new file mode 100644 index 0000000..f3beed1 --- /dev/null +++ b/src/main/java/themixray/repeating/mod/TickTask.java @@ -0,0 +1,94 @@ +package themixray.repeating.mod; + +import java.util.ArrayList; +import java.util.List; + +public abstract class TickTask implements Runnable { + public static List tasks = new ArrayList<>(); + + public static void tickTasks(TickAt at) { + for (TickTask t:new ArrayList<>(tasks)) + if (t.getAt() == at) t.tick(); + } + + private long living; + private long delay; + + private boolean is_repeating; + private long period; + + private boolean is_cancelled; + private TickAt at; + + public enum TickAt { + CLIENT_HEAD, CLIENT_TAIL, + MOVEMENT_HEAD, MOVEMENT_TAIL, + RENDER_HEAD, RENDER_TAIL + } + + public TickTask(long delay, TickAt at) { + this.is_cancelled = false; + this.is_repeating = false; + this.delay = delay; + this.living = 0; + this.period = 0; + this.at = at; + tasks.add(this); + } + + public TickTask(long delay, long period, TickAt at) { + this.is_cancelled = false; + this.is_repeating = true; + this.delay = delay; + this.period = period; + this.living = 0; + this.at = at; + tasks.add(this); + } + + public TickTask(long delay) { + this(delay,TickAt.CLIENT_HEAD); + } + + public TickTask(long delay, long period) { + this(delay,period,TickAt.CLIENT_HEAD); + } + + public void cancel() { + if (!is_cancelled) { + is_cancelled = true; + tasks.remove(this); + } + } + + public boolean isCancelled() { + return is_cancelled; + } + + public TickAt getAt() { + return at; + } + + public void setDelay(long delay) { + if (is_repeating) { + this.delay = delay; + } + } + public long getDelay() { + return this.delay; + } + + public void tick() { + if (living >= delay) { + if (is_repeating) { + delay = period; + run(); + living = -1; + } else { + run(); + cancel(); + } + } + living++; + } +} diff --git a/src/main/java/themixray/repeating/mod/mixin/ClientMixin.java b/src/main/java/themixray/repeating/mod/mixin/ClientMixin.java new file mode 100644 index 0000000..1d077ac --- /dev/null +++ b/src/main/java/themixray/repeating/mod/mixin/ClientMixin.java @@ -0,0 +1,24 @@ +package themixray.repeating.mod.mixin; + +import net.minecraft.client.MinecraftClient; +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; +import themixray.repeating.mod.RepeatingMod; +import themixray.repeating.mod.TickTask; + +@Mixin(MinecraftClient.class) +public abstract class ClientMixin { + @Inject(at = @At(value = "HEAD"), method = "tick") + private void onTickHead(CallbackInfo ci) { + if (RepeatingMod.me.is_recording) + RepeatingMod.me.recordAllInput(); + TickTask.tickTasks(TickTask.TickAt.CLIENT_HEAD); + } + + @Inject(at = @At(value = "TAIL"), method = "tick") + private void onTickTail(CallbackInfo ci) { + TickTask.tickTasks(TickTask.TickAt.CLIENT_TAIL); + } +} diff --git a/src/main/java/themixray/repeating/mod/mixin/EntityMixin.java b/src/main/java/themixray/repeating/mod/mixin/EntityMixin.java new file mode 100644 index 0000000..8b09ad0 --- /dev/null +++ b/src/main/java/themixray/repeating/mod/mixin/EntityMixin.java @@ -0,0 +1,36 @@ +package themixray.repeating.mod.mixin; + +import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents; +import net.fabricmc.fabric.api.event.player.UseBlockCallback; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.entity.Entity; +import net.minecraft.util.ActionResult; +import net.minecraft.util.hit.HitResult; +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; +import themixray.repeating.mod.RepeatingMod; +import themixray.repeating.mod.TickTask; + +import java.util.UUID; + +@Mixin(Entity.class) +public abstract class EntityMixin { + @Shadow public abstract UUID getUuid(); + + @Inject(at = @At(value = "HEAD"), method = "setSprinting", cancellable = true) + private void onSprint(boolean sprinting,CallbackInfo ci) { + if (getUuid().equals(RepeatingMod.client.player.getUuid())) { + if (RepeatingMod.me.is_replaying) { + if (RepeatingMod.input_replay != null && + RepeatingMod.input_replay.sprinting != null && + RepeatingMod.input_replay.sprinting != sprinting) { + ci.cancel(); + return; + } + } + } + } +} diff --git a/src/main/java/themixray/repeating/mod/mixin/MovementMixin.java b/src/main/java/themixray/repeating/mod/mixin/MovementMixin.java index a88da8c..594cbd0 100644 --- a/src/main/java/themixray/repeating/mod/mixin/MovementMixin.java +++ b/src/main/java/themixray/repeating/mod/mixin/MovementMixin.java @@ -12,6 +12,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import themixray.repeating.mod.RepeatingMod; import themixray.repeating.mod.TickTask; +import java.util.ArrayList; + @Mixin(ClientPlayerEntity.class) public abstract class MovementMixin { @@ -30,36 +32,13 @@ public abstract class MovementMixin { }); } - @Inject(at = @At(value = "HEAD"), method = "tick") - private void onTickHead(CallbackInfo ci) { - for (TickTask t:TickTask.ticks) - if (t.getAt() == TickTask.TickAt.HEAD) - t.tick(); + @Inject(at = @At(value = "HEAD"), method = "tickMovement") + private void onMoveHead(CallbackInfo ci) { + TickTask.tickTasks(TickTask.TickAt.MOVEMENT_HEAD); } @Inject(at = @At(value = "TAIL"), method = "tick") - private void onTickTail(CallbackInfo ci) { - for (TickTask t:TickTask.ticks) - if (t.getAt() == TickTask.TickAt.TAIL) - t.tick(); - } - - @Inject(at = @At(value = "HEAD"), method = "tickMovement") - private void onMove(CallbackInfo ci) { - if (RepeatingMod.me.is_recording) { - RepeatingMod.me.recordAllInput(); - } - } - - @Inject(at = @At(value = "HEAD"), method = "setSprinting", cancellable = true) - private void onSprint(boolean sprinting,CallbackInfo ci) { - if (RepeatingMod.me.is_replaying) { - if (RepeatingMod.input_replay != null && - RepeatingMod.input_replay.sprinting != null && - RepeatingMod.input_replay.sprinting != sprinting) { - ci.cancel(); - return; - } - } + private void onMoveTail(CallbackInfo ci) { + TickTask.tickTasks(TickTask.TickAt.MOVEMENT_TAIL); } } diff --git a/src/main/java/themixray/repeating/mod/mixin/RendererMixin.java b/src/main/java/themixray/repeating/mod/mixin/RendererMixin.java index f4530fb..d4511b1 100644 --- a/src/main/java/themixray/repeating/mod/mixin/RendererMixin.java +++ b/src/main/java/themixray/repeating/mod/mixin/RendererMixin.java @@ -7,15 +7,17 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import themixray.repeating.mod.RepeatingMod; +import themixray.repeating.mod.TickTask; @Mixin(GameRenderer.class) public abstract class RendererMixin { + @Inject(at = @At(value = "HEAD"), method = "tick") + private void onTickHead(CallbackInfo ci) { + TickTask.tickTasks(TickTask.TickAt.RENDER_HEAD); + } + @Inject(at = @At(value = "TAIL"), method = "tick") private void onTickTail(CallbackInfo ci) { - if (RepeatingMod.me.is_replaying) { - if (RepeatingMod.input_replay != null) { - RepeatingMod.me.recordCameraInput(); - } - } + TickTask.tickTasks(TickTask.TickAt.RENDER_TAIL); } } diff --git a/src/main/resources/assets/repeating-mod/lang/en_us.json b/src/main/resources/assets/repeating-mod/lang/en_us.json index d9417ba..ee191bd 100644 --- a/src/main/resources/assets/repeating-mod/lang/en_us.json +++ b/src/main/resources/assets/repeating-mod/lang/en_us.json @@ -14,9 +14,9 @@ "text.repeating-mod.parkour": "Parkour mode", "text.repeating-mod.settings": "Settings", "text.repeating-mod.dev": "In development...", - "text.repeating-mod.nan_pos_delay": "No pos delay", - "text.repeating-mod.pos_delay": "Pos delay: %s ms", - "text.repeating-mod.pos_delay_text": "Delay after which the pos event is added", + "text.repeating-mod.nan_pos_delay": "No pos timer", + "text.repeating-mod.pos_delay": "Pos timer: %s ticks", + "text.repeating-mod.pos_delay_text": "Timer after which the pos\nevent is added (20 ticks = 1 sec)", "message.repeating-mod.replay_start": "Replay started", "message.repeating-mod.replay_stop": "Replay finished", diff --git a/src/main/resources/assets/repeating-mod/lang/ru_ru.json b/src/main/resources/assets/repeating-mod/lang/ru_ru.json index ed68292..46ba2e1 100644 --- a/src/main/resources/assets/repeating-mod/lang/ru_ru.json +++ b/src/main/resources/assets/repeating-mod/lang/ru_ru.json @@ -14,9 +14,9 @@ "text.repeating-mod.parkour": "Режим паркура", "text.repeating-mod.settings": "Настройки", "text.repeating-mod.dev": "В разработке...", - "text.repeating-mod.nan_pos_delay": "Задержки позиции нету", - "text.repeating-mod.pos_delay": "Задержка позиции: %s мс", - "text.repeating-mod.pos_delay_text": "Задержка, после которой добавляется ивент позиции", + "text.repeating-mod.nan_pos_delay": "Таймера позиции нету", + "text.repeating-mod.pos_delay": "Таймер позиции: %s тиков", + "text.repeating-mod.pos_delay_text": "Таймер, после которой добавляется\nивент позиции (20 тиков = 1 сек)", "message.repeating-mod.replay_start": "Повтор начат", "message.repeating-mod.replay_stop": "Повтор закончен", diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 30b9df6..e137afe 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -29,7 +29,7 @@ "depends": { "fabricloader": ">=0.14.14", "fabric-api": "*", - "minecraft": "~1.19.3", + "minecraft": "1.19.x", "java": ">=17" }, "suggests": { diff --git a/src/main/resources/repeating-mod.mixins.json b/src/main/resources/repeating-mod.mixins.json index 50f497d..c03d7f6 100644 --- a/src/main/resources/repeating-mod.mixins.json +++ b/src/main/resources/repeating-mod.mixins.json @@ -7,7 +7,10 @@ ], "client": [ "MovementMixin", - "InputMixin" + "InputMixin", + "RendererMixin", + "EntityMixin", + "ClientMixin" ], "injectors": { "defaultRequire": 1