1
mirror of https://github.com/StarWishsama/Slimefun4.git synced 2024-09-20 03:35:51 +00:00

Added documentation

This commit is contained in:
TheBusyBiscuit 2020-09-07 03:12:31 +02:00
parent 06498e3f63
commit b09c4af900
2 changed files with 141 additions and 15 deletions

View File

@ -13,30 +13,85 @@ import org.bukkit.Tag;
import io.github.thebusybiscuit.slimefun4.api.exceptions.TagMisconfigurationException;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.CropGrowthAccelerator;
import io.github.thebusybiscuit.slimefun4.implementation.items.tools.ClimbingPick;
import io.github.thebusybiscuit.slimefun4.implementation.items.tools.ExplosiveShovel;
import io.github.thebusybiscuit.slimefun4.implementation.items.tools.PickaxeOfTheSeeker;
/**
* This enum contains various implementations of the {@link Tag} interface.
* Most of them serve some purpose within Slimefun's implementation, some are just pure
* extensions of the default Minecraft tags.
* The actual tag files are located in the {@literal /src/main/resources/tags} directory
* and follow Minecraft's tags.json format.
*
* @author TheBusyBiscuit
*
*/
public enum SlimefunTag implements Tag<Material> {
/**
* Materials which are sensitive to break.
* Things like Saplings or Pressure plates which break as well when you break
* the block beneath them.
*/
SENSITIVE_MATERIALS,
// Expanding upon Minecraft's tags:
/**
* Minecraft ores.
*/
ORES,
/**
* All terracotta variants, does not include glazed terracotta.
*/
TERRACOTTA,
/**
* All ice variants, normal, packed, blue and whatever else there is.
*/
ICE_VARIANTS,
/**
* All stone variants, normal, andesite, diorite, granite and whatever else may come.
*/
STONE_VARIANTS,
/**
* All variants of concrete powder.
* Can you believe there is no tag for this already?
*/
CONCRETE_POWDERS,
// Actual Slimefun tags:
/**
* All materials which the {@link ExplosiveShovel} can break.
*/
EXPLOSIVE_SHOVEL_BLOCKS,
/**
* All materials (ores) which the {@link PickaxeOfTheSeeker} recognizes.
*/
PICKAXE_OF_VEIN_MINING_BLOCKS,
/**
* All materials (crops) which the {@link CropGrowthAccelerator} will recognize.
*/
CROP_GROWTH_ACCELERATOR_BLOCKS,
/**
* All materials which the {@link ClimbingPick} is able to climb.
*/
CLIMBING_PICK_SURFACES;
private final NamespacedKey key;
private final Set<Material> includedMaterials = new HashSet<>();
private final Set<Tag<Material>> additionalTags = new HashSet<>();
/**
* This constructs a new {@link SlimefunTag}.
* The {@link NamespacedKey} will be automatically inferred using
* {@link SlimefunPlugin} and {@link #name()}.
*/
SlimefunTag() {
key = new NamespacedKey(SlimefunPlugin.instance(), name().toLowerCase(Locale.ROOT));
}
@ -48,7 +103,7 @@ public enum SlimefunTag implements Tag<Material> {
* This is thrown whenever a {@link SlimefunTag} could not be parsed properly
*/
public void reload() throws TagMisconfigurationException {
new TagParser(this).parse((materials, tags) -> {
new TagParser(this).parse(this, (materials, tags) -> {
this.includedMaterials.clear();
this.includedMaterials.addAll(materials);
@ -98,6 +153,14 @@ public enum SlimefunTag implements Tag<Material> {
}
}
/**
* This returns a {@link Set} of {@link Tag Tags} which are children of this {@link SlimefunTag},
* these can be other {@link SlimefunTag SlimefunTags} or regular {@link Tag Tags}.
*
* <strong>The returned {@link Set} is immutable</strong>
*
* @return An immutable {@link Set} of all sub tags.
*/
@Nonnull
public Set<Tag<Material>> getSubTags() {
return Collections.unmodifiableSet(additionalTags);

View File

@ -13,6 +13,7 @@ import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Keyed;
import org.bukkit.Material;
@ -30,22 +31,69 @@ import io.github.thebusybiscuit.slimefun4.api.exceptions.TagMisconfigurationExce
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
class TagParser implements Keyed {
/**
* The {@link TagParser} is responsible for parsing a JSON input into a {@link SlimefunTag}.
*
* @author TheBusyBiscuit
*
*/
public class TagParser implements Keyed {
private final NamespacedKey key;
TagParser(@Nonnull SlimefunTag tag) {
this.key = tag.getKey();
/**
* This constructs a new {@link TagParser}.
*
* @param key
* The {@link NamespacedKey} of the resulting {@link SlimefunTag}
*/
public TagParser(@Nonnull NamespacedKey key) {
this.key = key;
}
void parse(@Nonnull BiConsumer<Set<Material>, Set<Tag<Material>>> callback) throws TagMisconfigurationException {
Set<Material> materials = new HashSet<>();
Set<Tag<Material>> tags = new HashSet<>();
/**
* This constructs a new {@link TagParser} for the given {@link SlimefunTag}
*
* @param tag
* The {@link SlimefunTag} to parse inputs for
*/
TagParser(@Nonnull SlimefunTag tag) {
this(tag.getKey());
}
JsonParser parser = new JsonParser();
void parse(@Nonnull SlimefunTag tag, @Nonnull BiConsumer<Set<Material>, Set<Tag<Material>>> callback) throws TagMisconfigurationException {
String path = "/tags/" + tag.getKey().getKey() + ".json";
try (BufferedReader reader = new BufferedReader(new InputStreamReader(SlimefunPlugin.class.getResourceAsStream("/tags/" + key.getKey() + ".json"), StandardCharsets.UTF_8))) {
JsonObject root = parser.parse(reader.lines().collect(Collectors.joining(""))).getAsJsonObject();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(SlimefunPlugin.class.getResourceAsStream(path), StandardCharsets.UTF_8))) {
parse(reader.lines().collect(Collectors.joining("")), callback);
}
catch (IOException x) {
throw new TagMisconfigurationException(key, x.getMessage());
}
}
/**
* This will parse the given JSON {@link String} and run the provided callback with {@link Set Sets} of
* matched {@link Material Materials} and {@link Tag Tags}.
*
* @param json
* The JSON {@link String} to parse
* @param callback
* A callback to run after successfully parsing the input
*
* @throws TagMisconfigurationException
* This is thrown whenever the given input is malformed or no adequate
* {@link Material} or {@link Tag} could be found
*/
public void parse(@Nonnull String json, @Nonnull BiConsumer<Set<Material>, Set<Tag<Material>>> callback) throws TagMisconfigurationException {
Validate.notNull(json, "Cannot parse a null String");
try {
Set<Material> materials = new HashSet<>();
Set<Tag<Material>> tags = new HashSet<>();
JsonParser parser = new JsonParser();
JsonObject root = parser.parse(json).getAsJsonObject();
JsonElement child = root.get("values");
if (child instanceof JsonArray) {
@ -53,9 +101,12 @@ class TagParser implements Keyed {
for (JsonElement element : values) {
if (element instanceof JsonPrimitive && ((JsonPrimitive) element).isString()) {
// Strings will be parsed directly
parsePrimitiveValue(element.getAsString(), materials, tags);
}
else if (element instanceof JsonObject) {
// JSONObjects can have a "required" property which can make
// it optional to resolve the underlying value
parseComplexValue(element.getAsJsonObject(), materials, tags);
}
else {
@ -63,13 +114,15 @@ class TagParser implements Keyed {
}
}
// Run the callback with the filled-in materials and tags
callback.accept(materials, tags);
}
else {
// The JSON seems to be empty yet valid
throw new TagMisconfigurationException(key, "No values array specified");
}
}
catch (IOException | IllegalStateException | JsonParseException x) {
catch (IllegalStateException | JsonParseException x) {
throw new TagMisconfigurationException(key, x.getMessage());
}
}
@ -81,6 +134,7 @@ class TagParser implements Keyed {
Material material = Material.matchMaterial(value);
if (material != null) {
// If the Material could be matched, simply add it to our Set
materials.add(material);
}
else {
@ -88,23 +142,28 @@ class TagParser implements Keyed {
}
}
else if (PatternUtils.MINECRAFT_TAG.matcher(value).matches()) {
// Get the actual Key portion and match it to item and block tags.
String keyValue = PatternUtils.COLON.split(value)[1];
NamespacedKey namespacedKey = NamespacedKey.minecraft(keyValue);
Tag<Material> itemsTag = Bukkit.getTag(Tag.REGISTRY_ITEMS, namespacedKey, Material.class);
Tag<Material> blocksTag = Bukkit.getTag(Tag.REGISTRY_BLOCKS, namespacedKey, Material.class);
if (itemsTag != null) {
// We will prioritize the item tag
tags.add(itemsTag);
}
else if (blocksTag != null) {
// If no item tag exists, fall back to the block tag
tags.add(blocksTag);
}
else {
// If both fail, then the tag does not exist.
throw new TagMisconfigurationException(key, "There is no '" + value + "' tag in Minecraft.");
}
}
else if (PatternUtils.SLIMEFUN_TAG.matcher(value).matches()) {
try {
// Get a SlimefunTag enum value for the given key
String keyValue = PatternUtils.COLON.split(value)[1].toUpperCase(Locale.ROOT);
SlimefunTag tag = SlimefunTag.valueOf(keyValue);
tags.add(tag);
@ -114,6 +173,7 @@ class TagParser implements Keyed {
}
}
else {
// If no RegEx pattern matched, it's malformed.
throw new TagMisconfigurationException(key, "Could not recognize value '" + value + "'");
}
}
@ -123,11 +183,14 @@ class TagParser implements Keyed {
JsonElement id = entry.get("id");
JsonElement required = entry.get("required");
// Check if the entry contains elements of the correct type
if (id instanceof JsonPrimitive && ((JsonPrimitive) id).isString() && required instanceof JsonPrimitive && ((JsonPrimitive) required).isBoolean()) {
if (required.getAsBoolean()) {
// If this entry is required, parse it like normal
parsePrimitiveValue(id.getAsString(), materials, tags);
}
else {
// If the entry is not required, validation will be optional
try {
parsePrimitiveValue(id.getAsString(), materials, tags);
}