From e593859723f251414dabe0f1476548516c0672ea Mon Sep 17 00:00:00 2001 From: MeexReay <127148610+MeexReay@users.noreply.github.com> Date: Fri, 20 Oct 2023 16:46:07 +0300 Subject: [PATCH] 1.0.6 update removed owo lib fixed some bugs --- build.gradle | 15 +- gradle.properties | 12 +- .../themixray/repeating/mod/EasyConfig.java | 6 +- .../themixray/repeating/mod/RepeatingMod.java | 81 ++- .../repeating/mod/RepeatingScreen.java | 493 ++++++++++++------ .../repeating/mod/mixin/EntityMixin.java | 5 - .../repeating/mod/mixin/RendererMixin.java | 2 +- .../repeating/mod/render/RenderHelper.java | 200 +++++++ .../repeating/mod/render/RenderSystem.java | 13 + .../mod/render/buffer/BufferManager.java | 48 ++ .../repeating/mod/render/buffer/Vertex.java | 30 ++ .../mod/render/buffer/WorldBuffer.java | 82 +++ .../repeating/mod/render/shader/Shader.java | 42 ++ .../mod/render/shader/ShaderManager.java | 97 ++++ .../assets/renderer/shader/position_color.fsh | 12 + .../assets/renderer/shader/position_color.vsh | 13 + .../assets/repeating-mod/lang/en_us.json | 18 +- .../assets/repeating-mod/lang/ru_ru.json | 18 +- src/main/resources/fabric.mod.json | 2 +- 19 files changed, 990 insertions(+), 199 deletions(-) create mode 100644 src/main/java/themixray/repeating/mod/render/RenderHelper.java create mode 100644 src/main/java/themixray/repeating/mod/render/RenderSystem.java create mode 100644 src/main/java/themixray/repeating/mod/render/buffer/BufferManager.java create mode 100644 src/main/java/themixray/repeating/mod/render/buffer/Vertex.java create mode 100644 src/main/java/themixray/repeating/mod/render/buffer/WorldBuffer.java create mode 100644 src/main/java/themixray/repeating/mod/render/shader/Shader.java create mode 100644 src/main/java/themixray/repeating/mod/render/shader/ShaderManager.java create mode 100644 src/main/resources/assets/renderer/shader/position_color.fsh create mode 100644 src/main/resources/assets/renderer/shader/position_color.vsh diff --git a/build.gradle b/build.gradle index fb32d3f..220e433 100644 --- a/build.gradle +++ b/build.gradle @@ -17,6 +17,13 @@ repositories { } dependencies { + compileOnly 'org.projectlombok:lombok:1.18.24' + annotationProcessor 'org.projectlombok:lombok:1.18.24' + + //add joml + modImplementation 'org.joml:joml:1.10.4' + include 'org.joml:joml:1.10.4' + // To change the versions see the gradle.properties file minecraft "com.mojang:minecraft:${project.minecraft_version}" mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" @@ -30,13 +37,13 @@ dependencies { // modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" - modImplementation "io.wispforest:owo-lib:${project.owo_version}" - // only if you plan to use owo-config - annotationProcessor "io.wispforest:owo-lib:${project.owo_version}" +// modImplementation "io.wispforest:owo-lib:${project.owo_version}" +// // only if you plan to use owo-config +// annotationProcessor "io.wispforest:owo-lib:${project.owo_version}" // include this if you don't want force your users to install owo // sentinel will warn them and give the option to download it automatically - include "io.wispforest:owo-sentinel:${project.owo_version}" +// include "io.wispforest:owo-sentinel:${project.owo_version}" } base { diff --git a/gradle.properties b/gradle.properties index 1d9b018..47a1114 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,16 +4,16 @@ org.gradle.parallel=true # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.19.3 -yarn_mappings=1.19.3+build.1 -loader_version=0.14.17 +minecraft_version=1.20 +yarn_mappings=1.20+build.1 +loader_version=0.14.23 # Mod Properties -mod_version = 1.0.5 +mod_version = 1.0.6 maven_group = themixray.repeating.mod archives_base_name = repeating-mod # Dependencies -fabric_version=0.76.1+1.19.3 +fabric_version=0.83.0+1.20 -owo_version=0.10.3+1.19.3 +#owo_version=0.11.1+1.20 diff --git a/src/main/java/themixray/repeating/mod/EasyConfig.java b/src/main/java/themixray/repeating/mod/EasyConfig.java index eab45d1..8836722 100644 --- a/src/main/java/themixray/repeating/mod/EasyConfig.java +++ b/src/main/java/themixray/repeating/mod/EasyConfig.java @@ -71,10 +71,10 @@ public class EasyConfig { } private String toText(Map p) { - String t = ""; + StringBuilder t = new StringBuilder(); for (Map.Entry e:p.entrySet()) - t += e.getKey() + "=" + e.getValue() + "\n"; - return t; + t.append(e.getKey()).append("=").append(e.getValue()).append("\n"); + return t.toString(); } private Map toMap(String j) { Map m = new HashMap<>(); diff --git a/src/main/java/themixray/repeating/mod/RepeatingMod.java b/src/main/java/themixray/repeating/mod/RepeatingMod.java index 4ed30dd..068aa81 100644 --- a/src/main/java/themixray/repeating/mod/RepeatingMod.java +++ b/src/main/java/themixray/repeating/mod/RepeatingMod.java @@ -4,22 +4,39 @@ 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; +import net.fabricmc.fabric.api.client.rendering.v1.DimensionRenderingRegistry; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.render.*; import net.minecraft.client.util.InputUtil; import net.minecraft.entity.MovementType; +import net.minecraft.registry.Registry; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.text.MutableText; +import net.minecraft.text.Style; import net.minecraft.text.Text; +import net.minecraft.text.TextColor; +import net.minecraft.util.Formatting; import net.minecraft.util.Hand; +import net.minecraft.util.Identifier; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; import org.lwjgl.glfw.GLFW; +import org.lwjgl.opengl.GL11; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import themixray.repeating.mod.render.RenderHelper; +import themixray.repeating.mod.render.RenderSystem; +import themixray.repeating.mod.render.buffer.WorldBuffer; +import java.awt.*; import java.util.*; +import java.util.List; public class RepeatingMod implements ClientModInitializer { public static final Logger LOGGER = LoggerFactory.getLogger("repeating-mod"); @@ -27,6 +44,9 @@ public class RepeatingMod implements ClientModInitializer { public static final FabricLoader loader = FabricLoader.getInstance(); public static RepeatingMod me; + public Vec3d start_record_pos = null; + public Vec3d finish_record_pos = null; + public List record = new ArrayList<>(); public boolean is_recording = false; public long last_record = -1; @@ -46,6 +66,8 @@ public class RepeatingMod implements ClientModInitializer { public long record_pos_delay = 20; + public static Random rand = new Random(); + public EasyConfig conf; @Override @@ -53,6 +75,50 @@ public class RepeatingMod implements ClientModInitializer { LOGGER.info("Repeating mod initialized"); me = this; + 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, + + (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)); + } + RenderHelper.endTri(buffer); + }); + Map def = new HashMap<>(); def.put("record_pos_delay", String.valueOf(record_pos_delay)); @@ -109,14 +175,15 @@ public class RepeatingMod implements ClientModInitializer { return null; } - public void startRecording() { is_recording = true; menu.update_btns(); record.clear(); - record.add(new RecordMoveEvent(client.player.getPos(), - client.player.getHeadYaw(), client.player.getPitch())); + finish_record_pos = null; + Vec3d v = client.player.getPos(); + record.add(new RecordMoveEvent(v,client.player.getHeadYaw(),client.player.getPitch())); + start_record_pos = v; if (record_pos_delay > 0) { move_tick = new TickTask( @@ -226,6 +293,7 @@ public class RepeatingMod implements ClientModInitializer { public void stopRecording() { is_recording = false; + finish_record_pos = client.player.getPos(); if (move_tick != null) { move_tick.cancel(); move_tick = null; @@ -285,10 +353,11 @@ public class RepeatingMod implements ClientModInitializer { return (double) Math.round(value * factor) / factor; } - public static void sendMessage(Text text) { + public static void sendMessage(MutableText text) { client.player.sendMessage(Text.literal("[") - .append(Text.translatable("text.repeating-mod.name")) - .append("] ").append(text)); + .append(Text.translatable("text.repeating-mod.name")) + .append("] ").formatted(Formatting.BOLD,Formatting.DARK_GRAY) + .append(text.formatted(Formatting.RESET).formatted(Formatting.GRAY))); } public static void sendDebug(String s) { diff --git a/src/main/java/themixray/repeating/mod/RepeatingScreen.java b/src/main/java/themixray/repeating/mod/RepeatingScreen.java index 5fe187e..7e2412c 100644 --- a/src/main/java/themixray/repeating/mod/RepeatingScreen.java +++ b/src/main/java/themixray/repeating/mod/RepeatingScreen.java @@ -1,192 +1,371 @@ package themixray.repeating.mod; -import io.wispforest.owo.ui.base.*; -import io.wispforest.owo.ui.component.*; -import io.wispforest.owo.ui.container.*; -import io.wispforest.owo.ui.container.FlowLayout; -import io.wispforest.owo.ui.core.*; -import io.wispforest.owo.ui.core.Insets; +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.screen.Screen; +import net.minecraft.client.gui.tooltip.Tooltip; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.gui.widget.OptionSliderWidget; +import net.minecraft.client.gui.widget.SliderWidget; import net.minecraft.text.Text; -import org.jetbrains.annotations.NotNull; +import net.minecraft.util.math.Vec3d; -import java.io.*; +import java.awt.*; +import java.io.File; import java.nio.file.Files; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.List; -public class RepeatingScreen extends BaseOwoScreen { - public RepeatingMod mod; - public ButtonComponent replay_btn; - public ButtonComponent record_btn; - public ButtonComponent loop_btn; - public boolean was_build = false; - - public RepeatingScreen() { +@Environment(EnvType.CLIENT) +public class RepeatingScreen extends Screen { + protected RepeatingScreen() { + super(Text.literal("")); this.mod = RepeatingMod.me; } - @Override - protected @NotNull OwoUIAdapter createAdapter() { - return OwoUIAdapter.create(this, Containers::horizontalFlow); - } + public RepeatingMod mod; + + 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() { if (was_build) { replay_btn.setMessage(Text.translatable("text.repeating-mod." + - ((mod.is_replaying) ? "stop" : "start")).append(" ") - .append(Text.translatable("text.repeating-mod.replay"))); + ((mod.is_replaying) ? "stop_replay" : "start_replay"))); record_btn.setMessage(Text.translatable("text.repeating-mod." + - ((mod.is_recording) ? "stop" : "start")).append(" ") - .append(Text.translatable("text.repeating-mod.record"))); + ((mod.is_recording) ? "stop_record" : "start_record"))); loop_btn.setMessage(Text.of(((mod.loop_replay) ? "\uefff " : "\ueffe "))); } } @Override - protected void build(FlowLayout rootComponent) { - rootComponent - .surface(Surface.VANILLA_TRANSLUCENT) - .horizontalAlignment(HorizontalAlignment.CENTER) - .verticalAlignment(VerticalAlignment.CENTER); + public void render(DrawContext context, int mouseX, int mouseY, float delta) { + renderBackground(context); +// context.drawCenteredTextWithShadow(textRenderer, +// Text.literal("You must see me"), +// width / 2, height / 2, +// Color.white.getRGB()); + super.render(context, mouseX, mouseY, delta); + } - replay_btn = (ButtonComponent) Components.button(Text.of("replay"), - (ButtonComponent btn) -> { - if (!mod.is_recording) { - if (mod.is_replaying) - mod.stopReplay(); - else mod.startReplay(); - update_btns(); - } - }).margins(Insets.of(1)).sizing( - Sizing.fixed(98),Sizing.fixed(20)); - - loop_btn = (ButtonComponent) Components.button(Text.of(""), - (ButtonComponent btn) -> { - mod.loop_replay = !mod.loop_replay; - update_btns(); - }).margins(Insets.of(1)) - .sizing(Sizing.fixed(20),Sizing.fixed(20)); - - record_btn = (ButtonComponent) Components.button(Text.of("record"), - (ButtonComponent btn) -> { + @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(); } - }).margins(Insets.of(1)).sizing( - Sizing.fixed(120),Sizing.fixed(20)); + }) + .dimensions(width / 2 - 60, height / 2 - 54, 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(); + } + }) + .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) + .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).toText()); + 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(); + File file = new File(p,"import.txt"); + + try { + if (!file.exists()) { + file.createNewFile(); + Runtime.getRuntime().exec("explorer /select,\""+file.getAbsolutePath()+"\""); + return; + } + 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(RepeatingMod.RecordEvent.fromText(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])); + } 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/10d+1d)/101d) { + + @Override + protected void updateMessage() { + double v = value*101d-1d; + if (v <= 1) setMessage(Text.translatable("text.repeating-mod.nan_pos_delay")); + else setMessage(Text.translatable("text.repeating-mod.pos_delay", String.valueOf((long) (v*10)))); + } + + @Override + protected void applyValue() { + double v = value*101d-1d; + if (v <= 1) setMessage(Text.translatable("text.repeating-mod.nan_pos_delay")); + else setMessage(Text.translatable("text.repeating-mod.pos_delay", String.valueOf((long) (v*10)))); + mod.record_pos_delay = (long) (v*10); + mod.conf.data.put("record_pos_delay",String.valueOf(mod.record_pos_delay)); + mod.conf.save(); + } + + @Override + public void onRelease(double mouseX, double mouseY) { + super.onRelease(mouseX, mouseY); + applyValue(); + } + + @Override + protected void onDrag(double mouseX, double mouseY, double deltaX, double deltaY) { + super.onDrag(mouseX, mouseY, deltaX, deltaY); + applyValue(); + } + + @Override + public void render(DrawContext context, int mouseX, int mouseY, float delta) { + super.render(context, mouseX, mouseY, delta); + updateMessage(); + } + }; + pos_delay_slider.setTooltip(Tooltip.of(Text.translatable("text.repeating-mod.pos_delay_tooltip"))); + was_build = true; - rootComponent.child( - Containers.horizontalFlow(Sizing.content(), Sizing.content()).child( - Containers.verticalFlow(Sizing.content(), Sizing.content()) - .child(Containers.verticalFlow(Sizing.content(), Sizing.content()) - .child(Components.label(Text.translatable("text.repeating-mod.basic")).margins(Insets.of(1))) - .padding(Insets.of(5)) - .surface(Surface.DARK_PANEL) - .verticalAlignment(VerticalAlignment.CENTER) - .horizontalAlignment(HorizontalAlignment.CENTER) - .margins(Insets.of(1))) - .child(Containers.verticalFlow(Sizing.content(), Sizing.content()) - .child(Containers.horizontalFlow(Sizing.content(), Sizing.content()) - .child(replay_btn).child(loop_btn)) - .child(record_btn) - .child(Components.button(Text.translatable( - "text.repeating-mod.export"), - (ButtonComponent btn) -> { - String t = ""; - for (int i = 0; i < mod.record.size(); i++) { - t += mod.record.get(i).toText(); - if (i != mod.record.size()-1) - t += "\n"; - } + update_btns(); - File p = new File(FabricLoader.getInstance().getGameDir().toFile(),"repeating"); - if (!p.exists()) p.mkdir(); - File file = new File(p,"export.txt"); + addDrawableChild(replay_btn); + addDrawableChild(loop_btn); + addDrawableChild(record_btn); + addDrawableChild(export_btn); + addDrawableChild(import_btn); + addDrawableChild(pos_delay_slider); - try { - if (!file.exists()) file.createNewFile(); - Files.write(file.toPath(), t.getBytes()); - Runtime.getRuntime().exec("explorer /select,\""+file.getAbsolutePath()+"\""); - } catch (Exception e) { - e.printStackTrace(); - } - }).margins(Insets.of(10,1,1,1)).sizing( - Sizing.fixed(120),Sizing.fixed(20))) - .child(Components.button(Text.translatable( - "text.repeating-mod.import"), - (ButtonComponent btn) -> { - mod.record.clear(); - File p = new File(FabricLoader.getInstance().getGameDir().toFile(),"repeating"); - if (!p.exists()) p.mkdir(); - File file = new File(p,"import.txt"); - - try { - if (!file.exists()) { - file.createNewFile(); - Runtime.getRuntime().exec("explorer /select,\""+file.getAbsolutePath()+"\""); - return; - } - String t = Files.readString(file.toPath()); - for (String s:t.split("\n")) - mod.record.add(RepeatingMod.RecordEvent.fromText(s)); - } catch (Exception e) { - e.printStackTrace(); - } - }).margins(Insets.of(1)).sizing( - Sizing.fixed(120),Sizing.fixed(20))) - .padding(Insets.of(10)) - .surface(Surface.DARK_PANEL) - .verticalAlignment(VerticalAlignment.CENTER) - .horizontalAlignment(HorizontalAlignment.CENTER) - .margins(Insets.of(1))) - /*).child( - Containers.verticalFlow(Sizing.content(), Sizing.content()) - .child(Containers.verticalFlow(Sizing.content(), Sizing.content()) - .child(Components.label(Text.translatable("text.repeating-mod.parkour")).margins(Insets.of(1))) - .padding(Insets.of(5)) - .surface(Surface.DARK_PANEL) - .verticalAlignment(VerticalAlignment.CENTER) - .horizontalAlignment(HorizontalAlignment.CENTER) - .margins(Insets.of(1))) - .child(Containers.verticalFlow(Sizing.content(), Sizing.content()) - .child(Components.label(Text.translatable("text.repeating-mod.dev")).margins(Insets.of(1))) - .padding(Insets.of(10)) - .surface(Surface.DARK_PANEL) - .verticalAlignment(VerticalAlignment.CENTER) - .horizontalAlignment(HorizontalAlignment.CENTER) - .margins(Insets.of(1)))*/ - ).child( - Containers.verticalFlow(Sizing.content(), Sizing.content()) - .child(Containers.verticalFlow(Sizing.content(), Sizing.content()) - .child(Components.label(Text.translatable("text.repeating-mod.settings")).margins(Insets.of(1))) - .padding(Insets.of(5)) - .surface(Surface.DARK_PANEL) - .verticalAlignment(VerticalAlignment.CENTER) - .horizontalAlignment(HorizontalAlignment.CENTER) - .margins(Insets.of(1))) - .child(Containers.verticalFlow(Sizing.content(), Sizing.content()) - .child(Components.discreteSlider(Sizing.fixed(120),-20,100) - .setFromDiscreteValue(mod.record_pos_delay) - .message((String s)->{ - mod.record_pos_delay = Long.parseLong(s); - mod.conf.data.put("record_pos_delay",String.valueOf(mod.record_pos_delay)); - mod.conf.save(); - if (mod.record_pos_delay > -1) - return Text.translatable("text.repeating-mod.pos_delay", s); - return Text.translatable("text.repeating-mod.nan_pos_delay"); - }).scrollStep(25) - .margins(Insets.of(1)) - .tooltip(Text.translatable("text.repeating-mod.pos_delay_text"))) - .padding(Insets.of(10)) - .surface(Surface.DARK_PANEL) - .verticalAlignment(VerticalAlignment.CENTER) - .horizontalAlignment(HorizontalAlignment.CENTER) - .margins(Insets.of(1))) - )); +// rootComponent +// .surface(Surface.VANILLA_TRANSLUCENT) +// .horizontalAlignment(HorizontalAlignment.CENTER) +// .verticalAlignment(VerticalAlignment.CENTER); +// +// replay_btn = (ButtonComponent) Components.button(Text.of("replay"), +// (ButtonComponent btn) -> { +// if (!mod.is_recording) { +// if (mod.is_replaying) +// mod.stopReplay(); +// else mod.startReplay(); +// update_btns(); +// } +// }).margins(Insets.of(1)).sizing( +// Sizing.fixed(98),Sizing.fixed(20)); +// +// loop_btn = (ButtonComponent) Components.button(Text.of(""), +// (ButtonComponent btn) -> { +// mod.loop_replay = !mod.loop_replay; +// update_btns(); +// }).margins(Insets.of(1)) +// .sizing(Sizing.fixed(20),Sizing.fixed(20)); +// +// record_btn = (ButtonComponent) Components.button(Text.of("record"), +// (ButtonComponent btn) -> { +// if (!mod.is_replaying) { +// if (mod.is_recording) +// mod.stopRecording(); +// else mod.startRecording(); +// update_btns(); +// } +// }).margins(Insets.of(1)).sizing( +// Sizing.fixed(120),Sizing.fixed(20)); +// was_build = true; +// +// rootComponent.child( +// Containers.horizontalFlow(Sizing.content(), Sizing.content()).child( +// Containers.verticalFlow(Sizing.content(), Sizing.content()) +// .child(Containers.verticalFlow(Sizing.content(), Sizing.content()) +// .child(Components.label(Text.translatable("text.repeating-mod.basic")).margins(Insets.of(1))) +// .padding(Insets.of(5)) +// .surface(Surface.DARK_PANEL) +// .verticalAlignment(VerticalAlignment.CENTER) +// .horizontalAlignment(HorizontalAlignment.CENTER) +// .margins(Insets.of(1))) +// .child(Containers.verticalFlow(Sizing.content(), Sizing.content()) +// .child(Containers.horizontalFlow(Sizing.content(), Sizing.content()) +// .child(replay_btn).child(loop_btn)) +// .child(record_btn) +// .child(Components.button(Text.translatable( +// "text.repeating-mod.export"), +// (ButtonComponent btn) -> { +// String t = ""; +// for (int i = 0; i < mod.record.size(); i++) { +// t += mod.record.get(i).toText(); +// if (i != mod.record.size()-1) +// t += "\n"; +// } +// +// File p = new File(FabricLoader.getInstance().getGameDir().toFile(),"repeating"); +// if (!p.exists()) p.mkdir(); +// File file = new File(p,"export.txt"); +// +// try { +// if (!file.exists()) file.createNewFile(); +// Files.write(file.toPath(), t.getBytes()); +// Runtime.getRuntime().exec("explorer /select,\""+file.getAbsolutePath()+"\""); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// }).margins(Insets.of(10,1,1,1)).sizing( +// Sizing.fixed(120),Sizing.fixed(20))) +// .child(Components.button(Text.translatable( +// "text.repeating-mod.import"), +// (ButtonComponent btn) -> { +// mod.record.clear(); +// +// File p = new File(FabricLoader.getInstance().getGameDir().toFile(),"repeating"); +// if (!p.exists()) p.mkdir(); +// File file = new File(p,"import.txt"); +// +// try { +// if (!file.exists()) { +// file.createNewFile(); +// Runtime.getRuntime().exec("explorer /select,\""+file.getAbsolutePath()+"\""); +// return; +// } +// String t = Files.readString(file.toPath()); +// for (String s:t.split("\n")) +// mod.record.add(RepeatingMod.RecordEvent.fromText(s)); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// }).margins(Insets.of(1)).sizing( +// Sizing.fixed(120),Sizing.fixed(20))) +// .padding(Insets.of(10)) +// .surface(Surface.DARK_PANEL) +// .verticalAlignment(VerticalAlignment.CENTER) +// .horizontalAlignment(HorizontalAlignment.CENTER) +// .margins(Insets.of(1))) +// /*).child( +// Containers.verticalFlow(Sizing.content(), Sizing.content()) +// .child(Containers.verticalFlow(Sizing.content(), Sizing.content()) +// .child(Components.label(Text.translatable("text.repeating-mod.parkour")).margins(Insets.of(1))) +// .padding(Insets.of(5)) +// .surface(Surface.DARK_PANEL) +// .verticalAlignment(VerticalAlignment.CENTER) +// .horizontalAlignment(HorizontalAlignment.CENTER) +// .margins(Insets.of(1))) +// .child(Containers.verticalFlow(Sizing.content(), Sizing.content()) +// .child(Components.label(Text.translatable("text.repeating-mod.dev")).margins(Insets.of(1))) +// .padding(Insets.of(10)) +// .surface(Surface.DARK_PANEL) +// .verticalAlignment(VerticalAlignment.CENTER) +// .horizontalAlignment(HorizontalAlignment.CENTER) +// .margins(Insets.of(1)))*/ +// ).child( +// Containers.verticalFlow(Sizing.content(), Sizing.content()) +// .child(Containers.verticalFlow(Sizing.content(), Sizing.content()) +// .child(Components.label(Text.translatable("text.repeating-mod.settings")).margins(Insets.of(1))) +// .padding(Insets.of(5)) +// .surface(Surface.DARK_PANEL) +// .verticalAlignment(VerticalAlignment.CENTER) +// .horizontalAlignment(HorizontalAlignment.CENTER) +// .margins(Insets.of(1))) +// .child(Containers.verticalFlow(Sizing.content(), Sizing.content()) +// .child(Components.discreteSlider(Sizing.fixed(120),-20,100) +// .setFromDiscreteValue(mod.record_pos_delay) +// .message((String s)->{ +// mod.record_pos_delay = Long.parseLong(s); +// mod.conf.data.put("record_pos_delay",String.valueOf(mod.record_pos_delay)); +// mod.conf.save(); +// if (mod.record_pos_delay > -1) +// return Text.translatable("text.repeating-mod.pos_delay", s); +// return Text.translatable("text.repeating-mod.nan_pos_delay"); +// }).scrollStep(25) +// .margins(Insets.of(1)) +// .tooltip(Text.translatable("text.repeating-mod.pos_delay_text"))) +// .padding(Insets.of(10)) +// .surface(Surface.DARK_PANEL) +// .verticalAlignment(VerticalAlignment.CENTER) +// .horizontalAlignment(HorizontalAlignment.CENTER) +// .margins(Insets.of(1))) +// )); update_btns(); } } diff --git a/src/main/java/themixray/repeating/mod/mixin/EntityMixin.java b/src/main/java/themixray/repeating/mod/mixin/EntityMixin.java index 8b09ad0..94cfeb7 100644 --- a/src/main/java/themixray/repeating/mod/mixin/EntityMixin.java +++ b/src/main/java/themixray/repeating/mod/mixin/EntityMixin.java @@ -1,11 +1,6 @@ package themixray.repeating.mod.mixin; -import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents; -import net.fabricmc.fabric.api.event.player.UseBlockCallback; -import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.entity.Entity; -import net.minecraft.util.ActionResult; -import net.minecraft.util.hit.HitResult; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; diff --git a/src/main/java/themixray/repeating/mod/mixin/RendererMixin.java b/src/main/java/themixray/repeating/mod/mixin/RendererMixin.java index d4511b1..fcaca78 100644 --- a/src/main/java/themixray/repeating/mod/mixin/RendererMixin.java +++ b/src/main/java/themixray/repeating/mod/mixin/RendererMixin.java @@ -1,7 +1,7 @@ package themixray.repeating.mod.mixin; import net.minecraft.client.input.KeyboardInput; -import net.minecraft.client.render.GameRenderer; +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; diff --git a/src/main/java/themixray/repeating/mod/render/RenderHelper.java b/src/main/java/themixray/repeating/mod/render/RenderHelper.java new file mode 100644 index 0000000..edbe614 --- /dev/null +++ b/src/main/java/themixray/repeating/mod/render/RenderHelper.java @@ -0,0 +1,200 @@ +package themixray.repeating.mod.render; + +import lombok.experimental.UtilityClass; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; +import net.minecraft.util.math.Vec3d; +import themixray.repeating.mod.render.buffer.WorldBuffer; +import themixray.repeating.mod.render.shader.ShaderManager; + +import java.awt.*; + +import static org.lwjgl.opengl.GL33.*; + +@UtilityClass +public class RenderHelper { + public WorldBuffer startLines(WorldRenderContext context) { + glEnable(GL_LINE_SMOOTH); + return new WorldBuffer(GL_LINES, ShaderManager.getPositionColorShader(), context); + } + + public void endLines(WorldBuffer buffer) { + glEnable(GL_BLEND); + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask(false); + buffer.draw(); + glDepthMask(true); + glDisable(GL_BLEND); + } + + public void drawLine(WorldBuffer buffer, float x1, float y1, float z1, float x2, float y2, float z2, Color color) { + buffer.vert(x1, y1, z1, color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, color.getAlpha() / 255f); + buffer.vert(x2, y2, z2, color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, color.getAlpha() / 255f); + } + + public WorldBuffer startTri(WorldRenderContext context) { + return new WorldBuffer(GL_TRIANGLES, ShaderManager.getPositionColorShader(), context); + } + + public void endTri(WorldBuffer buffer) { + //glDepthRange(0, 0.7); + glEnable(GL_BLEND); + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_CULL_FACE); + glDepthMask(false); + buffer.draw(); + glDepthMask(true); + glEnable(GL_CULL_FACE); + glDisable(GL_BLEND); + glDepthRange(0, 1); + } + + public void drawTri(WorldBuffer buffer, float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, Color color) { + buffer.vert(x1, y1, z1, color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, color.getAlpha() / 255f); + buffer.vert(x2, y2, z2, color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, color.getAlpha() / 255f); + buffer.vert(x3, y3, z3, color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, color.getAlpha() / 255f); + } + + public void drawRectFromTri(WorldBuffer buffer, + float x1, float y1, float z1, + float x2, float y2, float z2, + float x3, float y3, float z3, + float x4, float y4, float z4, + Color color) { + drawTri(buffer, + x1, y1, z1, + x2, y2, z2, + x3, y3, z3, + color); + drawTri(buffer, + x3, y3, z3, + x4, y4, z4, + x1, y1, z1, + color); + } + + public void drawRectFromLines(WorldBuffer buffer, + float x1, float y1, float z1, + float x2, float y2, float z2, + float x3, float y3, float z3, + float x4, float y4, float z4, + Color color) { + drawLine(buffer, + x1, y1, z1, + x2, y2, z2, + color); + drawLine(buffer, + x2, y2, z2, + x3, y3, z3, + color); + drawLine(buffer, + x3, y3, z3, + x4, y4, z4, + color); + drawLine(buffer, + x4, y4, z4, + x1, y1, z1, + color); + } + + public void drawBoxFromTri(WorldBuffer buffer, + float x1, float y1, float z1, + float x2, float y2, float z2, + Color color) { + float[][] v = new float[][]{ + new float[]{Math.min(x1, x2), Math.min(y1, y2), Math.min(z1, z2)}, + new float[]{Math.max(x1, x2), Math.max(y1, y2), Math.max(z1, z2)}}; + + drawRectFromTri(buffer, + v[0][0], v[0][1], v[0][2], + v[1][0], v[0][1], v[0][2], + v[1][0], v[1][1], v[0][2], + v[0][0], v[1][1], v[0][2], + color); + + drawRectFromTri(buffer, + v[0][0], v[0][1], v[0][2], + v[1][0], v[0][1], v[0][2], + v[1][0], v[0][1], v[1][2], + v[0][0], v[0][1], v[1][2], + color); + + drawRectFromTri(buffer, + v[0][0], v[0][1], v[0][2], + v[0][0], v[0][1], v[1][2], + v[0][0], v[1][1], v[1][2], + v[0][0], v[1][1], v[0][2], + color); + + drawRectFromTri(buffer, + v[0][0], v[0][1], v[1][2], + v[1][0], v[0][1], v[1][2], + v[1][0], v[1][1], v[1][2], + v[0][0], v[1][1], v[1][2], + color); + + drawRectFromTri(buffer, + v[0][0], v[1][1], v[0][2], + v[1][0], v[1][1], v[0][2], + v[1][0], v[1][1], v[1][2], + v[0][0], v[1][1], v[1][2], + color); + + drawRectFromTri(buffer, + v[1][0], v[0][1], v[0][2], + v[1][0], v[0][1], v[1][2], + v[1][0], v[1][1], v[1][2], + v[1][0], v[1][1], v[0][2], + color); + } + + public void drawBoxFromLines(WorldBuffer buffer, + float x1, float y1, float z1, + float x2, float y2, float z2, + Color color) { + float[][] v = new float[][]{ + new float[]{Math.min(x1, x2), Math.min(y1, y2), Math.min(z1, z2)}, + new float[]{Math.max(x1, x2), Math.max(y1, y2), Math.max(z1, z2)}}; + + drawRectFromLines(buffer, + v[0][0], v[0][1], v[0][2], + v[1][0], v[0][1], v[0][2], + v[1][0], v[1][1], v[0][2], + v[0][0], v[1][1], v[0][2], + color); + + drawRectFromLines(buffer, + v[0][0], v[0][1], v[0][2], + v[1][0], v[0][1], v[0][2], + v[1][0], v[0][1], v[1][2], + v[0][0], v[0][1], v[1][2], + color); + + drawRectFromLines(buffer, + v[0][0], v[0][1], v[0][2], + v[0][0], v[0][1], v[1][2], + v[0][0], v[1][1], v[1][2], + v[0][0], v[1][1], v[0][2], + color); + + drawRectFromLines(buffer, + v[0][0], v[0][1], v[1][2], + v[1][0], v[0][1], v[1][2], + v[1][0], v[1][1], v[1][2], + v[0][0], v[1][1], v[1][2], + color); + + drawRectFromLines(buffer, + v[0][0], v[1][1], v[0][2], + v[1][0], v[1][1], v[0][2], + v[1][0], v[1][1], v[1][2], + v[0][0], v[1][1], v[1][2], + color); + + drawRectFromLines(buffer, + v[1][0], v[0][1], v[0][2], + v[1][0], v[0][1], v[1][2], + v[1][0], v[1][1], v[1][2], + v[1][0], v[1][1], v[0][2], + color); + } +} diff --git a/src/main/java/themixray/repeating/mod/render/RenderSystem.java b/src/main/java/themixray/repeating/mod/render/RenderSystem.java new file mode 100644 index 0000000..2a095f7 --- /dev/null +++ b/src/main/java/themixray/repeating/mod/render/RenderSystem.java @@ -0,0 +1,13 @@ +package themixray.repeating.mod.render; + +import lombok.experimental.UtilityClass; +import themixray.repeating.mod.render.buffer.BufferManager; +import themixray.repeating.mod.render.shader.ShaderManager; + +@UtilityClass +public class RenderSystem { + public void init() { + BufferManager.init(); + ShaderManager.init(); + } +} diff --git a/src/main/java/themixray/repeating/mod/render/buffer/BufferManager.java b/src/main/java/themixray/repeating/mod/render/buffer/BufferManager.java new file mode 100644 index 0000000..4c3ae98 --- /dev/null +++ b/src/main/java/themixray/repeating/mod/render/buffer/BufferManager.java @@ -0,0 +1,48 @@ +package themixray.repeating.mod.render.buffer; + +import lombok.experimental.UtilityClass; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; + +import java.nio.FloatBuffer; + +import static org.lwjgl.opengl.GL33.*; + +@UtilityClass +public class BufferManager { + private int vao; + private int vbo; + + private int prevVao; + + public void init() { + ClientLifecycleEvents.CLIENT_STARTED.register(client -> { + vao = glGenVertexArrays(); + vbo = glGenBuffers(); + }); + } + + public void bindBuffer() { + glBindBuffer(GL_ARRAY_BUFFER, vbo); + } + + public void unbindBuffer() { + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + + public void writeBuffer(FloatBuffer buffer) { + glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW); + } + + public void draw(int drawMode, int verts) { + glDrawArrays(drawMode, 0, verts); + } + + public void bind() { + prevVao = glGetInteger(GL_VERTEX_ARRAY_BINDING); + glBindVertexArray(vao); + } + + public void unbind() { + glBindVertexArray(prevVao); + } +} diff --git a/src/main/java/themixray/repeating/mod/render/buffer/Vertex.java b/src/main/java/themixray/repeating/mod/render/buffer/Vertex.java new file mode 100644 index 0000000..5aaa113 --- /dev/null +++ b/src/main/java/themixray/repeating/mod/render/buffer/Vertex.java @@ -0,0 +1,30 @@ +package themixray.repeating.mod.render.buffer; + +import lombok.Getter; + +public class Vertex { + @Getter + private float x; + @Getter + private float y; + @Getter + private float z; + @Getter + private float r; + @Getter + private float g; + @Getter + private float b; + @Getter + private float a; + + public Vertex(float x, float y, float z, float r, float g, float b, float a) { + this.x = x; + this.y = y; + this.z = z; + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } +} \ No newline at end of file diff --git a/src/main/java/themixray/repeating/mod/render/buffer/WorldBuffer.java b/src/main/java/themixray/repeating/mod/render/buffer/WorldBuffer.java new file mode 100644 index 0000000..390f97d --- /dev/null +++ b/src/main/java/themixray/repeating/mod/render/buffer/WorldBuffer.java @@ -0,0 +1,82 @@ +package themixray.repeating.mod.render.buffer; + +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; +import net.minecraft.util.math.Vec3d; +import org.apache.commons.lang3.ArrayUtils; +import org.joml.Matrix4f; +import org.lwjgl.BufferUtils; +import themixray.repeating.mod.render.shader.Shader; + +import java.nio.FloatBuffer; +import java.util.ArrayList; +import java.util.List; + +import static org.lwjgl.opengl.GL33.*; + +public class WorldBuffer { + private final List vertices = new ArrayList<>(); + private final int drawMode; + private final Shader shader; + private FloatBuffer projectionMatrix; + private final Vec3d cameraPos; + + public WorldBuffer(int drawMode, Shader shader, WorldRenderContext worldRenderContext) { + this.drawMode = drawMode; + this.shader = shader; + this.cameraPos = worldRenderContext.camera().getPos(); + makeProjectionMatrix(worldRenderContext.projectionMatrix(), worldRenderContext.matrixStack().peek().getPositionMatrix()); + } + + public void vert(float x, float y, float z, float r, float g, float b, float a) { + vertices.add(new Vertex(x - (float) cameraPos.x, y - (float) cameraPos.y, z - (float) cameraPos.z, r, g, b, a)); + } + + public void draw() { + BufferManager.bind(); + BufferManager.bindBuffer(); + + BufferManager.writeBuffer(getBuffer()); + applyProjectionMatrix(); + + glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0); + glEnableVertexAttribArray(0); + glVertexAttribPointer(1, 4, GL_FLOAT, false, 0, vertices.size() * 3 * 4L); + glEnableVertexAttribArray(1); + + BufferManager.unbindBuffer(); + + shader.bind(); + BufferManager.draw(drawMode, this.vertices.size()); + shader.unbind(); + + BufferManager.unbind(); + } + + private FloatBuffer getBuffer() { + FloatBuffer floatBuffer = BufferUtils.createFloatBuffer(vertices.size() * 7); + ArrayList floats = new ArrayList<>(); + for (Vertex vertex : vertices) { + floats.add(vertex.getX()); + floats.add(vertex.getY()); + floats.add(vertex.getZ()); + } + for (Vertex vertex : vertices) { + floats.add(vertex.getR()); + floats.add(vertex.getG()); + floats.add(vertex.getB()); + floats.add(vertex.getA()); + } + Float[] floatArray = new Float[floats.size()]; + floats.toArray(floatArray); + floatBuffer.put(ArrayUtils.toPrimitive(floatArray)); + return floatBuffer.flip(); + } + + private void makeProjectionMatrix(Matrix4f projectionMatrix, Matrix4f viewModelMatrix) { + this.projectionMatrix = projectionMatrix.mul(viewModelMatrix).get(BufferUtils.createFloatBuffer(16)); + } + + private void applyProjectionMatrix() { + shader.uniformMatrix4f("u_projection", projectionMatrix); + } +} diff --git a/src/main/java/themixray/repeating/mod/render/shader/Shader.java b/src/main/java/themixray/repeating/mod/render/shader/Shader.java new file mode 100644 index 0000000..e11dd9a --- /dev/null +++ b/src/main/java/themixray/repeating/mod/render/shader/Shader.java @@ -0,0 +1,42 @@ +package themixray.repeating.mod.render.shader; + +import lombok.Getter; + +import java.nio.FloatBuffer; + +import static org.lwjgl.opengl.GL33.*; + +public class Shader { + @Getter + private final int id; + + + public Shader(String name) { + int v = ShaderManager.loadShaderProgram(name, ShaderManager.ShaderType.VERTEX); + int f = ShaderManager.loadShaderProgram(name, ShaderManager.ShaderType.FRAGMENT); + this.id = glCreateProgram(); + glAttachShader(id, v); + glAttachShader(id, f); + glLinkProgram(id); + } + + public void bind() { + glUseProgram(id); + } + + public void unbind() { + glUseProgram(0); + } + + public void uniformMatrix4f(String name, FloatBuffer matrix) { + bind(); + glUniformMatrix4fv(glGetUniformLocation(id, name), false, matrix); + unbind(); + } + + public void uniformValue2f(String name, float value1, float value2) { + bind(); + glUniform2f(glGetUniformLocation(id, name), value1, value2); + unbind(); + } +} diff --git a/src/main/java/themixray/repeating/mod/render/shader/ShaderManager.java b/src/main/java/themixray/repeating/mod/render/shader/ShaderManager.java new file mode 100644 index 0000000..f11c98b --- /dev/null +++ b/src/main/java/themixray/repeating/mod/render/shader/ShaderManager.java @@ -0,0 +1,97 @@ +package themixray.repeating.mod.render.shader; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.platform.TextureUtil; +import lombok.Getter; +import lombok.SneakyThrows; +import lombok.experimental.UtilityClass; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gl.GlImportProcessor; +import net.minecraft.resource.Resource; +import net.minecraft.resource.ResourceFactory; +import net.minecraft.util.Identifier; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.system.MemoryUtil; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.Optional; + +import static org.lwjgl.opengl.GL33.*; + +@UtilityClass +public class ShaderManager { + @Getter + private Shader positionColorShader; + + public void init() { + ClientLifecycleEvents.CLIENT_STARTED.register(client -> loadShaders()); + } + + private void loadShaders() { + positionColorShader = new Shader("position_color"); + } + + public int loadShaderProgram(String name, ShaderType type) { + try { + boolean file_present = true; + ResourceFactory resourceFactory = MinecraftClient.getInstance().getResourceManager(); + Optional resource = resourceFactory.getResource(new Identifier("renderer", "shader/" + name + type.fileExtension)); + int i = glCreateShader(type.glType); + if (resource.isPresent()) { + GlStateManager.glShaderSource(i, new GlImportProcessor() { + @SneakyThrows + @Nullable + @Override + public String loadImport(boolean inline, String name) { + return IOUtils.toString(resource.get().getInputStream(), StandardCharsets.UTF_8); + } + }.readSource(readResourceAsString(resource.get().getInputStream()))); + } else file_present = false; + glCompileShader(i); + if (glGetShaderi(i, GL_COMPILE_STATUS) == 0 || !file_present) { + String shaderInfo = StringUtils.trim(glGetShaderInfoLog(i, 32768)); + throw new IOException("Couldn't compile " + type.name + " program (" + name + ") : " + shaderInfo); + } + return i; + } catch (IOException e) { + e.printStackTrace(); + } + return 0; + } + + private String readResourceAsString(InputStream inputStream) { + ByteBuffer byteBuffer = null; + try { + byteBuffer = TextureUtil.readResource(inputStream); + int i = byteBuffer.position(); + byteBuffer.rewind(); + return MemoryUtil.memASCII(byteBuffer, i); + } catch (IOException ignored) { + } finally { + if (byteBuffer != null) { + MemoryUtil.memFree(byteBuffer); + } + } + return null; + } + + public enum ShaderType { + VERTEX("vertex", ".vsh", GL_VERTEX_SHADER), + FRAGMENT("fragment", ".fsh", GL_FRAGMENT_SHADER); + private final String name; + private final String fileExtension; + private final int glType; + + ShaderType(String name, String fileExtension, int glType) { + this.name = name; + this.fileExtension = fileExtension; + this.glType = glType; + } + } +} diff --git a/src/main/resources/assets/renderer/shader/position_color.fsh b/src/main/resources/assets/renderer/shader/position_color.fsh new file mode 100644 index 0000000..aecb5f7 --- /dev/null +++ b/src/main/resources/assets/renderer/shader/position_color.fsh @@ -0,0 +1,12 @@ +#version 330 + +in vec4 vertexColor; + +out vec4 fragmentColor; + +void main() { + if (vertexColor.a == 0.0f) { + discard; + } + fragmentColor = vertexColor; +} \ No newline at end of file diff --git a/src/main/resources/assets/renderer/shader/position_color.vsh b/src/main/resources/assets/renderer/shader/position_color.vsh new file mode 100644 index 0000000..1f31658 --- /dev/null +++ b/src/main/resources/assets/renderer/shader/position_color.vsh @@ -0,0 +1,13 @@ +#version 330 + +layout (location = 0) in vec3 i_pos; +layout (location = 1) in vec4 i_color; + +uniform mat4 u_projection; + +out vec4 vertexColor; + +void main() { + gl_Position = u_projection * vec4(i_pos, 1.0f); + vertexColor = i_color; +} \ No newline at end of file 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 ee191bd..cfab5c4 100644 --- a/src/main/resources/assets/repeating-mod/lang/en_us.json +++ b/src/main/resources/assets/repeating-mod/lang/en_us.json @@ -4,19 +4,21 @@ "key.repeating-mod.toggle_record": "Toggle recording", "text.repeating-mod.name": "Repeating Mod", - "text.repeating-mod.record": "record", - "text.repeating-mod.replay": "replay", - "text.repeating-mod.start": "Start", - "text.repeating-mod.stop": "Stop", + "text.repeating-mod.start_record": "Start record", + "text.repeating-mod.stop_record": "Stop record", + "text.repeating-mod.start_replay": "Start replay", + "text.repeating-mod.stop_replay": "Stop replay", + "text.repeating-mod.record_tooltip": "Start/stop recording all activities", + "text.repeating-mod.replay_tooltip": "Start/stop repeating recorded actions", + "text.repeating-mod.loop_tooltip": "Enable/disable repeating of recorded actions replay", "text.repeating-mod.export": "Export record", "text.repeating-mod.import": "Import record", - "text.repeating-mod.basic": "Basic mode", - "text.repeating-mod.parkour": "Parkour mode", - "text.repeating-mod.settings": "Settings", + "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.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_text": "Timer after which the pos\nevent is added (20 ticks = 1 sec)", + "text.repeating-mod.pos_delay_tooltip": "Timer after which the pos\nevent is added (20 ticks = 1 sec)", "message.repeating-mod.replay_start": "Replay started", "message.repeating-mod.replay_stop": "Replay finished", diff --git a/src/main/resources/assets/repeating-mod/lang/ru_ru.json b/src/main/resources/assets/repeating-mod/lang/ru_ru.json index 46ba2e1..3fd30f4 100644 --- a/src/main/resources/assets/repeating-mod/lang/ru_ru.json +++ b/src/main/resources/assets/repeating-mod/lang/ru_ru.json @@ -4,19 +4,21 @@ "key.repeating-mod.toggle_record": "Вкл/выкл запись", "text.repeating-mod.name": "Репитинг Мод", - "text.repeating-mod.record": "запись", - "text.repeating-mod.replay": "повтор", - "text.repeating-mod.start": "Начать", - "text.repeating-mod.stop": "Остановить", + "text.repeating-mod.start_record": "Начать запись", + "text.repeating-mod.stop_record": "Остановить запись", + "text.repeating-mod.start_replay": "Начать повтор", + "text.repeating-mod.stop_replay": "Остановить повтор", + "text.repeating-mod.record_tooltip": "Начать/остановить запись всех действий", + "text.repeating-mod.replay_tooltip": "Начать/остановить повтор записанных действий", + "text.repeating-mod.loop_tooltip": "Вкл/выкл повтор повтора записанных действий", "text.repeating-mod.export": "Экспорт записи", "text.repeating-mod.import": "Импорт записи", - "text.repeating-mod.basic": "Обычный режим", - "text.repeating-mod.parkour": "Режим паркура", - "text.repeating-mod.settings": "Настройки", + "text.repeating-mod.export_tooltip": "Экспорт записи в файл", + "text.repeating-mod.import_tooltip": "Импорт записи из файла import.txt", "text.repeating-mod.dev": "В разработке...", "text.repeating-mod.nan_pos_delay": "Таймера позиции нету", "text.repeating-mod.pos_delay": "Таймер позиции: %s тиков", - "text.repeating-mod.pos_delay_text": "Таймер, после которой добавляется\nивент позиции (20 тиков = 1 сек)", + "text.repeating-mod.pos_delay_tooltip": "Таймер, после которой добавляется\nивент позиции (20 тиков = 1 сек)", "message.repeating-mod.replay_start": "Повтор начат", "message.repeating-mod.replay_stop": "Повтор закончен", diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index e137afe..cdf4d39 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -29,7 +29,7 @@ "depends": { "fabricloader": ">=0.14.14", "fabric-api": "*", - "minecraft": "1.19.x", + "minecraft": ">=1.20", "java": ">=17" }, "suggests": {