Начинающий
- Статус
- Оффлайн
- Регистрация
- 17 Дек 2023
- Сообщения
- 29
- Реакции
- 1
Привет форум. Хотел написать короче FTHelper обычный, вроде бы даже получается. Столкнулся с такой проблемой что после того как предмет использовался(не хотбар), то делается двойной свап и предмет, допустим, трапка остаётся в хотбаре но если бить, то это фантомная трапка а в оригинале меч. Всё безуспешно. Надеюсь вы поможете мне.
FTHelper:
package ru.okak.implement.features.modules.misc;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.experimental.FieldDefaults;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.network.packet.c2s.play.UpdateSelectedSlotC2SPacket;
import net.minecraft.screen.slot.Slot;
import net.minecraft.screen.slot.SlotActionType;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Hand;
import ru.okak.api.event.EventHandler;
import ru.okak.api.feature.module.Module;
import ru.okak.api.feature.module.ModuleCategory;
import ru.okak.api.feature.module.setting.implement.BindSetting;
import ru.okak.api.feature.module.setting.implement.MultiSelectSetting;
import ru.okak.common.util.entity.PlayerInventoryComponent;
import ru.okak.common.util.entity.PlayerInventoryUtil;
import ru.okak.common.util.other.StopWatch;
import ru.okak.implement.events.keyboard.KeyEvent;
import ru.okak.implement.events.player.TickEvent;
import ru.okak.implement.features.draggables.Notifications;
import java.util.ArrayList;
import java.util.List;
@Getter
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class FTHelper extends Module {
private static final String BIND_MODE = "Bind Mode";
MultiSelectSetting mode = new MultiSelectSetting("Mode", "Select usage mode")
.value("Bind Mode", "Close Inventory");
BindSetting disorientationKey = new BindSetting("Disorientation", "Key for disorientation item")
.visible(() -> mode.isSelected("Bind Mode"));
BindSetting trapKey = new BindSetting("Trap", "Key for trap item")
.visible(() -> mode.isSelected("Bind Mode"));
BindSetting sugarKey = new BindSetting("Sugar", "Key for sugar item")
.visible(() -> mode.isSelected("Bind Mode"));
BindSetting plastKey = new BindSetting("Plast", "Key for plast item")
.visible(() -> mode.isSelected("Bind Mode"));
BindSetting freezeKey = new BindSetting("Freeze", "Key for freeze item")
.visible(() -> mode.isSelected("Bind Mode"));
List<Ability> abilities = new ArrayList<>();
StopWatch delayStopWatch = new StopWatch();
private static final long DELAY_MS = 200L;
private static final int TICKS_BETWEEN_ACTIONS = 2;
public FTHelper() {
super("FTHelper", "FTHelper", ModuleCategory.MISC);
setup(mode, disorientationKey, trapKey, sugarKey, plastKey, freezeKey);
abilities.add(new Ability("трапка", Items.NETHERITE_SCRAP, trapKey,
"Trap item not found!", "Used trap item!", true));
abilities.add(new Ability("дезориентация", Items.ENDER_EYE, disorientationKey,
"Disorientation item not found!", "Used disorientation item!", true));
abilities.add(new Ability("явная пыль", Items.SUGAR, sugarKey,
"Sugar item not found!", "Used sugar item!", true));
abilities.add(new Ability("пласт", Items.DRIED_KELP, plastKey,
"Plast item not found!", "Used plast item!", true));
abilities.add(new Ability("снежок заморозка", Items.SNOWBALL, freezeKey,
"Freeze item not found!", "Used freeze item!", true));
}
@EventHandler
public void onKey(KeyEvent e) {
if (!isBindModeActive() || mc.player == null) return;
for (Ability ability : abilities) {
if (e.isKeyDown(ability.getBindSetting().getKey())) {
ability.queueUse();
}
}
}
@EventHandler
public void onTick(TickEvent e) {
if (!isBindModeActive() || mc.player == null) return;
if (!delayStopWatch.finished(DELAY_MS)) return;
for (Ability ability : abilities) {
if (ability.consumeQueuedUse()) {
triggerAbility(ability);
delayStopWatch.reset();
return;
}
}
for (Ability ability : abilities) {
ItemStack stack = new ItemStack(ability.getItem());
float cooldown = mc.player.getItemCooldownManager().getCooldownProgress(stack, 0);
ability.updateCooldown(cooldown);
}
}
private void triggerAbility(Ability ability) {
ItemStack stack = new ItemStack(ability.getItem());
if (mc.player.getItemCooldownManager().isCoolingDown(stack)) {
sendNotification("Item on cooldown!", Formatting.RED);
return;
}
Slot slot = findItemByName(ability.getInventoryKeyword());
if (slot == null) {
sendNotification(ability.getNotFoundMessage(), Formatting.RED);
return;
}
sendNotification(ability.getSuccessMessage(), Formatting.GREEN);
useItemWithSlot(slot, ability);
}
private void useItemWithSlot(Slot slot, Ability ability) {
int originalSlot = mc.player.getInventory().selectedSlot;
int slotId = slot.id;
boolean isInHotbar = slotId < 9;
ItemStack oldHandItem = mc.player.getMainHandStack().copy();
PlayerInventoryComponent.addTask(() -> {
PlayerInventoryComponent.disableMoveKeys();
if (isInHotbar) {
if (originalSlot != slotId) {
mc.player.networkHandler.sendPacket(new UpdateSelectedSlotC2SPacket(slotId));
mc.player.getInventory().selectedSlot = slotId;
PlayerInventoryComponent.script.addTickStep(1, () -> {
useCurrentItem();
if (ability.isRestoreSelectedSlot()) {
PlayerInventoryComponent.script.addTickStep(TICKS_BETWEEN_ACTIONS, () -> {
mc.player.networkHandler.sendPacket(new UpdateSelectedSlotC2SPacket(originalSlot));
mc.player.getInventory().selectedSlot = originalSlot;
PlayerInventoryComponent.enableMoveKeys();
});
} else {
PlayerInventoryComponent.script.addTickStep(TICKS_BETWEEN_ACTIONS, PlayerInventoryComponent::enableMoveKeys);
}
});
} else {
useCurrentItem();
PlayerInventoryComponent.script.addTickStep(TICKS_BETWEEN_ACTIONS, PlayerInventoryComponent::enableMoveKeys);
}
} else {
if (oldHandItem.isEmpty()) {
PlayerInventoryUtil.clickSlot(slot.id, originalSlot, SlotActionType.SWAP, false);
PlayerInventoryComponent.script.addTickStep(TICKS_BETWEEN_ACTIONS, () -> {
useCurrentItem();
PlayerInventoryComponent.script.addTickStep(TICKS_BETWEEN_ACTIONS, () -> {
PlayerInventoryUtil.clickSlot(originalSlot, slot.id, SlotActionType.SWAP, false);
if (ability.isRestoreSelectedSlot()) {
mc.player.networkHandler.sendPacket(new UpdateSelectedSlotC2SPacket(originalSlot));
mc.player.getInventory().selectedSlot = originalSlot;
}
PlayerInventoryComponent.script.addTickStep(1, PlayerInventoryComponent::enableMoveKeys);
});
});
} else {
PlayerInventoryUtil.clickSlot(slot.id, originalSlot, SlotActionType.SWAP, false);
PlayerInventoryComponent.script.addTickStep(TICKS_BETWEEN_ACTIONS, () -> {
useCurrentItem();
PlayerInventoryComponent.script.addTickStep(TICKS_BETWEEN_ACTIONS, () -> {
PlayerInventoryUtil.clickSlot(slot.id, originalSlot, SlotActionType.SWAP, false);
if (ability.isRestoreSelectedSlot()) {
mc.player.networkHandler.sendPacket(new UpdateSelectedSlotC2SPacket(originalSlot));
mc.player.getInventory().selectedSlot = originalSlot;
}
PlayerInventoryComponent.script.addTickStep(1, PlayerInventoryComponent::enableMoveKeys);
});
});
}
}
});
}
private void useCurrentItem() {
if (mc.player == null || mc.interactionManager == null) return;
mc.interactionManager.interactItem(mc.player, Hand.MAIN_HAND);
mc.player.swingHand(Hand.MAIN_HAND);
}
private Slot findItemByName(String name, boolean inHotBar) {
if (mc.player == null) return null;
int firstSlot = inHotBar ? 0 : 9;
int lastSlot = inHotBar ? 9 : 36;
for (int i = firstSlot; i < lastSlot; i++) {
ItemStack itemStack = mc.player.getInventory().getStack(i);
if (itemStack.isEmpty()) continue;
String displayName = Formatting.strip(itemStack.getName().getString()).toLowerCase();
if (displayName.contains(name.toLowerCase())) {
return mc.player.currentScreenHandler.slots.get(i);
}
}
return null;
}
private Slot findItemByName(String name) {
Slot hotbarSlot = findItemByName(name, true);
return hotbarSlot != null ? hotbarSlot : findItemByName(name, false);
}
private void sendNotification(String message, Formatting color) {
Text notification = Text.literal("")
.append(Text.literal("[FTHelper] ").formatted(Formatting.GRAY))
.append(Text.literal(message).formatted(color));
Notifications.getInstance().addList(notification.getString(), 2000);
}
private boolean isBindModeActive() {
return mode.isSelected("Bind Mode");
}
@Override
public void deactivate() {
for (Ability ability : abilities) {
ability.reset();
}
super.deactivate();
}
public List<HudAbilityState> getHudData(float partialTicks) {
if (!isBindModeActive() || mc.player == null) {
abilities.forEach(Ability::resetCooldown);
return List.of();
}
List<HudAbilityState> states = new ArrayList<>();
for (Ability ability : abilities) {
int keyCode = ability.getBindSetting().getKey();
if (keyCode == -1) {
ability.resetCooldown();
continue;
}
String keyName = resolveKeyName(keyCode);
double cooldown = ability.getCooldownSeconds();
states.add(new HudAbilityState(
new ItemStack(ability.getItem()),
keyName,
cooldown > 0 ? cooldown : null
));
}
return states;
}
private String resolveKeyName(int keyCode) {
return "Key_" + keyCode;
}
@Getter
public static class Ability {
private final String inventoryKeyword;
private final Item item;
private final BindSetting bindSetting;
private final String notFoundMessage;
private final String successMessage;
private final boolean restoreSelectedSlot;
private boolean queuedUse;
private final CooldownWatch cooldownWatch = new CooldownWatch();
public Ability(String inventoryKeyword, Item item, BindSetting bindSetting,
String notFoundMessage, String successMessage, boolean restoreSelectedSlot) {
this.inventoryKeyword = inventoryKeyword;
this.item = item;
this.bindSetting = bindSetting;
this.notFoundMessage = notFoundMessage;
this.successMessage = successMessage;
this.restoreSelectedSlot = restoreSelectedSlot;
}
public void queueUse() {
this.queuedUse = true;
}
public boolean consumeQueuedUse() {
if (!queuedUse) return false;
this.queuedUse = false;
return true;
}
public void reset() {
this.queuedUse = false;
this.cooldownWatch.reset();
}
public void updateCooldown(float progress) {
cooldownWatch.update(progress);
}
public double getCooldownSeconds() {
return cooldownWatch.getRemainingSeconds();
}
public void resetCooldown() {
cooldownWatch.reset();
}
}
public static class CooldownWatch {
private boolean active;
private long startTime;
private long totalDuration;
public void update(float progress) {
long now = System.currentTimeMillis();
if (progress <= 0) {
reset();
return;
}
if (!active) {
active = true;
startTime = now;
totalDuration = 0;
return;
}
if (totalDuration == 0 && progress < 0.98f) {
long elapsed = now - startTime;
if (elapsed > 0 && progress > 0) {
totalDuration = (long)(elapsed / (1.0 - progress));
}
}
}
public double getRemainingSeconds() {
if (!active || totalDuration == 0) return 0;
long elapsed = System.currentTimeMillis() - startTime;
long remaining = totalDuration - elapsed;
if (remaining <= 0) {
reset();
return 0;
}
return remaining / 1000.0;
}
public void reset() {
active = false;
totalDuration = 0;
}
}
public record HudAbilityState(ItemStack itemStack, String keyName, Double cooldownSeconds) {
public boolean hasCooldown() {
return cooldownSeconds != null && cooldownSeconds > 0;
}
}
}
Последнее редактирование: