mirror of https://github.com/Minestom/Minestom.git
BlockGenerator rework
This commit is contained in:
parent
48b1aa90db
commit
4fb6e37622
|
@ -33,11 +33,7 @@ public class Generators {
|
||||||
File inputFolder = new File(args[1]); // This will be ignored if resourceMode = true
|
File inputFolder = new File(args[1]); // This will be ignored if resourceMode = true
|
||||||
File outputFolder = new File(args[2]);
|
File outputFolder = new File(args[2]);
|
||||||
// Generate blocks
|
// Generate blocks
|
||||||
new BlockGenerator(
|
new BlockGenerator(Generators.class.getResourceAsStream("/blocks.json"), outputFolder).generate();
|
||||||
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();
|
|
||||||
// Generate fluids
|
// Generate fluids
|
||||||
new FluidGenerator(
|
new FluidGenerator(
|
||||||
resourceMode ? Generators.class.getResourceAsStream("/" + targetVersion + "_fluids.json") : new FileInputStream(new File(inputFolder, targetVersion + "_fluids.json")),
|
resourceMode ? Generators.class.getResourceAsStream("/" + targetVersion + "_fluids.json") : new FileInputStream(new File(inputFolder, targetVersion + "_fluids.json")),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package net.minestom.codegen.blocks;
|
package net.minestom.codegen.blocks;
|
||||||
|
|
||||||
import com.google.gson.*;
|
import com.google.gson.JsonObject;
|
||||||
import com.squareup.javapoet.*;
|
import com.squareup.javapoet.*;
|
||||||
import net.minestom.codegen.MinestomCodeGenerator;
|
import net.minestom.codegen.MinestomCodeGenerator;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
@ -12,17 +12,16 @@ import javax.lang.model.element.Modifier;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.util.*;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
public final class BlockGenerator extends MinestomCodeGenerator {
|
public final class BlockGenerator extends MinestomCodeGenerator {
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(BlockGenerator.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(BlockGenerator.class);
|
||||||
private final InputStream blocksFile;
|
private final InputStream blocksFile;
|
||||||
private final InputStream blockPropertyFile;
|
|
||||||
private final File outputFolder;
|
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.blocksFile = blocksFile;
|
||||||
this.blockPropertyFile = blockPropertyFile;
|
|
||||||
this.outputFolder = outputFolder;
|
this.outputFolder = outputFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,97 +32,10 @@ public final class BlockGenerator extends MinestomCodeGenerator {
|
||||||
LOGGER.error("Stopped code generation for blocks.");
|
LOGGER.error("Stopped code generation for blocks.");
|
||||||
return;
|
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 blockCN = ClassName.get("net.minestom.server.instance.block", "Block");
|
||||||
ClassName blockImplCN = ClassName.get("net.minestom.server.instance.block", "BlockImpl");
|
|
||||||
|
|
||||||
JsonArray blockProperties;
|
JsonObject blocks;
|
||||||
blockProperties = GSON.fromJson(new InputStreamReader(blockPropertyFile), JsonArray.class);
|
blocks = GSON.fromJson(new InputStreamReader(blocksFile), JsonObject.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<String, Class<?>> propertyClassMap = new HashMap<>();
|
|
||||||
Map<String, String> propertyKeyMap = new HashMap<>();
|
|
||||||
Map<String, String[]> 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<Boolean> WATERLOGGED = new BlockProperty<Boolean>("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);
|
|
||||||
ClassName blocksCN = ClassName.get("net.minestom.server.instance.block", "BlockConstants");
|
ClassName blocksCN = ClassName.get("net.minestom.server.instance.block", "BlockConstants");
|
||||||
// BlockConstants class
|
// BlockConstants class
|
||||||
TypeSpec.Builder blockConstantsClass = TypeSpec.interfaceBuilder(blocksCN)
|
TypeSpec.Builder blockConstantsClass = TypeSpec.interfaceBuilder(blocksCN)
|
||||||
|
@ -132,138 +44,22 @@ public final class BlockGenerator extends MinestomCodeGenerator {
|
||||||
.addJavadoc("AUTOGENERATED by " + getClass().getSimpleName());
|
.addJavadoc("AUTOGENERATED by " + getClass().getSimpleName());
|
||||||
|
|
||||||
// Use data
|
// Use data
|
||||||
for (JsonElement b : blocks) {
|
blocks.keySet().forEach(namespace -> {
|
||||||
JsonObject block = b.getAsJsonObject();
|
final String constantName = namespace.replace("minecraft:", "").toUpperCase(Locale.ROOT);
|
||||||
|
blockConstantsClass.addField(
|
||||||
String blockName = block.get("name").getAsString();
|
FieldSpec.builder(blockCN, constantName)
|
||||||
// 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("<ul>\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)
|
|
||||||
.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
|
||||||
.addJavadoc("Definition: \"$L\" = [", propertyKeyMap.get(propertyName));
|
.initializer(
|
||||||
// Results in "key" = ["value1", "value2"...]
|
// Blocks.STONE = Block.fromNamespaceId("minecraft:stone")
|
||||||
String[] propertyVals = propertyValueMap.get(propertyName);
|
"$T.fromNamespaceId($S)",
|
||||||
for (int i = 0; i < propertyVals.length; i++) {
|
blockCN,
|
||||||
if (i == propertyVals.length - 1) {
|
namespace
|
||||||
field.addJavadoc("$L]", propertyVals[i].toLowerCase());
|
)
|
||||||
} else {
|
.build()
|
||||||
field.addJavadoc("$L, ", propertyVals[i].toLowerCase());
|
);
|
||||||
}
|
});
|
||||||
}
|
|
||||||
// Add field to subclass
|
|
||||||
subClass.addField(field.build());
|
|
||||||
|
|
||||||
values.append(propertyName).append(", ");
|
|
||||||
subClass.addJavadoc("<li>{@link $T#$N}</li>\n", blockPropertiesCN, propertyName);
|
|
||||||
}
|
|
||||||
subClass.addJavadoc("</ul>");
|
|
||||||
// Delete final ', '
|
|
||||||
values.delete(values.lastIndexOf(","), values.length());
|
|
||||||
// Add a static method to get all the properties
|
|
||||||
subClass.addMethod(
|
|
||||||
MethodSpec.methodBuilder("getProperties")
|
|
||||||
.returns(
|
|
||||||
// List<BlockProperty<?>>
|
|
||||||
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()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
writeFiles(
|
writeFiles(
|
||||||
List.of(
|
List.of(
|
||||||
JavaFile.builder("net.minestom.server.instance.block", blockPropertiesClass.build())
|
|
||||||
.indent(" ")
|
|
||||||
.skipJavaLangImports(true)
|
|
||||||
.build(),
|
|
||||||
JavaFile.builder("net.minestom.server.instance.block", blockConstantsClass.build())
|
JavaFile.builder("net.minestom.server.instance.block", blockConstantsClass.build())
|
||||||
.indent(" ")
|
.indent(" ")
|
||||||
.skipJavaLangImports(true)
|
.skipJavaLangImports(true)
|
||||||
|
|
Loading…
Reference in New Issue