diff --git a/gradle.properties b/gradle.properties index 9109b7d..a80352b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,12 +4,12 @@ org.gradle.parallel=true # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.20 -yarn_mappings=1.20+build.1 -loader_version=0.14.23 +minecraft_version=1.20.1 +yarn_mappings=1.20.1+build.10 +loader_version=0.15.10 #Fabric api -fabric_version=0.83.0+1.20 +fabric_version=0.92.1+1.20.1 # Mod Properties mod_version = 1.0.6 diff --git a/src/main/java/themixray/repeating/mod/Main.java b/src/main/java/themixray/repeating/mod/Main.java index 151c8af..9eb4e53 100644 --- a/src/main/java/themixray/repeating/mod/Main.java +++ b/src/main/java/themixray/repeating/mod/Main.java @@ -1,6 +1,5 @@ package themixray.repeating.mod; -import com.google.common.collect.Lists; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; @@ -16,28 +15,29 @@ import net.minecraft.util.math.Vec3d; import org.lwjgl.glfw.GLFW; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import themixray.repeating.mod.events.RecordDelayEvent; -import themixray.repeating.mod.events.RecordEvent; -import themixray.repeating.mod.events.RecordInputEvent; -import themixray.repeating.mod.events.RecordMoveEvent; +import themixray.repeating.mod.event.RecordDelayEvent; +import themixray.repeating.mod.event.RecordEvent; +import themixray.repeating.mod.event.RecordInputEvent; +import themixray.repeating.mod.event.RecordMoveEvent; 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 RepeatingMod implements ClientModInitializer { +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 RepeatingMod me; + public static Main me; - public Vec3d start_record_pos = null; - public Vec3d finish_record_pos = null; + public RecordList record_list; + public RecordState now_record; - public List record = new ArrayList<>(); public boolean is_recording = false; public long last_record = -1; public TickTask move_tick = null; @@ -59,52 +59,30 @@ public class RepeatingMod implements ClientModInitializer { 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 (start_record_pos != null) { - RenderHelper.drawRectFromTri(buffer, - (float) start_record_pos.getX() - 0.25F, - (float) start_record_pos.getY() + 0.01F, - (float) start_record_pos.getZ() - 0.25F, + if (now_record != null) { + Vec3d start_pos = now_record.getStartRecordPos(); + Vec3d finish_pos = now_record.getFinishRecordPos(); - (float) start_record_pos.getX() + 0.25F, - (float) start_record_pos.getY() + 0.01F, - (float) start_record_pos.getZ() - 0.25F, - - (float) start_record_pos.getX() + 0.25F, - (float) start_record_pos.getY() + 0.01F, - (float) start_record_pos.getZ() + 0.25F, - - (float) start_record_pos.getX() - 0.25F, - (float) start_record_pos.getY() + 0.01F, - (float) start_record_pos.getZ() + 0.25F, - new Color(70,230,70,128)); - } - if (finish_record_pos != null) { - RenderHelper.drawRectFromTri(buffer, - (float) finish_record_pos.getX() - 0.25F, - (float) finish_record_pos.getY() + 0.01F, - (float) finish_record_pos.getZ() - 0.25F, - - (float) finish_record_pos.getX() + 0.25F, - (float) finish_record_pos.getY() + 0.01F, - (float) finish_record_pos.getZ() - 0.25F, - - (float) finish_record_pos.getX() + 0.25F, - (float) finish_record_pos.getY() + 0.01F, - (float) finish_record_pos.getZ() + 0.25F, - - (float) finish_record_pos.getX() - 0.25F, - (float) finish_record_pos.getY() + 0.01F, - (float) finish_record_pos.getZ() + 0.25F, - new Color(230,70,70,128)); + 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); }); @@ -131,11 +109,13 @@ public class RepeatingMod implements ClientModInitializer { if (menu_key.wasPressed()) client.setScreen(menu); if (toggle_replay_key.wasPressed()) { - if (!is_recording) { - if (is_replaying) - stopReplay(); - else startReplay(); - menu.update_btns(); + if (now_record != null) { + if (!is_recording) { + if (is_replaying) + stopReplay(); + else startReplay(); + menu.updateButtons(); + } } } if (toggle_record_key.wasPressed()) { @@ -143,7 +123,7 @@ public class RepeatingMod implements ClientModInitializer { if (is_recording) stopRecording(); else startRecording(); - menu.update_btns(); + menu.updateButtons(); } } }); @@ -154,26 +134,43 @@ public class RepeatingMod implements ClientModInitializer { living_ticks++; } }; + + System.setProperty("java.awt.headless", "false"); } - public RecordEvent getLastRecord(String t) { - for (RecordEvent r:Lists.reverse(new ArrayList<>(record))) { - if (r.getType().equals(t)) { - return r; - } - } - return null; + 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.update_btns(); - record.clear(); + menu.updateButtons(); - finish_record_pos = null; - Vec3d v = client.player.getPos(); - record.add(new RecordMoveEvent(v,client.player.getHeadYaw(),client.player.getPitch())); - start_record_pos = v; + now_record = record_list.newRecord(); + + Vec3d start_pos = client.player.getPos(); + now_record.addEvent(new RecordMoveEvent(start_pos,client.player.getHeadYaw(),client.player.getPitch())); + now_record.setStartRecordPos(start_pos); if (record_pos_delay > 0) { move_tick = new TickTask( @@ -181,7 +178,7 @@ public class RepeatingMod implements ClientModInitializer { record_pos_delay) { @Override public void run() { - record.add(new RecordMoveEvent(client.player.getPos(), + now_record.addEvent(new RecordMoveEvent(client.player.getPos(), client.player.getHeadYaw(), client.player.getPitch())); } }; @@ -195,15 +192,20 @@ public class RepeatingMod implements ClientModInitializer { long now = living_ticks; if (last_record != -1) { long diff = now - last_record - 2; - if (diff > 0) record.add(new RecordDelayEvent(diff)); + if (diff > 0) now_record.addEvent(new RecordDelayEvent(diff)); } - record.add(e); + now_record.addEvent(e); last_record = now; } } public void recordAllInput() { - RecordInputEvent l = ((RecordInputEvent)getLastRecord("input")); + if (client.player == null) { + stopRecording(); + return; + } + + RecordInputEvent l = ((RecordInputEvent) now_record.getLastEvent("input")); if (l == null) { RecordInputEvent e = new RecordInputEvent( client.player.input.sneaking, @@ -231,7 +233,7 @@ public class RepeatingMod implements ClientModInitializer { ((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(),RepeatingMod.client.player.getBodyYaw(),client.player.getPitch(), + 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()); @@ -248,12 +250,17 @@ public class RepeatingMod implements ClientModInitializer { public void stopRecording() { is_recording = false; - finish_record_pos = client.player.getPos(); - if (move_tick != null) { + 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.update_btns(); + menu.updateButtons(); last_record = -1; sendMessage(Text.translatable("message.repeating-mod.record_stop")); } @@ -262,14 +269,17 @@ public class RepeatingMod implements ClientModInitializer { public void startReplay() { is_recording = false; is_replaying = true; - menu.update_btns(); + menu.updateButtons(); + + List events = now_record.getEvents(); + 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); + RecordEvent e = events.get(replay_index); if (e instanceof RecordDelayEvent) { setDelay(((RecordDelayEvent) e).delay); } else { @@ -278,11 +288,11 @@ public class RepeatingMod implements ClientModInitializer { replay_index++; if (!loop_replay) { - if (replay_index == record.size()) { + if (replay_index == events.size()) { stopReplay(); cancel(); } - } else if (replay_index == record.size()) { + } else if (replay_index == events.size()) { replay_index = 0; } } @@ -298,7 +308,8 @@ public class RepeatingMod implements ClientModInitializer { replay_tick.cancel(); replay_tick = null; } - menu.update_btns(); + 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")); } diff --git a/src/main/java/themixray/repeating/mod/RecordList.java b/src/main/java/themixray/repeating/mod/RecordList.java index 907989f..b1a3c1d 100644 --- a/src/main/java/themixray/repeating/mod/RecordList.java +++ b/src/main/java/themixray/repeating/mod/RecordList.java @@ -1,5 +1,77 @@ package themixray.repeating.mod; -public class RecordList { +import net.minecraft.text.Text; +import themixray.repeating.mod.widget.RecordListWidget; +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class RecordList { + private final File folder; + private List records; + private RecordListWidget widget; + + public RecordList(File folder) { + this.folder = folder; + this.records = new ArrayList<>(); + this.widget = new RecordListWidget(0, 0, 120, 80); + } + + public List getRecords() { + return records; + } + + public File getFolder() { + return folder; + } + + public RecordListWidget getWidget() { + return widget; + } + + public void loadRecords() { + for (File file : folder.listFiles()) { + try { + addRecord(file); + } catch (Exception e) {} + } + } + + public void addRecord(File file) throws Exception { + addRecord(RecordState.load(file)); + } + + public void addRecord(RecordState record) { + records.add(record); + widget.addWidget(record); + } + + public void removeRecord(RecordState record) { + records.remove(record); + widget.removeWidget(record); + } + + public RecordState newRecord() { + Date date = new Date(); + String name = "Unnamed"; + String author = Main.client.player.getName().getString(); + + File file = new File(Main.me.records_folder, + "record_" + RecordState.FILE_DATE_FORMAT.format(date) + + "_" + Main.rand.nextInt(10) + ".rrm"); + + RecordState state = new RecordState( + file, name, date, author, + new ArrayList<>(), + null, + null); + + addRecord(state); + + return state; + } } diff --git a/src/main/java/themixray/repeating/mod/RecordState.java b/src/main/java/themixray/repeating/mod/RecordState.java index 4a55c68..fe844c8 100644 --- a/src/main/java/themixray/repeating/mod/RecordState.java +++ b/src/main/java/themixray/repeating/mod/RecordState.java @@ -1,32 +1,38 @@ package themixray.repeating.mod; -import net.minecraft.text.Text; +import com.google.common.collect.Lists; import net.minecraft.util.math.Vec3d; -import themixray.repeating.mod.events.RecordEvent; +import themixray.repeating.mod.event.RecordEvent; +import java.awt.*; import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.List; -public class RecordFile { +public class RecordState { + public static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM.dd.yyyy HH:mm:ss"); + public static SimpleDateFormat FILE_DATE_FORMAT = new SimpleDateFormat("MM-dd-yyyy_HH-mm-ss"); + private final File file; private String name; - private String date; + private Date date; private String author; private List events; private Vec3d start_record_pos; private Vec3d finish_record_pos; - public RecordFile(File file, - String name, - String date, - String author, - List events, - Vec3d start_record_pos, - Vec3d finish_record_pos) { + public RecordState(File file, + String name, + Date date, + String author, + List events, + Vec3d start_record_pos, + Vec3d finish_record_pos) { this.file = file; this.name = name; this.date = date; @@ -49,15 +55,27 @@ public class RecordFile { return author; } - public String getDate() { + public Date getDate() { return date; } + public List getEvents() { + return events; + } + + public Vec3d getFinishRecordPos() { + return finish_record_pos; + } + + public Vec3d getStartRecordPos() { + return start_record_pos; + } + public void setAuthor(String author) { this.author = author; } - public void setDate(String date) { + public void setDate(Date date) { this.date = date; } @@ -65,26 +83,66 @@ public class RecordFile { this.name = name; } - public void writeToMod() { - + public void setEvents(List events) { + this.events = events; } - public static void readFromMod() { - + public void setFinishRecordPos(Vec3d finish_record_pos) { + this.finish_record_pos = finish_record_pos; } - public void writeToFile(File file) { - + public void setStartRecordPos(Vec3d start_record_pos) { + this.start_record_pos = start_record_pos; } - public static RecordFile readFromFile(File file) throws IOException { + public void addEvent(RecordEvent event) { + events.add(event); + } + + public RecordEvent getLastEvent(String type) { + for (RecordEvent r: Lists.reverse(new ArrayList<>(events))) { + if (r.getType().equals(type)) { + return r; + } + } + return null; + } + + public void save() throws IOException { + StringBuilder text = new StringBuilder(); + + text.append(name).append("\n") + .append(DATE_FORMAT.format(date)).append("\n") + .append(author).append("\n"); + + text.append(start_record_pos.getX()).append("n") + .append(start_record_pos.getY()).append("n") + .append(start_record_pos.getZ()).append("x") + .append(finish_record_pos.getX()).append("n") + .append(finish_record_pos.getY()).append("n") + .append(finish_record_pos.getZ()); + + for (int i = 0; i < events.size(); i++) { + text.append("\n"); + text.append(events.get(i).serialize()); + } + + Files.write(file.toPath(), text.toString().getBytes()); + + if (Desktop.isDesktopSupported()) { + Desktop desktop = Desktop.getDesktop(); + desktop.browse(file.toURI()); + } + } + + public static RecordState load(File file) throws Exception { String text = Files.readString(file.toPath()); List lines = List.of(text.split("\n")); List signature = lines.subList(0,4); String name = signature.get(0); - String data = signature.get(1); + Date date = DATE_FORMAT.parse(signature.get(1)); String author = signature.get(2); String record_pos = signature.get(3); @@ -105,6 +163,12 @@ public class RecordFile { List event_lines = lines.subList(4,lines.size()); List events = event_lines.stream().map(RecordEvent::deserialize).toList(); - return new RecordFile(file, ) + return new RecordState(file, name, date, author, events, start_record_pos, finish_record_pos); + } + + public void remove() { + file.delete(); + Main.me.record_list.removeRecord(this); + Main.me.record_list.getWidget().removeWidget(this); } } diff --git a/src/main/java/themixray/repeating/mod/RenderListener.java b/src/main/java/themixray/repeating/mod/RenderListener.java new file mode 100644 index 0000000..9992e48 --- /dev/null +++ b/src/main/java/themixray/repeating/mod/RenderListener.java @@ -0,0 +1,11 @@ +package themixray.repeating.mod; + +import net.minecraft.client.gui.DrawContext; + +public interface RenderListener { + default boolean beforeRender() { + return true; + } + + void render(DrawContext context, int mouseX, int mouseY, float delta); +} diff --git a/src/main/java/themixray/repeating/mod/RepeatingScreen.java b/src/main/java/themixray/repeating/mod/RepeatingScreen.java index 6679c99..ed3ccb8 100644 --- a/src/main/java/themixray/repeating/mod/RepeatingScreen.java +++ b/src/main/java/themixray/repeating/mod/RepeatingScreen.java @@ -2,182 +2,99 @@ package themixray.repeating.mod; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.fabricmc.loader.api.FabricLoader; 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 net.minecraft.util.math.Vec3d; -import themixray.repeating.mod.events.RecordEvent; -import javax.swing.*; import java.awt.*; import java.io.File; -import java.nio.file.Files; -import java.text.SimpleDateFormat; -import java.util.Date; +import java.util.ArrayList; import java.util.List; @Environment(EnvType.CLIENT) public class RepeatingScreen extends Screen { - protected RepeatingScreen() { - super(Text.literal("")); - this.mod = RepeatingMod.me; - } - - public RepeatingMod mod; + private static List render_listeners = new ArrayList<>(); public ButtonWidget record_btn; - public ButtonWidget replay_btn; public ButtonWidget loop_btn; - - public ButtonWidget export_btn; public ButtonWidget import_btn; public SliderWidget pos_delay_slider; public boolean was_build = false; - public void update_btns() { + 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) { - replay_btn.setMessage(Text.translatable("text.repeating-mod." + - ((mod.is_replaying) ? "stop_replay" : "start_replay"))); - record_btn.setMessage(Text.translatable("text.repeating-mod." + - ((mod.is_recording) ? "stop_record" : "start_record"))); - loop_btn.setMessage(Text.of(((mod.loop_replay) ? "\uefff " : "\ueffe "))); + 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() { record_btn = ButtonWidget.builder( Text.translatable("text.repeating-mod.start_record"), button -> { - if (!mod.is_replaying) { - if (mod.is_recording) - mod.stopRecording(); - else mod.startRecording(); - update_btns(); + if (!Main.me.is_replaying) { + if (Main.me.is_recording) + Main.me.stopRecording(); + else Main.me.startRecording(); + updateButtons(); } }) - .dimensions(width / 2 - 60, height / 2 - 54, 120, 20) + .dimensions(width / 2 - 60, height / 2 - 76, 120, 20) .tooltip(Tooltip.of(Text.translatable("text.repeating-mod.record_tooltip"))) .build(); - replay_btn = ButtonWidget.builder( - Text.translatable("text.repeating-mod.start_replay"), button -> { - if (!mod.is_recording) { - if (mod.is_replaying) - mod.stopReplay(); - else mod.startReplay(); - update_btns(); - } + loop_btn = ButtonWidget.builder(Text.empty(), button -> { + Main.me.loop_replay = !Main.me.loop_replay; + updateButtons(); }) - .dimensions(width / 2 - 60, height / 2 - 32, 98, 20) - .tooltip(Tooltip.of(Text.translatable("text.repeating-mod.replay_tooltip"))) - .build(); - - loop_btn = ButtonWidget.builder(Text.of(""), button -> { - mod.loop_replay = !mod.loop_replay; - update_btns(); - }) - .dimensions(width / 2 + 40, height / 2 - 32, 20, 20) + .dimensions(width / 2 - 60, height / 2 - 54, 120, 20) .tooltip(Tooltip.of(Text.translatable("text.repeating-mod.loop_tooltip"))) .build(); - export_btn = ButtonWidget.builder( - Text.translatable("text.repeating-mod.export"), button -> { - if (mod.finish_record_pos == null) return; - StringBuilder t = new StringBuilder(); - for (int i = 0; i < mod.record.size(); i++) { - t.append(mod.record.get(i).serialize()); - t.append("\n"); - } - t.append(mod.start_record_pos.getX()+"n"+ - mod.start_record_pos.getY()+"n"+ - mod.start_record_pos.getZ()+"x"+ - mod.finish_record_pos.getX()+"n"+ - mod.finish_record_pos.getY()+"n"+ - mod.finish_record_pos.getZ()); - - File p = new File(FabricLoader.getInstance().getGameDir().toFile(),"repeating"); - if (!p.exists()) p.mkdir(); - File file = new File(p,"export_"+ - new SimpleDateFormat("MM_dd_yyyy").format(new Date()) - +"_"+RepeatingMod.rand.nextInt(10)+".txt"); - try { - if (!file.exists()) file.createNewFile(); - Files.write(file.toPath(), t.toString().getBytes()); - Runtime.getRuntime().exec("explorer /select,\""+file.getAbsolutePath()+"\""); - } catch (Exception e) { - e.printStackTrace(); - } - }) - .dimensions(width / 2 - 60, height / 2 - 10, 120, 20) - .tooltip(Tooltip.of(Text.translatable("text.repeating-mod.export_tooltip"))) - .build(); - - import_btn = ButtonWidget.builder( - Text.translatable("text.repeating-mod.import"), button -> { - mod.record.clear(); - - File p = new File(FabricLoader.getInstance().getGameDir().toFile(),"repeating"); - if (!p.exists()) p.mkdir(); - - JFileChooser fc = new JFileChooser() { - @Override - protected JDialog createDialog(Component parent) throws HeadlessException { - JDialog dialog = super.createDialog(parent); - dialog.setLocationByPlatform(true); - dialog.setAlwaysOnTop(true); - return dialog; - } - - }; - - int retValue = fc.showOpenDialog(null); - if (retValue == JFileChooser.APPROVE_OPTION){ - File file = fc.getSelectedFile(); - try { - String t = Files.readString(file.toPath()); - List ss = List.of(t.split("\n")); - String ls = ss.get(ss.size()-1); - ss = ss.subList(0,ss.size()-1); - for (String s:ss) - mod.record.add(RecordEvent.deserialize(s)); - String[] lss0 = ls.split("x"); - String[] lss1 = lss0[0].split("n"); - String[] lss2 = lss0[1].split("n"); - mod.start_record_pos = new Vec3d( - Float.parseFloat(lss1[0]), - Float.parseFloat(lss1[1]), - Float.parseFloat(lss1[2])); - mod.finish_record_pos = new Vec3d( - Float.parseFloat(lss2[0]), - Float.parseFloat(lss2[1]), - Float.parseFloat(lss2[2])); - RepeatingMod.sendMessage(Text.literal("")); - } catch (Exception e) { - e.printStackTrace(); - } - } - }) - .dimensions(width / 2 - 60, height / 2 + 12, 120, 20) - .tooltip(Tooltip.of(Text.translatable("text.repeating-mod.import_tooltip"))) - .build(); - pos_delay_slider = new SliderWidget( - width / 2 - 60, height / 2 + 34, 120, 20, - (mod.record_pos_delay < 0) ? Text.translatable("text.repeating-mod.nan_pos_delay") : - Text.translatable("text.repeating-mod.pos_delay", String.valueOf(mod.record_pos_delay)), - (mod.record_pos_delay+1d)/101d) { + width / 2 - 60, height / 2 - 32, 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() { @@ -191,9 +108,9 @@ public class RepeatingScreen extends Screen { 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))); - mod.record_pos_delay = (long) v; - mod.conf.data.put("record_pos_delay",String.valueOf(mod.record_pos_delay)); - mod.conf.save(); + 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 @@ -216,15 +133,57 @@ public class RepeatingScreen extends Screen { }; 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.record_list.addRecord(file); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }}).start(); + }) + .dimensions(width / 2 - 60, height / 2 - 10, 120, 20) + .tooltip(Tooltip.of(Text.translatable("text.repeating-mod.import_tooltip"))) + .build(); + + Main.me.record_list.getWidget().setX(width / 2 - Main.me.record_list.getWidget().getWidth() / 2); + Main.me.record_list.getWidget().setY(height / 2 + 12); + Main.me.record_list.getWidget().init(this); + was_build = true; - update_btns(); + updateButtons(); - addDrawableChild(replay_btn); addDrawableChild(loop_btn); addDrawableChild(record_btn); - addDrawableChild(export_btn); addDrawableChild(import_btn); addDrawableChild(pos_delay_slider); } + + public T addDrawableChild(T drawableElement) { + return super.addDrawableChild(drawableElement); + } + + public T addDrawable(T drawable) { + return super.addDrawable(drawable); + } + + public T addSelectableChild(T child) { + return super.addSelectableChild(child); + } + + public void remove(Element child) { + super.remove(child); + } } diff --git a/src/main/java/themixray/repeating/mod/event/RecordBlockBreakEvent.java b/src/main/java/themixray/repeating/mod/event/RecordBlockBreakEvent.java index 82934be..a39380c 100644 --- a/src/main/java/themixray/repeating/mod/event/RecordBlockBreakEvent.java +++ b/src/main/java/themixray/repeating/mod/event/RecordBlockBreakEvent.java @@ -1,4 +1,4 @@ -package themixray.repeating.mod.events; +package themixray.repeating.mod.event; import net.minecraft.util.math.BlockPos; import themixray.repeating.mod.Main; diff --git a/src/main/java/themixray/repeating/mod/event/RecordBlockInteractEvent.java b/src/main/java/themixray/repeating/mod/event/RecordBlockInteractEvent.java index 2d176ed..59d0b76 100644 --- a/src/main/java/themixray/repeating/mod/event/RecordBlockInteractEvent.java +++ b/src/main/java/themixray/repeating/mod/event/RecordBlockInteractEvent.java @@ -1,4 +1,4 @@ -package themixray.repeating.mod.events; +package themixray.repeating.mod.event; import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; diff --git a/src/main/java/themixray/repeating/mod/event/RecordDelayEvent.java b/src/main/java/themixray/repeating/mod/event/RecordDelayEvent.java index 2d899b4..7e4bcca 100644 --- a/src/main/java/themixray/repeating/mod/event/RecordDelayEvent.java +++ b/src/main/java/themixray/repeating/mod/event/RecordDelayEvent.java @@ -1,4 +1,4 @@ -package themixray.repeating.mod.events; +package themixray.repeating.mod.event; public class RecordDelayEvent extends RecordEvent { public long delay; diff --git a/src/main/java/themixray/repeating/mod/event/RecordEvent.java b/src/main/java/themixray/repeating/mod/event/RecordEvent.java index 3bf5b9c..e7c2ffe 100644 --- a/src/main/java/themixray/repeating/mod/event/RecordEvent.java +++ b/src/main/java/themixray/repeating/mod/event/RecordEvent.java @@ -1,4 +1,4 @@ -package themixray.repeating.mod.events; +package themixray.repeating.mod.event; public abstract class RecordEvent { public abstract void replay(); diff --git a/src/main/java/themixray/repeating/mod/event/RecordInputEvent.java b/src/main/java/themixray/repeating/mod/event/RecordInputEvent.java index e4cd62a..a760440 100644 --- a/src/main/java/themixray/repeating/mod/event/RecordInputEvent.java +++ b/src/main/java/themixray/repeating/mod/event/RecordInputEvent.java @@ -1,4 +1,4 @@ -package themixray.repeating.mod.events; +package themixray.repeating.mod.event; import themixray.repeating.mod.Main; diff --git a/src/main/java/themixray/repeating/mod/event/RecordMoveEvent.java b/src/main/java/themixray/repeating/mod/event/RecordMoveEvent.java index 757d58b..7b964de 100644 --- a/src/main/java/themixray/repeating/mod/event/RecordMoveEvent.java +++ b/src/main/java/themixray/repeating/mod/event/RecordMoveEvent.java @@ -1,4 +1,4 @@ -package themixray.repeating.mod.events; +package themixray.repeating.mod.event; import net.minecraft.entity.MovementType; import net.minecraft.util.math.Vec3d; diff --git a/src/main/java/themixray/repeating/mod/mixin/ClientMixin.java b/src/main/java/themixray/repeating/mod/mixin/ClientMixin.java index 1d077ac..60e9e64 100644 --- a/src/main/java/themixray/repeating/mod/mixin/ClientMixin.java +++ b/src/main/java/themixray/repeating/mod/mixin/ClientMixin.java @@ -5,15 +5,15 @@ 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.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 (RepeatingMod.me.is_recording) - RepeatingMod.me.recordAllInput(); + if (Main.me.is_recording) + Main.me.recordAllInput(); TickTask.tickTasks(TickTask.TickAt.CLIENT_HEAD); } diff --git a/src/main/java/themixray/repeating/mod/mixin/EntityMixin.java b/src/main/java/themixray/repeating/mod/mixin/EntityMixin.java index 94cfeb7..8d45d11 100644 --- a/src/main/java/themixray/repeating/mod/mixin/EntityMixin.java +++ b/src/main/java/themixray/repeating/mod/mixin/EntityMixin.java @@ -6,8 +6,7 @@ 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 themixray.repeating.mod.Main; import java.util.UUID; @@ -17,11 +16,11 @@ public abstract class EntityMixin { @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) { + 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(); return; } diff --git a/src/main/java/themixray/repeating/mod/mixin/InputMixin.java b/src/main/java/themixray/repeating/mod/mixin/InputMixin.java index bcaf1e0..800e147 100644 --- a/src/main/java/themixray/repeating/mod/mixin/InputMixin.java +++ b/src/main/java/themixray/repeating/mod/mixin/InputMixin.java @@ -5,15 +5,15 @@ 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.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 (RepeatingMod.me.is_replaying) { - if (RepeatingMod.input_replay != null) { - RepeatingMod.input_replay.inputCallback(); + if (Main.me.is_replaying) { + if (Main.input_replay != null) { + Main.input_replay.inputCallback(); } } } diff --git a/src/main/java/themixray/repeating/mod/mixin/MovementMixin.java b/src/main/java/themixray/repeating/mod/mixin/MovementMixin.java index a645ef1..45190ba 100644 --- a/src/main/java/themixray/repeating/mod/mixin/MovementMixin.java +++ b/src/main/java/themixray/repeating/mod/mixin/MovementMixin.java @@ -9,9 +9,9 @@ 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.events.RecordBlockBreakEvent; -import themixray.repeating.mod.events.RecordBlockInteractEvent; -import themixray.repeating.mod.RepeatingMod; +import themixray.repeating.mod.Main; +import themixray.repeating.mod.event.RecordBlockBreakEvent; +import themixray.repeating.mod.event.RecordBlockInteractEvent; import themixray.repeating.mod.TickTask; @Mixin(ClientPlayerEntity.class) @@ -20,14 +20,14 @@ 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 (RepeatingMod.me.is_recording) - RepeatingMod.me.recordTick(new RecordBlockBreakEvent(pos)); + if (Main.me.is_recording) + Main.me.recordTick(new RecordBlockBreakEvent(pos)); }); UseBlockCallback.EVENT.register((player, world, hand, hitResult) -> { if (hitResult.getType().equals(HitResult.Type.BLOCK)) - if (RepeatingMod.me.is_recording) - RepeatingMod.me.recordTick(new RecordBlockInteractEvent(hand,hitResult)); + if (Main.me.is_recording) + Main.me.recordTick(new RecordBlockInteractEvent(hand,hitResult)); return ActionResult.PASS; }); } diff --git a/src/main/java/themixray/repeating/mod/mixin/NetworkMixin.java b/src/main/java/themixray/repeating/mod/mixin/NetworkMixin.java index c116952..1ffb3c6 100644 --- a/src/main/java/themixray/repeating/mod/mixin/NetworkMixin.java +++ b/src/main/java/themixray/repeating/mod/mixin/NetworkMixin.java @@ -1,6 +1,5 @@ package themixray.repeating.mod.mixin; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.network.listener.ServerPlayPacketListener; import net.minecraft.network.packet.Packet; @@ -8,8 +7,6 @@ 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; import java.time.Duration; import java.util.function.BooleanSupplier; diff --git a/src/main/java/themixray/repeating/mod/mixin/RendererMixin.java b/src/main/java/themixray/repeating/mod/mixin/RendererMixin.java index fcaca78..edb363d 100644 --- a/src/main/java/themixray/repeating/mod/mixin/RendererMixin.java +++ b/src/main/java/themixray/repeating/mod/mixin/RendererMixin.java @@ -1,12 +1,10 @@ package themixray.repeating.mod.mixin; -import net.minecraft.client.input.KeyboardInput; 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.RepeatingMod; import themixray.repeating.mod.TickTask; @Mixin(GameRenderer.class) diff --git a/src/main/java/themixray/repeating/mod/render/buffer/BufferManager.java b/src/main/java/themixray/repeating/mod/render/buffer/BufferManager.java index 4c3ae98..76d2853 100644 --- a/src/main/java/themixray/repeating/mod/render/buffer/BufferManager.java +++ b/src/main/java/themixray/repeating/mod/render/buffer/BufferManager.java @@ -21,28 +21,28 @@ public class BufferManager { }); } - public void bindBuffer() { + public static void bindBuffer() { glBindBuffer(GL_ARRAY_BUFFER, vbo); } - public void unbindBuffer() { + public static void unbindBuffer() { glBindBuffer(GL_ARRAY_BUFFER, 0); } - public void writeBuffer(FloatBuffer buffer) { + public static void writeBuffer(FloatBuffer buffer) { glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW); } - public void draw(int drawMode, int verts) { + public static void draw(int drawMode, int verts) { glDrawArrays(drawMode, 0, verts); } - public void bind() { + public static void bind() { prevVao = glGetInteger(GL_VERTEX_ARRAY_BINDING); glBindVertexArray(vao); } - public void unbind() { + public static void unbind() { glBindVertexArray(prevVao); } } diff --git a/src/main/java/themixray/repeating/mod/widget/RecordListWidget.java b/src/main/java/themixray/repeating/mod/widget/RecordListWidget.java new file mode 100644 index 0000000..3106ae5 --- /dev/null +++ b/src/main/java/themixray/repeating/mod/widget/RecordListWidget.java @@ -0,0 +1,150 @@ +package themixray.repeating.mod.widget; + +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.narration.NarrationMessageBuilder; +import net.minecraft.client.gui.tooltip.Tooltip; +import net.minecraft.client.gui.widget.*; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; +import themixray.repeating.mod.Main; +import themixray.repeating.mod.RecordState; +import themixray.repeating.mod.RepeatingScreen; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +public class RecordListWidget extends ScrollableWidget { + private List widgets = new ArrayList<>(); + private boolean focused = false; + + public RecordListWidget(int x, int y, int width, int height) { + super(x,y,width,height,Text.empty()); + } + + @Override + public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + focused = true; + boolean res = super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + focused = false; + return res; + } + + @Override + protected double getDeltaYPerScroll() { + return 10; + } + + @Override + protected void renderContents(DrawContext ctx, int mouseX, int mouseY, float delta) { + int y = 0; + for (RecordWidget wid: widgets) { + wid.setY(y); + wid.render(ctx, mouseX, (int) (mouseY + this.getScrollY()), delta); + + y += wid.getHeight(); + y += 2; + } + } + + public void addWidget(RecordState record) { + RecordWidget widget = new RecordWidget(0, 0, width, 50, record, this); + widget.init(null); + widgets.add(0, widget); + } + + public void removeWidget(RecordState record) { + widgets.removeIf(i -> i.getRecord().equals(record)); + } + + @Override + public void setFocused(boolean focused) { + + } + + @Override + public boolean isFocused() { + return focused; + } + + @Override + protected int getContentsHeight() { + return !widgets.isEmpty() ? widgets.size() * 50 + (widgets.size() - 1) * 2 : 0; + } + + public void init(RepeatingScreen screen) { + for (RecordWidget widget : widgets) { + widget.init(screen); + } + + screen.addDrawableChild(this); + } + + @Override + protected void appendClickableNarrations(NarrationMessageBuilder builder) { + + } + + public RecordWidget getWidget(RecordState record) { + for (RecordWidget widget : widgets) { + if (widget.getRecord().equals(record)) { + return widget; + } + } + return null; + } + + public interface transport { + boolean check(ClickableWidget ch); + } + + public boolean checkTransport(transport tr) { + for (RecordWidget wid : widgets) { + for (ClickableWidget child : wid.getChildren()) { + if (tr.check(child)) { + return true; + } + } + } + return false; + } + + public boolean checkTransportNF(transport tr) { + for (RecordWidget wid : widgets) { + for (ClickableWidget child : wid.getChildren()) { + boolean res = tr.check(child); + + if (res) { + child.setFocused(true); + return true; + } else { + child.setFocused(false); + } + } + } + return false; + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + return checkTransportNF((c) -> c.mouseClicked(mouseX, mouseY + this.getScrollY(), button)) || super.mouseClicked(mouseX, mouseY, button); + } + + @Override + public boolean charTyped(char chr, int modifiers) { + return checkTransport((c) -> c.charTyped(chr, modifiers)) || super.charTyped(chr, modifiers); + } + + @Override + public boolean keyPressed(int keyCode, int scanCode, int modifiers) { + return checkTransport((c) -> c.keyPressed(keyCode, scanCode, modifiers)) || super.keyPressed(keyCode, scanCode, modifiers); + } + + @Override + public boolean keyReleased(int keyCode, int scanCode, int modifiers) { + return checkTransport((c) -> c.keyReleased(keyCode, scanCode, modifiers)) || super.keyReleased(keyCode, scanCode, modifiers); + } +} diff --git a/src/main/java/themixray/repeating/mod/widget/RecordWidget.java b/src/main/java/themixray/repeating/mod/widget/RecordWidget.java new file mode 100644 index 0000000..d8a2d21 --- /dev/null +++ b/src/main/java/themixray/repeating/mod/widget/RecordWidget.java @@ -0,0 +1,192 @@ +package themixray.repeating.mod.widget; + +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.Drawable; +import net.minecraft.client.gui.tooltip.Tooltip; +import net.minecraft.client.gui.widget.*; +import net.minecraft.text.Style; +import net.minecraft.text.Text; +import themixray.repeating.mod.Main; +import themixray.repeating.mod.RecordState; +import themixray.repeating.mod.RenderListener; +import themixray.repeating.mod.RepeatingScreen; + +import java.awt.*; +import java.io.IOException; +import java.util.ArrayList; + +import java.util.List; +import java.util.function.Consumer; + +public class RecordWidget implements Drawable, Widget { + private RecordState record; + + private List children; + + private RecordListWidget parent; + + private int x; + private int y; + private int width; + private int height; + + public RecordWidget(int x, int y, int width, int height, RecordState record, RecordListWidget parent) { + this.parent = parent; + this.record = record; + + this.x = x; + this.y = y; + this.width = width; + this.height = height; + + this.children = new ArrayList<>(); + } + + public void setX(int x) { + this.x = x; + } + public void setY(int y) { + this.y = y; + } + public int getX() { + return x; + } + public int getY() { + return y; + } + public int getWidth() { + return width; + } + public int getHeight() { + return height; + } + + public List getChildren() { + return children; + } + + @Override + public void forEachChild(Consumer consumer) { + children.forEach(consumer); + } + + public void init(RepeatingScreen screen) { + this.children = new ArrayList<>(); + + TextFieldWidget name_widget = new TextFieldWidget( + Main.client.textRenderer, + parent.getX() + getX() + 5, + parent.getY() + getY() + 5, + 70, + 10, + Text.empty()); + + name_widget.setText(record.getName()); + + name_widget.setChangedListener((s) -> { + record.setName(s); + try { + record.save(); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + + children.add(name_widget); + + ButtonWidget delete_button = ButtonWidget.builder(Text.translatable("text.repeating-mod.delete"), (i) -> { + record.remove(); + }).dimensions(parent.getX() + getX() + 77,parent.getY() + getY() + 4, 38, 13).build(); + + children.add(delete_button); + + ButtonWidget export_button = ButtonWidget.builder(Text.translatable("text.repeating-mod.export"), (i) -> { + if (Desktop.isDesktopSupported()) { + Desktop desk = Desktop.getDesktop(); + try { + desk.browse(record.getFile().toURI()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }).dimensions(parent.getX() + getX() + 77,parent.getY() + getY() + 4 + 14, 38, 13).build(); + + children.add(export_button); + + ButtonWidget replay_button = ButtonWidget.builder(Text.translatable("text.repeating-mod.start"), (i) -> { + if (Main.me.is_replaying) { + Main.me.stopReplay(); + } + + i.setMessage(Text.translatable("text.repeating-mod.stop")); + Main.me.now_record = record; + Main.me.startReplay(); + }).dimensions(parent.getX() + getX() + 77,parent.getY() + getY() + 4 + 28, 38, 13) + .tooltip(Tooltip.of(Text.translatable("text.repeating-mod.replay_tooltip"))).build(); + + children.add(replay_button); + } + + public RecordState getRecord() { + return record; + } + + public void drawText(int x, int y, DrawContext ctx, List lines, float size, int line_height, boolean shadow) { + ctx.getMatrices().push(); + ctx.getMatrices().scale(size, size, size); + + int now_y = y; + + for (Text line : lines) { + ctx.drawText(Main.client.textRenderer, line, (int) (x / size), (int) (now_y / size), line.getStyle().getColor().getRgb(), shadow); + now_y += line_height; + } + + ctx.getMatrices().pop(); + } + + @Override + public void render(DrawContext ctx, int mouseX, int mouseY, float delta) { + int color = record.equals(Main.me.now_record) ? 0xFF555555 : 0xFF333333; + + ctx.fill(parent.getX() + getX(), + parent.getY() + getY(), + parent.getX() + getX() + getWidth(), + parent.getY() + getY() + getHeight(), + color); + + drawText( + parent.getX() + getX() + 5, + parent.getY() + getY() + 5 + 12, + ctx, List.of( + Text.translatable("text.repeating-mod.recorded_at") + .append(": ") + .styled((s) -> s.withColor(0xbbbbbb)), + Text.literal(RecordState.DATE_FORMAT.format(record.getDate())).styled((s) -> s.withColor(0xffffff)), + Text.translatable("text.repeating-mod.author") + .append(": ") + .styled((s) -> s.withColor(0xbbbbbb)), + Text.literal(record.getAuthor()).styled((s) -> s.withColor(0xffffff)) + ), 0.7f, + 7, + false); + + if (!children.isEmpty()) { + ClickableWidget name_widget = children.get(0); + name_widget.setPosition(parent.getX() + getX() + 5, parent.getY() + getY() + 5); + + ClickableWidget delete_button = children.get(1); + delete_button.setPosition(parent.getX() + getX() + 77,parent.getY() + getY() + 4); + + ClickableWidget export_button = children.get(2); + export_button.setPosition(parent.getX() + getX() + 77,parent.getY() + getY() + 4 + 14); + + ClickableWidget replay_button = children.get(3); + replay_button.setPosition(parent.getX() + getX() + 77,parent.getY() + getY() + 4 + 28); + } + + for (ClickableWidget child : children) { + child.render(ctx, mouseX, mouseY, delta); + } + } +} 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 cfab5c4..774b7d8 100644 --- a/src/main/resources/assets/repeating-mod/lang/en_us.json +++ b/src/main/resources/assets/repeating-mod/lang/en_us.json @@ -11,14 +11,23 @@ "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": "Export record", + "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 an entry from the import.txt 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", 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 3fd30f4..2cf3521 100644 --- a/src/main/resources/assets/repeating-mod/lang/ru_ru.json +++ b/src/main/resources/assets/repeating-mod/lang/ru_ru.json @@ -10,19 +10,29 @@ "text.repeating-mod.stop_replay": "Остановить повтор", "text.repeating-mod.record_tooltip": "Начать/остановить запись всех действий", "text.repeating-mod.replay_tooltip": "Начать/остановить повтор записанных действий", - "text.repeating-mod.loop_tooltip": "Вкл/выкл повтор повтора записанных действий", - "text.repeating-mod.export": "Экспорт записи", + "text.repeating-mod.loop_tooltip": "Вкл/выкл повтор записи", "text.repeating-mod.import": "Импорт записи", "text.repeating-mod.export_tooltip": "Экспорт записи в файл", - "text.repeating-mod.import_tooltip": "Импорт записи из файла import.txt", + "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": "Запись закончена" + "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": "Стоп" } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index cdf4d39..7a2119f 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -19,7 +19,7 @@ "environment": "client", "entrypoints": { "client": [ - "themixray.repeating.mod.RepeatingMod" + "themixray.repeating.mod.Main" ] }, "mixins": [