finish logic for entity ingrs

This commit is contained in:
petrak@ 2022-12-28 14:11:28 -05:00
parent 2acf7920b5
commit c3ebba18f0
14 changed files with 797 additions and 696 deletions

View file

@ -8,7 +8,7 @@ import at.petrak.hexcasting.api.utils.TAU
import at.petrak.hexcasting.api.utils.getValue import at.petrak.hexcasting.api.utils.getValue
import at.petrak.hexcasting.api.utils.setValue import at.petrak.hexcasting.api.utils.setValue
import at.petrak.hexcasting.api.utils.weakMapped import at.petrak.hexcasting.api.utils.weakMapped
import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.BrainsweepIngredient import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.BrainsweepeeIngredient
import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.DefaultVertexFormat import com.mojang.blaze3d.vertex.DefaultVertexFormat
import com.mojang.blaze3d.vertex.PoseStack import com.mojang.blaze3d.vertex.PoseStack
@ -422,7 +422,7 @@ fun transferMsToGl(ms: PoseStack, toRun: Runnable) {
private var villager: Villager? by weakMapped(Villager::level) private var villager: Villager? by weakMapped(Villager::level)
fun prepareVillagerForRendering(ingredient: BrainsweepIngredient, level: Level): Villager { fun prepareVillagerForRendering(ingredient: BrainsweepeeIngredient, level: Level): Villager {
throw NotImplementedError() throw NotImplementedError()
/* /*
val minLevel: Int = ingredient.minLevel() val minLevel: Int = ingredient.minLevel()

View file

@ -2,7 +2,7 @@ package at.petrak.hexcasting.common.recipe;
import at.petrak.hexcasting.common.recipe.ingredient.StateIngredient; import at.petrak.hexcasting.common.recipe.ingredient.StateIngredient;
import at.petrak.hexcasting.common.recipe.ingredient.StateIngredientHelper; import at.petrak.hexcasting.common.recipe.ingredient.StateIngredientHelper;
import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.BrainsweepIngredient; import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.BrainsweepeeIngredient;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -22,91 +22,91 @@ import org.jetbrains.annotations.NotNull;
// God I am a horrible person // God I am a horrible person
public record BrainsweepRecipe( public record BrainsweepRecipe(
ResourceLocation id, ResourceLocation id,
StateIngredient blockIn, StateIngredient blockIn,
BrainsweepIngredient entityIn, BrainsweepeeIngredient entityIn,
int mediaCost, int mediaCost,
BlockState result BlockState result
) implements Recipe<Container> { ) implements Recipe<Container> {
public boolean matches(BlockState blockIn, Entity victim, ServerLevel level) { public boolean matches(BlockState blockIn, Entity victim, ServerLevel level) {
return this.blockIn.test(blockIn) && this.entityIn.test(victim, level); return this.blockIn.test(blockIn) && this.entityIn.test(victim, level);
} }
@Override @Override
public ResourceLocation getId() { public ResourceLocation getId() {
return id; return id;
} }
@Override @Override
public RecipeType<?> getType() { public RecipeType<?> getType() {
return HexRecipeStuffRegistry.BRAINSWEEP_TYPE; return HexRecipeStuffRegistry.BRAINSWEEP_TYPE;
} }
@Override @Override
public RecipeSerializer<?> getSerializer() { public RecipeSerializer<?> getSerializer() {
return HexRecipeStuffRegistry.BRAINSWEEP; return HexRecipeStuffRegistry.BRAINSWEEP;
} }
// in order to get this to be a "Recipe" we need to do a lot of bending-over-backwards // in order to get this to be a "Recipe" we need to do a lot of bending-over-backwards
// to get the implementation to be satisfied even though we never use it // to get the implementation to be satisfied even though we never use it
@Override @Override
public boolean matches(Container pContainer, Level pLevel) { public boolean matches(Container pContainer, Level pLevel) {
return false; return false;
} }
@Override @Override
public ItemStack assemble(Container pContainer) { public ItemStack assemble(Container pContainer) {
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
@Override @Override
public boolean canCraftInDimensions(int pWidth, int pHeight) { public boolean canCraftInDimensions(int pWidth, int pHeight) {
return false; return false;
} }
@Override @Override
public ItemStack getResultItem() { public ItemStack getResultItem() {
return ItemStack.EMPTY.copy(); return ItemStack.EMPTY.copy();
} }
// Because kotlin doesn't like doing raw, unchecked types // Because kotlin doesn't like doing raw, unchecked types
// Can't blame it, but that's what we need to do // Can't blame it, but that's what we need to do
@SuppressWarnings({"rawtypes", "unchecked"}) @SuppressWarnings({"rawtypes", "unchecked"})
public static BlockState copyProperties(BlockState original, BlockState copyTo) { public static BlockState copyProperties(BlockState original, BlockState copyTo) {
for (Property prop : original.getProperties()) { for (Property prop : original.getProperties()) {
if (copyTo.hasProperty(prop)) { if (copyTo.hasProperty(prop)) {
copyTo = copyTo.setValue(prop, original.getValue(prop)); copyTo = copyTo.setValue(prop, original.getValue(prop));
} }
} }
return copyTo; return copyTo;
} }
public static class Serializer extends RecipeSerializerBase<BrainsweepRecipe> { public static class Serializer extends RecipeSerializerBase<BrainsweepRecipe> {
@Override @Override
public @NotNull BrainsweepRecipe fromJson(ResourceLocation recipeID, JsonObject json) { public @NotNull BrainsweepRecipe fromJson(ResourceLocation recipeID, JsonObject json) {
var blockIn = StateIngredientHelper.deserialize(GsonHelper.getAsJsonObject(json, "blockIn")); var blockIn = StateIngredientHelper.deserialize(GsonHelper.getAsJsonObject(json, "blockIn"));
var villagerIn = BrainsweepIngredient.deserialize(GsonHelper.getAsJsonObject(json, "entityIn")); var villagerIn = BrainsweepeeIngredient.deserialize(GsonHelper.getAsJsonObject(json, "entityIn"));
var cost = GsonHelper.getAsInt(json, "cost"); var cost = GsonHelper.getAsInt(json, "cost");
var result = StateIngredientHelper.readBlockState(GsonHelper.getAsJsonObject(json, "result")); var result = StateIngredientHelper.readBlockState(GsonHelper.getAsJsonObject(json, "result"));
return new BrainsweepRecipe(recipeID, blockIn, villagerIn, cost, result); return new BrainsweepRecipe(recipeID, blockIn, villagerIn, cost, result);
} }
@Override @Override
public void toNetwork(FriendlyByteBuf buf, BrainsweepRecipe recipe) { public void toNetwork(FriendlyByteBuf buf, BrainsweepRecipe recipe) {
recipe.blockIn.write(buf); recipe.blockIn.write(buf);
recipe.entityIn.write(buf); recipe.entityIn.write(buf);
buf.writeVarInt(recipe.mediaCost); buf.writeVarInt(recipe.mediaCost);
buf.writeVarInt(Block.getId(recipe.result)); buf.writeVarInt(Block.getId(recipe.result));
} }
@Override @Override
public @NotNull BrainsweepRecipe fromNetwork(ResourceLocation recipeID, FriendlyByteBuf buf) { public @NotNull BrainsweepRecipe fromNetwork(ResourceLocation recipeID, FriendlyByteBuf buf) {
var blockIn = StateIngredientHelper.read(buf); var blockIn = StateIngredientHelper.read(buf);
var villagerIn = BrainsweepIngredient.read(buf); var villagerIn = BrainsweepeeIngredient.read(buf);
var cost = buf.readVarInt(); var cost = buf.readVarInt();
var result = Block.stateById(buf.readVarInt()); var result = Block.stateById(buf.readVarInt());
return new BrainsweepRecipe(recipeID, blockIn, villagerIn, cost, result); return new BrainsweepRecipe(recipeID, blockIn, villagerIn, cost, result);
} }
} }
} }

View file

@ -1,52 +0,0 @@
package at.petrak.hexcasting.common.recipe.ingredient.brainsweep;
import com.google.gson.JsonObject;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.GsonHelper;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.entity.Entity;
import java.util.List;
public abstract class BrainsweepIngredient {
public abstract boolean test(Entity entity, ServerLevel level);
public abstract List<Component> getTooltip(boolean advanced);
public abstract JsonObject serialize();
public abstract void write(FriendlyByteBuf buf);
public abstract Entity exampleEntity(ClientLevel level);
public static BrainsweepIngredient read(FriendlyByteBuf buf) {
var type = buf.readVarInt();
return switch (Type.values()[type]) {
case VILLAGER -> VillagerBrainsweepIngredient.read(buf);
case ENTITY -> EntityBrainsweepIngredient.read(buf);
};
}
public static BrainsweepIngredient deserialize(JsonObject json) {
var typestr = GsonHelper.getAsString(json, "type");
var type = Type.valueOf(typestr);
return switch (type) {
case VILLAGER -> VillagerBrainsweepIngredient.deserialize(json);
case ENTITY -> EntityBrainsweepIngredient.deserialize(json);
};
}
public enum Type implements StringRepresentable {
VILLAGER,
ENTITY;
@Override
public String getSerializedName() {
return this.toString();
}
}
}

View file

@ -0,0 +1,67 @@
package at.petrak.hexcasting.common.recipe.ingredient.brainsweep;
import com.google.gson.JsonObject;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.GsonHelper;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.entity.Entity;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Locale;
// Partially based on:
// https://github.com/SlimeKnights/Mantle/blob/1.18.2/src/main/java/slimeknights/mantle/recipe/ingredient/EntityIngredient.java
// Licensed under MIT
public abstract class BrainsweepeeIngredient {
public abstract boolean test(Entity entity, ServerLevel level);
public abstract List<Component> getTooltip(boolean advanced);
public abstract JsonObject serialize();
public abstract void write(FriendlyByteBuf buf);
/**
* For the benefit of showing to the client, return an example of the entity.
* <p>
* Can return null in case someone did something stupid with a recipe
*/
@Nullable
public abstract Entity exampleEntity(ClientLevel level);
public static BrainsweepeeIngredient read(FriendlyByteBuf buf) {
var type = buf.readVarInt();
return switch (Type.values()[type]) {
case VILLAGER -> VillagerIngredient.read(buf);
case ENTITY_TYPE -> EntityTypeIngredient.read(buf);
case ENTITY_TAG -> EntityTagIngredient.read(buf);
};
}
public static BrainsweepeeIngredient deserialize(JsonObject json) {
var typestr = GsonHelper.getAsString(json, "type");
var type = Type.valueOf(typestr.toUpperCase(Locale.ROOT));
return switch (type) {
case VILLAGER -> VillagerIngredient.deserialize(json);
case ENTITY_TYPE -> EntityTypeIngredient.deserialize(json);
case ENTITY_TAG -> EntityTagIngredient.deserialize(json);
};
}
// TODO: make this a registry?
public enum Type implements StringRepresentable {
VILLAGER,
ENTITY_TYPE,
ENTITY_TAG;
@Override
public String getSerializedName() {
return this.name().toLowerCase(Locale.ROOT);
}
}
}

View file

@ -1,71 +0,0 @@
package at.petrak.hexcasting.common.recipe.ingredient.brainsweep;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.minecraft.advancements.critereon.EntityPredicate;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import java.util.List;
// Code based on:
// https://github.com/SlimeKnights/Mantle/blob/1.18.2/src/main/java/slimeknights/mantle/recipe/ingredient/EntityIngredient.java
// Licensed under MIT
public class EntityBrainsweepIngredient extends BrainsweepIngredient {
public static final Gson GSON = new GsonBuilder().create();
public final EntityPredicate requirements;
// Just tell the player what it is you want
public final Component tooltip;
public EntityBrainsweepIngredient(EntityPredicate requirements, Component tooltip) {
this.requirements = requirements;
this.tooltip = tooltip;
}
@Override
public boolean test(Entity entity, ServerLevel level) {
return this.requirements.matches(level, null, entity);
}
@Override
public List<Component> getTooltip(boolean advanced) {
return List.of(this.tooltip);
}
@Override
public JsonObject serialize() {
var obj = new JsonObject();
obj.addProperty("type", "entity");
obj.add("requirements", this.requirements.serializeToJson());
obj.addProperty("tooltip", Component.Serializer.toJson(this.tooltip));
return obj;
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeVarInt(Type.ENTITY.ordinal());
buf.writeUtf(this.requirements.serializeToJson().toString());
buf.writeUtf(Component.Serializer.toJson(this.tooltip));
}
public static EntityBrainsweepIngredient deserialize(JsonObject obj) {
var reqs = EntityPredicate.fromJson(obj.get("requirements"));
var tooltip = Component.Serializer.fromJson(obj.get("tooltip"));
return new EntityBrainsweepIngredient(reqs, tooltip);
}
public static EntityBrainsweepIngredient read(FriendlyByteBuf buf) {
var reqsObj = GSON.fromJson(buf.readUtf(), JsonElement.class);
var reqs = EntityPredicate.fromJson(reqsObj);
var tooltip = Component.Serializer.fromJson(buf.readUtf());
return new EntityBrainsweepIngredient(reqs, tooltip);
}
}

View file

@ -0,0 +1,89 @@
package at.petrak.hexcasting.common.recipe.ingredient.brainsweep;
import com.google.gson.JsonObject;
import net.minecraft.ChatFormatting;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.resources.language.I18n;
import net.minecraft.core.Registry;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.TagKey;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import java.util.ArrayList;
import java.util.List;
public class EntityTagIngredient extends BrainsweepeeIngredient {
public final TagKey<EntityType<?>> entityTypeTag;
public EntityTagIngredient(TagKey<EntityType<?>> tag) {
this.entityTypeTag = tag;
}
@Override
public boolean test(Entity entity, ServerLevel level) {
return entity.getType().is(this.entityTypeTag);
}
@Override
public List<Component> getTooltip(boolean advanced) {
String key = "tag."
+ this.entityTypeTag.location().getNamespace()
+ "."
+ this.entityTypeTag.location().getPath().replace('/', '.');
boolean moddersDidAGoodJob = I18n.exists(key);
var out = new ArrayList<Component>();
out.add(moddersDidAGoodJob
? Component.translatable(key)
: Component.literal("#" + entityTypeTag));
if (advanced && moddersDidAGoodJob) {
out.add(Component.literal("#" + entityTypeTag).withStyle(ChatFormatting.DARK_GRAY));
}
return out;
}
@Override
public Entity exampleEntity(ClientLevel level) {
var someEntityTys = Registry.ENTITY_TYPE.getTagOrEmpty(this.entityTypeTag).iterator();
if (someEntityTys.hasNext()) {
var someTy = someEntityTys.next();
return someTy.value().create(level);
} else {
return null;
}
}
@Override
public JsonObject serialize() {
var obj = new JsonObject();
obj.addProperty("type", Type.ENTITY_TAG.getSerializedName());
obj.addProperty("tag", this.entityTypeTag.location().toString());
return obj;
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeVarInt(Type.ENTITY_TAG.ordinal());
buf.writeResourceLocation(this.entityTypeTag.location());
}
public static EntityTagIngredient deserialize(JsonObject obj) {
var typeLoc = ResourceLocation.tryParse(GsonHelper.getAsString(obj, "entityType"));
var type = TagKey.create(Registry.ENTITY_TYPE_REGISTRY, typeLoc);
return new EntityTagIngredient(type);
}
public static EntityTagIngredient read(FriendlyByteBuf buf) {
var typeLoc = buf.readResourceLocation();
var type = TagKey.create(Registry.ENTITY_TYPE_REGISTRY, typeLoc);
return new EntityTagIngredient(type);
}
}

View file

@ -0,0 +1,67 @@
package at.petrak.hexcasting.common.recipe.ingredient.brainsweep;
import com.google.gson.JsonObject;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.Registry;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import java.util.List;
public class EntityTypeIngredient extends BrainsweepeeIngredient {
public final EntityType<?> entityType;
public EntityTypeIngredient(EntityType<?> entityType) {
this.entityType = entityType;
}
@Override
public boolean test(Entity entity, ServerLevel level) {
// entity types are singletons
return entity.getType() == this.entityType;
}
@Override
public List<Component> getTooltip(boolean advanced) {
return List.of(this.entityType.getDescription());
}
@Override
public Entity exampleEntity(ClientLevel level) {
return this.entityType.create(level);
}
@Override
public JsonObject serialize() {
var obj = new JsonObject();
obj.addProperty("type", Type.ENTITY_TYPE.getSerializedName());
obj.addProperty("entityType", Registry.ENTITY_TYPE.getKey(this.entityType).toString());
return obj;
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeVarInt(Type.ENTITY_TYPE.ordinal());
buf.writeVarInt(Registry.ENTITY_TYPE.getId(this.entityType));
}
public static EntityTypeIngredient deserialize(JsonObject obj) {
var typeLoc = ResourceLocation.tryParse(GsonHelper.getAsString(obj, "entityType"));
if (!Registry.ENTITY_TYPE.containsKey(typeLoc)) {
throw new IllegalArgumentException("unknown entity type " + typeLoc);
}
return new EntityTypeIngredient(Registry.ENTITY_TYPE.get(typeLoc));
}
public static EntityTypeIngredient read(FriendlyByteBuf buf) {
var tyId = buf.readVarInt();
return new EntityTypeIngredient(Registry.ENTITY_TYPE.byId(tyId));
}
}

View file

@ -1,200 +0,0 @@
package at.petrak.hexcasting.common.recipe.ingredient.brainsweep;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import com.google.gson.JsonObject;
import net.minecraft.ChatFormatting;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.Registry;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.npc.Villager;
import net.minecraft.world.entity.npc.VillagerProfession;
import net.minecraft.world.entity.npc.VillagerType;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Special case for villagers so we can have biome/profession/level reqs
*/
public class VillagerBrainsweepIngredient extends BrainsweepIngredient {
public final @Nullable ResourceLocation profession;
public final @Nullable ResourceLocation biome;
public final int minLevel;
public VillagerBrainsweepIngredient(
@Nullable ResourceLocation profession,
@Nullable ResourceLocation biome, // aka their "type"
int minLevel
) {
this.profession = profession;
this.biome = biome;
this.minLevel = minLevel;
}
@Override
public boolean test(Entity entity, ServerLevel level) {
if (!(entity instanceof Villager villager)) return false;
var data = villager.getVillagerData();
ResourceLocation profID = IXplatAbstractions.INSTANCE.getID(data.getProfession());
return (this.profession == null || this.profession.equals(profID))
&& (this.biome == null || this.biome.equals(Registry.VILLAGER_TYPE.getKey(data.getType())))
&& this.minLevel <= data.getLevel();
}
@Override
public Entity exampleEntity(ClientLevel level) {
var type = this.biome == null
? VillagerType.PLAINS
: Registry.VILLAGER_TYPE.get(this.biome);
var out = new Villager(EntityType.VILLAGER, level, type);
var profession = this.profession == null
? VillagerProfession.TOOLSMITH
: Registry.VILLAGER_PROFESSION.get(this.profession);
out.getVillagerData().setProfession(profession);
out.getVillagerData().setLevel(Math.max(this.minLevel, 1));
return out;
}
@Override
public List<Component> getTooltip(boolean advanced) {
List<Component> tooltip = new ArrayList<>();
tooltip.add(name());
if (advanced) {
if (minLevel >= 5) {
tooltip.add(Component.translatable("hexcasting.tooltip.brainsweep.level", 5)
.withStyle(ChatFormatting.DARK_GRAY));
} else if (minLevel > 1) {
tooltip.add(Component.translatable("hexcasting.tooltip.brainsweep.min_level", minLevel)
.withStyle(ChatFormatting.DARK_GRAY));
}
if (biome != null) {
tooltip.add(Component.literal(biome.toString()).withStyle(ChatFormatting.DARK_GRAY));
}
ResourceLocation displayId = Objects.requireNonNullElseGet(profession,
() -> Registry.ENTITY_TYPE.getKey(EntityType.VILLAGER));
tooltip.add(Component.literal(displayId.toString()).withStyle(ChatFormatting.DARK_GRAY));
}
tooltip.add(getModNameComponent());
return tooltip;
}
public Component name() {
MutableComponent component = Component.literal("");
boolean addedAny = false;
if (minLevel >= 5) {
component.append(Component.translatable("merchant.level.5"));
addedAny = true;
} else if (minLevel > 1) {
component.append(Component.translatable("merchant.level." + minLevel));
addedAny = true;
} else if (profession != null) {
component.append(Component.translatable("merchant.level.1"));
addedAny = true;
}
if (biome != null) {
if (addedAny) {
component.append(" ");
}
component.append(Component.translatable("biome.minecraft." + biome.getPath()));
addedAny = true;
}
if (profession != null) {
// We've for sure added something
component.append(" ");
component.append(Component.translatable("entity.minecraft.villager." + profession.getPath()));
} else {
if (addedAny) {
component.append(" ");
}
component.append(EntityType.VILLAGER.getDescription());
}
return component;
}
public Component getModNameComponent() {
String namespace = profession == null ? "minecraft" : profession.getNamespace();
String mod = IXplatAbstractions.INSTANCE.getModName(namespace);
return Component.literal(mod).withStyle(ChatFormatting.BLUE, ChatFormatting.ITALIC);
}
@Override
public JsonObject serialize() {
var obj = new JsonObject();
if (this.profession != null) {
obj.addProperty("profession", this.profession.toString());
}
if (this.biome != null) {
obj.addProperty("biome", this.biome.toString());
}
obj.addProperty("minLevel", this.minLevel);
return obj;
}
@Override
public void write(FriendlyByteBuf buf) {
if (this.profession != null) {
buf.writeVarInt(1);
buf.writeResourceLocation(this.profession);
} else {
buf.writeVarInt(0);
}
if (this.biome != null) {
buf.writeVarInt(1);
buf.writeResourceLocation(this.biome);
} else {
buf.writeVarInt(0);
}
buf.writeInt(this.minLevel);
}
public static VillagerBrainsweepIngredient deserialize(JsonObject json) {
ResourceLocation profession = null;
if (json.has("profession") && !json.get("profession").isJsonNull()) {
profession = new ResourceLocation(GsonHelper.getAsString(json, "profession"));
}
ResourceLocation biome = null;
if (json.has("biome") && !json.get("biome").isJsonNull()) {
biome = new ResourceLocation(GsonHelper.getAsString(json, "biome"));
}
int minLevel = GsonHelper.getAsInt(json, "minLevel");
int cost = GsonHelper.getAsInt(json, "cost");
return new VillagerBrainsweepIngredient(profession, biome, minLevel);
}
public static VillagerBrainsweepIngredient read(FriendlyByteBuf buf) {
ResourceLocation profession = null;
var hasProfession = buf.readVarInt();
if (hasProfession != 0) {
profession = buf.readResourceLocation();
}
ResourceLocation biome = null;
var hasBiome = buf.readVarInt();
if (hasBiome != 0) {
biome = buf.readResourceLocation();
}
int minLevel = buf.readInt();
return new VillagerBrainsweepIngredient(profession, biome, minLevel);
}
}

View file

@ -0,0 +1,202 @@
package at.petrak.hexcasting.common.recipe.ingredient.brainsweep;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import com.google.gson.JsonObject;
import net.minecraft.ChatFormatting;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.Registry;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.npc.Villager;
import net.minecraft.world.entity.npc.VillagerProfession;
import net.minecraft.world.entity.npc.VillagerType;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Special case for villagers so we can have biome/profession/level reqs
*/
public class VillagerIngredient extends BrainsweepeeIngredient {
public final @Nullable ResourceLocation profession;
public final @Nullable ResourceLocation biome;
public final int minLevel;
public VillagerIngredient(
@Nullable ResourceLocation profession,
@Nullable ResourceLocation biome, // aka their "type"
int minLevel
) {
this.profession = profession;
this.biome = biome;
this.minLevel = minLevel;
}
@Override
public boolean test(Entity entity, ServerLevel level) {
if (!(entity instanceof Villager villager)) return false;
var data = villager.getVillagerData();
ResourceLocation profID = IXplatAbstractions.INSTANCE.getID(data.getProfession());
return (this.profession == null || this.profession.equals(profID))
&& (this.biome == null || this.biome.equals(Registry.VILLAGER_TYPE.getKey(data.getType())))
&& this.minLevel <= data.getLevel();
}
@Override
public Entity exampleEntity(ClientLevel level) {
var type = this.biome == null
? VillagerType.PLAINS
: Registry.VILLAGER_TYPE.get(this.biome);
var out = new Villager(EntityType.VILLAGER, level, type);
var profession = this.profession == null
? VillagerProfession.TOOLSMITH
: Registry.VILLAGER_PROFESSION.get(this.profession);
out.getVillagerData().setProfession(profession);
out.getVillagerData().setLevel(Math.max(this.minLevel, 1));
return out;
}
@Override
public List<Component> getTooltip(boolean advanced) {
List<Component> tooltip = new ArrayList<>();
tooltip.add(name());
if (advanced) {
if (minLevel >= 5) {
tooltip.add(Component.translatable("hexcasting.tooltip.brainsweep.level", 5)
.withStyle(ChatFormatting.DARK_GRAY));
} else if (minLevel > 1) {
tooltip.add(Component.translatable("hexcasting.tooltip.brainsweep.min_level", minLevel)
.withStyle(ChatFormatting.DARK_GRAY));
}
if (biome != null) {
tooltip.add(Component.literal(biome.toString()).withStyle(ChatFormatting.DARK_GRAY));
}
ResourceLocation displayId = Objects.requireNonNullElseGet(profession,
() -> Registry.ENTITY_TYPE.getKey(EntityType.VILLAGER));
tooltip.add(Component.literal(displayId.toString()).withStyle(ChatFormatting.DARK_GRAY));
}
tooltip.add(getModNameComponent());
return tooltip;
}
public Component name() {
MutableComponent component = Component.literal("");
boolean addedAny = false;
if (minLevel >= 5) {
component.append(Component.translatable("merchant.level.5"));
addedAny = true;
} else if (minLevel > 1) {
component.append(Component.translatable("merchant.level." + minLevel));
addedAny = true;
} else if (profession != null) {
component.append(Component.translatable("merchant.level.1"));
addedAny = true;
}
if (biome != null) {
if (addedAny) {
component.append(" ");
}
component.append(Component.translatable("biome.minecraft." + biome.getPath()));
addedAny = true;
}
if (profession != null) {
// We've for sure added something
component.append(" ");
component.append(Component.translatable("entity.minecraft.villager." + profession.getPath()));
} else {
if (addedAny) {
component.append(" ");
}
component.append(EntityType.VILLAGER.getDescription());
}
return component;
}
public Component getModNameComponent() {
String namespace = profession == null ? "minecraft" : profession.getNamespace();
String mod = IXplatAbstractions.INSTANCE.getModName(namespace);
return Component.literal(mod).withStyle(ChatFormatting.BLUE, ChatFormatting.ITALIC);
}
@Override
public JsonObject serialize() {
var obj = new JsonObject();
obj.addProperty("type", Type.VILLAGER.getSerializedName());
if (this.profession != null) {
obj.addProperty("profession", this.profession.toString());
}
if (this.biome != null) {
obj.addProperty("biome", this.biome.toString());
}
obj.addProperty("minLevel", this.minLevel);
return obj;
}
@Override
public void write(FriendlyByteBuf buf) {
if (this.profession != null) {
buf.writeVarInt(1);
buf.writeResourceLocation(this.profession);
} else {
buf.writeVarInt(0);
}
if (this.biome != null) {
buf.writeVarInt(1);
buf.writeResourceLocation(this.biome);
} else {
buf.writeVarInt(0);
}
buf.writeInt(this.minLevel);
}
public static VillagerIngredient deserialize(JsonObject json) {
ResourceLocation profession = null;
if (json.has("profession") && !json.get("profession").isJsonNull()) {
profession = new ResourceLocation(GsonHelper.getAsString(json, "profession"));
}
ResourceLocation biome = null;
if (json.has("biome") && !json.get("biome").isJsonNull()) {
biome = new ResourceLocation(GsonHelper.getAsString(json, "biome"));
}
int minLevel = GsonHelper.getAsInt(json, "minLevel");
int cost = GsonHelper.getAsInt(json, "cost");
return new VillagerIngredient(profession, biome, minLevel);
}
public static VillagerIngredient read(FriendlyByteBuf buf) {
ResourceLocation profession = null;
var hasProfession = buf.readVarInt();
if (hasProfession != 0) {
profession = buf.readResourceLocation();
}
ResourceLocation biome = null;
var hasBiome = buf.readVarInt();
if (hasBiome != 0) {
biome = buf.readResourceLocation();
}
int minLevel = buf.readInt();
return new VillagerIngredient(profession, biome, minLevel);
}
}

View file

@ -3,7 +3,6 @@ package at.petrak.hexcasting.datagen.recipe
import at.petrak.hexcasting.api.HexAPI import at.petrak.hexcasting.api.HexAPI
import at.petrak.hexcasting.api.advancements.OvercastTrigger import at.petrak.hexcasting.api.advancements.OvercastTrigger
import at.petrak.hexcasting.api.misc.MediaConstants import at.petrak.hexcasting.api.misc.MediaConstants
import at.petrak.hexcasting.api.mod.HexItemTags
import at.petrak.hexcasting.common.items.ItemStaff import at.petrak.hexcasting.common.items.ItemStaff
import at.petrak.hexcasting.common.items.colorizer.ItemPrideColorizer import at.petrak.hexcasting.common.items.colorizer.ItemPrideColorizer
import at.petrak.hexcasting.common.lib.HexBlocks import at.petrak.hexcasting.common.lib.HexBlocks
@ -11,7 +10,7 @@ import at.petrak.hexcasting.common.lib.HexItems
import at.petrak.hexcasting.common.recipe.SealFocusRecipe import at.petrak.hexcasting.common.recipe.SealFocusRecipe
import at.petrak.hexcasting.common.recipe.SealSpellbookRecipe import at.petrak.hexcasting.common.recipe.SealSpellbookRecipe
import at.petrak.hexcasting.common.recipe.ingredient.StateIngredientHelper import at.petrak.hexcasting.common.recipe.ingredient.StateIngredientHelper
import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.VillagerBrainsweepIngredient import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.VillagerIngredient
import at.petrak.hexcasting.datagen.IXplatConditionsBuilder import at.petrak.hexcasting.datagen.IXplatConditionsBuilder
import at.petrak.hexcasting.datagen.IXplatIngredients import at.petrak.hexcasting.datagen.IXplatIngredients
import at.petrak.hexcasting.datagen.recipe.builders.BrainsweepRecipeBuilder import at.petrak.hexcasting.datagen.recipe.builders.BrainsweepRecipeBuilder
@ -352,37 +351,37 @@ class HexplatRecipes(
.unlockedBy("enlightenment", enlightenment).save(recipes) .unlockedBy("enlightenment", enlightenment).save(recipes)
BrainsweepRecipeBuilder(StateIngredientHelper.of(Blocks.AMETHYST_BLOCK), BrainsweepRecipeBuilder(StateIngredientHelper.of(Blocks.AMETHYST_BLOCK),
VillagerBrainsweepIngredient(null, null, 3), VillagerIngredient(null, null, 3),
Blocks.BUDDING_AMETHYST.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10) Blocks.BUDDING_AMETHYST.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10)
.unlockedBy("enlightenment", enlightenment) .unlockedBy("enlightenment", enlightenment)
.save(recipes, modLoc("brainsweep/budding_amethyst")) .save(recipes, modLoc("brainsweep/budding_amethyst"))
BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.EMPTY_IMPETUS), BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.EMPTY_IMPETUS),
VillagerBrainsweepIngredient(ResourceLocation("toolsmith"), null, 2), VillagerIngredient(ResourceLocation("toolsmith"), null, 2),
HexBlocks.IMPETUS_RIGHTCLICK.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10) HexBlocks.IMPETUS_RIGHTCLICK.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10)
.unlockedBy("enlightenment", enlightenment) .unlockedBy("enlightenment", enlightenment)
.save(recipes, modLoc("brainsweep/impetus_rightclick")) .save(recipes, modLoc("brainsweep/impetus_rightclick"))
BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.EMPTY_IMPETUS), BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.EMPTY_IMPETUS),
VillagerBrainsweepIngredient(ResourceLocation("fletcher"), null, 2), VillagerIngredient(ResourceLocation("fletcher"), null, 2),
HexBlocks.IMPETUS_LOOK.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10) HexBlocks.IMPETUS_LOOK.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10)
.unlockedBy("enlightenment", enlightenment) .unlockedBy("enlightenment", enlightenment)
.save(recipes, modLoc("brainsweep/impetus_look")) .save(recipes, modLoc("brainsweep/impetus_look"))
BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.EMPTY_IMPETUS), BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.EMPTY_IMPETUS),
VillagerBrainsweepIngredient(ResourceLocation("cleric"), null, 2), VillagerIngredient(ResourceLocation("cleric"), null, 2),
HexBlocks.IMPETUS_STOREDPLAYER.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10) HexBlocks.IMPETUS_STOREDPLAYER.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10)
.unlockedBy("enlightenment", enlightenment) .unlockedBy("enlightenment", enlightenment)
.save(recipes, modLoc("brainsweep/impetus_storedplayer")) .save(recipes, modLoc("brainsweep/impetus_storedplayer"))
BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.EMPTY_DIRECTRIX), BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.EMPTY_DIRECTRIX),
VillagerBrainsweepIngredient(ResourceLocation("mason"), null, 1), VillagerIngredient(ResourceLocation("mason"), null, 1),
HexBlocks.DIRECTRIX_REDSTONE.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10) HexBlocks.DIRECTRIX_REDSTONE.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10)
.unlockedBy("enlightenment", enlightenment) .unlockedBy("enlightenment", enlightenment)
.save(recipes, modLoc("brainsweep/directrix_redstone")) .save(recipes, modLoc("brainsweep/directrix_redstone"))
BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.AKASHIC_LIGATURE), BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.AKASHIC_LIGATURE),
VillagerBrainsweepIngredient(ResourceLocation("librarian"), null, 5), VillagerIngredient(ResourceLocation("librarian"), null, 5),
HexBlocks.AKASHIC_RECORD.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10) HexBlocks.AKASHIC_RECORD.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10)
.unlockedBy("enlightenment", enlightenment) .unlockedBy("enlightenment", enlightenment)
.save(recipes, modLoc("brainsweep/akashic_record")) .save(recipes, modLoc("brainsweep/akashic_record"))

View file

@ -3,7 +3,7 @@ package at.petrak.hexcasting.datagen.recipe.builders;
import at.petrak.hexcasting.common.recipe.HexRecipeStuffRegistry; import at.petrak.hexcasting.common.recipe.HexRecipeStuffRegistry;
import at.petrak.hexcasting.common.recipe.ingredient.StateIngredient; import at.petrak.hexcasting.common.recipe.ingredient.StateIngredient;
import at.petrak.hexcasting.common.recipe.ingredient.StateIngredientHelper; import at.petrak.hexcasting.common.recipe.ingredient.StateIngredientHelper;
import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.BrainsweepIngredient; import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.BrainsweepeeIngredient;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import net.minecraft.advancements.Advancement; import net.minecraft.advancements.Advancement;
import net.minecraft.advancements.AdvancementRewards; import net.minecraft.advancements.AdvancementRewards;
@ -21,86 +21,86 @@ import org.jetbrains.annotations.Nullable;
import java.util.function.Consumer; import java.util.function.Consumer;
public class BrainsweepRecipeBuilder implements RecipeBuilder { public class BrainsweepRecipeBuilder implements RecipeBuilder {
private final StateIngredient blockIn; private final StateIngredient blockIn;
private final BrainsweepIngredient villagerIn; private final BrainsweepeeIngredient villagerIn;
private final int mediaCost; private final int mediaCost;
private final BlockState result; private final BlockState result;
private final Advancement.Builder advancement; private final Advancement.Builder advancement;
public BrainsweepRecipeBuilder(StateIngredient blockIn, BrainsweepIngredient villagerIn, BlockState result, public BrainsweepRecipeBuilder(StateIngredient blockIn, BrainsweepeeIngredient villagerIn, BlockState result,
int mediaCost) { int mediaCost) {
this.blockIn = blockIn; this.blockIn = blockIn;
this.villagerIn = villagerIn; this.villagerIn = villagerIn;
this.result = result; this.result = result;
this.mediaCost = mediaCost; this.mediaCost = mediaCost;
this.advancement = Advancement.Builder.advancement(); this.advancement = Advancement.Builder.advancement();
} }
@Override @Override
public RecipeBuilder unlockedBy(String pCriterionName, CriterionTriggerInstance pCriterionTrigger) { public RecipeBuilder unlockedBy(String pCriterionName, CriterionTriggerInstance pCriterionTrigger) {
this.advancement.addCriterion(pCriterionName, pCriterionTrigger); this.advancement.addCriterion(pCriterionName, pCriterionTrigger);
return this; return this;
} }
@Override @Override
public RecipeBuilder group(@Nullable String pGroupName) { public RecipeBuilder group(@Nullable String pGroupName) {
return this; return this;
} }
@Override @Override
public Item getResult() { public Item getResult() {
return this.result.getBlock().asItem(); return this.result.getBlock().asItem();
} }
@Override @Override
public void save(Consumer<FinishedRecipe> pFinishedRecipeConsumer, ResourceLocation pRecipeId) { public void save(Consumer<FinishedRecipe> pFinishedRecipeConsumer, ResourceLocation pRecipeId) {
if (this.advancement.getCriteria().isEmpty()) { if (this.advancement.getCriteria().isEmpty()) {
throw new IllegalStateException("No way of obtaining recipe " + pRecipeId); throw new IllegalStateException("No way of obtaining recipe " + pRecipeId);
} }
this.advancement.parent(new ResourceLocation("recipes/root")) this.advancement.parent(new ResourceLocation("recipes/root"))
.addCriterion("has_the_recipe", RecipeUnlockedTrigger.unlocked(pRecipeId)) .addCriterion("has_the_recipe", RecipeUnlockedTrigger.unlocked(pRecipeId))
.rewards(AdvancementRewards.Builder.recipe(pRecipeId)) .rewards(AdvancementRewards.Builder.recipe(pRecipeId))
.requirements(RequirementsStrategy.OR); .requirements(RequirementsStrategy.OR);
pFinishedRecipeConsumer.accept(new Result( pFinishedRecipeConsumer.accept(new Result(
pRecipeId, pRecipeId,
this.blockIn, this.villagerIn, this.mediaCost, this.result, this.blockIn, this.villagerIn, this.mediaCost, this.result,
this.advancement, this.advancement,
new ResourceLocation(pRecipeId.getNamespace(), "recipes/brainsweep/" + pRecipeId.getPath()))); new ResourceLocation(pRecipeId.getNamespace(), "recipes/brainsweep/" + pRecipeId.getPath())));
} }
public record Result(ResourceLocation id, StateIngredient blockIn, BrainsweepIngredient villagerIn, public record Result(ResourceLocation id, StateIngredient blockIn, BrainsweepeeIngredient villagerIn,
int mediaCost, BlockState result, Advancement.Builder advancement, int mediaCost, BlockState result, Advancement.Builder advancement,
ResourceLocation advancementId) implements FinishedRecipe { ResourceLocation advancementId) implements FinishedRecipe {
@Override @Override
public void serializeRecipeData(JsonObject json) { public void serializeRecipeData(JsonObject json) {
json.add("blockIn", this.blockIn.serialize()); json.add("blockIn", this.blockIn.serialize());
json.add("entityIn", this.villagerIn.serialize()); json.add("entityIn", this.villagerIn.serialize());
json.addProperty("cost", this.mediaCost); json.addProperty("cost", this.mediaCost);
json.add("result", StateIngredientHelper.serializeBlockState(this.result)); json.add("result", StateIngredientHelper.serializeBlockState(this.result));
} }
@Override @Override
public ResourceLocation getId() { public ResourceLocation getId() {
return this.id; return this.id;
} }
@Override @Override
public RecipeSerializer<?> getType() { public RecipeSerializer<?> getType() {
return HexRecipeStuffRegistry.BRAINSWEEP; return HexRecipeStuffRegistry.BRAINSWEEP;
} }
@Nullable @Nullable
@Override @Override
public JsonObject serializeAdvancement() { public JsonObject serializeAdvancement() {
return this.advancement.serializeToJson(); return this.advancement.serializeToJson();
} }
@Nullable @Nullable
@Override @Override
public ResourceLocation getAdvancementId() { public ResourceLocation getAdvancementId() {
return this.advancementId; return this.advancementId;
} }
} }
} }

View file

@ -2,8 +2,8 @@ package at.petrak.hexcasting.interop.patchouli;
import at.petrak.hexcasting.common.recipe.BrainsweepRecipe; import at.petrak.hexcasting.common.recipe.BrainsweepRecipe;
import at.petrak.hexcasting.common.recipe.HexRecipeStuffRegistry; import at.petrak.hexcasting.common.recipe.HexRecipeStuffRegistry;
import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.EntityBrainsweepIngredient; import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.EntityTypeIngredient;
import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.VillagerBrainsweepIngredient; import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.VillagerIngredient;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
@ -14,69 +14,69 @@ import vazkii.patchouli.api.IVariableProvider;
import java.util.Objects; import java.util.Objects;
public class BrainsweepProcessor implements IComponentProcessor { public class BrainsweepProcessor implements IComponentProcessor {
private BrainsweepRecipe recipe; private BrainsweepRecipe recipe;
@Override @Override
public void setup(IVariableProvider vars) { public void setup(IVariableProvider vars) {
var id = new ResourceLocation(vars.get("recipe").asString()); var id = new ResourceLocation(vars.get("recipe").asString());
var recman = Minecraft.getInstance().level.getRecipeManager(); var recman = Minecraft.getInstance().level.getRecipeManager();
var brainsweepings = recman.getAllRecipesFor(HexRecipeStuffRegistry.BRAINSWEEP_TYPE); var brainsweepings = recman.getAllRecipesFor(HexRecipeStuffRegistry.BRAINSWEEP_TYPE);
for (var poisonApples : brainsweepings) { for (var poisonApples : brainsweepings) {
if (poisonApples.getId().equals(id)) { if (poisonApples.getId().equals(id)) {
this.recipe = poisonApples; this.recipe = poisonApples;
break; break;
} }
} }
} }
@Override @Override
public IVariable process(String key) { public IVariable process(String key) {
if (this.recipe == null) { if (this.recipe == null) {
return null; return null;
} }
switch (key) { switch (key) {
case "header" -> { case "header" -> {
return IVariable.from(this.recipe.result().getBlock().getName()); return IVariable.from(this.recipe.result().getBlock().getName());
} }
case "input" -> { case "input" -> {
var inputStacks = this.recipe.blockIn().getDisplayedStacks(); var inputStacks = this.recipe.blockIn().getDisplayedStacks();
return IVariable.from(inputStacks.toArray(new ItemStack[0])); return IVariable.from(inputStacks.toArray(new ItemStack[0]));
} }
case "result" -> { case "result" -> {
return IVariable.from(new ItemStack(this.recipe.result().getBlock())); return IVariable.from(new ItemStack(this.recipe.result().getBlock()));
} }
case "entity" -> { case "entity" -> {
if (this.recipe.entityIn() instanceof VillagerBrainsweepIngredient villager) { if (this.recipe.entityIn() instanceof VillagerIngredient villager) {
var profession = Objects.requireNonNullElse(villager.profession, var profession = Objects.requireNonNullElse(villager.profession,
new ResourceLocation("toolsmith")); new ResourceLocation("toolsmith"));
var biome = Objects.requireNonNullElse(villager.biome, var biome = Objects.requireNonNullElse(villager.biome,
new ResourceLocation("plains")); new ResourceLocation("plains"));
var level = villager.minLevel; var level = villager.minLevel;
var iHatePatchouli = String.format( var iHatePatchouli = String.format(
"minecraft:villager{VillagerData:{profession:'%s',type:'%s',level:%d}}", "minecraft:villager{VillagerData:{profession:'%s',type:'%s',level:%d}}",
profession, biome, level); profession, biome, level);
return IVariable.wrap(iHatePatchouli); return IVariable.wrap(iHatePatchouli);
} else if (this.recipe.entityIn() instanceof EntityBrainsweepIngredient entity) { } else if (this.recipe.entityIn() instanceof EntityTypeIngredient entity) {
// TODO // TODO
return IVariable.wrap("minecraft:chicken"); return IVariable.wrap("minecraft:chicken");
} else { } else {
throw new IllegalStateException(); throw new IllegalStateException();
} }
} }
case "entityTooltip" -> { case "entityTooltip" -> {
Minecraft mc = Minecraft.getInstance(); Minecraft mc = Minecraft.getInstance();
return IVariable.wrapList(this.recipe.entityIn() return IVariable.wrapList(this.recipe.entityIn()
.getTooltip(mc.options.advancedItemTooltips) .getTooltip(mc.options.advancedItemTooltips)
.stream() .stream()
.map(IVariable::from) .map(IVariable::from)
.toList()); .toList());
} }
default -> { default -> {
return null; return null;
} }
} }
} }
} }

View file

@ -4,7 +4,7 @@ import at.petrak.hexcasting.client.ClientTickCounter;
import at.petrak.hexcasting.client.RenderLib; import at.petrak.hexcasting.client.RenderLib;
import at.petrak.hexcasting.client.shader.FakeBufferSource; import at.petrak.hexcasting.client.shader.FakeBufferSource;
import at.petrak.hexcasting.client.shader.HexRenderTypes; import at.petrak.hexcasting.client.shader.HexRenderTypes;
import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.BrainsweepIngredient; import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.BrainsweepeeIngredient;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import dev.emi.emi.api.render.EmiRender; import dev.emi.emi.api.render.EmiRender;
@ -34,191 +34,191 @@ import static at.petrak.hexcasting.api.HexAPI.modLoc;
import static at.petrak.hexcasting.client.RenderLib.renderEntity; import static at.petrak.hexcasting.client.RenderLib.renderEntity;
public class BrainsweepeeEmiStack extends EmiStack { public class BrainsweepeeEmiStack extends EmiStack {
private final VillagerEntry entry; private final VillagerEntry entry;
public final BrainsweepIngredient ingredient; public final BrainsweepeeIngredient ingredient;
public final boolean mindless; public final boolean mindless;
private final ResourceLocation id; private final ResourceLocation id;
public BrainsweepeeEmiStack(BrainsweepIngredient villager) { public BrainsweepeeEmiStack(BrainsweepeeIngredient villager) {
this(villager, false); this(villager, false);
} }
public BrainsweepeeEmiStack(BrainsweepIngredient villager, boolean mindless) { public BrainsweepeeEmiStack(BrainsweepeeIngredient villager, boolean mindless) {
this(villager, mindless, 1); this(villager, mindless, 1);
} }
public BrainsweepeeEmiStack(BrainsweepIngredient villager, boolean mindless, long amount) { public BrainsweepeeEmiStack(BrainsweepeeIngredient villager, boolean mindless, long amount) {
entry = new VillagerEntry(new VillagerVariant(villager, mindless)); entry = new VillagerEntry(new VillagerVariant(villager, mindless));
this.ingredient = villager; this.ingredient = villager;
this.mindless = mindless; this.mindless = mindless;
this.amount = amount; this.amount = amount;
// This is so scuffed // This is so scuffed
this.id = modLoc((Objects.toString(villager.profession()) + villager.minLevel() + mindless) this.id = modLoc((Objects.toString(villager.profession()) + villager.minLevel() + mindless)
.replace(':', '-')); .replace(':', '-'));
} }
public static Set<BlockState> matchingStatesForProfession(VillagerProfession profession) { public static Set<BlockState> matchingStatesForProfession(VillagerProfession profession) {
return Registry.POINT_OF_INTEREST_TYPE.holders() return Registry.POINT_OF_INTEREST_TYPE.holders()
.filter(profession.heldJobSite()) .filter(profession.heldJobSite())
.flatMap(it -> it.value().matchingStates().stream()) .flatMap(it -> it.value().matchingStates().stream())
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }
public static EmiIngredient atLevelOrHigher(BrainsweepIngredient ingredient, boolean remainder) { public static EmiIngredient atLevelOrHigher(BrainsweepeeIngredient ingredient, boolean remainder) {
if (ingredient.profession() == null) { if (ingredient.profession() == null) {
return EmiIngredient.of(Registry.VILLAGER_PROFESSION.stream() return EmiIngredient.of(Registry.VILLAGER_PROFESSION.stream()
.filter(it -> matchingStatesForProfession(it).isEmpty()) .filter(it -> matchingStatesForProfession(it).isEmpty())
.map(it -> atLevelOrHigher(new BrainsweepIngredient(Registry.VILLAGER_PROFESSION.getKey(it), .map(it -> atLevelOrHigher(new BrainsweepeeIngredient(Registry.VILLAGER_PROFESSION.getKey(it),
ingredient.biome(), ingredient.minLevel()), true)) ingredient.biome(), ingredient.minLevel()), true))
.toList()); .toList());
} }
BrainsweepeeEmiStack stack = new BrainsweepeeEmiStack(ingredient).orHigher(true); BrainsweepeeEmiStack stack = new BrainsweepeeEmiStack(ingredient).orHigher(true);
if (remainder) { if (remainder) {
stack.setRemainder(new BrainsweepeeEmiStack(ingredient, true)); stack.setRemainder(new BrainsweepeeEmiStack(ingredient, true));
} }
return stack; return stack;
} }
private boolean orHigher = false; private boolean orHigher = false;
public BrainsweepeeEmiStack orHigher(boolean orHigher) { public BrainsweepeeEmiStack orHigher(boolean orHigher) {
this.orHigher = orHigher; this.orHigher = orHigher;
return this; return this;
} }
@Override @Override
public EmiStack copy() { public EmiStack copy() {
BrainsweepeeEmiStack e = new BrainsweepeeEmiStack(ingredient, mindless, amount); BrainsweepeeEmiStack e = new BrainsweepeeEmiStack(ingredient, mindless, amount);
e.orHigher(orHigher).setRemainder(getRemainder().copy()); e.orHigher(orHigher).setRemainder(getRemainder().copy());
e.comparison = comparison; e.comparison = comparison;
return e; return e;
} }
@Override @Override
public boolean isEmpty() { public boolean isEmpty() {
return amount == 0; return amount == 0;
} }
@Override @Override
public CompoundTag getNbt() { public CompoundTag getNbt() {
return null; return null;
} }
@Override @Override
public Object getKey() { public Object getKey() {
return id; return id;
} }
@Override @Override
public Entry<?> getEntry() { public Entry<?> getEntry() {
return entry; return entry;
} }
@Override @Override
public ResourceLocation getId() { public ResourceLocation getId() {
return id; return id;
} }
@Override @Override
public List<Component> getTooltipText() { public List<Component> getTooltipText() {
Minecraft mc = Minecraft.getInstance(); Minecraft mc = Minecraft.getInstance();
boolean advanced = mc.options.advancedItemTooltips; boolean advanced = mc.options.advancedItemTooltips;
if (mindless) { if (mindless) {
List<Component> tooltip = new ArrayList<>(); List<Component> tooltip = new ArrayList<>();
tooltip.add(Component.translatable("hexcasting.tooltip.brainsweep.product")); tooltip.add(Component.translatable("hexcasting.tooltip.brainsweep.product"));
if (advanced) { if (advanced) {
if (ingredient.biome() != null) { if (ingredient.biome() != null) {
tooltip.add(Component.literal(ingredient.biome().toString()).withStyle(ChatFormatting.DARK_GRAY)); tooltip.add(Component.literal(ingredient.biome().toString()).withStyle(ChatFormatting.DARK_GRAY));
} }
ResourceLocation displayId = Objects.requireNonNullElseGet(ingredient.profession(), ResourceLocation displayId = Objects.requireNonNullElseGet(ingredient.profession(),
() -> Registry.ENTITY_TYPE.getKey(EntityType.VILLAGER)); () -> Registry.ENTITY_TYPE.getKey(EntityType.VILLAGER));
tooltip.add(Component.literal(displayId.toString()).withStyle(ChatFormatting.DARK_GRAY)); tooltip.add(Component.literal(displayId.toString()).withStyle(ChatFormatting.DARK_GRAY));
} }
tooltip.add(ingredient.getModNameComponent()); tooltip.add(ingredient.getModNameComponent());
return tooltip; return tooltip;
} }
return ingredient.getTooltip(advanced, orHigher); return ingredient.getTooltip(advanced, orHigher);
} }
@Override @Override
public List<ClientTooltipComponent> getTooltip() { public List<ClientTooltipComponent> getTooltip() {
List<ClientTooltipComponent> list = getTooltipText().stream() List<ClientTooltipComponent> list = getTooltipText().stream()
.map(Component::getVisualOrderText) .map(Component::getVisualOrderText)
.map(ClientTooltipComponent::create) .map(ClientTooltipComponent::create)
.collect(Collectors.toList()); .collect(Collectors.toList());
if (!getRemainder().isEmpty()) { if (!getRemainder().isEmpty()) {
list.add(EmiTooltipComponents.getRemainderTooltipComponent(this)); list.add(EmiTooltipComponents.getRemainderTooltipComponent(this));
} }
return list; return list;
} }
@Override @Override
public Component getName() { public Component getName() {
return ingredient.name(); return ingredient.name();
} }
@Override @Override
public void render(PoseStack poseStack, int x, int y, float delta, int flags) { public void render(PoseStack poseStack, int x, int y, float delta, int flags) {
if ((flags & RENDER_ICON) != 0) { if ((flags & RENDER_ICON) != 0) {
Minecraft mc = Minecraft.getInstance(); Minecraft mc = Minecraft.getInstance();
ClientLevel level = mc.level; ClientLevel level = mc.level;
if (level != null) { if (level != null) {
Villager villager = RenderLib.prepareVillagerForRendering(ingredient, level); Villager villager = RenderLib.prepareVillagerForRendering(ingredient, level);
RenderSystem.enableBlend(); RenderSystem.enableBlend();
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
renderEntity(poseStack, villager, level, x + 8, y + 16, ClientTickCounter.getTotal(), 8, 0, renderEntity(poseStack, villager, level, x + 8, y + 16, ClientTickCounter.getTotal(), 8, 0,
mindless ? (it) -> new FakeBufferSource(it, HexRenderTypes::getGrayscaleLayer) : it -> it); mindless ? (it) -> new FakeBufferSource(it, HexRenderTypes::getGrayscaleLayer) : it -> it);
} }
} }
if ((flags & RENDER_REMAINDER) != 0) { if ((flags & RENDER_REMAINDER) != 0) {
EmiRender.renderRemainderIcon(this, poseStack, x, y); EmiRender.renderRemainderIcon(this, poseStack, x, y);
} }
} }
public static class VillagerEntry extends EmiStack.Entry<VillagerVariant> { public static class VillagerEntry extends EmiStack.Entry<VillagerVariant> {
public VillagerEntry(VillagerVariant variant) { public VillagerEntry(VillagerVariant variant) {
super(variant); super(variant);
} }
@Override @Override
public Class<? extends VillagerVariant> getType() { public Class<? extends VillagerVariant> getType() {
return VillagerVariant.class; return VillagerVariant.class;
} }
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (!(obj instanceof VillagerEntry e)) { if (!(obj instanceof VillagerEntry e)) {
return false; return false;
} }
VillagerVariant self = getValue(); VillagerVariant self = getValue();
VillagerVariant other = e.getValue(); VillagerVariant other = e.getValue();
ResourceLocation selfBiome = self.ingredient().biome(); ResourceLocation selfBiome = self.ingredient().biome();
ResourceLocation otherBiome = other.ingredient().biome(); ResourceLocation otherBiome = other.ingredient().biome();
if (selfBiome != null && otherBiome != null && !selfBiome.equals(otherBiome)) { if (selfBiome != null && otherBiome != null && !selfBiome.equals(otherBiome)) {
return false; return false;
} }
ResourceLocation selfProfession = self.ingredient().profession(); ResourceLocation selfProfession = self.ingredient().profession();
ResourceLocation otherProfession = other.ingredient().profession(); ResourceLocation otherProfession = other.ingredient().profession();
if (selfProfession != null && otherProfession != null && !selfProfession.equals(otherProfession)) { if (selfProfession != null && otherProfession != null && !selfProfession.equals(otherProfession)) {
return false; return false;
} }
return self.ingredient().minLevel() == other.ingredient().minLevel() && self.mindless() == other.mindless(); return self.ingredient().minLevel() == other.ingredient().minLevel() && self.mindless() == other.mindless();
} }
} }
} }

View file

@ -1,7 +1,7 @@
package at.petrak.hexcasting.fabric.interop.emi; package at.petrak.hexcasting.fabric.interop.emi;
import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.BrainsweepIngredient; import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.BrainsweepeeIngredient;
public record VillagerVariant(BrainsweepIngredient ingredient, boolean mindless) { public record VillagerVariant(BrainsweepeeIngredient ingredient, boolean mindless) {
// NO-OP // NO-OP
} }