fix records list and add btns
This commit is contained in:
parent
b6589b3629
commit
38dad10048
@ -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
|
||||
|
@ -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<RecordEvent> 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 (now_record != null) {
|
||||
if (!is_recording) {
|
||||
if (is_replaying)
|
||||
stopReplay();
|
||||
else startReplay();
|
||||
menu.update_btns();
|
||||
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;
|
||||
public void setNowRecord(RecordState record) {
|
||||
now_record = record;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
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();
|
||||
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<RecordEvent> 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"));
|
||||
}
|
||||
|
||||
|
@ -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<RecordState> 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<RecordState> 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;
|
||||
}
|
||||
}
|
||||
|
@ -1,28 +1,34 @@
|
||||
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<RecordEvent> events;
|
||||
private Vec3d start_record_pos;
|
||||
private Vec3d finish_record_pos;
|
||||
|
||||
public RecordFile(File file,
|
||||
public RecordState(File file,
|
||||
String name,
|
||||
String date,
|
||||
Date date,
|
||||
String author,
|
||||
List<RecordEvent> events,
|
||||
Vec3d start_record_pos,
|
||||
@ -49,15 +55,27 @@ public class RecordFile {
|
||||
return author;
|
||||
}
|
||||
|
||||
public String getDate() {
|
||||
public Date getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public List<RecordEvent> 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<RecordEvent> 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<String> lines = List.of(text.split("\n"));
|
||||
|
||||
List<String> 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<String> event_lines = lines.subList(4,lines.size());
|
||||
List<RecordEvent> 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);
|
||||
}
|
||||
}
|
||||
|
11
src/main/java/themixray/repeating/mod/RenderListener.java
Normal file
11
src/main/java/themixray/repeating/mod/RenderListener.java
Normal file
@ -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);
|
||||
}
|
@ -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<RenderListener> 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<String> 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 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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package themixray.repeating.mod.events;
|
||||
package themixray.repeating.mod.event;
|
||||
|
||||
public class RecordDelayEvent extends RecordEvent {
|
||||
public long delay;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package themixray.repeating.mod.events;
|
||||
package themixray.repeating.mod.event;
|
||||
|
||||
public abstract class RecordEvent {
|
||||
public abstract void replay();
|
||||
|
@ -1,4 +1,4 @@
|
||||
package themixray.repeating.mod.events;
|
||||
package themixray.repeating.mod.event;
|
||||
|
||||
import themixray.repeating.mod.Main;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
});
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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<RecordWidget> 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);
|
||||
}
|
||||
}
|
192
src/main/java/themixray/repeating/mod/widget/RecordWidget.java
Normal file
192
src/main/java/themixray/repeating/mod/widget/RecordWidget.java
Normal file
@ -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<ClickableWidget> 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<ClickableWidget> getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachChild(Consumer<ClickableWidget> 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<Text> 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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",
|
||||
|
@ -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": "Стоп"
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
"environment": "client",
|
||||
"entrypoints": {
|
||||
"client": [
|
||||
"themixray.repeating.mod.RepeatingMod"
|
||||
"themixray.repeating.mod.Main"
|
||||
]
|
||||
},
|
||||
"mixins": [
|
||||
|
Loading…
Reference in New Issue
Block a user