From c60470e349aa2633cd7d0ab9a76bf04b63260d6c Mon Sep 17 00:00:00 2001 From: plulsls Date: Mon, 30 Aug 2021 16:14:58 +0800 Subject: [PATCH] add autoSwitchElytra --- README.md | 4 ++ README_EN.md | 4 ++ gradle.properties | 2 +- .../java/com/plusls/ommc/config/Configs.java | 2 + .../AutoSwitchElytraUtil.java | 62 +++++++++++++++++++ .../sortInventory/SortInventoryUtil.java | 18 ++++-- .../MixinClientPlayerEntity.java | 53 ++++++++++++++++ .../resources/assets/ommc/lang/en_us.json | 2 + .../resources/assets/ommc/lang/zh_cn.json | 2 + .../resources/ommc.compat.canvas.mixins.json | 4 +- src/main/resources/ommc.mixins.json | 1 + 11 files changed, 146 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/plusls/ommc/feature/autoSwitchElytra/AutoSwitchElytraUtil.java create mode 100644 src/main/java/com/plusls/ommc/mixin/feature/autoSwitchElytra/MixinClientPlayerEntity.java diff --git a/README.md b/README.md index 9aa045a..957474e 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,10 @@ Make Minecraft Client Great Again! ## Feature +### 自动切换鞘翅 + +自动切换鞘翅和胸甲(支持原地起飞) + ### 禁止破坏特定方块 玩家无法破坏在 **破坏方块黑名单** 中的方块 diff --git a/README_EN.md b/README_EN.md index dcd8231..d75f5fa 100644 --- a/README_EN.md +++ b/README_EN.md @@ -45,6 +45,10 @@ Support empty shulker box stack when sort inventory. ## Features +### Auto Switch Elytra + +Auto Switch elytra and chestplate. + ### Disable Break Block You can't break blocks in **breakBlockBlackList**. diff --git a/gradle.properties b/gradle.properties index 543e4f2..c880821 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ minecraft_version=1.17.1 yarn_mappings=1.17.1+build.10 loader_version=0.11.6 # Mod Properties -mod_version=0.3.4 +mod_version=0.3.5 maven_group=com.plusls archives_base_name=oh-my-minecraft-client # Dependencies diff --git a/src/main/java/com/plusls/ommc/config/Configs.java b/src/main/java/com/plusls/ommc/config/Configs.java index 4b56eb1..8348a55 100644 --- a/src/main/java/com/plusls/ommc/config/Configs.java +++ b/src/main/java/com/plusls/ommc/config/Configs.java @@ -88,6 +88,7 @@ public static class Generic { public static class FeatureToggle { private static final String PREFIX = String.format("%s.config.feature_toggle", ModInfo.MOD_ID); + public static final ConfigBooleanHotkeyed AUTO_SWITCH_ELYTRA = new TranslatableConfigBooleanHotkeyed(PREFIX, "autoSwitchElytra", false, ""); public static final ConfigBooleanHotkeyed DISABLE_BREAK_BLOCK = new TranslatableConfigBooleanHotkeyed(PREFIX, "disableBreakBlock", false, ""); public static final ConfigBooleanHotkeyed DISABLE_BREAK_SCAFFOLDING = new TranslatableConfigBooleanHotkeyed(PREFIX, "disableBreakScaffolding", false, ""); public static final ConfigBooleanHotkeyed DISABLE_MOVE_DOWN_IN_SCAFFOLDING = new TranslatableConfigBooleanHotkeyed(PREFIX, "disableMoveDownInScaffolding", false, ""); @@ -103,6 +104,7 @@ public static class FeatureToggle { public static final ConfigBooleanHotkeyed WORLD_EATER_MINE_HELPER = new TranslatableConfigBooleanHotkeyed(PREFIX, "worldEaterMineHelper", false, ""); public static final ImmutableList OPTIONS = ImmutableList.of( + AUTO_SWITCH_ELYTRA, DISABLE_BREAK_BLOCK, DISABLE_BREAK_SCAFFOLDING, DISABLE_MOVE_DOWN_IN_SCAFFOLDING, diff --git a/src/main/java/com/plusls/ommc/feature/autoSwitchElytra/AutoSwitchElytraUtil.java b/src/main/java/com/plusls/ommc/feature/autoSwitchElytra/AutoSwitchElytraUtil.java new file mode 100644 index 0000000..348c2e1 --- /dev/null +++ b/src/main/java/com/plusls/ommc/feature/autoSwitchElytra/AutoSwitchElytraUtil.java @@ -0,0 +1,62 @@ +package com.plusls.ommc.feature.autoSwitchElytra; + +import com.plusls.ommc.ModInfo; +import com.plusls.ommc.feature.sortInventory.SortInventoryUtil; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.entity.effect.StatusEffects; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.ScreenHandler; + +import java.util.ArrayList; +import java.util.function.Predicate; + +public class AutoSwitchElytraUtil { + public static final int CHEST_SLOT_IDX = 6; + + public static boolean myCheckFallFlying(PlayerEntity player) { + if (!player.isOnGround() && !player.isFallFlying() && !player.isTouchingWater() && !player.hasStatusEffect(StatusEffects.LEVITATION)) { + return true; + } + return false; + } + + public static void autoSwitch(int sourceSlot, MinecraftClient client, ClientPlayerEntity clientPlayerEntity, Predicate check) { + if (client.interactionManager == null) { + return; + } + ScreenHandler screenHandler = clientPlayerEntity.currentScreenHandler; + ArrayList clickQueue = new ArrayList<>(); + ItemStack cursorStack = screenHandler.getCursorStack().copy(); + ArrayList itemStacks = new ArrayList<>(); + int playerInventoryStartIdx = SortInventoryUtil.getPlayerInventoryStartIdx(screenHandler); + for (int i = 0; i < screenHandler.slots.size(); ++i) { + itemStacks.add(screenHandler.slots.get(i).getStack().copy()); + } + if (!cursorStack.isEmpty()) { + // 把鼠标的物品放到玩家仓库中 + clickQueue.addAll(SortInventoryUtil.addItemStack(itemStacks, cursorStack, playerInventoryStartIdx, screenHandler.slots.size())); + } + if (!cursorStack.isEmpty()) { + // 放不下了就扔出去 + clickQueue.add(ScreenHandler.EMPTY_SPACE_SLOT_INDEX); + } + int idxToSwitch = -1; + for (int i = 0; i < itemStacks.size(); ++i) { + if (check.test(itemStacks.get(i))) { + idxToSwitch = i; + break; + } + } + boolean sourceSlotEmpty = itemStacks.get(sourceSlot).isEmpty(); + if (idxToSwitch != -1) { + clickQueue.add(idxToSwitch); + clickQueue.add(sourceSlot); + if (!sourceSlotEmpty) { + clickQueue.add(idxToSwitch); + } + SortInventoryUtil.doClick(clientPlayerEntity, screenHandler.syncId, client.interactionManager, clickQueue); + } + } +} diff --git a/src/main/java/com/plusls/ommc/feature/sortInventory/SortInventoryUtil.java b/src/main/java/com/plusls/ommc/feature/sortInventory/SortInventoryUtil.java index a42b020..c187f40 100644 --- a/src/main/java/com/plusls/ommc/feature/sortInventory/SortInventoryUtil.java +++ b/src/main/java/com/plusls/ommc/feature/sortInventory/SortInventoryUtil.java @@ -4,6 +4,8 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.BundleItem; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -12,13 +14,15 @@ import net.minecraft.screen.*; import net.minecraft.screen.slot.Slot; import net.minecraft.screen.slot.SlotActionType; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.List; import java.util.Optional; public class SortInventoryUtil { - private static int getPlayerInventoryStartIdx(ScreenHandler screenHandler) { + public static int getPlayerInventoryStartIdx(ScreenHandler screenHandler) { if (screenHandler instanceof PlayerScreenHandler) { return 9; } else if (screenHandler instanceof CraftingScreenHandler) { @@ -120,14 +124,18 @@ public static boolean sort() { clickQueue.addAll(quickSort(itemStacks, playerInventoryStartIdx + 27, r)); } + doClick(player, screenHandler.syncId, client.interactionManager, clickQueue); + return !clickQueue.isEmpty(); + } + + public static void doClick(PlayerEntity player, int syncId, @NotNull ClientPlayerInteractionManager interactionManager, List clickQueue) { for (Integer slotId : clickQueue) { if (slotId < 0 && slotId != ScreenHandler.EMPTY_SPACE_SLOT_INDEX) { - client.interactionManager.clickSlot(screenHandler.syncId, -slotId, 1, SlotActionType.PICKUP, player); + interactionManager.clickSlot(syncId, -slotId, 1, SlotActionType.PICKUP, player); } else { - client.interactionManager.clickSlot(screenHandler.syncId, slotId, 0, SlotActionType.PICKUP, player); + interactionManager.clickSlot(syncId, slotId, 0, SlotActionType.PICKUP, player); } } - return !clickQueue.isEmpty(); } private static boolean canStackAddMore(ItemStack existingStack, ItemStack stack) { @@ -138,7 +146,7 @@ private static boolean canStackAddMore(ItemStack existingStack, ItemStack stack) existingStack.getCount() < 64; } - private static ArrayList addItemStack(ArrayList itemStacks, ItemStack stackToAdd, int l, int r) { + public static ArrayList addItemStack(ArrayList itemStacks, ItemStack stackToAdd, int l, int r) { // merge in [l, r) ArrayList ret = new ArrayList<>(); for (int i = l; i < r; ++i) { diff --git a/src/main/java/com/plusls/ommc/mixin/feature/autoSwitchElytra/MixinClientPlayerEntity.java b/src/main/java/com/plusls/ommc/mixin/feature/autoSwitchElytra/MixinClientPlayerEntity.java new file mode 100644 index 0000000..4af8b98 --- /dev/null +++ b/src/main/java/com/plusls/ommc/mixin/feature/autoSwitchElytra/MixinClientPlayerEntity.java @@ -0,0 +1,53 @@ +package com.plusls.ommc.mixin.feature.autoSwitchElytra; + +import com.mojang.authlib.GameProfile; +import com.plusls.ommc.feature.autoSwitchElytra.AutoSwitchElytraUtil; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.AbstractClientPlayerEntity; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.registry.Registry; +import org.spongepowered.asm.mixin.Final; +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; + +@Mixin(ClientPlayerEntity.class) +public abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity { + @Shadow + @Final + protected MinecraftClient client; + + boolean prevFallFlying = false; + + public MixinClientPlayerEntity(ClientWorld world, GameProfile profile) { + super(world, profile); + } + + @Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;getEquippedStack(Lnet/minecraft/entity/EquipmentSlot;)Lnet/minecraft/item/ItemStack;", ordinal = 0)) + private void autoSwitchElytra(CallbackInfo ci) { + ItemStack chestItemStack = this.getEquippedStack(EquipmentSlot.CHEST); + if (chestItemStack.isOf(Items.ELYTRA) || !AutoSwitchElytraUtil.myCheckFallFlying(this)) { + return; + } + AutoSwitchElytraUtil.autoSwitch(AutoSwitchElytraUtil.CHEST_SLOT_IDX, this.client, (ClientPlayerEntity) (Object) this, itemStack -> itemStack.isOf(Items.ELYTRA)); + } + + @Inject(method = "tickMovement", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isFallFlying()Z", ordinal = 0)) + private void autoSwitchChest(CallbackInfo ci) { + ItemStack chestItemStack = this.getEquippedStack(EquipmentSlot.CHEST); + if (!chestItemStack.isOf(Items.ELYTRA) || !prevFallFlying || this.isFallFlying()) { + prevFallFlying = this.isFallFlying(); + return; + } + prevFallFlying = this.isFallFlying(); + AutoSwitchElytraUtil.autoSwitch(AutoSwitchElytraUtil.CHEST_SLOT_IDX, this.client, (ClientPlayerEntity) (Object) this, itemStack -> Registry.ITEM.getId(itemStack.getItem()).toString().contains("_chestplate")); + + } + +} diff --git a/src/main/resources/assets/ommc/lang/en_us.json b/src/main/resources/assets/ommc/lang/en_us.json index 98dcf28..9284083 100644 --- a/src/main/resources/assets/ommc/lang/en_us.json +++ b/src/main/resources/assets/ommc/lang/en_us.json @@ -19,6 +19,8 @@ "ommc.config.generic.sortInventory.comment": "A hotkey to sort inventory.", "ommc.config.generic.sortInventorySupportEmptyShulkerBoxStack.name": "sortInventorySupportEmptyShulkerBoxStack", "ommc.config.generic.sortInventorySupportEmptyShulkerBoxStack.comment": "Support empty shulker box stack when sort inventory.", + "ommc.config.feature_toggle.autoSwitchElytra.name": "autoSwitchElytra", + "ommc.config.feature_toggle.autoSwitchElytra.comment": "Auto switch elytra and chestplate.", "ommc.config.feature_toggle.disableBreakBlock.name": "disableBreakBlock", "ommc.config.feature_toggle.disableBreakBlock.comment": "You can't break blocks in §6breakBlockBlackList§r.", "ommc.config.feature_toggle.disableBreakScaffolding.name": "disableBreakScaffolding", diff --git a/src/main/resources/assets/ommc/lang/zh_cn.json b/src/main/resources/assets/ommc/lang/zh_cn.json index d53a952..e0733b7 100644 --- a/src/main/resources/assets/ommc/lang/zh_cn.json +++ b/src/main/resources/assets/ommc/lang/zh_cn.json @@ -19,6 +19,8 @@ "ommc.config.generic.sortInventory.comment": "整理仓库的快捷键", "ommc.config.generic.sortInventorySupportEmptyShulkerBoxStack.name": "整理仓库时支持空潜影盒堆叠", "ommc.config.generic.sortInventorySupportEmptyShulkerBoxStack.comment": "整理仓库时支持空潜影盒堆叠(请配合 PCA 使用)", + "ommc.config.feature_toggle.autoSwitchElytra.name": "自动切换鞘翅", + "ommc.config.feature_toggle.autoSwitchElytra.comment": "自动切换鞘翅和胸甲", "ommc.config.feature_toggle.disableBreakBlock.name": "禁止破坏特定方块", "ommc.config.feature_toggle.disableBreakBlock.comment": "玩家无法破坏在 §6破坏方块黑名单§r 中的方块", "ommc.config.feature_toggle.disableBreakScaffolding.name": "禁止破坏脚手架", diff --git a/src/main/resources/ommc.compat.canvas.mixins.json b/src/main/resources/ommc.compat.canvas.mixins.json index c502ae5..6f49e42 100644 --- a/src/main/resources/ommc.compat.canvas.mixins.json +++ b/src/main/resources/ommc.compat.canvas.mixins.json @@ -3,8 +3,8 @@ "package": "com.plusls.ommc.compat.canvas.mixin", "plugin": "com.plusls.ommc.OmmcCompatMixinPlugin", "client": [ + "MixinBlockRenderContext", "MixinLavaFluidModel", - "MixinTerrainRenderContext", - "MixinBlockRenderContext" + "MixinTerrainRenderContext" ] } \ No newline at end of file diff --git a/src/main/resources/ommc.mixins.json b/src/main/resources/ommc.mixins.json index 97884a4..49ff9e9 100644 --- a/src/main/resources/ommc.mixins.json +++ b/src/main/resources/ommc.mixins.json @@ -7,6 +7,7 @@ "client": [ "advancedIntegratedServer.MixinIntegratedServer", "advancedIntegratedServer.MixinOpenToLanScreen", + "feature.autoSwitchElytra.MixinClientPlayerEntity", "feature.disableBreakBlock.MixinClientPlayerInteractionManager", "feature.disableBreakScaffolding.MixinClientPlayerInteractionManager", "feature.disableMoveDownInScaffolding.MixinScaffoldingBlock",