diff --git a/gradle.properties b/gradle.properties index 1492971..5519133 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ yarn_mappings=1.21.4+build.8 loader_version=0.16.14 # Mod Properties -mod_version=0.7.0 +mod_version=0.7.2 maven_group=com.genyo archives_base_name=genyo-addon diff --git a/src/main/java/com/genyo/addon/GenyoAddon.java b/src/main/java/com/genyo/addon/GenyoAddon.java index 64994ec..3a9fdb5 100644 --- a/src/main/java/com/genyo/addon/GenyoAddon.java +++ b/src/main/java/com/genyo/addon/GenyoAddon.java @@ -3,6 +3,7 @@ import com.genyo.addon.modules.AngelSexHulkenberg; import com.genyo.addon.modules.GenyoAutoEZ; import com.genyo.addon.modules.GenyoSurround; +import com.genyo.addon.modules.GenyoWelcome; import com.genyo.addon.systems.enemies.EnemiesTab; import com.genyo.addon.hud.InCombatHud; import com.genyo.addon.hud.PvPNeccessaryHud; @@ -61,6 +62,7 @@ private void initModules(Modules modules) { modules.add(new GenyoAutoEZ()); modules.add(new AngelSexHulkenberg()); modules.add(new GenyoSurround()); + modules.add(new GenyoWelcome()); } private void initHUD(Hud hud) { diff --git a/src/main/java/com/genyo/addon/mixin/DefaultSettingsWidgetFactoryMixin.java b/src/main/java/com/genyo/addon/mixin/DefaultSettingsWidgetFactoryMixin.java new file mode 100644 index 0000000..305e4f2 --- /dev/null +++ b/src/main/java/com/genyo/addon/mixin/DefaultSettingsWidgetFactoryMixin.java @@ -0,0 +1,37 @@ +package com.genyo.addon.mixin; + +import com.genyo.addon.screens.PlayerListScreen; +import com.genyo.addon.settings.PlayerListSetting; +import meteordevelopment.meteorclient.gui.DefaultSettingsWidgetFactory; +import meteordevelopment.meteorclient.gui.GuiTheme; +import meteordevelopment.meteorclient.gui.utils.SettingsWidgetFactory; +import meteordevelopment.meteorclient.gui.widgets.containers.WContainer; +import meteordevelopment.meteorclient.gui.widgets.containers.WTable; +import meteordevelopment.meteorclient.settings.Setting; +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 static meteordevelopment.meteorclient.MeteorClient.mc; + +@Mixin(DefaultSettingsWidgetFactory.class) +public abstract class DefaultSettingsWidgetFactoryMixin extends SettingsWidgetFactory { + + @Shadow + private void selectW(WContainer c, Setting setting, Runnable action) {} + + public DefaultSettingsWidgetFactoryMixin(GuiTheme theme) { + super(theme); + } + + @Inject(method = "", at = @At("TAIL")) + protected void genyo(CallbackInfo info) { + factories.put(PlayerListSetting.class, (table, setting) -> playerListW(table, (PlayerListSetting) setting)); + } + + private void playerListW(WTable table, PlayerListSetting setting) { + selectW(table, setting, () -> mc.setScreen(new PlayerListScreen(theme, "Add Players", setting))); + } +} diff --git a/src/main/java/com/genyo/addon/modules/GenyoAutoEZ.java b/src/main/java/com/genyo/addon/modules/GenyoAutoEZ.java index 0a7fa9f..832adba 100644 --- a/src/main/java/com/genyo/addon/modules/GenyoAutoEZ.java +++ b/src/main/java/com/genyo/addon/modules/GenyoAutoEZ.java @@ -7,7 +7,6 @@ import meteordevelopment.meteorclient.events.packets.PacketEvent; import meteordevelopment.meteorclient.events.world.TickEvent; import meteordevelopment.meteorclient.settings.*; -import meteordevelopment.meteorclient.systems.modules.Module; import meteordevelopment.meteorclient.utils.player.ChatUtils; import meteordevelopment.orbit.EventHandler; import meteordevelopment.orbit.EventPriority; @@ -166,7 +165,7 @@ private boolean checkPersonValidity(PlayerEntity player) { return true; } - //TODO: if we want to display this for everyone, then implement something here + //TODO: if we want to display this for everyone return false; } diff --git a/src/main/java/com/genyo/addon/modules/GenyoModule.java b/src/main/java/com/genyo/addon/modules/GenyoModule.java index a1453a7..a41f15f 100644 --- a/src/main/java/com/genyo/addon/modules/GenyoModule.java +++ b/src/main/java/com/genyo/addon/modules/GenyoModule.java @@ -61,7 +61,7 @@ public void sendDisableMsg(String text) { sendMessage(Text.of(msg), hashCode()); } - public void sendBOInfo(String text) { + public void sendInfo(String text) { if (mc.world == null) return; ChatUtils.forceNextPrefixClass(getClass()); diff --git a/src/main/java/com/genyo/addon/modules/GenyoSurround.java b/src/main/java/com/genyo/addon/modules/GenyoSurround.java index 09d7272..3abcbb0 100644 --- a/src/main/java/com/genyo/addon/modules/GenyoSurround.java +++ b/src/main/java/com/genyo/addon/modules/GenyoSurround.java @@ -138,7 +138,7 @@ private void onTick(TickEvent.Pre event) { if (delayTicks >= placeDelay.get()) { delayTicks = 0; if (disableOnJump.get() && mc.options.jumpKey.isPressed() && mc.player.isOnGround()) { - sendBOInfo("Player jumped, disabling."); + sendInfo("Player jumped, disabling."); toggle(); } else { FindItemResult obsidian = InvUtils.findInHotbar(Items.OBSIDIAN); diff --git a/src/main/java/com/genyo/addon/modules/GenyoWelcome.java b/src/main/java/com/genyo/addon/modules/GenyoWelcome.java new file mode 100644 index 0000000..aca2bc0 --- /dev/null +++ b/src/main/java/com/genyo/addon/modules/GenyoWelcome.java @@ -0,0 +1,258 @@ +package com.genyo.addon.modules; + +import com.genyo.addon.GenyoAddon; +import com.genyo.addon.settings.PlayerListSetting; +import com.mojang.authlib.GameProfile; +import com.mojang.util.UndashedUuid; +import meteordevelopment.meteorclient.events.game.GameJoinedEvent; +import meteordevelopment.meteorclient.events.game.GameLeftEvent; +import meteordevelopment.meteorclient.events.packets.PacketEvent; +import meteordevelopment.meteorclient.events.world.TickEvent; +import meteordevelopment.meteorclient.settings.IntSetting; +import meteordevelopment.meteorclient.settings.Setting; +import meteordevelopment.meteorclient.settings.SettingGroup; +import meteordevelopment.meteorclient.settings.StringSetting; +import meteordevelopment.meteorclient.utils.misc.ISerializable; +import meteordevelopment.meteorclient.utils.network.Http; +import meteordevelopment.meteorclient.utils.network.PacketUtils; +import meteordevelopment.meteorclient.utils.player.ChatUtils; +import meteordevelopment.meteorclient.utils.render.PlayerHeadTexture; +import meteordevelopment.meteorclient.utils.render.PlayerHeadUtils; +import meteordevelopment.orbit.EventHandler; +import meteordevelopment.orbit.EventPriority; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.PlayerListEntry; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.packet.s2c.play.GameJoinS2CPacket; +import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket; +import net.minecraft.util.profiling.jfr.event.PacketReceivedEvent; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nullable; +import java.util.*; + +public class GenyoWelcome extends GenyoModule { + + public static List genyo = new ArrayList<>(); + + private Set onlinePlayers = new HashSet<>(); + private final List messageQueue = new LinkedList<>(); + private int timer = 0; + + private final SettingGroup sgGeneral = settings.getDefaultGroup(); + + private final Setting> players = sgGeneral.add(new PlayerListSetting.Builder() + .name("Players") + .description("sdasdjgewqjhgfjhgewjhfg ew gfjhewgfhjgwehjf gjhwe few") + .onChanged(this::refreshList) + .build() + ); + + private final Setting message = sgGeneral.add(new StringSetting.Builder() + .name("Message") + .description(" ewhfhewjkfhejwkhfhewkjfhewjkfhkjewhfkhewfke") + .defaultValue("genyo ") + .build() + ); + + private final Setting tickDelay = sgGeneral.add(new IntSetting.Builder() + .name("Delay") + .description("tick delay between the messages.") + .defaultValue(0) + .min(0) + .sliderRange(0, 100) + .build() + ); + + @Override + public void onActivate() { + onlinePlayers.clear(); + } + + public GenyoWelcome() { + super(GenyoAddon.GENYO, "Genyo Welcome", "i love kiwi. i love kiwi. i love kiwi. i love kiwi. i love kiwi."); + } + + @EventHandler + private void onGameJoined(GameJoinedEvent event) { + if (mc.player == null && mc.world == null) return; + onlinePlayers.clear(); + mc.getNetworkHandler().getPlayerList().iterator().forEachRemaining(p -> { + if (p.getProfile() != null) onlinePlayers.add(p.getProfile().getId()); + }); + } + + @EventHandler + private void onGameLeft(GameLeftEvent event) { + onlinePlayers.clear(); + } + + @EventHandler(priority = EventPriority.HIGHEST) + private void onTick(TickEvent.Pre event) { + if (mc.player == null && mc.world == null) return; + timer++; + + if (timer >= tickDelay.get() && !messageQueue.isEmpty()) { + Message msg = messageQueue.get(0); + ChatUtils.sendPlayerMsg(msg.message); + timer = 0; + + if (msg.kill) messageQueue.clear(); + else messageQueue.removeFirst(); + } + } + + @EventHandler + private void onReceivePacket(PacketEvent.Receive event) { + if (event.packet instanceof PlayerListS2CPacket pac) { + pac.getEntries().forEach(entry -> { + GameProfile profile = entry.profile(); + if (profile == null) return; + + String name = profile.getName(); + if (!contains(name)) return; + UUID playerUuid = profile.getId(); + GenyoAddon.LOG.info("asd"); + if (!pac.getActions().contains(PlayerListS2CPacket.Action.ADD_PLAYER) + && playerUuid != null && !onlinePlayers.contains(playerUuid)) return; + + handleMessage(name); + onlinePlayers.add(playerUuid); + }); + } + } + + private void handleMessage(String name) { + if (mc.world == null) return; + + String toSend = message.get(); + toSend = toSend.contains("") ? toSend.replace("", name) : toSend; + + Message msg = new Message(toSend, false); + messageQueue.add(msg); + } + + private boolean contains(String name) { + for (ListPlayer listPlayer : players.get()) { + if (listPlayer.name.equalsIgnoreCase(name)) return true; + } + + return false; + } + + private void refreshList(List a) { + genyo = a; + } + + public static ListPlayer get(String name) { + for (ListPlayer player : genyo) { + if (player == null) return null; + + if (player.name.equalsIgnoreCase(name)) { + return player; + } + } + + return null; + } + + public boolean isInList(String name) { + return get(name) != null; + } + + public static ListPlayer createListPlayer(String name) { + return new ListPlayer(name); + } + + public static class ListPlayer implements ISerializable, Comparable { + private static final MinecraftClient mc = MinecraftClient.getInstance(); + + public volatile String name; + private volatile @Nullable UUID id; + private volatile @Nullable PlayerHeadTexture headTexture; + private volatile boolean updating; + + public ListPlayer(String name, @Nullable UUID id) { + this.name = name; + this.id = id; + this.headTexture = null; + } + + public ListPlayer(PlayerEntity player) { + this(player.getName().getString(), player.getUuid()); + } + + public ListPlayer(String name) { + this(name, null); + } + + public UUID getId() { + return id; + } + + public String getName() { + return name; + } + + public PlayerHeadTexture getHead() { + return headTexture != null ? headTexture : PlayerHeadUtils.STEVE_HEAD; + } + + public void updateInfo() { + updating = true; + APIResponse res = Http.get("https://api.mojang.com/users/profiles/minecraft/" + name).sendJson(APIResponse.class); + if (res == null || res.name == null || res.id == null) return; + name = res.name; + id = UndashedUuid.fromStringLenient(res.id); + mc.execute(() -> headTexture = PlayerHeadUtils.fetchHead(id)); + updating = false; + } + + public boolean headTextureNeedsUpdate() { + return !this.updating && headTexture == null; + } + + @Override + public NbtCompound toTag() { + NbtCompound tag = new NbtCompound(); + + tag.putString("name", name); + if (id != null) tag.putString("id", UndashedUuid.toString(id)); + + return tag; + } + + @Override + public ListPlayer fromTag(NbtCompound tag) { + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ListPlayer player = (ListPlayer) o; + return Objects.equals(name, player.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } + + @Override + public int compareTo(@NotNull GenyoWelcome.ListPlayer player) { + return name.compareTo(player.name); + } + + private static class APIResponse { + String name, id; + } + } + + private record Message(String message, boolean kill) { + } + + +} diff --git a/src/main/java/com/genyo/addon/screens/PlayerListScreen.java b/src/main/java/com/genyo/addon/screens/PlayerListScreen.java new file mode 100644 index 0000000..805f7a9 --- /dev/null +++ b/src/main/java/com/genyo/addon/screens/PlayerListScreen.java @@ -0,0 +1,111 @@ +package com.genyo.addon.screens; + +import com.genyo.addon.GenyoAddon; +import com.genyo.addon.modules.GenyoWelcome; +import com.genyo.addon.settings.PlayerListSetting; +import meteordevelopment.meteorclient.gui.GuiTheme; +import meteordevelopment.meteorclient.gui.WindowScreen; +import meteordevelopment.meteorclient.gui.widgets.WWidget; +import meteordevelopment.meteorclient.gui.widgets.containers.WHorizontalList; +import meteordevelopment.meteorclient.gui.widgets.containers.WTable; +import meteordevelopment.meteorclient.gui.widgets.input.WTextBox; +import meteordevelopment.meteorclient.gui.widgets.pressable.WMinus; +import meteordevelopment.meteorclient.gui.widgets.pressable.WPlus; +import meteordevelopment.meteorclient.utils.network.MeteorExecutor; + +public class PlayerListScreen extends WindowScreen { + + protected final PlayerListSetting setting; + private WTable table; + + public PlayerListScreen(GuiTheme theme, String title, PlayerListSetting setting) { + super(theme, title); + + this.setting = setting; + } + + @Override + public void initWidgets() { + table = add(theme.table()).expandX().minWidth(400).widget(); + + initTable(table); + + // New + WHorizontalList list = add(theme.horizontalList()).expandX().widget(); + + WTextBox nameW = list.add(theme.textBox("", (text, c) -> c != ' ')).expandX().widget(); + nameW.setFocused(true); + + WPlus add = list.add(theme.plus()).widget(); + add.action = () -> { + String name = nameW.get().trim(); + if (name.equalsIgnoreCase("")) return; + + if (setting.get(name) != null) { + nameW.set(""); + return; + } + + GenyoWelcome.ListPlayer player = GenyoWelcome.createListPlayer(name); + nameW.set(""); + setting.get().add(player); + + MeteorExecutor.execute(() -> { + player.updateInfo(); + reload(); + }); + + setting.onChanged(); + //table.clear(); + }; + + enterAction = add.action; + } + + private void initTable(WTable table) { + table.clear(); + if (setting.get().isEmpty()) return; + + setting.get().forEach(player -> + MeteorExecutor.execute(() -> { + if (player == null) { + setting.get().remove(player); + return; + } + if (player.headTextureNeedsUpdate()) { + player.updateInfo(); + reload(); + } + }) + ); + + for (GenyoWelcome.ListPlayer player : setting.get()) { + if (player == null) { + setting.get().remove(player); + return; + } + table.add(theme.texture(32, 32, player.getHead().needsRotate() ? 90 : 0, player.getHead())); + table.add(theme.label(player.getName())); + + WMinus remove = table.add(theme.minus()).expandCellX().right().widget(); + remove.action = () -> { + setting.get().remove(player); + + setting.onChanged(); + table.clear(); + reload(); + }; + + table.row(); + } + } + + protected WWidget getValueWidget(GenyoWelcome.ListPlayer value) { + return theme.label(getValueName(value)); + } + + protected String getValueName(GenyoWelcome.ListPlayer value) { + return value.getName(); + } + +} diff --git a/src/main/java/com/genyo/addon/settings/PlayerListSetting.java b/src/main/java/com/genyo/addon/settings/PlayerListSetting.java new file mode 100644 index 0000000..6867356 --- /dev/null +++ b/src/main/java/com/genyo/addon/settings/PlayerListSetting.java @@ -0,0 +1,97 @@ +package com.genyo.addon.settings; + +import com.genyo.addon.GenyoAddon; +import com.genyo.addon.modules.GenyoWelcome; +import meteordevelopment.meteorclient.settings.IVisible; +import meteordevelopment.meteorclient.settings.Setting; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; +import net.minecraft.nbt.NbtList; +import net.minecraft.nbt.NbtString; +import net.minecraft.util.Identifier; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Consumer; + +public class PlayerListSetting extends Setting> { + + public PlayerListSetting(String name, String description, List defaultValue, Consumer> onChanged, Consumer>> onModuleActivated, IVisible visible) { + super(name, description, defaultValue, onChanged, onModuleActivated, visible); + } + + @Override + protected List parseImpl(String str) { + String[] values = str.split(","); + List players = new ArrayList<>(values.length); + + try { + for (String value : values) { + if (GenyoWelcome.get(value) != null) players.add(GenyoWelcome.get(value)); + } + } catch (Exception ignored) {} + + return players; + } + + @Override + public void resetImpl() { + value = new ArrayList<>(defaultValue); + } + + public GenyoWelcome.ListPlayer get(String name) { + for (GenyoWelcome.ListPlayer player : get()) { + if (player.name.equalsIgnoreCase(name)) return player; + } + + return null; + } + + @Override + protected boolean isValueValid(List value) { + return true; + } + + @Override + public NbtCompound save(NbtCompound tag) { + NbtList valueTag = new NbtList(); + for (GenyoWelcome.ListPlayer player : get()) { + valueTag.add(NbtString.of(player.getName())); + } + tag.put("value", valueTag); + + return tag; + } + + @Override + public List load(NbtCompound tag) { + get().clear(); + + NbtList valueTag = tag.getList("value", 8); + for (NbtElement tagI : valueTag) { + GenyoWelcome.ListPlayer player = GenyoWelcome.createListPlayer(tagI.asString()); + + get().add(player); + } + + return get(); + } + + public static class Builder extends SettingBuilder, PlayerListSetting> { + public Builder() { + super(new ArrayList<>(0)); + } + + public Builder defaultValue(GenyoWelcome.ListPlayer... defaults) { + return defaultValue(defaults != null ? Arrays.asList(defaults) : new ArrayList<>()); + } + + @Override + public PlayerListSetting build() { + return new PlayerListSetting(name, description, defaultValue, onChanged, onModuleActivated, visible); + } + } + + +} diff --git a/src/main/resources/genyo.mixins.json b/src/main/resources/genyo.mixins.json index e1d3542..072fd05 100644 --- a/src/main/resources/genyo.mixins.json +++ b/src/main/resources/genyo.mixins.json @@ -5,7 +5,8 @@ "client": [ "PlayerUtilsMixin", "FriendsInjector", - "IEntity" + "IEntity", + "DefaultSettingsWidgetFactoryMixin" ], "injectors": { "defaultRequire": 1