diff --git a/.github/workflows/dev_build.yml b/.github/workflows/dev_build.yml index 30b546b..398c7f5 100644 --- a/.github/workflows/dev_build.yml +++ b/.github/workflows/dev_build.yml @@ -26,8 +26,8 @@ jobs: uses: marvinpinto/action-automatic-releases@latest with: repo_token: '${{ secrets.GITHUB_TOKEN }}' - automatic_release_tag: "1.21.1_1.0.0.1" + automatic_release_tag: "1.21.1_1.0.0.2" prerelease: true - title: "1.21.1 | 1.0.0.1" + title: "1.21.1 | 1.0.0.2" files: | ./build/libs/*.jar diff --git a/gradle.properties b/gradle.properties index 16277b4..c4cbe64 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ yarn_mappings=1.21+build.3 loader_version=0.15.11 # Mod Properties -mod_version=1.21.1_1.0.0.1 +mod_version=1.21.1_1.0.0.2 maven_group=nekiplay.protrainer archives_base_name=pro-trainer diff --git a/src/main/java/nekiplay/protrainer/ProTrainerAddon.java b/src/main/java/nekiplay/protrainer/ProTrainerAddon.java index 79d3123..2830439 100644 --- a/src/main/java/nekiplay/protrainer/ProTrainerAddon.java +++ b/src/main/java/nekiplay/protrainer/ProTrainerAddon.java @@ -3,7 +3,9 @@ import meteordevelopment.meteorclient.MeteorClient; import meteordevelopment.meteorclient.addons.GithubRepo; import meteordevelopment.meteorclient.commands.Commands; +import meteordevelopment.meteorclient.systems.modules.Modules; import nekiplay.protrainer.features.commands.TrainerCommand; +import nekiplay.protrainer.features.modules.ProTrainerModule; import net.fabricmc.loader.api.FabricLoader; import meteordevelopment.meteorclient.addons.MeteorAddon; import org.slf4j.Logger; @@ -20,17 +22,22 @@ public static ProTrainerAddon getInstance() { return instance; } + public ProTrainerModule module = new ProTrainerModule(); + @Override public void onInitialize() { instance = this; - LOG.info(METEOR_LOGPREFIX + " Initializing..."); + LOG.info("Initializing..."); + Modules.get().add(module); TrainerCommand command = new TrainerCommand(); Commands.add(command); MeteorClient.EVENT_BUS.subscribe(command); + LOG.info("Initializing done"); + } @Override diff --git a/src/main/java/nekiplay/protrainer/data/BlockData.java b/src/main/java/nekiplay/protrainer/data/BlockData.java index 09d132f..54d3bdc 100644 --- a/src/main/java/nekiplay/protrainer/data/BlockData.java +++ b/src/main/java/nekiplay/protrainer/data/BlockData.java @@ -1,6 +1,18 @@ package nekiplay.protrainer.data; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; + public class BlockData { - public int blockId; - public BlockPosition blockPosition; + public int blockId = 0; + + public BlockData() {} + + public BlockData(int rawId) { + this.blockId = rawId; + } + + public BlockState toBlockState() { + return Block.getStateFromRawId(blockId); + } } diff --git a/src/main/java/nekiplay/protrainer/data/BlockDataAndPosition.java b/src/main/java/nekiplay/protrainer/data/BlockDataAndPosition.java new file mode 100644 index 0000000..b4ff042 --- /dev/null +++ b/src/main/java/nekiplay/protrainer/data/BlockDataAndPosition.java @@ -0,0 +1,15 @@ +package nekiplay.protrainer.data; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; + +public class BlockDataAndPosition { + public int blockId = 0; + public BlockPosition blockPosition; + + @Override + public int hashCode() { + return blockPosition.hashCode(); + } +} diff --git a/src/main/java/nekiplay/protrainer/data/BlockPosition.java b/src/main/java/nekiplay/protrainer/data/BlockPosition.java index 538a5df..b82e2ba 100644 --- a/src/main/java/nekiplay/protrainer/data/BlockPosition.java +++ b/src/main/java/nekiplay/protrainer/data/BlockPosition.java @@ -1,5 +1,8 @@ package nekiplay.protrainer.data; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import net.fabricmc.loader.impl.lib.sat4j.core.Vec; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; @@ -23,4 +26,25 @@ public BlockPosition(Vec3d pos) { public BlockPosition() { } + + @Override + public int hashCode() { + return new Vec3d(x, y, z).hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + BlockPosition other = (BlockPosition) obj; + if (x != other.x) + return false; + if (y != other.y) + return false; + return z == other.z; + } } diff --git a/src/main/java/nekiplay/protrainer/data/ProTrainerMap.java b/src/main/java/nekiplay/protrainer/data/ProTrainerMap.java index 115441c..f0e1922 100644 --- a/src/main/java/nekiplay/protrainer/data/ProTrainerMap.java +++ b/src/main/java/nekiplay/protrainer/data/ProTrainerMap.java @@ -1,9 +1,10 @@ package nekiplay.protrainer.data; import java.util.ArrayList; +import java.util.List; public class ProTrainerMap { - public ArrayList blocks = new ArrayList<>(); - public BlockPosition start = new BlockPosition(); + public List blocks = new ArrayList<>(); + } diff --git a/src/main/java/nekiplay/protrainer/features/commands/TrainerCommand.java b/src/main/java/nekiplay/protrainer/features/commands/TrainerCommand.java index a79bfa0..c3c4539 100644 --- a/src/main/java/nekiplay/protrainer/features/commands/TrainerCommand.java +++ b/src/main/java/nekiplay/protrainer/features/commands/TrainerCommand.java @@ -7,10 +7,12 @@ import meteordevelopment.meteorclient.MeteorClient; import meteordevelopment.meteorclient.commands.Command; import meteordevelopment.meteorclient.events.packets.PacketEvent; +import meteordevelopment.meteorclient.events.world.BlockUpdateEvent; import meteordevelopment.orbit.EventHandler; import nekiplay.Main; import nekiplay.protrainer.ProTrainerAddon; import nekiplay.protrainer.data.BlockData; +import nekiplay.protrainer.data.BlockDataAndPosition; import nekiplay.protrainer.data.BlockPosition; import nekiplay.protrainer.data.ProTrainerMap; import nekiplay.protrainer.mixin.minecraft.PlayerMoveC2SPacketAccesor; @@ -28,6 +30,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.stream.Collectors; @@ -42,7 +45,8 @@ public TrainerCommand() { public boolean started = false; public Vec3d start_position = new Vec3d(0, 0, 0); - public List replaced = new ArrayList<>(); + public List replaced = new ArrayList<>(); + public HashMap map_blocks = new HashMap<>(); public void build(LiteralArgumentBuilder builder) { builder.then(literal("pos1").executes(context -> { @@ -69,35 +73,52 @@ public void build(LiteralArgumentBuilder builder) { } File dir2 = new File(dir, map + ".json"); - try { - BufferedReader reader = Files.newBufferedReader(Path.of(dir2.toURI()), StandardCharsets.UTF_8); - try { - String json = reader.lines().collect(Collectors.joining()); - - ProTrainerMap proTrainerMap = gson.fromJson(json, ProTrainerMap.class); - for (BlockData data : proTrainerMap.blocks) { - assert mc.world != null; - BlockState state = Block.getStateFromRawId(data.blockId); - BlockPos pos = new BlockPos((int) (data.blockPosition.x + mc.player.getBlockX()), (int) (data.blockPosition.y + mc.player.getBlockY()), (int) (data.blockPosition.z + mc.player.getBlockZ())); - - BlockData blockData = new BlockData(); - blockData.blockPosition = new BlockPosition(pos); - blockData.blockId = Block.getRawIdFromState(mc.world.getBlockState(pos)); - replaced.add(blockData); + start_position = mc.player.getPos(); - mc.world.setBlockState(pos, state); + new Thread(() -> { + try { + map_blocks.clear(); + BufferedReader reader = Files.newBufferedReader(Path.of(dir2.toURI()), StandardCharsets.UTF_8); + try { + String json = reader.lines().collect(Collectors.joining()); + int counter = 0; + ProTrainerMap proTrainerMap = gson.fromJson(json, ProTrainerMap.class); + for (BlockDataAndPosition data : proTrainerMap.blocks) { + assert mc.world != null; + BlockState state = Block.getStateFromRawId(data.blockId); + mc.player.setPos(start_position.x, start_position.y, start_position.z); + BlockPos pos = new BlockPos((int) (data.blockPosition.x + mc.player.getBlockX()), (int) (data.blockPosition.y + mc.player.getBlockY()), (int) (data.blockPosition.z + mc.player.getBlockZ())); + + BlockDataAndPosition blockData = new BlockDataAndPosition(); + blockData.blockPosition = new BlockPosition(pos); + blockData.blockId = Block.getRawIdFromState(mc.world.getBlockState(pos)); + replaced.add(blockData); + map_blocks.put(new BlockPosition(pos), new BlockData(data.blockId)); + + BlockState original_state = mc.world.getBlockState(pos); + if (original_state.getBlock() != state.getBlock()) { + mc.execute(() -> mc.world.setBlockState(pos, state)); + if (counter >= ProTrainerAddon.getInstance().module.loadingSpeed.get()) { + Thread.sleep(1); + counter = 0; + } else { + counter++; + } + } + } + info("Successfully loaded"); + + } catch (JsonSyntaxException e) { + ProTrainerAddon.LOG.error(Main.METEOR_LOGPREFIX + " Error in custom block: " + e); + + } catch (InterruptedException e) { + ProTrainerAddon.LOG.error(Main.METEOR_LOGPREFIX + " Error in custom block: " + e); } - - } catch (JsonSyntaxException e) { + } catch (IOException e) { ProTrainerAddon.LOG.error(Main.METEOR_LOGPREFIX + " Error in custom block: " + e); - } - } catch (IOException e) { - ProTrainerAddon.LOG.error(Main.METEOR_LOGPREFIX + " Error in custom block: " + e); - } - info("Successfully loaded"); - start_position = mc.player.getPos(); - started = true; + started = true; + }).start(); return SINGLE_SUCCESS; } else { @@ -110,16 +131,29 @@ public void build(LiteralArgumentBuilder builder) { info("Parkour hasn't started"); return SINGLE_SUCCESS; } - for (BlockData replace : replaced) { - mc.player.setPos(start_position.x, start_position.y, start_position.z); - BlockState state = Block.getStateFromRawId(replace.blockId); - BlockPos pos = new BlockPos((int) replace.blockPosition.x, (int) replace.blockPosition.y, (int) replace.blockPosition.z); - mc.world.setBlockState(pos, state); + new Thread(() -> { + int counter = 0; + map_blocks.clear(); + for (BlockDataAndPosition replace : replaced) { + BlockState state = Block.getStateFromRawId(replace.blockId); + BlockPos pos = new BlockPos((int) replace.blockPosition.x, (int) replace.blockPosition.y, (int) replace.blockPosition.z); + mc.execute(() -> mc.world.setBlockState(pos, state)); + if (counter >= ProTrainerAddon.getInstance().module.loadingSpeed.get()) { + try { + Thread.sleep(1); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + counter = 0; + } else { + counter++; + } + } mc.player.setPos(start_position.x, start_position.y, start_position.z); started = false; - } - replaced.clear(); - info("Parkour has been stopped"); + replaced.clear(); + info("Parkour has been stopped"); + }).start(); return SINGLE_SUCCESS; })); builder.then(literal("save").then(argument("map", StringArgumentType.string()).executes(context -> { @@ -134,7 +168,6 @@ public void build(LiteralArgumentBuilder builder) { String map = context.getArgument("map", String.class); Vec3d start = mc.player.getPos(); ProTrainerMap trainerMap = new ProTrainerMap(); - trainerMap.start = new BlockPosition(start); List blocks = collectBlocksBetween(mc.world, pos1, pos2); List sortedBlocks = new ArrayList<>(); @@ -144,7 +177,7 @@ public void build(LiteralArgumentBuilder builder) { for (BlockPos sorted : sortedBlocks) { var unsorted = sorted.add(new Vec3i(mc.player.getBlockX(), mc.player.getBlockY(), mc.player.getBlockZ())); BlockState state = mc.world.getBlockState(unsorted); - BlockData blockData = new BlockData(); + BlockDataAndPosition blockData = new BlockDataAndPosition(); blockData.blockId = Block.getRawIdFromState(state); blockData.blockPosition = new BlockPosition(sorted); trainerMap.blocks.add(blockData); @@ -196,6 +229,15 @@ public List collectBlocksBetween(World world, BlockPos start, BlockPos return blocks; } + @EventHandler + private void onBlockUpdate(BlockUpdateEvent event) { + BlockPosition position = new BlockPosition(event.pos); + if (map_blocks.containsKey(position) && started) { + BlockData data = map_blocks.get(position); + mc.world.setBlockState(event.pos, Block.getStateFromRawId(data.blockId)); + } + } + @EventHandler private void onSendPacket(PacketEvent.Send event) { if (event.packet instanceof PlayerMoveC2SPacket playerMoveC2SPacket) { diff --git a/src/main/java/nekiplay/protrainer/features/modules/ProTrainerModule.java b/src/main/java/nekiplay/protrainer/features/modules/ProTrainerModule.java index a208961..75ce6a7 100644 --- a/src/main/java/nekiplay/protrainer/features/modules/ProTrainerModule.java +++ b/src/main/java/nekiplay/protrainer/features/modules/ProTrainerModule.java @@ -1,5 +1,8 @@ package nekiplay.protrainer.features.modules; +import meteordevelopment.meteorclient.settings.IntSetting; +import meteordevelopment.meteorclient.settings.Setting; +import meteordevelopment.meteorclient.settings.SettingGroup; import meteordevelopment.meteorclient.systems.modules.Categories; import meteordevelopment.meteorclient.systems.modules.Module; @@ -8,5 +11,17 @@ public ProTrainerModule() { super(Categories.World, "pro-trainer", "Settings for trainer command"); } + private final SettingGroup defaultGroup = settings.getDefaultGroup(); + + public final Setting loadingSpeed = defaultGroup.add(new IntSetting.Builder() + .name("loading-speed") + .description("World loading speed in blocks.") + .defaultValue(8) + .min(1) + .max(64) + .sliderMin(1) + .sliderMax(64) + .build() + ); }