commit - 8807bf3c95b0c4b284897192e9d22bbebad9cbcd
commit + 546a78f77fa588fbd1f48d14c4b0ee16273abe26
blob - 8f5ecc2c4322359fbb7f1749fbc698b91d3e7bba
blob + 4c4a00eabdddf1d4b78d64f886807a1fd8c43b3b
--- src/main/java/com/github/alexthe666/citadel/server/entity/pathfinding/raycoms/AbstractAdvancedPathNavigate.java
+++ src/main/java/com/github/alexthe666/citadel/server/entity/pathfinding/raycoms/AbstractAdvancedPathNavigate.java
import net.minecraft.world.entity.Mob;
-/**
- * COMPILE-TIME STUB of
- * {@code com.github.alexthe666.citadel.server.entity.pathfinding.raycoms.AbstractAdvancedPathNavigate}.
- *
- * <p>The real class at runtime is provided by Citadel and declares
- * {@code protected final Mob ourEntity} and {@code public Mob getOurEntity()}.
- * We only need {@code getOurEntity()} for the Citadel mixin to compile;
- * the field itself is not referenced from our code.
- *
- * <p>Excluded from the output jar via {@code jar { exclude 'com/github/**' }}
- * in build.gradle so it can never shadow the real class at runtime.
- */
public abstract class AbstractAdvancedPathNavigate {
public Mob getOurEntity() {
blob - 42dcdfb8fc946f8a4bea02b6ba9115b95a22103c
blob + 6203a0f9ed2fe09ca5f5cedf1a4dc3a4c343406f
--- src/main/java/com/github/alexthe666/citadel/server/entity/pathfinding/raycoms/AdvancedPathNavigate.java
+++ src/main/java/com/github/alexthe666/citadel/server/entity/pathfinding/raycoms/AdvancedPathNavigate.java
package com.github.alexthe666.citadel.server.entity.pathfinding.raycoms;
-/**
- * COMPILE-TIME STUB of
- * {@code com.github.alexthe666.citadel.server.entity.pathfinding.raycoms.AdvancedPathNavigate}.
- *
- * <p>The real class at runtime extends {@code AbstractAdvancedPathNavigate}
- * (which holds the {@code ourEntity} field and the {@code getOurEntity()}
- * accessor we use). The mixin doesn't need to reference any fields directly
- * — it casts {@code this} to the parent at runtime — so this stub only needs
- * the inheritance link to be present so {@code (AbstractAdvancedPathNavigate)
- * (Object) this} compiles cleanly.
- *
- * <p>Excluded from the output jar via {@code jar { exclude 'com/github/**' }}
- * in build.gradle so it can never shadow the real class at runtime.
- */
public abstract class AdvancedPathNavigate extends AbstractAdvancedPathNavigate {
protected PathResult moveToXYZ(final double x, final double y, final double z, final double speedFactor) {
blob - 42992ad16c531461a662b90b737a84de2085c9b8
blob + 46b08b679f27076c025ef10486f80d9db726e0d5
--- src/main/java/com/github/alexthe666/citadel/server/entity/pathfinding/raycoms/PathResult.java
+++ src/main/java/com/github/alexthe666/citadel/server/entity/pathfinding/raycoms/PathResult.java
package com.github.alexthe666.citadel.server.entity.pathfinding.raycoms;
-/**
- * COMPILE-TIME STUB of
- * {@code com.github.alexthe666.citadel.server.entity.pathfinding.raycoms.PathResult}.
- *
- * <p>The real class at runtime is provided by Citadel. This stub only needs
- * to exist to satisfy the compiler for AeronauticsCompat's mixin; no fields
- * or methods from it are used by the mixin itself. Excluded from the output
- * jar via the {@code jar { exclude 'com/github/**' }} rule in build.gradle.
- */
public class PathResult<J> {
}
blob - b4b7effa2d6806ca8669964bd3b23a907c211ab0
blob + f6988de35ef0cc6e4a49bc78d80b232c6ca9bd36
--- src/main/java/dev/ryanhcode/sable/sound/MovingSoundInstanceDelegate.java
+++ src/main/java/dev/ryanhcode/sable/sound/MovingSoundInstanceDelegate.java
package dev.ryanhcode.sable.sound;
-/**
- * COMPILE-TIME STUB of Sable's
- * {@code dev.ryanhcode.sable.sound.MovingSoundInstanceDelegate}.
- *
- * <p>This stub exists only so Etchtube's mixin can refer to the type name.
- * The mixin stores a reference via {@link SoundInstanceDelegated#setDelegate}
- * and reads it back via {@link SoundInstanceDelegated#getDelegate}; it never
- * touches any methods on this class, so a no-body stub is sufficient.
- *
- * <p>At runtime, Sable itself provides the real class. This stub is built
- * into a separate source set whose output is excluded from the Etchtube jar
- * (see {@code build.gradle}).
- */
public class MovingSoundInstanceDelegate {
}
blob - 752e29c85150b03e64d304506518bf364af5fa2e
blob + 9ceaa254805a4f52f5dfcbe83c122bb4fdccc6a8
--- src/main/java/dev/ryanhcode/sable/sound/SoundInstanceDelegated.java
+++ src/main/java/dev/ryanhcode/sable/sound/SoundInstanceDelegated.java
package dev.ryanhcode.sable.sound;
-/**
- * COMPILE-TIME STUB of Sable's {@code dev.ryanhcode.sable.sound.SoundInstanceDelegated}.
- *
- * <p>This file exists purely so Etchtube's mixin can reference this interface at
- * compile time. It is built into a separate {@code sableStubs} source set whose
- * output is explicitly excluded from the Etchtube jar (see {@code build.gradle}).
- * At runtime, Sable itself provides the real interface; if Sable isn't loaded,
- * the mixin that depends on it is disabled by {@code EtchtubeMixinPlugin}.
- *
- * <p>Keep this shape in sync with upstream Sable. If the upstream interface
- * changes its method signatures, this stub must be updated to match.
- */
public interface SoundInstanceDelegated {
MovingSoundInstanceDelegate getDelegate();
blob - 8241691230773707dfbb36c24bcba50a5ec3f511
blob + f200478d61a0fe9d773a0a293719886b40acb70c
--- src/main/java/me/srrapero720/waterframes/WaterFrames.java
+++ src/main/java/me/srrapero720/waterframes/WaterFrames.java
import net.minecraft.core.Position;
import net.minecraft.world.level.Level;
-/**
- * COMPILE-TIME STUB of
- * {@code me.srrapero720.waterframes.WaterFrames}.
- *
- * <p>Only the method signature that AeronauticsCompat's mixin targets is
- * declared. The real WaterFrames class at runtime provides the full
- * implementation. This stub is built into a separate source set whose
- * output is excluded from the AeronauticsCompat jar (see {@code build.gradle}).
- *
- * <p>Keep the {@code getDistance} signature in sync with upstream. The
- * mixin targets the three-argument {@code (Level, BlockPos, Position)}
- * overload by its full JVM descriptor.
- */
public class WaterFrames {
public static double getDistance(Level level, BlockPos pos, Position position) {
blob - 6f30b702572ce3c60dedc454f83b4ce528abb29c
blob + 8c7b4ce76fcf9af35197a9d934de2a3a0f09338a
--- src/main/java/sh/rsap/aeronauticscompat/AeronauticsCompat.java
+++ src/main/java/sh/rsap/aeronauticscompat/AeronauticsCompat.java
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import org.slf4j.Logger;
-/**
- * AeronauticsCompat entry point.
- *
- * <p>All of this mod's actual behavior lives in its mixins — see
- * {@code aeronauticscompat.mixins.json} and
- * {@link sh.rsap.aeronauticscompat.mixin.AeronauticsCompatMixinPlugin} for the
- * list of patches and their per-mod gates. This class just logs what's on the
- * classpath at common setup time so crash reports are easier to read.
- */
@Mod(AeronauticsCompat.MOD_ID)
public final class AeronauticsCompat {
blob - 0767b5fca0ee1a1e17b034b21949dd8212888137
blob + 02389948c4dae6e1a03518a1dcb919b2dbd9b323
--- src/main/java/sh/rsap/aeronauticscompat/compat/SableBridge.java
+++ src/main/java/sh/rsap/aeronauticscompat/compat/SableBridge.java
import java.lang.reflect.Field;
import java.lang.reflect.Method;
-/**
- * Reflective bridge to Sable's {@code SableCompanion}. We don't compile
- * against Sable; lookups short-circuit to a no-op when the class isn't
- * present so the mod stays loadable without Sable.
- */
public final class SableBridge {
private static final Logger LOGGER = LogUtils.getLogger();
return INSTANCE != null && DIST_SQ_METHOD != null;
}
- /**
- * Compute the squared distance between two points including any sub-level
- * transforms. Returns {@code Double.NaN} when Sable isn't available — the
- * caller should fall back to vanilla distance in that case.
- */
public static double distanceSquaredWithSubLevels(Level level, Position a, Position b) {
if (!isAvailable()) return Double.NaN;
try {
}
}
- /**
- * Whether the given entity is currently inside a Sable sub-level (i.e.
- * standing on a contraption / ship). Used by the Citadel pathfinding
- * guard to avoid rejecting legitimate paths between two entities that
- * are both on the same contraption — those endpoints have huge
- * world-space coords by design and would otherwise look identical to
- * the sub-level entity bleed-through that the guard exists to catch.
- *
- * <p>Returns {@code false} if Sable isn't loaded, the membership lookup
- * isn't available, or the call throws — all of which are fail-safe:
- * the caller will then fall back to the conservative distance check.
- */
public static boolean isInSubLevel(Entity entity) {
if (entity == null || GET_CONTAINING_ENTITY_METHOD == null) return false;
try {
blob - cb534c34f5b64b8a83873d3d7afb2cc161819a6f
blob + 65cd64a8d97e1d3216bf8cade6b59dd7a7703c4e
--- src/main/java/sh/rsap/aeronauticscompat/mixin/AeronauticsCompatMixinPlugin.java
+++ src/main/java/sh/rsap/aeronauticscompat/mixin/AeronauticsCompatMixinPlugin.java
import java.util.Map;
import java.util.Set;
-/**
- * Gates each mixin on the required target mod(s) being present. A mixin is
- * applied only if every marker class it depends on resolves.
- *
- * <p>If a required mod is missing the mixin is silently skipped — the rest
- * of AeronauticsCompat (config, logs, other mixins) keeps working.
- */
public class AeronauticsCompatMixinPlugin implements IMixinConfigPlugin {
private static final String SABLE = "dev.ryanhcode.sable.sound.SoundInstanceDelegated";
}
private static boolean resolves(String fqn, ClassLoader cl) {
- // IMPORTANT: don't use Class.forName here — it *defines* the class even
- // with initialize=false, which trips Mixin's "target loaded too early"
- // check if we happen to probe a class that another mixin wants to
- // transform. getResource only looks for the .class file on the
- // classpath; it does not load it.
String resource = fqn.replace('.', '/') + ".class";
return cl.getResource(resource) != null;
}
blob - 3faec0a4989be5bea853b1659507a0d278745e94
blob + 3702a34bef1209621ffad955cea8e1eaa29cc176
--- src/main/java/sh/rsap/aeronauticscompat/mixin/citadel/CitadelAdvancedPathNavigateMixin.java
+++ src/main/java/sh/rsap/aeronauticscompat/mixin/citadel/CitadelAdvancedPathNavigateMixin.java
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
-/**
- * Citadel-from-contraption OOM guard.
- *
- * <p>When Sable is installed,
- * {@code dev.ryanhcode.sable.util.SubLevelInclusiveLevelEntityGetter} causes
- * {@code Level#getEntities(AABB, ...)} to also scan entities living in Sable
- * sub-levels. Those entities' raw positions live in <i>sub-level-local</i>
- * coordinates — often tens of millions of blocks from any world-space mob
- * that sees them.
- *
- * <p>When a Citadel-powered mob (Alex's Mobs, Alex's Caves, Cataclysm, etc.)
- * calls {@link AdvancedPathNavigate#moveToXYZ} with one of these targets,
- * Citadel's {@code AbstractPathJob} allocates a {@code ChunkCache} sized by
- * the bounding box between the mob's <b>world-space</b> start position and
- * the <b>sub-level-space</b> end position:
- *
- * <pre>
- * final int minX = Math.min(start.getX(), end.getX()) - range/2;
- * final int maxX = Math.max(start.getX(), end.getX()) + range/2;
- * // ... same for Z, then a LevelChunk[dx/16 + 1][dz/16 + 1] is allocated.
- * </pre>
- *
- * With one coordinate near origin and the other in the tens of millions, the
- * chunk array is sized in the trillions of entries and the JVM OOMs. This
- * happens on servers too — the path job runs on the server thread.
- *
- * <p><b>The span-based guard.</b> We measure the <i>span</i> between the
- * mob's current position (what {@code AbstractPathJob.prepareStart} will use
- * as {@code start}) and the requested target {@code (x, y, z)} (the
- * {@code end}). If the horizontal span exceeds
- * {@link #AERONAUTICSCOMPAT$MAX_REASONABLE_SPAN} blocks, the resulting
- * {@code ChunkCache} would be too large to allocate safely — this is
- * definitionally the bleed-through pattern, regardless of whether the mob
- * is on a contraption or in world space. We reject the path and return
- * {@code null}; next tick the goal will pick a saner target.
- *
- * <p>Crucially this guard is <i>symmetric</i>: it doesn't matter whether
- * start is tiny and end is huge, or vice-versa — we only care about the
- * span. That means legitimate mob-to-mob paths entirely within a single
- * sub-level (both endpoints at, say, 20000001 and 20000005) are allowed
- * through, because the span is small. And legitimate world-space paths
- * (start and end both near world origin) are also allowed. Only the
- * pathological cross-domain case is rejected.
- */
@Pseudo
@Mixin(value = AdvancedPathNavigate.class, remap = false)
public abstract class CitadelAdvancedPathNavigateMixin {
- /**
- * Maximum horizontal span (blocks, per axis) between a mob's current
- * position and a prospective path target before the call is rejected.
- * Chosen so that {@code (span / 16 + 1)²} stays comfortably below
- * anything that could exhaust a typical server heap — 4096 blocks yields
- * a ~256×256 chunk array (65k entries), still plenty of headroom for
- * any real pathing job while catching anything in the millions.
- */
@Unique
private static final double AERONAUTICSCOMPAT$MAX_REASONABLE_SPAN = 4096.0;
blob - ffaba628e15d07a3e732d46ad4bc0441545f7284
blob + de1bb51dad23c19336c34528764af4847ffacc69
--- src/main/java/sh/rsap/aeronauticscompat/mixin/etched/EtchedStopListeningSoundMixin.java
+++ src/main/java/sh/rsap/aeronauticscompat/mixin/etched/EtchedStopListeningSoundMixin.java
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
-/**
- * Fixes the "jukebox music never stops on a Sable/Create: Aeronautics
- * contraption" bug that affects <em>every</em> music disc (vanilla,
- * datapack, Etched) as long as Etched is installed.
- *
- * <p><strong>Root cause.</strong> When a jukebox sound is played on a
- * block sitting in a Sable sub-level (i.e. a moving contraption), Sable's
- * {@code SoundEngineMixin.sable$play} wraps the sound in a
- * {@link MovingSoundInstanceDelegate} at play-time — OpenAL's channel is
- * keyed by that wrapper. On stop, Sable's {@code sable$stop} unwraps back
- * to the wrapper via {@link SoundInstanceDelegated}, so the lookup hits
- * and the channel is closed.
- *
- * <p>Etched, however, installs its own wrapper over <em>every</em>
- * jukebox sound via {@code LevelRendererMixin.modifySoundInstance}, which
- * rewrites the local variable in {@code LevelRenderer.playRecord} to be a
- * {@link StopListeningSound}. {@code StopListeningSound} does not extend
- * {@code AbstractSoundInstance}, so it doesn't inherit Sable's
- * {@code SoundInstanceDelegated} mixin. Consequence: at stop time,
- * Sable's unwrap check ({@code instance instanceof SoundInstanceDelegated})
- * fails, the {@link StopListeningSound} is passed through to OpenAL, no
- * channel matches it, and the sound plays forever.
- *
- * <p><strong>Fix.</strong> Make {@code StopListeningSound} implement
- * {@link SoundInstanceDelegated}. Sable's constructor sets the back-ref
- * on us at play-time; Sable's stop-time unwrap reads it back. Now both
- * ends of the Sable pipeline see a matched channel key and the sound
- * stops when the disc is ejected.
- *
- * <p>This mixin is conditionally applied (see
- * {@code sh.rsap.etchtube.mixin.EtchtubeMixinPlugin}): if Sable isn't
- * loaded, the mixin isn't applied, and Etchtube runs without it.
- */
@Mixin(StopListeningSound.class)
public abstract class EtchedStopListeningSoundMixin implements SoundInstanceDelegated {
blob - e039ac8160c40beeac10f16935c1e04dddc8715b
blob + c243ed167a2fe7b685f55f1770f0b2dbfaf486bf
--- src/main/java/sh/rsap/aeronauticscompat/mixin/waterframes/WaterFramesSableDistanceMixin.java
+++ src/main/java/sh/rsap/aeronauticscompat/mixin/waterframes/WaterFramesSableDistanceMixin.java
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import sh.rsap.aeronauticscompat.compat.SableBridge;
-/**
- * Makes WaterFrames' TVs audible when they ride a Sable / Create: Aeronautics
- * contraption.
- *
- * <p><b>Bug.</b> WaterFrames attenuates audio by the distance between the
- * TV's block position and the player. On a Sable contraption the block lives
- * in a sub-level at coordinates around 20 million blocks from the player's
- * world-space position — so the computed distance is astronomical and the
- * TV is silent no matter how close you stand.
- *
- * <p><b>Fix.</b> WaterFrames already has an exact analog for Valkyrien Skies
- * ({@code VSCompat.getSquaredDistance}). This mixin adds the Sable equivalent
- * at HEAD: if Sable is loaded, short-circuit to its
- * {@code distanceSquaredWithSubLevels}, which projects both endpoints out
- * of any enclosing sub-level before measuring.
- *
- * <p>Gated on both WaterFrames and Sable being loaded — see
- * {@code AeronauticsCompatMixinPlugin}.
- */
@Mixin(WaterFrames.class)
public abstract class WaterFramesSableDistanceMixin {