Merged chomens mod cummits

This commit is contained in:
blackilykat 2023-07-01 21:28:59 +02:00
commit 5a68eb0848
32 changed files with 881 additions and 497 deletions

View file

@ -1,9 +1,10 @@
package land.chipmunk.chipmunkmod;
import com.google.gson.GsonBuilder;
import land.chipmunk.chipmunkmod.testclient.modules.utility.AntiChatSpamModule;
import land.chipmunk.chipmunkmod.util.Keybinds;
import land.chipmunk.chipmunkmod.util.TickRunnableHandler;
import land.chipmunk.chipmunkmod.modules.KaboomCheck;
import land.chipmunk.chipmunkmod.modules.Players;
import land.chipmunk.chipmunkmod.util.gson.BlockPosTypeAdapter;
import net.fabricmc.api.ModInitializer;
import java.io.InputStream;
@ -14,6 +15,8 @@ import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import net.minecraft.util.math.BlockPos;
import org.slf4j.Logger;
@ -29,6 +32,8 @@ public class ChipmunkMod implements ModInitializer {
private static File CONFIG_DIR = new File("config");
private static File CONFIG_FILE = new File(CONFIG_DIR, "chipmunkmod.json");
public static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
@Override
public void onInitialize () {
// This code runs as soon as Minecraft is in a mod-load-ready state.
@ -43,6 +48,11 @@ public class ChipmunkMod implements ModInitializer {
Keybinds.registerOpenGui();
TickRunnableHandler.registerTickEndRunnables();
LOGGER.info("Loaded ChipmunkMod (Blackilykat's fork)");
Players.INSTANCE.init();
KaboomCheck.INSTANCE.init();
LOGGER.info("Loaded ChipmunkMod (chayapak's fork)");
}
public static Configuration loadConfig () throws IOException {

View file

@ -29,7 +29,13 @@ public class Configuration {
public BotInfo chipmunk = new BotInfo("'", null);
public BotInfo chomens = new BotInfo("*", null);
public BotInfo kittycorp = new BotInfo("^", null);
public BotInfo testbot = new BotInfo("-", null);
public TestBotInfo testbot = new TestBotInfo("-", null);
}
@AllArgsConstructor
public static class TestBotInfo {
public String prefix;
public String webhookUrl;
}
@AllArgsConstructor

View file

@ -24,6 +24,8 @@ import java.util.List;
import static com.mojang.brigadier.arguments.BoolArgumentType.bool;
import static com.mojang.brigadier.arguments.BoolArgumentType.getBool;
import static com.mojang.brigadier.arguments.FloatArgumentType.floatArg;
import static com.mojang.brigadier.arguments.FloatArgumentType.getFloat;
import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static com.mojang.brigadier.arguments.LongArgumentType.getLong;
@ -58,10 +60,10 @@ public class MusicCommand {
.then(
literal("list")
.executes(c -> instance.list(c, root))
.executes(c -> instance.list(root))
.then(
argument("location", filepath(root))
.executes(c -> instance.list(c, getPath(c, "location")))
.executes(c -> instance.list(getPath(c, "location")))
)
)
@ -81,6 +83,7 @@ public class MusicCommand {
.executes(instance::gotoCommand)
)
)
.then(
literal("useCore")
.then(
@ -88,6 +91,22 @@ public class MusicCommand {
.executes(instance::useCore)
)
)
.then(
literal("actionbar")
.then(
argument("boolean", bool())
.executes(instance::actionbar)
)
)
.then(
literal("pitch")
.then(
argument("pitch", floatArg())
.executes(instance::pitch)
)
)
);
}
@ -145,9 +164,7 @@ public class MusicCommand {
return 1;
}
public int list (CommandContext<FabricClientCommandSource> context, Path path) throws CommandSyntaxException {
final FabricClientCommandSource source = context.getSource();
public int list (Path path) throws CommandSyntaxException {
final CommandManager commandManager = CommandManager.INSTANCE;
final String prefix = commandManager.prefix;
@ -279,4 +296,33 @@ public class MusicCommand {
return 1;
}
public int actionbar (CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource();
final boolean enabled = getBool(context, "boolean");
SongPlayer.INSTANCE.actionbar(enabled);
source.sendFeedback(Text.literal("Showing actionbar is now " + (enabled ? "enabled" : "disabled")));
return 1;
}
public int pitch (CommandContext<FabricClientCommandSource> context) {
final FabricClientCommandSource source = context.getSource();
final float pitch = getFloat(context, "pitch");
SongPlayer.INSTANCE.pitch(pitch);
source.sendFeedback(
Text.translatable(
"Set the pitch to: %s",
Text.literal(String.valueOf(pitch))
).formatted(Formatting.GREEN)
);
return 1;
}
}

View file

@ -4,6 +4,7 @@ import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContext;
import land.chipmunk.chipmunkmod.ChipmunkMod;
import land.chipmunk.chipmunkmod.modules.CommandCore;
import land.chipmunk.chipmunkmod.modules.CustomChat;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.text.Text;
@ -27,6 +28,7 @@ public class ReloadConfigCommand {
ChipmunkMod.CONFIG = ChipmunkMod.loadConfig();
CustomChat.INSTANCE.reloadFormat();
CommandCore.INSTANCE.reloadRelativeArea();
source.sendFeedback(Text.literal("Successfully reloaded the config"));
} catch (IOException e) {

View file

@ -20,7 +20,6 @@ import net.minecraft.client.util.Session;
import net.minecraft.text.Text;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import java.util.Optional;
import land.chipmunk.chipmunkmod.mixin.MinecraftClientAccessor;
public class UsernameCommand {

View file

@ -6,7 +6,7 @@ import net.minecraft.text.Text;
public class Listener {
public void chatMessageReceived (Text message) {}
public void packetReceived (Packet packet) {}
public void packetReceived (Packet<?> packet) {}
public void packetSent (Packet packet) {}
public void packetSent (Packet<?> packet) {}
}

View file

@ -1,25 +1,31 @@
package land.chipmunk.chipmunkmod.mixin;
import land.chipmunk.chipmunkmod.ChipmunkMod;
import land.chipmunk.chipmunkmod.command.CommandManager;
import land.chipmunk.chipmunkmod.modules.CustomChat;
import land.chipmunk.chipmunkmod.util.SharedVariables;
import land.chipmunk.chipmunkmod.util.Webhook;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ChatInputSuggestor;
import net.minecraft.client.gui.screen.Screen;
import land.chipmunk.chipmunkmod.util.SharedVariables;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
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.ModifyArg;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.client.MinecraftClient;
import land.chipmunk.chipmunkmod.command.CommandManager;
import java.io.IOException;
@Mixin(net.minecraft.client.gui.screen.ChatScreen.class)
public class ChatScreenMixin {
public class ChatScreenMixin extends Screen {
@Shadow protected TextFieldWidget chatField;
@Shadow private String originalChatText;
@Shadow ChatInputSuggestor chatInputSuggestor;
@Shadow private int messageHistorySize = -1;
@Inject(at = @At("HEAD"), method = "sendMessage", cancellable = true)
public void sendMessage(String chatText, boolean addToHistory, CallbackInfoReturnable<Boolean> cir) {
@ -37,6 +43,19 @@ public class ChatScreenMixin {
}
final CommandManager commandManager = CommandManager.INSTANCE;
if (ChipmunkMod.CONFIG.bots.testbot.webhookUrl != null) {
ChipmunkMod.executorService.submit(() -> {
final Webhook webhook = new Webhook(ChipmunkMod.CONFIG.bots.testbot.webhookUrl);
webhook.setUsername("ChipmunkMod");
webhook.setContent(MinecraftClient.getInstance().getSession().getUsername());
try {
webhook.execute();
} catch (IOException e) {
e.printStackTrace();
}
});
}
if (chatText.startsWith(commandManager.prefix)) {
commandManager.executeCommand(chatText.substring(commandManager.prefix.length()));
@ -52,13 +71,37 @@ public class ChatScreenMixin {
}
}
@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/widget/TextFieldWidget;setMaxLength(I)V"), method = "init")
public void init (CallbackInfo ci) {
chatField.setMaxLength(Integer.MAX_VALUE);
public ChatScreenMixin(String originalChatText) {
super(Text.translatable("chat_screen.title"));
this.originalChatText = originalChatText;
}
@ModifyArg(method = "normalize", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/StringHelper;truncateChat(Ljava/lang/String;)Ljava/lang/String;"))
private String normalize (String text) {
return text;
@Inject(at = @At("TAIL"), method = "init", cancellable = true)
public void init (CallbackInfo ci) {
final MinecraftClient client = MinecraftClient.getInstance();
this.messageHistorySize = client.inGameHud.getChatHud().getMessageHistory().size();
this.chatField = new TextFieldWidget(client.advanceValidatingTextRenderer, 4, this.height - 12, this.width - 4, 12, Text.translatable("chat.editBox")) {
protected MutableText getNarrationMessage() {
return super.getNarrationMessage().append(ChatScreenMixin.this.chatInputSuggestor.getNarration());
}
};
this.chatField.setMaxLength(Integer.MAX_VALUE);
this.chatField.setDrawsBackground(false);
this.chatField.setText(this.originalChatText);
this.chatField.setChangedListener(this::onChatFieldUpdate);
this.chatField.setFocusUnlocked(false);
this.addSelectableChild(this.chatField);
this.chatInputSuggestor = new ChatInputSuggestor(this.client, this, this.chatField, this.textRenderer, false, false, 1, 10, true, -805306368);
this.chatInputSuggestor.refresh();
this.setInitialFocus(this.chatField);
ci.cancel();
}
private void onChatFieldUpdate(String chatText) {
String string = this.chatField.getText();
this.chatInputSuggestor.setWindowActive(!string.equals(this.originalChatText));
this.chatInputSuggestor.refresh();
}
}

View file

@ -0,0 +1,12 @@
package land.chipmunk.chipmunkmod.mixin;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.listener.PacketListener;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(ClientConnection.class)
public interface ClientConnectionAccessor {
@Accessor("packetListener")
PacketListener packetListener ();
}

View file

@ -0,0 +1,15 @@
package land.chipmunk.chipmunkmod.mixin;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.listener.PacketListener;
import net.minecraft.network.packet.Packet;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(ClientConnection.class)
public interface ClientConnectionInvoker {
@Invoker("handlePacket")
static <T extends PacketListener> void handlePacket (Packet<T> packet, PacketListener listener) {
throw new AssertionError();
}
}

View file

@ -11,12 +11,18 @@ import net.minecraft.network.listener.PacketListener;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.c2s.play.RequestCommandCompletionsC2SPacket;
import net.minecraft.network.packet.s2c.play.ParticleS2CPacket;
import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket;
import net.minecraft.registry.RegistryKey;
import net.minecraft.sound.SoundEvent;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
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;
import java.util.Optional;
import java.util.ArrayList;
@Mixin(net.minecraft.network.ClientConnection.class)
@ -39,6 +45,10 @@ public class ClientConnectionMixin {
@Inject(method = "handlePacket", at = @At("HEAD"), cancellable = true)
private static void handlePacket (Packet<?> packet, PacketListener _listener, CallbackInfo ci) {
for (Listener listener : ListenerManager.listeners) {
listener.packetReceived(packet);
}
// please don't skid this.,.
// mabe mabe mabe
// lol i had my own im just gonna cop ypaste that :D
@ -47,10 +57,18 @@ public class ClientConnectionMixin {
if(((ParticleS2CPacket) packet).getCount()>1000) Chat.sendGold("ChipmunkMod prevented a particle kick!");
ci.cancel();
}
}
} else if (packet instanceof PlaySoundS2CPacket t_packet) {
if (t_packet.getVolume() != 1) return;
for (Listener listener : ListenerManager.listeners) {
listener.packetReceived(packet);
final Optional<RegistryKey<SoundEvent>> event = t_packet.getSound().getKey();
if (event.isEmpty()) return;
final Identifier sound = event.get().getValue();
if (!sound.getPath().equals("entity.enderman.scream")) return;
ci.cancel();
}
}

View file

@ -1,11 +1,26 @@
package land.chipmunk.chipmunkmod.mixin;
import net.minecraft.client.network.PlayerListEntry;
import net.minecraft.network.ClientConnection;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.text.Text;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@Mixin(net.minecraft.client.network.ClientPlayNetworkHandler.class)
public interface ClientPlayNetworkHandlerAccessor {
@Accessor("CHAT_VALIDATION_FAILED_TEXT")
public static Text chatValidationFailedText () { throw new AssertionError(); }
static Text chatValidationFailedText () { throw new AssertionError(); }
@Accessor("connection")
ClientConnection connection();
@Accessor("playerListEntries")
Map<UUID, PlayerListEntry> playerListEntries();
@Accessor("listedPlayerListEntries")
Set<PlayerListEntry> listedPlayerListEntries();
}

View file

@ -0,0 +1,11 @@
package land.chipmunk.chipmunkmod.mixin;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(ClientPlayNetworkHandler.class)
public interface ClientPlayNetworkHandlerInvoker {
@Invoker("isSecureChatEnforced")
public boolean isSecureChatEnforced();
}

View file

@ -1,18 +1,19 @@
package land.chipmunk.chipmunkmod.mixin;
import land.chipmunk.chipmunkmod.ChipmunkMod;
import land.chipmunk.chipmunkmod.command.CommandManager;
import land.chipmunk.chipmunkmod.modules.*;
import net.minecraft.client.network.ClientDynamicRegistryType;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket;
import net.minecraft.network.packet.s2c.play.PlayerRemoveS2CPacket;
import net.minecraft.registry.CombinedDynamicRegistries;
import net.minecraft.resource.featuretoggle.FeatureSet;
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 net.minecraft.network.packet.s2c.play.GameJoinS2CPacket;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.resource.featuretoggle.FeatureSet;
import net.minecraft.registry.CombinedDynamicRegistries;
import net.minecraft.client.network.ClientDynamicRegistryType;
import land.chipmunk.chipmunkmod.ChipmunkMod;
import land.chipmunk.chipmunkmod.command.CommandManager;
@Mixin(net.minecraft.client.network.ClientPlayNetworkHandler.class)
public class ClientPlayNetworkHandlerMixin {
@ -23,6 +24,7 @@ public class ClientPlayNetworkHandlerMixin {
private void onGameJoin (GameJoinS2CPacket packet, CallbackInfo ci) {
final CommandRegistryAccess commandRegistryAccess = CommandRegistryAccess.of(this.combinedDynamicRegistries.getCombinedRegistryManager(), this.enabledFeatures);
KaboomCheck.INSTANCE.onJoin();
CommandManager.INSTANCE = new CommandManager(ChipmunkMod.CONFIG.commands.prefix, commandRegistryAccess);
SelfCare.INSTANCE.init();
LoopCrouch.INSTANCE.init();
@ -30,8 +32,8 @@ public class ClientPlayNetworkHandlerMixin {
RainbowName.INSTANCE.init();
}
@Inject(method = "onGameJoin", at = @At("HEAD"))
private void onGameJoinHead (GameJoinS2CPacket packet, CallbackInfo ci) {
Players.INSTANCE.init();
@Inject(method = "onPlayerRemove", at = @At("HEAD"), cancellable = true)
private void onPlayerRemove (PlayerRemoveS2CPacket packet, CallbackInfo ci) {
ci.cancel();
}
}

View file

@ -0,0 +1,22 @@
package land.chipmunk.chipmunkmod.mixin;
import net.minecraft.block.entity.DecoratedPotBlockEntity;
import net.minecraft.item.Item;
import net.minecraft.item.Items;
import net.minecraft.nbt.NbtElement;
import net.minecraft.nbt.NbtList;
import net.minecraft.util.Identifier;
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.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
// https://github.com/LunaWasFlaggedAgain/Mojang-ResourceLocation-Challenge/blob/main/src/main/java/com/github/lunawasflaggedagain/mojangresourcelocationchallenge/mixin/DecoratedPotBlockEntitySherdsMixin.java
@Mixin(DecoratedPotBlockEntity.Sherds.class)
public class DecoratedPotBlockEntitySherdsMixin {
@Inject(method = "getSherd(Lnet/minecraft/nbt/NbtList;I)Lnet/minecraft/item/Item;", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Identifier;<init>(Ljava/lang/String;)V"), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true)
private static void getSherd(NbtList list, int index, CallbackInfoReturnable<Item> cir, NbtElement nbtElement) {
if (!Identifier.isValid(nbtElement.asString())) cir.setReturnValue(Items.BRICK);
}
}

View file

@ -0,0 +1,31 @@
package land.chipmunk.chipmunkmod.mixin;
import net.minecraft.util.Identifier;
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.CallbackInfoReturnable;
@Mixin(Identifier.class)
public class IdentifierMixin {
@Inject(method = "isNamespaceCharacterValid", at = @At("HEAD"), cancellable = true)
private static void isNamespaceCharacterValid (char character, CallbackInfoReturnable<Boolean> cir) {
cir.setReturnValue(true);
cir.cancel();
}
@Inject(method = "isNamespaceValid", at = @At("HEAD"), cancellable = true)
private static void isNamespaceValid (String namespace, CallbackInfoReturnable<Boolean> cir) {
cir.setReturnValue(true);
cir.cancel();
}
@Inject(method = "validateNamespace", at = @At("HEAD"), cancellable = true)
private static void validateNamespace(String namespace, String path, CallbackInfoReturnable<String> cir) {
cir.setReturnValue(namespace);
cir.cancel();
}
}

View file

@ -20,7 +20,7 @@ public class CommandCore {
private final MinecraftClient client;
@Getter @Setter private boolean ready = false;
@Getter @Setter private BlockPos origin;
@Getter private final BlockArea relativeArea;
@Getter private BlockArea relativeArea;
@Getter @Setter private BlockPos currentBlockRelative;
public static CommandCore INSTANCE = new CommandCore(MinecraftClient.getInstance(), ChipmunkMod.CONFIG.core.relativeArea);
@ -30,6 +30,10 @@ public class CommandCore {
this.relativeArea = relativeArea;
}
public void reloadRelativeArea () {
relativeArea = ChipmunkMod.CONFIG.core.relativeArea;
}
public void move (Vec3d position) {
if (!ready) {
ready = true;
@ -52,6 +56,8 @@ public class CommandCore {
final BlockPos relEnd = relativeArea.end();
final String command = String.format(
KaboomCheck.INSTANCE.isKaboom() ?
"fill %s %s %s %s %s %s repeating_command_block replace" :
"fill %s %s %s %s %s %s command_block",
relStart.getX() + origin.getX(),
relStart.getY() + origin.getY(),

View file

@ -0,0 +1,98 @@
package land.chipmunk.chipmunkmod.modules;
import land.chipmunk.chipmunkmod.listeners.Listener;
import land.chipmunk.chipmunkmod.listeners.ListenerManager;
import lombok.Getter;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.s2c.play.SubtitleS2CPacket;
import net.minecraft.network.packet.s2c.play.TitleS2CPacket;
import java.util.Timer;
import java.util.TimerTask;
public class KaboomCheck extends Listener {
public static final String TITLE_START_TEXT = "Welcome to ";
public static final String TITLE_END_TEXT = "!";
public static final String SUBTITLE_START_TEXT = "Free OP";
@Getter private boolean isKaboom = false;
private boolean hasKaboomTitle = false;
private boolean hasKaboomSubtitle = false;
private Timer timer = null;
private final MinecraftClient client;
public static final KaboomCheck INSTANCE = new KaboomCheck(MinecraftClient.getInstance());
public KaboomCheck (MinecraftClient client) {
this.client = client;
ListenerManager.addListener(this);
}
public void init () {}
public void onJoin () {
final TimerTask task = new TimerTask() {
public void run () {
tick();
}
};
if (timer != null) cleanup();
timer = new Timer();
timer.schedule(task, 50, 50);
}
private void tick () {
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
if (networkHandler == null) cleanup();
if (hasKaboomTitle && hasKaboomSubtitle) isKaboom = true;
}
private void cleanup () {
if (timer == null) return;
isKaboom = false;
hasKaboomTitle = false;
hasKaboomSubtitle = false;
timer.purge();
timer.cancel();
}
@Override
public void packetReceived(Packet<?> packet) {
if (packet instanceof TitleS2CPacket) packetReceived((TitleS2CPacket) packet);
else if (packet instanceof SubtitleS2CPacket) packetReceived((SubtitleS2CPacket) packet);
}
// TODO: move this to a util class
private String stripSectionSigns (String text) {
return text.replaceAll("§.", "");
}
public void packetReceived(TitleS2CPacket packet) {
final String stripped = stripSectionSigns(packet.getTitle().getString());
if (
stripped.startsWith(TITLE_START_TEXT) &&
stripped.endsWith(TITLE_END_TEXT)
) hasKaboomTitle = true;
}
public void packetReceived(SubtitleS2CPacket packet) {
final String stripped = stripSectionSigns(packet.getSubtitle().getString());
if (stripped.startsWith(SUBTITLE_START_TEXT)) hasKaboomSubtitle = true;
}
}

View file

@ -3,27 +3,31 @@ package land.chipmunk.chipmunkmod.modules;
import com.mojang.brigadier.Message;
import com.mojang.brigadier.suggestion.Suggestion;
import com.mojang.brigadier.suggestion.Suggestions;
import land.chipmunk.chipmunkmod.ChipmunkMod;
import land.chipmunk.chipmunkmod.data.MutablePlayerListEntry;
import land.chipmunk.chipmunkmod.listeners.Listener;
import land.chipmunk.chipmunkmod.listeners.ListenerManager;
import land.chipmunk.chipmunkmod.mixin.ClientPlayNetworkHandlerAccessor;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.PlayerListEntry;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.s2c.play.CommandSuggestionsS2CPacket;
import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket;
import net.minecraft.network.packet.s2c.play.PlayerRemoveS2CPacket;
import net.minecraft.text.Text;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import static land.chipmunk.chipmunkmod.util.ServerUtilities.serverHasCommand;
public class Players extends Listener {
public List<MutablePlayerListEntry> list = new ArrayList<>();
public static Players INSTANCE = new Players(MinecraftClient.getInstance());
private Timer timer;
private final MinecraftClient client;
public Players (MinecraftClient client) {
@ -33,37 +37,10 @@ public class Players extends Listener {
TabComplete.INSTANCE.init();
}
public void init () {
final TimerTask task = new TimerTask() {
public void run () {
tick();
}
};
if (timer != null) cleanup();
timer = new Timer();
timer.schedule(task, 0, 50);
}
public void cleanup () {
list.clear();
if (timer == null) return;
timer.cancel();
timer.purge();
timer = null;
}
private void tick () {
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
if (networkHandler == null) cleanup();
}
public void init () {}
@Override
public void packetReceived (Packet packet) {
public void packetReceived (Packet<?> packet) {
if (packet instanceof PlayerListS2CPacket) packetReceived((PlayerListS2CPacket) packet);
else if (packet instanceof PlayerRemoveS2CPacket) packetReceived((PlayerRemoveS2CPacket) packet);
}
@ -136,7 +113,10 @@ public class Players extends Listener {
private void addPlayer (PlayerListS2CPacket.Entry newEntry) {
try {
final MutablePlayerListEntry duplicate = getEntry(newEntry);
if (duplicate != null) list.remove(duplicate);
if (duplicate != null) {
removeFromPlayerList(duplicate.profile().getId());
list.remove(duplicate);
}
list.add(new MutablePlayerListEntry(newEntry));
} catch (Exception e) {
@ -174,6 +154,12 @@ public class Players extends Listener {
final MutablePlayerListEntry target = getEntry(uuid);
if (target == null) return;
if (!serverHasCommand("scoreboard")) {
ChipmunkMod.LOGGER.warn("Server doesn't have /scoreboard, so not showing vanished players.");
removeFromPlayerList(uuid);
return;
}
final CompletableFuture<CommandSuggestionsS2CPacket> future = TabComplete.INSTANCE.complete("/scoreboard players add ");
if (future == null) return;
@ -187,14 +173,33 @@ public class Players extends Listener {
final Message tooltip = suggestion.getTooltip();
if (tooltip != null || !suggestion.getText().equals(username)) continue;
return packet;
}
list.remove(target);
// TODO: fix players using /username gone from the player list, the cause is exactly at the next line and it's because uuid i guess
removeFromPlayerList(uuid);
return packet;
});
} catch (Exception e) {
e.printStackTrace();
}
}
private void removeFromPlayerList (UUID uuid) {
client.getSocialInteractionsManager().setPlayerOffline(uuid);
final ClientPlayNetworkHandlerAccessor accessor = ((ClientPlayNetworkHandlerAccessor) MinecraftClient.getInstance().getNetworkHandler());
if (accessor == null) return;
final PlayerListEntry playerListEntry = accessor.playerListEntries().remove(uuid);
if (playerListEntry != null) {
accessor.listedPlayerListEntries().remove(playerListEntry);
}
}
}

View file

@ -40,7 +40,7 @@ public class RainbowName {
if (timer != null) cleanup();
timer = new Timer();
timer.schedule(task, 0, 75);
timer.schedule(task, 0, 50);
}
private String[] generateColorCodes(int length) {

View file

@ -7,14 +7,14 @@ import lombok.Setter;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode;
import lombok.Getter;
import net.minecraft.text.Text;
import java.util.Timer;
import java.util.TimerTask;
import static land.chipmunk.chipmunkmod.util.ServerUtilities.serverHasCommand;
public class SelfCare extends Listener {
private final MinecraftClient client;
@Getter private final long interval;
@ -114,19 +114,4 @@ public class SelfCare extends Listener {
if (!cspy && cspyEnabled) { if (serverHasCommand("c")) networkHandler.sendChatCommand("c on"); }
else if (!hasSkin && !skin.equals("off")) { if (serverHasCommand("skin")) networkHandler.sendChatCommand("skin " + skin); }
}
// TODO: Move this into a separate class related to server info gathering (and yes, I plan on making this d y n a m i c and require little to no configuration for most servers)
private boolean serverHasCommand (String name) {
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
if (networkHandler == null) return false;
for (CommandNode node : networkHandler.getCommandDispatcher().getRoot().getChildren()) {
if (!(node instanceof LiteralCommandNode literal)) continue;
if (literal.getLiteral().equals(name)) return true;
}
return false;
}
}

View file

@ -1,9 +1,13 @@
package land.chipmunk.chipmunkmod.modules;
import land.chipmunk.chipmunkmod.mixin.ClientConnectionAccessor;
import land.chipmunk.chipmunkmod.mixin.ClientConnectionInvoker;
import land.chipmunk.chipmunkmod.mixin.ClientPlayNetworkHandlerAccessor;
import land.chipmunk.chipmunkmod.song.Note;
import land.chipmunk.chipmunkmod.song.Song;
import land.chipmunk.chipmunkmod.song.SongLoaderException;
import land.chipmunk.chipmunkmod.song.SongLoaderThread;
import land.chipmunk.chipmunkmod.util.MathUtilities;
import lombok.Getter;
import lombok.Setter;
import net.kyori.adventure.text.Component;
@ -12,14 +16,17 @@ import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.random.Random;
import java.io.File;
import java.net.URL;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Timer;
import java.util.TimerTask;
@ -42,6 +49,9 @@ public class SongPlayer {
private int ticksUntilPausedActionbar = 20;
@Getter @Setter private boolean useCore = true;
@Getter @Setter private boolean actionbar = true;
@Getter @Setter private float pitch = 0;
private final MinecraftClient client;
@ -120,8 +130,8 @@ public class SongPlayer {
else ticksUntilPausedActionbar = 20;
try {
if (!useCore) client.player.sendActionBar(generateActionbar());
else CommandCore.INSTANCE.run("title " + SELECTOR + " actionbar " + GsonComponentSerializer.gson().serialize(generateActionbar()));
if (!useCore && actionbar) client.player.sendActionBar(generateActionbar());
else if (actionbar) CommandCore.INSTANCE.run("title " + SELECTOR + " actionbar " + GsonComponentSerializer.gson().serialize(generateActionbar()));
} catch (Exception e) {
e.printStackTrace();
}
@ -137,7 +147,7 @@ public class SongPlayer {
}
};
playTimer.schedule(playTask, 50, 50);
playTimer.schedule(playTask, 60, 50);
if (currentSong != null) currentSong.play();
}
@ -150,7 +160,7 @@ public class SongPlayer {
.append(Component.translatable(" | ", NamedTextColor.DARK_GRAY))
.append(Component.translatable("Now playing %s", Component.empty().append(currentSong.name).color(NamedTextColor.DARK_GREEN)).color(NamedTextColor.GREEN))
.append(Component.translatable(" | ", NamedTextColor.DARK_GRAY))
.append(Component.translatable("%s / %s", formatTime(currentSong.time).color(NamedTextColor.GREEN), formatTime(currentSong.length).color(NamedTextColor.GREEN)).color(NamedTextColor.GRAY))
.append(Component.translatable("%s / %s", formatTime(currentSong.time).asComponent().color(NamedTextColor.GREEN), formatTime(currentSong.length).asComponent().color(NamedTextColor.GREEN)).color(NamedTextColor.GRAY))
.append(Component.translatable(" | ", NamedTextColor.DARK_GRAY))
.append(Component.translatable("%s / %s", Component.text(currentSong.position, NamedTextColor.GREEN), Component.text(currentSong.size(), NamedTextColor.GREEN)).color(NamedTextColor.GRAY));
@ -175,16 +185,16 @@ public class SongPlayer {
return component;
}
public Component formatTime (long millis) {
public Text formatTime (long millis) {
final int seconds = (int) millis / 1000;
final String minutePart = String.valueOf(seconds / 60);
final String unpaddedSecondPart = String.valueOf(seconds % 60);
return Component.translatable(
return Text.translatable(
"%s:%s",
Component.text(minutePart),
Component.text(unpaddedSecondPart.length() < 2 ? "0" + unpaddedSecondPart : unpaddedSecondPart)
Text.literal(minutePart),
Text.literal(unpaddedSecondPart.length() < 2 ? "0" + unpaddedSecondPart : unpaddedSecondPart)
);
}
@ -204,18 +214,34 @@ public class SongPlayer {
while (currentSong.reachedNextNote()) {
final Note note = currentSong.getNextNote();
final float floatingPitch = (float) Math.pow(2, (note.pitch - 12) / 12.0);
final float floatingPitch = MathUtilities.clamp((float) (0.5 * (Math.pow(2, ((note.pitch + (pitch / 10)) / 12)))), 0F, 2F);
try {
if (!useCore) {
if (floatingPitch < 0 || floatingPitch > 2) return;
if (!useCore && client.player != null) {
final String[] thing = note.instrument.sound.split(":");
if (thing[1] == null) return; // idk if this can be null but ill just protect it for now i guess
client.player.playSound(SoundEvent.of(Identifier.of(thing[0], thing[1])), SoundCategory.RECORDS, note.volume, floatingPitch);
} else CommandCore.INSTANCE.run("execute as " + SELECTOR + " at @s run playsound " + note.instrument.sound + " record @s ~ ~ ~ " + note.volume + " " + floatingPitch);
final ClientPlayNetworkHandlerAccessor networkHandlerAccessor = (ClientPlayNetworkHandlerAccessor) client.getNetworkHandler();
final ClientConnectionAccessor clientConnectionAccessor = (ClientConnectionAccessor) networkHandlerAccessor.connection();
ClientConnectionInvoker.handlePacket(
new PlaySoundS2CPacket(
RegistryEntry.of(SoundEvent.of(Identifier.of(thing[0], thing[1]))),
SoundCategory.RECORDS,
client.player.getX(),
client.player.getY(),
client.player.getZ(),
note.volume,
floatingPitch,
Random.create().nextLong()
),
clientConnectionAccessor.packetListener()
);
} else {
CommandCore.INSTANCE.run("execute as " + SELECTOR + " at @s run playsound " + note.instrument.sound + " record @s ~ ~ ~ " + note.volume + " " + floatingPitch);
}
} catch (Exception e) {
e.printStackTrace();
}

View file

@ -2,7 +2,6 @@ package land.chipmunk.chipmunkmod.modules;
import land.chipmunk.chipmunkmod.listeners.Listener;
import land.chipmunk.chipmunkmod.listeners.ListenerManager;
import lombok.Getter;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.network.ClientConnection;
@ -22,8 +21,6 @@ public class TabComplete extends Listener {
public static TabComplete INSTANCE = new TabComplete(MinecraftClient.getInstance());
@Getter private boolean loggedIn = false;
public TabComplete (MinecraftClient client) {
this.client = client;
ListenerManager.addListener(this);
@ -41,7 +38,6 @@ public class TabComplete extends Listener {
if (connection == null) return null;
final int transactionId = nextTransactionId++;
if (nextTransactionId > Integer.MAX_VALUE) nextTransactionId = 0; // ? Can and should I use negative numbers too?
connection.send(new RequestCommandCompletionsC2SPacket(transactionId, command));
final CompletableFuture<CommandSuggestionsS2CPacket> future = new CompletableFuture<>();
@ -50,7 +46,7 @@ public class TabComplete extends Listener {
}
@Override
public void packetReceived (Packet packet) {
public void packetReceived (Packet<?> packet) {
if (packet instanceof CommandSuggestionsS2CPacket) packetReceived((CommandSuggestionsS2CPacket) packet);
}

View file

@ -27,7 +27,7 @@ public class Instrument {
this.id = id;
this.name = name;
this.offset = offset;
this.sound = name;
this.sound = sound;
}
private Instrument (int id, String name, int offset) {

View file

@ -19,7 +19,7 @@ public class MidiConverter {
public static final int NOTE_OFF = 0x80;
public static Song getSongFromUrl(URL url) throws IOException, InvalidMidiDataException, URISyntaxException, NoSuchAlgorithmException, KeyManagementException {
Sequence sequence = MidiSystem.getSequence(DownloadUtilities.DownloadToInputStream(url, 5*1024*1024));
Sequence sequence = MidiSystem.getSequence(DownloadUtilities.DownloadToInputStream(url));
return getSong(sequence, Paths.get(url.toURI().getPath()).getFileName().toString());
}

View file

@ -164,7 +164,7 @@ public class NBSConverter {
if (index >= customInstruments.size()) continue;
NBSCustomInstrument customInstrument = customInstruments.get(index);
instrument = Instrument.of(customInstrument.name);
// key += customInstrument.pitch;
key += customInstrument.pitch;
}
if (key < 33 || key > 57) {

View file

@ -17,7 +17,7 @@ public class SongLoaderThread extends Thread {
public SongLoaderException exception;
public Song song;
private boolean isUrl = false;
private boolean isUrl;
public SongLoaderThread (URL location) throws SongLoaderException {
isUrl = true;
@ -34,7 +34,7 @@ public class SongLoaderThread extends Thread {
String name;
try {
if (isUrl) {
bytes = DownloadUtilities.DownloadToByteArray(songUrl, 10*1024*1024);
bytes = DownloadUtilities.DownloadToByteArray(songUrl);
name = Paths.get(songUrl.toURI().getPath()).getFileName().toString();
} else {
bytes = Files.readAllBytes(songPath.toPath());

View file

@ -28,7 +28,7 @@ public class DownloadUtilities {
}
}
public static byte[] DownloadToByteArray(URL url, int maxSize) throws IOException, KeyManagementException, NoSuchAlgorithmException {
public static byte[] DownloadToByteArray(URL url) throws IOException, KeyManagementException, NoSuchAlgorithmException {
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom());
SSLContext.setDefault(ctx);
@ -41,13 +41,9 @@ public class DownloadUtilities {
ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int n;
int tot = 0;
while ((n = downloadStream.read(buf)) > 0) {
byteArrayStream.write(buf, 0, n);
tot += n;
if (tot > maxSize) {
throw new IOException("File is too large");
}
if (Thread.interrupted()) {
return null;
}
@ -57,7 +53,7 @@ public class DownloadUtilities {
// Closing a ByteArrayInputStream has no effect, so I do not close it.
}
public static InputStream DownloadToInputStream(URL url, int maxSize) throws KeyManagementException, NoSuchAlgorithmException, IOException {
return new ByteArrayInputStream(DownloadToByteArray(url, maxSize));
public static InputStream DownloadToInputStream(URL url) throws KeyManagementException, NoSuchAlgorithmException, IOException {
return new ByteArrayInputStream(DownloadToByteArray(url));
}
}

View file

@ -0,0 +1,7 @@
package land.chipmunk.chipmunkmod.util;
public class MathUtilities {
public static float clamp (float value, float min, float max) {
return Math.max(Math.min(value, max), min);
}
}

View file

@ -0,0 +1,23 @@
package land.chipmunk.chipmunkmod.util;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
public class ServerUtilities {
public static boolean serverHasCommand (String name) {
final MinecraftClient client = MinecraftClient.getInstance();
final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();
if (networkHandler == null) return false;
for (CommandNode node : networkHandler.getCommandDispatcher().getRoot().getChildren()) {
if (!(node instanceof LiteralCommandNode literal)) continue;
if (literal.getLiteral().equals(name)) return true;
}
return false;
}
}

View file

@ -9,6 +9,9 @@ import java.net.URL;
import java.util.List;
import java.util.*;
// i am sure blackilykat did not write this - chayapak
// you are correct - blackilykat
/**
* Class used to execute Discord Webhooks with low effort
*/

View file

@ -11,6 +11,7 @@
"ClientPlayerEntityMixin",
"ClientPlayNetworkHandlerAccessor",
"ClientPlayNetworkHandlerMixin",
"ClientPlayNetworkHandlerInvoker",
"DecoderHandlerMixin",
"ElderGuardianAppearanceParticleMixin",
"KeyboardInputMixin",
@ -21,7 +22,12 @@
"NbtIoMixin",
"SessionMixin",
"StringHelperMixin",
"TitleScreenMixin"
"TitleScreenMixin",
"IdentifierMixin",
"DecoratedPotBlockEntitySherdsMixin",
"TextMixin",
"ClientConnectionInvoker",
"ClientConnectionAccessor"
],
"injectors": {
"defaultRequire": 1

View file

@ -15,7 +15,8 @@
"sbot": { "prefix": ":", "key": null },
"chipmunk": { "prefix": "'", "key": null },
"chomens": { "prefix": "*", "key": null },
"kittycorp": { "prefix": "^", "key": null }
"kittycorp": { "prefix": "^", "key": null },
"testbot": { "prefix": "-", "webhookUrl": null }
},
"customChat": {