diff --git a/code-generators/src/main/java/net/minestom/codegen/Generators.java b/code-generators/src/main/java/net/minestom/codegen/Generators.java index 288a0da70..7fcafc59a 100644 --- a/code-generators/src/main/java/net/minestom/codegen/Generators.java +++ b/code-generators/src/main/java/net/minestom/codegen/Generators.java @@ -33,11 +33,7 @@ public class Generators { File inputFolder = new File(args[1]); // This will be ignored if resourceMode = true File outputFolder = new File(args[2]); // Generate blocks - new BlockGenerator( - resourceMode ? Generators.class.getResourceAsStream("/" + targetVersion + "_blocks.json") : new FileInputStream(new File(inputFolder, targetVersion + "_blocks.json")), - resourceMode ? Generators.class.getResourceAsStream("/" + targetVersion + "_block_properties.json") : new FileInputStream(new File(inputFolder, targetVersion + "_block_properties.json")), - outputFolder - ).generate(); + new BlockGenerator(Generators.class.getResourceAsStream("/blocks.json"), outputFolder).generate(); // Generate fluids new FluidGenerator( resourceMode ? Generators.class.getResourceAsStream("/" + targetVersion + "_fluids.json") : new FileInputStream(new File(inputFolder, targetVersion + "_fluids.json")), diff --git a/code-generators/src/main/java/net/minestom/codegen/blocks/BlockGenerator.java b/code-generators/src/main/java/net/minestom/codegen/blocks/BlockGenerator.java index 23f2aaa78..ccfa75bf6 100644 --- a/code-generators/src/main/java/net/minestom/codegen/blocks/BlockGenerator.java +++ b/code-generators/src/main/java/net/minestom/codegen/blocks/BlockGenerator.java @@ -1,6 +1,6 @@ package net.minestom.codegen.blocks; -import com.google.gson.*; +import com.google.gson.JsonObject; import com.squareup.javapoet.*; import net.minestom.codegen.MinestomCodeGenerator; import org.jetbrains.annotations.NotNull; @@ -12,17 +12,16 @@ import javax.lang.model.element.Modifier; import java.io.File; import java.io.InputStream; import java.io.InputStreamReader; -import java.util.*; +import java.util.List; +import java.util.Locale; public final class BlockGenerator extends MinestomCodeGenerator { private static final Logger LOGGER = LoggerFactory.getLogger(BlockGenerator.class); private final InputStream blocksFile; - private final InputStream blockPropertyFile; private final File outputFolder; - public BlockGenerator(@Nullable InputStream blocksFile, @Nullable InputStream blockPropertyFile, @NotNull File outputFolder) { + public BlockGenerator(@Nullable InputStream blocksFile, @NotNull File outputFolder) { this.blocksFile = blocksFile; - this.blockPropertyFile = blockPropertyFile; this.outputFolder = outputFolder; } @@ -33,97 +32,10 @@ public final class BlockGenerator extends MinestomCodeGenerator { LOGGER.error("Stopped code generation for blocks."); return; } - if (blockPropertyFile == null) { - LOGGER.error("Failed to find block_properties.json."); - LOGGER.error("Stopped code generation for block properties."); - return; - } - - if (!outputFolder.exists() && !outputFolder.mkdirs()) { - LOGGER.error("Output folder for code generation does not exist and could not be created."); - 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 namespaceIDCN = ClassName.get("net.minestom.server.utils", "NamespaceID"); - ClassName blockPropertyCN = ClassName.get("net.minestom.server.instance.block", "BlockProperty"); ClassName blockCN = ClassName.get("net.minestom.server.instance.block", "Block"); - ClassName blockImplCN = ClassName.get("net.minestom.server.instance.block", "BlockImpl"); - JsonArray blockProperties; - blockProperties = GSON.fromJson(new InputStreamReader(blockPropertyFile), JsonArray.class); - ClassName blockPropertiesCN = ClassName.get("net.minestom.server.instance.block", "BlockProperties"); - // Particle - TypeSpec.Builder blockPropertiesClass = TypeSpec.classBuilder(blockPropertiesCN) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - // Add @SuppressWarnings("unused") - .addAnnotation(AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "$S", "unused").build()) - .addJavadoc("AUTOGENERATED by " + getClass().getSimpleName()); - // Add private constructor - blockPropertiesClass.addMethod( - MethodSpec.constructorBuilder() - .addModifiers(Modifier.PRIVATE) - .build() - ); - // This stores the classes of the field names, e.g. WATERLOGGED --> Boolean - Map> propertyClassMap = new HashMap<>(); - Map propertyKeyMap = new HashMap<>(); - Map propertyValueMap = new HashMap<>(); - // Use data - for (JsonElement e : blockProperties) { - JsonObject blockProperty = e.getAsJsonObject(); - - String propertyName = blockProperty.get("name").getAsString(); - JsonArray blockValues = blockProperty.get("values").getAsJsonArray(); - JsonPrimitive firstElement = blockValues.get(0).getAsJsonPrimitive(); - - Class type; - StringBuilder values = new StringBuilder(); - if (firstElement.isBoolean()) { - type = Boolean.class; - values = new StringBuilder("true, false"); - } else if (firstElement.isNumber()) { - type = Integer.class; - for (JsonElement blockValue : blockValues) { - int i = blockValue.getAsInt(); - values.append(i).append(", "); - } - // Delete final ', ' - values.delete(values.lastIndexOf(","), values.length()); - } else { - type = String.class; - for (JsonElement blockValue : blockValues) { - String s = blockValue.getAsString(); - values.append("\"").append(s).append("\", "); - } - // Delete final ', ' - values.delete(values.lastIndexOf(","), values.length()); - } - String propertyKey = blockProperty.get("key").getAsString(); - - propertyKeyMap.put(propertyName, propertyKey); - propertyClassMap.put(propertyName, type); - propertyValueMap.put(propertyName, values.toString().split(", ")); - // Adds the field to the main class - // e.g. BlockProperty WATERLOGGED = new BlockProperty("waterlogged", true, false) - blockPropertiesClass.addField( - FieldSpec.builder( - ParameterizedTypeName.get(blockPropertyCN, TypeName.get(type)), - propertyName - ).initializer( - "new $T<>($S, $L)", - blockPropertyCN, - propertyKey, - values - ).addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL).build() - ); - } - - JsonArray blocks; - blocks = GSON.fromJson(new InputStreamReader(blocksFile), JsonArray.class); + JsonObject blocks; + blocks = GSON.fromJson(new InputStreamReader(blocksFile), JsonObject.class); ClassName blocksCN = ClassName.get("net.minestom.server.instance.block", "BlockConstants"); // BlockConstants class TypeSpec.Builder blockConstantsClass = TypeSpec.interfaceBuilder(blocksCN) @@ -132,138 +44,22 @@ public final class BlockGenerator extends MinestomCodeGenerator { .addJavadoc("AUTOGENERATED by " + getClass().getSimpleName()); // Use data - for (JsonElement b : blocks) { - JsonObject block = b.getAsJsonObject(); - - String blockName = block.get("name").getAsString(); - // Handle the properties - // Create a subclass for each Block and reference the main BlockProperty. - JsonArray properties = block.get("properties").getAsJsonArray(); - if (properties.size() != 0) { - // Create a subclass called "blockName" - // e.g. subclass AIR in BlockProperties - TypeSpec.Builder subClass = TypeSpec.classBuilder(blockPropertiesCN.nestedClass(blockName)) - .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) - .addJavadoc( - "Represents the $L {@link $T $L} that {@link $T#$N} can have:\n", - properties.size(), - blockPropertyCN, - properties.size() > 1 ? "properties" : "property", - blocksCN, - blockName - ).addJavadoc("
    \n"); - - // Store a list of values for the getProperties() method. - StringBuilder values = new StringBuilder(); - // Go through all properties the block has. - for (JsonElement property : properties) { - String propertyName = property.getAsString().toUpperCase(Locale.ROOT); - - // Add a static field that delegates to the BlockProperties static definition - FieldSpec.Builder field = FieldSpec.builder( - ParameterizedTypeName.get(blockPropertyCN, TypeName.get(propertyClassMap.get(propertyName))), - propertyName) - .initializer("$T.$N", blockPropertiesCN, propertyName) + blocks.keySet().forEach(namespace -> { + final String constantName = namespace.replace("minecraft:", "").toUpperCase(Locale.ROOT); + blockConstantsClass.addField( + FieldSpec.builder(blockCN, constantName) .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) - .addJavadoc("Definition: \"$L\" = [", propertyKeyMap.get(propertyName)); - // Results in "key" = ["value1", "value2"...] - String[] propertyVals = propertyValueMap.get(propertyName); - for (int i = 0; i < propertyVals.length; i++) { - if (i == propertyVals.length - 1) { - field.addJavadoc("$L]", propertyVals[i].toLowerCase()); - } else { - field.addJavadoc("$L, ", propertyVals[i].toLowerCase()); - } - } - // Add field to subclass - subClass.addField(field.build()); - - values.append(propertyName).append(", "); - subClass.addJavadoc("
  • {@link $T#$N}
  • \n", blockPropertiesCN, propertyName); - } - subClass.addJavadoc("
"); - // Delete final ', ' - values.delete(values.lastIndexOf(","), values.length()); - // Add a static method to get all the properties - subClass.addMethod( - MethodSpec.methodBuilder("getProperties") - .returns( - // List> - ParameterizedTypeName.get( - ClassName.get(List.class), - // BlockProperty - ParameterizedTypeName.get(blockPropertyCN, TypeVariableName.get("?")) - ) - ) - .addStatement( - "return $T.of($L)", - // If it has multiple properties --> Arrays.asList() else Collections.singletonList() - ClassName.get(List.class), - values - ) - .addModifiers(Modifier.STATIC) - .build() - ); - blockPropertiesClass.addType(subClass.build()); - } - JsonArray states = block.getAsJsonArray("states"); - // Now handle the fields in Blocks. - // If we don't have properties - if (properties.size() == 0) { - // This is a block like Stone that only has 1 BlockState. - blockConstantsClass.addField( - FieldSpec.builder(blockCN, blockName) - .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) - .initializer( - // Blocks.STONE = new BlockImpl(NamespaceID.from("minecraft:stone"), 1, Collections.emptyList()) - "$T.create($T.from($S), (short) $L, (short) $L, (short) $L, (short) $L, $T.emptyList())", - blockImplCN, - namespaceIDCN, - block.get("id").getAsString(), - // Block id - block.get("numericalID").getAsShort(), - // First state id - states.get(0).getAsJsonObject().get("id").getAsShort(), - // Last state id - states.get(states.size() - 1).getAsJsonObject().get("id").getAsShort(), - // Default state id - block.get("defaultBlockState").getAsShort(), - ClassName.get(Collections.class) - ) - .build() - ); - } else { - // This is a block that has multiple properties. - blockConstantsClass.addField( - FieldSpec.builder(blockCN, blockName) - .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) - .initializer( - // Blocks.GRASS_BLOCK = new BlockImpl(NamespaceID.from("minecraft:grass_block"), 9, 8, varargsProperty) - "$T.create($T.from($S), (short) $L, (short) $L, (short) $L, (short) $L, $T.$N.getProperties())", - blockImplCN, - namespaceIDCN, - block.get("id").getAsString(), - // Block id - block.get("numericalID").getAsShort(), - // First id - block.getAsJsonArray("states").get(0).getAsJsonObject().get("id").getAsShort(), - // Last state id - states.get(states.size() - 1).getAsJsonObject().get("id").getAsShort(), - // DefaultBlockStateId - block.get("defaultBlockState").getAsShort(), - blockPropertiesCN, - blockName - ) - .build() - ); - } - } + .initializer( + // Blocks.STONE = Block.fromNamespaceId("minecraft:stone") + "$T.fromNamespaceId($S)", + blockCN, + namespace + ) + .build() + ); + }); writeFiles( List.of( - JavaFile.builder("net.minestom.server.instance.block", blockPropertiesClass.build()) - .indent(" ") - .skipJavaLangImports(true) - .build(), JavaFile.builder("net.minestom.server.instance.block", blockConstantsClass.build()) .indent(" ") .skipJavaLangImports(true)