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.setValue
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.vertex.DefaultVertexFormat
import com.mojang.blaze3d.vertex.PoseStack
@ -422,7 +422,7 @@ fun transferMsToGl(ms: PoseStack, toRun: Runnable) {
private var villager: Villager? by weakMapped(Villager::level)
fun prepareVillagerForRendering(ingredient: BrainsweepIngredient, level: Level): Villager {
fun prepareVillagerForRendering(ingredient: BrainsweepeeIngredient, level: Level): Villager {
throw NotImplementedError()
/*
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.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 net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
@ -22,91 +22,91 @@ import org.jetbrains.annotations.NotNull;
// God I am a horrible person
public record BrainsweepRecipe(
ResourceLocation id,
StateIngredient blockIn,
BrainsweepIngredient entityIn,
int mediaCost,
BlockState result
ResourceLocation id,
StateIngredient blockIn,
BrainsweepeeIngredient entityIn,
int mediaCost,
BlockState result
) implements Recipe<Container> {
public boolean matches(BlockState blockIn, Entity victim, ServerLevel level) {
return this.blockIn.test(blockIn) && this.entityIn.test(victim, level);
}
public boolean matches(BlockState blockIn, Entity victim, ServerLevel level) {
return this.blockIn.test(blockIn) && this.entityIn.test(victim, level);
}
@Override
public ResourceLocation getId() {
return id;
}
@Override
public ResourceLocation getId() {
return id;
}
@Override
public RecipeType<?> getType() {
return HexRecipeStuffRegistry.BRAINSWEEP_TYPE;
}
@Override
public RecipeType<?> getType() {
return HexRecipeStuffRegistry.BRAINSWEEP_TYPE;
}
@Override
public RecipeSerializer<?> getSerializer() {
return HexRecipeStuffRegistry.BRAINSWEEP;
}
@Override
public RecipeSerializer<?> getSerializer() {
return HexRecipeStuffRegistry.BRAINSWEEP;
}
// 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
@Override
public boolean matches(Container pContainer, Level pLevel) {
return false;
}
// 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
@Override
public boolean matches(Container pContainer, Level pLevel) {
return false;
}
@Override
public ItemStack assemble(Container pContainer) {
return ItemStack.EMPTY;
}
@Override
public ItemStack assemble(Container pContainer) {
return ItemStack.EMPTY;
}
@Override
public boolean canCraftInDimensions(int pWidth, int pHeight) {
return false;
}
@Override
public boolean canCraftInDimensions(int pWidth, int pHeight) {
return false;
}
@Override
public ItemStack getResultItem() {
return ItemStack.EMPTY.copy();
}
@Override
public ItemStack getResultItem() {
return ItemStack.EMPTY.copy();
}
// Because kotlin doesn't like doing raw, unchecked types
// Can't blame it, but that's what we need to do
@SuppressWarnings({"rawtypes", "unchecked"})
public static BlockState copyProperties(BlockState original, BlockState copyTo) {
for (Property prop : original.getProperties()) {
if (copyTo.hasProperty(prop)) {
copyTo = copyTo.setValue(prop, original.getValue(prop));
}
}
// Because kotlin doesn't like doing raw, unchecked types
// Can't blame it, but that's what we need to do
@SuppressWarnings({"rawtypes", "unchecked"})
public static BlockState copyProperties(BlockState original, BlockState copyTo) {
for (Property prop : original.getProperties()) {
if (copyTo.hasProperty(prop)) {
copyTo = copyTo.setValue(prop, original.getValue(prop));
}
}
return copyTo;
}
return copyTo;
}
public static class Serializer extends RecipeSerializerBase<BrainsweepRecipe> {
@Override
public @NotNull BrainsweepRecipe fromJson(ResourceLocation recipeID, JsonObject json) {
var blockIn = StateIngredientHelper.deserialize(GsonHelper.getAsJsonObject(json, "blockIn"));
var villagerIn = BrainsweepIngredient.deserialize(GsonHelper.getAsJsonObject(json, "entityIn"));
var cost = GsonHelper.getAsInt(json, "cost");
var result = StateIngredientHelper.readBlockState(GsonHelper.getAsJsonObject(json, "result"));
return new BrainsweepRecipe(recipeID, blockIn, villagerIn, cost, result);
}
public static class Serializer extends RecipeSerializerBase<BrainsweepRecipe> {
@Override
public @NotNull BrainsweepRecipe fromJson(ResourceLocation recipeID, JsonObject json) {
var blockIn = StateIngredientHelper.deserialize(GsonHelper.getAsJsonObject(json, "blockIn"));
var villagerIn = BrainsweepeeIngredient.deserialize(GsonHelper.getAsJsonObject(json, "entityIn"));
var cost = GsonHelper.getAsInt(json, "cost");
var result = StateIngredientHelper.readBlockState(GsonHelper.getAsJsonObject(json, "result"));
return new BrainsweepRecipe(recipeID, blockIn, villagerIn, cost, result);
}
@Override
public void toNetwork(FriendlyByteBuf buf, BrainsweepRecipe recipe) {
recipe.blockIn.write(buf);
recipe.entityIn.write(buf);
buf.writeVarInt(recipe.mediaCost);
buf.writeVarInt(Block.getId(recipe.result));
}
@Override
public void toNetwork(FriendlyByteBuf buf, BrainsweepRecipe recipe) {
recipe.blockIn.write(buf);
recipe.entityIn.write(buf);
buf.writeVarInt(recipe.mediaCost);
buf.writeVarInt(Block.getId(recipe.result));
}
@Override
public @NotNull BrainsweepRecipe fromNetwork(ResourceLocation recipeID, FriendlyByteBuf buf) {
var blockIn = StateIngredientHelper.read(buf);
var villagerIn = BrainsweepIngredient.read(buf);
var cost = buf.readVarInt();
var result = Block.stateById(buf.readVarInt());
return new BrainsweepRecipe(recipeID, blockIn, villagerIn, cost, result);
}
}
@Override
public @NotNull BrainsweepRecipe fromNetwork(ResourceLocation recipeID, FriendlyByteBuf buf) {
var blockIn = StateIngredientHelper.read(buf);
var villagerIn = BrainsweepeeIngredient.read(buf);
var cost = buf.readVarInt();
var result = Block.stateById(buf.readVarInt());
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.advancements.OvercastTrigger
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.colorizer.ItemPrideColorizer
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.SealSpellbookRecipe
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.IXplatIngredients
import at.petrak.hexcasting.datagen.recipe.builders.BrainsweepRecipeBuilder
@ -352,37 +351,37 @@ class HexplatRecipes(
.unlockedBy("enlightenment", enlightenment).save(recipes)
BrainsweepRecipeBuilder(StateIngredientHelper.of(Blocks.AMETHYST_BLOCK),
VillagerBrainsweepIngredient(null, null, 3),
VillagerIngredient(null, null, 3),
Blocks.BUDDING_AMETHYST.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10)
.unlockedBy("enlightenment", enlightenment)
.save(recipes, modLoc("brainsweep/budding_amethyst"))
BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.EMPTY_IMPETUS),
VillagerBrainsweepIngredient(ResourceLocation("toolsmith"), null, 2),
VillagerIngredient(ResourceLocation("toolsmith"), null, 2),
HexBlocks.IMPETUS_RIGHTCLICK.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10)
.unlockedBy("enlightenment", enlightenment)
.save(recipes, modLoc("brainsweep/impetus_rightclick"))
BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.EMPTY_IMPETUS),
VillagerBrainsweepIngredient(ResourceLocation("fletcher"), null, 2),
VillagerIngredient(ResourceLocation("fletcher"), null, 2),
HexBlocks.IMPETUS_LOOK.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10)
.unlockedBy("enlightenment", enlightenment)
.save(recipes, modLoc("brainsweep/impetus_look"))
BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.EMPTY_IMPETUS),
VillagerBrainsweepIngredient(ResourceLocation("cleric"), null, 2),
VillagerIngredient(ResourceLocation("cleric"), null, 2),
HexBlocks.IMPETUS_STOREDPLAYER.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10)
.unlockedBy("enlightenment", enlightenment)
.save(recipes, modLoc("brainsweep/impetus_storedplayer"))
BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.EMPTY_DIRECTRIX),
VillagerBrainsweepIngredient(ResourceLocation("mason"), null, 1),
VillagerIngredient(ResourceLocation("mason"), null, 1),
HexBlocks.DIRECTRIX_REDSTONE.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10)
.unlockedBy("enlightenment", enlightenment)
.save(recipes, modLoc("brainsweep/directrix_redstone"))
BrainsweepRecipeBuilder(StateIngredientHelper.of(HexBlocks.AKASHIC_LIGATURE),
VillagerBrainsweepIngredient(ResourceLocation("librarian"), null, 5),
VillagerIngredient(ResourceLocation("librarian"), null, 5),
HexBlocks.AKASHIC_RECORD.defaultBlockState(), MediaConstants.CRYSTAL_UNIT * 10)
.unlockedBy("enlightenment", enlightenment)
.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.ingredient.StateIngredient;
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 net.minecraft.advancements.Advancement;
import net.minecraft.advancements.AdvancementRewards;
@ -21,86 +21,86 @@ import org.jetbrains.annotations.Nullable;
import java.util.function.Consumer;
public class BrainsweepRecipeBuilder implements RecipeBuilder {
private final StateIngredient blockIn;
private final BrainsweepIngredient villagerIn;
private final int mediaCost;
private final BlockState result;
private final StateIngredient blockIn;
private final BrainsweepeeIngredient villagerIn;
private final int mediaCost;
private final BlockState result;
private final Advancement.Builder advancement;
private final Advancement.Builder advancement;
public BrainsweepRecipeBuilder(StateIngredient blockIn, BrainsweepIngredient villagerIn, BlockState result,
int mediaCost) {
this.blockIn = blockIn;
this.villagerIn = villagerIn;
this.result = result;
this.mediaCost = mediaCost;
this.advancement = Advancement.Builder.advancement();
}
public BrainsweepRecipeBuilder(StateIngredient blockIn, BrainsweepeeIngredient villagerIn, BlockState result,
int mediaCost) {
this.blockIn = blockIn;
this.villagerIn = villagerIn;
this.result = result;
this.mediaCost = mediaCost;
this.advancement = Advancement.Builder.advancement();
}
@Override
public RecipeBuilder unlockedBy(String pCriterionName, CriterionTriggerInstance pCriterionTrigger) {
this.advancement.addCriterion(pCriterionName, pCriterionTrigger);
return this;
}
@Override
public RecipeBuilder unlockedBy(String pCriterionName, CriterionTriggerInstance pCriterionTrigger) {
this.advancement.addCriterion(pCriterionName, pCriterionTrigger);
return this;
}
@Override
public RecipeBuilder group(@Nullable String pGroupName) {
return this;
}
@Override
public RecipeBuilder group(@Nullable String pGroupName) {
return this;
}
@Override
public Item getResult() {
return this.result.getBlock().asItem();
}
@Override
public Item getResult() {
return this.result.getBlock().asItem();
}
@Override
public void save(Consumer<FinishedRecipe> pFinishedRecipeConsumer, ResourceLocation pRecipeId) {
if (this.advancement.getCriteria().isEmpty()) {
throw new IllegalStateException("No way of obtaining recipe " + pRecipeId);
}
@Override
public void save(Consumer<FinishedRecipe> pFinishedRecipeConsumer, ResourceLocation pRecipeId) {
if (this.advancement.getCriteria().isEmpty()) {
throw new IllegalStateException("No way of obtaining recipe " + pRecipeId);
}
this.advancement.parent(new ResourceLocation("recipes/root"))
.addCriterion("has_the_recipe", RecipeUnlockedTrigger.unlocked(pRecipeId))
.rewards(AdvancementRewards.Builder.recipe(pRecipeId))
.requirements(RequirementsStrategy.OR);
pFinishedRecipeConsumer.accept(new Result(
pRecipeId,
this.blockIn, this.villagerIn, this.mediaCost, this.result,
this.advancement,
new ResourceLocation(pRecipeId.getNamespace(), "recipes/brainsweep/" + pRecipeId.getPath())));
}
this.advancement.parent(new ResourceLocation("recipes/root"))
.addCriterion("has_the_recipe", RecipeUnlockedTrigger.unlocked(pRecipeId))
.rewards(AdvancementRewards.Builder.recipe(pRecipeId))
.requirements(RequirementsStrategy.OR);
pFinishedRecipeConsumer.accept(new Result(
pRecipeId,
this.blockIn, this.villagerIn, this.mediaCost, this.result,
this.advancement,
new ResourceLocation(pRecipeId.getNamespace(), "recipes/brainsweep/" + pRecipeId.getPath())));
}
public record Result(ResourceLocation id, StateIngredient blockIn, BrainsweepIngredient villagerIn,
int mediaCost, BlockState result, Advancement.Builder advancement,
ResourceLocation advancementId) implements FinishedRecipe {
@Override
public void serializeRecipeData(JsonObject json) {
json.add("blockIn", this.blockIn.serialize());
json.add("entityIn", this.villagerIn.serialize());
json.addProperty("cost", this.mediaCost);
json.add("result", StateIngredientHelper.serializeBlockState(this.result));
}
public record Result(ResourceLocation id, StateIngredient blockIn, BrainsweepeeIngredient villagerIn,
int mediaCost, BlockState result, Advancement.Builder advancement,
ResourceLocation advancementId) implements FinishedRecipe {
@Override
public void serializeRecipeData(JsonObject json) {
json.add("blockIn", this.blockIn.serialize());
json.add("entityIn", this.villagerIn.serialize());
json.addProperty("cost", this.mediaCost);
json.add("result", StateIngredientHelper.serializeBlockState(this.result));
}
@Override
public ResourceLocation getId() {
return this.id;
}
@Override
public ResourceLocation getId() {
return this.id;
}
@Override
public RecipeSerializer<?> getType() {
return HexRecipeStuffRegistry.BRAINSWEEP;
}
@Override
public RecipeSerializer<?> getType() {
return HexRecipeStuffRegistry.BRAINSWEEP;
}
@Nullable
@Override
public JsonObject serializeAdvancement() {
return this.advancement.serializeToJson();
}
@Nullable
@Override
public JsonObject serializeAdvancement() {
return this.advancement.serializeToJson();
}
@Nullable
@Override
public ResourceLocation getAdvancementId() {
return this.advancementId;
}
}
@Nullable
@Override
public ResourceLocation getAdvancementId() {
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.HexRecipeStuffRegistry;
import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.EntityBrainsweepIngredient;
import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.VillagerBrainsweepIngredient;
import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.EntityTypeIngredient;
import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.VillagerIngredient;
import net.minecraft.client.Minecraft;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
@ -14,69 +14,69 @@ import vazkii.patchouli.api.IVariableProvider;
import java.util.Objects;
public class BrainsweepProcessor implements IComponentProcessor {
private BrainsweepRecipe recipe;
private BrainsweepRecipe recipe;
@Override
public void setup(IVariableProvider vars) {
var id = new ResourceLocation(vars.get("recipe").asString());
@Override
public void setup(IVariableProvider vars) {
var id = new ResourceLocation(vars.get("recipe").asString());
var recman = Minecraft.getInstance().level.getRecipeManager();
var brainsweepings = recman.getAllRecipesFor(HexRecipeStuffRegistry.BRAINSWEEP_TYPE);
for (var poisonApples : brainsweepings) {
if (poisonApples.getId().equals(id)) {
this.recipe = poisonApples;
break;
}
}
}
var recman = Minecraft.getInstance().level.getRecipeManager();
var brainsweepings = recman.getAllRecipesFor(HexRecipeStuffRegistry.BRAINSWEEP_TYPE);
for (var poisonApples : brainsweepings) {
if (poisonApples.getId().equals(id)) {
this.recipe = poisonApples;
break;
}
}
}
@Override
public IVariable process(String key) {
if (this.recipe == null) {
return null;
}
@Override
public IVariable process(String key) {
if (this.recipe == null) {
return null;
}
switch (key) {
case "header" -> {
return IVariable.from(this.recipe.result().getBlock().getName());
}
case "input" -> {
var inputStacks = this.recipe.blockIn().getDisplayedStacks();
return IVariable.from(inputStacks.toArray(new ItemStack[0]));
}
case "result" -> {
return IVariable.from(new ItemStack(this.recipe.result().getBlock()));
}
switch (key) {
case "header" -> {
return IVariable.from(this.recipe.result().getBlock().getName());
}
case "input" -> {
var inputStacks = this.recipe.blockIn().getDisplayedStacks();
return IVariable.from(inputStacks.toArray(new ItemStack[0]));
}
case "result" -> {
return IVariable.from(new ItemStack(this.recipe.result().getBlock()));
}
case "entity" -> {
if (this.recipe.entityIn() instanceof VillagerBrainsweepIngredient villager) {
var profession = Objects.requireNonNullElse(villager.profession,
new ResourceLocation("toolsmith"));
var biome = Objects.requireNonNullElse(villager.biome,
new ResourceLocation("plains"));
var level = villager.minLevel;
var iHatePatchouli = String.format(
"minecraft:villager{VillagerData:{profession:'%s',type:'%s',level:%d}}",
profession, biome, level);
return IVariable.wrap(iHatePatchouli);
} else if (this.recipe.entityIn() instanceof EntityBrainsweepIngredient entity) {
// TODO
return IVariable.wrap("minecraft:chicken");
} else {
throw new IllegalStateException();
}
}
case "entityTooltip" -> {
Minecraft mc = Minecraft.getInstance();
return IVariable.wrapList(this.recipe.entityIn()
.getTooltip(mc.options.advancedItemTooltips)
.stream()
.map(IVariable::from)
.toList());
}
default -> {
return null;
}
}
}
case "entity" -> {
if (this.recipe.entityIn() instanceof VillagerIngredient villager) {
var profession = Objects.requireNonNullElse(villager.profession,
new ResourceLocation("toolsmith"));
var biome = Objects.requireNonNullElse(villager.biome,
new ResourceLocation("plains"));
var level = villager.minLevel;
var iHatePatchouli = String.format(
"minecraft:villager{VillagerData:{profession:'%s',type:'%s',level:%d}}",
profession, biome, level);
return IVariable.wrap(iHatePatchouli);
} else if (this.recipe.entityIn() instanceof EntityTypeIngredient entity) {
// TODO
return IVariable.wrap("minecraft:chicken");
} else {
throw new IllegalStateException();
}
}
case "entityTooltip" -> {
Minecraft mc = Minecraft.getInstance();
return IVariable.wrapList(this.recipe.entityIn()
.getTooltip(mc.options.advancedItemTooltips)
.stream()
.map(IVariable::from)
.toList());
}
default -> {
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.shader.FakeBufferSource;
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.vertex.PoseStack;
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;
public class BrainsweepeeEmiStack extends EmiStack {
private final VillagerEntry entry;
public final BrainsweepIngredient ingredient;
public final boolean mindless;
private final VillagerEntry entry;
public final BrainsweepeeIngredient ingredient;
public final boolean mindless;
private final ResourceLocation id;
private final ResourceLocation id;
public BrainsweepeeEmiStack(BrainsweepIngredient villager) {
this(villager, false);
}
public BrainsweepeeEmiStack(BrainsweepeeIngredient villager) {
this(villager, false);
}
public BrainsweepeeEmiStack(BrainsweepIngredient villager, boolean mindless) {
this(villager, mindless, 1);
}
public BrainsweepeeEmiStack(BrainsweepeeIngredient villager, boolean mindless) {
this(villager, mindless, 1);
}
public BrainsweepeeEmiStack(BrainsweepIngredient villager, boolean mindless, long amount) {
entry = new VillagerEntry(new VillagerVariant(villager, mindless));
this.ingredient = villager;
this.mindless = mindless;
this.amount = amount;
// This is so scuffed
this.id = modLoc((Objects.toString(villager.profession()) + villager.minLevel() + mindless)
.replace(':', '-'));
}
public BrainsweepeeEmiStack(BrainsweepeeIngredient villager, boolean mindless, long amount) {
entry = new VillagerEntry(new VillagerVariant(villager, mindless));
this.ingredient = villager;
this.mindless = mindless;
this.amount = amount;
// This is so scuffed
this.id = modLoc((Objects.toString(villager.profession()) + villager.minLevel() + mindless)
.replace(':', '-'));
}
public static Set<BlockState> matchingStatesForProfession(VillagerProfession profession) {
return Registry.POINT_OF_INTEREST_TYPE.holders()
.filter(profession.heldJobSite())
.flatMap(it -> it.value().matchingStates().stream())
.collect(Collectors.toSet());
}
public static Set<BlockState> matchingStatesForProfession(VillagerProfession profession) {
return Registry.POINT_OF_INTEREST_TYPE.holders()
.filter(profession.heldJobSite())
.flatMap(it -> it.value().matchingStates().stream())
.collect(Collectors.toSet());
}
public static EmiIngredient atLevelOrHigher(BrainsweepIngredient ingredient, boolean remainder) {
if (ingredient.profession() == null) {
return EmiIngredient.of(Registry.VILLAGER_PROFESSION.stream()
.filter(it -> matchingStatesForProfession(it).isEmpty())
.map(it -> atLevelOrHigher(new BrainsweepIngredient(Registry.VILLAGER_PROFESSION.getKey(it),
ingredient.biome(), ingredient.minLevel()), true))
.toList());
}
public static EmiIngredient atLevelOrHigher(BrainsweepeeIngredient ingredient, boolean remainder) {
if (ingredient.profession() == null) {
return EmiIngredient.of(Registry.VILLAGER_PROFESSION.stream()
.filter(it -> matchingStatesForProfession(it).isEmpty())
.map(it -> atLevelOrHigher(new BrainsweepeeIngredient(Registry.VILLAGER_PROFESSION.getKey(it),
ingredient.biome(), ingredient.minLevel()), true))
.toList());
}
BrainsweepeeEmiStack stack = new BrainsweepeeEmiStack(ingredient).orHigher(true);
if (remainder) {
stack.setRemainder(new BrainsweepeeEmiStack(ingredient, true));
}
return stack;
}
BrainsweepeeEmiStack stack = new BrainsweepeeEmiStack(ingredient).orHigher(true);
if (remainder) {
stack.setRemainder(new BrainsweepeeEmiStack(ingredient, true));
}
return stack;
}
private boolean orHigher = false;
private boolean orHigher = false;
public BrainsweepeeEmiStack orHigher(boolean orHigher) {
this.orHigher = orHigher;
return this;
}
public BrainsweepeeEmiStack orHigher(boolean orHigher) {
this.orHigher = orHigher;
return this;
}
@Override
public EmiStack copy() {
BrainsweepeeEmiStack e = new BrainsweepeeEmiStack(ingredient, mindless, amount);
e.orHigher(orHigher).setRemainder(getRemainder().copy());
e.comparison = comparison;
return e;
}
@Override
public EmiStack copy() {
BrainsweepeeEmiStack e = new BrainsweepeeEmiStack(ingredient, mindless, amount);
e.orHigher(orHigher).setRemainder(getRemainder().copy());
e.comparison = comparison;
return e;
}
@Override
public boolean isEmpty() {
return amount == 0;
}
@Override
public boolean isEmpty() {
return amount == 0;
}
@Override
public CompoundTag getNbt() {
return null;
}
@Override
public CompoundTag getNbt() {
return null;
}
@Override
public Object getKey() {
return id;
}
@Override
public Object getKey() {
return id;
}
@Override
public Entry<?> getEntry() {
return entry;
}
@Override
public Entry<?> getEntry() {
return entry;
}
@Override
public ResourceLocation getId() {
return id;
}
@Override
public ResourceLocation getId() {
return id;
}
@Override
public List<Component> getTooltipText() {
Minecraft mc = Minecraft.getInstance();
boolean advanced = mc.options.advancedItemTooltips;
@Override
public List<Component> getTooltipText() {
Minecraft mc = Minecraft.getInstance();
boolean advanced = mc.options.advancedItemTooltips;
if (mindless) {
List<Component> tooltip = new ArrayList<>();
tooltip.add(Component.translatable("hexcasting.tooltip.brainsweep.product"));
if (mindless) {
List<Component> tooltip = new ArrayList<>();
tooltip.add(Component.translatable("hexcasting.tooltip.brainsweep.product"));
if (advanced) {
if (ingredient.biome() != null) {
tooltip.add(Component.literal(ingredient.biome().toString()).withStyle(ChatFormatting.DARK_GRAY));
}
if (advanced) {
if (ingredient.biome() != null) {
tooltip.add(Component.literal(ingredient.biome().toString()).withStyle(ChatFormatting.DARK_GRAY));
}
ResourceLocation displayId = Objects.requireNonNullElseGet(ingredient.profession(),
() -> Registry.ENTITY_TYPE.getKey(EntityType.VILLAGER));
tooltip.add(Component.literal(displayId.toString()).withStyle(ChatFormatting.DARK_GRAY));
}
ResourceLocation displayId = Objects.requireNonNullElseGet(ingredient.profession(),
() -> Registry.ENTITY_TYPE.getKey(EntityType.VILLAGER));
tooltip.add(Component.literal(displayId.toString()).withStyle(ChatFormatting.DARK_GRAY));
}
tooltip.add(ingredient.getModNameComponent());
return tooltip;
}
tooltip.add(ingredient.getModNameComponent());
return tooltip;
}
return ingredient.getTooltip(advanced, orHigher);
}
return ingredient.getTooltip(advanced, orHigher);
}
@Override
public List<ClientTooltipComponent> getTooltip() {
List<ClientTooltipComponent> list = getTooltipText().stream()
.map(Component::getVisualOrderText)
.map(ClientTooltipComponent::create)
.collect(Collectors.toList());
if (!getRemainder().isEmpty()) {
list.add(EmiTooltipComponents.getRemainderTooltipComponent(this));
}
return list;
}
@Override
public List<ClientTooltipComponent> getTooltip() {
List<ClientTooltipComponent> list = getTooltipText().stream()
.map(Component::getVisualOrderText)
.map(ClientTooltipComponent::create)
.collect(Collectors.toList());
if (!getRemainder().isEmpty()) {
list.add(EmiTooltipComponents.getRemainderTooltipComponent(this));
}
return list;
}
@Override
public Component getName() {
return ingredient.name();
}
@Override
public Component getName() {
return ingredient.name();
}
@Override
public void render(PoseStack poseStack, int x, int y, float delta, int flags) {
if ((flags & RENDER_ICON) != 0) {
Minecraft mc = Minecraft.getInstance();
ClientLevel level = mc.level;
if (level != null) {
Villager villager = RenderLib.prepareVillagerForRendering(ingredient, level);
@Override
public void render(PoseStack poseStack, int x, int y, float delta, int flags) {
if ((flags & RENDER_ICON) != 0) {
Minecraft mc = Minecraft.getInstance();
ClientLevel level = mc.level;
if (level != null) {
Villager villager = RenderLib.prepareVillagerForRendering(ingredient, level);
RenderSystem.enableBlend();
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
renderEntity(poseStack, villager, level, x + 8, y + 16, ClientTickCounter.getTotal(), 8, 0,
mindless ? (it) -> new FakeBufferSource(it, HexRenderTypes::getGrayscaleLayer) : it -> it);
}
}
RenderSystem.enableBlend();
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
renderEntity(poseStack, villager, level, x + 8, y + 16, ClientTickCounter.getTotal(), 8, 0,
mindless ? (it) -> new FakeBufferSource(it, HexRenderTypes::getGrayscaleLayer) : it -> it);
}
}
if ((flags & RENDER_REMAINDER) != 0) {
EmiRender.renderRemainderIcon(this, poseStack, x, y);
}
}
if ((flags & RENDER_REMAINDER) != 0) {
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) {
super(variant);
}
public VillagerEntry(VillagerVariant variant) {
super(variant);
}
@Override
public Class<? extends VillagerVariant> getType() {
return VillagerVariant.class;
}
@Override
public Class<? extends VillagerVariant> getType() {
return VillagerVariant.class;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof VillagerEntry e)) {
return false;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof VillagerEntry e)) {
return false;
}
VillagerVariant self = getValue();
VillagerVariant other = e.getValue();
VillagerVariant self = getValue();
VillagerVariant other = e.getValue();
ResourceLocation selfBiome = self.ingredient().biome();
ResourceLocation otherBiome = other.ingredient().biome();
if (selfBiome != null && otherBiome != null && !selfBiome.equals(otherBiome)) {
return false;
}
ResourceLocation selfBiome = self.ingredient().biome();
ResourceLocation otherBiome = other.ingredient().biome();
if (selfBiome != null && otherBiome != null && !selfBiome.equals(otherBiome)) {
return false;
}
ResourceLocation selfProfession = self.ingredient().profession();
ResourceLocation otherProfession = other.ingredient().profession();
if (selfProfession != null && otherProfession != null && !selfProfession.equals(otherProfession)) {
return false;
}
ResourceLocation selfProfession = self.ingredient().profession();
ResourceLocation otherProfession = other.ingredient().profession();
if (selfProfession != null && otherProfession != null && !selfProfession.equals(otherProfession)) {
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;
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) {
// NO-OP
public record VillagerVariant(BrainsweepeeIngredient ingredient, boolean mindless) {
// NO-OP
}