001package com.mrivanplays.commandworker.bukkit.argtypes;
002
003import com.mojang.brigadier.arguments.ArgumentType;
004import com.mrivanplays.commandworker.bukkit.registry.CmdRegistryHandler;
005import java.lang.reflect.Constructor;
006import java.lang.reflect.InvocationTargetException;
007import org.bukkit.NamespacedKey;
008
009/**
010 * Represents an enum, holding all known minecraft brigadier types.
011 *
012 * <p>Source: <a href="https://minecraft.gamepedia.com/Argument_types">Minecraft wiki</a>, where you
013 * can find examples.
014 */
015public enum MinecraftArgumentTypes {
016  BLOCK_POS("block_pos"),
017  BLOCK_PREDICATE("block_predicate"),
018  BLOCK_STATE("block_state"),
019  COLOR("color"),
020  COMPONENT("component"),
021  DIMENSION("dimension"),
022
023  /** Constructor parameters: single, playersOnly */
024  ENTITY("entity", boolean.class, boolean.class),
025
026  ENTITY_ANCHOR("entity_anchor"),
027  ENTITY_SUMMON("entity_summon"),
028  FLOAT_RANGE("float_range"),
029  FUNCTION("function"),
030  GAME_PROFILE("game_profile"),
031  INT_RANGE("int_range"),
032  ITEM_ENCHANTMENT("item_enchantment"),
033  ITEM_PREDICATE("item_predicate"),
034  ITEM_SLOT("item_slot"),
035  ITEM_STACK("item_stack"),
036  MESSAGE("message"),
037  MOB_EFFECT("mob_effect"),
038  NBT_COMPOUND_TAG("nbt_compound_tag"),
039  NBT_PATH("nbt_path"),
040  NBT_TAG("nbt_tag"),
041  OBJECTIVE("objective"),
042  OBJECTIVE_CRITERIA("objective_criteria"),
043  OPERATION("operation"),
044  PARTICLE("particle"),
045
046  /** Responsible for both advancements and recipes. */
047  RESOURCE_LOCATION("resource_location"),
048
049  ROTATION("rotation"),
050
051  /** Constructor parameters: multiple */
052  SCORE_HOLDER("score_holder", boolean.class),
053
054  SCOREBOARD_SLOT("scoreboard_slot"),
055  SWIZZLE("swizzle"),
056  TEAM("team"),
057  TIME("time"),
058  UUID("uuid"),
059
060  /** Constructor parameters: centerCorrect */
061  VEC2("vec2", boolean.class),
062
063  /** Constructor parameters: centerCorrect */
064  VEC3("vec3", boolean.class);
065
066  private final NamespacedKey namespacedKey;
067
068  private ArgumentType<?> firstOption, secondOption, thirdOption, fourthOption;
069
070  MinecraftArgumentTypes(String namespace, Class<?>... constructorParameters) {
071    namespacedKey = NamespacedKey.minecraft(namespace);
072    if (CmdRegistryHandler.isSupported()) {
073      if (constructorParameters == null) {
074        firstOption = MinecraftArgumentTypesAccessor.getByKey(namespacedKey);
075      } else {
076        try {
077          Class<? extends ArgumentType<?>> argumentClass =
078              MinecraftArgumentTypesAccessor.getArgumentClass(namespacedKey);
079          Constructor<? extends ArgumentType<?>> constructor =
080              argumentClass.getDeclaredConstructor(constructorParameters);
081          if (constructorParameters.length == 1) {
082            this.firstOption = constructor.newInstance(true);
083            this.secondOption = constructor.newInstance(false);
084          } else {
085            this.firstOption = constructor.newInstance(false, true);
086            this.secondOption = constructor.newInstance(true, false);
087            this.thirdOption = constructor.newInstance(true, true);
088            this.fourthOption = constructor.newInstance(false, false);
089          }
090        } catch (NullPointerException
091            | NoSuchMethodException
092            | IllegalAccessException
093            | InstantiationException
094            | InvocationTargetException e) {
095          this.firstOption = null;
096          this.secondOption = null;
097          this.thirdOption = null;
098          this.fourthOption = null;
099        }
100      }
101    }
102  }
103
104  /**
105   * Returns the brigadier {@link ArgumentType} of the argument, if it is present.
106   *
107   * @return argument type
108   */
109  public ArgumentType<?> getArgumentType() {
110    return firstOption;
111  }
112
113  /**
114   * Returns the key of this argument type.
115   *
116   * @return key
117   */
118  public NamespacedKey getKey() {
119    return namespacedKey;
120  }
121
122  // bellow are the other types of the argument type.
123
124  public ArgumentType<?> getSecondWay() {
125    return secondOption == null ? firstOption : secondOption;
126  }
127
128  public ArgumentType<?> getThirdWay() {
129    return thirdOption == null ? getSecondWay() : thirdOption;
130  }
131
132  public ArgumentType<?> getFourthWay() {
133    return fourthOption == null ? getThirdWay() : fourthOption;
134  }
135}