possibly impl arbitrary brainsweeps. i don't know. i'm in offline mode

This commit is contained in:
petrak@ 2022-11-22 19:31:09 -06:00
parent 30701702c7
commit 7c00cbaec8
18 changed files with 439 additions and 423 deletions

View file

@ -13,9 +13,9 @@ import net.minecraft.core.BlockPos
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.Entity import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.Mob
import net.minecraft.world.entity.decoration.ArmorStand import net.minecraft.world.entity.decoration.ArmorStand
import net.minecraft.world.entity.item.ItemEntity import net.minecraft.world.entity.item.ItemEntity
import net.minecraft.world.entity.npc.Villager
import net.minecraft.world.phys.Vec3 import net.minecraft.world.phys.Vec3
import java.util.function.DoubleUnaryOperator import java.util.function.DoubleUnaryOperator
import kotlin.math.abs import kotlin.math.abs
@ -99,14 +99,14 @@ fun List<Iota>.getPlayer(idx: Int, argc: Int = 0): ServerPlayer {
throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.player") throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.player")
} }
fun List<Iota>.getVillager(idx: Int, argc: Int = 0): Villager { fun List<Iota>.getMob(idx: Int, argc: Int = 0): Mob {
val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) }
if (x is EntityIota) { if (x is EntityIota) {
val e = x.entity val e = x.entity
if (e is Villager) if (e is Mob)
return e return e
} }
throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.villager") throw MishapInvalidIota.ofType(x, if (argc == 0) idx else argc - (idx + 1), "entity.mob")
} }
fun List<Iota>.getLivingEntityButNotArmorStand(idx: Int, argc: Int = 0): LivingEntity { fun List<Iota>.getLivingEntityButNotArmorStand(idx: Int, argc: Int = 0): LivingEntity {
@ -216,7 +216,7 @@ fun List<Iota>.getPositiveIntUnderInclusive(idx: Int, max: Int, argc: Int = 0):
if (x is DoubleIota) { if (x is DoubleIota) {
val double = x.double val double = x.double
val rounded = double.roundToInt() val rounded = double.roundToInt()
if (abs(double - rounded) <= DoubleIota.TOLERANCE && rounded in 0 .. max) { if (abs(double - rounded) <= DoubleIota.TOLERANCE && rounded in 0..max) {
return rounded return rounded
} }
} }

View file

@ -2,22 +2,22 @@ package at.petrak.hexcasting.api.spell.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.misc.HexDamageSources import at.petrak.hexcasting.api.misc.HexDamageSources
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.ParticleSpray import at.petrak.hexcasting.api.spell.ParticleSpray
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import net.minecraft.world.entity.npc.Villager import at.petrak.hexcasting.api.spell.iota.Iota
import net.minecraft.world.entity.Mob
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
class MishapAlreadyBrainswept(val villager: Villager) : Mishap() { class MishapAlreadyBrainswept(val mob: Mob) : Mishap() {
override fun accentColor(ctx: CastingContext, errorCtx: Context): FrozenColorizer = override fun accentColor(ctx: CastingContext, errorCtx: Context): FrozenColorizer =
dyeColor(DyeColor.GREEN) dyeColor(DyeColor.GREEN)
override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<Iota>) { override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<Iota>) {
villager.hurt(HexDamageSources.overcastDamageFrom(ctx.caster), villager.health) mob.hurt(HexDamageSources.overcastDamageFrom(ctx.caster), mob.health)
} }
override fun particleSpray(ctx: CastingContext) = override fun particleSpray(ctx: CastingContext) =
ParticleSpray.burst(villager.eyePosition, 1.0) ParticleSpray.burst(mob.eyePosition, 1.0)
override fun errorMessage(ctx: CastingContext, errorCtx: Context) = override fun errorMessage(ctx: CastingContext, errorCtx: Context) =
error("already_brainswept") error("already_brainswept")

View file

@ -3,19 +3,19 @@ package at.petrak.hexcasting.api.spell.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.misc.HexDamageSources import at.petrak.hexcasting.api.misc.HexDamageSources
import at.petrak.hexcasting.api.spell.ParticleSpray import at.petrak.hexcasting.api.spell.ParticleSpray
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.iota.Iota
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import net.minecraft.world.entity.npc.Villager import net.minecraft.world.entity.Mob
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
import net.minecraft.world.phys.Vec3 import net.minecraft.world.phys.Vec3
class MishapBadBrainsweep(val villager: Villager, val pos: BlockPos) : Mishap() { class MishapBadBrainsweep(val mob: Mob, val pos: BlockPos) : Mishap() {
override fun accentColor(ctx: CastingContext, errorCtx: Context): FrozenColorizer = override fun accentColor(ctx: CastingContext, errorCtx: Context): FrozenColorizer =
dyeColor(DyeColor.GREEN) dyeColor(DyeColor.GREEN)
override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<Iota>) { override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<Iota>) {
trulyHurt(villager, HexDamageSources.overcastDamageFrom(ctx.caster), villager.health) trulyHurt(mob, HexDamageSources.overcastDamageFrom(ctx.caster), mob.health)
} }
override fun particleSpray(ctx: CastingContext): ParticleSpray { override fun particleSpray(ctx: CastingContext): ParticleSpray {

View file

@ -1,19 +1,20 @@
package at.petrak.hexcasting.common.casting.operators.spells.great package at.petrak.hexcasting.common.casting.operators.spells.great
import at.petrak.hexcasting.api.misc.MediaConstants
import at.petrak.hexcasting.api.mod.HexConfig import at.petrak.hexcasting.api.mod.HexConfig
import at.petrak.hexcasting.api.spell.* import at.petrak.hexcasting.api.spell.*
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.iota.Iota import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.api.spell.mishaps.MishapAlreadyBrainswept import at.petrak.hexcasting.api.spell.mishaps.MishapAlreadyBrainswept
import at.petrak.hexcasting.api.spell.mishaps.MishapBadBrainsweep import at.petrak.hexcasting.api.spell.mishaps.MishapBadBrainsweep
import at.petrak.hexcasting.common.misc.Brainsweeping
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.ktxt.tellWitnessesThatIWasMurdered import at.petrak.hexcasting.ktxt.tellWitnessesThatIWasMurdered
import at.petrak.hexcasting.mixin.accessor.AccessorLivingEntity
import at.petrak.hexcasting.xplat.IXplatAbstractions
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import net.minecraft.sounds.SoundEvents import net.minecraft.sounds.SoundEvents
import net.minecraft.sounds.SoundSource import net.minecraft.sounds.SoundSource
import net.minecraft.world.entity.Mob
import net.minecraft.world.entity.npc.Villager import net.minecraft.world.entity.npc.Villager
import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.phys.Vec3 import net.minecraft.world.phys.Vec3
@ -30,12 +31,12 @@ object OpBrainsweep : SpellAction {
args: List<Iota>, args: List<Iota>,
ctx: CastingContext ctx: CastingContext
): Triple<RenderedSpell, Int, List<ParticleSpray>>? { ): Triple<RenderedSpell, Int, List<ParticleSpray>>? {
val sacrifice = args.getVillager(0, argc) val sacrifice = args.getMob(0, argc)
val pos = args.getBlockPos(1, argc) val pos = args.getBlockPos(1, argc)
ctx.assertVecInRange(pos) ctx.assertVecInRange(pos)
ctx.assertEntityInRange(sacrifice) ctx.assertEntityInRange(sacrifice)
if (Brainsweeping.isBrainswept(sacrifice)) if (IXplatAbstractions.INSTANCE.isBrainswept(sacrifice))
throw MishapAlreadyBrainswept(sacrifice) throw MishapAlreadyBrainswept(sacrifice)
val state = ctx.world.getBlockState(pos) val state = ctx.world.getBlockState(pos)
@ -45,12 +46,12 @@ object OpBrainsweep : SpellAction {
val recman = ctx.world.recipeManager val recman = ctx.world.recipeManager
val recipes = recman.getAllRecipesFor(HexRecipeStuffRegistry.BRAINSWEEP_TYPE) val recipes = recman.getAllRecipesFor(HexRecipeStuffRegistry.BRAINSWEEP_TYPE)
val recipe = recipes.find { it.matches(state, sacrifice) } val recipe = recipes.find { it.matches(state, sacrifice, ctx.world) }
?: throw MishapBadBrainsweep(sacrifice, pos) ?: throw MishapBadBrainsweep(sacrifice, pos)
return Triple( return Triple(
Spell(pos, state, sacrifice, recipe), Spell(pos, state, sacrifice, recipe),
10 * MediaConstants.CRYSTAL_UNIT, recipe.mediaCost,
listOf(ParticleSpray.cloud(sacrifice.position(), 1.0), ParticleSpray.burst(Vec3.atCenterOf(pos), 0.3, 100)) listOf(ParticleSpray.cloud(sacrifice.position(), 1.0), ParticleSpray.burst(Vec3.atCenterOf(pos), 0.3, 100))
) )
} }
@ -58,18 +59,20 @@ object OpBrainsweep : SpellAction {
private data class Spell( private data class Spell(
val pos: BlockPos, val pos: BlockPos,
val state: BlockState, val state: BlockState,
val sacrifice: Villager, val sacrifice: Mob,
val recipe: BrainsweepRecipe val recipe: BrainsweepRecipe
) : RenderedSpell { ) : RenderedSpell {
override fun cast(ctx: CastingContext) { override fun cast(ctx: CastingContext) {
ctx.world.setBlockAndUpdate(pos, BrainsweepRecipe.copyProperties(state, recipe.result)) ctx.world.setBlockAndUpdate(pos, BrainsweepRecipe.copyProperties(state, recipe.result))
Brainsweeping.brainsweep(sacrifice) IXplatAbstractions.INSTANCE.brainsweep(sacrifice)
if (HexConfig.server().doVillagersTakeOffenseAtMindMurder()) { if (sacrifice is Villager && HexConfig.server().doVillagersTakeOffenseAtMindMurder()) {
sacrifice.tellWitnessesThatIWasMurdered(ctx.caster) sacrifice.tellWitnessesThatIWasMurdered(ctx.caster)
} }
ctx.world.playSound(null, sacrifice, SoundEvents.VILLAGER_DEATH, SoundSource.AMBIENT, 0.8f, 1f) val sound = (sacrifice as AccessorLivingEntity).`hex$getDeathSound`()
if (sound != null)
ctx.world.playSound(null, sacrifice, sound, SoundSource.AMBIENT, 0.8f, 1f)
ctx.world.playSound(null, sacrifice, SoundEvents.PLAYER_LEVELUP, SoundSource.AMBIENT, 0.5f, 0.8f) ctx.world.playSound(null, sacrifice, SoundEvents.PLAYER_LEVELUP, SoundSource.AMBIENT, 0.5f, 0.8f)
} }
} }

View file

@ -6,43 +6,24 @@ import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.npc.Villager;
import net.minecraft.world.entity.npc.VillagerDataHolder;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.raid.Raider;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.EntityHitResult;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public class Brainsweeping { public class Brainsweeping {
// Keeping these functions in Brainsweeping just so we have to change less code public static InteractionResult interactWithBrainswept(Player player, Level world, InteractionHand hand,
public static void brainsweep(Mob entity) { Entity entity, @Nullable EntityHitResult hitResult) {
if (isValidTarget(entity)) { if (entity instanceof Mob mob && IXplatAbstractions.INSTANCE.isBrainswept(mob)) {
IXplatAbstractions.INSTANCE.brainsweep(entity);
}
}
public static boolean isBrainswept(Mob entity) {
return isValidTarget(entity) && IXplatAbstractions.INSTANCE.isBrainswept(entity);
}
// TODO: make this a tag
public static boolean isValidTarget(Mob mob) {
return mob instanceof VillagerDataHolder || mob instanceof Raider;
}
public static InteractionResult tradeWithVillager(Player player, Level world, InteractionHand hand, Entity entity,
@Nullable EntityHitResult hitResult) {
if (entity instanceof Villager v && IXplatAbstractions.INSTANCE.isBrainswept(v)) {
return InteractionResult.FAIL; return InteractionResult.FAIL;
} }
return InteractionResult.PASS; return InteractionResult.PASS;
} }
public static InteractionResult copyBrainsweepFromVillager(LivingEntity original, LivingEntity outcome) { public static InteractionResult copyBrainsweepPostTransformation(LivingEntity original, LivingEntity outcome) {
if (original instanceof Mob mOriginal && outcome instanceof Mob mOutcome if (original instanceof Mob mOriginal && outcome instanceof Mob mOutcome
&& IXplatAbstractions.INSTANCE.isBrainswept(mOriginal) && Brainsweeping.isValidTarget(mOutcome)) { && IXplatAbstractions.INSTANCE.isBrainswept(mOriginal)) {
IXplatAbstractions.INSTANCE.brainsweep(mOutcome); IXplatAbstractions.INSTANCE.brainsweep(mOutcome);
} }
return InteractionResult.PASS; return InteractionResult.PASS;

View file

@ -6,9 +6,10 @@ import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.BrainsweepIngred
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;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.GsonHelper; import net.minecraft.util.GsonHelper;
import net.minecraft.world.Container; import net.minecraft.world.Container;
import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.RecipeSerializer;
@ -21,13 +22,14 @@ 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 villagerIn, BrainsweepIngredient entityIn,
BlockState result int mediaCost,
BlockState result
) implements Recipe<Container> { ) implements Recipe<Container> {
public boolean matches(BlockState blockIn, Villager villagerIn) { public boolean matches(BlockState blockIn, Entity victim, ServerLevel level) {
return this.blockIn.test(blockIn) && this.villagerIn.test(villagerIn); return this.blockIn.test(blockIn) && this.entityIn.test(victim, level);
} }
@Override @Override
@ -84,15 +86,17 @@ public record 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, "villagerIn")); var villagerIn = BrainsweepIngredient.deserialize(GsonHelper.getAsJsonObject(json, "entityIn"));
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, 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.villagerIn.write(buf); recipe.entityIn.write(buf);
buf.writeVarInt(recipe.mediaCost);
buf.writeVarInt(Block.getId(recipe.result)); buf.writeVarInt(Block.getId(recipe.result));
} }
@ -100,8 +104,9 @@ public record BrainsweepRecipe(
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 = BrainsweepIngredient.read(buf);
var cost = buf.readVarInt();
var result = Block.stateById(buf.readVarInt()); var result = Block.stateById(buf.readVarInt());
return new BrainsweepRecipe(recipeID, blockIn, villagerIn, result); return new BrainsweepRecipe(recipeID, blockIn, villagerIn, cost, result);
} }
} }
} }

View file

@ -3,14 +3,16 @@ package at.petrak.hexcasting.common.recipe.ingredient.brainsweep;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.GsonHelper; import net.minecraft.util.GsonHelper;
import net.minecraft.util.StringRepresentable; import net.minecraft.util.StringRepresentable;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import java.util.List; import java.util.List;
import java.util.function.Predicate;
public abstract class BrainsweepIngredient implements Predicate<Entity> { public abstract class BrainsweepIngredient {
public abstract boolean test(Entity entity, ServerLevel level);
public abstract List<Component> getTooltip(boolean advanced); public abstract List<Component> getTooltip(boolean advanced);
public abstract JsonObject serialize(); public abstract JsonObject serialize();
@ -21,8 +23,7 @@ public abstract class BrainsweepIngredient implements Predicate<Entity> {
var type = buf.readVarInt(); var type = buf.readVarInt();
return switch (Type.values()[type]) { return switch (Type.values()[type]) {
case VILLAGER -> VillagerBrainsweepIngredient.read(buf); case VILLAGER -> VillagerBrainsweepIngredient.read(buf);
case ENTITY -> { case ENTITY -> EntityBrainsweepIngredient.read(buf);
}
}; };
} }
@ -31,7 +32,7 @@ public abstract class BrainsweepIngredient implements Predicate<Entity> {
var type = Type.valueOf(typestr); var type = Type.valueOf(typestr);
return switch (type) { return switch (type) {
case VILLAGER -> VillagerBrainsweepIngredient.deserialize(json); case VILLAGER -> VillagerBrainsweepIngredient.deserialize(json);
case ENTITY -> null; case ENTITY -> EntityBrainsweepIngredient.deserialize(json);
}; };
} }

View file

@ -1,30 +1,35 @@
package at.petrak.hexcasting.common.recipe.ingredient.brainsweep; 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 com.google.gson.JsonObject;
import net.minecraft.advancements.critereon.DeserializationContext;
import net.minecraft.advancements.critereon.EntityPredicate; import net.minecraft.advancements.critereon.EntityPredicate;
import net.minecraft.advancements.critereon.SerializationContext;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
import java.util.List; 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 class EntityBrainsweepIngredient extends BrainsweepIngredient {
public final EntityPredicate.Composite requirements; public static final Gson GSON = new GsonBuilder().create();
public final EntityPredicate requirements;
// Just tell the player what it is you want // Just tell the player what it is you want
public final Component tooltip; public final Component tooltip;
protected EntityBrainsweepIngredient(EntityPredicate.Composite requirements, Component tooltip) { public EntityBrainsweepIngredient(EntityPredicate requirements, Component tooltip) {
super();
this.requirements = requirements; this.requirements = requirements;
this.tooltip = tooltip; this.tooltip = tooltip;
} }
@Override @Override
public boolean test(Entity entity) { public boolean test(Entity entity, ServerLevel level) {
return false; return this.requirements.matches(level, null, entity);
} }
@Override @Override
@ -35,17 +40,32 @@ public class EntityBrainsweepIngredient extends BrainsweepIngredient {
@Override @Override
public JsonObject serialize() { public JsonObject serialize() {
var obj = new JsonObject(); var obj = new JsonObject();
obj.add("requirements", this.requirements.toJson(SerializationContext.INSTANCE)); obj.addProperty("type", "entity");
obj.add("requirements", this.requirements.serializeToJson());
obj.addProperty("tooltip", Component.Serializer.toJson(this.tooltip)); obj.addProperty("tooltip", Component.Serializer.toJson(this.tooltip));
return obj; return obj;
} }
@Override @Override
public void write(FriendlyByteBuf buf) { 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) { public static EntityBrainsweepIngredient deserialize(JsonObject obj) {
var reqs = EntityPredicate.Composite.fromJson(obj, "requirements", DeserializationContext) 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

@ -8,6 +8,7 @@ import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.MutableComponent;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.GsonHelper; import net.minecraft.util.GsonHelper;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
@ -26,27 +27,26 @@ public class VillagerBrainsweepIngredient extends BrainsweepIngredient {
private final @Nullable ResourceLocation biome; private final @Nullable ResourceLocation biome;
private final int minLevel; private final int minLevel;
protected VillagerBrainsweepIngredient( public VillagerBrainsweepIngredient(
@Nullable ResourceLocation profession, @Nullable ResourceLocation profession,
@Nullable ResourceLocation biome, // aka their "type" @Nullable ResourceLocation biome, // aka their "type"
int minLevel int minLevel
) { ) {
super();
this.profession = profession; this.profession = profession;
this.biome = biome; this.biome = biome;
this.minLevel = minLevel; this.minLevel = minLevel;
} }
@Override @Override
public boolean test(Entity entity) { public boolean test(Entity entity, ServerLevel level) {
if (!(entity instanceof Villager villager)) return false; if (!(entity instanceof Villager villager)) return false;
var data = villager.getVillagerData(); var data = villager.getVillagerData();
ResourceLocation profID = IXplatAbstractions.INSTANCE.getID(data.getProfession()); ResourceLocation profID = IXplatAbstractions.INSTANCE.getID(data.getProfession());
return (this.profession == null || this.profession.equals(profID)) return (this.profession == null || this.profession.equals(profID))
&& (this.biome == null || this.biome.equals(Registry.VILLAGER_TYPE.getKey(data.getType()))) && (this.biome == null || this.biome.equals(Registry.VILLAGER_TYPE.getKey(data.getType())))
&& this.minLevel <= data.getLevel(); && this.minLevel <= data.getLevel();
} }
@Override @Override
@ -57,10 +57,10 @@ public class VillagerBrainsweepIngredient extends BrainsweepIngredient {
if (advanced) { if (advanced) {
if (minLevel >= 5) { if (minLevel >= 5) {
tooltip.add(Component.translatable("hexcasting.tooltip.brainsweep.level", 5) tooltip.add(Component.translatable("hexcasting.tooltip.brainsweep.level", 5)
.withStyle(ChatFormatting.DARK_GRAY)); .withStyle(ChatFormatting.DARK_GRAY));
} else if (minLevel > 1) { } else if (minLevel > 1) {
tooltip.add(Component.translatable("hexcasting.tooltip.brainsweep.min_level", minLevel) tooltip.add(Component.translatable("hexcasting.tooltip.brainsweep.min_level", minLevel)
.withStyle(ChatFormatting.DARK_GRAY)); .withStyle(ChatFormatting.DARK_GRAY));
} }
if (biome != null) { if (biome != null) {
@ -68,7 +68,7 @@ public class VillagerBrainsweepIngredient extends BrainsweepIngredient {
} }
ResourceLocation displayId = Objects.requireNonNullElseGet(profession, ResourceLocation displayId = Objects.requireNonNullElseGet(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));
} }
@ -153,14 +153,15 @@ public class VillagerBrainsweepIngredient extends BrainsweepIngredient {
public static VillagerBrainsweepIngredient deserialize(JsonObject json) { public static VillagerBrainsweepIngredient deserialize(JsonObject json) {
ResourceLocation profession = null; ResourceLocation profession = null;
if (json.has("profession")) { if (json.has("profession") && !json.get("profession").isJsonNull()) {
profession = new ResourceLocation(GsonHelper.getAsString(json, "profession")); profession = new ResourceLocation(GsonHelper.getAsString(json, "profession"));
} }
ResourceLocation biome = null; ResourceLocation biome = null;
if (json.has("biome")) { if (json.has("biome") && !json.get("biome").isJsonNull()) {
biome = new ResourceLocation(GsonHelper.getAsString(json, "biome")); biome = new ResourceLocation(GsonHelper.getAsString(json, "biome"));
} }
int minLevel = GsonHelper.getAsInt(json, "minLevel"); int minLevel = GsonHelper.getAsInt(json, "minLevel");
int cost = GsonHelper.getAsInt(json, "cost");
return new VillagerBrainsweepIngredient(profession, biome, minLevel); return new VillagerBrainsweepIngredient(profession, biome, minLevel);
} }

View file

@ -2,6 +2,7 @@ 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.mod.HexItemTags 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
@ -10,7 +11,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.BrainsweepIngredient import at.petrak.hexcasting.common.recipe.ingredient.brainsweep.VillagerBrainsweepIngredient
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
@ -36,9 +37,9 @@ import net.minecraft.world.level.block.Blocks
import java.util.function.Consumer import java.util.function.Consumer
class HexplatRecipes( class HexplatRecipes(
val generator: DataGenerator, val generator: DataGenerator,
val ingredients: IXplatIngredients, val ingredients: IXplatIngredients,
val conditions: (RecipeBuilder) -> IXplatConditionsBuilder val conditions: (RecipeBuilder) -> IXplatConditionsBuilder
) : PaucalRecipeProvider(generator, HexAPI.MOD_ID) { ) : PaucalRecipeProvider(generator, HexAPI.MOD_ID) {
override fun makeRecipes(recipes: Consumer<FinishedRecipe>) { override fun makeRecipes(recipes: Consumer<FinishedRecipe>) {
@ -56,78 +57,78 @@ class HexplatRecipes(
wandRecipe(recipes, HexItems.STAFF_EDIFIED, HexBlocks.EDIFIED_PLANKS.asItem()) wandRecipe(recipes, HexItems.STAFF_EDIFIED, HexBlocks.EDIFIED_PLANKS.asItem())
ringCornered(HexItems.FOCUS, 1, ringCornered(HexItems.FOCUS, 1,
ingredients.glowstoneDust(), ingredients.glowstoneDust(),
ingredients.leather(), ingredients.leather(),
Ingredient.of(HexItems.CHARGED_AMETHYST)) Ingredient.of(HexItems.CHARGED_AMETHYST))
.unlockedBy("has_item", hasItem(HexItemTags.STAVES)) .unlockedBy("has_item", hasItem(HexItemTags.STAVES))
.save(recipes) .save(recipes)
ShapedRecipeBuilder.shaped(HexItems.SPELLBOOK) ShapedRecipeBuilder.shaped(HexItems.SPELLBOOK)
.define('N', ingredients.goldNugget()) .define('N', ingredients.goldNugget())
.define('B', Items.WRITABLE_BOOK) .define('B', Items.WRITABLE_BOOK)
.define('A', HexItems.CHARGED_AMETHYST) .define('A', HexItems.CHARGED_AMETHYST)
.define('F', Items.CHORUS_FRUIT) // i wanna gate this behind the end SOMEHOW .define('F', Items.CHORUS_FRUIT) // i wanna gate this behind the end SOMEHOW
// hey look its my gender ^^ // hey look its my gender ^^
.pattern("NBA") .pattern("NBA")
.pattern("NFA") .pattern("NFA")
.pattern("NBA") .pattern("NBA")
.unlockedBy("has_focus", hasItem(HexItems.FOCUS)) .unlockedBy("has_focus", hasItem(HexItems.FOCUS))
.unlockedBy("has_chorus", hasItem(Items.CHORUS_FRUIT)).save(recipes) .unlockedBy("has_chorus", hasItem(Items.CHORUS_FRUIT)).save(recipes)
ringCornerless( ringCornerless(
HexItems.CYPHER, 1, HexItems.CYPHER, 1,
ingredients.copperIngot(), ingredients.copperIngot(),
Ingredient.of(HexItems.AMETHYST_DUST)) Ingredient.of(HexItems.AMETHYST_DUST))
.unlockedBy("has_item", hasItem(HexItemTags.STAVES)).save(recipes) .unlockedBy("has_item", hasItem(HexItemTags.STAVES)).save(recipes)
ringCornerless( ringCornerless(
HexItems.TRINKET, 1, HexItems.TRINKET, 1,
ingredients.ironIngot(), ingredients.ironIngot(),
Ingredient.of(Items.AMETHYST_SHARD)) Ingredient.of(Items.AMETHYST_SHARD))
.unlockedBy("has_item", hasItem(HexItemTags.STAVES)).save(recipes) .unlockedBy("has_item", hasItem(HexItemTags.STAVES)).save(recipes)
ShapedRecipeBuilder.shaped(HexItems.ARTIFACT) ShapedRecipeBuilder.shaped(HexItems.ARTIFACT)
.define('F', ingredients.goldIngot()) .define('F', ingredients.goldIngot())
.define('A', HexItems.CHARGED_AMETHYST) .define('A', HexItems.CHARGED_AMETHYST)
// why in god's name does minecraft have two different places for item tags // why in god's name does minecraft have two different places for item tags
.define('D', ItemTags.MUSIC_DISCS) .define('D', ItemTags.MUSIC_DISCS)
.pattern(" F ") .pattern(" F ")
.pattern("FAF") .pattern("FAF")
.pattern(" D ") .pattern(" D ")
.unlockedBy("has_item", hasItem(HexItemTags.STAVES)).save(recipes) .unlockedBy("has_item", hasItem(HexItemTags.STAVES)).save(recipes)
ringCornerless(HexItems.SCRYING_LENS, 1, Items.GLASS, HexItems.AMETHYST_DUST) ringCornerless(HexItems.SCRYING_LENS, 1, Items.GLASS, HexItems.AMETHYST_DUST)
.unlockedBy("has_item", hasItem(HexItemTags.STAVES)).save(recipes) .unlockedBy("has_item", hasItem(HexItemTags.STAVES)).save(recipes)
ShapedRecipeBuilder.shaped(HexItems.ABACUS) ShapedRecipeBuilder.shaped(HexItems.ABACUS)
.define('S', Items.STICK) .define('S', Items.STICK)
.define('A', Items.AMETHYST_SHARD) .define('A', Items.AMETHYST_SHARD)
.define('W', ItemTags.PLANKS) .define('W', ItemTags.PLANKS)
.pattern("WAW") .pattern("WAW")
.pattern("SAS") .pattern("SAS")
.pattern("WAW") .pattern("WAW")
.unlockedBy("has_item", hasItem(HexItemTags.STAVES)).save(recipes) .unlockedBy("has_item", hasItem(HexItemTags.STAVES)).save(recipes)
// Why am I like this // Why am I like this
ShapedRecipeBuilder.shaped(HexItems.SUBMARINE_SANDWICH) ShapedRecipeBuilder.shaped(HexItems.SUBMARINE_SANDWICH)
.define('S', Items.STICK) .define('S', Items.STICK)
.define('A', Items.AMETHYST_SHARD) .define('A', Items.AMETHYST_SHARD)
.define('C', Items.COOKED_BEEF) .define('C', Items.COOKED_BEEF)
.define('B', Items.BREAD) .define('B', Items.BREAD)
.pattern(" SA") .pattern(" SA")
.pattern(" C ") .pattern(" C ")
.pattern(" B ") .pattern(" B ")
.unlockedBy("has_item", hasItem(Items.AMETHYST_SHARD)).save(recipes) .unlockedBy("has_item", hasItem(Items.AMETHYST_SHARD)).save(recipes)
for (dye in DyeColor.values()) { for (dye in DyeColor.values()) {
val item = HexItems.DYE_COLORIZERS[dye]!! val item = HexItems.DYE_COLORIZERS[dye]!!
ShapedRecipeBuilder.shaped(item) ShapedRecipeBuilder.shaped(item)
.define('D', HexItems.AMETHYST_DUST) .define('D', HexItems.AMETHYST_DUST)
.define('C', DyeItem.byColor(dye)) .define('C', DyeItem.byColor(dye))
.pattern(" D ") .pattern(" D ")
.pattern("DCD") .pattern("DCD")
.pattern(" D ") .pattern(" D ")
.unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)).save(recipes) .unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)).save(recipes)
} }
gayRecipe(recipes, ItemPrideColorizer.Type.AGENDER, Ingredient.of(Items.GLASS)) gayRecipe(recipes, ItemPrideColorizer.Type.AGENDER, Ingredient.of(Items.GLASS))
@ -144,337 +145,337 @@ class HexplatRecipes(
gayRecipe(recipes, ItemPrideColorizer.Type.LESBIAN, Ingredient.of(Items.HONEYCOMB)) gayRecipe(recipes, ItemPrideColorizer.Type.LESBIAN, Ingredient.of(Items.HONEYCOMB))
gayRecipe(recipes, ItemPrideColorizer.Type.NONBINARY, Ingredient.of(Items.MOSS_BLOCK)) gayRecipe(recipes, ItemPrideColorizer.Type.NONBINARY, Ingredient.of(Items.MOSS_BLOCK))
gayRecipe(recipes, ItemPrideColorizer.Type.PANSEXUAL, ingredients.whenModIngredient( gayRecipe(recipes, ItemPrideColorizer.Type.PANSEXUAL, ingredients.whenModIngredient(
Ingredient.of(Items.CARROT), Ingredient.of(Items.CARROT),
"farmersdelight", "farmersdelight",
CompatIngredientValue.of("farmersdelight:skillet") CompatIngredientValue.of("farmersdelight:skillet")
)) ))
gayRecipe(recipes, ItemPrideColorizer.Type.PLURAL, Ingredient.of(Items.REPEATER)) gayRecipe(recipes, ItemPrideColorizer.Type.PLURAL, Ingredient.of(Items.REPEATER))
gayRecipe(recipes, ItemPrideColorizer.Type.TRANSGENDER, Ingredient.of(Items.EGG)) gayRecipe(recipes, ItemPrideColorizer.Type.TRANSGENDER, Ingredient.of(Items.EGG))
ShapedRecipeBuilder.shaped(HexItems.UUID_COLORIZER) ShapedRecipeBuilder.shaped(HexItems.UUID_COLORIZER)
.define('B', Items.BOWL) .define('B', Items.BOWL)
.define('D', HexItems.AMETHYST_DUST) .define('D', HexItems.AMETHYST_DUST)
.define('C', Items.AMETHYST_SHARD) .define('C', Items.AMETHYST_SHARD)
.pattern(" C ") .pattern(" C ")
.pattern(" D ") .pattern(" D ")
.pattern(" B ") .pattern(" B ")
.unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)).save(recipes) .unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)).save(recipes)
ShapedRecipeBuilder.shaped(HexItems.SCROLL_SMOL) ShapedRecipeBuilder.shaped(HexItems.SCROLL_SMOL)
.define('P', Items.PAPER) .define('P', Items.PAPER)
.define('A', Items.AMETHYST_SHARD) .define('A', Items.AMETHYST_SHARD)
.pattern(" A") .pattern(" A")
.pattern("P ") .pattern("P ")
.unlockedBy("has_item", hasItem(Items.AMETHYST_SHARD)).save(recipes) .unlockedBy("has_item", hasItem(Items.AMETHYST_SHARD)).save(recipes)
ShapedRecipeBuilder.shaped(HexItems.SCROLL_MEDIUM) ShapedRecipeBuilder.shaped(HexItems.SCROLL_MEDIUM)
.define('P', Items.PAPER) .define('P', Items.PAPER)
.define('A', Items.AMETHYST_SHARD) .define('A', Items.AMETHYST_SHARD)
.pattern(" A") .pattern(" A")
.pattern("PP ") .pattern("PP ")
.pattern("PP ") .pattern("PP ")
.unlockedBy("has_item", hasItem(Items.AMETHYST_SHARD)).save(recipes) .unlockedBy("has_item", hasItem(Items.AMETHYST_SHARD)).save(recipes)
ShapedRecipeBuilder.shaped(HexItems.SCROLL_LARGE) ShapedRecipeBuilder.shaped(HexItems.SCROLL_LARGE)
.define('P', Items.PAPER) .define('P', Items.PAPER)
.define('A', Items.AMETHYST_SHARD) .define('A', Items.AMETHYST_SHARD)
.pattern("PPA") .pattern("PPA")
.pattern("PPP") .pattern("PPP")
.pattern("PPP") .pattern("PPP")
.unlockedBy("has_item", hasItem(Items.AMETHYST_SHARD)).save(recipes) .unlockedBy("has_item", hasItem(Items.AMETHYST_SHARD)).save(recipes)
ShapedRecipeBuilder.shaped(HexItems.SLATE, 6) ShapedRecipeBuilder.shaped(HexItems.SLATE, 6)
.define('S', Items.DEEPSLATE) .define('S', Items.DEEPSLATE)
.define('A', HexItems.AMETHYST_DUST) .define('A', HexItems.AMETHYST_DUST)
.pattern(" A ") .pattern(" A ")
.pattern("SSS") .pattern("SSS")
.unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)).save(recipes) .unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)).save(recipes)
ShapedRecipeBuilder.shaped(HexItems.JEWELER_HAMMER) ShapedRecipeBuilder.shaped(HexItems.JEWELER_HAMMER)
.define('I', ingredients.ironIngot()) .define('I', ingredients.ironIngot())
.define('N', ingredients.ironNugget()) .define('N', ingredients.ironNugget())
.define('A', Items.AMETHYST_SHARD) .define('A', Items.AMETHYST_SHARD)
.define('S', ingredients.stick()) .define('S', ingredients.stick())
.pattern("IAN") .pattern("IAN")
.pattern(" S ") .pattern(" S ")
.pattern(" S ") .pattern(" S ")
.unlockedBy("has_item", hasItem(Items.AMETHYST_SHARD)).save(recipes) .unlockedBy("has_item", hasItem(Items.AMETHYST_SHARD)).save(recipes)
ShapedRecipeBuilder.shaped(HexBlocks.SLATE_BLOCK) ShapedRecipeBuilder.shaped(HexBlocks.SLATE_BLOCK)
.define('S', HexItems.SLATE) .define('S', HexItems.SLATE)
.pattern("S") .pattern("S")
.pattern("S") .pattern("S")
.unlockedBy("has_item", hasItem(HexItems.SLATE)) .unlockedBy("has_item", hasItem(HexItems.SLATE))
.save(recipes, modLoc("slate_block_from_slates")) .save(recipes, modLoc("slate_block_from_slates"))
ringAll(HexBlocks.SLATE_BLOCK, 8, Blocks.DEEPSLATE, HexItems.AMETHYST_DUST) ringAll(HexBlocks.SLATE_BLOCK, 8, Blocks.DEEPSLATE, HexItems.AMETHYST_DUST)
.unlockedBy("has_item", hasItem(HexItems.SLATE)).save(recipes) .unlockedBy("has_item", hasItem(HexItems.SLATE)).save(recipes)
packing(HexItems.AMETHYST_DUST, HexBlocks.AMETHYST_DUST_BLOCK.asItem(), "amethyst_dust", packing(HexItems.AMETHYST_DUST, HexBlocks.AMETHYST_DUST_BLOCK.asItem(), "amethyst_dust",
false, recipes) false, recipes)
ringAll(HexBlocks.AMETHYST_TILES, 8, Blocks.AMETHYST_BLOCK, HexItems.AMETHYST_DUST) ringAll(HexBlocks.AMETHYST_TILES, 8, Blocks.AMETHYST_BLOCK, HexItems.AMETHYST_DUST)
.unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)).save(recipes) .unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)).save(recipes)
SingleItemRecipeBuilder.stonecutting(Ingredient.of(Blocks.AMETHYST_BLOCK), HexBlocks.AMETHYST_TILES) SingleItemRecipeBuilder.stonecutting(Ingredient.of(Blocks.AMETHYST_BLOCK), HexBlocks.AMETHYST_TILES)
.unlockedBy("has_item", hasItem(Blocks.AMETHYST_BLOCK)) .unlockedBy("has_item", hasItem(Blocks.AMETHYST_BLOCK))
.save(recipes, modLoc("stonecutting/amethyst_tiles")) .save(recipes, modLoc("stonecutting/amethyst_tiles"))
ringAll(HexBlocks.SCROLL_PAPER, 8, Items.PAPER, Items.AMETHYST_SHARD) ringAll(HexBlocks.SCROLL_PAPER, 8, Items.PAPER, Items.AMETHYST_SHARD)
.unlockedBy("has_item", hasItem(Items.AMETHYST_SHARD)).save(recipes) .unlockedBy("has_item", hasItem(Items.AMETHYST_SHARD)).save(recipes)
ShapelessRecipeBuilder.shapeless(HexBlocks.ANCIENT_SCROLL_PAPER, 8) ShapelessRecipeBuilder.shapeless(HexBlocks.ANCIENT_SCROLL_PAPER, 8)
.requires(ingredients.dyes()[DyeColor.BROWN]!!) .requires(ingredients.dyes()[DyeColor.BROWN]!!)
.requires(HexBlocks.SCROLL_PAPER, 8) .requires(HexBlocks.SCROLL_PAPER, 8)
.unlockedBy("has_item", hasItem(HexBlocks.SCROLL_PAPER)).save(recipes) .unlockedBy("has_item", hasItem(HexBlocks.SCROLL_PAPER)).save(recipes)
stack(HexBlocks.SCROLL_PAPER_LANTERN, 1, HexBlocks.SCROLL_PAPER, Items.TORCH) stack(HexBlocks.SCROLL_PAPER_LANTERN, 1, HexBlocks.SCROLL_PAPER, Items.TORCH)
.unlockedBy("has_item", hasItem(HexBlocks.SCROLL_PAPER)).save(recipes) .unlockedBy("has_item", hasItem(HexBlocks.SCROLL_PAPER)).save(recipes)
stack(HexBlocks.ANCIENT_SCROLL_PAPER_LANTERN, 1, HexBlocks.ANCIENT_SCROLL_PAPER, Items.TORCH) stack(HexBlocks.ANCIENT_SCROLL_PAPER_LANTERN, 1, HexBlocks.ANCIENT_SCROLL_PAPER, Items.TORCH)
.unlockedBy("has_item", hasItem(HexBlocks.ANCIENT_SCROLL_PAPER)).save(recipes) .unlockedBy("has_item", hasItem(HexBlocks.ANCIENT_SCROLL_PAPER)).save(recipes)
ShapelessRecipeBuilder.shapeless(HexBlocks.ANCIENT_SCROLL_PAPER_LANTERN, 8) ShapelessRecipeBuilder.shapeless(HexBlocks.ANCIENT_SCROLL_PAPER_LANTERN, 8)
.requires(ingredients.dyes()[DyeColor.BROWN]!!) .requires(ingredients.dyes()[DyeColor.BROWN]!!)
.requires(HexBlocks.SCROLL_PAPER_LANTERN, 8) .requires(HexBlocks.SCROLL_PAPER_LANTERN, 8)
.unlockedBy("has_item", hasItem(HexBlocks.SCROLL_PAPER_LANTERN)) .unlockedBy("has_item", hasItem(HexBlocks.SCROLL_PAPER_LANTERN))
.save(recipes, modLoc("ageing_scroll_paper_lantern")) .save(recipes, modLoc("ageing_scroll_paper_lantern"))
stack(HexBlocks.SCONCE, 4, stack(HexBlocks.SCONCE, 4,
Ingredient.of(HexItems.CHARGED_AMETHYST), Ingredient.of(HexItems.CHARGED_AMETHYST),
ingredients.copperIngot()) ingredients.copperIngot())
.unlockedBy("has_item", hasItem(HexItems.CHARGED_AMETHYST)).save(recipes) .unlockedBy("has_item", hasItem(HexItems.CHARGED_AMETHYST)).save(recipes)
ShapelessRecipeBuilder.shapeless(HexBlocks.EDIFIED_PLANKS, 4) ShapelessRecipeBuilder.shapeless(HexBlocks.EDIFIED_PLANKS, 4)
.requires(HexItemTags.EDIFIED_LOGS) .requires(HexItemTags.EDIFIED_LOGS)
.unlockedBy("has_item", hasItem(HexItemTags.EDIFIED_LOGS)).save(recipes) .unlockedBy("has_item", hasItem(HexItemTags.EDIFIED_LOGS)).save(recipes)
ShapedRecipeBuilder.shaped(HexBlocks.EDIFIED_WOOD, 3) ShapedRecipeBuilder.shaped(HexBlocks.EDIFIED_WOOD, 3)
.define('W', HexBlocks.EDIFIED_LOG) .define('W', HexBlocks.EDIFIED_LOG)
.pattern("WW") .pattern("WW")
.pattern("WW") .pattern("WW")
.unlockedBy("has_item", hasItem(HexBlocks.EDIFIED_LOG)).save(recipes) .unlockedBy("has_item", hasItem(HexBlocks.EDIFIED_LOG)).save(recipes)
ShapedRecipeBuilder.shaped(HexBlocks.STRIPPED_EDIFIED_WOOD, 3) ShapedRecipeBuilder.shaped(HexBlocks.STRIPPED_EDIFIED_WOOD, 3)
.define('W', HexBlocks.STRIPPED_EDIFIED_LOG) .define('W', HexBlocks.STRIPPED_EDIFIED_LOG)
.pattern("WW") .pattern("WW")
.pattern("WW") .pattern("WW")
.unlockedBy("has_item", hasItem(HexBlocks.STRIPPED_EDIFIED_LOG)).save(recipes) .unlockedBy("has_item", hasItem(HexBlocks.STRIPPED_EDIFIED_LOG)).save(recipes)
ring(HexBlocks.EDIFIED_PANEL, 8, ring(HexBlocks.EDIFIED_PANEL, 8,
HexItemTags.EDIFIED_PLANKS, null) HexItemTags.EDIFIED_PLANKS, null)
.unlockedBy("has_item", hasItem(HexItemTags.EDIFIED_PLANKS)).save(recipes) .unlockedBy("has_item", hasItem(HexItemTags.EDIFIED_PLANKS)).save(recipes)
ShapedRecipeBuilder.shaped(HexBlocks.EDIFIED_TILE, 6) ShapedRecipeBuilder.shaped(HexBlocks.EDIFIED_TILE, 6)
.define('W', HexItemTags.EDIFIED_PLANKS) .define('W', HexItemTags.EDIFIED_PLANKS)
.pattern("WW ") .pattern("WW ")
.pattern("W W") .pattern("W W")
.pattern(" WW") .pattern(" WW")
.unlockedBy("has_item", hasItem(HexItemTags.EDIFIED_PLANKS)).save(recipes) .unlockedBy("has_item", hasItem(HexItemTags.EDIFIED_PLANKS)).save(recipes)
ShapedRecipeBuilder.shaped(HexBlocks.EDIFIED_DOOR, 3) ShapedRecipeBuilder.shaped(HexBlocks.EDIFIED_DOOR, 3)
.define('W', HexItemTags.EDIFIED_PLANKS) .define('W', HexItemTags.EDIFIED_PLANKS)
.pattern("WW") .pattern("WW")
.pattern("WW") .pattern("WW")
.pattern("WW") .pattern("WW")
.unlockedBy("has_item", hasItem(HexItemTags.EDIFIED_PLANKS)).save(recipes) .unlockedBy("has_item", hasItem(HexItemTags.EDIFIED_PLANKS)).save(recipes)
ShapedRecipeBuilder.shaped(HexBlocks.EDIFIED_TRAPDOOR, 2) ShapedRecipeBuilder.shaped(HexBlocks.EDIFIED_TRAPDOOR, 2)
.define('W', HexItemTags.EDIFIED_PLANKS) .define('W', HexItemTags.EDIFIED_PLANKS)
.pattern("WWW") .pattern("WWW")
.pattern("WWW") .pattern("WWW")
.unlockedBy("has_item", hasItem(HexItemTags.EDIFIED_PLANKS)).save(recipes) .unlockedBy("has_item", hasItem(HexItemTags.EDIFIED_PLANKS)).save(recipes)
ShapedRecipeBuilder.shaped(HexBlocks.EDIFIED_STAIRS, 4) ShapedRecipeBuilder.shaped(HexBlocks.EDIFIED_STAIRS, 4)
.define('W', HexItemTags.EDIFIED_PLANKS) .define('W', HexItemTags.EDIFIED_PLANKS)
.pattern("W ") .pattern("W ")
.pattern("WW ") .pattern("WW ")
.pattern("WWW") .pattern("WWW")
.unlockedBy("has_item", hasItem(HexItemTags.EDIFIED_PLANKS)).save(recipes) .unlockedBy("has_item", hasItem(HexItemTags.EDIFIED_PLANKS)).save(recipes)
ShapedRecipeBuilder.shaped(HexBlocks.EDIFIED_SLAB, 6) ShapedRecipeBuilder.shaped(HexBlocks.EDIFIED_SLAB, 6)
.define('W', HexItemTags.EDIFIED_PLANKS) .define('W', HexItemTags.EDIFIED_PLANKS)
.pattern("WWW") .pattern("WWW")
.unlockedBy("has_item", hasItem(HexItemTags.EDIFIED_PLANKS)).save(recipes) .unlockedBy("has_item", hasItem(HexItemTags.EDIFIED_PLANKS)).save(recipes)
ShapedRecipeBuilder.shaped(HexBlocks.EDIFIED_PRESSURE_PLATE, 1) ShapedRecipeBuilder.shaped(HexBlocks.EDIFIED_PRESSURE_PLATE, 1)
.define('W', HexItemTags.EDIFIED_PLANKS) .define('W', HexItemTags.EDIFIED_PLANKS)
.pattern("WW") .pattern("WW")
.unlockedBy("has_item", hasItem(HexItemTags.EDIFIED_PLANKS)).save(recipes) .unlockedBy("has_item", hasItem(HexItemTags.EDIFIED_PLANKS)).save(recipes)
ShapelessRecipeBuilder.shapeless(HexBlocks.EDIFIED_BUTTON) ShapelessRecipeBuilder.shapeless(HexBlocks.EDIFIED_BUTTON)
.requires(HexItemTags.EDIFIED_PLANKS) .requires(HexItemTags.EDIFIED_PLANKS)
.unlockedBy("has_item", hasItem(HexItemTags.EDIFIED_PLANKS)).save(recipes) .unlockedBy("has_item", hasItem(HexItemTags.EDIFIED_PLANKS)).save(recipes)
val enlightenment = OvercastTrigger.Instance( val enlightenment = OvercastTrigger.Instance(
EntityPredicate.Composite.ANY, EntityPredicate.Composite.ANY,
MinMaxBounds.Ints.ANY, // add a little bit of slop here MinMaxBounds.Ints.ANY, // add a little bit of slop here
MinMaxBounds.Doubles.atLeast(0.8), MinMaxBounds.Doubles.atLeast(0.8),
MinMaxBounds.Doubles.between(0.1, 2.05) MinMaxBounds.Doubles.between(0.1, 2.05)
) )
ShapedRecipeBuilder.shaped(HexBlocks.EMPTY_IMPETUS) ShapedRecipeBuilder.shaped(HexBlocks.EMPTY_IMPETUS)
.define('B', Items.IRON_BARS) .define('B', Items.IRON_BARS)
.define('A', HexItems.CHARGED_AMETHYST) .define('A', HexItems.CHARGED_AMETHYST)
.define('S', HexBlocks.SLATE_BLOCK) .define('S', HexBlocks.SLATE_BLOCK)
.define('P', Items.PURPUR_BLOCK) .define('P', Items.PURPUR_BLOCK)
.pattern("PSS") .pattern("PSS")
.pattern("BAB") .pattern("BAB")
.pattern("SSP") .pattern("SSP")
.unlockedBy("enlightenment", enlightenment).save(recipes) .unlockedBy("enlightenment", enlightenment).save(recipes)
ShapedRecipeBuilder.shaped(HexBlocks.EMPTY_DIRECTRIX) ShapedRecipeBuilder.shaped(HexBlocks.EMPTY_DIRECTRIX)
.define('C', Items.COMPARATOR) .define('C', Items.COMPARATOR)
.define('O', Items.OBSERVER) .define('O', Items.OBSERVER)
.define('A', HexItems.CHARGED_AMETHYST) .define('A', HexItems.CHARGED_AMETHYST)
.define('S', HexBlocks.SLATE_BLOCK) .define('S', HexBlocks.SLATE_BLOCK)
.pattern("CSS") .pattern("CSS")
.pattern("OAO") .pattern("OAO")
.pattern("SSC") .pattern("SSC")
.unlockedBy("enlightenment", enlightenment).save(recipes) .unlockedBy("enlightenment", enlightenment).save(recipes)
ShapedRecipeBuilder.shaped(HexBlocks.AKASHIC_BOOKSHELF) ShapedRecipeBuilder.shaped(HexBlocks.AKASHIC_BOOKSHELF)
.define('L', HexItemTags.EDIFIED_LOGS) .define('L', HexItemTags.EDIFIED_LOGS)
.define('P', HexItemTags.EDIFIED_PLANKS) .define('P', HexItemTags.EDIFIED_PLANKS)
.define('C', Items.BOOK) .define('C', Items.BOOK)
/*this is the*/.pattern("LPL") // and what i have for you today is /*this is the*/.pattern("LPL") // and what i have for you today is
.pattern("CCC") .pattern("CCC")
.pattern("LPL") .pattern("LPL")
.unlockedBy("enlightenment", enlightenment).save(recipes) .unlockedBy("enlightenment", enlightenment).save(recipes)
ShapedRecipeBuilder.shaped(HexBlocks.AKASHIC_LIGATURE) ShapedRecipeBuilder.shaped(HexBlocks.AKASHIC_LIGATURE)
.define('L', HexItemTags.EDIFIED_LOGS) .define('L', HexItemTags.EDIFIED_LOGS)
.define('P', HexItemTags.EDIFIED_PLANKS) .define('P', HexItemTags.EDIFIED_PLANKS)
.define('C', HexItems.CHARGED_AMETHYST) .define('C', HexItems.CHARGED_AMETHYST)
.pattern("LPL") .pattern("LPL")
.pattern("CCC") .pattern("CCC")
.pattern("LPL") .pattern("LPL")
.unlockedBy("enlightenment", enlightenment).save(recipes) .unlockedBy("enlightenment", enlightenment).save(recipes)
BrainsweepRecipeBuilder(StateIngredientHelper.of(Blocks.AMETHYST_BLOCK), BrainsweepRecipeBuilder(StateIngredientHelper.of(Blocks.AMETHYST_BLOCK),
BrainsweepIngredient(null, null, 3), VillagerBrainsweepIngredient(null, null, 3),
Blocks.BUDDING_AMETHYST.defaultBlockState()) 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),
BrainsweepIngredient(ResourceLocation("toolsmith"), null, 2), VillagerBrainsweepIngredient(ResourceLocation("toolsmith"), null, 2),
HexBlocks.IMPETUS_RIGHTCLICK.defaultBlockState()) 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),
BrainsweepIngredient(ResourceLocation("fletcher"), null, 2), VillagerBrainsweepIngredient(ResourceLocation("fletcher"), null, 2),
HexBlocks.IMPETUS_LOOK.defaultBlockState()) 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),
BrainsweepIngredient(ResourceLocation("cleric"), null, 2), VillagerBrainsweepIngredient(ResourceLocation("cleric"), null, 2),
HexBlocks.IMPETUS_STOREDPLAYER.defaultBlockState()) 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),
BrainsweepIngredient(ResourceLocation("mason"), null, 1), VillagerBrainsweepIngredient(ResourceLocation("mason"), null, 1),
HexBlocks.DIRECTRIX_REDSTONE.defaultBlockState()) 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),
BrainsweepIngredient(ResourceLocation("librarian"), null, 5), VillagerBrainsweepIngredient(ResourceLocation("librarian"), null, 5),
HexBlocks.AKASHIC_RECORD.defaultBlockState()) 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"))
// Create compat // Create compat
CreateCrushingRecipeBuilder() CreateCrushingRecipeBuilder()
.withInput(Blocks.AMETHYST_CLUSTER) .withInput(Blocks.AMETHYST_CLUSTER)
.duration(150) .duration(150)
.withOutput(Items.AMETHYST_SHARD, 7) .withOutput(Items.AMETHYST_SHARD, 7)
.withOutput(HexItems.AMETHYST_DUST, 5) .withOutput(HexItems.AMETHYST_DUST, 5)
.withOutput(0.25f, HexItems.CHARGED_AMETHYST) .withOutput(0.25f, HexItems.CHARGED_AMETHYST)
.withConditions() .withConditions()
.whenModLoaded("create") .whenModLoaded("create")
.save(recipes, ResourceLocation("create", "crushing/amethyst_cluster")) .save(recipes, ResourceLocation("create", "crushing/amethyst_cluster"))
CreateCrushingRecipeBuilder() CreateCrushingRecipeBuilder()
.withInput(Blocks.AMETHYST_BLOCK) .withInput(Blocks.AMETHYST_BLOCK)
.duration(150) .duration(150)
.withOutput(Items.AMETHYST_SHARD, 3) .withOutput(Items.AMETHYST_SHARD, 3)
.withOutput(0.5f, HexItems.AMETHYST_DUST, 4) .withOutput(0.5f, HexItems.AMETHYST_DUST, 4)
.withConditions() .withConditions()
.whenModLoaded("create") .whenModLoaded("create")
.save(recipes, ResourceLocation("create", "crushing/amethyst_block")) .save(recipes, ResourceLocation("create", "crushing/amethyst_block"))
CreateCrushingRecipeBuilder() CreateCrushingRecipeBuilder()
.withInput(Items.AMETHYST_SHARD) .withInput(Items.AMETHYST_SHARD)
.duration(150) .duration(150)
.withOutput(HexItems.AMETHYST_DUST, 4) .withOutput(HexItems.AMETHYST_DUST, 4)
.withOutput(0.5f, HexItems.AMETHYST_DUST) .withOutput(0.5f, HexItems.AMETHYST_DUST)
.withConditions() .withConditions()
.whenModLoaded("create") .whenModLoaded("create")
.save(recipes, modLoc("compat/create/crushing/amethyst_shard")) .save(recipes, modLoc("compat/create/crushing/amethyst_shard"))
// FD compat // FD compat
FarmersDelightCuttingRecipeBuilder() FarmersDelightCuttingRecipeBuilder()
.withInput(HexBlocks.EDIFIED_LOG) .withInput(HexBlocks.EDIFIED_LOG)
.withTool(ingredients.axeStrip()) .withTool(ingredients.axeStrip())
.withOutput(HexBlocks.STRIPPED_EDIFIED_LOG) .withOutput(HexBlocks.STRIPPED_EDIFIED_LOG)
.withOutput("farmersdelight:tree_bark") .withOutput("farmersdelight:tree_bark")
.withSound(SoundEvents.AXE_STRIP) .withSound(SoundEvents.AXE_STRIP)
.withConditions() .withConditions()
.whenModLoaded("farmersdelight") .whenModLoaded("farmersdelight")
.save(recipes, modLoc("compat/farmersdelight/cutting/akashic_log")) .save(recipes, modLoc("compat/farmersdelight/cutting/akashic_log"))
FarmersDelightCuttingRecipeBuilder() FarmersDelightCuttingRecipeBuilder()
.withInput(HexBlocks.EDIFIED_WOOD) .withInput(HexBlocks.EDIFIED_WOOD)
.withTool(ingredients.axeStrip()) .withTool(ingredients.axeStrip())
.withOutput(HexBlocks.STRIPPED_EDIFIED_WOOD) .withOutput(HexBlocks.STRIPPED_EDIFIED_WOOD)
.withOutput("farmersdelight:tree_bark") .withOutput("farmersdelight:tree_bark")
.withSound(SoundEvents.AXE_STRIP) .withSound(SoundEvents.AXE_STRIP)
.withConditions() .withConditions()
.whenModLoaded("farmersdelight") .whenModLoaded("farmersdelight")
.save(recipes, modLoc("compat/farmersdelight/cutting/akashic_wood")) .save(recipes, modLoc("compat/farmersdelight/cutting/akashic_wood"))
FarmersDelightCuttingRecipeBuilder() FarmersDelightCuttingRecipeBuilder()
.withInput(HexBlocks.EDIFIED_TRAPDOOR) .withInput(HexBlocks.EDIFIED_TRAPDOOR)
.withTool(ingredients.axeDig()) .withTool(ingredients.axeDig())
.withOutput(HexBlocks.EDIFIED_PLANKS) .withOutput(HexBlocks.EDIFIED_PLANKS)
.withConditions() .withConditions()
.whenModLoaded("farmersdelight") .whenModLoaded("farmersdelight")
.save(recipes, modLoc("compat/farmersdelight/cutting/akashic_trapdoor")) .save(recipes, modLoc("compat/farmersdelight/cutting/akashic_trapdoor"))
FarmersDelightCuttingRecipeBuilder() FarmersDelightCuttingRecipeBuilder()
.withInput(HexBlocks.EDIFIED_DOOR) .withInput(HexBlocks.EDIFIED_DOOR)
.withTool(ingredients.axeDig()) .withTool(ingredients.axeDig())
.withOutput(HexBlocks.EDIFIED_PLANKS) .withOutput(HexBlocks.EDIFIED_PLANKS)
.withConditions() .withConditions()
.whenModLoaded("farmersdelight") .whenModLoaded("farmersdelight")
.save(recipes, modLoc("compat/farmersdelight/cutting/akashic_door")) .save(recipes, modLoc("compat/farmersdelight/cutting/akashic_door"))
} }
private fun wandRecipe(recipes: Consumer<FinishedRecipe>, wand: ItemStaff, plank: Item) { private fun wandRecipe(recipes: Consumer<FinishedRecipe>, wand: ItemStaff, plank: Item) {
ShapedRecipeBuilder.shaped(wand) ShapedRecipeBuilder.shaped(wand)
.define('W', plank) .define('W', plank)
.define('S', Items.STICK) .define('S', Items.STICK)
.define('A', HexItems.CHARGED_AMETHYST) .define('A', HexItems.CHARGED_AMETHYST)
.pattern(" SA") .pattern(" SA")
.pattern(" WS") .pattern(" WS")
.pattern("S ") .pattern("S ")
.unlockedBy("has_item", hasItem(HexItems.CHARGED_AMETHYST)) .unlockedBy("has_item", hasItem(HexItems.CHARGED_AMETHYST))
.save(recipes) .save(recipes)
} }
private fun gayRecipe(recipes: Consumer<FinishedRecipe>, type: ItemPrideColorizer.Type, material: Ingredient) { private fun gayRecipe(recipes: Consumer<FinishedRecipe>, type: ItemPrideColorizer.Type, material: Ingredient) {
val colorizer = HexItems.PRIDE_COLORIZERS[type]!! val colorizer = HexItems.PRIDE_COLORIZERS[type]!!
ShapedRecipeBuilder.shaped(colorizer) ShapedRecipeBuilder.shaped(colorizer)
.define('D', HexItems.AMETHYST_DUST) .define('D', HexItems.AMETHYST_DUST)
.define('C', material) .define('C', material)
.pattern(" D ") .pattern(" D ")
.pattern("DCD") .pattern("DCD")
.pattern(" D ") .pattern(" D ")
.unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST)) .unlockedBy("has_item", hasItem(HexItems.AMETHYST_DUST))
.save(recipes) .save(recipes)
} }
private fun specialRecipe(consumer: Consumer<FinishedRecipe>, serializer: SimpleRecipeSerializer<*>) { private fun specialRecipe(consumer: Consumer<FinishedRecipe>, serializer: SimpleRecipeSerializer<*>) {

View file

@ -21,16 +21,19 @@ 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 StateIngredient blockIn; private final StateIngredient blockIn;
private BrainsweepIngredient villagerIn; private final BrainsweepIngredient villagerIn;
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, BrainsweepIngredient villagerIn, BlockState result,
int mediaCost) {
this.blockIn = blockIn; this.blockIn = blockIn;
this.villagerIn = villagerIn; this.villagerIn = villagerIn;
this.result = result; this.result = result;
this.mediaCost = mediaCost;
this.advancement = Advancement.Builder.advancement(); this.advancement = Advancement.Builder.advancement();
} }
@ -57,23 +60,24 @@ public class BrainsweepRecipeBuilder implements RecipeBuilder {
} }
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.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, BrainsweepIngredient villagerIn,
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("villagerIn", this.villagerIn.serialize()); json.add("entityIn", this.villagerIn.serialize());
json.addProperty("cost", this.mediaCost);
json.add("result", StateIngredientHelper.serializeBlockState(this.result)); json.add("result", StateIngredientHelper.serializeBlockState(this.result));
} }

View file

@ -47,11 +47,11 @@ public class BrainsweepProcessor implements IComponentProcessor {
} }
case "entity" -> { case "entity" -> {
var profession = Objects.requireNonNullElse(this.recipe.villagerIn().profession(), var profession = Objects.requireNonNullElse(this.recipe.entityIn().profession(),
new ResourceLocation("toolsmith")); new ResourceLocation("toolsmith"));
var biome = Objects.requireNonNullElse(this.recipe.villagerIn().biome(), var biome = Objects.requireNonNullElse(this.recipe.entityIn().biome(),
new ResourceLocation("plains")); new ResourceLocation("plains"));
var level = this.recipe.villagerIn().minLevel(); var level = this.recipe.entityIn().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);
@ -59,7 +59,7 @@ public class BrainsweepProcessor implements IComponentProcessor {
} }
case "entityTooltip" -> { case "entityTooltip" -> {
Minecraft mc = Minecraft.getInstance(); Minecraft mc = Minecraft.getInstance();
return IVariable.wrapList(this.recipe.villagerIn() return IVariable.wrapList(this.recipe.entityIn()
.getTooltip(mc.options.advancedItemTooltips) .getTooltip(mc.options.advancedItemTooltips)
.stream() .stream()
.map(IVariable::from) .map(IVariable::from)

View file

@ -1,6 +1,6 @@
package at.petrak.hexcasting.mixin; package at.petrak.hexcasting.mixin;
import at.petrak.hexcasting.common.misc.Brainsweeping; import at.petrak.hexcasting.xplat.IXplatAbstractions;
import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.Mob;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@ -13,7 +13,7 @@ public class MixinMob {
@Inject(method = "serverAiStep", at = @At("HEAD"), cancellable = true) @Inject(method = "serverAiStep", at = @At("HEAD"), cancellable = true)
private void onRegisterBrainGoals(CallbackInfo ci) { private void onRegisterBrainGoals(CallbackInfo ci) {
var self = (Mob) (Object) this; var self = (Mob) (Object) this;
if (Brainsweeping.isBrainswept(self)) { if (IXplatAbstractions.INSTANCE.isBrainswept(self)) {
ci.cancel(); ci.cancel();
} }
} }
@ -21,7 +21,7 @@ public class MixinMob {
@Inject(method = "playAmbientSound", at = @At("HEAD"), cancellable = true) @Inject(method = "playAmbientSound", at = @At("HEAD"), cancellable = true)
protected void onPlayAmbientSound(CallbackInfo ci) { protected void onPlayAmbientSound(CallbackInfo ci) {
var self = (Mob) (Object) this; var self = (Mob) (Object) this;
if (Brainsweeping.isBrainswept(self)) { if (IXplatAbstractions.INSTANCE.isBrainswept(self)) {
ci.cancel(); ci.cancel();
} }
} }

View file

@ -253,7 +253,7 @@
"command.hexcasting.pats.specific.success": "Gave %s with id %s to %s", "command.hexcasting.pats.specific.success": "Gave %s with id %s to %s",
"command.hexcasting.recalc": "Recalculated patterns", "command.hexcasting.recalc": "Recalculated patterns",
"command.hexcasting.brainsweep": "Brainswept %s", "command.hexcasting.brainsweep": "Brainswept %s",
"command.hexcasting.brainsweep.fail.badtype": "%s is not a villager", "command.hexcasting.brainsweep.fail.badtype": "%s is not a mob",
"command.hexcasting.brainsweep.fail.already": "%s is already empty", "command.hexcasting.brainsweep.fail.already": "%s is already empty",
"hexcasting.pattern.unknown": "Unknown pattern resource location %s", "hexcasting.pattern.unknown": "Unknown pattern resource location %s",
"hexcasting.debug.media_withdrawn": "%s - Media withdrawn: %s", "hexcasting.debug.media_withdrawn": "%s - Media withdrawn: %s",
@ -561,8 +561,8 @@
"hexcasting.mishap.bad_block": "Expected %s at %s, but got %s", "hexcasting.mishap.bad_block": "Expected %s at %s, but got %s",
"hexcasting.mishap.bad_block.sapling": "a sapling", "hexcasting.mishap.bad_block.sapling": "a sapling",
"hexcasting.mishap.bad_block.replaceable": "somewhere to place a block", "hexcasting.mishap.bad_block.replaceable": "somewhere to place a block",
"hexcasting.mishap.bad_brainsweep": "The %s rejected the villager's mind", "hexcasting.mishap.bad_brainsweep": "The %s rejected the being's mind",
"hexcasting.mishap.already_brainswept": "The villager has already been used", "hexcasting.mishap.already_brainswept": "The mind has already been used",
"hexcasting.mishap.no_spell_circle": "%s requires a spell circle", "hexcasting.mishap.no_spell_circle": "%s requires a spell circle",
"hexcasting.mishap.others_name": "Tried to invade the privacy of %s's soul", "hexcasting.mishap.others_name": "Tried to invade the privacy of %s's soul",
"hexcasting.mishap.others_name.self": "Tried to divulge my Name too recklessly", "hexcasting.mishap.others_name.self": "Tried to divulge my Name too recklessly",
@ -714,7 +714,7 @@
"hexcasting.entry.mishaps2": "Enlightened Mishaps", "hexcasting.entry.mishaps2": "Enlightened Mishaps",
"hexcasting.page.mishaps2.1": "I have discovered new and horrifying modes of failure. I must not succumb to them.", "hexcasting.page.mishaps2.1": "I have discovered new and horrifying modes of failure. I must not succumb to them.",
"hexcasting.page.mishaps2.bad_mindflay.title": "Inert Mindflay", "hexcasting.page.mishaps2.bad_mindflay.title": "Inert Mindflay",
"hexcasting.page.mishaps2.bad_mindflay": "Attempted to flay the mind of a villager that I have either already used, or of a character not suitable for the target block.$(br2)Causes dark green sparks, and kills the subject. If another villager sees that, I doubt they would look on it favorably.", "hexcasting.page.mishaps2.bad_mindflay": "Attempted to flay the mind of something that I have either already used, or of a character not suitable for the target block.$(br2)Causes dark green sparks, and kills the subject. If a villager sees that, I doubt they would look on it favorably.",
"hexcasting.page.mishaps2.no_circle.title": "Lack Spell Circle", "hexcasting.page.mishaps2.no_circle.title": "Lack Spell Circle",
"hexcasting.page.mishaps2.no_circle": "Tried to cast an action requiring a spell circle without a spell circle.$(br2)Causes light blue sparks, and upends my inventory onto the ground.", "hexcasting.page.mishaps2.no_circle": "Tried to cast an action requiring a spell circle without a spell circle.$(br2)Causes light blue sparks, and upends my inventory onto the ground.",
"hexcasting.page.mishaps2.no_record.title": "Lack Akashic Record", "hexcasting.page.mishaps2.no_record.title": "Lack Akashic Record",

View file

@ -63,8 +63,8 @@ object FabricHexInitializer : ModInitializer {
} }
fun initListeners() { fun initListeners() {
UseEntityCallback.EVENT.register(Brainsweeping::tradeWithVillager) UseEntityCallback.EVENT.register(Brainsweeping::interactWithBrainswept)
VillagerConversionCallback.EVENT.register(Brainsweeping::copyBrainsweepFromVillager) VillagerConversionCallback.EVENT.register(Brainsweeping::copyBrainsweepPostTransformation)
AttackBlockCallback.EVENT.register { player, world, _, pos, _ -> AttackBlockCallback.EVENT.register { player, world, _, pos, _ ->
// SUCCESS cancels further processing and, on the client, sends a packet to the server. // SUCCESS cancels further processing and, on the client, sends a packet to the server.
// PASS falls back to further processing. // PASS falls back to further processing.

View file

@ -39,24 +39,24 @@ public class HexEMIPlugin implements EmiPlugin {
private static final ResourceLocation SIMPLIFIED_ICON_PROFESSION = modLoc("textures/gui/villager_profession.png"); private static final ResourceLocation SIMPLIFIED_ICON_PROFESSION = modLoc("textures/gui/villager_profession.png");
public static final EmiRecipeCategory BRAINSWEEP = new EmiRecipeCategory(BRAINSWEEP_ID, public static final EmiRecipeCategory BRAINSWEEP = new EmiRecipeCategory(BRAINSWEEP_ID,
new PatternRendererEMI(BRAINSWEEP_ID, 16, 16), new PatternRendererEMI(BRAINSWEEP_ID, 16, 16),
new EmiTexture(SIMPLIFIED_ICON_BRAINSWEEP, 0, 0, 16, 16, 16, 16, 16, 16)); new EmiTexture(SIMPLIFIED_ICON_BRAINSWEEP, 0, 0, 16, 16, 16, 16, 16, 16));
public static final EmiRecipeCategory PHIAL = new EmiRecipeCategory(PHIAL_ID, public static final EmiRecipeCategory PHIAL = new EmiRecipeCategory(PHIAL_ID,
new PatternRendererEMI(PHIAL_ID, 12, 12).shift(2, 2), new PatternRendererEMI(PHIAL_ID, 12, 12).shift(2, 2),
new EmiTexture(SIMPLIFIED_ICON_PHIAL, 0, 0, 16, 16, 16, 16, 16, 16)); new EmiTexture(SIMPLIFIED_ICON_PHIAL, 0, 0, 16, 16, 16, 16, 16, 16));
public static final EmiRecipeCategory EDIFY = new EmiRecipeCategory(EDIFY_ID, public static final EmiRecipeCategory EDIFY = new EmiRecipeCategory(EDIFY_ID,
new PatternRendererEMI(EDIFY_ID, 16, 16).strokeOrder(false), new PatternRendererEMI(EDIFY_ID, 16, 16).strokeOrder(false),
new EmiTexture(SIMPLIFIED_ICON_EDIFY, 0, 0, 16, 16, 16, 16, 16, 16)); new EmiTexture(SIMPLIFIED_ICON_EDIFY, 0, 0, 16, 16, 16, 16, 16, 16));
public static final EmiRecipeCategory VILLAGER_LEVELING = new EmiRecipeCategory(VILLAGER_LEVELING_ID, public static final EmiRecipeCategory VILLAGER_LEVELING = new EmiRecipeCategory(VILLAGER_LEVELING_ID,
EmiStack.of(Items.EMERALD), EmiStack.of(Items.EMERALD),
new EmiTexture(SIMPLIFIED_ICON_LEVELING, 0, 0, 16, 16, 16, 16, 16, 16)); new EmiTexture(SIMPLIFIED_ICON_LEVELING, 0, 0, 16, 16, 16, 16, 16, 16));
public static final EmiRecipeCategory VILLAGER_PROFESSION = new EmiRecipeCategory(VILLAGER_PROFESSION_ID, public static final EmiRecipeCategory VILLAGER_PROFESSION = new EmiRecipeCategory(VILLAGER_PROFESSION_ID,
EmiStack.of(Blocks.LECTERN), EmiStack.of(Blocks.LECTERN),
new EmiTexture(SIMPLIFIED_ICON_PROFESSION, 0, 0, 16, 16, 16, 16, 16, 16)); new EmiTexture(SIMPLIFIED_ICON_PROFESSION, 0, 0, 16, 16, 16, 16, 16, 16));
@Override @Override
public void register(EmiRegistry registry) { public void register(EmiRegistry registry) {
@ -70,10 +70,10 @@ public class HexEMIPlugin implements EmiPlugin {
registry.addWorkstation(EDIFY, EmiIngredient.of(HexItemTags.STAVES)); registry.addWorkstation(EDIFY, EmiIngredient.of(HexItemTags.STAVES));
for (BrainsweepRecipe recipe : registry.getRecipeManager() for (BrainsweepRecipe recipe : registry.getRecipeManager()
.getAllRecipesFor(HexRecipeStuffRegistry.BRAINSWEEP_TYPE)) { .getAllRecipesFor(HexRecipeStuffRegistry.BRAINSWEEP_TYPE)) {
var inputs = EmiIngredient.of(recipe.blockIn().getDisplayedStacks().stream() var inputs = EmiIngredient.of(recipe.blockIn().getDisplayedStacks().stream()
.map(EmiStack::of).toList()); .map(EmiStack::of).toList());
var villagerInput = VillagerEmiStack.atLevelOrHigher(recipe.villagerIn(), true); var villagerInput = VillagerEmiStack.atLevelOrHigher(recipe.entityIn(), true);
var output = EmiStack.of(recipe.result().getBlock()); var output = EmiStack.of(recipe.result().getBlock());
registry.addRecipe(new EmiBrainsweepRecipe(inputs, villagerInput, output, recipe.getId())); registry.addRecipe(new EmiBrainsweepRecipe(inputs, villagerInput, output, recipe.getId()));
} }
@ -94,28 +94,28 @@ public class HexEMIPlugin implements EmiPlugin {
Set<BlockState> states = VillagerEmiStack.matchingStatesForProfession(profession); Set<BlockState> states = VillagerEmiStack.matchingStatesForProfession(profession);
if (!states.isEmpty()) { if (!states.isEmpty()) {
List<Item> workstations = states.stream() List<Item> workstations = states.stream()
.map(BlockState::getBlock) .map(BlockState::getBlock)
.map(Block::asItem) .map(Block::asItem)
.distinct() .distinct()
.filter((it) -> it != Items.AIR) .filter((it) -> it != Items.AIR)
.toList(); .toList();
if (!workstations.isEmpty()) { if (!workstations.isEmpty()) {
registry.addWorkstation(VILLAGER_LEVELING, registry.addWorkstation(VILLAGER_LEVELING,
EmiIngredient.of(workstations.stream().map(EmiStack::of).toList())); EmiIngredient.of(workstations.stream().map(EmiStack::of).toList()));
registry.addWorkstation(VILLAGER_PROFESSION, registry.addWorkstation(VILLAGER_PROFESSION,
EmiIngredient.of(workstations.stream().map(EmiStack::of).toList())); EmiIngredient.of(workstations.stream().map(EmiStack::of).toList()));
registry.addRecipe(new EmiProfessionRecipe(new VillagerEmiStack(basicVillager), registry.addRecipe(new EmiProfessionRecipe(new VillagerEmiStack(basicVillager),
EmiIngredient.of(workstations.stream().map(EmiStack::of).toList()), EmiIngredient.of(workstations.stream().map(EmiStack::of).toList()),
new VillagerEmiStack(manWithJob), poiRecipeId)); new VillagerEmiStack(manWithJob), poiRecipeId));
for (int lvl = 1; lvl < 5; lvl++) { for (int lvl = 1; lvl < 5; lvl++) {
ResourceLocation levelRecipeId = modLoc( ResourceLocation levelRecipeId = modLoc(
"villager/levelup/" + lvl + "/" + id.getNamespace() + "/" + id.getPath()); "villager/levelup/" + lvl + "/" + id.getNamespace() + "/" + id.getPath());
var manWithBadJob = new BrainsweepIngredient(id, null, lvl); var manWithBadJob = new BrainsweepIngredient(id, null, lvl);
var manWithBetterJob = new BrainsweepIngredient(id, null, lvl + 1); var manWithBetterJob = new BrainsweepIngredient(id, null, lvl + 1);
registry.addRecipe(new EmiLevelupRecipe(new VillagerEmiStack(manWithBadJob), registry.addRecipe(new EmiLevelupRecipe(new VillagerEmiStack(manWithBadJob),
new VillagerEmiStack(manWithBetterJob), levelRecipeId)); new VillagerEmiStack(manWithBetterJob), levelRecipeId));
} }
} }
} }

View file

@ -112,7 +112,7 @@ public class ForgeHexInitializer {
// https://github.com/VazkiiMods/Botania/blob/1.18.x/Forge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java // https://github.com/VazkiiMods/Botania/blob/1.18.x/Forge/src/main/java/vazkii/botania/forge/ForgeCommonInitializer.java
private static <T> void bind(ResourceKey<Registry<T>> registry, private static <T> void bind(ResourceKey<Registry<T>> registry,
Consumer<BiConsumer<T, ResourceLocation>> source) { Consumer<BiConsumer<T, ResourceLocation>> source) {
getModEventBus().addListener((RegisterEvent event) -> { getModEventBus().addListener((RegisterEvent event) -> {
if (registry.equals(event.getRegistryKey())) { if (registry.equals(event.getRegistryKey())) {
source.accept((t, rl) -> event.register(registry, rl, () -> t)); source.accept((t, rl) -> event.register(registry, rl, () -> t));
@ -159,7 +159,7 @@ public class ForgeHexInitializer {
HexAPI.LOGGER.info(PatternRegistry.getPatternCountInfo())); HexAPI.LOGGER.info(PatternRegistry.getPatternCountInfo()));
evBus.addListener((PlayerInteractEvent.EntityInteract evt) -> { evBus.addListener((PlayerInteractEvent.EntityInteract evt) -> {
var res = Brainsweeping.tradeWithVillager( var res = Brainsweeping.interactWithBrainswept(
evt.getEntity(), evt.getLevel(), evt.getHand(), evt.getTarget(), null); evt.getEntity(), evt.getLevel(), evt.getHand(), evt.getTarget(), null);
if (res.consumesAction()) { if (res.consumesAction()) {
evt.setCanceled(true); evt.setCanceled(true);
@ -167,7 +167,7 @@ public class ForgeHexInitializer {
} }
}); });
evBus.addListener((LivingConversionEvent.Post evt) -> evBus.addListener((LivingConversionEvent.Post evt) ->
Brainsweeping.copyBrainsweepFromVillager(evt.getEntity(), evt.getOutcome())); Brainsweeping.copyBrainsweepPostTransformation(evt.getEntity(), evt.getOutcome()));
evBus.addListener((LivingEvent.LivingTickEvent evt) -> { evBus.addListener((LivingEvent.LivingTickEvent evt) -> {
OpFlight.INSTANCE.tickDownFlight(evt.getEntity()); OpFlight.INSTANCE.tickDownFlight(evt.getEntity());

View file

@ -70,7 +70,7 @@ public class BrainsweepRecipeCategory implements IRecipeCategory<BrainsweepRecip
@NotNull IRecipeSlotsView recipeSlotsView, double mouseX, double mouseY) { @NotNull IRecipeSlotsView recipeSlotsView, double mouseX, double mouseY) {
if (37 <= mouseX && mouseX <= 37 + 26 && 19 <= mouseY && mouseY <= 19 + 48) { if (37 <= mouseX && mouseX <= 37 + 26 && 19 <= mouseY && mouseY <= 19 + 48) {
Minecraft mc = Minecraft.getInstance(); Minecraft mc = Minecraft.getInstance();
return recipe.villagerIn().getTooltip(mc.options.advancedItemTooltips); return recipe.entityIn().getTooltip(mc.options.advancedItemTooltips);
} }
return Collections.emptyList(); return Collections.emptyList();
@ -81,7 +81,7 @@ public class BrainsweepRecipeCategory implements IRecipeCategory<BrainsweepRecip
@NotNull PoseStack stack, double mouseX, double mouseY) { @NotNull PoseStack stack, double mouseX, double mouseY) {
ClientLevel level = Minecraft.getInstance().level; ClientLevel level = Minecraft.getInstance().level;
if (level != null) { if (level != null) {
Villager villager = RenderLib.prepareVillagerForRendering(recipe.villagerIn(), level); Villager villager = RenderLib.prepareVillagerForRendering(recipe.entityIn(), 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);