use chipmunk cloop and sync some stuff

This commit is contained in:
Chayapak 2023-05-07 20:18:44 +07:00
parent ee22870183
commit ae6f3b21ac
5 changed files with 148 additions and 159 deletions

View file

@ -3,127 +3,102 @@ package land.chipmunk.chipmunkmod.commands;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContext;
import land.chipmunk.chipmunkmod.data.CommandLoop;
import land.chipmunk.chipmunkmod.modules.CommandLooper;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
import static com.mojang.brigadier.arguments.LongArgumentType.longArg;
import static com.mojang.brigadier.arguments.LongArgumentType.getLong;
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString;
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import land.chipmunk.chipmunkmod.modules.CommandLoopManager;
import java.util.List;
import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString;
import static land.chipmunk.chipmunkmod.command.CommandManager.argument;
import static land.chipmunk.chipmunkmod.command.CommandManager.literal;
public class CloopCommand {
private static final DynamicCommandExceptionType INVALID_CLOOP_ID_EXCEPTION = new DynamicCommandExceptionType(id -> Text.translatable("Invalid cloop id: %s", Text.literal(String.valueOf(id))));
public static void register (CommandDispatcher<FabricClientCommandSource> dispatcher) {
dispatcher.register(
literal("cloop")
.then(
literal("add")
.then(
argument("interval", integer())
argument("interval", longArg())
.then(
argument("command", greedyString())
.executes(c -> add(c))
.executes(c -> addCloop(c))
)
)
)
.then(
literal("remove")
.then(
argument("index", integer())
.executes(c -> remove(c))
argument("id", integer())
.executes(c -> removeCloop(c))
)
)
.then(
literal("clear")
.executes(c -> clear(c))
.executes(c -> clearCloops(c))
)
.then(
literal("list")
.executes(c -> list(c))
.executes(c -> listCloops(c))
)
);
}
public static int add (CommandContext<FabricClientCommandSource> context) {
public static int addCloop (CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource();
final long interval = getLong(context, "interval");
final String command = getString(context, "command");
final int interval = getInteger(context, "interval");
CommandLooper.INSTANCE.addLoop(command, interval);
source.sendFeedback(
Text.translatable(
"Added command %s with interval %s to the command loops",
Text.literal(command).formatted(Formatting.AQUA),
Text.literal(String.valueOf(interval)).formatted(Formatting.GOLD)
)
);
int id = CommandLoopManager.INSTANCE.loopCommand(command, interval);
source.sendFeedback(Text.translatable("Successfully created a loop for command '%s' with id %s", Text.literal(command), Text.literal(String.valueOf(id))));
return Command.SINGLE_SUCCESS;
}
public static int remove (CommandContext<FabricClientCommandSource> context) {
public static int removeCloop (CommandContext<FabricClientCommandSource> context) throws CommandSyntaxException {
final FabricClientCommandSource source = context.getSource();
final CommandLoopManager manager = CommandLoopManager.INSTANCE;
final int id = getInteger(context, "id");
final int index = getInteger(context, "index");
if (id < 0 || id >= manager.commandLoops().size()) throw INVALID_CLOOP_ID_EXCEPTION.create(id);
CommandLooper.INSTANCE.removeLoop(index);
source.sendFeedback(
Text.translatable(
"Removed command loop %s",
Text.literal(String.valueOf(index)).formatted(Formatting.GOLD)
)
);
manager.removeAndStop(id);
source.sendFeedback(Text.translatable("Successfully removed loop with id %s", Text.literal(String.valueOf(id))));
return Command.SINGLE_SUCCESS;
}
public static int list (CommandContext<FabricClientCommandSource> context) {
public static int clearCloops (CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource();
final CommandLoopManager manager = CommandLoopManager.INSTANCE;
final List<CommandLoop> cloops = CommandLooper.INSTANCE.loops();
manager.clearLoops();
MutableText text = Text.empty();
text.append(Text.literal("Command Loops:").formatted(Formatting.GREEN));
text.append("\n"); // should i use Text.literal("\n")?
source.sendFeedback(Text.translatable("Successfully cleared all command loops"));
return Command.SINGLE_SUCCESS;
}
for (int i = 0; i < cloops.size(); i++) {
final CommandLoop cloop = cloops.get(i);
text.append(
Text.translatable(
"%s > %s - %s", // should i use \u203a?
Text.literal(String.valueOf(i)).formatted(Formatting.GREEN),
Text.literal(cloop.command()).formatted(Formatting.AQUA),
Text.literal(String.valueOf(cloop.interval())).formatted(Formatting.GOLD)
).formatted(Formatting.GRAY)
);
public static int listCloops (CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource();
final List<CommandLoopManager.CommandLoop> loops = CommandLoopManager.INSTANCE.commandLoops();
// PLS TELL ME HOW TO REMOVE THE LAST ONE OF MutableText SPLSPLpLSLPsSSPLPSPLSPSL
// btw is this the best way to do it lol
final int lastIndex = cloops.size() - 1;
if (i < lastIndex) { text.append("\n"); }
int id = 0;
for (CommandLoopManager.CommandLoop loop : loops) {
source.sendFeedback(Text.translatable("%s: %s (%s)", Text.literal(String.valueOf(id)), Text.literal(loop.command()), Text.literal(String.valueOf(loop.interval()))));
id++;
}
source.sendFeedback(text);
return Command.SINGLE_SUCCESS;
}
public static int clear (CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource();
CommandLooper.INSTANCE.clearLoops();
source.sendFeedback(Text.literal("Cleared all command loops"));
if (id == 0) {
source.sendFeedback(Text.translatable("No command loops are currently running"));
}
return Command.SINGLE_SUCCESS;
}

View file

@ -1,28 +1,36 @@
package land.chipmunk.chipmunkmod.mixin;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.suggestion.Suggestions;
import land.chipmunk.chipmunkmod.command.CommandManager;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.widget.TextFieldWidget;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
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 java.util.concurrent.CompletableFuture;
import com.mojang.brigadier.suggestion.Suggestions;
import net.minecraft.client.gui.widget.TextFieldWidget;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.client.MinecraftClient;
import land.chipmunk.chipmunkmod.command.CommandManager;
@Mixin(net.minecraft.client.gui.screen.ChatInputSuggestor.class)
public class ChatInputSuggestorMixin {
@Shadow
CompletableFuture<Suggestions> pendingSuggestions;
private CompletableFuture<Suggestions> pendingSuggestions;
@Final
@Shadow
private boolean slashOptional;
@Shadow
public void show (boolean narrateFirstSuggestion) {}
@Mutable
@Final
@Shadow
final TextFieldWidget textField;
@ -31,7 +39,9 @@ public class ChatInputSuggestorMixin {
}
@Inject(at = @At("TAIL"), method = "refresh()V")
public void onRefresh (CallbackInfo ci) {
public void refresh (CallbackInfo ci) {
if (slashOptional) return;
final String text = this.textField.getText();
final int cursor = this.textField.getCursor();

View file

@ -12,7 +12,6 @@ public class ClientPlayNetworkHandlerMixin {
@Inject(method = "onGameJoin", at = @At("TAIL"))
private void onGameJoin (GameJoinS2CPacket packet, CallbackInfo ci) {
SelfCare.INSTANCE.init();
CommandLooper.INSTANCE.init();
SongPlayer.INSTANCE.coreReady();
RainbowName.INSTANCE.init();
}

View file

@ -0,0 +1,83 @@
package land.chipmunk.chipmunkmod.modules;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
public class CommandLoopManager {
private final CommandCore core;
@Getter @Setter private List<CommandLoop> commandLoops = new ArrayList<>();
public CommandLoopManager (CommandCore core) {
this.core = core;
}
public static final CommandLoopManager INSTANCE = new CommandLoopManager(CommandCore.INSTANCE);
public int loopCommand (String command, long interval) {
final CommandLoop loop = new CommandLoop(this.core, command, interval);
if (!commandLoops.add(loop)) return -1;
return commandLoops.size() - 1;
}
public boolean removeAndStop (CommandLoop loop) {
loop.stop();
return commandLoops.remove(loop);
}
public boolean removeAndStop (int id) {
return removeAndStop(commandLoops.get(id));
}
public void clearLoops () {
for (CommandLoop loop : this.commandLoops) loop.stop();
commandLoops.clear();
}
public void cleanup () { this.clearLoops(); }
public static class CommandLoop {
@Getter @Setter private CommandCore core;
@Getter @Setter private String command;
@Getter private long interval;
private Timer timer;
public CommandLoop (CommandCore core, String command, long interval) {
this.core = core;
this.command = command;
this.interval = interval;
this.timer = new Timer();
timer.schedule(this.createTimerTask(), interval, interval);
}
private long interval (long interval) {
if (timer == null) throw new IllegalStateException("Attempted to set the interval of a stopped command loop");
timer.cancel();
timer.purge();
this.interval = interval;
this.timer = new Timer();
timer.schedule(this.createTimerTask(), interval, interval);
return interval;
}
private void stop () {
timer.cancel();
timer.purge();
}
public TimerTask createTimerTask () {
return new TimerTask() {
@Override
public void run () {
core.run(command);
}
};
}
}
}

View file

@ -1,78 +0,0 @@
package land.chipmunk.chipmunkmod.modules;
import land.chipmunk.chipmunkmod.data.CommandLoop;
import lombok.Getter;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
public class CommandLooper {
private final MinecraftClient client;
// sus
private final List<TimerTask> loopTasks = new ArrayList<>();
@Getter private final List<CommandLoop> loops = new ArrayList<>();
private Timer timer = null;
public static CommandLooper INSTANCE = new CommandLooper(MinecraftClient.getInstance());
public CommandLooper (MinecraftClient client) {
this.client = client;
}
public void init () {
TimerTask task = new TimerTask() {
@Override
public void run () {
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
if (networkHandler == null) { cleanup(); }
}
};
if (timer != null) cleanup();
timer = new Timer();
timer.schedule(task, 0, 50);
}
public void cleanup() {
if (timer == null) return;
clearLoops();
}
public void addLoop(String command, long interval) {
TimerTask loopTask = new TimerTask() {
public void run() {
CommandCore.INSTANCE.run(command);
}
};
loopTasks.add(loopTask);
loops.add(new CommandLoop(command, interval)); // mabe,.,..
// should i use 50 or 0?
timer.scheduleAtFixedRate(loopTask, 0, interval);
}
public void removeLoop(int index) {
TimerTask loopTask = loopTasks.remove(index);
if (loopTask != null) {
loopTask.cancel();
}
loops.remove(index);
}
public void clearLoops() {
for (TimerTask loopTask : loopTasks) {
loopTask.cancel();
}
loopTasks.clear();
loops.clear();
}
}