mega update

This commit is contained in:
MeexReay 2023-05-29 23:04:11 +03:00
parent ed627ca2f6
commit 94549c51e0
13 changed files with 518 additions and 138 deletions

View File

@ -1,40 +0,0 @@
# Automatically build the project and run any configured tests for every push
# and submitted pull request. This can help catch issues that only occur on
# certain platforms or Java versions, and provides a first line of defence
# against bad commits.
name: build
on: [pull_request, push]
jobs:
build:
strategy:
matrix:
# Use these Java versions
java: [
17, # Current Java LTS & minimum supported by Minecraft
]
# and run on both Linux and Windows
os: [ubuntu-22.04, windows-2022]
runs-on: ${{ matrix.os }}
steps:
- name: checkout repository
uses: actions/checkout@v3
- name: validate gradle wrapper
uses: gradle/wrapper-validation-action@v1
- name: setup jdk ${{ matrix.java }}
uses: actions/setup-java@v3
with:
java-version: ${{ matrix.java }}
distribution: 'microsoft'
- name: make gradle wrapper executable
if: ${{ runner.os != 'Windows' }}
run: chmod +x ./gradlew
- name: build
run: ./gradlew build
- name: capture build artifacts
if: ${{ runner.os == 'Linux' && matrix.java == '17' }} # Only upload artifacts built from latest java on one OS
uses: actions/upload-artifact@v3
with:
name: Artifacts
path: build/libs/

40
.gitignore vendored
View File

@ -1,40 +0,0 @@
# gradle
.gradle/
build/
out/
classes/
# eclipse
*.launch
# idea
.idea/
*.iml
*.ipr
*.iws
# vscode
.settings/
.vscode/
bin/
.classpath
.project
# macos
*.DS_Store
# fabric
run/
# java
hs_err_*.log
replay_*.log
*.hprof
*.jfr

View File

@ -12,6 +12,7 @@ repositories {
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically. // Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
// See https://docs.gradle.org/current/userguide/declaring_repositories.html // See https://docs.gradle.org/current/userguide/declaring_repositories.html
// for more information about repositories. // for more information about repositories.
maven { url 'https://maven.wispforest.io' }
} }
dependencies { dependencies {
@ -27,6 +28,16 @@ dependencies {
// These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time. // These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time.
// modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" // 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}"
// 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}"
// https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple
implementation group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1.1'
} }
base { base {

View File

@ -4,14 +4,16 @@ org.gradle.parallel=true
# Fabric Properties # Fabric Properties
# check these on https://fabricmc.net/develop # check these on https://fabricmc.net/develop
minecraft_version=1.19.4 minecraft_version=1.19.3
yarn_mappings=1.19.4+build.1 yarn_mappings=1.19.3+build.1
loader_version=0.14.17 loader_version=0.14.17
# Mod Properties # Mod Properties
mod_version = 1.0.0 mod_version = 1.0.0
maven_group = com.example maven_group = themixray.repeating.mod
archives_base_name = fabric-example-mod archives_base_name = repeating-mod
# Dependencies # Dependencies
fabric_version=0.75.3+1.19.4 fabric_version=0.76.1+1.19.3
owo_version=0.10.3+1.19.3

View File

@ -1,21 +0,0 @@
package net.fabricmc.example;
import net.fabricmc.api.ModInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ExampleMod implements ModInitializer {
// This logger is used to write text to the console and the log file.
// It is considered best practice to use your mod id as the logger's name.
// That way, it's clear which mod wrote info, warnings, and errors.
public static final Logger LOGGER = LoggerFactory.getLogger("modid");
@Override
public void onInitialize() {
// This code runs as soon as Minecraft is in a mod-load-ready state.
// However, some things (like resources) may still be uninitialized.
// Proceed with mild caution.
LOGGER.info("Hello Fabric world!");
}
}

View File

@ -1,16 +0,0 @@
package net.fabricmc.example.mixin;
import net.fabricmc.example.ExampleMod;
import net.minecraft.client.gui.screen.TitleScreen;
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;
@Mixin(TitleScreen.class)
public class ExampleMixin {
@Inject(at = @At("HEAD"), method = "init()V")
private void init(CallbackInfo info) {
ExampleMod.LOGGER.info("This line is printed by an example mod mixin!");
}
}

View File

@ -0,0 +1,338 @@
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;
import net.fabricmc.fabric.api.renderer.v1.RendererAccess;
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.util.InputUtil;
import net.minecraft.entity.MovementType;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.resource.Resource;
import net.minecraft.resource.ResourceManager;
import net.minecraft.resource.ResourceType;
import net.minecraft.text.Text;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.InputStream;
import java.util.*;
public class RepeatingMod 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 List<RecordEvent> record = new ArrayList<>();
public boolean is_recording = false;
public Date last_record = null;
public Thread replay = null;
public boolean is_replaying = false;
public boolean loop_replay = false;
public static boolean replay_sneaking = false;
public static RepeatingScreen menu;
private static KeyBinding menu_key;
private static KeyBinding toggle_replay_key;
private static KeyBinding toggle_record_key;
public double record_blocks_limit = 2;
public long record_time_limit = 50;
public EasyConfig conf;
@Override
public void onInitializeClient() {
LOGGER.info("Repeating mod initialized");
me = this;
Map<String,Object> def = new HashMap<>();
def.put("record_blocks_limit", record_blocks_limit);
def.put("record_time_limit", record_time_limit);
conf = new EasyConfig(new File(loader.getConfigDir().toFile(),"repeating-mod").toPath(),def);
record_blocks_limit = (double) conf.data.get("record_blocks_limit");
record_time_limit = (long) conf.data.get("record_time_limit");
menu_key = KeyBindingHelper.registerKeyBinding(new KeyBinding(
"key.repeating-mod.menu",InputUtil.Type.KEYSYM,
GLFW.GLFW_KEY_J,"text.repeating-mod.name"));
toggle_replay_key = KeyBindingHelper.registerKeyBinding(new KeyBinding(
"key.repeating-mod.toggle_replay",InputUtil.Type.KEYSYM,
-1,"text.repeating-mod.name"));
toggle_record_key = KeyBindingHelper.registerKeyBinding(new KeyBinding(
"key.repeating-mod.toggle_record",InputUtil.Type.KEYSYM,
-1,"text.repeating-mod.name"));
menu = new RepeatingScreen();
ClientTickEvents.END_CLIENT_TICK.register(client -> {
if (menu_key.wasPressed()) {
client.setScreen(menu);
}
if (toggle_replay_key.wasPressed()) {
if (!is_recording) {
if (is_replaying)
stopReplay();
else startReplay();
menu.update_btns();
}
}
if (toggle_record_key.wasPressed()) {
if (!is_replaying) {
if (is_recording)
stopRecording();
else startRecording();
menu.update_btns();
}
}
});
}
public RecordEvent getLastRecord(String t) {
for (RecordEvent r:Lists.reverse(new ArrayList<>(record))) {
if (r.getType().equals(t)) {
return r;
}
}
return null;
}
public void startRecording() {
is_recording = true;
menu.update_btns();
record.clear();
sendMessage(Text.translatable("message.repeating-mod.record_start"));
}
public void recordTick(RecordEvent e) {
Date now = new Date();
if (last_record != null) {
long diff = now.getTime() - last_record.getTime();
if (diff >= 0) record.add(new RecordDelayEvent(diff));
}
record.add(e);
last_record = now;
}
public void stopRecording() {
is_recording = false;
menu.update_btns();
last_record = null;
sendMessage(Text.translatable("message.repeating-mod.record_stop"));
}
public void startReplay() {
is_recording = false;
is_replaying = true;
menu.update_btns();
client.player.setNoGravity(true);
replay = new Thread(() -> {
while (true) {
for (RecordEvent e : record)
if (is_replaying)
e.callback();
if (!loop_replay || !is_replaying) break;
}
stopReplay();
});
replay.start();
sendMessage(Text.translatable("message.repeating-mod.replay_start"));
}
public void stopReplay() {
is_recording = false;
is_replaying = false;
menu.update_btns();
client.player.setNoGravity(false);
sendMessage(Text.translatable("message.repeating-mod.replay_stop"));
}
public static double round(double value, int places) {
if (places < 0) throw new IllegalArgumentException();
long factor = (long) Math.pow(10, places);
return (double) Math.round(value * factor) / factor;
}
public static void sendMessage(Text text) {
client.player.sendMessage(Text.literal("[")
.append(Text.translatable("text.repeating-mod.name"))
.append("] ").append(text));
}
public static abstract class RecordEvent {
abstract void callback();
abstract String toText();
abstract String getType();
public static RecordEvent fromText(String t) {
try {
String type = String.valueOf(t.charAt(0));
String[] args = t.substring(2).split("&");
if (type.equals("d")) {
return new RecordDelayEvent(
Long.parseLong(args[0]));
} else if (type.equals("m")) {
return new RecordMoveEvent(new Vec3d(
Double.parseDouble(args[0]),
Double.parseDouble(args[1]),
Double.parseDouble(args[2])),
Float.parseFloat(args[3]),
Float.parseFloat(args[4]));
} else if (type.equals("s")) {
return new RecordSneakEvent(
args[0].equals("1"));
} else if (type.equals("b")) {
return new RecordBlockBreakEvent(new BlockPos(
Integer.parseInt(args[0]),
Integer.parseInt(args[1]),
Integer.parseInt(args[2])));
} else if (type.equals("i")) {
return new RecordBlockInteractEvent(
Hand.valueOf(args[5]),
new BlockHitResult(new Vec3d(
Double.parseDouble(args[0]),
Double.parseDouble(args[1]),
Double.parseDouble(args[2])),
Direction.byId(Integer.parseInt(args[4])),
new BlockPos(
Integer.parseInt(args[0]),
Integer.parseInt(args[1]),
Integer.parseInt(args[2])),
args[3].equals("1")));
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
public static class RecordDelayEvent extends RecordEvent {
public long delay;
public RecordDelayEvent(long delay) {
this.delay = delay;
}
public void callback() {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public String toText() {
return "d="+delay;
}
public String getType() {
return "delay";
}
}
public static class RecordMoveEvent extends RecordEvent {
public Vec3d vec;
public float yaw;
public float pitch;
public RecordMoveEvent(Vec3d vec,float yaw,float pitch) {
this.vec = vec;
this.yaw = yaw;
this.pitch = pitch;
}
public void callback() {
Vec3d p = client.player.getPos();
Vec3d v = new Vec3d(vec.getX()-p.getX(),vec.getY()-p.getY(),vec.getZ()-p.getZ());
client.player.move(MovementType.SELF,v);
client.player.setYaw(yaw);
client.player.setPitch(pitch);
}
public String toText() {
return "m="+vec.getX()+"&"+vec.getY()+"&"+vec.getZ()+"&"+yaw+"&"+pitch;
}
public String getType() {
return "move";
}
}
public static class RecordSneakEvent extends RecordEvent {
public boolean sneaking;
public RecordSneakEvent(boolean sneaking) {
this.sneaking = sneaking;
}
public void callback() {
RepeatingMod.replay_sneaking = sneaking;
}
public String toText() {
return "s="+(sneaking?"1":"0");
}
public String getType() {
return "sneak";
}
}
public static class RecordBlockBreakEvent extends RecordEvent {
public BlockPos pos;
public RecordBlockBreakEvent(
BlockPos pos) {
this.pos = pos;
}
public void callback() {
client.interactionManager.breakBlock(pos);
}
public String toText() {
return "b="+pos.getX()+"&"+pos.getY()+"&"+pos.getZ();
}
public String getType() {
return "block_break";
}
}
public static class RecordBlockInteractEvent extends RecordEvent {
public Hand hand;
public BlockHitResult hitResult;
public RecordBlockInteractEvent(Hand hand, BlockHitResult hitResult) {
this.hand = hand;
this.hitResult = hitResult;
}
public void callback() {
client.interactionManager.interactBlock(client.player,hand,hitResult);
}
public String toText() {
return "i="+hitResult.getBlockPos().getX()+"&"+hitResult.getBlockPos().getY()+"&"+hitResult.getBlockPos().getZ()+
"&"+(hitResult.isInsideBlock()?"1":"0")+"&"+hitResult.getSide().getId()+"&"+hand.name();
}
public String getType() {
return "block_interact";
}
}
}

View File

@ -0,0 +1,92 @@
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.MinecraftClient;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.entity.MovementType;
import net.minecraft.text.Text;
import net.minecraft.util.ActionResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.Vec3d;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import themixray.repeating.mod.RepeatingMod;
import java.util.Date;
@Mixin(ClientPlayerEntity.class)
public abstract class MovementMixin {
public Vec3d lastVec = null;
@Shadow public abstract void sendMessage(Text message);
@Shadow @Final protected MinecraftClient client;
@Shadow public abstract float getYaw(float tickDelta);
@Shadow private float lastYaw;
@Shadow private float lastPitch;
@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 RepeatingMod.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 RepeatingMod.RecordBlockInteractEvent(hand,hitResult));
return ActionResult.PASS;
});
}
@Inject(at = @At(value = "HEAD"), method = "move")
private void onMove(MovementType movementType, Vec3d vec, CallbackInfo ci) {
if (RepeatingMod.me.is_recording) {
if (vec != lastVec) {
double dist = 0;
if (lastVec != null)
dist = vec.distanceTo(lastVec);
if (dist > 0.0) {
Vec3d c = client.player.getPos();
RepeatingMod.RecordMoveEvent ev = new RepeatingMod.RecordMoveEvent(
new Vec3d(c.getX() + vec.getX(),
c.getY() + vec.getY(),
c.getZ() + vec.getZ()),
lastYaw, lastPitch);
boolean just_add = true;
Date now = new Date();
if (RepeatingMod.me.last_record != null) {
long diff = now.getTime() - RepeatingMod.me.last_record.getTime();
boolean add_delay = true;
if (diff > 0) {
RepeatingMod.RecordEvent last_ev = RepeatingMod.me.record.get(RepeatingMod.me.record.size()-1);
if (last_ev instanceof RepeatingMod.RecordMoveEvent) {
RepeatingMod.RecordMoveEvent last_ev1 = (RepeatingMod.RecordMoveEvent) last_ev;
if (last_ev1.vec.distanceTo(ev.vec) < RepeatingMod.me.record_blocks_limit &&
diff < RepeatingMod.me.record_time_limit) {
just_add = false;
add_delay = false;
last_ev1.vec = ev.vec;
}
}
}
if (add_delay) {
RepeatingMod.me.record.add(new RepeatingMod.RecordDelayEvent(diff));
}
}
if (just_add) {
RepeatingMod.me.record.add(ev);
RepeatingMod.me.last_record = now;
}
}
}
lastVec = vec;
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 453 B

View File

@ -0,0 +1,26 @@
{
"key.repeating-mod.menu": "Repeating menu",
"key.repeating-mod.toggle_replay": "Toggle replay",
"key.repeating-mod.toggle_record": "Toggle recording",
"text.repeating-mod.name": "Repeating Mod",
"text.repeating-mod.record": "record",
"text.repeating-mod.replay": "replay",
"text.repeating-mod.start": "Start",
"text.repeating-mod.stop": "Stop",
"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.dev": "In development...",
"text.repeating-mod.block_limit": "Block limit: %s",
"text.repeating-mod.block_limit_tooltip": "Two recording events will\nbe summed up if the\ndistance between them is\nless than the limit.",
"text.repeating-mod.time_limit": "Time limit: %s ms",
"text.repeating-mod.time_limit_tooltip": "Two recording events will\nbe summed up if the time\nbetween them is less than\nthe limit.",
"message.repeating-mod.replay_start": "Replay started",
"message.repeating-mod.replay_stop": "Replay finished",
"message.repeating-mod.record_start": "Record started",
"message.repeating-mod.record_stop": "Record finished"
}

View File

@ -0,0 +1,27 @@
{
"key.repeating-mod.menu": "Меню репитинга",
"key.repeating-mod.toggle_replay": "Вкл/выкл повтор",
"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.export": "Экспорт записи",
"text.repeating-mod.import": "Импорт записи",
"text.repeating-mod.basic": "Обычный режим",
"text.repeating-mod.parkour": "Режим паркура",
"text.repeating-mod.settings": "Настройки",
"text.repeating-mod.dev": "В разработке...",
"text.repeating-mod.block_limit": "Лимит блоков: %s",
"text.repeating-mod.block_limit_tooltip": "Два ивента записи будут\nсуммироваться, если\nрасстояние между ними\nменьше лимита.",
"text.repeating-mod.time_limit": "Лимит времени: %s мс",
"text.repeating-mod.time_limit_tooltip": "Два ивента записи будут\nсуммироваться, если время\nмежду ними меньше лимита.",
"message.repeating-mod.replay_start": "Повтор начат",
"message.repeating-mod.replay_stop": "Повтор закончен",
"message.repeating-mod.record_start": "Запись начата",
"message.repeating-mod.record_stop": "Запись закончена"
}

View File

@ -1,12 +1,12 @@
{ {
"schemaVersion": 1, "schemaVersion": 1,
"id": "modid", "id": "repeating-mod",
"version": "${version}", "version": "${version}",
"name": "Example Mod", "name": "Repeating Mod",
"description": "This is an example description! Tell everyone what your mod is about!", "description": "Mod that repeats your actions. ",
"authors": [ "authors": [
"Me!" "TheMixRay"
], ],
"contact": { "contact": {
"homepage": "https://fabricmc.net/", "homepage": "https://fabricmc.net/",
@ -14,22 +14,22 @@
}, },
"license": "CC0-1.0", "license": "CC0-1.0",
"icon": "assets/modid/icon.png", "icon": "icon.png",
"environment": "*", "environment": "client",
"entrypoints": { "entrypoints": {
"main": [ "client": [
"net.fabricmc.example.ExampleMod" "themixray.repeating.mod.RepeatingMod"
] ]
}, },
"mixins": [ "mixins": [
"modid.mixins.json" "repeating-mod.mixins.json"
], ],
"depends": { "depends": {
"fabricloader": ">=0.14.17", "fabricloader": ">=0.14.14",
"fabric-api": "*", "fabric-api": "*",
"minecraft": "~1.19.4", "minecraft": "~1.19.3",
"java": ">=17" "java": ">=17"
}, },
"suggests": { "suggests": {

View File

@ -1,12 +1,13 @@
{ {
"required": true, "required": true,
"minVersion": "0.8", "minVersion": "0.8",
"package": "net.fabricmc.example.mixin", "package": "themixray.repeating.mod.mixin",
"compatibilityLevel": "JAVA_17", "compatibilityLevel": "JAVA_17",
"mixins": [ "mixins": [
], ],
"client": [ "client": [
"ExampleMixin" "MovementMixin",
"InputMixin"
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1