feat: generate RecipeType (for ids)

This commit is contained in:
mworzala 2024-04-19 08:26:25 -04:00
parent 8a829ebe47
commit c77fefbf3a
No known key found for this signature in database
GPG Key ID: B148F922E64797C7
18 changed files with 255 additions and 65 deletions

View File

@ -2,6 +2,7 @@ package net.minestom.codegen;
import net.minestom.codegen.color.DyeColorGenerator;
import net.minestom.codegen.fluid.FluidGenerator;
import net.minestom.codegen.recipe.RecipeTypeGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -18,9 +19,11 @@ public class Generators {
}
File outputFolder = new File(args[0]);
// Generate DyeColors
// Special generators
new DyeColorGenerator(resource("dye_colors.json"), outputFolder).generate();
new RecipeTypeGenerator(resource("recipe_types.json"), outputFolder).generate();
// Generic protocol object
var generator = new CodeGenerator(outputFolder);
generator.generate(resource("blocks.json"), "net.minestom.server.instance.block", "Block", "BlockImpl", "Blocks");
generator.generate(resource("items.json"), "net.minestom.server.item", "Material", "MaterialImpl", "Materials");

View File

@ -0,0 +1,113 @@
package net.minestom.codegen.recipe;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
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.InputStream;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.List;
import java.util.stream.StreamSupport;
public class RecipeTypeGenerator extends MinestomCodeGenerator {
private static final Logger LOGGER = LoggerFactory.getLogger(RecipeTypeGenerator.class);
private final InputStream recipeTypesFile;
private final File outputFolder;
public RecipeTypeGenerator(@Nullable InputStream recipeTypesFile, @NotNull File outputFolder) {
this.recipeTypesFile = recipeTypesFile;
this.outputFolder = outputFolder;
}
@Override
public void generate() {
if (recipeTypesFile == null) {
LOGGER.error("Failed to find recipe_types.json.");
LOGGER.error("Stopped code generation for recipe types.");
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
JsonArray recipeTypes = GSON.fromJson(new InputStreamReader(recipeTypesFile), JsonArray.class);
ClassName recipeTypeCN = ClassName.get("net.minestom.server.recipe", "RecipeType");
TypeSpec.Builder recipeTypeEnum = TypeSpec.enumBuilder(recipeTypeCN)
.addSuperinterface(ClassName.get("net.minestom.server.registry", "StaticProtocolObject"))
.addModifiers(Modifier.PUBLIC).addJavadoc("AUTOGENERATED by " + getClass().getSimpleName());
ClassName namespaceIdCN = ClassName.get("net.minestom.server.utils", "NamespaceID");
ClassName networkBufferCN = ClassName.get("net.minestom.server.network", "NetworkBuffer");
ParameterizedTypeName networkBufferTypeCN = ParameterizedTypeName.get(networkBufferCN.nestedClass("Type"), recipeTypeCN);
// Fields
recipeTypeEnum.addFields(
List.of(
FieldSpec.builder(networkBufferTypeCN, "NETWORK_TYPE", Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
.initializer("$T.fromEnum($T.class)", networkBufferCN, recipeTypeCN)
.build(),
FieldSpec.builder(namespaceIdCN, "namespace", Modifier.PRIVATE, Modifier.FINAL).build()
)
);
// Methods
recipeTypeEnum.addMethods(
List.of(
// Constructor
MethodSpec.constructorBuilder()
.addParameter(ParameterSpec.builder(namespaceIdCN, "namespace").addAnnotation(NotNull.class).build())
.addStatement("this.namespace = namespace")
.build(),
MethodSpec.methodBuilder("namespace")
.addModifiers(Modifier.PUBLIC)
.addAnnotation(NotNull.class)
.addAnnotation(Override.class)
.returns(namespaceIdCN)
.addStatement("return this.namespace")
.build(),
MethodSpec.methodBuilder("id")
.addModifiers(Modifier.PUBLIC)
.returns(TypeName.INT)
.addAnnotation(Override.class)
.addStatement("return this.ordinal()")
.build()
)
);
// Use data
for (JsonObject recipeTypeObject : StreamSupport.stream(recipeTypes.spliterator(), true).map(JsonElement::getAsJsonObject).sorted(Comparator.comparingInt(o -> o.get("id").getAsInt())).toList()) {
String recipeTypeName = recipeTypeObject.get("name").getAsString();
recipeTypeEnum.addEnumConstant(recipeTypeConstantName(recipeTypeName), TypeSpec.anonymousClassBuilder(
"$T.from($S)",
namespaceIdCN, recipeTypeName
).build()
);
}
// Write files to outputFolder
writeFiles(
List.of(
JavaFile.builder("net.minestom.server.recipe", recipeTypeEnum.build())
.indent(" ")
.skipJavaLangImports(true)
.build()
),
outputFolder
);
}
private static @NotNull String recipeTypeConstantName(@NotNull String name) {
return toConstant(name).replace("CRAFTING_", "");
}
}

View File

@ -0,0 +1,76 @@
package net.minestom.server.recipe;
import net.minestom.server.network.NetworkBuffer;
import net.minestom.server.registry.StaticProtocolObject;
import net.minestom.server.utils.NamespaceID;
import org.jetbrains.annotations.NotNull;
/**
* AUTOGENERATED by RecipeTypeGenerator
*/
public enum RecipeType implements StaticProtocolObject {
SHAPED(NamespaceID.from("minecraft:crafting_shaped")),
SHAPELESS(NamespaceID.from("minecraft:crafting_shapeless")),
SPECIAL_ARMORDYE(NamespaceID.from("minecraft:crafting_special_armordye")),
SPECIAL_BOOKCLONING(NamespaceID.from("minecraft:crafting_special_bookcloning")),
SPECIAL_MAPCLONING(NamespaceID.from("minecraft:crafting_special_mapcloning")),
SPECIAL_MAPEXTENDING(NamespaceID.from("minecraft:crafting_special_mapextending")),
SPECIAL_FIREWORK_ROCKET(NamespaceID.from("minecraft:crafting_special_firework_rocket")),
SPECIAL_FIREWORK_STAR(NamespaceID.from("minecraft:crafting_special_firework_star")),
SPECIAL_FIREWORK_STAR_FADE(NamespaceID.from("minecraft:crafting_special_firework_star_fade")),
SPECIAL_TIPPEDARROW(NamespaceID.from("minecraft:crafting_special_tippedarrow")),
SPECIAL_BANNERDUPLICATE(NamespaceID.from("minecraft:crafting_special_bannerduplicate")),
SPECIAL_SHIELDDECORATION(NamespaceID.from("minecraft:crafting_special_shielddecoration")),
SPECIAL_SHULKERBOXCOLORING(NamespaceID.from("minecraft:crafting_special_shulkerboxcoloring")),
SPECIAL_SUSPICIOUSSTEW(NamespaceID.from("minecraft:crafting_special_suspiciousstew")),
SPECIAL_REPAIRITEM(NamespaceID.from("minecraft:crafting_special_repairitem")),
SMELTING(NamespaceID.from("minecraft:smelting")),
BLASTING(NamespaceID.from("minecraft:blasting")),
SMOKING(NamespaceID.from("minecraft:smoking")),
CAMPFIRE_COOKING(NamespaceID.from("minecraft:campfire_cooking")),
STONECUTTING(NamespaceID.from("minecraft:stonecutting")),
SMITHING_TRANSFORM(NamespaceID.from("minecraft:smithing_transform")),
SMITHING_TRIM(NamespaceID.from("minecraft:smithing_trim")),
DECORATED_POT(NamespaceID.from("minecraft:crafting_decorated_pot"));
public static final NetworkBuffer.Type<RecipeType> NETWORK_TYPE = NetworkBuffer.fromEnum(RecipeType.class);
private final NamespaceID namespace;
RecipeType(@NotNull NamespaceID namespace) {
this.namespace = namespace;
}
@NotNull
@Override
public NamespaceID namespace() {
return this.namespace;
}
@Override
public int id() {
return this.ordinal();
}
}

View File

@ -354,7 +354,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
for (Recipe recipe : recipeManager.getRecipes()) {
if (!recipe.shouldShow(this))
continue;
recipesIdentifier.add(recipe.getRecipeId());
recipesIdentifier.add(recipe.id());
}
if (!recipesIdentifier.isEmpty()) {
UnlockRecipesPacket unlockRecipesPacket = new UnlockRecipesPacket(0,

View File

@ -5,6 +5,7 @@ import net.minestom.server.network.NetworkBuffer;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.recipe.RecipeCategory;
import net.minestom.server.recipe.RecipeType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -43,7 +44,7 @@ public record DeclareRecipesPacket(@NotNull List<DeclaredRecipe> recipes) implem
public void write(@NotNull NetworkBuffer writer) {
writer.writeCollection(recipes, (bWriter, recipe) -> {
bWriter.write(STRING, recipe.recipeId());
bWriter.write(STRING, recipe.type());
bWriter.write(RecipeType.NETWORK_TYPE, recipe.type());
bWriter.write(recipe);
});
}
@ -58,7 +59,7 @@ public record DeclareRecipesPacket(@NotNull List<DeclaredRecipe> recipes) implem
DeclaredSmeltingRecipe, DeclaredBlastingRecipe, DeclaredSmokingRecipe,
DeclaredCampfireCookingRecipe, DeclaredStonecutterRecipe,
DeclaredSmithingTrimRecipe, DeclaredSmithingTransformRecipe {
@NotNull String type();
@NotNull RecipeType type();
@NotNull String recipeId();
}
@ -82,8 +83,8 @@ public record DeclareRecipesPacket(@NotNull List<DeclaredRecipe> recipes) implem
}
@Override
public @NotNull String type() {
return "crafting_shapeless";
public @NotNull RecipeType type() {
return RecipeType.SHAPELESS;
}
}
@ -133,8 +134,8 @@ public record DeclareRecipesPacket(@NotNull List<DeclaredRecipe> recipes) implem
}
@Override
public @NotNull String type() {
return "crafting_shaped";
public @NotNull RecipeType type() {
return RecipeType.SHAPED;
}
}
@ -160,8 +161,8 @@ public record DeclareRecipesPacket(@NotNull List<DeclaredRecipe> recipes) implem
}
@Override
public @NotNull String type() {
return "smelting";
public @NotNull RecipeType type() {
return RecipeType.SMELTING;
}
}
@ -187,8 +188,8 @@ public record DeclareRecipesPacket(@NotNull List<DeclaredRecipe> recipes) implem
}
@Override
public @NotNull String type() {
return "blasting";
public @NotNull RecipeType type() {
return RecipeType.BLASTING;
}
}
@ -214,8 +215,8 @@ public record DeclareRecipesPacket(@NotNull List<DeclaredRecipe> recipes) implem
}
@Override
public @NotNull String type() {
return "smoking";
public @NotNull RecipeType type() {
return RecipeType.SMOKING;
}
}
@ -241,8 +242,8 @@ public record DeclareRecipesPacket(@NotNull List<DeclaredRecipe> recipes) implem
}
@Override
public @NotNull String type() {
return "campfire_cooking";
public @NotNull RecipeType type() {
return RecipeType.CAMPFIRE_COOKING;
}
}
@ -261,8 +262,8 @@ public record DeclareRecipesPacket(@NotNull List<DeclaredRecipe> recipes) implem
}
@Override
public @NotNull String type() {
return "stonecutting";
public @NotNull RecipeType type() {
return RecipeType.STONECUTTING;
}
}
@ -282,8 +283,8 @@ public record DeclareRecipesPacket(@NotNull List<DeclaredRecipe> recipes) implem
}
@Override
public @NotNull String type() {
return "smithing_transform";
public @NotNull RecipeType type() {
return RecipeType.SMITHING_TRANSFORM;
}
}
@ -301,8 +302,8 @@ public record DeclareRecipesPacket(@NotNull List<DeclaredRecipe> recipes) implem
}
@Override
public @NotNull String type() {
return "smithing_trim";
public @NotNull RecipeType type() {
return RecipeType.SMITHING_TRIM;
}
}

View File

@ -20,7 +20,7 @@ public abstract class BlastingRecipe extends Recipe {
float experience,
int cookingTime
) {
super(Type.BLASTING, recipeId);
super(RecipeType.BLASTING, recipeId);
this.group = group;
this.category = category;
this.result = result;

View File

@ -20,7 +20,7 @@ public abstract class CampfireCookingRecipe extends Recipe {
float experience,
int cookingTime
) {
super(Type.CAMPFIRE_COOKING, recipeId);
super(RecipeType.CAMPFIRE_COOKING, recipeId);
this.group = group;
this.category = category;
this.result = result;

View File

@ -4,36 +4,22 @@ import net.minestom.server.entity.Player;
import org.jetbrains.annotations.NotNull;
public abstract class Recipe {
protected final Type recipeType;
protected final String recipeId;
protected final RecipeType type;
protected final String id;
protected Recipe(@NotNull Type recipeType, @NotNull String recipeId) {
this.recipeType = recipeType;
this.recipeId = recipeId;
protected Recipe(@NotNull RecipeType type, @NotNull String id) {
this.type = type;
this.id = id;
}
public abstract boolean shouldShow(@NotNull Player player);
@NotNull
public Type getRecipeType() {
return recipeType;
public RecipeType type() {
return type;
}
@NotNull
public String getRecipeId() {
return recipeId;
public @NotNull String id() {
return id;
}
public enum Type {
SHAPELESS,
SHAPED,
SMELTING,
BLASTING,
SMOKING,
CAMPFIRE_COOKING,
STONECUTTING,
SMITHING_TRANSFORM,
SMITHING_TRIM
}
}

View File

@ -6,7 +6,7 @@ import org.jetbrains.annotations.NotNull;
final class RecipeConversion {
static @NotNull DeclareRecipesPacket.DeclaredShapelessCraftingRecipe shapeless(@NotNull ShapelessRecipe shapelessRecipe) {
return new DeclareRecipesPacket.DeclaredShapelessCraftingRecipe(shapelessRecipe.getRecipeId(),
return new DeclareRecipesPacket.DeclaredShapelessCraftingRecipe(shapelessRecipe.id(),
shapelessRecipe.getGroup(),
shapelessRecipe.getCategory(),
shapelessRecipe.getIngredients(),
@ -14,7 +14,7 @@ final class RecipeConversion {
}
static @NotNull DeclareRecipesPacket.DeclaredShapedCraftingRecipe shaped(@NotNull ShapedRecipe shapedRecipe) {
return new DeclareRecipesPacket.DeclaredShapedCraftingRecipe(shapedRecipe.getRecipeId(),
return new DeclareRecipesPacket.DeclaredShapedCraftingRecipe(shapedRecipe.id(),
shapedRecipe.getGroup(),
shapedRecipe.getCategory(),
shapedRecipe.getWidth(),
@ -26,7 +26,7 @@ final class RecipeConversion {
static @NotNull DeclareRecipesPacket.DeclaredSmeltingRecipe smelting(@NotNull SmeltingRecipe smeltingRecipe) {
return new DeclareRecipesPacket.DeclaredSmeltingRecipe(
smeltingRecipe.getRecipeId(),
smeltingRecipe.id(),
smeltingRecipe.getGroup(),
smeltingRecipe.getCategory(),
smeltingRecipe.getIngredient(),
@ -37,7 +37,7 @@ final class RecipeConversion {
static @NotNull DeclareRecipesPacket.DeclaredBlastingRecipe blasting(@NotNull BlastingRecipe blastingRecipe) {
return new DeclareRecipesPacket.DeclaredBlastingRecipe(
blastingRecipe.getRecipeId(),
blastingRecipe.id(),
blastingRecipe.getGroup(),
blastingRecipe.getCategory(),
blastingRecipe.getIngredient(),
@ -48,7 +48,7 @@ final class RecipeConversion {
static @NotNull DeclareRecipesPacket.DeclaredSmokingRecipe smoking(@NotNull SmokingRecipe smokingRecipe) {
return new DeclareRecipesPacket.DeclaredSmokingRecipe(
smokingRecipe.getRecipeId(),
smokingRecipe.id(),
smokingRecipe.getGroup(),
smokingRecipe.getCategory(),
smokingRecipe.getIngredient(),
@ -59,7 +59,7 @@ final class RecipeConversion {
static @NotNull DeclareRecipesPacket.DeclaredCampfireCookingRecipe campfire(@NotNull CampfireCookingRecipe campfireCookingRecipe) {
return new DeclareRecipesPacket.DeclaredCampfireCookingRecipe(
campfireCookingRecipe.getRecipeId(),
campfireCookingRecipe.id(),
campfireCookingRecipe.getGroup(),
campfireCookingRecipe.getCategory(),
campfireCookingRecipe.getIngredient(),
@ -70,7 +70,7 @@ final class RecipeConversion {
static @NotNull DeclareRecipesPacket.DeclaredStonecutterRecipe stonecutter(@NotNull StonecutterRecipe stonecuttingRecipe) {
return new DeclareRecipesPacket.DeclaredStonecutterRecipe(
stonecuttingRecipe.getRecipeId(),
stonecuttingRecipe.id(),
stonecuttingRecipe.getGroup(),
stonecuttingRecipe.getIngredient(),
stonecuttingRecipe.getResult());
@ -78,7 +78,7 @@ final class RecipeConversion {
static @NotNull DeclareRecipesPacket.DeclaredSmithingTransformRecipe smithingTransform(@NotNull SmithingTransformRecipe smithingTransformRecipe) {
return new DeclareRecipesPacket.DeclaredSmithingTransformRecipe(
smithingTransformRecipe.getRecipeId(),
smithingTransformRecipe.id(),
smithingTransformRecipe.getTemplate(),
smithingTransformRecipe.getBaseIngredient(),
smithingTransformRecipe.getAdditionIngredient(),
@ -87,7 +87,7 @@ final class RecipeConversion {
static @NotNull DeclareRecipesPacket.DeclaredSmithingTrimRecipe smithingTrim(@NotNull SmithingTrimRecipe smithingTrimRecipe) {
return new DeclareRecipesPacket.DeclaredSmithingTrimRecipe(
smithingTrimRecipe.getRecipeId(),
smithingTrimRecipe.id(),
smithingTrimRecipe.getTemplate(),
smithingTrimRecipe.getBaseIngredient(),
smithingTrimRecipe.getAdditionIngredient());

View File

@ -45,7 +45,7 @@ public class RecipeManager {
private @NotNull DeclareRecipesPacket createDeclareRecipesPacket() {
var entries = new ArrayList<DeclareRecipesPacket.DeclaredRecipe>();
for (var recipe : recipes) {
entries.add(switch (recipe.recipeType) {
entries.add(switch (recipe.type) {
case SHAPELESS -> RecipeConversion.shapeless((ShapelessRecipe) recipe);
case SHAPED -> RecipeConversion.shaped((ShapedRecipe) recipe);
case SMELTING -> RecipeConversion.smelting((SmeltingRecipe) recipe);
@ -55,6 +55,7 @@ public class RecipeManager {
case STONECUTTING -> RecipeConversion.stonecutter((StonecutterRecipe) recipe);
case SMITHING_TRANSFORM -> RecipeConversion.smithingTransform((SmithingTransformRecipe) recipe);
case SMITHING_TRIM -> RecipeConversion.smithingTrim((SmithingTrimRecipe) recipe);
default -> throw new IllegalStateException("Unhandled recipe type : " + recipe.type);
});
}
return new DeclareRecipesPacket(List.of());

View File

@ -25,7 +25,7 @@ public abstract class ShapedRecipe extends Recipe {
@NotNull RecipeCategory.Crafting category,
@Nullable List<DeclareRecipesPacket.Ingredient> ingredients,
@NotNull ItemStack result, boolean showNotification) {
super(Type.SHAPED, recipeId);
super(RecipeType.SHAPED, recipeId);
this.width = width;
this.height = height;
this.group = group;

View File

@ -22,7 +22,7 @@ public abstract class ShapelessRecipe extends Recipe {
@Nullable List<DeclareRecipesPacket.Ingredient> ingredients,
@NotNull ItemStack result
) {
super(Type.SHAPELESS, recipeId);
super(RecipeType.SHAPELESS, recipeId);
this.group = group;
this.category = category;
this.ingredients = Objects.requireNonNullElseGet(ingredients, LinkedList::new);

View File

@ -20,7 +20,7 @@ public abstract class SmeltingRecipe extends Recipe {
float experience,
int cookingTime
) {
super(Type.SMELTING, recipeId);
super(RecipeType.SMELTING, recipeId);
this.group = group;
this.category = category;
this.result = result;

View File

@ -17,7 +17,7 @@ public abstract class SmithingTransformRecipe extends Recipe {
@NotNull DeclareRecipesPacket.Ingredient additionIngredient,
@NotNull ItemStack result
) {
super(Type.SMITHING_TRANSFORM, recipeId);
super(RecipeType.SMITHING_TRANSFORM, recipeId);
this.template = template;
this.baseIngredient = baseIngredient;
this.additionIngredient = additionIngredient;

View File

@ -1,6 +1,5 @@
package net.minestom.server.recipe;
import net.minestom.server.item.ItemStack;
import net.minestom.server.network.packet.server.play.DeclareRecipesPacket;
import org.jetbrains.annotations.NotNull;
@ -15,7 +14,7 @@ public abstract class SmithingTrimRecipe extends Recipe {
@NotNull DeclareRecipesPacket.Ingredient baseIngredient,
@NotNull DeclareRecipesPacket.Ingredient additionIngredient
) {
super(Type.SMITHING_TRIM, recipeId);
super(RecipeType.SMITHING_TRIM, recipeId);
this.template = template;
this.baseIngredient = baseIngredient;
this.additionIngredient = additionIngredient;

View File

@ -20,7 +20,7 @@ public abstract class SmokingRecipe extends Recipe {
float experience,
int cookingTime
) {
super(Type.SMOKING, recipeId);
super(RecipeType.SMOKING, recipeId);
this.group = group;
this.category = category;
this.result = result;

View File

@ -15,7 +15,7 @@ public abstract class StonecutterRecipe extends Recipe {
@NotNull DeclareRecipesPacket.Ingredient ingredient,
@NotNull ItemStack result
) {
super(Type.STONECUTTING, recipeId);
super(RecipeType.STONECUTTING, recipeId);
this.group = group;
this.ingredient = ingredient;
this.result = result;

View File

@ -51,6 +51,17 @@ public sealed interface SoundEvent extends ProtocolObject, Sound.Type, SoundEven
return BuiltinSoundEvent.getId(id);
}
/**
* Create a custom sound event. The namespace should match a sound provided in the resource pack.
*
* @param namespaceID the namespace ID of the custom sound event
* @param range the range of the sound event, or null for (legacy) dynamic range
* @return the custom sound event
*/
static @NotNull SoundEvent of(@NotNull String namespaceID, @Nullable Float range) {
return new CustomSoundEvent(NamespaceID.from(namespaceID), range);
}
/**
* Create a custom sound event. The {@link NamespaceID} should match a sound provided in the resource pack.
* @param namespaceID the namespace ID of the custom sound event