Skip to content

Commit

Permalink
Get flags loading and organize some stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
cjburkey01 committed Aug 16, 2024
1 parent f74cf47 commit b66c2a1
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 83 deletions.
12 changes: 11 additions & 1 deletion src/main/java/com/cjburkey/claimchunk/ClaimChunk.java
Original file line number Diff line number Diff line change
@@ -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.*;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/cjburkey/claimchunk/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}

Expand Down
40 changes: 40 additions & 0 deletions src/main/java/com/cjburkey/claimchunk/access/CCFlags.java
Original file line number Diff line number Diff line change
@@ -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<TypeEnum extends Enum<?>> {
@NotNull
TypeEnum flagType();

@NotNull
FlagData flagData();
}

public enum BlockFlagType {
BREAK,
PLACE,
INTERACT,
EXPLODE,
}

public enum EntityFlagType {
DAMAGE,
INTERACT,
EXPLODE,
}

public record FlagData(@Nullable List<String> include, @Nullable List<String> exclude) {}

public record BlockFlagData(@NotNull BlockFlagType flagType, @NotNull FlagData flagData)
implements IFlagData<BlockFlagType> {}

public record EntityFlagData(@NotNull EntityFlagType flagType, @NotNull FlagData flagData)
implements IFlagData<EntityFlagType> {}
}
157 changes: 82 additions & 75 deletions src/main/java/com/cjburkey/claimchunk/access/CCPermFlags.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
Expand All @@ -23,8 +25,8 @@
*/
public class CCPermFlags {

public final HashMap<String, BlockFlagData> blockControls = new HashMap<>();
public final HashMap<String, EntityFlagData> entityControls = new HashMap<>();
public final HashMap<String, CCFlags.BlockFlagData> blockControls = new HashMap<>();
public final HashMap<String, CCFlags.EntityFlagData> entityControls = new HashMap<>();

/**
* Read the flags defined in the flag definitions file.
Expand All @@ -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);
Expand All @@ -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) {
Expand All @@ -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
Expand All @@ -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" -> {
Expand All @@ -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 ->
Expand All @@ -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<String>) flagMap.get("include"), (List<String>) 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
Expand All @@ -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",
Expand All @@ -202,31 +180,60 @@ 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());
}
return ymlConfig;
}
}

// -- CLASSES -- //
// Generics make this method look like hell, but I just extracted this :)
private static <
FlagTypeEnum extends Enum<FlagTypeEnum>,
FlagDataType extends CCFlags.IFlagData<FlagTypeEnum>>
@Nullable FlagDataType readFlagType(
@NotNull String flagName,
@NotNull String interactType,
@NotNull Map<?, ?> flagMap,
@NotNull BiFunction<FlagTypeEnum, CCFlags.FlagData, FlagDataType> makeFlagData,
@NotNull Class<FlagTypeEnum> 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<String> include, @Nullable List<String> exclude) {}
// Please don't break :|
@SuppressWarnings("unchecked")
private static @Nullable CCFlags.FlagData readIncludeExclude(@NotNull Map<?, ?> flagMap) {
try {
return new CCFlags.FlagData(
(List<String>) flagMap.get("include"), (List<String>) 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) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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()));
Expand Down Expand Up @@ -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.
Expand Down
9 changes: 5 additions & 4 deletions src/test/java/com/cjburkey/claimchunk/PermFlagTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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(),
Expand Down

0 comments on commit b66c2a1

Please sign in to comment.