This commit is contained in:
MeexReay 2024-12-08 02:39:49 +03:00
parent 5d9b27cd9a
commit cc12eab006
50 changed files with 1166 additions and 3483 deletions

View file

@ -1,103 +1,103 @@
package themixray.repeating.mod;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.io.File;
public class EasyConfig {
public final Path path;
public final File file;
public Map<String,String> data;
public EasyConfig(File f, Map<String,String> def) {
this.path = f.toPath();
this.file = f;
this.data = new HashMap<>();
if (!file.exists()) {
try {
file.createNewFile();
write(def);
} catch (IOException e) {
e.printStackTrace();
}
}
reload();
for (Map.Entry<String,String> m:def.entrySet())
if (!data.containsKey(m.getKey()))
data.put(m.getKey(),m.getValue());
save();
}
public EasyConfig(Path f, Map<String,String> def) {
this(f.toFile(),def);
}
public EasyConfig(String parent,String child,Map<String,String> def) {
this(new File(parent,child),def);
}
public EasyConfig(File parent,String child,Map<String,String> def) {
this(new File(parent,child),def);
}
public EasyConfig(Path parent,String child,Map<String,String> def) {
this(new File(parent.toFile(),child),def);
}
public EasyConfig(File f) {
this(f,new HashMap<>());
}
public EasyConfig(Path path) {
this(path.toFile(),new HashMap<>());
}
public EasyConfig(String parent,String child) {
this(new File(parent,child),new HashMap<>());
}
public EasyConfig(File parent,String child) {
this(new File(parent,child),new HashMap<>());
}
public EasyConfig(Path parent,String child) {
this(new File(parent.toFile(),child),new HashMap<>());
}
public void reload() {
data = read();
}
public void save() {
write(data);
}
private String toText(Map<String,String> p) {
StringBuilder t = new StringBuilder();
for (Map.Entry<String,String> e:p.entrySet())
t.append(e.getKey()).append("=").append(e.getValue()).append("\n");
return t.toString();
}
private Map<String,String> toMap(String j) {
Map<String,String> m = new HashMap<>();
for (String l:j.split("\n")) {
String s[] = l.split("=");
m.put(s[0],s[1]);
}
return m;
}
private Map<String,String> read() {
try {
return toMap(Files.readString(path));
} catch (IOException e) {
e.printStackTrace();
}
return new HashMap<>();
}
private void write(Map<String,String> p) {
try {
Files.write(path, toText(p).getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
package themixray.repeating.mod;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.io.File;
public class EasyConfig {
public final Path path;
public final File file;
public Map<String,String> data;
public EasyConfig(File f, Map<String,String> def) {
this.path = f.toPath();
this.file = f;
this.data = new HashMap<>();
if (!file.exists()) {
try {
file.createNewFile();
write(def);
} catch (IOException e) {
e.printStackTrace();
}
}
reload();
for (Map.Entry<String,String> m:def.entrySet())
if (!data.containsKey(m.getKey()))
data.put(m.getKey(),m.getValue());
save();
}
public EasyConfig(Path f, Map<String,String> def) {
this(f.toFile(),def);
}
public EasyConfig(String parent,String child,Map<String,String> def) {
this(new File(parent,child),def);
}
public EasyConfig(File parent,String child,Map<String,String> def) {
this(new File(parent,child),def);
}
public EasyConfig(Path parent,String child,Map<String,String> def) {
this(new File(parent.toFile(),child),def);
}
public EasyConfig(File f) {
this(f,new HashMap<>());
}
public EasyConfig(Path path) {
this(path.toFile(),new HashMap<>());
}
public EasyConfig(String parent,String child) {
this(new File(parent,child),new HashMap<>());
}
public EasyConfig(File parent,String child) {
this(new File(parent,child),new HashMap<>());
}
public EasyConfig(Path parent,String child) {
this(new File(parent.toFile(),child),new HashMap<>());
}
public void reload() {
data = read();
}
public void save() {
write(data);
}
private String toText(Map<String,String> p) {
StringBuilder t = new StringBuilder();
for (Map.Entry<String,String> e:p.entrySet())
t.append(e.getKey()).append("=").append(e.getValue()).append("\n");
return t.toString();
}
private Map<String,String> toMap(String j) {
Map<String,String> m = new HashMap<>();
for (String l:j.split("\n")) {
String s[] = l.split("=");
m.put(s[0],s[1]);
}
return m;
}
private Map<String,String> read() {
try {
return toMap(Files.readString(path));
} catch (IOException e) {
e.printStackTrace();
}
return new HashMap<>();
}
private void write(Map<String,String> p) {
try {
Files.write(path, toText(p).getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}

View file

@ -1,339 +1,341 @@
package themixray.repeating.mod;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.util.InputUtil;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.math.Vec3d;
import org.lwjgl.glfw.GLFW;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import themixray.repeating.mod.event.events.DelayEvent;
import themixray.repeating.mod.event.RecordEvent;
import themixray.repeating.mod.event.events.InputEvent;
import themixray.repeating.mod.event.events.MoveEvent;
import themixray.repeating.mod.render.RenderHelper;
import themixray.repeating.mod.render.RenderSystem;
import themixray.repeating.mod.render.buffer.WorldBuffer;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.List;
public class Main implements ClientModInitializer {
public static final Logger LOGGER = LoggerFactory.getLogger("repeating-mod");
public static final MinecraftClient client = MinecraftClient.getInstance();
public static final FabricLoader loader = FabricLoader.getInstance();
public static Main me;
public RecordList record_list;
public RecordState now_record;
public boolean is_recording = false;
public long last_record = -1;
public TickTask move_tick = null;
public TickTask replay_tick = null;
public boolean is_replaying = false;
public boolean loop_replay = false;
public static InputEvent 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 = 20;
public static Random rand = new Random();
public EasyConfig conf;
public File records_folder;
@Override
public void onInitializeClient() {
LOGGER.info("Repeating mod initialized");
me = this;
now_record = null;
records_folder = new File(FabricLoader.getInstance().getGameDir().toFile(),"repeating_mod_records");
if (!records_folder.exists()) records_folder.mkdir();
record_list = new RecordList(records_folder);
record_list.loadRecords();
RenderSystem.init();
WorldRenderEvents.LAST.register(context -> {
WorldBuffer buffer = RenderHelper.startTri(context);
if (now_record != null) {
Vec3d start_pos = now_record.getStartRecordPos();
Vec3d finish_pos = now_record.getFinishRecordPos();
if (start_pos != null) drawRecordPos(buffer, start_pos, new Color(70, 230, 70, 128));
if (finish_pos != null) drawRecordPos(buffer, finish_pos, new Color(230, 70, 70, 128));
}
RenderHelper.endTri(buffer);
});
ClientTickEvents.END_CLIENT_TICK.register(client -> {
TickTask.tickTasks(TickTask.TickAt.CLIENT_EVENT);
});
Map<String,String> def = new HashMap<>();
def.put("record_pos_delay", String.valueOf(record_pos_delay));
conf = new EasyConfig(loader.getConfigDir(),"repeating-mod",def);
record_pos_delay = Long.parseLong(conf.data.get("record_pos_delay"));
menu_key = KeyBindingHelper.registerKeyBinding(new KeyBinding(
"key.repeating-mod.menu",InputUtil.Type.KEYSYM,
GLFW.GLFW_KEY_J,"text.repeating-mod.name"));
toggle_replay_key = KeyBindingHelper.registerKeyBinding(new KeyBinding(
"key.repeating-mod.toggle_replay",InputUtil.Type.KEYSYM,
-1,"text.repeating-mod.name"));
toggle_record_key = KeyBindingHelper.registerKeyBinding(new KeyBinding(
"key.repeating-mod.toggle_record",InputUtil.Type.KEYSYM,
-1,"text.repeating-mod.name"));
menu = new RepeatingScreen();
ClientTickEvents.END_CLIENT_TICK.register(client -> {
if (menu_key.wasPressed())
client.setScreen(menu);
if (toggle_replay_key.wasPressed()) {
if (now_record != null) {
if (!is_recording) {
if (is_replaying)
stopReplay();
else startReplay();
menu.updateButtons();
}
}
}
if (toggle_record_key.wasPressed()) {
if (!is_replaying) {
if (is_recording)
stopRecording();
else startRecording();
menu.updateButtons();
}
}
});
new TickTask(0,0) {
@Override
public void run() {
living_ticks++;
}
};
System.setProperty("java.awt.headless", "false");
}
public void setNowRecord(RecordState record) {
now_record = record;
}
public void drawRecordPos(WorldBuffer buffer, Vec3d pos, Color color) {
RenderHelper.drawRectFromTri(buffer,
(float) pos.getX() - 0.25F,
(float) pos.getY() + 0.01F,
(float) pos.getZ() - 0.25F,
(float) pos.getX() + 0.25F,
(float) pos.getY() + 0.01F,
(float) pos.getZ() - 0.25F,
(float) pos.getX() + 0.25F,
(float) pos.getY() + 0.01F,
(float) pos.getZ() + 0.25F,
(float) pos.getX() - 0.25F,
(float) pos.getY() + 0.01F,
(float) pos.getZ() + 0.25F,
color);
}
public void startRecording() {
is_recording = true;
menu.updateButtons();
now_record = record_list.newRecord();
Vec3d start_pos = client.player.getPos();
now_record.addEvent(new MoveEvent(start_pos,client.player.getHeadYaw(),client.player.getPitch()));
now_record.setStartRecordPos(start_pos);
if (record_pos_delay > 0) {
move_tick = new TickTask(
record_pos_delay,
record_pos_delay) {
@Override
public void run() {
now_record.addEvent(new MoveEvent(client.player.getPos(),
client.player.getHeadYaw(), client.player.getPitch()));
}
};
}
sendMessage(Text.translatable("message.repeating-mod.record_start"));
}
public void recordTick(RecordEvent e) {
if (is_recording) {
long now = living_ticks;
if (last_record != -1) {
long diff = now - last_record - 2;
if (diff > 0) now_record.addEvent(new DelayEvent(diff));
}
now_record.addEvent(e);
last_record = now;
}
}
public void recordAllInput() {
if (client.player == null) {
stopRecording();
return;
}
InputEvent l = ((InputEvent) now_record.getLastEvent("input"));
if (l == null) {
InputEvent e = new InputEvent(
client.player.input.sneaking,
client.player.input.jumping,
client.player.input.movementSideways,
client.player.input.movementForward,
client.player.input.pressingForward,
client.player.input.pressingBack,
client.player.input.pressingLeft,
client.player.input.pressingRight,
client.player.getHeadYaw(),
client.player.getBodyYaw(),
client.player.getPitch(),
client.player.isSprinting(),
client.player.getYaw(),
client.player.getMovementSpeed());
recordTick(e);
} else {
InputEvent e = new InputEvent(
((Boolean) client.player.input.sneaking == l.sneaking) ? null : client.player.input.sneaking,
((Boolean) client.player.input.jumping == l.jumping) ? null : client.player.input.jumping,
(((Float) client.player.input.movementSideways).equals(l.movementSideways)) ? null : client.player.input.movementSideways,
(((Float) client.player.input.movementForward).equals(l.movementForward)) ? null : client.player.input.movementForward,
((Boolean) client.player.input.pressingForward == l.pressingForward) ? null : client.player.input.pressingForward,
((Boolean) client.player.input.pressingBack == l.pressingBack) ? null : client.player.input.pressingBack,
((Boolean) client.player.input.pressingLeft == l.pressingLeft) ? null : client.player.input.pressingLeft,
((Boolean) client.player.input.pressingRight == l.pressingRight) ? null : client.player.input.pressingRight,
client.player.getHeadYaw(), Main.client.player.getBodyYaw(),client.player.getPitch(),
((Boolean) client.player.isSprinting() == l.sprinting) ? null : client.player.isSprinting(),
client.player.getYaw(),client.player.getMovementSpeed());
if (!(e.isEmpty() &&
e.yaw == l.yaw &&
e.head_yaw == l.head_yaw &&
e.pitch == l.pitch &&
e.body_yaw == l.body_yaw)) {
e.fillEmpty(l);
recordTick(e);
}
}
}
public void stopRecording() {
is_recording = false;
now_record.setFinishRecordPos(client.player.getPos());
try {
now_record.save();
} catch (IOException e) {
throw new RuntimeException(e);
}
if (move_tick != null) {
move_tick.cancel();
move_tick = null;
}
menu.updateButtons();
last_record = -1;
sendMessage(Text.translatable("message.repeating-mod.record_stop"));
}
public void startReplay() {
is_recording = false;
is_replaying = true;
menu.updateButtons();
List<RecordEvent> events = now_record.getEvents();
replay_tick = new TickTask(0,0, TickTask.TickAt.CLIENT_EVENT) {
public int replay_index = 0;
@Override
public void run() {
if (!is_replaying) {
cancel();
return;
}
RecordEvent e = events.get(replay_index);
if (e instanceof DelayEvent) {
setDelay(((DelayEvent) e).delay);
} else {
e.replay();
}
replay_index++;
if (!loop_replay) {
if (replay_index == events.size()) {
stopReplay();
cancel();
}
} else if (replay_index == events.size()) {
replay_index = 0;
}
}
};
sendMessage(Text.translatable("message.repeating-mod.replay_start"));
}
public void stopReplay() {
is_recording = false;
is_replaying = false;
if (replay_tick != null) {
replay_tick.cancel();
replay_tick = null;
}
try {
now_record.save();
} catch (IOException e) {
throw new RuntimeException(e);
}
menu.updateButtons();
record_list.getWidget().getWidget(now_record).getChildren().get(3).setMessage(Text.translatable("text.repeating-mod.start"));
sendMessage(Text.translatable("message.repeating-mod.replay_stop"));
}
public static void sendMessage(MutableText text) {
client.player.sendMessage(Text.literal("[")
.append(Text.translatable("text.repeating-mod.name"))
.append("] ").formatted(Formatting.BOLD,Formatting.DARK_GRAY)
.append(text.formatted(Formatting.RESET).formatted(Formatting.GRAY)));
}
public static void sendDebug(String s) {
client.player.sendMessage(Text.literal("[DEBUG] ").append(Text.of(s)));
}
}
package themixray.repeating.mod;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.util.InputUtil;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.math.Vec3d;
import org.lwjgl.glfw.GLFW;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import themixray.repeating.mod.event.events.DelayEvent;
import themixray.repeating.mod.event.RecordEvent;
import themixray.repeating.mod.event.events.InputEvent;
import themixray.repeating.mod.event.events.MoveEvent;
import themixray.repeating.mod.render.RenderHelper;
import themixray.repeating.mod.render.RenderSystem;
import themixray.repeating.mod.render.buffer.WorldBuffer;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.List;
public class Main implements ClientModInitializer {
public static final Logger LOGGER = LoggerFactory.getLogger("repeating-mod");
public static final MinecraftClient client = MinecraftClient.getInstance();
public static final FabricLoader loader = FabricLoader.getInstance();
public static Main me;
public RecordList record_list;
public RecordState now_record;
public boolean is_recording = false;
public long last_record = -1;
public TickTask move_tick = null;
public TickTask replay_tick = null;
public boolean is_replaying = false;
public boolean loop_replay = false;
public static InputEvent 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 = 20;
public static Random rand = new Random();
public EasyConfig conf;
public File records_folder;
@Override
public void onInitializeClient() {
LOGGER.info("Repeating mod initialized");
me = this;
now_record = null;
records_folder = new File(FabricLoader.getInstance().getGameDir().toFile(),"repeating_mod_records");
if (!records_folder.exists()) records_folder.mkdir();
record_list = new RecordList(records_folder);
record_list.loadRecords();
RenderSystem.init();
WorldRenderEvents.LAST.register(context -> {
WorldBuffer buffer = RenderHelper.startTri(context);
if (now_record != null) {
Vec3d start_pos = now_record.getStartRecordPos();
Vec3d finish_pos = now_record.getFinishRecordPos();
if (start_pos != null) drawRecordPos(buffer, start_pos, new Color(70, 230, 70, 128));
if (finish_pos != null) drawRecordPos(buffer, finish_pos, new Color(230, 70, 70, 128));
}
RenderHelper.endTri(buffer);
});
ClientTickEvents.END_CLIENT_TICK.register(client -> {
TickTask.tickTasks(TickTask.TickAt.CLIENT_EVENT);
});
Map<String,String> def = new HashMap<>();
def.put("record_pos_delay", String.valueOf(record_pos_delay));
conf = new EasyConfig(loader.getConfigDir(),"repeating-mod",def);
record_pos_delay = Long.parseLong(conf.data.get("record_pos_delay"));
menu_key = KeyBindingHelper.registerKeyBinding(new KeyBinding(
"key.repeating-mod.menu",InputUtil.Type.KEYSYM,
GLFW.GLFW_KEY_J,"text.repeating-mod.name"));
toggle_replay_key = KeyBindingHelper.registerKeyBinding(new KeyBinding(
"key.repeating-mod.toggle_replay",InputUtil.Type.KEYSYM,
-1,"text.repeating-mod.name"));
toggle_record_key = KeyBindingHelper.registerKeyBinding(new KeyBinding(
"key.repeating-mod.toggle_record",InputUtil.Type.KEYSYM,
-1,"text.repeating-mod.name"));
menu = new RepeatingScreen();
ClientTickEvents.END_CLIENT_TICK.register(client -> {
if (menu_key.wasPressed())
client.setScreen(menu);
if (toggle_replay_key.wasPressed()) {
if (now_record != null) {
if (!is_recording) {
if (is_replaying)
stopReplay();
else startReplay();
menu.updateButtons();
}
}
}
if (toggle_record_key.wasPressed()) {
if (!is_replaying) {
if (is_recording)
stopRecording();
else startRecording();
menu.updateButtons();
}
}
});
new TickTask(0,0) {
@Override
public void run() {
living_ticks++;
}
};
System.setProperty("java.awt.headless", "false");
}
public void setNowRecord(RecordState record) {
now_record = record;
}
public void drawRecordPos(WorldBuffer buffer, Vec3d pos, Color color) {
RenderHelper.drawRectFromTri(buffer,
(float) pos.getX() - 0.25F,
(float) pos.getY() + 0.01F,
(float) pos.getZ() - 0.25F,
(float) pos.getX() + 0.25F,
(float) pos.getY() + 0.01F,
(float) pos.getZ() - 0.25F,
(float) pos.getX() + 0.25F,
(float) pos.getY() + 0.01F,
(float) pos.getZ() + 0.25F,
(float) pos.getX() - 0.25F,
(float) pos.getY() + 0.01F,
(float) pos.getZ() + 0.25F,
color);
}
public void startRecording() {
is_recording = true;
menu.updateButtons();
now_record = record_list.newRecord();
Vec3d start_pos = client.player.getPos();
now_record.addEvent(new MoveEvent(start_pos,client.player.getHeadYaw(),client.player.getPitch()));
now_record.setStartRecordPos(start_pos);
if (record_pos_delay > 0) {
move_tick = new TickTask(
record_pos_delay,
record_pos_delay) {
@Override
public void run() {
now_record.addEvent(new MoveEvent(client.player.getPos(),
client.player.getHeadYaw(), client.player.getPitch()));
}
};
}
sendMessage(Text.translatable("message.repeating-mod.record_start"));
}
public void recordTick(RecordEvent e) {
if (is_recording) {
long now = living_ticks;
if (last_record != -1) {
long diff = now - last_record - 2;
if (diff > 0) now_record.addEvent(new DelayEvent(diff));
}
now_record.addEvent(e);
last_record = now;
}
}
public void recordAllInput() {
if (client.player == null) {
stopRecording();
return;
}
InputEvent l = ((InputEvent) now_record.getLastEvent("input"));
if (l == null) {
InputEvent e = new InputEvent(
client.player.input.sneaking,
client.player.input.jumping,
client.player.input.movementSideways,
client.player.input.movementForward,
client.player.input.pressingForward,
client.player.input.pressingBack,
client.player.input.pressingLeft,
client.player.input.pressingRight,
client.player.getHeadYaw(),
client.player.getBodyYaw(),
client.player.getPitch(),
client.player.isSprinting(),
client.player.getYaw(),
client.player.getMovementSpeed());
recordTick(e);
} else {
InputEvent e = new InputEvent(
((Boolean) client.player.input.sneaking == l.sneaking) ? null : client.player.input.sneaking,
((Boolean) client.player.input.jumping == l.jumping) ? null : client.player.input.jumping,
(((Float) client.player.input.movementSideways).equals(l.movementSideways)) ? null : client.player.input.movementSideways,
(((Float) client.player.input.movementForward).equals(l.movementForward)) ? null : client.player.input.movementForward,
((Boolean) client.player.input.pressingForward == l.pressingForward) ? null : client.player.input.pressingForward,
((Boolean) client.player.input.pressingBack == l.pressingBack) ? null : client.player.input.pressingBack,
((Boolean) client.player.input.pressingLeft == l.pressingLeft) ? null : client.player.input.pressingLeft,
((Boolean) client.player.input.pressingRight == l.pressingRight) ? null : client.player.input.pressingRight,
client.player.getHeadYaw(), Main.client.player.getBodyYaw(),client.player.getPitch(),
((Boolean) client.player.isSprinting() == l.sprinting) ? null : client.player.isSprinting(),
client.player.getYaw(),client.player.getMovementSpeed());
if (!(e.isEmpty() &&
e.yaw == l.yaw &&
e.head_yaw == l.head_yaw &&
e.pitch == l.pitch &&
e.body_yaw == l.body_yaw)) {
e.fillEmpty(l);
recordTick(e);
}
}
}
public void stopRecording() {
is_recording = false;
now_record.setFinishRecordPos(client.player.getPos());
try {
now_record.save();
} catch (IOException e) {
throw new RuntimeException(e);
}
if (move_tick != null) {
move_tick.cancel();
move_tick = null;
}
menu.updateButtons();
last_record = -1;
sendMessage(Text.translatable("message.repeating-mod.record_stop"));
}
public void startReplay() {
is_recording = false;
is_replaying = true;
menu.updateButtons();
List<RecordEvent> events = now_record.getEvents();
replay_tick = new TickTask(0,0, TickTask.TickAt.CLIENT_EVENT) {
public int replay_index = 0;
@Override
public void run() {
if (!is_replaying) {
cancel();
return;
}
RecordEvent e = events.get(replay_index);
if (e != null) {
if (e instanceof DelayEvent) {
setDelay(((DelayEvent) e).delay);
} else {
e.replay();
}
}
replay_index++;
if (!loop_replay) {
if (replay_index >= events.size()) {
stopReplay();
cancel();
}
} else if (replay_index >= events.size()) {
replay_index = 0;
}
}
};
sendMessage(Text.translatable("message.repeating-mod.replay_start"));
}
public void stopReplay() {
is_recording = false;
is_replaying = false;
if (replay_tick != null) {
replay_tick.cancel();
replay_tick = null;
}
try {
now_record.save();
} catch (IOException e) {
throw new RuntimeException(e);
}
menu.updateButtons();
record_list.getWidget().getWidget(now_record).getChildren().get(3).setMessage(Text.translatable("text.repeating-mod.start"));
sendMessage(Text.translatable("message.repeating-mod.replay_stop"));
}
public static void sendMessage(MutableText text) {
client.player.sendMessage(Text.literal("[")
.append(Text.translatable("text.repeating-mod.name"))
.append("] ").formatted(Formatting.BOLD,Formatting.DARK_GRAY)
.append(text.formatted(Formatting.RESET).formatted(Formatting.GRAY)));
}
public static void sendDebug(String s) {
client.player.sendMessage(Text.literal("[DEBUG] ").append(Text.of(s)));
}
}

View file

@ -51,6 +51,7 @@ public class RecordList {
}
public void addRecord(RecordState record) {
if (record == null) return;
records.add(record);
widget.addWidget(record);
}

View file

@ -96,6 +96,7 @@ public class RecordState {
}
public void addEvent(RecordEvent event) {
if (event == null) return;
events.add(event);
}
@ -124,9 +125,10 @@ public class RecordState {
.append(finish_record_pos.getY()).append("n")
.append(finish_record_pos.getZ());
for (int i = 0; i < events.size(); i++) {
for (RecordEvent event : events) {
if (event == null) continue;
text.append("\n");
text.append(events.get(i).serialize());
text.append(event.serialize());
}
Files.write(file.toPath(), text.toString().getBytes());

View file

@ -1,187 +1,187 @@
package themixray.repeating.mod;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.Drawable;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.Selectable;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.tooltip.Tooltip;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.SliderWidget;
import net.minecraft.text.Text;
import themixray.repeating.mod.widget.RecordListWidget;
import java.awt.*;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
@Environment(EnvType.CLIENT)
public class RepeatingScreen extends Screen {
private static List<RenderListener> render_listeners = new ArrayList<>();
public ButtonWidget record_btn;
public ButtonWidget loop_btn;
public ButtonWidget import_btn;
public SliderWidget pos_delay_slider;
public boolean was_build = false;
protected RepeatingScreen() {
super(Text.empty());
}
public static void addRenderListener(RenderListener render) {
render_listeners.add(render);
}
public static void removeRenderListener(RenderListener render) {
render_listeners.remove(render);
}
public void updateButtons() {
if (was_build) {
record_btn.setMessage(Text.translatable("text.repeating-mod." + ((Main.me.is_recording) ? "stop_record" : "start_record")));
loop_btn.setMessage(Text.translatable("text.repeating-mod." + ((Main.me.loop_replay) ? "off_loop" : "on_loop")));
}
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
renderBackground(context);
for (RenderListener l : render_listeners) {
if (l.beforeRender()) {
l.render(context, mouseX, mouseY, delta);
}
}
super.render(context, mouseX, mouseY, delta);
for (RenderListener l : render_listeners) {
if (!l.beforeRender()) {
l.render(context, mouseX, mouseY, delta);
}
}
}
@Override
protected void init() {
RecordListWidget list_widget = Main.me.record_list.getWidget();
list_widget.setX(width / 2 + 2);
list_widget.setY(height / 2 - list_widget.getHeight() / 2);
list_widget.init(this);
record_btn = ButtonWidget.builder(
Text.translatable("text.repeating-mod.start_record"), button -> {
if (!Main.me.is_replaying) {
if (Main.me.is_recording)
Main.me.stopRecording();
else Main.me.startRecording();
updateButtons();
}
})
.dimensions(width / 2 - 120, height / 2 - 32, 120, 20)
.tooltip(Tooltip.of(Text.translatable("text.repeating-mod.record_tooltip")))
.build();
loop_btn = ButtonWidget.builder(Text.empty(), button -> {
Main.me.loop_replay = !Main.me.loop_replay;
updateButtons();
})
.dimensions(width / 2 - 120, height / 2 - 10, 120, 20)
.tooltip(Tooltip.of(Text.translatable("text.repeating-mod.loop_tooltip")))
.build();
pos_delay_slider = new SliderWidget(
width / 2 - 120, height / 2 + 12, 120, 20,
(Main.me.record_pos_delay < 0) ? Text.translatable("text.repeating-mod.nan_pos_delay") :
Text.translatable("text.repeating-mod.pos_delay", String.valueOf(Main.me.record_pos_delay)),
(Main.me.record_pos_delay+1d)/101d) {
@Override
protected void updateMessage() {
double v = value*101d-1d;
if (v <= 1) setMessage(Text.translatable("text.repeating-mod.nan_pos_delay"));
else setMessage(Text.translatable("text.repeating-mod.pos_delay", String.valueOf((long) v)));
}
@Override
protected void applyValue() {
double v = value*101d-1d;
if (v <= 1) setMessage(Text.translatable("text.repeating-mod.nan_pos_delay"));
else setMessage(Text.translatable("text.repeating-mod.pos_delay", String.valueOf((long) v)));
Main.me.record_pos_delay = (long) v;
Main.me.conf.data.put("record_pos_delay",String.valueOf(Main.me.record_pos_delay));
Main.me.conf.save();
}
@Override
public void onRelease(double mouseX, double mouseY) {
super.onRelease(mouseX, mouseY);
applyValue();
}
@Override
protected void onDrag(double mouseX, double mouseY, double deltaX, double deltaY) {
super.onDrag(mouseX, mouseY, deltaX, deltaY);
applyValue();
}
};
pos_delay_slider.setTooltip(Tooltip.of(Text.translatable("text.repeating-mod.pos_delay_tooltip")));
import_btn = ButtonWidget.builder(Text.translatable("text.repeating-mod.import"), button -> {
new Thread(() -> {
FileDialog fd = new FileDialog((java.awt.Frame) null);
fd.setMultipleMode(true);
fd.setName("Choose record files");
fd.setTitle("Choose record files");
fd.setFilenameFilter((dir, name) -> name.endsWith(".rrm"));
fd.setVisible(true);
File[] files = fd.getFiles();
if (files != null) {
for (File file : files) {
try {
Main.me.setNowRecord(Main.me.record_list.cloneRecord(file));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}}).start();
})
.dimensions(width / 2 + 2, height / 2 - list_widget.getHeight() / 2 - 22, 180, 20)
.tooltip(Tooltip.of(Text.translatable("text.repeating-mod.import_tooltip")))
.build();
was_build = true;
updateButtons();
addDrawableChild(loop_btn);
addDrawableChild(record_btn);
addDrawableChild(import_btn);
addDrawableChild(pos_delay_slider);
}
public <T extends Element & Drawable & Selectable> T addDrawableChild(T drawableElement) {
return super.addDrawableChild(drawableElement);
}
public <T extends Drawable> T addDrawable(T drawable) {
return super.addDrawable(drawable);
}
public <T extends Element & Selectable> T addSelectableChild(T child) {
return super.addSelectableChild(child);
}
public void remove(Element child) {
super.remove(child);
}
}
package themixray.repeating.mod;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.Drawable;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.Selectable;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.tooltip.Tooltip;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.SliderWidget;
import net.minecraft.text.Text;
import themixray.repeating.mod.widget.RecordListWidget;
import java.awt.*;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
@Environment(EnvType.CLIENT)
public class RepeatingScreen extends Screen {
private static List<RenderListener> render_listeners = new ArrayList<>();
public ButtonWidget record_btn;
public ButtonWidget loop_btn;
public ButtonWidget import_btn;
public SliderWidget pos_delay_slider;
public boolean was_build = false;
protected RepeatingScreen() {
super(Text.empty());
}
public static void addRenderListener(RenderListener render) {
render_listeners.add(render);
}
public static void removeRenderListener(RenderListener render) {
render_listeners.remove(render);
}
public void updateButtons() {
if (was_build) {
record_btn.setMessage(Text.translatable("text.repeating-mod." + ((Main.me.is_recording) ? "stop_record" : "start_record")));
loop_btn.setMessage(Text.translatable("text.repeating-mod." + ((Main.me.loop_replay) ? "off_loop" : "on_loop")));
}
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
renderBackground(context);
for (RenderListener l : render_listeners) {
if (l.beforeRender()) {
l.render(context, mouseX, mouseY, delta);
}
}
super.render(context, mouseX, mouseY, delta);
for (RenderListener l : render_listeners) {
if (!l.beforeRender()) {
l.render(context, mouseX, mouseY, delta);
}
}
}
@Override
protected void init() {
RecordListWidget list_widget = Main.me.record_list.getWidget();
list_widget.setX(width / 2 + 2);
list_widget.setY(height / 2 - list_widget.getHeight() / 2);
list_widget.init(this);
record_btn = ButtonWidget.builder(
Text.translatable("text.repeating-mod.start_record"), button -> {
if (!Main.me.is_replaying) {
if (Main.me.is_recording)
Main.me.stopRecording();
else Main.me.startRecording();
updateButtons();
}
})
.dimensions(width / 2 - 120, height / 2 - 32, 120, 20)
.tooltip(Tooltip.of(Text.translatable("text.repeating-mod.record_tooltip")))
.build();
loop_btn = ButtonWidget.builder(Text.empty(), button -> {
Main.me.loop_replay = !Main.me.loop_replay;
updateButtons();
})
.dimensions(width / 2 - 120, height / 2 - 10, 120, 20)
.tooltip(Tooltip.of(Text.translatable("text.repeating-mod.loop_tooltip")))
.build();
pos_delay_slider = new SliderWidget(
width / 2 - 120, height / 2 + 12, 120, 20,
(Main.me.record_pos_delay < 0) ? Text.translatable("text.repeating-mod.nan_pos_delay") :
Text.translatable("text.repeating-mod.pos_delay", String.valueOf(Main.me.record_pos_delay)),
(Main.me.record_pos_delay+1d)/101d) {
@Override
protected void updateMessage() {
double v = value*101d-1d;
if (v <= 1) setMessage(Text.translatable("text.repeating-mod.nan_pos_delay"));
else setMessage(Text.translatable("text.repeating-mod.pos_delay", String.valueOf((long) v)));
}
@Override
protected void applyValue() {
double v = value*101d-1d;
if (v <= 1) setMessage(Text.translatable("text.repeating-mod.nan_pos_delay"));
else setMessage(Text.translatable("text.repeating-mod.pos_delay", String.valueOf((long) v)));
Main.me.record_pos_delay = (long) v;
Main.me.conf.data.put("record_pos_delay",String.valueOf(Main.me.record_pos_delay));
Main.me.conf.save();
}
@Override
public void onRelease(double mouseX, double mouseY) {
super.onRelease(mouseX, mouseY);
applyValue();
}
@Override
protected void onDrag(double mouseX, double mouseY, double deltaX, double deltaY) {
super.onDrag(mouseX, mouseY, deltaX, deltaY);
applyValue();
}
};
pos_delay_slider.setTooltip(Tooltip.of(Text.translatable("text.repeating-mod.pos_delay_tooltip")));
import_btn = ButtonWidget.builder(Text.translatable("text.repeating-mod.import"), button -> {
new Thread(() -> {
FileDialog fd = new FileDialog((java.awt.Frame) null);
fd.setMultipleMode(true);
fd.setName("Choose record files");
fd.setTitle("Choose record files");
fd.setFilenameFilter((dir, name) -> name.endsWith(".rrm"));
fd.setVisible(true);
File[] files = fd.getFiles();
if (files != null) {
for (File file : files) {
try {
Main.me.setNowRecord(Main.me.record_list.cloneRecord(file));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}}).start();
})
.dimensions(width / 2 + 2, height / 2 - list_widget.getHeight() / 2 - 22, 180, 20)
.tooltip(Tooltip.of(Text.translatable("text.repeating-mod.import_tooltip")))
.build();
was_build = true;
updateButtons();
addDrawableChild(loop_btn);
addDrawableChild(record_btn);
addDrawableChild(import_btn);
addDrawableChild(pos_delay_slider);
}
public <T extends Element & Drawable & Selectable> T addDrawableChild(T drawableElement) {
return super.addDrawableChild(drawableElement);
}
public <T extends Drawable> T addDrawable(T drawable) {
return super.addDrawable(drawable);
}
public <T extends Element & Selectable> T addSelectableChild(T child) {
return super.addSelectableChild(child);
}
public void remove(Element child) {
super.remove(child);
}
}

View file

@ -1,95 +1,95 @@
package themixray.repeating.mod;
import java.util.ArrayList;
import java.util.List;
public abstract class TickTask implements Runnable {
public static List<TickTask> 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,
CLIENT_EVENT
}
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++;
}
}
package themixray.repeating.mod;
import java.util.ArrayList;
import java.util.List;
public abstract class TickTask implements Runnable {
public static List<TickTask> 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,
CLIENT_EVENT
}
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++;
}
}

View file

@ -16,7 +16,7 @@ public class GuiMouseScrollEvent extends RecordEvent {
public void replay() {
if (Main.client.currentScreen != null) {
Main.client.currentScreen.mouseScrolled(mouseX, mouseY, amount);
// Main.client.currentScreen.mouseScrolled(mouseX, mouseY, amount);
}
}

View file

@ -1,24 +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.Main;
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 (Main.me.is_recording)
Main.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);
}
}
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.Main;
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 (Main.me.is_recording)
Main.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);
}
}

View file

@ -1,31 +1,31 @@
package themixray.repeating.mod.mixin;
import net.minecraft.entity.Entity;
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.Main;
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 (Main.client.player != null) {
if (getUuid().equals(Main.client.player.getUuid())) {
if (Main.me.is_replaying) {
if (Main.input_replay != null &&
Main.input_replay.sprinting != null &&
Main.input_replay.sprinting != sprinting) {
ci.cancel();
}
}
}
}
}
}
package themixray.repeating.mod.mixin;
import net.minecraft.entity.Entity;
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.Main;
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 (Main.client.player != null) {
if (getUuid().equals(Main.client.player.getUuid())) {
if (Main.me.is_replaying) {
if (Main.input_replay != null &&
Main.input_replay.sprinting != null &&
Main.input_replay.sprinting != sprinting) {
ci.cancel();
}
}
}
}
}
}

View file

@ -1,20 +1,20 @@
package themixray.repeating.mod.mixin;
import net.minecraft.client.input.KeyboardInput;
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.Main;
@Mixin(KeyboardInput.class)
public abstract class InputMixin {
@Inject(at = @At(value = "TAIL"), method = "tick")
private void onTickTail(boolean slowDown, float f, CallbackInfo ci) {
if (Main.me.is_replaying) {
if (Main.input_replay != null) {
Main.input_replay.inputCallback();
}
}
}
}
package themixray.repeating.mod.mixin;
import net.minecraft.client.input.KeyboardInput;
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.Main;
@Mixin(KeyboardInput.class)
public abstract class InputMixin {
@Inject(at = @At(value = "TAIL"), method = "tick")
private void onTickTail(boolean slowDown, float f, CallbackInfo ci) {
if (Main.me.is_replaying) {
if (Main.input_replay != null) {
Main.input_replay.inputCallback();
}
}
}
}

View file

@ -1,44 +1,44 @@
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.util.ActionResult;
import net.minecraft.util.hit.HitResult;
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.Main;
import themixray.repeating.mod.event.events.BlockBreakEvent;
import themixray.repeating.mod.event.events.BlockInteractEvent;
import themixray.repeating.mod.TickTask;
@Mixin(ClientPlayerEntity.class)
public abstract class MovementMixin {
@Inject(at = @At(value = "HEAD"), method = "init")
private void init(CallbackInfo ci) {
PlayerBlockBreakEvents.AFTER.register((world, player, pos, blockState, blockEntity) -> {
if (Main.me.is_recording)
Main.me.recordTick(new BlockBreakEvent(pos));
});
UseBlockCallback.EVENT.register((player, world, hand, hitResult) -> {
if (hitResult.getType().equals(HitResult.Type.BLOCK))
if (Main.me.is_recording)
Main.me.recordTick(new BlockInteractEvent(hand,hitResult));
return ActionResult.PASS;
});
}
@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 onMoveTail(CallbackInfo ci) {
TickTask.tickTasks(TickTask.TickAt.MOVEMENT_TAIL);
}
}
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.util.ActionResult;
import net.minecraft.util.hit.HitResult;
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.Main;
import themixray.repeating.mod.event.events.BlockBreakEvent;
import themixray.repeating.mod.event.events.BlockInteractEvent;
import themixray.repeating.mod.TickTask;
@Mixin(ClientPlayerEntity.class)
public abstract class MovementMixin {
@Inject(at = @At(value = "HEAD"), method = "init")
private void init(CallbackInfo ci) {
PlayerBlockBreakEvents.AFTER.register((world, player, pos, blockState, blockEntity) -> {
if (Main.me.is_recording)
Main.me.recordTick(new BlockBreakEvent(pos));
});
UseBlockCallback.EVENT.register((player, world, hand, hitResult) -> {
if (hitResult.getType().equals(HitResult.Type.BLOCK))
if (Main.me.is_recording)
Main.me.recordTick(new BlockInteractEvent(hand,hitResult));
return ActionResult.PASS;
});
}
@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 onMoveTail(CallbackInfo ci) {
TickTask.tickTasks(TickTask.TickAt.MOVEMENT_TAIL);
}
}

View file

@ -1,29 +1,29 @@
package themixray.repeating.mod.mixin;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.network.listener.ServerPlayPacketListener;
import net.minecraft.network.packet.Packet;
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 java.time.Duration;
import java.util.function.BooleanSupplier;
@Mixin(ClientPlayNetworkHandler.class)
public abstract class NetworkMixin {
// @Inject(at = @At(value = "HEAD"), method = "sendPacket(Lnet/minecraft/network/packet/Packet;)V")
// private void onSendPacket1Head(Packet<?> packet,
// CallbackInfo ci) {
//
// }
//
// @Inject(at = @At(value = "HEAD"), method = "sendPacket(Lnet/minecraft/network/packet/Packet;Ljava/util/function/BooleanSupplier;Ljava/time/Duration;)V")
// private void onSendPacket2Head(Packet<ServerPlayPacketListener> packet,
// BooleanSupplier sendCondition,
// Duration expirationTime,
// CallbackInfo ci) {
//
// }
}
package themixray.repeating.mod.mixin;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.network.listener.ServerPlayPacketListener;
import net.minecraft.network.packet.Packet;
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 java.time.Duration;
import java.util.function.BooleanSupplier;
@Mixin(ClientPlayNetworkHandler.class)
public abstract class NetworkMixin {
// @Inject(at = @At(value = "HEAD"), method = "sendPacket(Lnet/minecraft/network/packet/Packet;)V")
// private void onSendPacket1Head(Packet<?> packet,
// CallbackInfo ci) {
//
// }
//
// @Inject(at = @At(value = "HEAD"), method = "sendPacket(Lnet/minecraft/network/packet/Packet;Ljava/util/function/BooleanSupplier;Ljava/time/Duration;)V")
// private void onSendPacket2Head(Packet<ServerPlayPacketListener> packet,
// BooleanSupplier sendCondition,
// Duration expirationTime,
// CallbackInfo ci) {
//
// }
}

View file

@ -1,21 +1,21 @@
package themixray.repeating.mod.mixin;
import net.minecraft.client.render.*;
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.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) {
TickTask.tickTasks(TickTask.TickAt.RENDER_TAIL);
}
}
package themixray.repeating.mod.mixin;
import net.minecraft.client.render.*;
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.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) {
TickTask.tickTasks(TickTask.TickAt.RENDER_TAIL);
}
}

View file

@ -80,11 +80,11 @@ public abstract class ScreenMixin extends AbstractParentElement implements Drawa
return super.mouseReleased(mouseX, mouseY, button);
}
@Override
public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
if (Main.me.is_recording) {
// Main.me.now_record.addEvent(new GuiMouseScrollEvent(mouseX, mouseY, amount));
}
return super.mouseScrolled(mouseX, mouseY, amount);
}
// @Override
// public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
// if (Main.me.is_recording) {
//// Main.me.now_record.addEvent(new GuiMouseScrollEvent(mouseX, mouseY, amount));
// }
// return super.mouseScrolled(mouseX, mouseY, amount);
// }
}

View file

@ -134,7 +134,8 @@ public class RecordWidget implements Drawable, Widget {
children.add(export_button);
ButtonWidget replay_button = ButtonWidget.builder(Text.translatable("text.repeating-mod.start"), (i) -> {
ButtonWidget replay_button = ButtonWidget.builder(Text.translatable("text.repeating-mod." +
(getRecord().equals(Main.me.now_record) && Main.me.is_replaying ? "stop" : "start")), (i) -> {
if (Main.me.is_replaying) {
Main.me.stopReplay();
if (getRecord().equals(Main.me.now_record)) {
@ -143,7 +144,7 @@ public class RecordWidget implements Drawable, Widget {
}
i.setMessage(Text.translatable("text.repeating-mod.stop"));
Main.me.now_record = record;
Main.me.now_record = getRecord();
Main.me.startReplay();
Main.client.setScreen(null);
}).dimensions(parent.getX() + getX() + 110,parent.getY() + getY() + 4 + 28, 65, 13)

View file

@ -1,17 +1,17 @@
{
"providers": [
{
"file":"repeating-mod:ui/no-loop.png",
"chars":["\ueffe"],
"height":16,
"ascent":12,
"type":"bitmap"
},{
"file":"repeating-mod:ui/loop.png",
"chars":["\uefff"],
"height":16,
"ascent":12,
"type":"bitmap"
}
]
{
"providers": [
{
"file":"repeating-mod:ui/no-loop.png",
"chars":["\ueffe"],
"height":16,
"ascent":12,
"type":"bitmap"
},{
"file":"repeating-mod:ui/loop.png",
"chars":["\uefff"],
"height":16,
"ascent":12,
"type":"bitmap"
}
]
}

View file

@ -1,36 +1,36 @@
{
"key.repeating-mod.menu": "Repeating menu",
"key.repeating-mod.toggle_replay": "Toggle replay",
"key.repeating-mod.toggle_record": "Toggle recording",
"text.repeating-mod.name": "Repeating Mod",
"text.repeating-mod.start_record": "Start record",
"text.repeating-mod.stop_record": "Stop record",
"text.repeating-mod.start_replay": "Start replay",
"text.repeating-mod.stop_replay": "Stop replay",
"text.repeating-mod.record_tooltip": "Start/stop recording all activities",
"text.repeating-mod.replay_tooltip": "Start/stop repeating recorded actions",
"text.repeating-mod.loop_tooltip": "Enable/disable repeating of recorded actions replay",
"text.repeating-mod.export_record": "Export record",
"text.repeating-mod.import": "Import record",
"text.repeating-mod.export_tooltip": "Exporting a recording to a file",
"text.repeating-mod.import_tooltip": "Importing a recording from a file",
"text.repeating-mod.dev": "In development...",
"text.repeating-mod.nan_pos_delay": "No pos timer",
"text.repeating-mod.pos_delay": "Pos timer: %s ticks",
"text.repeating-mod.pos_delay_tooltip": "Timer after which the pos\nevent is added (20 ticks = 1 sec)",
"text.repeating-mod.unnamed": "Unnamed Record",
"text.repeating-mod.on_loop": "Enable repeat",
"text.repeating-mod.off_loop": "Disable repeat",
"text.repeating-mod.recorded_at": "Recorded at",
"text.repeating-mod.author": "Author",
"text.repeating-mod.delete": "Delete",
"text.repeating-mod.start": "Start",
"text.repeating-mod.stop": "Stop",
"text.repeating-mod.export": "Export",
"message.repeating-mod.replay_start": "Replay started",
"message.repeating-mod.replay_stop": "Replay finished",
"message.repeating-mod.record_start": "Record started",
"message.repeating-mod.record_stop": "Record finished"
{
"key.repeating-mod.menu": "Repeating menu",
"key.repeating-mod.toggle_replay": "Toggle replay",
"key.repeating-mod.toggle_record": "Toggle recording",
"text.repeating-mod.name": "Repeating Mod",
"text.repeating-mod.start_record": "Start record",
"text.repeating-mod.stop_record": "Stop record",
"text.repeating-mod.start_replay": "Start replay",
"text.repeating-mod.stop_replay": "Stop replay",
"text.repeating-mod.record_tooltip": "Start/stop recording all activities",
"text.repeating-mod.replay_tooltip": "Start/stop repeating recorded actions",
"text.repeating-mod.loop_tooltip": "Enable/disable repeating of recorded actions replay",
"text.repeating-mod.export_record": "Export record",
"text.repeating-mod.import": "Import record",
"text.repeating-mod.export_tooltip": "Exporting a recording to a file",
"text.repeating-mod.import_tooltip": "Importing a recording from a file",
"text.repeating-mod.dev": "In development...",
"text.repeating-mod.nan_pos_delay": "No pos timer",
"text.repeating-mod.pos_delay": "Pos timer: %s ticks",
"text.repeating-mod.pos_delay_tooltip": "Timer after which the pos\nevent is added (20 ticks = 1 sec)",
"text.repeating-mod.unnamed": "Unnamed Record",
"text.repeating-mod.on_loop": "Enable repeat",
"text.repeating-mod.off_loop": "Disable repeat",
"text.repeating-mod.recorded_at": "Recorded at",
"text.repeating-mod.author": "Author",
"text.repeating-mod.delete": "Delete",
"text.repeating-mod.start": "Start",
"text.repeating-mod.stop": "Stop",
"text.repeating-mod.export": "Export",
"message.repeating-mod.replay_start": "Replay started",
"message.repeating-mod.replay_stop": "Replay finished",
"message.repeating-mod.record_start": "Record started",
"message.repeating-mod.record_stop": "Record finished"
}

View file

@ -1,38 +1,38 @@
{
"key.repeating-mod.menu": "Меню репитинга",
"key.repeating-mod.toggle_replay": "Вкл/выкл повтор",
"key.repeating-mod.toggle_record": "Вкл/выкл запись",
"text.repeating-mod.name": "Репитинг Мод",
"text.repeating-mod.start_record": "Начать запись",
"text.repeating-mod.stop_record": "Остановить запись",
"text.repeating-mod.start_replay": "Начать повтор",
"text.repeating-mod.stop_replay": "Остановить повтор",
"text.repeating-mod.record_tooltip": "Начать/остановить запись всех действий",
"text.repeating-mod.replay_tooltip": "Начать/остановить повтор записанных действий",
"text.repeating-mod.loop_tooltip": "Вкл/выкл повтор записи",
"text.repeating-mod.import": "Импорт записи",
"text.repeating-mod.export_tooltip": "Экспорт записи в файл",
"text.repeating-mod.import_tooltip": "Импорт записи из файла",
"text.repeating-mod.dev": "В разработке...",
"text.repeating-mod.nan_pos_delay": "Таймера позиции нету",
"text.repeating-mod.pos_delay": "Таймер позиции: %s тиков",
"text.repeating-mod.pos_delay_tooltip": "Таймер, после которой добавляется\nивент позиции (20 тиков = 1 сек)",
"text.repeating-mod.unnamed": "Безымянная Запись",
"text.repeating-mod.on_loop": "Включить повторение",
"text.repeating-mod.off_loop": "Выключить повторение",
"text.repeating-mod.recorded_at": "Записано в",
"text.repeating-mod.author": "Автор",
"message.repeating-mod.replay_start": "Повтор начат",
"message.repeating-mod.replay_stop": "Повтор закончен",
"message.repeating-mod.record_start": "Запись начата",
"message.repeating-mod.record_stop": "Запись закончена",
"text.repeating-mod.export_record": "Экпорт записи",
"text.repeating-mod.export": "Экспорт",
"text.repeating-mod.delete": "Удалить",
"text.repeating-mod.start": "Старт",
"text.repeating-mod.stop": "Стоп"
}
{
"key.repeating-mod.menu": "Меню репитинга",
"key.repeating-mod.toggle_replay": "Вкл/выкл повтор",
"key.repeating-mod.toggle_record": "Вкл/выкл запись",
"text.repeating-mod.name": "Репитинг Мод",
"text.repeating-mod.start_record": "Начать запись",
"text.repeating-mod.stop_record": "Остановить запись",
"text.repeating-mod.start_replay": "Начать повтор",
"text.repeating-mod.stop_replay": "Остановить повтор",
"text.repeating-mod.record_tooltip": "Начать/остановить запись всех действий",
"text.repeating-mod.replay_tooltip": "Начать/остановить повтор записанных действий",
"text.repeating-mod.loop_tooltip": "Вкл/выкл повтор записи",
"text.repeating-mod.import": "Импорт записи",
"text.repeating-mod.export_tooltip": "Экспорт записи в файл",
"text.repeating-mod.import_tooltip": "Импорт записи из файла",
"text.repeating-mod.dev": "В разработке...",
"text.repeating-mod.nan_pos_delay": "Таймера позиции нету",
"text.repeating-mod.pos_delay": "Таймер позиции: %s тиков",
"text.repeating-mod.pos_delay_tooltip": "Таймер, после которой добавляется\nивент позиции (20 тиков = 1 сек)",
"text.repeating-mod.unnamed": "Безымянная Запись",
"text.repeating-mod.on_loop": "Включить повторение",
"text.repeating-mod.off_loop": "Выключить повторение",
"text.repeating-mod.recorded_at": "Записано в",
"text.repeating-mod.author": "Автор",
"message.repeating-mod.replay_start": "Повтор начат",
"message.repeating-mod.replay_stop": "Повтор закончен",
"message.repeating-mod.record_start": "Запись начата",
"message.repeating-mod.record_stop": "Запись закончена",
"text.repeating-mod.export_record": "Экпорт записи",
"text.repeating-mod.export": "Экспорт",
"text.repeating-mod.delete": "Удалить",
"text.repeating-mod.start": "Старт",
"text.repeating-mod.stop": "Стоп"
}

View file

@ -1,38 +1,38 @@
{
"schemaVersion": 1,
"id": "repeating-mod",
"version": "${version}",
"name": "Repeating Mod",
"description": "Mod that repeats your recorded actions. ",
"authors": [
"TheMixRay"
],
"contact": {
"homepage": "https://modrinth.com/mod/repeating-mod",
"sources": "https://github.com/MeexReay/repeating-mod"
},
"license": "CC0-1.0",
"icon": "icon.png",
"environment": "client",
"entrypoints": {
"client": [
"themixray.repeating.mod.Main"
]
},
"mixins": [
"repeating-mod.mixins.json"
],
"depends": {
"fabricloader": ">=0.14.14",
"fabric-api": "*",
"minecraft": ">=1.20",
"java": ">=17"
},
"suggests": {
"another-mod": "*"
}
}
{
"schemaVersion": 1,
"id": "repeating-mod",
"version": "${version}",
"name": "Repeating Mod",
"description": "Mod that repeats your recorded actions. ",
"authors": [
"TheMixRay"
],
"contact": {
"homepage": "https://modrinth.com/mod/repeating-mod",
"sources": "https://github.com/MeexReay/repeating-mod"
},
"license": "CC0-1.0",
"icon": "icon.png",
"environment": "client",
"entrypoints": {
"client": [
"themixray.repeating.mod.Main"
]
},
"mixins": [
"repeating-mod.mixins.json"
],
"depends": {
"fabricloader": ">=0.14.14",
"fabric-api": "*",
"minecraft": ">=1.20",
"java": ">=17"
},
"suggests": {
"another-mod": "*"
}
}

View file

@ -1,20 +1,20 @@
{
"required": true,
"minVersion": "0.8",
"package": "themixray.repeating.mod.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
],
"client": [
"MovementMixin",
"InputMixin",
"RendererMixin",
"EntityMixin",
"ClientMixin",
"ScreenMixin",
"PlayerMixin"
],
"injectors": {
"defaultRequire": 1
}
}
{
"required": true,
"minVersion": "0.8",
"package": "themixray.repeating.mod.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
],
"client": [
"MovementMixin",
"InputMixin",
"RendererMixin",
"EntityMixin",
"ClientMixin",
"ScreenMixin",
"PlayerMixin"
],
"injectors": {
"defaultRequire": 1
}
}