From b66c2a172dae273f5f3d6e415df47605eca51cb8 Mon Sep 17 00:00:00 2001 From: CJ Burkey Date: Fri, 16 Aug 2024 13:38:08 -0400 Subject: [PATCH] Get flags loading and organize some stuff --- .../com/cjburkey/claimchunk/ClaimChunk.java | 12 +- .../java/com/cjburkey/claimchunk/Utils.java | 2 +- .../cjburkey/claimchunk/access/CCFlags.java | 40 +++++ .../claimchunk/access/CCPermFlags.java | 157 +++++++++--------- .../claimchunk/i18n/V2JsonMessages.java | 4 +- .../cjburkey/claimchunk/PermFlagTests.java | 9 +- 6 files changed, 141 insertions(+), 83 deletions(-) create mode 100644 src/main/java/com/cjburkey/claimchunk/access/CCFlags.java diff --git a/src/main/java/com/cjburkey/claimchunk/ClaimChunk.java b/src/main/java/com/cjburkey/claimchunk/ClaimChunk.java index 2ffade2..a7f685d 100644 --- a/src/main/java/com/cjburkey/claimchunk/ClaimChunk.java +++ b/src/main/java/com/cjburkey/claimchunk/ClaimChunk.java @@ -1,6 +1,7 @@ package com.cjburkey.claimchunk; import com.cjburkey.claimchunk.access.CCInteractClasses; +import com.cjburkey.claimchunk.access.CCPermFlags; import com.cjburkey.claimchunk.api.IClaimChunkPlugin; import com.cjburkey.claimchunk.api.layer.ClaimChunkLayerHandler; import com.cjburkey.claimchunk.chunk.*; @@ -113,6 +114,7 @@ public final class ClaimChunk extends JavaPlugin implements IClaimChunkPlugin { @Getter private ChunkOutlineHandler chunkOutlineHandler; @Getter private CCInteractClasses interactClasses; + @Getter private CCPermFlags permFlags; // Config conversion storage private FromPre0023 fromPre0023; @@ -220,7 +222,15 @@ public void onLoad() { } catch (Exception e) { Utils.warn( "Failed to write classes.yml file. This doesn't really matter, but something" - + " else is probably wrong!"); + + " else is probably wrong!"); + } + + permFlags = new CCPermFlags(); + try { + permFlags.load(new File(getDataFolder(), "flags.yml"), this, "flags.yml"); + Utils.log("Loaded permission flags from flags.yml"); + } catch (Exception e) { + throw new RuntimeException("Failed to load permission flags from flags.yml!", e); } } diff --git a/src/main/java/com/cjburkey/claimchunk/Utils.java b/src/main/java/com/cjburkey/claimchunk/Utils.java index 457ed46..517064a 100644 --- a/src/main/java/com/cjburkey/claimchunk/Utils.java +++ b/src/main/java/com/cjburkey/claimchunk/Utils.java @@ -57,7 +57,7 @@ public static void debug(String msg, Object... data) { || claimChunk != null && claimChunk.getConfigHandler() != null && claimChunk.getConfigHandler().getDebugSpam()) { - getLogger().info(prepMsg("[DEBUG]" + msg, data)); + getLogger().info(prepMsg("[DEBUG] " + msg, data)); } } diff --git a/src/main/java/com/cjburkey/claimchunk/access/CCFlags.java b/src/main/java/com/cjburkey/claimchunk/access/CCFlags.java new file mode 100644 index 0000000..796940c --- /dev/null +++ b/src/main/java/com/cjburkey/claimchunk/access/CCFlags.java @@ -0,0 +1,40 @@ +package com.cjburkey.claimchunk.access; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public final class CCFlags { + + // Generics...gotta love 'em, but feel free to hate them too. + // Methods named such that they may align with record getters :} + public interface IFlagData> { + @NotNull + TypeEnum flagType(); + + @NotNull + FlagData flagData(); + } + + public enum BlockFlagType { + BREAK, + PLACE, + INTERACT, + EXPLODE, + } + + public enum EntityFlagType { + DAMAGE, + INTERACT, + EXPLODE, + } + + public record FlagData(@Nullable List include, @Nullable List exclude) {} + + public record BlockFlagData(@NotNull BlockFlagType flagType, @NotNull FlagData flagData) + implements IFlagData {} + + public record EntityFlagData(@NotNull EntityFlagType flagType, @NotNull FlagData flagData) + implements IFlagData {} +} diff --git a/src/main/java/com/cjburkey/claimchunk/access/CCPermFlags.java b/src/main/java/com/cjburkey/claimchunk/access/CCPermFlags.java index 6944202..2cc133d 100644 --- a/src/main/java/com/cjburkey/claimchunk/access/CCPermFlags.java +++ b/src/main/java/com/cjburkey/claimchunk/access/CCPermFlags.java @@ -6,6 +6,7 @@ import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; @@ -15,6 +16,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.function.BiFunction; /** * Keeps track of loading the permission flags specified in the flags.yml configuration file. @@ -23,8 +25,8 @@ */ public class CCPermFlags { - public final HashMap blockControls = new HashMap<>(); - public final HashMap entityControls = new HashMap<>(); + public final HashMap blockControls = new HashMap<>(); + public final HashMap entityControls = new HashMap<>(); /** * Read the flags defined in the flag definitions file. @@ -37,11 +39,16 @@ public class CCPermFlags { * @param defaultFlagsResource The path to/name of the default flags resource in the plugin jar * file. */ - public void load(File flagsFile, JavaPlugin plugin, String defaultFlagsResource) { + public void load( + @NotNull File flagsFile, + @NotNull JavaPlugin plugin, + @NotNull String defaultFlagsResource) { // Load the flags.yml file while ensuring the default exists YamlConfiguration config = readFlagFile(flagsFile, plugin, defaultFlagsResource); if (config == null) { - throw new RuntimeException("Failed to load flag config file (see ClaimChunk errors)"); + throw new RuntimeException( + "Failed to load flag config file (see ClaimChunk errors; if no errors, try" + + " enabling debugSpam in the config.yml?)"); } loadFromConfig(config); @@ -53,7 +60,7 @@ public void load(File flagsFile, JavaPlugin plugin, String defaultFlagsResource) * * @param config The config file from which to load the user-defined flags. */ - public void loadFromConfig(YamlConfiguration config) { + public void loadFromConfig(@NotNull YamlConfiguration config) { // Read the flag section ConfigurationSection flagSection = config.getConfigurationSection("permissionFlags"); if (flagSection == null) { @@ -78,6 +85,7 @@ public void loadFromConfig(YamlConfiguration config) { "Missing interaction type in one of the flag protection maps in flag" + " \"%s\"", flagName); + continue; } // Check if this is for blocks/entities @@ -88,29 +96,18 @@ public void loadFromConfig(YamlConfiguration config) { "Flag \"%s\" already has block protections defined", flagName); continue; } - - // Get the type of interaction to block - BlockFlagType flagType; - try { - flagType = BlockFlagType.valueOf(interactType); - } catch (Exception ignored) { - Utils.err( - "Unknown block interaction type \"%s\" in flag \"%s\"", - interactType, flagName); + // Ugly generics make this easier I guess + CCFlags.BlockFlagData blockFlagData = + readFlagType( + flagName, + interactType, + flagMap, + CCFlags.BlockFlagData::new, + CCFlags.BlockFlagType.class); + if (blockFlagData == null) { + Utils.err("Failed to load block flag data for flag \"%s\"", flagName); continue; } - - // Get the includes/excludes - FlagData flagData = readIncludeExclude(flagMap); - if (flagData == null) { - Utils.err( - "Failed to load flag includes/excludes from flag \"%s\" for" - + " block protections", - flagName); - } - - // Add the protections - BlockFlagData blockFlagData = new BlockFlagData(flagType, flagData); blockControls.put(flagName, blockFlagData); } case "ENTITIES" -> { @@ -119,29 +116,18 @@ public void loadFromConfig(YamlConfiguration config) { "Flag \"%s\" already has entity protections defined", flagName); continue; } - - // Get the type of interaction to block - EntityFlagType flagType; - try { - flagType = EntityFlagType.valueOf(interactType); - } catch (Exception ignored) { - Utils.err( - "Unknown entity interaction type \"%s\" in flag \"%s\"", - interactType, flagName); + // Ugly generics make this easier I guess + CCFlags.EntityFlagData entityFlagData = + readFlagType( + flagName, + interactType, + flagMap, + CCFlags.EntityFlagData::new, + CCFlags.EntityFlagType.class); + if (entityFlagData == null) { + Utils.err("Failed to load entity flag data for flag \"%s\"", flagName); continue; } - - // Get the includes/excludes - FlagData flagData = readIncludeExclude(flagMap); - if (flagData == null) { - Utils.err( - "Failed to load flag includes/excludes from flag \"%s\" for" - + " entity protections", - flagName); - } - - // Add the protections - EntityFlagData entityFlagData = new EntityFlagData(flagType, flagData); entityControls.put(flagName, entityFlagData); } default -> @@ -161,22 +147,13 @@ public void loadFromConfig(YamlConfiguration config) { } } - // Please don't break :| - @SuppressWarnings("unchecked") - private FlagData readIncludeExclude(Map flagMap) { - try { - return new FlagData( - (List) flagMap.get("include"), (List) flagMap.get("exclude")); - } catch (Exception e) { - Utils.err("Failed to read include/exclude data: %s", e.getMessage()); - } - return null; - } - - private YamlConfiguration readFlagFile( - File flagsFile, JavaPlugin plugin, String defaultFlagsResource) { + private @Nullable YamlConfiguration readFlagFile( + @NotNull File flagsFile, + @NotNull JavaPlugin plugin, + @NotNull String defaultFlagsResource) { if (flagsFile.exists()) { // Just load the config + Utils.debug("Flag file already exists"); return YamlConfiguration.loadConfiguration(flagsFile); } else { // Load the configuration from the defaultFlags.yml file @@ -191,6 +168,7 @@ private YamlConfiguration readFlagFile( "Failed to locate resource at " + defaultFlagsResource), Charsets.UTF_8)); + Utils.debug("Loaded default flags from jar"); } catch (Exception e) { Utils.err( "Failed to load default flag config (Is your file UTF-8?): %s", @@ -202,6 +180,7 @@ private YamlConfiguration readFlagFile( try { ymlConfig.options().copyDefaults(true); ymlConfig.save(flagsFile); + Utils.log("Created new default flags.yml"); } catch (Exception e) { Utils.err("Failed to save default flags file: %s", e.getMessage()); } @@ -209,24 +188,52 @@ private YamlConfiguration readFlagFile( } } - // -- CLASSES -- // + // Generics make this method look like hell, but I just extracted this :) + private static < + FlagTypeEnum extends Enum, + FlagDataType extends CCFlags.IFlagData> + @Nullable FlagDataType readFlagType( + @NotNull String flagName, + @NotNull String interactType, + @NotNull Map flagMap, + @NotNull BiFunction makeFlagData, + @NotNull Class typeEnumClass) { + // Get the type of interaction to block + FlagTypeEnum flagType; + try { + flagType = FlagTypeEnum.valueOf(typeEnumClass, interactType); + } catch (Exception ignored) { + Utils.err( + "Unknown interaction type \"%s\" in flag \"%s\" for %s", + interactType, flagName, typeEnumClass.getName()); + return null; + } - public enum BlockFlagType { - BREAK, - PLACE, - INTERACT, - EXPLODE, - } + // Get the includes/excludes + CCFlags.FlagData flagData = readIncludeExclude(flagMap); + if (flagData == null) { + Utils.err( + "Failed to load flag includes/excludes from flag \"%s\" for %s protections", + flagName, typeEnumClass.getName()); + return null; + } - public enum EntityFlagType { - DAMAGE, - INTERACT, - EXPLODE, + // Add the protections + return makeFlagData.apply(flagType, flagData); } - public record FlagData(@Nullable List include, @Nullable List exclude) {} + // Please don't break :| + @SuppressWarnings("unchecked") + private static @Nullable CCFlags.FlagData readIncludeExclude(@NotNull Map flagMap) { + try { + return new CCFlags.FlagData( + (List) flagMap.get("include"), (List) flagMap.get("exclude")); + } catch (Exception e) { + Utils.err("Failed to read include/exclude data: %s", e.getMessage()); + } + return null; + } - public record BlockFlagData(BlockFlagType flagType, FlagData flagData) {} + // -- CLASSES -- // - public record EntityFlagData(EntityFlagType flagType, FlagData flagData) {} } diff --git a/src/main/java/com/cjburkey/claimchunk/i18n/V2JsonMessages.java b/src/main/java/com/cjburkey/claimchunk/i18n/V2JsonMessages.java index 2f2caa1..deff936 100644 --- a/src/main/java/com/cjburkey/claimchunk/i18n/V2JsonMessages.java +++ b/src/main/java/com/cjburkey/claimchunk/i18n/V2JsonMessages.java @@ -252,7 +252,6 @@ public final class V2JsonMessages { // Argument types public String argTypeBoolTrue = "true"; public String argTypeBoolFalse = "false"; - public String argTypePlayer = "Player"; // PlaceholderAPI public String placeholderApiUnclaimedChunkOwner = "nobody"; @@ -383,7 +382,7 @@ public static BaseComponent replaceLocalizedMsg( String firstPart = input.substring(0, input.indexOf(search)); BaseComponent a = Utils.toComponent(sender, firstPart); - BaseComponent endA = a.getExtra().isEmpty() ? a : a.getExtra().get(a.getExtra().size() - 1); + BaseComponent endA = a.getExtra().isEmpty() ? a : a.getExtra().getLast(); BaseComponent translated = new TranslatableComponent(localized); BaseComponent b = Utils.toComponent(sender, input.substring(firstPart.length() + search.length())); @@ -412,6 +411,7 @@ public static V2JsonMessages load(File file) throws IOException { Utils.err("Failed to load messages.json file!"); Utils.err("This is probably a problem!!"); Utils.err("Here's the error report:"); + //noinspection CallToPrintStackTrace e.printStackTrace(); // Don't overwrite users' files if they don't parse correctly, that's mean. diff --git a/src/test/java/com/cjburkey/claimchunk/PermFlagTests.java b/src/test/java/com/cjburkey/claimchunk/PermFlagTests.java index c25e0af..4a12499 100644 --- a/src/test/java/com/cjburkey/claimchunk/PermFlagTests.java +++ b/src/test/java/com/cjburkey/claimchunk/PermFlagTests.java @@ -2,6 +2,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; +import com.cjburkey.claimchunk.access.CCFlags; import com.cjburkey.claimchunk.access.CCPermFlags; import org.bukkit.configuration.file.YamlConfiguration; @@ -33,11 +34,11 @@ void testLoadFlags() { CCPermFlags permFlags = new CCPermFlags(); permFlags.loadFromConfig(config); - CCPermFlags.BlockFlagData breakBlocks = permFlags.blockControls.get("breakBlocks"); - assertEquals(breakBlocks.flagType(), CCPermFlags.BlockFlagType.BREAK); + CCFlags.BlockFlagData breakBlocks = permFlags.blockControls.get("breakBlocks"); + assertEquals(breakBlocks.flagType(), CCFlags.BlockFlagType.BREAK); - CCPermFlags.EntityFlagData damageEntities = permFlags.entityControls.get("damageEntities"); - assertEquals(damageEntities.flagType(), CCPermFlags.EntityFlagType.DAMAGE); + CCFlags.EntityFlagData damageEntities = permFlags.entityControls.get("damageEntities"); + assertEquals(damageEntities.flagType(), CCFlags.EntityFlagType.DAMAGE); assert Objects.requireNonNull( permFlags.blockControls.get("redstone").flagData().include(),