package net.minestom.codegen.potion; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.stream.JsonReader; import com.squareup.javapoet.*; import net.minestom.codegen.MinestomCodeGenerator; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.lang.model.element.Modifier; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.util.Collections; public final class PotionTypeGenerator extends MinestomCodeGenerator { private static final Logger LOGGER = LoggerFactory.getLogger(PotionTypeGenerator.class); private final File potionsFile; private final File outputFolder; public PotionTypeGenerator(@NotNull File potionsFile, @NotNull File outputFolder) { this.potionsFile = potionsFile; this.outputFolder = outputFolder; } @Override public void generate() { if (!potionsFile.exists()) { LOGGER.error("Failed to find potions.json."); LOGGER.error("Stopped code generation for potions."); return; } if (!outputFolder.exists() && !outputFolder.mkdirs()) { LOGGER.error("Output folder for code generation does not exist and could not be created."); return; } // Important classes we use alot ClassName namespaceIDClassName = ClassName.get("net.minestom.server.utils", "NamespaceID"); ClassName registriesClassName = ClassName.get("net.minestom.server.registry", "Registries"); JsonArray potions; try { potions = GSON.fromJson(new JsonReader(new FileReader(potionsFile)), JsonArray.class); } catch (FileNotFoundException e) { LOGGER.error("Failed to find potions.json."); LOGGER.error("Stopped code generation for potions."); return; } ClassName potionTypeClassName = ClassName.get("net.minestom.server.potion", "PotionType"); // Particle TypeSpec.Builder potionTypeClass = TypeSpec.enumBuilder(potionTypeClassName) .addSuperinterface(ClassName.get("net.kyori.adventure.key", "Keyed")) .addModifiers(Modifier.PUBLIC).addJavadoc("AUTOGENERATED by " + getClass().getSimpleName()); potionTypeClass.addField( FieldSpec.builder(namespaceIDClassName, "id") .addModifiers(Modifier.PRIVATE, Modifier.FINAL).addAnnotation(NotNull.class).build() ); // static field potionTypeClass.addField( FieldSpec.builder(ArrayTypeName.of(potionTypeClassName), "VALUES") .addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL) .initializer("values()") .build() ); potionTypeClass.addMethod( MethodSpec.constructorBuilder() .addParameter(ParameterSpec.builder(namespaceIDClassName, "id").addAnnotation(NotNull.class).build()) .addStatement("this.id = id") .addStatement("$T.potionTypes.put(id, this)", registriesClassName) .build() ); // Override key method (adventure) potionTypeClass.addMethod( MethodSpec.methodBuilder("key") .returns(ClassName.get("net.kyori.adventure.key", "Key")) .addAnnotation(Override.class) .addAnnotation(NotNull.class) .addStatement("return this.id") .addModifiers(Modifier.PUBLIC) .build() ); // getId method potionTypeClass.addMethod( MethodSpec.methodBuilder("getId") .returns(TypeName.SHORT) .addStatement("return (short) ordinal()") .addModifiers(Modifier.PUBLIC) .build() ); // getNamespaceID method potionTypeClass.addMethod( MethodSpec.methodBuilder("getNamespaceID") .returns(namespaceIDClassName) .addAnnotation(NotNull.class) .addStatement("return this.id") .addModifiers(Modifier.PUBLIC) .build() ); // fromId Method potionTypeClass.addMethod( MethodSpec.methodBuilder("fromId") .returns(potionTypeClassName) .addAnnotation(Nullable.class) .addParameter(TypeName.SHORT, "id") .beginControlFlow("if(id >= 0 && id < VALUES.length)") .addStatement("return VALUES[id]") .endControlFlow() .addStatement("return null") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .build() ); // toString method potionTypeClass.addMethod( MethodSpec.methodBuilder("toString") .addAnnotation(NotNull.class) .addAnnotation(Override.class) .returns(String.class) // this resolves to [Namespace] .addStatement("return \"[\" + this.id + \"]\"") .addModifiers(Modifier.PUBLIC) .build() ); // Use data for (JsonElement p : potions) { JsonObject potion = p.getAsJsonObject(); String potionName = potion.get("name").getAsString(); potionTypeClass.addEnumConstant(potionName, TypeSpec.anonymousClassBuilder( "$T.from($S)", namespaceIDClassName, potion.get("id").getAsString() ).build() ); } // Write files to outputFolder writeFiles( Collections.singletonList( JavaFile.builder("net.minestom.server.potion", potionTypeClass.build()) .indent(" ") .skipJavaLangImports(true) .build() ), outputFolder ); } }