Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
uses: actions/setup-java@v3
with:
java-version: 21
distribution: "temurin"
distribution: "temurin"
- name: Build with Gradle
run: ./gradlew build '-Pversion=${{ github.run_number }}'
- name: Upload Artifact
Expand Down
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ dependencies {
modImplementation "com.terraformersmc:modmenu:${project.modmenu_version}"

// Adventure for MiniMessage parsing.
implementation("net.kyori:adventure-api:${project.adventure_api_version}")
modImplementation include("net.kyori:adventure-platform-fabric:${project.adventure_fabric_version}")

// WebSocket for CodeClient API.
Expand Down
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ archives_base_name=CodeClient
fabric_version=0.108.0+1.21.3
modmenu_version=12.0.0-beta.1
yacl_version=3.6.1+1.21.2-fabric
adventure_api_version=4.17.0
adventure_fabric_version=6.1.0
15 changes: 14 additions & 1 deletion src/main/java/dev/dfonline/codeclient/CodeClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import dev.dfonline.codeclient.action.None;
import dev.dfonline.codeclient.action.impl.DevForBuild;
import dev.dfonline.codeclient.command.CommandManager;
import dev.dfonline.codeclient.command.CommandSender;
import dev.dfonline.codeclient.config.Config;
import dev.dfonline.codeclient.config.KeyBinds;
import dev.dfonline.codeclient.data.DFItem;
Expand All @@ -15,6 +16,7 @@
import dev.dfonline.codeclient.data.value.StringDataValue;
import dev.dfonline.codeclient.dev.*;
import dev.dfonline.codeclient.dev.debug.Debug;
import dev.dfonline.codeclient.dev.highlighter.ExpressionHighlighter;
import dev.dfonline.codeclient.dev.menu.InsertOverlayFeature;
import dev.dfonline.codeclient.dev.menu.RecentValues;
import dev.dfonline.codeclient.dev.menu.SlotGhostManager;
Expand Down Expand Up @@ -50,6 +52,7 @@
import net.minecraft.network.listener.PacketListener;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket;
import net.minecraft.network.packet.s2c.play.BundleS2CPacket;
import net.minecraft.network.packet.s2c.play.CloseScreenS2CPacket;
import net.minecraft.screen.slot.Slot;
import net.minecraft.screen.slot.SlotActionType;
Expand Down Expand Up @@ -115,6 +118,8 @@ public void onInitializeClient() {

ClientLifecycleEvents.CLIENT_STOPPING.register(Identifier.of(MOD_ID, "close"), client -> API.stop());

ClientTickEvents.END_CLIENT_TICK.register(client -> CommandSender.tick());

if (Config.getConfig().CodeClientAPI) {
try {
API.start();
Expand Down Expand Up @@ -187,7 +192,7 @@ private static void loadFeatures() {
feat(new ChatAutoEdit());
feat(new CPUDisplay());
feat(new MessageHiding());
//FIXME: feat(new ExpressionHighlighter());
feat(new ExpressionHighlighter());
}

/**
Expand Down Expand Up @@ -225,6 +230,12 @@ public static <T extends Feature> Optional<T> getFeature(Class<T> clazz) {
}

public static <T extends PacketListener> boolean handlePacket(Packet<T> packet) {
if (packet instanceof BundleS2CPacket bundle) {
bundle.getPackets().forEach(CodeClient::handlePacket);
return false;
}


if (currentAction.onReceivePacket(packet)) return true;
for (var feature : features().toList()) {
if (feature.onReceivePacket(packet)) return true;
Expand Down Expand Up @@ -272,6 +283,8 @@ public static void onTick() {
features().forEach(Feature::tick);
KeyBinds.tick();

// System.out.println(location.name());

if (!(location instanceof Dev) || !(MC.currentScreen instanceof HandledScreen<?>)) {
isCodeChest = false;
features().forEach(Feature::closeChest);
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/dev/dfonline/codeclient/Event.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package dev.dfonline.codeclient;

import dev.dfonline.codeclient.command.CommandSender;
import dev.dfonline.codeclient.config.Config;
import dev.dfonline.codeclient.location.*;
import net.minecraft.network.listener.PacketListener;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.c2s.play.ChatMessageC2SPacket;
import net.minecraft.network.packet.c2s.play.CommandExecutionC2SPacket;
import net.minecraft.network.packet.s2c.play.*;
import net.minecraft.util.math.Vec3d;
Expand Down Expand Up @@ -52,10 +54,14 @@ public static <T extends PacketListener> void handlePacket(Packet<T> packet) {

public static <T extends PacketListener> void onSendPacket(Packet<T> packet) {
if (packet instanceof CommandExecutionC2SPacket command) {
CommandSender.registerCommandSend();
if (List.of("play", "build", "code", "dev").contains(command.command().replaceFirst("mode ", ""))) {
switchingMode = true;
}
}
if (packet instanceof ChatMessageC2SPacket) {
CommandSender.registerCommandSend();
}
}

public static void updateLocation(Location location) {
Expand Down
1 change: 0 additions & 1 deletion src/main/java/dev/dfonline/codeclient/ItemSelector.java
Original file line number Diff line number Diff line change
Expand Up @@ -131,5 +131,4 @@ protected void appendClickableNarrations(NarrationMessageBuilder builder) {
private record Search(ItemStack item, int x, int y) {
}

;
}
44 changes: 44 additions & 0 deletions src/main/java/dev/dfonline/codeclient/RateLimiter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package dev.dfonline.codeclient;

/**
* A rate limiter that can be used to limit the rate of execution of a certain operation.
*/
public class RateLimiter {
private final int incrementStep;
private final int threshold;
private int count;

/**
* Creates a new rate limiter.
* @param incrementStep The amount to increment the count by each time the operation is executed.
* @param threshold The maximum count before the operation is rate limited.
*/
public RateLimiter(int incrementStep, int threshold) {
this.incrementStep = incrementStep;
this.threshold = threshold;
}

/**
* Registers an operation, incrementing the count.
*/
public void increment() {
count += incrementStep;
}

/**
* Decrements the count, should be called once per tick.
*/
public void tick() {
if (count > 0) {
--count;
}
}

/**
* Checks if the operation is rate limited.
* @return True if the operation is rate limited, false otherwise.
*/
public boolean isRateLimited() {
return count >= threshold;
}
}
44 changes: 21 additions & 23 deletions src/main/java/dev/dfonline/codeclient/Utility.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import dev.dfonline.codeclient.action.impl.GetActionDump;
import dev.dfonline.codeclient.data.DFItem;
import dev.dfonline.codeclient.hypercube.template.Template;
import net.kyori.adventure.platform.modcommon.impl.NonWrappingComponentSerializer;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack;
Expand All @@ -17,6 +18,7 @@
import net.minecraft.text.*;
import net.minecraft.util.Formatting;
import org.jetbrains.annotations.Nullable;
import net.kyori.adventure.text.Component;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
Expand All @@ -26,8 +28,6 @@
import java.util.regex.Pattern;
import java.util.zip.GZIPOutputStream;

//FIXME: import static net.kyori.adventure.platform.fabric.FabricAudiences.nonWrappingSerializer;

public class Utility {
/**
* Get the slot id to be used with a creative packet, from a local slot id.
Expand Down Expand Up @@ -174,7 +174,6 @@ public static void sendMessage(Text message, @Nullable ChatType type) {
* @return Usable in lore and as a name in nbt.
*/
public static NbtString textToNBT(Text text) {
assert CodeClient.MC.world != null;
JsonElement json = TextCodecs.CODEC.encodeStart(JsonOps.INSTANCE, text).getOrThrow();
if (json.isJsonObject()) {
JsonObject obj = (JsonObject) json;
Expand Down Expand Up @@ -299,25 +298,24 @@ public static String fromTrimmed(String trimmedUUID) {
return builder.toString();
}

/* FIXME: */
// /**
// * Turns a {@link Component} to an {@link OrderedText}
// *
// * @param component The component to convert
// * @return The converted component
// */
// public static OrderedText componentToOrderedText(Component component) {
// return nonWrappingSerializer().serialize(component).asOrderedText();
// }
//
// /**
// * Turns a {@link Component} to a {@link Text}
// *
// * @param component The component to convert
// * @return The converted component
// */
// public static Text componentToText(Component component) {
// return nonWrappingSerializer().serialize(component);
// }
/**
* Turns a {@link net.kyori.adventure.text.Component} to an {@link OrderedText}
*
* @param component The component to convert
* @return The converted component
*/
public static OrderedText componentToOrderedText(Component component) {
return NonWrappingComponentSerializer.INSTANCE.serialize(component).asOrderedText();
}

/**
* Turns a {@link net.kyori.adventure.text.Component} to a {@link Text}
*
* @param component The component to convert
* @return The converted component
*/
public static Text componentToText(Component component) {
return NonWrappingComponentSerializer.INSTANCE.serialize(component);
}

}
3 changes: 0 additions & 3 deletions src/main/java/dev/dfonline/codeclient/action/Action.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package dev.dfonline.codeclient.action;

import dev.dfonline.codeclient.Callback;
import dev.dfonline.codeclient.CodeClient;
import dev.dfonline.codeclient.Feature;
import dev.dfonline.codeclient.location.Location;
import net.minecraft.network.packet.Packet;

public abstract class Action extends Feature {
private final Callback callback;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public void tick() {


private class PickUpBlock extends Action {
private BlockPos pos;
private final BlockPos pos;
private Integer ticks = 0;

public PickUpBlock(BlockPos pos, Callback callback) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class CommandManager {
new CommandName(),
new CommandNode(),
new CommandPing(),
//FIXME: new CommandPreview(),
new CommandPreview(),
new CommandSave(),
new CommandScanFor(),
new CommandScanPlot(),
Expand All @@ -36,7 +36,8 @@ public class CommandManager {
new CommandTemplatePlacer(),
new CommandUuid(),
new CommandWidthDump(),
new CommandWorldPlot()
new CommandWorldPlot(),
new CommandClearQueue()
);

public static void init(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess registryAccess) {
Expand Down
69 changes: 69 additions & 0 deletions src/main/java/dev/dfonline/codeclient/command/CommandSender.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package dev.dfonline.codeclient.command;

import dev.dfonline.codeclient.CodeClient;
import dev.dfonline.codeclient.RateLimiter;

import java.util.ArrayDeque;

/**
* Queues up commands and sends them to avoid getting kicked for spam.
*/
public class CommandSender {
// Vanilla Minecraft uses 20 increment 200 threshold.
// We have a lower threshold for extra safety and to account for lag.
private static final RateLimiter rateLimiter = new RateLimiter(20, 140);
private static final ArrayDeque<String> commandQueue = new ArrayDeque<>();

/*
public static void queue(String command, int delay, Runnable callback) {
rateLimiter.increment();
for (int i = 0; i < delay; i++) {
}
commandQueue.add(command);
if (callback != null) {
callback.run();
}
}

public static void queue(String command, int delay) {
queue(command, delay, null);
}

public static void queue(String command) {
queue(command, 0, null);
}
*/

public static void queue(String command) {
// rateLimiter.increment();
commandQueue.add(command);
}

public static void clearQueue() {
commandQueue.clear();
}

public static int queueSize() {
return commandQueue.size();
}


public static void tick() {
rateLimiter.tick();
if (CodeClient.MC.getNetworkHandler() == null) return;
if (!rateLimiter.isRateLimited() && !commandQueue.isEmpty()) {
CodeClient.MC.getNetworkHandler().sendCommand(commandQueue.pop());
// No need to increment here, since our packet listener will do that for us. (Event#onSendPacket)
}
}


/**
* Registers a command send.
* This should be called whenever a command or chat message is sent to the server.
*/
public static void registerCommandSend() {
rateLimiter.increment();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package dev.dfonline.codeclient.command.impl;

import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import dev.dfonline.codeclient.ChatType;
import dev.dfonline.codeclient.Utility;
import dev.dfonline.codeclient.command.Command;
import dev.dfonline.codeclient.command.CommandSender;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.text.Text;

public class CommandClearQueue extends Command {

@Override
public String name() {
return "ccclearqueue";
}

@Override
public LiteralArgumentBuilder<FabricClientCommandSource> create(LiteralArgumentBuilder<FabricClientCommandSource> cmd, CommandRegistryAccess registryAccess) {
return cmd.executes(context -> {
if (CommandSender.queueSize() > 0) {
CommandSender.clearQueue();
Utility.sendMessage(Text.translatable("codeclient.action.clearqueue.success"), ChatType.SUCCESS);
} else {
Utility.sendMessage(Text.translatable("codeclient.action.clearqueue.empty"), ChatType.FAIL);
}

return 1;
});
}
}
Loading