-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Displace better player check & options #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,4 +23,4 @@ plugins { | |
| } | ||
|
|
||
|
|
||
| rootProject.name = "myau-injection-template" | ||
| rootProject.name = "SUIM" | ||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -7,37 +7,46 @@ | |||||||||
| import coffee.axle.suim.util.MyauLogger; | ||||||||||
| import coffee.axle.suim.util.Utils; | ||||||||||
| import net.minecraft.client.Minecraft; | ||||||||||
| import net.minecraft.entity.Entity; | ||||||||||
| import net.minecraft.entity.EntityLivingBase; | ||||||||||
| import net.minecraft.entity.player.EntityPlayer; | ||||||||||
| import net.minecraft.util.ChatComponentText; | ||||||||||
| import net.minecraft.util.Vec3; | ||||||||||
| import net.minecraftforge.common.MinecraftForge; | ||||||||||
| import net.minecraftforge.event.entity.player.AttackEntityEvent; | ||||||||||
| import net.minecraftforge.fml.common.eventhandler.EventPriority; | ||||||||||
| import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; | ||||||||||
| import net.minecraft.enchantment.EnchantmentHelper; | ||||||||||
| import net.minecraft.client.settings.KeyBinding; | ||||||||||
| import org.lwjgl.input.Mouse; | ||||||||||
| import net.minecraft.init.Items; | ||||||||||
| import net.minecraft.item.ItemStack; | ||||||||||
| import net.minecraft.item.ItemSword; | ||||||||||
|
|
||||||||||
| import java.util.HashMap; | ||||||||||
| import java.util.Iterator; | ||||||||||
| import java.util.Map; | ||||||||||
|
|
||||||||||
| @SuppressWarnings({ "unused" }) | ||||||||||
| public class Displace extends Feature { | ||||||||||
|
|
||||||||||
| private static final Minecraft mc = Minecraft.getMinecraft(); | ||||||||||
| private static final int DISPLACE_WINDOW_TICKS = 10; | ||||||||||
| private static final String[] DIRECTIONS = {"Left", "Right"}; | ||||||||||
| private static final String[] DIRECTIONS = { "Left", "Right" }; | ||||||||||
|
|
||||||||||
| private Object moduleInstance; | ||||||||||
| private Object yawOffsetProperty; | ||||||||||
| private Object delayProperty; | ||||||||||
| private Object directionProperty; | ||||||||||
| private Object findVoidProperty; | ||||||||||
| private Object weaponOnly, knockbackOnly; | ||||||||||
|
|
||||||||||
| private boolean displaceThisTick = false; | ||||||||||
| private boolean active = false; | ||||||||||
| private boolean compensateNextTick = false; | ||||||||||
| private boolean displaceLeft = false; | ||||||||||
| private boolean wasDisplacingLastTick = false; | ||||||||||
| private boolean hasKB = false; | ||||||||||
| private Entity attackedLivingEntity = null; | ||||||||||
| private int tickCounter = 0; | ||||||||||
| private final Map<Integer, Integer> targetWindowStartTicks = new HashMap<>(); | ||||||||||
|
|
||||||||||
|
|
@@ -61,9 +70,11 @@ public boolean initialize() { | |||||||||
| delayProperty = creator.createIntegerProperty("delay-ms", 0, 0, 500); | ||||||||||
| directionProperty = creator.createEnumProperty("direction", 0, DIRECTIONS); | ||||||||||
| findVoidProperty = creator.createBooleanProperty("find-void", false); | ||||||||||
| weaponOnly = creator.createBooleanProperty("weapon-only", true); | ||||||||||
| knockbackOnly = creator.createBooleanProperty("knockback-only", false); | ||||||||||
|
|
||||||||||
| creator.registerProperties(moduleInstance, yawOffsetProperty, delayProperty, | ||||||||||
| directionProperty, findVoidProperty); | ||||||||||
| directionProperty, findVoidProperty, weaponOnly, knockbackOnly); | ||||||||||
| manager.reloadModuleCommand(); | ||||||||||
|
|
||||||||||
| MinecraftForge.EVENT_BUS.register(this); | ||||||||||
|
|
@@ -83,6 +94,7 @@ private void onEnable() { | |||||||||
| hasKB = false; | ||||||||||
| compensateNextTick = false; | ||||||||||
| wasDisplacingLastTick = false; | ||||||||||
| attackedLivingEntity = null; | ||||||||||
| tickCounter = 0; | ||||||||||
| targetWindowStartTicks.clear(); | ||||||||||
| } | ||||||||||
|
|
@@ -92,11 +104,13 @@ private void onDisable() { | |||||||||
| hasKB = false; | ||||||||||
| compensateNextTick = false; | ||||||||||
| wasDisplacingLastTick = false; | ||||||||||
| attackedLivingEntity = null; | ||||||||||
| targetWindowStartTicks.clear(); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| private int msToTicks(double ms) { | ||||||||||
| if (ms <= 0.0) return 0; | ||||||||||
| if (ms <= 0.0) | ||||||||||
| return 0; | ||||||||||
| return (int) Math.ceil(ms / 50.0); | ||||||||||
| } | ||||||||||
|
|
||||||||||
|
|
@@ -107,11 +121,19 @@ private boolean anyMovementKey() { | |||||||||
| || mc.gameSettings.keyBindRight.isKeyDown(); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| private boolean tryFindVoidDirection(EntityPlayer target) { | ||||||||||
| private boolean isHoldingAllowedWeapon() { | ||||||||||
| ItemStack heldItem = mc.thePlayer.getHeldItem(); | ||||||||||
| if (heldItem == null) | ||||||||||
| return false; | ||||||||||
| return heldItem.getItem() instanceof ItemSword || heldItem.getItem() == Items.stick; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| private boolean tryFindVoidDirection(Entity target) { | ||||||||||
| double dx = target.posX - mc.thePlayer.posX; | ||||||||||
| double dz = target.posZ - mc.thePlayer.posZ; | ||||||||||
| double dist = Math.sqrt(dx * dx + dz * dz); | ||||||||||
| if (dist < 0.001) return false; | ||||||||||
| if (dist < 0.001) | ||||||||||
| return false; | ||||||||||
| dx /= dist; | ||||||||||
| dz /= dist; | ||||||||||
| double rightX = -dz; | ||||||||||
|
|
@@ -130,8 +152,10 @@ private boolean tryFindVoidDirection(EntityPlayer target) { | |||||||||
| if (mc.theWorld.rayTraceBlocks(new Vec3(lx, eyeY, lz), new Vec3(lx, eyeY - 10, lz)) == null) | ||||||||||
| leftVoidCount++; | ||||||||||
| } | ||||||||||
| if (leftVoidCount == 0 && rightVoidCount == 0) return false; | ||||||||||
| if (leftVoidCount != rightVoidCount) displaceLeft = leftVoidCount > rightVoidCount; | ||||||||||
| if (leftVoidCount == 0 && rightVoidCount == 0) | ||||||||||
| return false; | ||||||||||
| if (leftVoidCount != rightVoidCount) | ||||||||||
| displaceLeft = leftVoidCount > rightVoidCount; | ||||||||||
| return true; | ||||||||||
| } | ||||||||||
|
|
||||||||||
|
|
@@ -149,24 +173,27 @@ private void pruneTargetDelayStates() { | |||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| private boolean shouldDisplaceInCurrentWindow(EntityPlayer target, int currentTick) { | ||||||||||
| if (target == null) return true; | ||||||||||
| private boolean shouldDisplaceInCurrentWindow(Entity target, int currentTick) { | ||||||||||
| if (target == null) | ||||||||||
| return true; | ||||||||||
| int targetId = target.getEntityId(); | ||||||||||
| Integer windowStartTick = targetWindowStartTicks.get(targetId); | ||||||||||
| if (windowStartTick == null || currentTick - windowStartTick >= DISPLACE_WINDOW_TICKS) { | ||||||||||
| targetWindowStartTicks.put(targetId, currentTick); | ||||||||||
| return true; | ||||||||||
| } | ||||||||||
| int delayTicks = msToTicks(properties.getInt(delayProperty, 0)); | ||||||||||
| if (delayTicks <= 0) return true; | ||||||||||
| if (delayTicks <= 0) | ||||||||||
| return true; | ||||||||||
| return currentTick - windowStartTick >= delayTicks; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| private EntityPlayer findClosestTarget(double rangeSq) { | ||||||||||
| EntityPlayer closest = null; | ||||||||||
| double closestDist = rangeSq; | ||||||||||
| for (EntityPlayer player : mc.theWorld.playerEntities) { | ||||||||||
| if (player == mc.thePlayer || player.isDead || player.deathTime != 0) continue; | ||||||||||
| if (player == mc.thePlayer || player.isDead || player.deathTime != 0) | ||||||||||
| continue; | ||||||||||
| double dist = mc.thePlayer.getDistanceSqToEntity(player); | ||||||||||
| if (dist < closestDist) { | ||||||||||
| closestDist = dist; | ||||||||||
|
|
@@ -178,7 +205,8 @@ private EntityPlayer findClosestTarget(double rangeSq) { | |||||||||
|
|
||||||||||
| @SubscribeEvent(priority = EventPriority.HIGH) | ||||||||||
| public void onPrePlayerInput(PrePlayerInputEvent e) { | ||||||||||
| if (!manager.isModuleEnabled(moduleInstance)) return; | ||||||||||
| if (!manager.isModuleEnabled(moduleInstance)) | ||||||||||
| return; | ||||||||||
| if (!active) { | ||||||||||
| compensateNextTick = false; | ||||||||||
| return; | ||||||||||
|
|
@@ -190,16 +218,28 @@ public void onPrePlayerInput(PrePlayerInputEvent e) { | |||||||||
| return; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| if (!displaceThisTick || hasKB) return; | ||||||||||
| if (!anyMovementKey()) return; | ||||||||||
| if (!displaceThisTick || hasKB) | ||||||||||
| return; | ||||||||||
| if (!anyMovementKey()) | ||||||||||
| return; | ||||||||||
|
|
||||||||||
| e.setForward(1); | ||||||||||
| compensateNextTick = true; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| @SubscribeEvent(priority = EventPriority.HIGHEST) | ||||||||||
| public void onAttack(AttackEntityEvent e) { | ||||||||||
| if (e.entityPlayer != mc.thePlayer) | ||||||||||
| return; | ||||||||||
| if (!(e.target instanceof EntityLivingBase)) return; | ||||||||||
| // if (!(e.target instanceof EntityPlayer)) return; | ||||||||||
|
Comment on lines
+234
to
+235
|
||||||||||
| if (!(e.target instanceof EntityLivingBase)) return; | |
| // if (!(e.target instanceof EntityPlayer)) return; | |
| if (!(e.target instanceof EntityPlayer)) | |
| return; |
Copilot
AI
Apr 13, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
onAttack updates module state (attackedLivingEntity) even when the module is disabled or when the client/player context is invalid. Other modules (e.g. HitSelect/MoreKB) guard AttackEntityEvent handlers with manager.isModuleEnabled(...) and Utils.nullCheck(). Add those guards here to avoid stale target state carrying over when toggling the module.
Copilot
AI
Apr 13, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
compensateNextTick compensation can't trigger because it depends on active being true in onPrePlayerInput, but active requires target != null and attackedLivingEntity is always cleared in onPreMotion. Unless AttackEntityEvent fires every tick, the next tick will have active == false and compensateNextTick gets reset, skipping the strafe compensation. Consider keeping the last target for a short window (ticks) or deriving active from keyBindAttack.isKeyDown() while a recent target exists, rather than clearing the target immediately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ChatComponentTextis imported but never used in this class. Please remove the unused import to keep the file clean and avoid warnings.