Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ spotless {
// The third and remaining stems are optional, allowing matching lines with only two stems (in this case "skyblocker.config"), and separating it from other keys that start with "skyblocker.config.[whatever]".
/^( "skyblocker\.config(?:\.([^."]++)(?:\.[^"]++)?)?": "(?:[^\\"]++|\\.)*+",)$\n^(?= "skyblocker\.config\.(?!\2[."]))/,
'$1\n\n'
final List<String> excludeCategories = ["debug", "eventNotifications", "quickNav", "shortcutToKeybindsSettings", "title"]
final List<String> excludeCategories = ["commands", "debug", "eventNotifications", "quickNav", "shortcutToKeybindsSettings", "title"]
final String excludeCategoriesLookahead = /(?!(?:${excludeCategories.join('|')})(?=[."]))/
replaceRegex \
"Separate different fouth stems if the first three stems are skyblocker.config.[configCategory]",
Expand Down
17 changes: 1 addition & 16 deletions src/main/java/de/hysky/skyblocker/DisableAll.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
*/
public class DisableAll {
private static final Logger LOGGER = LogUtils.getLogger();
private static final String CONFIGS_PACKAGE = "de.hysky.skyblocker.config.configs";

@Init
public static void init() {
Expand Down Expand Up @@ -95,23 +94,9 @@ private static void disableBooleans(Object target) throws IllegalAccessException
m.put(entry.getKey(), Boolean.FALSE);
}
}
} else if (value != null && isConfigClass(type)) {
} else if (value != null && SkyblockerConfigManager.isConfigClass(type)) {
disableBooleans(value);
}
}
}

/**
* Returns {@code true} if the given class represents one of our config
* classes. This prevents {@link #disableBooleans(Object)} from touching
* unrelated objects from other mods.
*/
private static boolean isConfigClass(Class<?> clazz) {
return !clazz.isPrimitive()
&& !clazz.isEnum()
&& !clazz.isRecord()
&& !clazz.equals(String.class)
&& !Number.class.isAssignableFrom(clazz)
&& clazz.getPackageName().startsWith(CONFIGS_PACKAGE);
}
}
77 changes: 77 additions & 0 deletions src/main/java/de/hysky/skyblocker/config/ConfigCommands.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package de.hysky.skyblocker.config;

import com.mojang.brigadier.Command;
import com.mojang.brigadier.arguments.BoolArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import de.hysky.skyblocker.utils.Constants;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument;
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;

public class ConfigCommands {
static void registerConfigEntries(LiteralArgumentBuilder<FabricClientCommandSource> builder) {
try {
registerConfigEntries(builder, SkyblockerConfigManager.get());
} catch (Exception e) {
SkyblockerConfigManager.LOGGER.error("[Skyblocker Config Manager] Failed to register config entries command!", e);
}
}

private static LiteralArgumentBuilder<FabricClientCommandSource> registerConfigEntries(LiteralArgumentBuilder<FabricClientCommandSource> builder, Object object) throws IllegalAccessException {
for (Field field : object.getClass().getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers())) continue;
field.setAccessible(true);

Class<?> type = field.getType();
String name = field.getName();
Object value = field.get(object);

if (type == boolean.class) {
builder.then(registerBooleanConfigEntry(field, object, name));
} else if (value != null && SkyblockerConfigManager.isConfigClass(type)) {
builder.then(registerConfigEntries(literal(name), value));
}
}

return builder;
}

private static LiteralArgumentBuilder<FabricClientCommandSource> registerBooleanConfigEntry(Field field, Object object, String name) {
return literal(name).then(argument("value", BoolArgumentType.bool()).executes(context -> {
SkyblockerConfigManager.update(config -> {
try {
boolean value = BoolArgumentType.getBool(context, "value");
field.setBoolean(object, value);
context.getSource().sendFeedback(Constants.PREFIX.get().append(Component.translatable("skyblocker.config.commands.set", name, value).withStyle(ChatFormatting.GREEN)));
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
});
return Command.SINGLE_SUCCESS;
})).then(literal("toggle").executes(context -> {
SkyblockerConfigManager.update(config -> {
try {
boolean toggled = !field.getBoolean(object);
field.setBoolean(object, toggled);
context.getSource().sendFeedback(Constants.PREFIX.get().append(Component.translatable("skyblocker.config.commands.set", name, toggled).withStyle(ChatFormatting.GREEN)));
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
});
return Command.SINGLE_SUCCESS;
})).executes(context -> {
try {
context.getSource().sendFeedback(Constants.PREFIX.get().append(Component.translatable("skyblocker.config.commands.query", name, field.getBoolean(object)).withStyle(ChatFormatting.GREEN)));
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
return Command.SINGLE_SUCCESS;
});
}
}
47 changes: 15 additions & 32 deletions src/main/java/de/hysky/skyblocker/config/ConfigNullFieldsFix.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package de.hysky.skyblocker.config;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Map;

import org.slf4j.Logger;

Expand All @@ -16,49 +14,34 @@
*/
public class ConfigNullFieldsFix {
private static final Logger LOGGER = LogUtils.getLogger();
private static final String CONFIGS_PACKAGE = "de.hysky.skyblocker.config.configs";

@SuppressWarnings("removal")
public static void init() {
SkyblockerConfig current = SkyblockerConfigManager.get();
SkyblockerConfig clean = new SkyblockerConfig();

try {
fixNullFields(current, clean);
SkyblockerConfigManager.save();
} catch (Exception e) {
LOGGER.error("[Skyblocker Config Null Fields Fixer] Failed to ensure that the config has no null fields! You may encounter crashes :(", e);
}
SkyblockerConfigManager.update(config -> {
try {
fixNullFields(config, new SkyblockerConfig());
} catch (Exception e) {
LOGGER.error("[Skyblocker Config Null Fields Fixer] Failed to ensure that the config has no null fields! You may encounter crashes :(", e);
}
});
}

/**
* Traverse through every config field to ensure that is isn't null, if it is then reset the value.
*/
private static void fixNullFields(Object target, Object source) throws Exception {
for (Field field : target.getClass().getDeclaredFields()) {
private static void fixNullFields(Object config, Object defaultConfig) throws Exception {
for (Field field : config.getClass().getDeclaredFields()) {
if (field.isAnnotationPresent(SerialEntry.class)) {
field.setAccessible(true);

Object targetValue = field.get(target);
Object sourceValue = field.get(source);
Object configValue = field.get(config);
Object defaultValue = field.get(defaultConfig);

if (targetValue == null && sourceValue != null) {
field.set(target, sourceValue);
} else if (targetValue != null && sourceValue != null && isFixable(field.getType())) {
fixNullFields(targetValue, sourceValue);
if (configValue == null && defaultValue != null) {
field.set(config, defaultValue);
} else if (configValue != null && defaultValue != null && SkyblockerConfigManager.isConfigClass(field.getType())) {
fixNullFields(configValue, defaultValue);
}
}
}
}

private static boolean isFixable(Class<?> clazz) {
return !clazz.isPrimitive()
&& !clazz.isEnum()
&& !clazz.isRecord()
&& !clazz.equals(String.class)
&& !Number.class.isAssignableFrom(clazz)
&& !Map.class.isAssignableFrom(clazz)
&& !Collection.class.isAssignableFrom(clazz)
&& clazz.getPackageName().startsWith(CONFIGS_PACKAGE);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package de.hysky.skyblocker.config;

import com.mojang.brigadier.arguments.StringArgumentType;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.logging.LogUtils;
import de.hysky.skyblocker.SkyblockerMod;
Expand Down Expand Up @@ -42,22 +42,25 @@
import net.minecraft.network.chat.Component;
import org.apache.commons.lang3.function.Consumers;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.lang.StackWalker.Option;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.UnaryOperator;

import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument;
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
import org.slf4j.Logger;

public class SkyblockerConfigManager {
public static final int CONFIG_VERSION = 6;
private static final Logger LOGGER = LogUtils.getLogger();
static final Logger LOGGER = LogUtils.getLogger();
private static final String CONFIGS_PACKAGE = "de.hysky.skyblocker.config.configs";
private static final Path CONFIG_DIR = FabricLoader.getInstance().getConfigDir();
private static final Path CONFIG_FILE = CONFIG_DIR.resolve("skyblocker.json");
private static final ConfigManager<SkyblockerConfig> CONFIG_MANAGER = ConfigManager.create(SkyblockerConfig.class, CONFIG_FILE, UnaryOperator.identity());
Expand Down Expand Up @@ -103,7 +106,7 @@ public static void update(Consumer<SkyblockerConfig> action) {
CONFIG_MANAGER.save();
}

public static Screen createGUI(Screen parent) {
public static Screen createGUI(@Nullable Screen parent) {
return createGUI(parent, "");
}

Expand Down Expand Up @@ -150,8 +153,27 @@ public static void reload() {
* @return the command builder
*/
private static LiteralArgumentBuilder<FabricClientCommandSource> configLiteral(String name) {
return literal(name).executes(Scheduler.queueOpenScreenCommand(() -> createGUI(null)))
LiteralArgumentBuilder<FabricClientCommandSource> builder = literal(name).executes(Scheduler.queueOpenScreenCommand(() -> createGUI(null)))
.then(argument("option", StringArgumentType.greedyString()).executes((ctx) -> Scheduler.queueOpenScreen(createGUI(null, ctx.getArgument("option", String.class)))));
ConfigCommands.registerConfigEntries(builder);
return builder;
}

/**
* Returns {@code true} if the given class represents one of our config
* classes. This prevents {@link de.hysky.skyblocker.DisableAll#disableBooleans(Object)} from touching
* unrelated objects from other mods.
*/
@SuppressWarnings("JavadocReference")
public static boolean isConfigClass(Class<?> clazz) {
return !clazz.isPrimitive()
&& !clazz.isEnum()
&& !clazz.isRecord()
&& !clazz.equals(String.class)
&& !Number.class.isAssignableFrom(clazz)
&& !Map.class.isAssignableFrom(clazz)
&& !Collection.class.isAssignableFrom(clazz)
&& clazz.getPackageName().startsWith(CONFIGS_PACKAGE);
}

public static void dataFix(Path configDir, Path backupDir) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ public static boolean isLocked(int slot) {

public static void handleInputEvents(LocalPlayer player) {
while (hotbarSlotLock.consumeClick()) {
List<Integer> lockedSlots = SkyblockerConfigManager.get().general.lockedSlots;
int selected = player.getInventory().getSelectedSlot();
if (!isLocked(player.getInventory().getSelectedSlot())) lockedSlots.add(selected);
else lockedSlots.remove(Integer.valueOf(selected));
SkyblockerConfigManager.save();
SkyblockerConfigManager.update(config -> {
List<Integer> lockedSlots = config.general.lockedSlots;
if (!lockedSlots.contains(selected)) lockedSlots.add(selected);
else lockedSlots.remove(Integer.valueOf(selected));
});
}
}
}
48 changes: 24 additions & 24 deletions src/main/java/de/hysky/skyblocker/skyblock/item/ItemProtection.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,17 @@ private static int protectMyItem(FabricClientCommandSource source) {
String itemUuid = heldItem.getUuid();

if (!itemUuid.isEmpty()) {
ObjectOpenHashSet<String> protectedItems = SkyblockerConfigManager.get().general.protectedItems;

if (!protectedItems.contains(itemUuid)) {
protectedItems.add(itemUuid);
SkyblockerConfigManager.save();
source.sendFeedback(Constants.PREFIX.get().append(Component.translatable("skyblocker.itemProtection.added", heldItem.getHoverName())));
} else {
protectedItems.remove(itemUuid);
SkyblockerConfigManager.save();
source.sendFeedback(Constants.PREFIX.get().append(Component.translatable("skyblocker.itemProtection.removed", heldItem.getHoverName())));
}
SkyblockerConfigManager.update(config -> {
ObjectOpenHashSet<String> protectedItems = config.general.protectedItems;

if (!protectedItems.contains(itemUuid)) {
protectedItems.add(itemUuid);
source.sendFeedback(Constants.PREFIX.get().append(Component.translatable("skyblocker.itemProtection.added", heldItem.getHoverName())));
} else {
protectedItems.remove(itemUuid);
source.sendFeedback(Constants.PREFIX.get().append(Component.translatable("skyblocker.itemProtection.removed", heldItem.getHoverName())));
}
});
} else {
source.sendFeedback(Constants.PREFIX.get().append(Component.translatable("skyblocker.itemProtection.noItemUuid")));
}
Expand Down Expand Up @@ -105,21 +105,21 @@ public static void handleKeyPressed(ItemStack heldItem) {

String itemUuid = heldItem.getUuid();
if (!itemUuid.isEmpty()) {
ObjectOpenHashSet<String> protectedItems = SkyblockerConfigManager.get().general.protectedItems;
SkyblockerConfigManager.update(config -> {
ObjectOpenHashSet<String> protectedItems = config.general.protectedItems;

if (!protectedItems.contains(itemUuid)) {
protectedItems.add(itemUuid);
SkyblockerConfigManager.save();
if (notifyConfiguration) {
playerEntity.displayClientMessage(Constants.PREFIX.get().append(Component.translatable("skyblocker.itemProtection.added", heldItem.getHoverName())), false);
}
} else {
protectedItems.remove(itemUuid);
SkyblockerConfigManager.save();
if (notifyConfiguration) {
playerEntity.displayClientMessage(Constants.PREFIX.get().append(Component.translatable("skyblocker.itemProtection.removed", heldItem.getHoverName())), false);
if (!protectedItems.contains(itemUuid)) {
protectedItems.add(itemUuid);
if (notifyConfiguration) {
playerEntity.displayClientMessage(Constants.PREFIX.get().append(Component.translatable("skyblocker.itemProtection.added", heldItem.getHoverName())), false);
}
} else {
protectedItems.remove(itemUuid);
if (notifyConfiguration) {
playerEntity.displayClientMessage(Constants.PREFIX.get().append(Component.translatable("skyblocker.itemProtection.removed", heldItem.getHoverName())), false);
}
}
}
});
} else {
playerEntity.displayClientMessage(Constants.PREFIX.get().append(Component.translatable("skyblocker.itemProtection.noItemUuid")), false);
}
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/assets/skyblocker/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@
"skyblocker.config.chat.skyblockXpMessages": "SkyBlock XP Messages",
"skyblocker.config.chat.skyblockXpMessages.@Tooltip": "Notifies you in the chat when you gain SkyBlock XP.",

"skyblocker.config.commands.query": "Option '%s' is currently set to %s",
"skyblocker.config.commands.set": "Option '%s' is now set to %s",

"skyblocker.config.crimsonIsle": "Crimson Isle",

"skyblocker.config.crimsonIsle.extendNetherFog": "Extend Nether Fog",
Expand Down