fix config loading, add arraylist module info
- fullbright no longer crashes during config load (mc.options is null while the game is still starting, which aborted loading every module registered after fullbright - including killaura's keybind) - one broken module no longer aborts loading the rest - fix "is a directory" IOException on every startup (commandmanager had no file name, so it resolved to the config folder itself) - arraylist: alignment/sort options, module info shown on the opposite side of the row, hides hud/disabled modules behind settings - killaura: show target name as module info
This commit is contained in:
@@ -19,21 +19,25 @@ public class KillAuraModule extends Module {
|
||||
private final Setting<Boolean> onlyWeapon = bool("OnlyWeapon", false);
|
||||
private final Setting<Boolean> sync = bool("MovementSync", false);
|
||||
|
||||
private String targetName;
|
||||
|
||||
public KillAuraModule() {
|
||||
super("KillAura", "Attacks nearby players.", Category.COMBAT);
|
||||
}
|
||||
|
||||
@Subscribe public void onPreTick(TickEvent.Pre event) {
|
||||
Player target = findPlayerTarget();
|
||||
this.targetName = target == null ? null : target.getScoreboardName();
|
||||
|
||||
if (target == null)
|
||||
return;
|
||||
|
||||
if (isOnCooldown())
|
||||
return;
|
||||
|
||||
if (onlyWeapon.getValue() && !isHoldingWeapon())
|
||||
return;
|
||||
|
||||
Player target = findPlayerTarget();
|
||||
if (target == null)
|
||||
return;
|
||||
|
||||
Angles angles = Angles.entity(target);
|
||||
int priority = 0;
|
||||
|
||||
@@ -74,4 +78,14 @@ public class KillAuraModule extends Module {
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
targetName = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayInfo() {
|
||||
return targetName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
package cc.fros.features.modules.hud;
|
||||
|
||||
import cc.fros.Fros;
|
||||
import cc.fros.event.impl.render.Render2DEvent;
|
||||
import cc.fros.features.modules.client.HudModule;
|
||||
import cc.fros.features.modules.Module;
|
||||
import cc.fros.features.settings.Setting;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class ArrayListHudModule extends HudModule {
|
||||
private static final int DISABLED_COLOR = 0xFF555555;
|
||||
private static final int BRACKET_COLOR = 0xFFAAAAAA;
|
||||
private static final int GAP = 4;
|
||||
|
||||
public final Setting<Align> alignment = mode("Alignment", Align.RIGHT);
|
||||
public final Setting<Sort> sort = mode("Sort", Sort.LENGTH);
|
||||
public final Setting<Boolean> disabled = bool("Disabled", false);
|
||||
public final Setting<Boolean> hudModules = bool("HudModules", false);
|
||||
|
||||
public ArrayListHudModule() {
|
||||
super("ArrayList", "Display modules and their state", 100, 10);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void render(Render2DEvent e) {
|
||||
super.render(e);
|
||||
|
||||
List<Module> shown = Fros.moduleManager.getModules().stream()
|
||||
.filter(module -> !module.hidden)
|
||||
.filter(module -> module.getCategory() != Module.Category.HUD || hudModules.getValue())
|
||||
.filter(module -> module.isEnabled() || disabled.getValue())
|
||||
.sorted(comparator())
|
||||
.toList();
|
||||
|
||||
if (shown.isEmpty()) return;
|
||||
|
||||
float x = getX();
|
||||
float y = getY();
|
||||
int lineHeight = mc.font.lineHeight;
|
||||
int color = Fros.colorManager.getColorAsInt();
|
||||
boolean right = alignment.getValue() == Align.RIGHT;
|
||||
int widest = 0;
|
||||
|
||||
for (Module module : shown) {
|
||||
widest = Math.max(widest, width(module));
|
||||
}
|
||||
|
||||
for (int i = 0; i < shown.size(); i++) {
|
||||
Module module = shown.get(i);
|
||||
String name = module.getDisplayName();
|
||||
String info = module.getDisplayInfo();
|
||||
boolean on = module.isEnabled();
|
||||
|
||||
int rowY = (int) (y + i * lineHeight);
|
||||
int baseColor = on ? color : DISABLED_COLOR;
|
||||
|
||||
// name sits on the alignment side
|
||||
int nameX = (int) (right ? x + widest - mc.font.width(name) : x);
|
||||
e.getContext().drawString(mc.font, name, nameX, rowY, baseColor);
|
||||
|
||||
if (info != null) {
|
||||
// info sits on the opposite side of the row
|
||||
int blockWidth = infoWidth(info);
|
||||
int infoX = (int) (right ? x : x + widest - blockWidth);
|
||||
int bracketColor = on ? BRACKET_COLOR : DISABLED_COLOR;
|
||||
|
||||
e.getContext().drawString(mc.font, " [", infoX, rowY, bracketColor);
|
||||
infoX += mc.font.width(" [");
|
||||
e.getContext().drawString(mc.font, info, infoX, rowY, on ? -1 : DISABLED_COLOR);
|
||||
infoX += mc.font.width(info);
|
||||
e.getContext().drawString(mc.font, "]", infoX, rowY, bracketColor);
|
||||
}
|
||||
}
|
||||
|
||||
setWidth(widest);
|
||||
setHeight(lineHeight * shown.size());
|
||||
}
|
||||
|
||||
private int width(Module module) {
|
||||
int width = mc.font.width(module.getDisplayName());
|
||||
String info = module.getDisplayInfo();
|
||||
if (info != null) {
|
||||
width += GAP + infoWidth(info);
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
private int infoWidth(String info) {
|
||||
return mc.font.width(" [") + mc.font.width(info) + mc.font.width("]");
|
||||
}
|
||||
|
||||
private Comparator<Module> comparator() {
|
||||
return switch (sort.getValue()) {
|
||||
case LENGTH -> Comparator.comparingInt((Module module) ->
|
||||
module.getDisplayName().length()).reversed();
|
||||
case ALPHABETICAL -> Comparator.comparing(module ->
|
||||
module.getDisplayName().toLowerCase(Locale.ROOT));
|
||||
case NONE -> (first, second) -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
public enum Align {
|
||||
LEFT,
|
||||
RIGHT
|
||||
}
|
||||
|
||||
public enum Sort {
|
||||
LENGTH,
|
||||
ALPHABETICAL,
|
||||
NONE
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ public class FullbrightModule extends Module {
|
||||
|
||||
private Mode activeMode = Mode.GAMMA;
|
||||
private double previousGamma;
|
||||
private boolean gammaCaptured;
|
||||
private boolean hadNightVision;
|
||||
|
||||
public FullbrightModule() {
|
||||
@@ -52,16 +53,28 @@ public class FullbrightModule extends Module {
|
||||
|
||||
private void prepare(Mode newMode) {
|
||||
if (newMode == Mode.GAMMA) {
|
||||
previousGamma = mc.options.gamma().get();
|
||||
gammaCaptured = false;
|
||||
// during config load mc.options is still null, so this can be a no-op;
|
||||
// applyGamma() captures lazily on the first real tick instead
|
||||
captureGamma();
|
||||
return;
|
||||
}
|
||||
hadNightVision = !nullCheck() && mc.player.hasEffect(MobEffects.NIGHT_VISION);
|
||||
}
|
||||
|
||||
private void captureGamma() {
|
||||
if (gammaCaptured || mc.options == null) return;
|
||||
previousGamma = mc.options.gamma().get();
|
||||
gammaCaptured = true;
|
||||
}
|
||||
|
||||
private void restore(Mode oldMode) {
|
||||
if (oldMode == Mode.GAMMA) {
|
||||
// bypass OptionInstance#set, which rejects values outside [0.0, 1.0]
|
||||
mc.options.gamma().value = previousGamma;
|
||||
if (gammaCaptured && mc.options != null) {
|
||||
// bypass OptionInstance#set, which rejects values outside [0.0, 1.0]
|
||||
mc.options.gamma().value = previousGamma;
|
||||
}
|
||||
gammaCaptured = false;
|
||||
return;
|
||||
}
|
||||
if (!nullCheck() && !hadNightVision) {
|
||||
@@ -70,6 +83,8 @@ public class FullbrightModule extends Module {
|
||||
}
|
||||
|
||||
private void applyGamma() {
|
||||
if (mc.options == null) return;
|
||||
captureGamma();
|
||||
mc.options.gamma().value = gamma.getValue();
|
||||
}
|
||||
|
||||
|
||||
@@ -111,4 +111,9 @@ public class CommandManager extends Feature implements Jsonable {
|
||||
setCommandPrefix(object.get("prefix").getAsString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileName() {
|
||||
return "commands.json";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,9 @@ public class ConfigManager {
|
||||
mkdirs();
|
||||
for (Jsonable jsonable : jsonables) {
|
||||
Path path = FROS_PATH.resolve(jsonable.getFileName());
|
||||
if (!Files.exists(path)) continue;
|
||||
// isRegularFile, not exists: a Jsonable with no file name resolves to the
|
||||
// config directory itself, and readString on a directory throws IOException
|
||||
if (!Files.isRegularFile(path)) continue;
|
||||
try {
|
||||
String read = Files.readString(path);
|
||||
jsonable.fromJson(JsonParser.parseString(read));
|
||||
@@ -51,6 +53,7 @@ public class ConfigManager {
|
||||
try {
|
||||
JsonElement json = jsonable.toJson();
|
||||
Path path = FROS_PATH.resolve(jsonable.getFileName());
|
||||
if (Files.isDirectory(path)) continue;
|
||||
Files.writeString(path, GSON.toJson(json));
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Failed to write to file", e);
|
||||
|
||||
@@ -17,6 +17,7 @@ import cc.fros.features.modules.client.NotificationsModule;
|
||||
import cc.fros.features.modules.combat.KillAuraModule;
|
||||
import cc.fros.features.modules.combat.CriticalsModule;
|
||||
import cc.fros.features.modules.combat.KeyPearlModule;
|
||||
import cc.fros.features.modules.hud.ArrayListHudModule;
|
||||
import cc.fros.features.modules.hud.CoordinatesHudModule;
|
||||
import cc.fros.features.modules.hud.FpsHudModule;
|
||||
import cc.fros.features.modules.hud.PingHudModule;
|
||||
@@ -48,6 +49,7 @@ public class ModuleManager implements Jsonable, Util {
|
||||
private final List<Module> modules = new ArrayList<>();
|
||||
|
||||
public void init() {
|
||||
register(new ArrayListHudModule());
|
||||
register(new WatermarkHudModule());
|
||||
register(new CoordinatesHudModule());
|
||||
register(new FpsHudModule());
|
||||
@@ -165,8 +167,14 @@ public class ModuleManager implements Jsonable, Util {
|
||||
|
||||
@Override
|
||||
public void fromJson(JsonElement element) {
|
||||
if (element == null || !element.isJsonObject()) return;
|
||||
for (Module module : getModules()) {
|
||||
module.fromJson(element.getAsJsonObject().get(module.getName()));
|
||||
// one broken module must never abort loading the rest
|
||||
try {
|
||||
module.fromJson(element.getAsJsonObject().get(module.getName()));
|
||||
} catch (Throwable throwable) {
|
||||
LOGGER.error("Failed to load module {}", module.getName(), throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user