diff --git a/Common/src/main/java/at/petrak/hexcasting/annotations/SoftImplement.java b/Common/src/main/java/at/petrak/hexcasting/annotations/SoftImplement.java index c90949187f..de6da6fb94 100644 --- a/Common/src/main/java/at/petrak/hexcasting/annotations/SoftImplement.java +++ b/Common/src/main/java/at/petrak/hexcasting/annotations/SoftImplement.java @@ -9,22 +9,18 @@ // yoinky sploinky /** - * A purely-documentative annotation. - * This annotation is used by developers in xplat code. The annotated method is intended - * to "soft implement" a certain method in a loader specific interface that cannot be - * named in xplat code and thus cannot be checked with @Override. - * In this context, "soft implement" means to implement the method by matching the signature - * with the intended interface method. - * Examples of interfaces that we would use this for is IForgeItem or FabricItem. - *
- * The intent is that we audit such sites every major Minecraft version or so, to ensure - * that they still properly override the intended target. + * A purely-documentative annotation. This annotation is used by developers in xplat code. The + * annotated method is intended to "soft implement" a certain method in a loader specific interface + * that cannot be named in xplat code and thus cannot be checked with @Override. In this context, + * "soft implement" means to implement the method by matching the signature with the intended + * interface method. Examples of interfaces that we would use this for is IForgeItem or FabricItem. + * + *
The intent is that we audit such sites every major Minecraft version or so, to ensure that
+ * they still properly override the intended target.
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.METHOD)
public @interface SoftImplement {
- /**
- * What interface we're soft implementing
- */
- String value();
+ /** What interface we're soft implementing */
+ String value();
}
diff --git a/Common/src/main/java/at/petrak/hexcasting/api/HexAPI.java b/Common/src/main/java/at/petrak/hexcasting/api/HexAPI.java
index 8ddde5669b..eaf3fb5c8b 100644
--- a/Common/src/main/java/at/petrak/hexcasting/api/HexAPI.java
+++ b/Common/src/main/java/at/petrak/hexcasting/api/HexAPI.java
@@ -7,6 +7,8 @@
import at.petrak.hexcasting.api.player.Sentinel;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
import com.google.common.base.Suppliers;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
@@ -16,7 +18,6 @@
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
-import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ArmorItem;
@@ -29,206 +30,201 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.function.Consumer;
-import java.util.function.Supplier;
-
public interface HexAPI {
- String MOD_ID = "hexcasting";
- Logger LOGGER = LogManager.getLogger(MOD_ID);
-
- Supplier
- * Note we're allowed to have action resource keys on the client, just no actual actions.
- *
- * Special handlers should be calling {@link SpecialHandler#getName()}
- */
- default String getActionI18nKey(ResourceKey
- * This knocks out the normal behavior; if you want that behavior you should call
- */
- default
- * Something registered with {@link HexAPI#registerCustomBrainsweepingBehavior} doesn't call this automatically;
- * you can use this to add things on top of the default behavior
- */
- default Consumer
- * This ignores the unbrainsweepable tag.
- */
- default void brainsweep(Mob mob) {
- var type = (EntityType extends Mob>) mob.getType();
- var behavior = this.getBrainsweepBehavior(type);
- var erasedBehavior = (Consumer Note we're allowed to have action resource keys on the client, just no actual
+ * actions.
+ *
+ * Special handlers should be calling {@link SpecialHandler#getName()}
+ */
+ default String getActionI18nKey(ResourceKey This knocks out the normal behavior; if you want that behavior you should call
+ */
+ default Something registered with {@link HexAPI#registerCustomBrainsweepingBehavior} doesn't call
+ * this automatically; you can use this to add things on top of the default behavior
+ */
+ default Consumer This ignores the unbrainsweepable tag.
+ */
+ default void brainsweep(Mob mob) {
+ var type = (EntityType extends Mob>) mob.getType();
+ var behavior = this.getBrainsweepBehavior(type);
+ var erasedBehavior = (Consumer
- * By default,
- * * Charged Amethyst has priority 1000
- * * Amethyst Shards have priority 2000
- * * Amethyst Dust has priority 3000
- * * Items which hold media have priority 4000
- */
- int getConsumptionPriority();
+ /**
+ * The priority for this media holder to be selected when casting a hex. Higher priorities are
+ * taken first.
+ *
+ * By default, * Charged Amethyst has priority 1000 * Amethyst Shards have priority 2000 *
+ * Amethyst Dust has priority 3000 * Items which hold media have priority 4000
+ */
+ int getConsumptionPriority();
- /**
- * Whether the media inside this media holder may be used to construct a battery.
- */
- boolean canConstructBattery();
+ /** Whether the media inside this media holder may be used to construct a battery. */
+ boolean canConstructBattery();
- /**
- * Withdraws media from the holder. Returns the amount of media extracted, which may be less or more than the cost.
- *
- * Even if {@link ADMediaHolder#canProvide} is false, you can still withdraw media this way.
- *
- * Withdrawing a negative amount will act as though you attempted to withdraw as much media as the holder contains.
- */
- default long withdrawMedia(long cost, boolean simulate) {
- var mediaHere = getMedia();
- if (cost < 0) {
- cost = mediaHere;
- }
- if (!simulate) {
- var mediaLeft = mediaHere - cost;
- setMedia(mediaLeft);
- }
- return Math.min(cost, mediaHere);
- }
+ /**
+ * Withdraws media from the holder. Returns the amount of media extracted, which may be less or
+ * more than the cost.
+ *
+ * Even if {@link ADMediaHolder#canProvide} is false, you can still withdraw media this way.
+ *
+ * Withdrawing a negative amount will act as though you attempted to withdraw as much media as
+ * the holder contains.
+ */
+ default long withdrawMedia(long cost, boolean simulate) {
+ var mediaHere = getMedia();
+ if (cost < 0) {
+ cost = mediaHere;
+ }
+ if (!simulate) {
+ var mediaLeft = mediaHere - cost;
+ setMedia(mediaLeft);
+ }
+ return Math.min(cost, mediaHere);
+ }
- /**
- * Inserts media into the holder. Returns the amount of media inserted, which may be less than the requested amount.
- *
- * Even if {@link ADMediaHolder#canRecharge} is false, you can still insert media this way.
- *
- * Inserting a negative amount will act as though you attempted to insert exactly as much media as the holder was
- * missing.
- */
- default long insertMedia(long amount, boolean simulate) {
- var mediaHere = getMedia();
- long emptySpace = getMaxMedia() - mediaHere;
- if (emptySpace <= 0) {
- return 0;
- }
- if (amount < 0) {
- amount = emptySpace;
- }
+ /**
+ * Inserts media into the holder. Returns the amount of media inserted, which may be less than the
+ * requested amount.
+ *
+ * Even if {@link ADMediaHolder#canRecharge} is false, you can still insert media this way.
+ *
+ * Inserting a negative amount will act as though you attempted to insert exactly as much media
+ * as the holder was missing.
+ */
+ default long insertMedia(long amount, boolean simulate) {
+ var mediaHere = getMedia();
+ long emptySpace = getMaxMedia() - mediaHere;
+ if (emptySpace <= 0) {
+ return 0;
+ }
+ if (amount < 0) {
+ amount = emptySpace;
+ }
- long inserting = Math.min(amount, emptySpace);
+ long inserting = Math.min(amount, emptySpace);
- if (!simulate) {
- var newMedia = mediaHere + inserting;
- setMedia(newMedia);
- }
- return inserting;
- }
+ if (!simulate) {
+ var newMedia = mediaHere + inserting;
+ setMedia(newMedia);
+ }
+ return inserting;
+ }
- int QUENCHED_ALLAY_PRIORITY = 800;
- int QUENCHED_SHARD_PRIORITY = 900;
- int CHARGED_AMETHYST_PRIORITY = 1000;
- int AMETHYST_SHARD_PRIORITY = 2000;
- int AMETHYST_DUST_PRIORITY = 3000;
- int BATTERY_PRIORITY = 4000;
+ int QUENCHED_ALLAY_PRIORITY = 800;
+ int QUENCHED_SHARD_PRIORITY = 900;
+ int CHARGED_AMETHYST_PRIORITY = 1000;
+ int AMETHYST_SHARD_PRIORITY = 2000;
+ int AMETHYST_DUST_PRIORITY = 3000;
+ int BATTERY_PRIORITY = 4000;
}
diff --git a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADPigment.java b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADPigment.java
index 86984439c9..e5ed045b68 100644
--- a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADPigment.java
+++ b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADPigment.java
@@ -1,38 +1,37 @@
package at.petrak.hexcasting.api.addldata;
import at.petrak.hexcasting.api.pigment.ColorProvider;
+import java.util.UUID;
import net.minecraft.util.FastColor;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec3;
-import java.util.UUID;
-
public interface ADPigment {
- ColorProvider provideColor(UUID owner);
-
- static int morphBetweenColors(int[] colors, Vec3 gradientDir, float time, Vec3 position) {
- float fIdx = Mth.positiveModulo(time + (float) gradientDir.dot(position), 1f) * colors.length;
-
- int baseIdx = Mth.floor(fIdx);
- float tRaw = fIdx - baseIdx;
- float t = tRaw < 0.5 ? 4 * tRaw * tRaw * tRaw : (float) (1 - Math.pow(-2 * tRaw + 2, 3) / 2);
- int start = colors[baseIdx % colors.length];
- int end = colors[(baseIdx + 1) % colors.length];
-
- var r1 = FastColor.ARGB32.red(start);
- var g1 = FastColor.ARGB32.green(start);
- var b1 = FastColor.ARGB32.blue(start);
- var a1 = FastColor.ARGB32.alpha(start);
- var r2 = FastColor.ARGB32.red(end);
- var g2 = FastColor.ARGB32.green(end);
- var b2 = FastColor.ARGB32.blue(end);
- var a2 = FastColor.ARGB32.alpha(end);
-
- var r = Mth.lerp(t, r1, r2);
- var g = Mth.lerp(t, g1, g2);
- var b = Mth.lerp(t, b1, b2);
- var a = Mth.lerp(t, a1, a2);
-
- return FastColor.ARGB32.color((int) a, (int) r, (int) g, (int) b);
- }
+ ColorProvider provideColor(UUID owner);
+
+ static int morphBetweenColors(int[] colors, Vec3 gradientDir, float time, Vec3 position) {
+ float fIdx = Mth.positiveModulo(time + (float) gradientDir.dot(position), 1f) * colors.length;
+
+ int baseIdx = Mth.floor(fIdx);
+ float tRaw = fIdx - baseIdx;
+ float t = tRaw < 0.5 ? 4 * tRaw * tRaw * tRaw : (float) (1 - Math.pow(-2 * tRaw + 2, 3) / 2);
+ int start = colors[baseIdx % colors.length];
+ int end = colors[(baseIdx + 1) % colors.length];
+
+ var r1 = FastColor.ARGB32.red(start);
+ var g1 = FastColor.ARGB32.green(start);
+ var b1 = FastColor.ARGB32.blue(start);
+ var a1 = FastColor.ARGB32.alpha(start);
+ var r2 = FastColor.ARGB32.red(end);
+ var g2 = FastColor.ARGB32.green(end);
+ var b2 = FastColor.ARGB32.blue(end);
+ var a2 = FastColor.ARGB32.alpha(end);
+
+ var r = Mth.lerp(t, r1, r2);
+ var g = Mth.lerp(t, g1, g2);
+ var b = Mth.lerp(t, b1, b2);
+ var a = Mth.lerp(t, a1, a2);
+
+ return FastColor.ARGB32.color((int) a, (int) r, (int) g, (int) b);
+ }
}
diff --git a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADVariantItem.java b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADVariantItem.java
index 6b1a59f76d..925caddc01 100644
--- a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADVariantItem.java
+++ b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ADVariantItem.java
@@ -1,9 +1,9 @@
package at.petrak.hexcasting.api.addldata;
public interface ADVariantItem {
- int numVariants();
- int getVariant();
+ int numVariants();
+ int getVariant();
- void setVariant(int variant);
+ void setVariant(int variant);
}
diff --git a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ItemDelegatingEntityIotaHolder.java b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ItemDelegatingEntityIotaHolder.java
index 5af67a99ab..cbf4578f95 100644
--- a/Common/src/main/java/at/petrak/hexcasting/api/addldata/ItemDelegatingEntityIotaHolder.java
+++ b/Common/src/main/java/at/petrak/hexcasting/api/addldata/ItemDelegatingEntityIotaHolder.java
@@ -3,6 +3,8 @@
import at.petrak.hexcasting.api.casting.iota.Iota;
import at.petrak.hexcasting.common.entities.EntityWallScroll;
import at.petrak.hexcasting.xplat.IXplatAbstractions;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.decoration.ItemFrame;
@@ -10,80 +12,79 @@
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.Nullable;
-import java.util.function.Consumer;
-import java.util.function.Supplier;
-
public abstract class ItemDelegatingEntityIotaHolder implements ADIotaHolder {
- private final Supplier
- * An {@code ADFooBar} in this package will be implemented by a {@code CCFooBar} on Fabric.
- * On Forge, there are a set of private records that implement them.
- *
- * The point is, this provides an interface for interacting with however whatever platform sticks extra info on stuff.
+ *
+ * An {@code ADFooBar} in this package will be implemented by a {@code CCFooBar} on Fabric. On
+ * Forge, there are a set of private records that implement them.
+ *
+ * The point is, this provides an interface for interacting with however whatever platform sticks
+ * extra info on stuff.
*/
package at.petrak.hexcasting.api.addldata;
diff --git a/Common/src/main/java/at/petrak/hexcasting/api/advancements/FailToCastGreatSpellTrigger.java b/Common/src/main/java/at/petrak/hexcasting/api/advancements/FailToCastGreatSpellTrigger.java
index fe85fec5b3..05e169f172 100644
--- a/Common/src/main/java/at/petrak/hexcasting/api/advancements/FailToCastGreatSpellTrigger.java
+++ b/Common/src/main/java/at/petrak/hexcasting/api/advancements/FailToCastGreatSpellTrigger.java
@@ -5,35 +5,38 @@
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
-public class FailToCastGreatSpellTrigger extends SimpleCriterionTrigger
- * On the server, {@link PerWorld#certain} means whether this is an exact match, or if it's just the
- * right shape. (In other words it should only actually be casted if it is true.)
- *
- * On the client, it is always false.
- */
- public static final class PerWorld extends PatternShapeMatch {
- public final ResourceKey On the server, {@link PerWorld#certain} means whether this is an exact match, or if it's
+ * just the right shape. (In other words it should only actually be casted if it is true.)
+ *
+ * On the client, it is always false.
+ */
+ public static final class PerWorld extends PatternShapeMatch {
+ public final ResourceKey
- * In the base mod, this is used for number patterns and Bookkeeper's Gambit.
- *
- * There's a separation between the special handlers and their factories so we never have to use
- * {@link Action} instances on the client. We can have SpecialHandlers on the client though because they're just
- * wrappers.
+ * a given pattern is run by all of these special handlers patterns. If none of them return
+ * non-null, then its signature is checked.
+ *
+ * In the base mod, this is used for number patterns and Bookkeeper's Gambit.
+ *
+ * There's a separation between the special handlers and their factories so we never have to use
+ * {@link Action} instances on the client. We can have SpecialHandlers on the client though because
+ * they're just wrappers.
*/
public interface SpecialHandler {
- /**
- * Convert this to an action, for modification of the stack and state.
- *
- * This is called on the SERVER-SIDE ONLY.
- */
- Action act();
+ /**
+ * Convert this to an action, for modification of the stack and state.
+ *
+ * This is called on the SERVER-SIDE ONLY.
+ */
+ Action act();
- /**
- * Get the name of this handler.
- */
- Component getName();
+ /** Get the name of this handler. */
+ Component getName();
- /**
- * Given a pattern, possibly make up the special handler from it.
- *
- * This is what goes in the registry! Think of it like BlockEntityType vs BlockEntity.
- */
- @FunctionalInterface
- public interface Factory This is what goes in the registry! Think of it like BlockEntityType vs BlockEntity.
+ */
+ @FunctionalInterface
+ public interface Factory
- * This does assume a great deal so you might have to re-implement a lot of this yourself if you
+ *
+ * This does assume a great deal so you might have to re-implement a lot of this yourself if you
* wanna do something wild and new
*/
-public abstract class BlockEntityAbstractImpetus extends HexBlockEntity implements WorldlyContainer {
- private static final DecimalFormat DUST_AMOUNT = new DecimalFormat("###,###.##");
- private static final long MAX_CAPACITY = 9_000_000_000_000_000_000L;
-
- public static final String
- TAG_EXECUTION_STATE = "executor",
- TAG_MEDIA = "media",
- TAG_ERROR_MSG = "errorMsg",
- TAG_ERROR_DISPLAY = "errorDisplay",
- TAG_PIGMENT = "pigment";
-
- // We might try to load the executor in loadModData when the level doesn't exist yet,
- // so save the tag and load it lazy
- @Nullable CompoundTag lazyExecutionState;
- @Nullable
- protected CircleExecutionState executionState;
-
- protected long media = 0;
-
- // these are null together
- @Nullable
- protected Component displayMsg = null;
- @Nullable
- protected ItemStack displayItem = null;
- @Nullable
- protected FrozenPigment pigment = null;
-
-
- public BlockEntityAbstractImpetus(BlockEntityType> pType, BlockPos pWorldPosition, BlockState pBlockState) {
- super(pType, pWorldPosition, pBlockState);
- }
-
- public Direction getStartDirection() {
- return this.getBlockState().getValue(BlockStateProperties.FACING);
- }
-
- @Nullable
- public Component getDisplayMsg() {
- return displayMsg;
- }
-
- public void clearDisplay() {
- this.displayMsg = null;
- this.displayItem = null;
- this.sync();
- }
-
- public void postDisplay(Component error, ItemStack display) {
- this.displayMsg = error;
- this.displayItem = display;
- this.sync();
- }
-
- public void postMishap(Component mishapDisplay) {
- this.postDisplay(mishapDisplay, new ItemStack(Items.MUSIC_DISC_11));
- }
-
- public void postPrint(Component printDisplay) {
- this.postDisplay(printDisplay, new ItemStack(Items.BOOK));
- }
-
- // Pull this out because we may need to call it both on startup and halfway thru
- public void postNoExits(BlockPos pos) {
- this.postDisplay(
- Component.translatable("hexcasting.tooltip.circle.no_exit",
- Component.literal(pos.toShortString()).withStyle(ChatFormatting.RED)),
- new ItemStack(Items.OAK_SIGN));
- }
-
- //region execution
-
- public void tickExecution() {
- if (this.level == null)
- return;
-
- this.setChanged();
-
- var state = this.getExecutionState();
- if (state == null) {
- return;
- }
-
- var shouldContinue = state.tick(this);
-
- if (!shouldContinue) {
- this.endExecution();
- this.executionState = null;
- } else
- this.level.scheduleTick(this.getBlockPos(), this.getBlockState().getBlock(), state.getTickSpeed());
- }
-
- public void endExecution() {
- if (this.executionState == null)
- return;
-
- this.executionState.endExecution(this);
- }
-
- /**
- * ONLY CALL THIS WHEN YOU KNOW THE WORLD EXISTS AND ON THE SERVER, lazy-loads it
- */
- public @Nullable CircleExecutionState getExecutionState() {
- if (this.level == null) {
- throw new IllegalStateException("didn't you read the doc comment, don't call this if the level is null");
- }
-
- if (this.executionState != null)
- return this.executionState;
-
- if (this.lazyExecutionState != null)
- this.executionState = CircleExecutionState.load(this.lazyExecutionState, (ServerLevel) this.level);
-
- return this.executionState;
- }
-
- public void startExecution(@Nullable ServerPlayer player) {
- if (this.level == null)
- return; // TODO: error here?
- if (this.level.isClientSide)
- return; // TODO: error here?
-
- if (this.executionState != null) {
- return;
- }
- var result = CircleExecutionState.createNew(this, player);
- if (result.isErr()) {
- var errPos = result.unwrapErr();
- if (errPos == null) {
- ICircleComponent.sfx(this.getBlockPos(), this.getBlockState(), this.level, null, false);
- this.postNoExits(this.getBlockPos());
- } else {
- ICircleComponent.sfx(errPos, this.level.getBlockState(errPos), this.level, null, false);
- this.postDisplay(Component.translatable("hexcasting.tooltip.circle.no_closure",
- Component.literal(errPos.toShortString()).withStyle(ChatFormatting.RED)),
- new ItemStack(Items.LEAD));
- }
-
- return;
- }
- this.executionState = result.unwrap();
-
- this.clearDisplay();
- var serverLevel = (ServerLevel) this.level;
- serverLevel.scheduleTick(this.getBlockPos(), this.getBlockState().getBlock(),
- this.executionState.getTickSpeed());
- serverLevel.setBlockAndUpdate(this.getBlockPos(),
- this.getBlockState().setValue(BlockCircleComponent.ENERGIZED, true));
- }
-
- @Contract(pure = true)
- protected static AABB getBounds(List
- * Returns whether to continue.
- */
- public boolean tick(BlockEntityAbstractImpetus impetus) {
- var world = (ServerLevel) impetus.getLevel();
-
- if (world == null)
- return true; // if the world is null, try again next tick.
-
- var env = new CircleCastEnv(world, this);
-
- var executorBlockState = world.getBlockState(this.currentPos);
- if (!(executorBlockState.getBlock() instanceof ICircleComponent executor)) {
- // TODO: notification of the error?
- ICircleComponent.sfx(this.currentPos, executorBlockState, world,
- Objects.requireNonNull(env.getImpetus()), false);
- return false;
- }
-
- executorBlockState = executor.startEnergized(this.currentPos, executorBlockState, world);
- this.reachedPositions.add(this.currentPos);
-
- // Do the execution!
- boolean halt = false;
- var ctrl = executor.acceptControlFlow(this.currentImage, env, this.enteredFrom, this.currentPos,
- executorBlockState, world);
-
- if (env.getImpetus() == null)
- return false; //the impetus got removed during the cast and no longer exists in the world. stop casting
-
- if (ctrl instanceof ICircleComponent.ControlFlow.Stop) {
- // acceptControlFlow should have already posted the error
- halt = true;
- } else if (ctrl instanceof ICircleComponent.ControlFlow.Continue cont) {
- Pair