Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
b8cb13b
chore(l10n): update Norwegian Bokmål translation
hexxy-weblate Aug 29, 2026
f2fd1b1
chore(l10n): update Chinese (Simplified Han script) translation
hexxy-weblate Aug 29, 2026
7c7b1a0
chore(l10n): update translation files
hexxy-weblate Aug 29, 2026
b8552f7
chore(l10n): update translation files
hexxy-weblate Aug 29, 2026
8fed46b
chore(l10n): update French translation
hexxy-weblate Aug 29, 2026
1330ea8
chore(l10n): update translation files
hexxy-weblate Aug 29, 2026
9467a9b
chore(l10n): update translations (#1280)
object-Object Aug 29, 2026
edba45d
Only check for enlightenment when drawing outside parens (#1290)
Robotgiggle Sep 7, 2026
038ca4c
chore(l10n): update Norwegian Bokmål translation
hexxy-weblate Sep 9, 2026
50c0b54
chore(l10n): update Japanese translation
hexxy-weblate Sep 9, 2026
5b0b862
chore(l10n): update Chinese (Simplified Han script) translation
hexxy-weblate Sep 9, 2026
acf8ca8
chore(l10n): update Finnish translation
hexxy-weblate Sep 9, 2026
695ec95
chore(l10n): update French translation
hexxy-weblate Sep 9, 2026
ee5c320
chore(l10n): update English (Pirate) translation
hexxy-weblate Sep 9, 2026
f684e93
chore(l10n): update Swedish translation
hexxy-weblate Sep 9, 2026
bb32244
chore(l10n): update Spanish translation
hexxy-weblate Sep 9, 2026
b1a0739
chore(l10n): update Polish translation
hexxy-weblate Sep 9, 2026
81bb810
chore(l10n): update Russian translation
hexxy-weblate Sep 9, 2026
fbe014f
chore(l10n): update translations (#1286)
object-Object Sep 9, 2026
78b5190
chore(l10n): update Norwegian Bokmål translation
hexxy-weblate Sep 21, 2026
8ade6bc
chore(l10n): update Spanish translation
hexxy-weblate Sep 21, 2026
53659f6
chore(l10n): update Polish translation
hexxy-weblate Sep 21, 2026
ef98502
chore(l10n): update Russian translation
hexxy-weblate Sep 21, 2026
073bb14
chore(l10n): update translations (#1300)
object-Object Sep 21, 2026
ffa7c37
Make impulse cost calculation respect max magnitude (#1307)
beholderface Sep 22, 2026
4db93ab
fix: retain velocity after teleportation (#1310)
drtheodor Sep 23, 2026
e49b3ad
Add media costs to EMI flay mind recipes (#1323)
MEEPofFaith Oct 8, 2026
24f31a2
Tweak OpLightning implementation (#1304)
Robotgiggle Oct 11, 2026
37c1b66
Prevent variable-cost spells being made free with very small inputs (…
Robotgiggle Oct 12, 2026
6ebfa70
Allow anything with the right NBT to shift-scroll (#1329)
Robotgiggle Oct 13, 2026
c876428
Merge branch 'main' into main-to-next
s5bug Oct 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import java.util.function.DoubleUnaryOperator
import kotlin.math.abs
import kotlin.math.roundToInt
import kotlin.math.roundToLong
import kotlin.math.sign

fun List<Iota>.getDouble(idx: Int, argc: Int = 0): Double {
val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) }
Expand Down Expand Up @@ -305,6 +306,18 @@ fun List<Iota>.getEvaluatable(idx: Int, argc: Int = 0): Either<Iota, TreeList<Io

fun Iota?.orNull() = this ?: NullIota()

/**
* Converts to long while ensuring that the final result is always nonzero.
* Used when a spell's cost depends on an arbitrary multiplier provided by
* the player, so that an extremely small value doesn't make the spell free.
*/
fun Double.toNonZeroLong(): Long {
val result = this.roundToLong()
if (result == 0L)
return if (this >= 0) 1L else -1L
return result
}

// TODO do we make this work on lists
// there should probably be some way to abstract function application over lists, vecs, and numbers,
// and i bet it's fucking monads
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package at.petrak.hexcasting.api.casting.eval;

import at.petrak.hexcasting.api.casting.OperatorUtils;
import at.petrak.hexcasting.api.casting.ParticleSpray;
import at.petrak.hexcasting.api.casting.PatternShapeMatch;
import at.petrak.hexcasting.api.casting.eval.env.PlayerBasedCastEnv;
import at.petrak.hexcasting.api.casting.eval.vm.CastingImage;
import at.petrak.hexcasting.api.casting.mishaps.Mishap;
import at.petrak.hexcasting.api.casting.mishaps.MishapBadLocation;
Expand All @@ -12,7 +12,6 @@
import at.petrak.hexcasting.api.mod.HexTags;
import at.petrak.hexcasting.api.pigment.FrozenPigment;
import at.petrak.hexcasting.api.utils.HexUtils;
import at.petrak.hexcasting.common.lib.HexAttributes;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
Expand Down Expand Up @@ -243,7 +242,8 @@ public boolean isEnlightened() {
* positive.
*/
public long extractMedia(long cost, boolean simulate) {
cost = (long) (cost * costModifier);
if (cost == 0) return 0;
cost = OperatorUtils.toNonZeroLong(cost * costModifier);
for (var extractMediaComponent : preMediaExtract)
cost = extractMediaComponent.onExtractMedia(cost, simulate);
cost = extractMediaEnvironment(cost, simulate);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public boolean executable() {
}

var reqsEnlightenment = isOfTag(IXplatAbstractions.INSTANCE.getActionRegistry(), key,
HexTags.Actions.REQUIRES_ENLIGHTENMENT);
inParens ? HexTags.Actions.REQUIRES_ENLIGHTENMENT_IN_PARENS : HexTags.Actions.REQUIRES_ENLIGHTENMENT);

castedName = () -> HexAPI.instance().getActionI18n(key, reqsEnlightenment);
action = Objects.requireNonNull(IXplatAbstractions.INSTANCE.getActionRegistry().get(key)).action();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ public static final class Actions {
* "am I not skilled enough" message
*/
public static final TagKey<ActionRegistryEntry> REQUIRES_ENLIGHTENMENT = create("requires_enlightenment");
/**
* Same as REQUIRES_ENLIGHTENMENT but applies to actions that take effect while parenthesized.
* The base mod does not have any actions meeting both criteria but future addons might.
*/
public static final TagKey<ActionRegistryEntry> REQUIRES_ENLIGHTENMENT_IN_PARENS = create("requires_enlightenment_in_parens");
/**
* Actions where the pattern is calculated per-world
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package at.petrak.hexcasting.client;

import at.petrak.hexcasting.api.mod.HexConfig;
import at.petrak.hexcasting.common.items.storage.ItemSpellbook;
import at.petrak.hexcasting.common.lib.HexItems;
import at.petrak.hexcasting.common.msgs.MsgShiftScrollC2S;
import at.petrak.hexcasting.xplat.IClientXplatAbstractions;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;

public class ShiftScrollListener {
private static double mainHandDelta = 0;
Expand Down Expand Up @@ -36,11 +37,11 @@ public static boolean onScroll(double delta, boolean needsSneaking, boolean allo
return false;
}

if (IsScrollableItem(player.getMainHandItem().getItem())) {
mainHandDelta += delta * getScrollModifier(player.getMainHandItem().getItem(), allowInverting);
if (isScrollableStack(player.getMainHandItem())) {
mainHandDelta += delta * getScrollModifier(player.getMainHandItem(), allowInverting);
return true;
} else if (IsScrollableItem(player.getOffhandItem().getItem())) {
offHandDelta += delta * getScrollModifier(player.getOffhandItem().getItem(), allowInverting);
} else if (isScrollableStack(player.getOffhandItem())) {
offHandDelta += delta * getScrollModifier(player.getOffhandItem(), allowInverting);
return true;
}
}
Expand All @@ -58,17 +59,17 @@ public static void clientTickEnd() {
}
}

private static boolean IsScrollableItem(Item item) {
return item == HexItems.SPELLBOOK.get() || item == HexItems.ABACUS.get();
private static boolean isScrollableStack(ItemStack stack) {
return ItemSpellbook.supportsPageScrolling(stack) || stack.getItem() == HexItems.ABACUS;
}

private static double getScrollModifier(Item item, boolean allowInverting) {
private static double getScrollModifier(ItemStack stack, boolean allowInverting) {
if (!allowInverting) return 1;

if (item == HexItems.SPELLBOOK.get()) {
return HexConfig.client().invertSpellbookScrollDirection() ? -1 : 1;
} else if (item == HexItems.ABACUS.get()) {
if (stack.getItem() == HexItems.ABACUS) {
return HexConfig.client().invertAbacusScrollDirection() ? -1 : 1;
} else if (ItemSpellbook.supportsPageScrolling(stack)) {
return HexConfig.client().invertSpellbookScrollDirection() ? -1 : 1;
} else {
return 1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
import at.petrak.hexcasting.api.casting.getEntity
import at.petrak.hexcasting.api.casting.getVec3
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.casting.toNonZeroLong
import at.petrak.hexcasting.api.misc.MediaConstants
import net.minecraft.world.entity.Entity
import net.minecraft.world.phys.Vec3
Expand All @@ -31,7 +32,7 @@ object OpAddMotion : SpellAction {

return SpellAction.Result(
Spell(target, shrunkMotion),
(2 * motion.length() * MediaConstants.DUST_UNIT).roundToLong(),
(2 * motion.length() * MediaConstants.DUST_UNIT).toNonZeroLong(),
listOf(
ParticleSpray(
target.position().add(0.0, target.eyeHeight / 2.0, 0.0),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import at.petrak.hexcasting.api.casting.getEntity
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.casting.mishaps.MishapBadLocation
import at.petrak.hexcasting.api.casting.mishaps.MishapImmuneEntity
import at.petrak.hexcasting.api.casting.toNonZeroLong
import at.petrak.hexcasting.api.misc.MediaConstants
import at.petrak.hexcasting.api.mod.HexConfig
import at.petrak.hexcasting.api.mod.HexTags
import at.petrak.hexcasting.common.casting.actions.spells.great.OpTeleport
import net.minecraft.world.entity.Entity
import net.minecraft.world.phys.Vec3
import kotlin.math.absoluteValue
import kotlin.math.roundToLong

object OpBlink : SpellAction {
override val argc = 2
Expand Down Expand Up @@ -54,7 +54,7 @@ object OpBlink : SpellAction {

return SpellAction.Result(
Spell(target, dvec),
(MediaConstants.SHARD_UNIT * delta.absoluteValue * 0.5).roundToLong(),
(MediaConstants.SHARD_UNIT * delta.absoluteValue * 0.5).toNonZeroLong(),
listOf(
ParticleSpray.cloud(targetMiddlePos, 2.0, 50),
ParticleSpray.burst(targetMiddlePos.add(dvec), 2.0, 100)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
import at.petrak.hexcasting.api.casting.getPositiveDoubleUnderInclusive
import at.petrak.hexcasting.api.casting.getVec3
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.casting.toNonZeroLong
import at.petrak.hexcasting.api.misc.MediaConstants
import at.petrak.hexcasting.common.casting.actions.selectors.OpGetEntitiesBy
import net.minecraft.core.BlockPos
Expand Down Expand Up @@ -42,7 +43,7 @@ class OpExplode(val fire: Boolean) : SpellAction {
val cost = MediaConstants.DUST_UNIT * (3 * clampedStrength + if (fire) 1.0 else 0.125)
return SpellAction.Result(
Spell(pos, strength, this.fire),
cost.toLong(),
cost.toNonZeroLong(),
listOf(ParticleSpray.burst(pos, strength, 50))
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
import at.petrak.hexcasting.api.casting.getPlayer
import at.petrak.hexcasting.api.casting.getPositiveDouble
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.casting.toNonZeroLong
import at.petrak.hexcasting.api.misc.MediaConstants
import at.petrak.hexcasting.api.pigment.FrozenPigment
import at.petrak.hexcasting.api.player.FlightAbility
Expand All @@ -23,7 +24,6 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.phys.Vec3
import kotlin.math.max
import kotlin.math.roundToInt
import kotlin.math.roundToLong

class OpFlight(val type: Type) : SpellAction {
override val argc = 2
Expand All @@ -37,7 +37,7 @@ class OpFlight(val type: Type) : SpellAction {

// One block of radius, or one second of duration, costs 2 dust
val costUnit = 2 * MediaConstants.DUST_UNIT
var cost = (theArg * costUnit).roundToLong()
var cost = (theArg * costUnit).toNonZeroLong()
// Cost for anchorite does not decrease below 1 meter
if (type == Type.LimitRange) cost = max(cost, costUnit)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ class OpPotionEffect(
}
return SpellAction.Result(
Spell(effect, target, duration, potency),
cost.toLong(),
cost.toNonZeroLong(),
listOf(ParticleSpray.cloud(target.position().add(0.0, target.eyeHeight / 2.0, 0.0), 1.0))
)
}

private class Spell(val effect: Holder<MobEffect>, val target: LivingEntity, val duration: Double, val potency: Double) :
RenderedSpell {
override fun cast(env: CastingEnvironment) {
if (duration > 1.0 / 20.0) {
if (duration >= 1.0 / 20.0) {
val effectInst = MobEffectInstance(effect, (duration * 20).toInt(), potency.toInt() - 1)
target.addEffect(effectInst)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.casting.mishaps.MishapBadLocation
import at.petrak.hexcasting.api.misc.MediaConstants
import net.minecraft.core.BlockPos
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.EntityType
import net.minecraft.world.entity.LightningBolt
import net.minecraft.world.phys.Vec3
Expand Down Expand Up @@ -37,8 +38,9 @@ object OpLightning : SpellAction {
override fun cast(env: CastingEnvironment) {

val lightning = LightningBolt(EntityType.LIGHTNING_BOLT, env.world)
lightning.setPosRaw(target.x, target.y, target.z)
env.world.addWithUUID(lightning) // why the hell is it called this it doesnt even involve a uuid
lightning.setPos(target.x, target.y, target.z)
lightning.cause = env.castingEntity as? ServerPlayer
env.world.addFreshEntity(lightning)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import net.minecraft.core.component.DataComponents
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.RelativeMovement
import net.minecraft.world.item.enchantment.Enchantments
import net.minecraft.world.phys.Vec3

Expand Down Expand Up @@ -109,6 +110,10 @@ object OpTeleport : SpellAction {
teleportee.stopRiding()
if (!teleportee.type.`is`(HexTags.Entities.STICKY_TELEPORTERS))
teleportee.passengers.forEach(Entity::stopRiding)
teleportee.teleportTo(target.x, target.y, target.z)

// we specify that this is relative movement so that it doesn't reset player velocity. :mojank:
// note that the coordinates here are still absolute, because vanilla relative teleports are weird
teleportee.teleportTo(world, target.x, target.y, target.z,
RelativeMovement.ALL, teleportee.yRot, teleportee.xRot)
}
}

@Robotgiggle Robotgiggle Oct 16, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In 1.21, spellbooks don't have the page-names component by default anymore, only the page-index one, so as written this no longer allows scrolling on non-renamed spellbooks. You can probably just remove the supportsPageScrolling method entirely and replace its usages with a direct check for the page-index component.

Maybe also replace the supportsPageScrolling doc comment with a comment in HexDataComponents saying something similar, ie "applying this component will enable shift-scrolling, though it won't do much without the other components and a way to read/write the iota"

Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,17 @@ public void writeDatum(ItemStack stack, Iota datum) {
}
}

/**
* Returns whether this stack has the NBT tags necessary to make the shift-scrolling mechanic work.
* The scroll listener checks this when attempting to scroll, so by using these tags you can make
* any item support shift-scrolling without needing to mixin or implement a new scroll listener.
* However, you will still need to implement ways to actually *set* the relevant NBT tags yourself.
*/
public static boolean supportsPageScrolling(ItemStack stack) {
return stack.has(HexDataComponents.SELECTED_SPELLBOOK_PAGE.get())
&& stack.has(HexDataComponents.SPELLBOOK_PAGE_NAMES.get());
}

public static int getPage(ItemStack stack, int ifEmpty) {
if (arePagesEmpty(stack)) {
return ifEmpty;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package at.petrak.hexcasting.common.msgs;

import at.petrak.hexcasting.api.HexAPI;
import at.petrak.hexcasting.api.casting.iota.IotaType;
import at.petrak.hexcasting.api.utils.NBTHelper;
import at.petrak.hexcasting.common.items.storage.ItemAbacus;
import at.petrak.hexcasting.common.items.storage.ItemSpellbook;
import at.petrak.hexcasting.common.lib.HexDataComponents;
import at.petrak.hexcasting.common.lib.HexItems;
Expand Down Expand Up @@ -49,10 +52,10 @@ private void handleForHand(ServerPlayer sender, InteractionHand hand, double del
if (delta != 0) {
var stack = sender.getItemInHand(hand);

if (stack.getItem() == HexItems.SPELLBOOK.get()) {
spellbook(sender, hand, stack, delta);
} else if (stack.getItem() == HexItems.ABACUS.get()) {
if (stack.getItem() == HexItems.ABACUS) {
abacus(sender, hand, stack, delta);
} else if (ItemSpellbook.supportsPageScrolling(stack)) {
spellbook(sender, hand, stack, delta);
}
}
}
Expand Down Expand Up @@ -98,6 +101,12 @@ private void spellbook(ServerPlayer sender, InteractionHand hand, ItemStack stac
}

private void abacus(ServerPlayer sender, InteractionHand hand, ItemStack stack, double delta) {
if (ItemSpellbook.supportsPageScrolling(stack)) {
HexAPI.LOGGER.warn("Item stack has spellbook tags but is an abacus! The spellbook tags will be removed.");

@Robotgiggle Robotgiggle Oct 16, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be updated to refer to components rather than tags (and should maybe only remove SELECTED_SPELLBOOK_PAGE since that should be the only one checked for now)

stack.remove(HexDataComponents.SELECTED_SPELLBOOK_PAGE.get());
stack.remove(HexDataComponents.SPELLBOOK_PAGE_NAMES.get());
}

var increase = delta < 0;
Double num = stack.get(HexDataComponents.ABACUS_VALUE.get());
if(num == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

public record EmiBrainsweepRecipe(EmiIngredient blockInput,
EmiIngredient villagerInput,
EmiIngredient mediaCost,
EmiStack output,
ResourceLocation id) implements EmiRecipe {
private static final ResourceLocation OVERLAY = modLoc("textures/gui/brainsweep_recipe.png");
Expand Down Expand Up @@ -52,8 +53,9 @@ public int getDisplayHeight() {
public void addWidgets(WidgetHolder widgets) {
widgets.addTexture(OVERLAY, 0, 0, getDisplayWidth(), getDisplayHeight(), 0, 0, getDisplayWidth(), getDisplayHeight(), 128, 128);
widgets.addSlot(blockInput, 11, 34).drawBack(false).customBackground(null, 0, 0, 19, 19);
widgets.addSlot(mediaCost, 11, 54).drawBack(false).customBackground(null, 0, 0, 19, 19);

widgets.add(new TheCoolerSlotWidget(villagerInput, 37, 19, 2.75f).useOffset(false).customShift(-8.5f, 2.485f))
widgets.add(new EntitySlotWidget(villagerInput, 37, 19, 2.75f).useOffset(false).customShift(-8.5f, 2.485f))
.drawBack(false).customBackground(null, 0, 0, 27, 49);

widgets.addSlot(output, 86, 34).drawBack(false).large(true).recipeContext(this).customBackground(null, 0, 0, 19, 19);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.GameRenderer;

public class TheCoolerSlotWidget extends SlotWidget {
public class EntitySlotWidget extends SlotWidget {

private final float renderScale;

public TheCoolerSlotWidget(EmiIngredient stack, int x, int y, float renderScale) {
public EntitySlotWidget(EmiIngredient stack, int x, int y, float renderScale) {
super(stack, x, y);
this.renderScale = renderScale;
}
Expand All @@ -22,12 +22,12 @@ public TheCoolerSlotWidget(EmiIngredient stack, int x, int y, float renderScale)
private float xShift = 0;
private float yShift = 0;

public TheCoolerSlotWidget useOffset(boolean offset) {
public EntitySlotWidget useOffset(boolean offset) {
useOffset = offset;
return this;
}

public TheCoolerSlotWidget customShift(float xShift, float yShift) {
public EntitySlotWidget customShift(float xShift, float yShift) {
this.xShift = xShift;
this.yShift = yShift;
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,12 @@ public void register(EmiRegistry registry) {
var inputBlocks = EmiIngredient.of(recipe.value().blockIn().getDisplayedStacks().stream()
.map(EmiStack::of).toList());
var inputEntity = new BrainsweepeeEmiStack(recipe.value().entityIn());
var mediaCost = new MediaEmiStack(recipe.value().mediaCost());
var output = EmiStack.of(recipe.value().result().getBlock());
var outputId = output.getId().getNamespace().equals("minecraft") ? output.getId().getPath() : output.getId().toString();
var inputEntityId = inputEntity.getName().getString().toLowerCase().replaceAll(" ", "_");
var recipeId = modLoc("/brainsweep/" + (outputId.replaceAll(":", "/")) + "_from_" + inputEntityId);
registry.addRecipe(new EmiBrainsweepRecipe(inputBlocks, inputEntity, output, recipeId));
registry.addRecipe(new EmiBrainsweepRecipe(inputBlocks, inputEntity, mediaCost, output, recipeId));
}

if (PhialRecipeStackBuilder.shouldAddRecipe()) {
Expand Down
Loading
Loading