patchouli template

This commit is contained in:
lcy0x1
2024-06-29 21:29:52 +08:00
parent 697f53ce60
commit 67aac096e5
10 changed files with 509 additions and 127 deletions

View File

@@ -0,0 +1,8 @@
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
package dev.xkmc.l2core.compat.curios;
import net.minecraft.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;

View File

@@ -0,0 +1,53 @@
package dev.xkmc.l2core.compat.jei;
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.recipe.RecipeType;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.resources.ResourceLocation;
import javax.annotation.ParametersAreNonnullByDefault;
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public abstract class BaseRecipeCategory<T, C extends BaseRecipeCategory<T, C>> implements IRecipeCategory<T> {
@SuppressWarnings("unchecked")
public static <T extends R, R> Class<T> cast(Class<R> cls) {
return (Class<T>) cls;
}
private final RecipeType<T> type;
protected IDrawable background, icon;
public BaseRecipeCategory(ResourceLocation name, Class<T> cls) {
this.type = new RecipeType<>(name, cls);
}
@SuppressWarnings("unchecked")
public final C getThis() {
return (C) this;
}
@Override
public final RecipeType<T> getRecipeType() {
return type;
}
@Override
public final IDrawable getBackground() {
return background;
}
@Override
public final IDrawable getIcon() {
return icon;
}
@Override
public abstract void setRecipe(IRecipeLayoutBuilder builder, T recipe, IFocusGroup focuses);
}

View File

@@ -0,0 +1,8 @@
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
package dev.xkmc.l2core.compat.jei;
import net.minecraft.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;

View File

@@ -0,0 +1,99 @@
package dev.xkmc.l2core.compat.patchouli;
import com.tterrag.registrate.providers.ProviderType;
import com.tterrag.registrate.util.DataIngredient;
import dev.xkmc.l2core.init.reg.registrate.L2Registrate;
import dev.xkmc.l2core.serial.recipe.ConditionalRecipeWrapper;
import net.minecraft.Util;
import net.minecraft.data.recipes.RecipeBuilder;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.storage.loot.LootPool;
import net.minecraft.world.level.storage.loot.LootTable;
import net.neoforged.neoforge.client.model.generators.ModelFile;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class PatchouliHelper {
public static final ProviderType<PatchouliProvider> PATCHOULI = ProviderType.register("patchouli", (p, e) -> new PatchouliProvider(p, e.getLookupProvider(), e.getGenerator()));
public static ItemStack getBook(ResourceLocation book) {
return ItemStack.EMPTY; // TODO ItemModBook.forBook(book);
}
public static LootTable.Builder getBookLoot(ResourceLocation book) {
CompoundTag tag = new CompoundTag();
tag.putString("patchouli:book", book.toString());
return LootTable.lootTable().withPool(
LootPool.lootPool()//TODO .add(LootItem.lootTableItem(PatchouliItems.BOOK).apply(SetNbtFunction.setTag(tag)))
);
}
private final L2Registrate reg;
private final ResourceLocation book;
private ResourceLocation model;
public PatchouliHelper(L2Registrate reg, String name) {
this.reg = reg;
book = ResourceLocation.fromNamespaceAndPath(reg.getModid(), name);
}
public PatchouliHelper buildModel() {
return buildModel("book");
}
public PatchouliHelper buildModel(String path) {
model = ResourceLocation.fromNamespaceAndPath(reg.getModid(), path);
reg.addDataGenerator(ProviderType.ITEM_MODEL, pvd -> pvd.getBuilder(path)
.parent(new ModelFile.UncheckedModelFile("item/generated"))
.texture("layer0", "item/" + path));
return this;
}
/* TODO
public PatchouliHelper buildShapelessRecipe(Consumer<ShapelessPatchouliBuilder> cons, Supplier<Item> unlock) {
return buildRecipe(() -> Util.make(new ShapelessPatchouliBuilder(book), cons), unlock);
}
public PatchouliHelper buildShapedRecipe(Consumer<ShapedPatchouliBuilder> cons, Supplier<Item> unlock) {
return buildRecipe(() -> Util.make(new ShapedPatchouliBuilder(book), cons), unlock);
}
*/
private PatchouliHelper buildRecipe(Supplier<RecipeBuilder> cons, Supplier<Item> unlock) {
reg.addDataGenerator(ProviderType.RECIPE, pvd -> {
var builder = cons.get();
builder.unlockedBy("has_" + pvd.safeName(unlock.get()),
DataIngredient.items(unlock.get()).getCriterion(pvd));
builder.save(ConditionalRecipeWrapper.mod(pvd, "patchouli"),
ResourceLocation.fromNamespaceAndPath(reg.getModid(), "book"));
});
return this;
}
public PatchouliHelper buildBook(String title, String landing, int ver, ResourceKey<CreativeModeTab> tab) {
if (model == null) {
throw new IllegalStateException("Patchouli Book must have a model first");
}
String titleId = "patchouli." + reg.getModid() + ".title";
String descId = "patchouli." + reg.getModid() + ".landing";
reg.addRawLang(titleId, title);
reg.addRawLang(descId, landing);
reg.addDataGenerator(PATCHOULI, pvd -> pvd.accept(reg.getModid() + "/patchouli_books/" + book.getPath() + "/book",
new BookEntry(titleId, descId, ver, model, tab.location(), true)));
return this;
}
public record BookEntry(String name, String landing_text, int version,
ResourceLocation model, ResourceLocation creative_tab,
boolean use_resource_pack) {
}
}

View File

@@ -0,0 +1,43 @@
package dev.xkmc.l2core.compat.patchouli;
import com.tterrag.registrate.AbstractRegistrate;
import com.tterrag.registrate.providers.RegistrateProvider;
import dev.xkmc.l2core.serial.config.RecordDataProvider;
import net.minecraft.core.HolderLookup;
import net.minecraft.data.DataGenerator;
import net.neoforged.fml.LogicalSide;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
public class PatchouliProvider extends RecordDataProvider implements RegistrateProvider, BiConsumer<String, Record> {
private final AbstractRegistrate<?> owner;
private BiConsumer<String, Record> map;
public PatchouliProvider(AbstractRegistrate<?> owner, CompletableFuture<HolderLookup.Provider> pvd, DataGenerator gen) {
super(gen, pvd, "Patchouli Provider");
this.owner = owner;
}
public void accept(String path, Record rec) {
if (map == null) {
throw new IllegalStateException("Cannot accept recipes outside of a call to registerRecipes");
}
map.accept(path, rec);
}
@Override
public LogicalSide getSide() {
return LogicalSide.SERVER;
}
@Override
public void add(BiConsumer<String, Record> map) {
this.map = map;
owner.genData(PatchouliHelper.PATCHOULI, this);
this.map = null;
}
}

View File

@@ -0,0 +1,83 @@
package dev.xkmc.l2core.compat.patchouli;
/*
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.minecraft.advancements.Advancement;
import net.minecraft.advancements.AdvancementRewards;
import net.minecraft.advancements.RequirementsStrategy;
import net.minecraft.advancements.critereon.RecipeUnlockedTrigger;
import net.minecraft.data.recipes.FinishedRecipe;
import net.minecraft.data.recipes.RecipeCategory;
import net.minecraft.data.recipes.RecipeOutput;
import net.minecraft.data.recipes.ShapedRecipeBuilder;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeSerializer;
import vazkii.patchouli.common.item.PatchouliItems;
import vazkii.patchouli.common.recipe.ShapedBookRecipe;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
public class ShapedPatchouliBuilder extends ShapedRecipeBuilder {
private final ResourceLocation book;
public ShapedPatchouliBuilder(ResourceLocation book) {
super(RecipeCategory.MISC, PatchouliItems.BOOK, 1);
this.book = book;
}
@Override
public void save(RecipeOutput pvd, ResourceLocation id) {
this.ensureValid(id);
this.advancement.parent(ROOT_RECIPE_ADVANCEMENT)
.addCriterion("has_the_recipe", RecipeUnlockedTrigger.unlocked(id))
.rewards(AdvancementRewards.Builder.recipe(id))
.requirements(RequirementsStrategy.OR);
pvd.accept(new Result(book, id, this.rows, this.key, this.advancement, id.withPrefix("recipes/")));
}
public record Result(ResourceLocation book, ResourceLocation id, List<String> pattern,
Map<Character, Ingredient> key, Advancement.Builder advancement,
ResourceLocation advancementId) implements FinishedRecipe {
public void serializeRecipeData(JsonObject json) {
JsonArray jsonarray = new JsonArray();
for (String s : this.pattern) {
jsonarray.add(s);
}
json.add("pattern", jsonarray);
JsonObject jsonobject = new JsonObject();
for (Map.Entry<Character, Ingredient> entry : this.key.entrySet()) {
jsonobject.add(String.valueOf(entry.getKey()), entry.getValue().toJson());
}
json.add("key", jsonobject);
json.addProperty("book", book.toString());
}
public RecipeSerializer<?> getType() {
return ShapedBookRecipe.SERIALIZER;
}
public ResourceLocation getId() {
return this.id;
}
public JsonObject serializeAdvancement() {
return this.advancement.serializeToJson();
}
@Nullable
public ResourceLocation getAdvancementId() {
return this.advancementId;
}
}
}
*/

View File

@@ -0,0 +1,76 @@
package dev.xkmc.l2core.compat.patchouli;
/*
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.minecraft.advancements.Advancement;
import net.minecraft.advancements.AdvancementRewards;
import net.minecraft.advancements.RequirementsStrategy;
import net.minecraft.advancements.critereon.RecipeUnlockedTrigger;
import net.minecraft.data.recipes.FinishedRecipe;
import net.minecraft.data.recipes.RecipeCategory;
import net.minecraft.data.recipes.ShapelessRecipeBuilder;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeSerializer;
import vazkii.patchouli.common.item.PatchouliItems;
import vazkii.patchouli.common.recipe.ShapelessBookRecipe;
import javax.annotation.Nullable;
import java.util.List;
import java.util.function.Consumer;
public class ShapelessPatchouliBuilder extends ShapelessRecipeBuilder {
private final ResourceLocation book;
public ShapelessPatchouliBuilder(ResourceLocation book) {
super(RecipeCategory.MISC, PatchouliItems.BOOK, 1);
this.book = book;
}
@Override
public void save(Consumer<FinishedRecipe> pvd, ResourceLocation id) {
this.ensureValid(id);
this.advancement.parent(ROOT_RECIPE_ADVANCEMENT)
.addCriterion("has_the_recipe", RecipeUnlockedTrigger.unlocked(id))
.rewards(AdvancementRewards.Builder.recipe(id))
.requirements(RequirementsStrategy.OR);
pvd.accept(new Shapeless(book, id, this.ingredients, this.advancement, id.withPrefix("recipes/")));
}
public record Shapeless(ResourceLocation book, ResourceLocation id, List<Ingredient> ingredients,
Advancement.Builder advancement, ResourceLocation advId) implements FinishedRecipe {
public void serializeRecipeData(JsonObject json) {
JsonArray jsonarray = new JsonArray();
for (Ingredient ingredient : this.ingredients) {
jsonarray.add(ingredient.toJson());
}
json.add("ingredients", jsonarray);
json.addProperty("book", book.toString());
}
public RecipeSerializer<?> getType() {
return ShapelessBookRecipe.SERIALIZER;
}
public ResourceLocation getId() {
return this.id;
}
public JsonObject serializeAdvancement() {
return this.advancement.serializeToJson();
}
@Nullable
public ResourceLocation getAdvancementId() {
return this.advId;
}
}
}
*/

View File

@@ -0,0 +1,8 @@
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
package dev.xkmc.l2core.compat.patchouli;
import net.minecraft.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;

View File

@@ -1,9 +1,13 @@
package dev.xkmc.l2core.serial.advancements;
import com.tterrag.registrate.providers.RegistrateAdvancementProvider;
import dev.xkmc.l2core.compat.patchouli.PatchouliHelper;
import dev.xkmc.l2core.init.reg.registrate.L2Registrate;
import net.minecraft.advancements.Advancement;
import net.minecraft.advancements.AdvancementHolder;
import net.minecraft.advancements.AdvancementType;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
@@ -17,152 +21,151 @@ import java.util.function.Consumer;
@SuppressWarnings("unused")
public class AdvancementGenerator {
private final RegistrateAdvancementProvider pvd;
private final String modid;
private final RegistrateAdvancementProvider pvd;
private final String modid;
public AdvancementGenerator(RegistrateAdvancementProvider pvd, String modid) {
this.pvd = pvd;
this.modid = modid;
}
public AdvancementGenerator(RegistrateAdvancementProvider pvd, String modid) {
this.pvd = pvd;
this.modid = modid;
}
public class TabBuilder {
public class TabBuilder {
private final String tab;
private final ResourceLocation bg;
private final String tab;
private final ResourceLocation bg;
private Entry root;
private Entry root;
public TabBuilder(String tab) {
this.tab = tab;
this.bg = ResourceLocation.fromNamespaceAndPath(modid, "textures/gui/advancements/backgrounds/" + tab + ".png");
}
public TabBuilder(String tab) {
this.tab = tab;
this.bg = ResourceLocation.fromNamespaceAndPath(modid, "textures/gui/advancements/backgrounds/" + tab + ".png");
}
public void build() {
root.build();
}
public void build() {
root.build();
}
public Entry root(String id, Item item, CriterionBuilder builder, String title, String desc) {
return root(id, item.getDefaultInstance(), builder, title, desc);
}
public Entry root(String id, Item item, CriterionBuilder builder, String title, String desc) {
return root(id, item.getDefaultInstance(), builder, title, desc);
}
public Entry root(String id, ItemStack item, CriterionBuilder builder, String title, String desc) {
if (root == null) {
root = new Entry(new EntryData(id, item, builder, title, desc), null);
}
return root;
}
public Entry root(String id, ItemStack item, CriterionBuilder builder, String title, String desc) {
if (root == null) {
root = new Entry(new EntryData(id, item, builder, title, desc), null);
}
return root;
}
public Entry hidden(String id, CriterionBuilder builder) {
return new Entry(new EntryData(id, ItemStack.EMPTY, builder, "", ""), null);
}
public Entry hidden(String id, CriterionBuilder builder) {
return new Entry(new EntryData(id, ItemStack.EMPTY, builder, "", ""), null);
}
public class Entry {
public class Entry {
private final List<Entry> children = new ArrayList<>();
private final EntryData data;
private final ResourceLocation rl;
private final Entry parent;
private final List<Entry> children = new ArrayList<>();
private final EntryData data;
private final ResourceLocation rl;
private final Entry parent;
private AdvancementType type = AdvancementType.TASK;
private boolean showToast = true, announce = true, hidden = false;
private AdvancementHolder result;
private AdvancementType type = AdvancementType.TASK;
private boolean showToast = true, announce = true, hidden = false;
private AdvancementHolder result;
private Entry(EntryData data, @Nullable Entry parent) {
this.data = data;
this.parent = parent;
if (parent == null) {
showToast = false;
announce = false;
rl = bg;
} else {
rl = null;
}
}
private Entry(EntryData data, @Nullable Entry parent) {
this.data = data;
this.parent = parent;
if (parent == null) {
showToast = false;
announce = false;
rl = bg;
} else {
rl = null;
}
}
public Entry create(String id, Item item, CriterionBuilder builder, String title, String desc) {
return create(id, item.getDefaultInstance(), builder, title, desc);
}
public Entry create(String id, Item item, CriterionBuilder builder, String title, String desc) {
return create(id, item.getDefaultInstance(), builder, title, desc);
}
public Entry create(String id, ItemStack item, CriterionBuilder builder, String title, String desc) {
Entry sub = new Entry(new EntryData(id, item, builder, title, desc), this);
children.add(sub);
return sub;
}
public Entry create(String id, ItemStack item, CriterionBuilder builder, String title, String desc) {
Entry sub = new Entry(new EntryData(id, item, builder, title, desc), this);
children.add(sub);
return sub;
}
/*TODO
public Entry patchouli(L2Registrate reg, CriterionBuilder builder, ResourceLocation book, String title, String desc) {
ItemStack stack = PatchouliHelper.getBook(book);
return create("patchouli", stack, builder, title, desc)
.add(new ModLoadedAdv("patchouli"))
.add(new RewardBuilder(reg, 0, book, () -> PatchouliHelper.getBookLoot(book)));
}*/
.add(new RewardBuilder(reg, 0, ResourceKey.create(Registries.LOOT_TABLE, book), () -> PatchouliHelper.getBookLoot(book)));
}
public Entry root() {
return root;
}
public Entry root() {
return root;
}
public Entry enter() {
return children.getLast();
}
public Entry enter() {
return children.getLast();
}
public Entry type(AdvancementType type) {
this.type = type;
return this;
}
public Entry type(AdvancementType type) {
this.type = type;
return this;
}
public Entry type(AdvancementType type, boolean showToast, boolean announce, boolean hidden) {
this.type = type;
this.showToast = showToast;
this.announce = announce;
this.hidden = hidden;
return this;
}
public Entry type(AdvancementType type, boolean showToast, boolean announce, boolean hidden) {
this.type = type;
this.showToast = showToast;
this.announce = announce;
this.hidden = hidden;
return this;
}
public Entry add(IAdvBuilder builder) {
data.builder.add(builder);
return this;
}
public Entry add(IAdvBuilder builder) {
data.builder.add(builder);
return this;
}
public void build() {
var builder = Advancement.Builder.advancement();
if (!data.item.isEmpty()) {
builder.display(data.item,
pvd.title(modid, tab + "." + data.id, data.title),
pvd.desc(modid, tab + "." + data.id, data.desc),
rl, type, showToast, announce, hidden
);
}
if (parent != null) {
builder.parent(parent.result);
}
public void build() {
var builder = Advancement.Builder.advancement();
if (!data.item.isEmpty()) {
builder.display(data.item,
pvd.title(modid, tab + "." + data.id, data.title),
pvd.desc(modid, tab + "." + data.id, data.desc),
rl, type, showToast, announce, hidden
);
}
if (parent != null) {
builder.parent(parent.result);
}
String uid = modid + ":" + tab + "/" + data.id;
List<ICondition> conditions = new ArrayList<>();
for (var e : data.builder) {
e.onBuild(uid, builder, conditions);
}
Consumer<AdvancementHolder> cons = conditions.isEmpty() ? pvd :
e -> pvd.withConditions(e, conditions);
result = builder.save(cons, uid);
for (Entry e : children) {
e.build();
}
}
String uid = modid + ":" + tab + "/" + data.id;
List<ICondition> conditions = new ArrayList<>();
for (var e : data.builder) {
e.onBuild(uid, builder, conditions);
}
Consumer<AdvancementHolder> cons = conditions.isEmpty() ? pvd :
e -> pvd.withConditions(e, conditions);
result = builder.save(cons, uid);
for (Entry e : children) {
e.build();
}
}
public void finish() {
TabBuilder.this.build();
}
public void finish() {
TabBuilder.this.build();
}
}
}
}
}
private record EntryData(String id, ItemStack item, List<IAdvBuilder> builder, String title, String desc) {
private record EntryData(String id, ItemStack item, List<IAdvBuilder> builder, String title, String desc) {
EntryData(String id, ItemStack item, IAdvBuilder builder, String title, String desc) {
this(id, item, new ArrayList<>(List.of(builder)), title, desc);
}
EntryData(String id, ItemStack item, IAdvBuilder builder, String title, String desc) {
this(id, item, new ArrayList<>(List.of(builder)), title, desc);
}
}
}
}

View File

@@ -17,11 +17,11 @@ import java.util.function.BiConsumer;
public abstract class RecordDataProvider implements DataProvider {
private final DataGenerator generator;
private final HolderLookup.Provider pvd;
private final CompletableFuture<HolderLookup.Provider> pvd;
private final String name;
private final Map<String, Record> map = new HashMap<>();
public RecordDataProvider(DataGenerator generator, HolderLookup.Provider pvd, String name) {
public RecordDataProvider(DataGenerator generator, CompletableFuture<HolderLookup.Provider> pvd, String name) {
this.generator = generator;
this.pvd = pvd;
this.name = name;
@@ -30,18 +30,19 @@ public abstract class RecordDataProvider implements DataProvider {
public abstract void add(BiConsumer<String, Record> map);
public CompletableFuture<?> run(CachedOutput cache) {
Path folder = this.generator.getPackOutput().getOutputFolder();
this.add(this.map::put);
List<CompletableFuture<?>> list = new ArrayList<>();
this.map.forEach((k, v) -> {
JsonElement elem = new JsonCodec(pvd).toJson(v);
if (elem != null) {
Path path = folder.resolve("data/" + k + ".json");
list.add(DataProvider.saveStable(cache, elem, path));
}
return pvd.thenCompose(pvd -> {
Path folder = this.generator.getPackOutput().getOutputFolder();
this.add(this.map::put);
List<CompletableFuture<?>> list = new ArrayList<>();
this.map.forEach((k, v) -> {
JsonElement elem = new JsonCodec(pvd).toJson(v);
if (elem != null) {
Path path = folder.resolve("data/" + k + ".json");
list.add(DataProvider.saveStable(cache, elem, path));
}
});
return CompletableFuture.allOf(list.toArray(CompletableFuture[]::new));
});
return CompletableFuture.allOf(list.toArray(CompletableFuture[]::new));
}
public String getName() {