mirror of
https://github.com/Minestom/Minestom.git
synced 2025-02-05 06:51:22 +01:00
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 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")),
|
||||
|
@ -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<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);
|
||||
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("<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)
|
||||
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("<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()
|
||||
);
|
||||
}
|
||||
}
|
||||
.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)
|
||||
|
Loading…
Reference in New Issue
Block a user