2.2.9
This commit is contained in:
1 parent
5a8cb58cb0
commit
8626d205f7
132 files changed
+18
-931
No files matched your search
@@ -10,9 +10,6 @@ allprojects {
|
|||||||
group = rootProject.maven_group
|
group = rootProject.maven_group
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
// CurseForge Maven artifacts must be resolved from CurseMaven. The
|
|
||||||
// Fabric repository does not proxy these coordinates reliably and can
|
|
||||||
// prevent Gradle from reaching the working repository.
|
|
||||||
maven {
|
maven {
|
||||||
name = "CurseMaven"
|
name = "CurseMaven"
|
||||||
url = "https://www.cursemaven.com"
|
url = "https://www.cursemaven.com"
|
||||||
@@ -63,13 +60,10 @@ allprojects {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't build the root project itself.
|
|
||||||
tasks.named('jar') {
|
tasks.named('jar') {
|
||||||
enabled = false
|
enabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delegate forge-1.20.1 tasks to its own Gradle 8.8 wrapper. ForgeGradle 6 can't run
|
|
||||||
// on Gradle 9 and includeBuild can't mix Gradle versions, so we shell out instead.
|
|
||||||
def forge1201Dir = file('forge-1.20.1')
|
def forge1201Dir = file('forge-1.20.1')
|
||||||
def forge1201Wrapper = providers.systemProperty('os.name').get().toLowerCase().contains('win')
|
def forge1201Wrapper = providers.systemProperty('os.name').get().toLowerCase().contains('win')
|
||||||
? new File(forge1201Dir, 'gradlew.bat')
|
? new File(forge1201Dir, 'gradlew.bat')
|
||||||
@@ -84,10 +78,6 @@ def forge1201Wrapper = providers.systemProperty('os.name').get().toLowerCase().c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delegate fabric-1.20.1 tasks to its own standalone Gradle wrapper. Fabric Loom's
|
|
||||||
// build-wide tinyRemapperService isn't classloader-safe across two loom projects
|
|
||||||
// targeting different Minecraft versions in the same Gradle invocation, so
|
|
||||||
// fabric-1.20.1 can't be a normal included subproject alongside fabric-1.21.1.
|
|
||||||
def fabric120Dir = file('fabric-1.20.1')
|
def fabric120Dir = file('fabric-1.20.1')
|
||||||
def fabric120Wrapper = providers.systemProperty('os.name').get().toLowerCase().contains('win')
|
def fabric120Wrapper = providers.systemProperty('os.name').get().toLowerCase().contains('win')
|
||||||
? new File(fabric120Dir, 'gradlew.bat')
|
? new File(fabric120Dir, 'gradlew.bat')
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ base {
|
|||||||
archivesName = "${mod_id}-common-1.20.1"
|
archivesName = "${mod_id}-common-1.20.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Source-only module — each loader module compiles these sources itself.
|
|
||||||
tasks.named('compileJava').configure {
|
tasks.named('compileJava').configure {
|
||||||
enabled = false
|
enabled = false
|
||||||
}
|
}
|
||||||
|
|||||||
-1
@@ -17,7 +17,6 @@ public final class MoonSkyTracker {
|
|||||||
private static final long MAX_AGE_MILLIS = 1500L;
|
private static final long MAX_AGE_MILLIS = 1500L;
|
||||||
private static final double AIM_COSINE = Math.cos(Math.toRadians(PortalGunMoonMath.AIM_TOLERANCE_DEGREES));
|
private static final double AIM_COSINE = Math.cos(Math.toRadians(PortalGunMoonMath.AIM_TOLERANCE_DEGREES));
|
||||||
private static Vec3 direction;
|
private static Vec3 direction;
|
||||||
// Weak so a dimension change or logout doesn't pin the old client world in memory.
|
|
||||||
private static WeakReference<ClientLevel> level = new WeakReference<>(null);
|
private static WeakReference<ClientLevel> level = new WeakReference<>(null);
|
||||||
private static long recordedAt;
|
private static long recordedAt;
|
||||||
private static Consumer<PortalGunMoonAimPayload> sender = payload -> {};
|
private static Consumer<PortalGunMoonAimPayload> sender = payload -> {};
|
||||||
|
|||||||
-1
@@ -20,7 +20,6 @@ public final class PortalGunCrosshairRenderer {
|
|||||||
private static final int HALF_WIDTH = 17;
|
private static final int HALF_WIDTH = 17;
|
||||||
private static final float MISSING_BRIGHTNESS = 0.3F;
|
private static final float MISSING_BRIGHTNESS = 0.3F;
|
||||||
private static final float MISSING_ALPHA = 0.75F;
|
private static final float MISSING_ALPHA = 0.75F;
|
||||||
// Weak so a dimension change or logout doesn't pin the old client world in memory.
|
|
||||||
private static WeakReference<ClientLevel> cachedLevel = new WeakReference<>(null);
|
private static WeakReference<ClientLevel> cachedLevel = new WeakReference<>(null);
|
||||||
private static long cachedGameTime = Long.MIN_VALUE;
|
private static long cachedGameTime = Long.MIN_VALUE;
|
||||||
private static UUID cachedGunId;
|
private static UUID cachedGunId;
|
||||||
|
|||||||
-1
@@ -12,7 +12,6 @@ import net.minecraft.client.multiplayer.ClientLevel;
|
|||||||
|
|
||||||
public final class PortalGunIndicatorClientState {
|
public final class PortalGunIndicatorClientState {
|
||||||
private static final Map<UUID, PortalGunIndicatorPayload> STATES = new HashMap<>();
|
private static final Map<UUID, PortalGunIndicatorPayload> STATES = new HashMap<>();
|
||||||
// Weak so a dimension change or logout doesn't pin the old client world in memory.
|
|
||||||
private static WeakReference<ClientLevel> level = new WeakReference<>(null);
|
private static WeakReference<ClientLevel> level = new WeakReference<>(null);
|
||||||
private static long lastRequestTick = Long.MIN_VALUE;
|
private static long lastRequestTick = Long.MIN_VALUE;
|
||||||
private static UUID lastRequestedGun;
|
private static UUID lastRequestedGun;
|
||||||
|
|||||||
-5
@@ -31,11 +31,6 @@ public interface InfinityCompatBridge {
|
|||||||
return InfinityWarpResult.REJECTED;
|
return InfinityWarpResult.REJECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts an already-ignited vanilla Nether portal frame at {@code anyPortalBlockPos} into a real, permanent
|
|
||||||
* Infinite Dimensions portal to {@code dimensionId}, generating the dimension first if it doesn't exist yet.
|
|
||||||
* Mirrors what Infinity itself does when a written book is thrown into a lit portal.
|
|
||||||
*/
|
|
||||||
default boolean createPhysicalPortal(ServerLevel level, BlockPos anyPortalBlockPos, ResourceLocation dimensionId) {
|
default boolean createPhysicalPortal(ServerLevel level, BlockPos anyPortalBlockPos, ResourceLocation dimensionId) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -567,7 +567,6 @@ public final class AntarchySettings {
|
|||||||
private static int bloodCrystalAppleDurationTicks = 2400;
|
private static int bloodCrystalAppleDurationTicks = 2400;
|
||||||
private static int bloodCrystalAppleShieldRechargeTicks = 600;
|
private static int bloodCrystalAppleShieldRechargeTicks = 600;
|
||||||
private static int bloodCrystalHardMaxShields = 10;
|
private static int bloodCrystalHardMaxShields = 10;
|
||||||
// Armor stats (iron defense, gold durability, 0 toughness by default)
|
|
||||||
private static int bloodCrystalHelmetDefense = 3;
|
private static int bloodCrystalHelmetDefense = 3;
|
||||||
private static int bloodCrystalChestplateDefense = 7;
|
private static int bloodCrystalChestplateDefense = 7;
|
||||||
private static int bloodCrystalLeggingsDefense = 6;
|
private static int bloodCrystalLeggingsDefense = 6;
|
||||||
@@ -2530,7 +2529,6 @@ public final class AntarchySettings {
|
|||||||
public static int reverieDuplicationCooldownTicks() { return reverieDuplicationCooldownTicks; }
|
public static int reverieDuplicationCooldownTicks() { return reverieDuplicationCooldownTicks; }
|
||||||
public static void setReverieDuplicationCooldownTicks(int v){ reverieDuplicationCooldownTicks = v; }
|
public static void setReverieDuplicationCooldownTicks(int v){ reverieDuplicationCooldownTicks = v; }
|
||||||
|
|
||||||
// Hardcoded AI tuning — getters only, no config wiring
|
|
||||||
public static double reveriePreferredFollowMinDistance() { return reveriePreferredFollowMinDistance; }
|
public static double reveriePreferredFollowMinDistance() { return reveriePreferredFollowMinDistance; }
|
||||||
public static double reveriePreferredFollowMaxDistance() { return reveriePreferredFollowMaxDistance; }
|
public static double reveriePreferredFollowMaxDistance() { return reveriePreferredFollowMaxDistance; }
|
||||||
public static double reverieCatchUpDistance() { return reverieCatchUpDistance; }
|
public static double reverieCatchUpDistance() { return reverieCatchUpDistance; }
|
||||||
|
|||||||
-5
@@ -30,11 +30,6 @@ public final class AntarchyAdvancementTriggers {
|
|||||||
register((id, trigger) -> CriteriaTriggers.register(id.toString(), trigger));
|
register((id, trigger) -> CriteriaTriggers.register(id.toString(), trigger));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers these triggers through the active loader's lifecycle hook.
|
|
||||||
* NeoForge calls this from its trigger-type RegisterEvent; Fabric can call
|
|
||||||
* the no-argument overload during its initializer.
|
|
||||||
*/
|
|
||||||
public static void register(BiConsumer<ResourceLocation, CriterionTrigger<?>> registrar) {
|
public static void register(BiConsumer<ResourceLocation, CriterionTrigger<?>> registrar) {
|
||||||
registrar.accept(ResourceLocation.fromNamespaceAndPath("antarchy", "crossed_gravity_throat"), CROSSING);
|
registrar.accept(ResourceLocation.fromNamespaceAndPath("antarchy", "crossed_gravity_throat"), CROSSING);
|
||||||
registrar.accept(ResourceLocation.fromNamespaceAndPath("antarchy", "horde_phase_changed"), HORDE_PHASE);
|
registrar.accept(ResourceLocation.fromNamespaceAndPath("antarchy", "horde_phase_changed"), HORDE_PHASE);
|
||||||
|
|||||||
-1
@@ -25,7 +25,6 @@ public final class DuplicatorTreeLogic {
|
|||||||
private static final int LOG_SEARCH_BELOW = 5;
|
private static final int LOG_SEARCH_BELOW = 5;
|
||||||
private static final int LOG_SEARCH_ABOVE = 1;
|
private static final int LOG_SEARCH_ABOVE = 1;
|
||||||
|
|
||||||
// Cache center log pos per chunk. WeakHashMap lets levels be GC'd when unloaded.
|
|
||||||
private static final WeakHashMap<ServerLevel, HashMap<Long, BlockPos>> CENTER_LOG_CACHE = new WeakHashMap<>();
|
private static final WeakHashMap<ServerLevel, HashMap<Long, BlockPos>> CENTER_LOG_CACHE = new WeakHashMap<>();
|
||||||
|
|
||||||
private DuplicatorTreeLogic() {
|
private DuplicatorTreeLogic() {
|
||||||
|
|||||||
-1
@@ -20,7 +20,6 @@ import net.minecraft.world.level.block.state.BlockState;
|
|||||||
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
|
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
|
||||||
import net.minecraft.world.phys.BlockHitResult;
|
import net.minecraft.world.phys.BlockHitResult;
|
||||||
|
|
||||||
/** A two-block-tall, light-emitting reed found around Lumen pools. */
|
|
||||||
public final class GlimmeringReedBlock extends DoublePlantBlock implements BonemealableBlock {
|
public final class GlimmeringReedBlock extends DoublePlantBlock implements BonemealableBlock {
|
||||||
public static final MapCodec<GlimmeringReedBlock> CODEC = Block.simpleCodec(GlimmeringReedBlock::new);
|
public static final MapCodec<GlimmeringReedBlock> CODEC = Block.simpleCodec(GlimmeringReedBlock::new);
|
||||||
|
|
||||||
|
|||||||
-6
@@ -25,12 +25,6 @@ import net.minecraft.world.level.material.Fluids;
|
|||||||
public class OuranwoodLeavesBlock extends LeavesBlock implements BonemealableBlock {
|
public class OuranwoodLeavesBlock extends LeavesBlock implements BonemealableBlock {
|
||||||
public static final MapCodec<OuranwoodLeavesBlock> CODEC = Block.simpleCodec(OuranwoodLeavesBlock::new);
|
public static final MapCodec<OuranwoodLeavesBlock> CODEC = Block.simpleCodec(OuranwoodLeavesBlock::new);
|
||||||
|
|
||||||
/*
|
|
||||||
* We still include vanilla LeavesBlock.DISTANCE in the state definition because
|
|
||||||
* LeavesBlock's constructor sets it.
|
|
||||||
*
|
|
||||||
* This is the real Ouranwood decay distance.
|
|
||||||
*/
|
|
||||||
public static final IntegerProperty OURANWOOD_DISTANCE = IntegerProperty.create("ouranwood_distance", 1, 17);
|
public static final IntegerProperty OURANWOOD_DISTANCE = IntegerProperty.create("ouranwood_distance", 1, 17);
|
||||||
|
|
||||||
public static final BooleanProperty PERSISTENT = LeavesBlock.PERSISTENT;
|
public static final BooleanProperty PERSISTENT = LeavesBlock.PERSISTENT;
|
||||||
|
|||||||
-6
@@ -13,12 +13,6 @@ import net.minecraft.world.level.block.state.BlockState;
|
|||||||
import net.minecraft.world.level.block.state.StateDefinition;
|
import net.minecraft.world.level.block.state.StateDefinition;
|
||||||
import net.minecraft.world.level.block.state.properties.IntegerProperty;
|
import net.minecraft.world.level.block.state.properties.IntegerProperty;
|
||||||
|
|
||||||
/**
|
|
||||||
* Invisible world-gen-only marker placed inside a flying squirrel hollow.
|
|
||||||
* Schedules itself to replace with COARSE_DIRT and spawn squirrels shortly
|
|
||||||
* after the chunk loads, so entity creation never blocks the gen thread.
|
|
||||||
* No BlockItem is registered, so this block never appears in creative or JEI.
|
|
||||||
*/
|
|
||||||
public class OuranwoodSquirrelNestBlock extends Block {
|
public class OuranwoodSquirrelNestBlock extends Block {
|
||||||
public static final IntegerProperty SQUIRREL_COUNT = IntegerProperty.create("squirrels", 1, 3);
|
public static final IntegerProperty SQUIRREL_COUNT = IntegerProperty.create("squirrels", 1, 3);
|
||||||
|
|
||||||
|
|||||||
@@ -168,11 +168,6 @@ public abstract class RoyalEggBlock extends BaseEntityBlock {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Vanilla FallingBlockEntity always falls in world-down direction, so an
|
|
||||||
* unsupported egg placed with inverted underside gravity is stepped
|
|
||||||
* upward toward its support instead of being handed to that entity.
|
|
||||||
*/
|
|
||||||
private void tickInvertedFall(BlockState state, ServerLevel level, BlockPos pos) {
|
private void tickInvertedFall(BlockState state, ServerLevel level, BlockPos pos) {
|
||||||
BlockPos above = pos.above();
|
BlockPos above = pos.above();
|
||||||
if (!FallingBlock.isFree(level.getBlockState(above)) || above.getY() > level.getMaxBuildHeight()) {
|
if (!FallingBlock.isFree(level.getBlockState(above)) || above.getY() > level.getMaxBuildHeight()) {
|
||||||
|
|||||||
-2
@@ -65,8 +65,6 @@ public final class QueenTrailSpawnMarkerBlockEntity extends BlockEntity {
|
|||||||
if (!nearbyPlayer) {
|
if (!nearbyPlayer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// The Queen is large enough to span several chunks. Ensure the area around
|
|
||||||
// the arrival point is available before checking its collision box.
|
|
||||||
for (int chunkX = (marker.spawnPos.getX() - 16) >> 4; chunkX <= (marker.spawnPos.getX() + 16) >> 4; chunkX++) {
|
for (int chunkX = (marker.spawnPos.getX() - 16) >> 4; chunkX <= (marker.spawnPos.getX() + 16) >> 4; chunkX++) {
|
||||||
for (int chunkZ = (marker.spawnPos.getZ() - 16) >> 4; chunkZ <= (marker.spawnPos.getZ() + 16) >> 4; chunkZ++) {
|
for (int chunkZ = (marker.spawnPos.getZ() - 16) >> 4; chunkZ <= (marker.spawnPos.getZ() + 16) >> 4; chunkZ++) {
|
||||||
level.getChunk(chunkX, chunkZ);
|
level.getChunk(chunkX, chunkZ);
|
||||||
|
|||||||
-3
@@ -47,9 +47,6 @@ public final class UnderVaultBlockEntity extends BlockEntity {
|
|||||||
|
|
||||||
public static void serverTick(ServerLevel level, BlockPos pos, BlockState state, UnderVaultBlockEntity blockEntity) {
|
public static void serverTick(ServerLevel level, BlockPos pos, BlockState state, UnderVaultBlockEntity blockEntity) {
|
||||||
blockEntity.vaultData.setLevel(level);
|
blockEntity.vaultData.setLevel(level);
|
||||||
// The vanilla vault detector can miss this ceiling-mounted wrapper because its
|
|
||||||
// block state has a separate render-facing property. Keep the state synchronized
|
|
||||||
// with the same four-block activation range before running vanilla's state machine.
|
|
||||||
boolean playerNearby = !level.getEntitiesOfClass(Player.class, new AABB(pos).inflate(4.0D), player -> !player.isSpectator()).isEmpty();
|
boolean playerNearby = !level.getEntitiesOfClass(Player.class, new AABB(pos).inflate(4.0D), player -> !player.isSpectator()).isEmpty();
|
||||||
if (state.getValue(UnderVaultBlock.STATE) == VaultState.INACTIVE && playerNearby && !blockEntity.playerWasNearby) {
|
if (state.getValue(UnderVaultBlock.STATE) == VaultState.INACTIVE && playerNearby && !blockEntity.playerWasNearby) {
|
||||||
state = state.setValue(UnderVaultBlock.STATE, VaultState.ACTIVE);
|
state = state.setValue(UnderVaultBlock.STATE, VaultState.ACTIVE);
|
||||||
|
|||||||
-5
@@ -1,10 +1,5 @@
|
|||||||
package com.craisinlord.antarchy.content.block.entity;
|
package com.craisinlord.antarchy.content.block.entity;
|
||||||
|
|
||||||
/**
|
|
||||||
* Identifies spawn-rule checks made by an Undertrial spawner's vanilla
|
|
||||||
* TrialSpawner tick. The context is scoped to the current server-thread call
|
|
||||||
* so ordinary trial spawners and all other spawn paths retain vanilla rules.
|
|
||||||
*/
|
|
||||||
public final class UndertrialSpawnContext implements AutoCloseable {
|
public final class UndertrialSpawnContext implements AutoCloseable {
|
||||||
private static final ThreadLocal<Integer> DEPTH = ThreadLocal.withInitial(() -> 0);
|
private static final ThreadLocal<Integer> DEPTH = ThreadLocal.withInitial(() -> 0);
|
||||||
|
|
||||||
|
|||||||
-2
@@ -190,8 +190,6 @@ public final class UndertrialSpawnerBlockEntity extends BlockEntity implements T
|
|||||||
if (this.level == null) {
|
if (this.level == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Match vanilla Trial Spawner interaction: override the next mob's entity id while
|
|
||||||
// preserving weighted potentials, ominous settings, and the trial's reward configuration.
|
|
||||||
this.trialSpawner.getData().setEntityId(this.trialSpawner, this.level.random, entityType);
|
this.trialSpawner.getData().setEntityId(this.trialSpawner, this.level.random, entityType);
|
||||||
this.markUpdated();
|
this.markUpdated();
|
||||||
}
|
}
|
||||||
|
|||||||
-1
@@ -6,7 +6,6 @@ import java.util.Map;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
|
||||||
/** Client state for Antarchy-owned games hosted by AntOS. */
|
|
||||||
public final class AntarchyGameClientState {
|
public final class AntarchyGameClientState {
|
||||||
private static final Map<String, String> GAME_STATES = new ConcurrentHashMap<>();
|
private static final Map<String, String> GAME_STATES = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
|||||||
-1
@@ -17,7 +17,6 @@ public final class MoonSkyTracker {
|
|||||||
private static final long MAX_AGE_MILLIS = 1500L;
|
private static final long MAX_AGE_MILLIS = 1500L;
|
||||||
private static final double AIM_COSINE = Math.cos(Math.toRadians(PortalGunMoonMath.AIM_TOLERANCE_DEGREES));
|
private static final double AIM_COSINE = Math.cos(Math.toRadians(PortalGunMoonMath.AIM_TOLERANCE_DEGREES));
|
||||||
private static Vec3 direction;
|
private static Vec3 direction;
|
||||||
// Weak so a dimension change or logout doesn't pin the old client world in memory.
|
|
||||||
private static WeakReference<ClientLevel> level = new WeakReference<>(null);
|
private static WeakReference<ClientLevel> level = new WeakReference<>(null);
|
||||||
private static long recordedAt;
|
private static long recordedAt;
|
||||||
private static Consumer<PortalGunMoonAimPayload> sender = payload -> {};
|
private static Consumer<PortalGunMoonAimPayload> sender = payload -> {};
|
||||||
|
|||||||
-1
@@ -20,7 +20,6 @@ public final class PortalGunCrosshairRenderer {
|
|||||||
private static final int HALF_WIDTH = 17;
|
private static final int HALF_WIDTH = 17;
|
||||||
private static final float MISSING_BRIGHTNESS = 0.3F;
|
private static final float MISSING_BRIGHTNESS = 0.3F;
|
||||||
private static final float MISSING_ALPHA = 0.75F;
|
private static final float MISSING_ALPHA = 0.75F;
|
||||||
// Weak so a dimension change or logout doesn't pin the old client world in memory.
|
|
||||||
private static WeakReference<ClientLevel> cachedLevel = new WeakReference<>(null);
|
private static WeakReference<ClientLevel> cachedLevel = new WeakReference<>(null);
|
||||||
private static long cachedGameTime = Long.MIN_VALUE;
|
private static long cachedGameTime = Long.MIN_VALUE;
|
||||||
private static UUID cachedGunId;
|
private static UUID cachedGunId;
|
||||||
|
|||||||
-1
@@ -12,7 +12,6 @@ import net.minecraft.client.multiplayer.ClientLevel;
|
|||||||
|
|
||||||
public final class PortalGunIndicatorClientState {
|
public final class PortalGunIndicatorClientState {
|
||||||
private static final Map<UUID, PortalGunIndicatorPayload> STATES = new HashMap<>();
|
private static final Map<UUID, PortalGunIndicatorPayload> STATES = new HashMap<>();
|
||||||
// Weak so a dimension change or logout doesn't pin the old client world in memory.
|
|
||||||
private static WeakReference<ClientLevel> level = new WeakReference<>(null);
|
private static WeakReference<ClientLevel> level = new WeakReference<>(null);
|
||||||
private static long lastRequestTick = Long.MIN_VALUE;
|
private static long lastRequestTick = Long.MIN_VALUE;
|
||||||
private static UUID lastRequestedGun;
|
private static UUID lastRequestedGun;
|
||||||
|
|||||||
-3
@@ -8,14 +8,11 @@ import net.minecraft.resources.ResourceLocation;
|
|||||||
import java.util.function.IntPredicate;
|
import java.util.function.IntPredicate;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
/** Registers Antarchy's native games with the AntOS Games app. */
|
|
||||||
public final class AntarchyComputerGames {
|
public final class AntarchyComputerGames {
|
||||||
private AntarchyComputerGames() {}
|
private AntarchyComputerGames() {}
|
||||||
|
|
||||||
public static void register() {
|
public static void register() {
|
||||||
registerIfMissing(game("basilisk", "BASILISK", () -> {
|
registerIfMissing(game("basilisk", "BASILISK", () -> {
|
||||||
// AntOS 1.2.1 creates game sessions without passing the computer position.
|
|
||||||
// Keep Basilisk playable without a position-bound score callback.
|
|
||||||
BasiliskProgram program = new BasiliskProgram(true, 0, 0, score -> {});
|
BasiliskProgram program = new BasiliskProgram(true, 0, 0, score -> {});
|
||||||
return new GameSession(program::tick, program::render, program::keyPressed, ignored -> false);
|
return new GameSession(program::tick, program::render, program::keyPressed, ignored -> false);
|
||||||
}));
|
}));
|
||||||
|
|||||||
-5
@@ -8,11 +8,6 @@ import net.minecraft.client.model.FrogModel;
|
|||||||
import net.minecraft.client.model.geom.ModelPart;
|
import net.minecraft.client.model.geom.ModelPart;
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
|
|
||||||
/**
|
|
||||||
* Reuses vanilla Frog geometry ({@link FrogModel}/{@code ModelLayers.FROG}) for the Frog
|
|
||||||
* Glimmer variant instead of an ill-fitting GeckoLib placeholder mesh, with a simplified
|
|
||||||
* walk/idle animation (GlimmerEntity has no Frog-specific jump/tongue state).
|
|
||||||
*/
|
|
||||||
public class GlimmerFrogModel extends EntityModel<GlimmerEntity> {
|
public class GlimmerFrogModel extends EntityModel<GlimmerEntity> {
|
||||||
private final ModelPart root;
|
private final ModelPart root;
|
||||||
private final ModelPart head;
|
private final ModelPart head;
|
||||||
|
|||||||
-1
@@ -9,7 +9,6 @@ public class AlphaMantisRenderer extends GeoEntityRenderer<AlphaMantisEntity> {
|
|||||||
public AlphaMantisRenderer(EntityRendererProvider.Context context) {
|
public AlphaMantisRenderer(EntityRendererProvider.Context context) {
|
||||||
super(context, new AlphaMantisModel());
|
super(context, new AlphaMantisModel());
|
||||||
this.shadowRadius = 1.5F;
|
this.shadowRadius = 1.5F;
|
||||||
// Mantis renders at 1.25x; the alpha is 1.5x bigger overall
|
|
||||||
this.withScale(1.875F);
|
this.withScale(1.875F);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+4
-9
@@ -74,7 +74,6 @@ public final class ElythiaSkyRenderer {
|
|||||||
float starBrightness = level.getStarBrightness(partialTick) * (1.0F - rainLevel);
|
float starBrightness = level.getStarBrightness(partialTick) * (1.0F - rainLevel);
|
||||||
double timeDegrees = (level.getDayTime() + partialTick) * (360.0D / 24000.0D);
|
double timeDegrees = (level.getDayTime() + partialTick) * (360.0D / 24000.0D);
|
||||||
|
|
||||||
// Blend in a dark purple when it's night (starBrightness > 0)
|
|
||||||
float nightPurpleR = 0.055F;
|
float nightPurpleR = 0.055F;
|
||||||
float nightPurpleG = 0.010F;
|
float nightPurpleG = 0.010F;
|
||||||
float nightPurpleB = 0.120F;
|
float nightPurpleB = 0.120F;
|
||||||
@@ -169,10 +168,10 @@ public final class ElythiaSkyRenderer {
|
|||||||
|
|
||||||
private static float[] pickStarColor(Random random) {
|
private static float[] pickStarColor(Random random) {
|
||||||
float roll = random.nextFloat();
|
float roll = random.nextFloat();
|
||||||
if (roll < 0.80F) return new float[]{1.0F, 1.0F, 1.0F}; // white
|
if (roll < 0.80F) return new float[]{1.0F, 1.0F, 1.0F};
|
||||||
if (roll < 0.87F) return new float[]{0.85F, 0.60F, 1.00F}; // light purple
|
if (roll < 0.87F) return new float[]{0.85F, 0.60F, 1.00F};
|
||||||
if (roll < 0.94F) return new float[]{1.00F, 0.95F, 0.50F}; // yellow
|
if (roll < 0.94F) return new float[]{1.00F, 0.95F, 0.50F};
|
||||||
return new float[]{1.0F, 0.45F, 0.45F}; // red
|
return new float[]{1.0F, 0.45F, 0.45F};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void renderSunrise(PoseStack poseStack, Matrix4f projectionMatrix, ClientLevel level, float partialTick, float rainLevel) {
|
private static void renderSunrise(PoseStack poseStack, Matrix4f projectionMatrix, ClientLevel level, float partialTick, float rainLevel) {
|
||||||
@@ -212,22 +211,18 @@ public final class ElythiaSkyRenderer {
|
|||||||
|
|
||||||
private static void renderCelestialBodies(Matrix4f modelViewMatrix, Matrix4f projectionMatrix, double timeDegrees, float rainLevel) {
|
private static void renderCelestialBodies(Matrix4f modelViewMatrix, Matrix4f projectionMatrix, double timeDegrees, float rainLevel) {
|
||||||
|
|
||||||
// Purple sun
|
|
||||||
float sun1Orbit = orbitAngle(timeDegrees, 1.0D, 0.0D);
|
float sun1Orbit = orbitAngle(timeDegrees, 1.0D, 0.0D);
|
||||||
renderBodyGlow(modelViewMatrix, projectionMatrix, sun1Orbit, 0.0F, 0xD06BFF, rainLevel, 70.0F);
|
renderBodyGlow(modelViewMatrix, projectionMatrix, sun1Orbit, 0.0F, 0xD06BFF, rainLevel, 70.0F);
|
||||||
renderTexturedBody(modelViewMatrix, projectionMatrix, sun1Orbit, 0.0F, 38.0F, 0xD06BFF, 1.0F, SUN_TEXTURE, false, 0, orbitAngle(timeDegrees, 0.8D, 0.0D));
|
renderTexturedBody(modelViewMatrix, projectionMatrix, sun1Orbit, 0.0F, 38.0F, 0xD06BFF, 1.0F, SUN_TEXTURE, false, 0, orbitAngle(timeDegrees, 0.8D, 0.0D));
|
||||||
|
|
||||||
// Orange sub
|
|
||||||
float sun2Orbit = orbitAngle(timeDegrees, 0.73D, 54.0D);
|
float sun2Orbit = orbitAngle(timeDegrees, 0.73D, 54.0D);
|
||||||
renderBodyGlow(modelViewMatrix, projectionMatrix, sun2Orbit, -14.0F, 0xFF9A33, rainLevel, 70.0F);
|
renderBodyGlow(modelViewMatrix, projectionMatrix, sun2Orbit, -14.0F, 0xFF9A33, rainLevel, 70.0F);
|
||||||
renderTexturedBody(modelViewMatrix, projectionMatrix, sun2Orbit, -14.0F, 16.0F, 0xFF9A33, 1.0F, SUN_TEXTURE, false, 0, orbitAngle(timeDegrees, -0.5D, 0.0D));
|
renderTexturedBody(modelViewMatrix, projectionMatrix, sun2Orbit, -14.0F, 16.0F, 0xFF9A33, 1.0F, SUN_TEXTURE, false, 0, orbitAngle(timeDegrees, -0.5D, 0.0D));
|
||||||
|
|
||||||
// Dark green moon
|
|
||||||
float moon2Orbit = orbitAngle(timeDegrees, 1.27D, 228.0D);
|
float moon2Orbit = orbitAngle(timeDegrees, 1.27D, 228.0D);
|
||||||
renderBodyGlow(modelViewMatrix, projectionMatrix, moon2Orbit, 36.0F, 0x4FD84D, rainLevel, 78.0F);
|
renderBodyGlow(modelViewMatrix, projectionMatrix, moon2Orbit, 36.0F, 0x4FD84D, rainLevel, 78.0F);
|
||||||
renderTexturedBody(modelViewMatrix, projectionMatrix, moon2Orbit, 36.0F, 14.0F, 0x4FD84D, 1.0F, MOON_TEXTURE, true, 1, orbitAngle(timeDegrees, 0.3D, 0.0D));
|
renderTexturedBody(modelViewMatrix, projectionMatrix, moon2Orbit, 36.0F, 14.0F, 0x4FD84D, 1.0F, MOON_TEXTURE, true, 1, orbitAngle(timeDegrees, 0.3D, 0.0D));
|
||||||
|
|
||||||
// Light green moon
|
|
||||||
float moon3Orbit = orbitAngle(timeDegrees, 0.38D, 122.0D);
|
float moon3Orbit = orbitAngle(timeDegrees, 0.38D, 122.0D);
|
||||||
renderBodyGlow(modelViewMatrix, projectionMatrix, moon3Orbit, -34.0F, 0xA3FF8F, rainLevel, 78.0F);
|
renderBodyGlow(modelViewMatrix, projectionMatrix, moon3Orbit, -34.0F, 0xA3FF8F, rainLevel, 78.0F);
|
||||||
renderTexturedBody(modelViewMatrix, projectionMatrix, moon3Orbit, -34.0F, 12.0F, 0xA3FF8F, 1.0F, MOON_TEXTURE, true, 2, orbitAngle(timeDegrees, -0.6D, 0.0D));
|
renderTexturedBody(modelViewMatrix, projectionMatrix, moon3Orbit, -34.0F, 12.0F, 0xA3FF8F, 1.0F, MOON_TEXTURE, true, 2, orbitAngle(timeDegrees, -0.6D, 0.0D));
|
||||||
|
|||||||
-3
@@ -193,9 +193,6 @@ public class RoyalBossRenderer extends GeoEntityRenderer<RoyalBossEntity> {
|
|||||||
float outerV = -time * 0.25F;
|
float outerV = -time * 0.25F;
|
||||||
float innerV = -time * 0.25F * 0.5F;
|
float innerV = -time * 0.25F * 0.5F;
|
||||||
|
|
||||||
// Tremorzilla renders the beam in local +Z space. Keeping the mesh in that
|
|
||||||
// space is important: the beam textures are authored for these exact face
|
|
||||||
// coordinates and are not interchangeable with a world-space billboard.
|
|
||||||
float yaw = (float) Math.atan2(dir.z, dir.x);
|
float yaw = (float) Math.atan2(dir.z, dir.x);
|
||||||
float pitch = (float) Math.acos(dir.y);
|
float pitch = (float) Math.acos(dir.y);
|
||||||
poseStack.pushPose();
|
poseStack.pushPose();
|
||||||
|
|||||||
-2
@@ -79,8 +79,6 @@ public final class RoyalIndicatorRenderer {
|
|||||||
out.addVertex(pose, right, top, depth).setUv(1.0F, 0.0F).setOverlay(0).setLight(packedLight).setNormal(pose, 0.0F, 0.0F, 1.0F);
|
out.addVertex(pose, right, top, depth).setUv(1.0F, 0.0F).setOverlay(0).setLight(packedLight).setNormal(pose, 0.0F, 0.0F, 1.0F);
|
||||||
out.addVertex(pose, left, top, depth).setUv(0.0F, 0.0F).setOverlay(0).setLight(packedLight).setNormal(pose, 0.0F, 0.0F, 1.0F);
|
out.addVertex(pose, left, top, depth).setUv(0.0F, 0.0F).setOverlay(0).setLight(packedLight).setNormal(pose, 0.0F, 0.0F, 1.0F);
|
||||||
|
|
||||||
// Emit the reverse winding as well. The crown is viewed from every angle, and
|
|
||||||
// a single-sided quad can vanish when the renderer's culling state rejects it.
|
|
||||||
out.addVertex(pose, left, top, depth).setUv(0.0F, 0.0F).setOverlay(0).setLight(packedLight).setNormal(pose, 0.0F, 0.0F, -1.0F);
|
out.addVertex(pose, left, top, depth).setUv(0.0F, 0.0F).setOverlay(0).setLight(packedLight).setNormal(pose, 0.0F, 0.0F, -1.0F);
|
||||||
out.addVertex(pose, right, top, depth).setUv(1.0F, 0.0F).setOverlay(0).setLight(packedLight).setNormal(pose, 0.0F, 0.0F, -1.0F);
|
out.addVertex(pose, right, top, depth).setUv(1.0F, 0.0F).setOverlay(0).setLight(packedLight).setNormal(pose, 0.0F, 0.0F, -1.0F);
|
||||||
out.addVertex(pose, right, bottom, depth).setUv(1.0F, 1.0F).setOverlay(0).setLight(packedLight).setNormal(pose, 0.0F, 0.0F, -1.0F);
|
out.addVertex(pose, right, bottom, depth).setUv(1.0F, 1.0F).setOverlay(0).setLight(packedLight).setNormal(pose, 0.0F, 0.0F, -1.0F);
|
||||||
|
|||||||
-4
@@ -22,9 +22,6 @@ import net.minecraft.world.level.block.state.BlockState;
|
|||||||
public final class TigerEyeCamouflageTextureResolver {
|
public final class TigerEyeCamouflageTextureResolver {
|
||||||
public record ResolvedTexture(ResourceLocation texture, int argbTint) {}
|
public record ResolvedTexture(ResourceLocation texture, int argbTint) {}
|
||||||
|
|
||||||
// PlayerModel's skin layout is always laid out on a 64x64 canvas, regardless of the
|
|
||||||
// block texture's actual size, so the generated overlay texture must match that grid
|
|
||||||
// for every body part to sample the block texture at the same pixel density.
|
|
||||||
private static final int SKIN_SIZE = 64;
|
private static final int SKIN_SIZE = 64;
|
||||||
private static final Map<Integer, ResolvedTexture> CACHE = new ConcurrentHashMap<>();
|
private static final Map<Integer, ResolvedTexture> CACHE = new ConcurrentHashMap<>();
|
||||||
private static final ResourceLocation FALLBACK_TEXTURE = ResourceLocation.withDefaultNamespace("textures/block/stone.png");
|
private static final ResourceLocation FALLBACK_TEXTURE = ResourceLocation.withDefaultNamespace("textures/block/stone.png");
|
||||||
@@ -102,7 +99,6 @@ public final class TigerEyeCamouflageTextureResolver {
|
|||||||
|
|
||||||
try (NativeImage sourceImage = NativeImage.read(stream)) {
|
try (NativeImage sourceImage = NativeImage.read(stream)) {
|
||||||
int tileWidth = sourceImage.getWidth();
|
int tileWidth = sourceImage.getWidth();
|
||||||
// Animated block textures stack frames vertically below a square first frame.
|
|
||||||
int tileHeight = tileWidth <= sourceImage.getHeight() ? tileWidth : sourceImage.getHeight();
|
int tileHeight = tileWidth <= sourceImage.getHeight() ? tileWidth : sourceImage.getHeight();
|
||||||
|
|
||||||
NativeImage canvas = new NativeImage(SKIN_SIZE, SKIN_SIZE, false);
|
NativeImage canvas = new NativeImage(SKIN_SIZE, SKIN_SIZE, false);
|
||||||
|
|||||||
-3
@@ -94,9 +94,6 @@ public class WindVortexRenderer extends EntityRenderer<WindVortexEntity> {
|
|||||||
addVertex(consumer, pose, end.x + offset.x, end.y + offset.y, end.z + offset.z, red, green, blue, alpha);
|
addVertex(consumer, pose, end.x + offset.x, end.y + offset.y, end.z + offset.z, red, green, blue, alpha);
|
||||||
addVertex(consumer, pose, start.x + offset.x, start.y + offset.y, start.z + offset.z, red, green, blue, alpha);
|
addVertex(consumer, pose, start.x + offset.x, start.y + offset.y, start.z + offset.z, red, green, blue, alpha);
|
||||||
|
|
||||||
// The lightning render type can cull one winding from some camera
|
|
||||||
// angles. Emit the opposite winding as well so every ribbon is
|
|
||||||
// visible from both sides.
|
|
||||||
addVertex(consumer, pose, start.x + offset.x, start.y + offset.y, start.z + offset.z, red, green, blue, alpha);
|
addVertex(consumer, pose, start.x + offset.x, start.y + offset.y, start.z + offset.z, red, green, blue, alpha);
|
||||||
addVertex(consumer, pose, end.x + offset.x, end.y + offset.y, end.z + offset.z, red, green, blue, alpha);
|
addVertex(consumer, pose, end.x + offset.x, end.y + offset.y, end.z + offset.z, red, green, blue, alpha);
|
||||||
addVertex(consumer, pose, end.x - offset.x, end.y - offset.y, end.z - offset.z, red, green, blue, alpha);
|
addVertex(consumer, pose, end.x - offset.x, end.y - offset.y, end.z - offset.z, red, green, blue, alpha);
|
||||||
|
|||||||
-3
@@ -48,9 +48,6 @@ public class GlimmerRenderer extends GeoEntityRenderer<GlimmerEntity> {
|
|||||||
float growth = entity.getGrowthScale();
|
float growth = entity.getGrowthScale();
|
||||||
poseStack.scale(growth, growth, growth);
|
poseStack.scale(growth, growth, growth);
|
||||||
|
|
||||||
// Compute body yaw directly from the entity's own tracked fields rather than trusting
|
|
||||||
// the ambient entityYaw parameter, so the body pose and the head-offset math below stay
|
|
||||||
// self-consistent.
|
|
||||||
float bodyYaw = Mth.rotLerp(partialTick, entity.yBodyRotO, entity.yBodyRot);
|
float bodyYaw = Mth.rotLerp(partialTick, entity.yBodyRotO, entity.yBodyRot);
|
||||||
poseStack.mulPose(Axis.YP.rotationDegrees(180.0F - bodyYaw));
|
poseStack.mulPose(Axis.YP.rotationDegrees(180.0F - bodyYaw));
|
||||||
poseStack.scale(-1.0F, -1.0F, 1.0F);
|
poseStack.scale(-1.0F, -1.0F, 1.0F);
|
||||||
|
|||||||
-1
@@ -82,7 +82,6 @@ public final class QueenLocateCommand {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Finds the nearest generated Queen spawn site without spawning her. Loads (and may generate) the checked chunks. */
|
|
||||||
public static NearestSite findNearestSite(ServerLevel thoraxis, int originX, int originZ) {
|
public static NearestSite findNearestSite(ServerLevel thoraxis, int originX, int originZ) {
|
||||||
int cellX = Math.floorDiv(originX, QueenTrailGrid.SPACING);
|
int cellX = Math.floorDiv(originX, QueenTrailGrid.SPACING);
|
||||||
int cellZ = Math.floorDiv(originZ, QueenTrailGrid.SPACING);
|
int cellZ = Math.floorDiv(originZ, QueenTrailGrid.SPACING);
|
||||||
|
|||||||
-1
@@ -10,7 +10,6 @@ import net.minecraft.resources.ResourceLocation;
|
|||||||
import net.minecraft.world.level.levelgen.Heightmap;
|
import net.minecraft.world.level.levelgen.Heightmap;
|
||||||
import net.minecraft.world.phys.AABB;
|
import net.minecraft.world.phys.AABB;
|
||||||
|
|
||||||
/** Archive coordinate lookups for royals that live on grids rather than in vanilla structures. */
|
|
||||||
public final class AntarchyArchiveLocators {
|
public final class AntarchyArchiveLocators {
|
||||||
private AntarchyArchiveLocators() {
|
private AntarchyArchiveLocators() {
|
||||||
}
|
}
|
||||||
|
|||||||
-1
@@ -10,7 +10,6 @@ import net.minecraft.nbt.ListTag;
|
|||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.world.level.saveddata.SavedData;
|
import net.minecraft.world.level.saveddata.SavedData;
|
||||||
|
|
||||||
/** Persistent Antarchy game progress keyed by AntOS computer location. */
|
|
||||||
public final class AntarchyGameSavedData extends SavedData {
|
public final class AntarchyGameSavedData extends SavedData {
|
||||||
private static final String ID = "antarchy_computer_games";
|
private static final String ID = "antarchy_computer_games";
|
||||||
private final Map<String, GameState> games = new HashMap<>();
|
private final Map<String, GameState> games = new HashMap<>();
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
package com.craisinlord.antarchy.content.effect;
|
package com.craisinlord.antarchy.content.effect;
|
||||||
|
|
||||||
/** Synchronized, presentation-only state for the short-lived Royal Judgment mark. */
|
|
||||||
public interface JudgmentMarkAccess {
|
public interface JudgmentMarkAccess {
|
||||||
boolean antarchy$isJudgmentMarked();
|
boolean antarchy$isJudgmentMarked();
|
||||||
|
|
||||||
|
|||||||
-3
@@ -14,14 +14,12 @@ import net.minecraft.world.entity.EquipmentSlot;
|
|||||||
import net.minecraft.world.entity.LivingEntity;
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
|
||||||
/** Server-owned, player-specific Judgment marks. The visible bit is synchronized by vanilla entity data. */
|
|
||||||
public final class JudgmentMarkManager {
|
public final class JudgmentMarkManager {
|
||||||
private static final Map<ServerLevel, MarkBook> MARKS = new WeakHashMap<>();
|
private static final Map<ServerLevel, MarkBook> MARKS = new WeakHashMap<>();
|
||||||
|
|
||||||
private JudgmentMarkManager() {
|
private JudgmentMarkManager() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns true when this owner had already marked this target before the current hit. */
|
|
||||||
public static boolean recordSuccessfulHit(Player owner, LivingEntity target) {
|
public static boolean recordSuccessfulHit(Player owner, LivingEntity target) {
|
||||||
if (!(owner instanceof ServerPlayer serverPlayer) || !(target.level() instanceof ServerLevel level)
|
if (!(owner instanceof ServerPlayer serverPlayer) || !(target.level() instanceof ServerLevel level)
|
||||||
|| owner.level() != target.level() || !hasGuardianArmor(owner) || !target.isAlive()) {
|
|| owner.level() != target.level() || !hasGuardianArmor(owner) || !target.isAlive()) {
|
||||||
@@ -66,7 +64,6 @@ public final class JudgmentMarkManager {
|
|||||||
return entity instanceof LivingEntity living && living.isAlive() ? living : null;
|
return entity instanceof LivingEntity living && living.isAlive() ? living : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Prunes marks from this target and updates the vanilla-synchronized render bit. */
|
|
||||||
public static void tickTarget(LivingEntity target) {
|
public static void tickTarget(LivingEntity target) {
|
||||||
if (!(target.level() instanceof ServerLevel level)) {
|
if (!(target.level() instanceof ServerLevel level)) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
-4
@@ -23,7 +23,6 @@ import net.minecraft.world.phys.AABB;
|
|||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
/** Server-authoritative Royal Guardian chestplate field and temporary projectile arrest state. */
|
|
||||||
public final class RoyalBoundaryManager {
|
public final class RoyalBoundaryManager {
|
||||||
private static final int ALLY_REFRESH_INTERVAL = 10;
|
private static final int ALLY_REFRESH_INTERVAL = 10;
|
||||||
private static final DustParticleOptions ROYAL_GOLD = new DustParticleOptions(new Vector3f(1.0F, 0.72F, 0.12F), 1.15F);
|
private static final DustParticleOptions ROYAL_GOLD = new DustParticleOptions(new Vector3f(1.0F, 0.72F, 0.12F), 1.15F);
|
||||||
@@ -51,7 +50,6 @@ public final class RoyalBoundaryManager {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Called from ServerPlayer.tick; ends fields immediately when their owner can no longer sustain them. */
|
|
||||||
public static void tickOwner(ServerPlayer owner) {
|
public static void tickOwner(ServerPlayer owner) {
|
||||||
if (!(owner.level() instanceof ServerLevel level)) return;
|
if (!(owner.level() instanceof ServerLevel level)) return;
|
||||||
UUID ownerId = owner.getUUID();
|
UUID ownerId = owner.getUUID();
|
||||||
@@ -92,7 +90,6 @@ public final class RoyalBoundaryManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Predicts this tick's movement so a fast projectile is arrested before its own collision pass. */
|
|
||||||
public static void prepareProjectile(Projectile projectile) {
|
public static void prepareProjectile(Projectile projectile) {
|
||||||
if (!(projectile.level() instanceof ServerLevel level) || projectile.isRemoved()) return;
|
if (!(projectile.level() instanceof ServerLevel level) || projectile.isRemoved()) return;
|
||||||
Map<UUID, ArrestedProjectile> arrested = ARRESTED.get(level);
|
Map<UUID, ArrestedProjectile> arrested = ARRESTED.get(level);
|
||||||
@@ -111,7 +108,6 @@ public final class RoyalBoundaryManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Swept fallback for unusual projectiles and arrest-state progression. */
|
|
||||||
public static void tickProjectile(Projectile projectile) {
|
public static void tickProjectile(Projectile projectile) {
|
||||||
if (!(projectile.level() instanceof ServerLevel level)) return;
|
if (!(projectile.level() instanceof ServerLevel level)) return;
|
||||||
Map<UUID, ArrestedProjectile> arrested = ARRESTED.get(level);
|
Map<UUID, ArrestedProjectile> arrested = ARRESTED.get(level);
|
||||||
|
|||||||
@@ -408,10 +408,6 @@ public class FlytrapEntity extends Monster implements GeoEntity {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put the entity on cooldown before hurting it, regardless of hurt()'s result: a
|
|
||||||
// shield or armor effect can absorb the damage and make hurt() return false without
|
|
||||||
// granting the vanilla invulnerability window, which would otherwise let this attack
|
|
||||||
// re-attempt damage on the same entity every single tick of the active window.
|
|
||||||
this.sweepHitCooldowns.put(candidate.getUUID(), AntarchySettings.flytrapSweepHitCooldownTicks());
|
this.sweepHitCooldowns.put(candidate.getUUID(), AntarchySettings.flytrapSweepHitCooldownTicks());
|
||||||
candidate.hurt(AntarchyDamageSources.flytrapMauling(serverLevel, this), (float) AntarchySettings.flytrapAttackDamage());
|
candidate.hurt(AntarchyDamageSources.flytrapMauling(serverLevel, this), (float) AntarchySettings.flytrapAttackDamage());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,12 +149,10 @@ public class MantisEntity extends Monster implements GeoEntity {
|
|||||||
|
|
||||||
boolean ignoreLightLevel = AntarchySettings.mantisIgnoreLightLevel();
|
boolean ignoreLightLevel = AntarchySettings.mantisIgnoreLightLevel();
|
||||||
|
|
||||||
// Daytime overworld spawns can't pass the vanilla darkness check, so no light gate here
|
|
||||||
if (level.getLevel().isDay() && level.getBiome(pos).is(AntarchyTags.Biomes.MANTIS_OVERWORLD_SPAWN_BIOMES)) {
|
if (level.getLevel().isDay() && level.getBiome(pos).is(AntarchyTags.Biomes.MANTIS_OVERWORLD_SPAWN_BIOMES)) {
|
||||||
return atSurface && level.canSeeSky(pos);
|
return atSurface && level.canSeeSky(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Elythia meadow (and any future mantis_spawn_biomes): nighttime, no sky-access requirement
|
|
||||||
if (level.getLevel().isNight() && level.getBiome(pos).is(AntarchyTags.Biomes.MANTIS_SPAWN_BIOMES)) {
|
if (level.getLevel().isNight() && level.getBiome(pos).is(AntarchyTags.Biomes.MANTIS_SPAWN_BIOMES)) {
|
||||||
return atSurface && (ignoreLightLevel || Monster.checkMonsterSpawnRules(entityType, level, spawnReason, pos, random));
|
return atSurface && (ignoreLightLevel || Monster.checkMonsterSpawnRules(entityType, level, spawnReason, pos, random));
|
||||||
}
|
}
|
||||||
@@ -184,7 +182,6 @@ public class MantisEntity extends Monster implements GeoEntity {
|
|||||||
|
|
||||||
HurtByTargetGoal hurtByTargetGoal = new HurtByTargetGoal(this);
|
HurtByTargetGoal hurtByTargetGoal = new HurtByTargetGoal(this);
|
||||||
this.targetSelector.addGoal(1, hurtByTargetGoal);
|
this.targetSelector.addGoal(1, hurtByTargetGoal);
|
||||||
// randomInterval lowered from default 10 to 5 for faster re-acquisition
|
|
||||||
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 5, true, false, null));
|
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 5, true, false, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-10
@@ -88,7 +88,6 @@ public class OctopusBombEntity extends Monster implements GeoEntity {
|
|||||||
|
|
||||||
private boolean spawnedByKraken;
|
private boolean spawnedByKraken;
|
||||||
|
|
||||||
// Explosive impact (fired from the R.P.O. Launcher)
|
|
||||||
private boolean explosiveImpact;
|
private boolean explosiveImpact;
|
||||||
private java.util.UUID explosiveLauncherId;
|
private java.util.UUID explosiveLauncherId;
|
||||||
private int explosiveArmTicks;
|
private int explosiveArmTicks;
|
||||||
@@ -140,9 +139,7 @@ public class OctopusBombEntity extends Monster implements GeoEntity {
|
|||||||
this.goalSelector.addGoal(5, new LookAtPlayerGoal(this, Player.class, 20.0F));
|
this.goalSelector.addGoal(5, new LookAtPlayerGoal(this, Player.class, 20.0F));
|
||||||
this.goalSelector.addGoal(6, new RandomLookAroundGoal(this));
|
this.goalSelector.addGoal(6, new RandomLookAroundGoal(this));
|
||||||
|
|
||||||
// Only retaliate when hit — neutral otherwise
|
|
||||||
this.targetSelector.addGoal(1, new HurtByTargetGoal(this));
|
this.targetSelector.addGoal(1, new HurtByTargetGoal(this));
|
||||||
// When spawned by Kraken and flying, target nearest player
|
|
||||||
this.targetSelector.addGoal(2, new KrakenSummonTargetGoal(this));
|
this.targetSelector.addGoal(2, new KrakenSummonTargetGoal(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,7 +212,6 @@ public class OctopusBombEntity extends Monster implements GeoEntity {
|
|||||||
if (this.attackCooldown > 0) this.attackCooldown--;
|
if (this.attackCooldown > 0) this.attackCooldown--;
|
||||||
if (this.inkSprayCooldown > 0) this.inkSprayCooldown--;
|
if (this.inkSprayCooldown > 0) this.inkSprayCooldown--;
|
||||||
|
|
||||||
// Ink spray — always active regardless of aggro state
|
|
||||||
this.tickInkSpray();
|
this.tickInkSpray();
|
||||||
|
|
||||||
LivingEntity target = this.getTarget();
|
LivingEntity target = this.getTarget();
|
||||||
@@ -375,10 +371,9 @@ public class OctopusBombEntity extends Monster implements GeoEntity {
|
|||||||
float angle = this.random.nextFloat() * (float) (Math.PI * 2);
|
float angle = this.random.nextFloat() * (float) (Math.PI * 2);
|
||||||
this.wanderDx = Mth.cos(angle) * 0.015f;
|
this.wanderDx = Mth.cos(angle) * 0.015f;
|
||||||
this.wanderDz = Mth.sin(angle) * 0.015f;
|
this.wanderDz = Mth.sin(angle) * 0.015f;
|
||||||
this.wanderDy = -0.01f + this.random.nextFloat() * 0.01f; // slight downward bias
|
this.wanderDy = -0.01f + this.random.nextFloat() * 0.01f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Surface avoidance: if the block above is not water, push down
|
|
||||||
float dy = this.wanderDy;
|
float dy = this.wanderDy;
|
||||||
if (!this.level().getFluidState(this.blockPosition().above()).is(net.minecraft.tags.FluidTags.WATER)) {
|
if (!this.level().getFluidState(this.blockPosition().above()).is(net.minecraft.tags.FluidTags.WATER)) {
|
||||||
dy = -0.03f;
|
dy = -0.03f;
|
||||||
@@ -663,10 +658,6 @@ public class OctopusBombEntity extends Monster implements GeoEntity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
|
||||||
// Inner goal: only target players when spawned by Kraken in fly mode
|
|
||||||
// -------------------------------------------------------------------------
|
|
||||||
|
|
||||||
private static final class KrakenSummonTargetGoal extends NearestAttackableTargetGoal<Player> {
|
private static final class KrakenSummonTargetGoal extends NearestAttackableTargetGoal<Player> {
|
||||||
private final OctopusBombEntity octopus;
|
private final OctopusBombEntity octopus;
|
||||||
|
|
||||||
|
|||||||
-3
@@ -84,7 +84,6 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity {
|
|||||||
private static final int ANIM_ROLL_UP = 2;
|
private static final int ANIM_ROLL_UP = 2;
|
||||||
private static final int ANIM_UNROLL = 4;
|
private static final int ANIM_UNROLL = 4;
|
||||||
|
|
||||||
// wheel_mode is 0.75s, normal_mode is ~0.42s
|
|
||||||
private static final int ROLL_UP_TICKS = 15;
|
private static final int ROLL_UP_TICKS = 15;
|
||||||
private static final int UNROLL_TICKS = 9;
|
private static final int UNROLL_TICKS = 9;
|
||||||
private static final int DEFENSIVE_CURL_TICKS = 100;
|
private static final int DEFENSIVE_CURL_TICKS = 100;
|
||||||
@@ -156,7 +155,6 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity {
|
|||||||
this.goalSelector.addGoal(1, new PanicGoal(this, 1.4D) {
|
this.goalSelector.addGoal(1, new PanicGoal(this, 1.4D) {
|
||||||
@Override
|
@Override
|
||||||
public boolean canUse() {
|
public boolean canUse() {
|
||||||
// Curled-up or tamed rolly pollies stand their ground
|
|
||||||
return !RollyPollyEntity.this.isRolled() && !RollyPollyEntity.this.isTame() && super.canUse();
|
return !RollyPollyEntity.this.isRolled() && !RollyPollyEntity.this.isTame() && super.canUse();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -318,7 +316,6 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity {
|
|||||||
amount *= 0.25F;
|
amount *= 0.25F;
|
||||||
}
|
}
|
||||||
boolean hurt = super.hurt(source, amount);
|
boolean hurt = super.hurt(source, amount);
|
||||||
// Wild rolly pollies curl up defensively when attacked
|
|
||||||
if (hurt && !this.level().isClientSide && !this.isTame() && this.isAlive()
|
if (hurt && !this.level().isClientSide && !this.isTame() && this.isAlive()
|
||||||
&& !this.isRolled() && this.rollTransitionTicks <= 0) {
|
&& !this.isRolled() && this.rollTransitionTicks <= 0) {
|
||||||
this.defensiveCurlTicks = DEFENSIVE_CURL_TICKS;
|
this.defensiveCurlTicks = DEFENSIVE_CURL_TICKS;
|
||||||
|
|||||||
-8
@@ -111,9 +111,6 @@ public class ScorpionEntity extends Monster implements GeoEntity {
|
|||||||
|| spawnReason == MobSpawnType.COMMAND) {
|
|| spawnReason == MobSpawnType.COMMAND) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// The Dream Dunes biome is the entire underside below Y=0. Its higher
|
|
||||||
// spawn weight is therefore targeted there without doubling the small
|
|
||||||
// surface-side Dream Dunes band as well.
|
|
||||||
if (pos.getY() >= 0 && level.getBiome(pos).is(DREAM_DUNES) && random.nextBoolean()) {
|
if (pos.getY() >= 0 && level.getBiome(pos).is(DREAM_DUNES) && random.nextBoolean()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -356,8 +353,6 @@ public class ScorpionEntity extends Monster implements GeoEntity {
|
|||||||
ScorpionEntity.this.getNavigation().stop();
|
ScorpionEntity.this.getNavigation().stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// This goal overrides MeleeAttackGoal.tick, so the gravity mixin on the
|
|
||||||
// vanilla method cannot supply the inverted movement frame here.
|
|
||||||
LivingEntity target = ScorpionEntity.this.getTarget();
|
LivingEntity target = ScorpionEntity.this.getTarget();
|
||||||
if (target != null && ThoraxisUndersideManager.shouldInvertInUnderside(ScorpionEntity.this)) {
|
if (target != null && ThoraxisUndersideManager.shouldInvertInUnderside(ScorpionEntity.this)) {
|
||||||
ScorpionEntity.this.getNavigation().stop();
|
ScorpionEntity.this.getNavigation().stop();
|
||||||
@@ -379,9 +374,6 @@ public class ScorpionEntity extends Monster implements GeoEntity {
|
|||||||
if (ScorpionEntity.this.isAttackLocked()) {
|
if (ScorpionEntity.this.isAttackLocked()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Inverted melee tick handling replaces vanilla MeleeAttackGoal.tick,
|
|
||||||
// so vanilla's internal attack timer is not advanced. The Scorpion's
|
|
||||||
// own cooldown already covers its wind-up and hit timing.
|
|
||||||
if (this.canPerformAttack(enemy) && ScorpionEntity.this.attackCooldownTicks <= 0) {
|
if (this.canPerformAttack(enemy) && ScorpionEntity.this.attackCooldownTicks <= 0) {
|
||||||
ScorpionEntity.this.beginAttack(enemy);
|
ScorpionEntity.this.beginAttack(enemy);
|
||||||
return;
|
return;
|
||||||
|
|||||||
-2
@@ -774,11 +774,9 @@ public class ToreterrorEntity extends Monster implements GeoEntity {
|
|||||||
double dh = Math.sqrt(diff.x * diff.x + diff.z * diff.z);
|
double dh = Math.sqrt(diff.x * diff.x + diff.z * diff.z);
|
||||||
double dy = diff.y;
|
double dy = diff.y;
|
||||||
double gravity = AntarchySettings.waterBombGravity();
|
double gravity = AntarchySettings.waterBombGravity();
|
||||||
// Choose travel time based on horizontal distance at minSpeed, minimum 8 ticks
|
|
||||||
double t = Math.max(8.0, dh / minSpeed);
|
double t = Math.max(8.0, dh / minSpeed);
|
||||||
double vx = diff.x / t;
|
double vx = diff.x / t;
|
||||||
double vz = diff.z / t;
|
double vz = diff.z / t;
|
||||||
// Compensate for gravity accumulating over t ticks
|
|
||||||
double vy = dy / t + 0.5 * gravity * t;
|
double vy = dy / t + 0.5 * gravity * t;
|
||||||
return new Vec3(vx, vy, vz);
|
return new Vec3(vx, vy, vz);
|
||||||
}
|
}
|
||||||
|
|||||||
-6
@@ -46,10 +46,6 @@ public class UpwardFallingBlockEntity extends Entity {
|
|||||||
|
|
||||||
public UpwardFallingBlockEntity(EntityType<UpwardFallingBlockEntity> type, Level level) {
|
public UpwardFallingBlockEntity(EntityType<UpwardFallingBlockEntity> type, Level level) {
|
||||||
super(type, level);
|
super(type, level);
|
||||||
// This entity has its own simple upward-flight and landing checks below. Do not
|
|
||||||
// send it through the normal entity collision solver: Thoraxis can create many of
|
|
||||||
// these at once while chunks are loading, and swept entity collision is needlessly
|
|
||||||
// expensive for a block that only collides with the block directly above it.
|
|
||||||
this.noPhysics = true;
|
this.noPhysics = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,8 +144,6 @@ public class UpwardFallingBlockEntity extends Entity {
|
|||||||
BlockPos headPos = BlockPos.containing(getX(), getBoundingBox().maxY, getZ());
|
BlockPos headPos = BlockPos.containing(getX(), getBoundingBox().maxY, getZ());
|
||||||
BlockState above = level().getBlockState(headPos);
|
BlockState above = level().getBlockState(headPos);
|
||||||
|
|
||||||
// Leaves block the entity but can't hold scaffolding — drop as item, unless this
|
|
||||||
// instance is allowed to land on leaves like a normal falling block would
|
|
||||||
if (above.is(BlockTags.LEAVES) && this.breaksOnLeaves) {
|
if (above.is(BlockTags.LEAVES) && this.breaksOnLeaves) {
|
||||||
dropAndRemove(blockState);
|
dropAndRemove(blockState);
|
||||||
return;
|
return;
|
||||||
|
|||||||
-4
@@ -15,10 +15,6 @@ import net.minecraft.world.phys.BlockHitResult;
|
|||||||
import net.minecraft.world.phys.EntityHitResult;
|
import net.minecraft.world.phys.EntityHitResult;
|
||||||
import net.minecraft.world.phys.HitResult;
|
import net.minecraft.world.phys.HitResult;
|
||||||
|
|
||||||
/**
|
|
||||||
* Thrown out by the worm hook item. Sticks into the first block it hits and stays there,
|
|
||||||
* anchoring a swing rope back to the thrower until the player detaches.
|
|
||||||
*/
|
|
||||||
public class WormHookProjectileEntity extends ThrowableItemProjectile {
|
public class WormHookProjectileEntity extends ThrowableItemProjectile {
|
||||||
private boolean stuck = false;
|
private boolean stuck = false;
|
||||||
|
|
||||||
|
|||||||
-15
@@ -302,8 +302,6 @@ public final class AntTeleportHelper {
|
|||||||
return safePos;
|
return safePos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The bounded search can fail near rough or sparsely-generated terrain.
|
|
||||||
// Retry once with a wider radius before giving up.
|
|
||||||
loadArrivalSearchArea(destination, preferredPos, EXPANDED_ARRIVAL_SEARCH_RADIUS);
|
loadArrivalSearchArea(destination, preferredPos, EXPANDED_ARRIVAL_SEARCH_RADIUS);
|
||||||
Vec3 expandedSafePos = findSafeArrivalPositionInYRange(
|
Vec3 expandedSafePos = findSafeArrivalPositionInYRange(
|
||||||
player, destination, preferredPos, yRange[0], yRange[1],
|
player, destination, preferredPos, yRange[0], yRange[1],
|
||||||
@@ -393,11 +391,6 @@ public final class AntTeleportHelper {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Arrival validation needs neighboring chunks for collision checks. Load a
|
|
||||||
* bounded area up front so unloaded terrain is not mistaken for an unsafe
|
|
||||||
* destination and rejected prematurely.
|
|
||||||
*/
|
|
||||||
public static void loadArrivalSearchArea(ServerLevel destination, BlockPos preferredPos, int searchRadius) {
|
public static void loadArrivalSearchArea(ServerLevel destination, BlockPos preferredPos, int searchRadius) {
|
||||||
ChunkPos center = new ChunkPos(preferredPos);
|
ChunkPos center = new ChunkPos(preferredPos);
|
||||||
int chunkRadius = (searchRadius >> 4) + 1;
|
int chunkRadius = (searchRadius >> 4) + 1;
|
||||||
@@ -462,9 +455,6 @@ public final class AntTeleportHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prefer actual generated surfaces. This is especially important in
|
|
||||||
// Elythia, where the configured spawn height is not necessarily the
|
|
||||||
// playable surface.
|
|
||||||
for (BlockPos candidate : surfaceCandidates) {
|
for (BlockPos candidate : surfaceCandidates) {
|
||||||
if (candidate.getY() < minY || candidate.getY() > maxY) {
|
if (candidate.getY() < minY || candidate.getY() > maxY) {
|
||||||
continue;
|
continue;
|
||||||
@@ -475,15 +465,10 @@ public final class AntTeleportHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Elythia arrivals must stay on the generated surface; a vertical scan
|
|
||||||
// can otherwise select an underground cave floor after a surface miss.
|
|
||||||
if (elythia) {
|
if (elythia) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Heightmaps can be stale or unsuitable around structures, so retain a
|
|
||||||
// bounded exhaustive search as a final generated-terrain attempt in
|
|
||||||
// dimensions whose configured arrival ranges intentionally allow it.
|
|
||||||
for (int radius = 0; radius <= searchRadius; radius++) {
|
for (int radius = 0; radius <= searchRadius; radius++) {
|
||||||
for (int xOff = -radius; xOff <= radius; xOff++) {
|
for (int xOff = -radius; xOff <= radius; xOff++) {
|
||||||
for (int zOff = -radius; zOff <= radius; zOff++) {
|
for (int zOff = -radius; zOff <= radius; zOff++) {
|
||||||
|
|||||||
-5
@@ -78,11 +78,6 @@ public class RainbowAntEntity extends BaseAntEntity implements GeoEntity {
|
|||||||
return this.hasActiveInfinityDestination() || super.requiresCustomPersistence();
|
return this.hasActiveInfinityDestination() || super.requiresCustomPersistence();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Called on death. If this ant has already been activated (fed its reagent) and Infinity integration is
|
|
||||||
* enabled, looks for a nearby unlit obsidian Nether-portal frame and, if found, ignites it as a permanent
|
|
||||||
* physical Infinity Dimensions portal to this ant's assigned dimension.
|
|
||||||
*/
|
|
||||||
public boolean tryIgniteInfinityPortalOnDeath() {
|
public boolean tryIgniteInfinityPortalOnDeath() {
|
||||||
if (!this.infinityActivated) {
|
if (!this.infinityActivated) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
-2
@@ -260,7 +260,6 @@ public class TermiteEntity extends BaseAntEntity implements GeoEntity {
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// North/South faces (dz = ±r)
|
|
||||||
for (int dx = -r; dx <= r; dx++) {
|
for (int dx = -r; dx <= r; dx++) {
|
||||||
candidate.set(ox + dx, oy + dy, oz - r);
|
candidate.set(ox + dx, oy + dy, oz - r);
|
||||||
if (this.isValidWoodTarget(candidate)) {
|
if (this.isValidWoodTarget(candidate)) {
|
||||||
@@ -273,7 +272,6 @@ public class TermiteEntity extends BaseAntEntity implements GeoEntity {
|
|||||||
if (d < bestDistSq) { bestDistSq = d; bestPos = candidate.immutable(); }
|
if (d < bestDistSq) { bestDistSq = d; bestPos = candidate.immutable(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// East/West faces (dx = ±r, corners already covered above)
|
|
||||||
for (int dz = -r + 1; dz <= r - 1; dz++) {
|
for (int dz = -r + 1; dz <= r - 1; dz++) {
|
||||||
candidate.set(ox - r, oy + dy, oz + dz);
|
candidate.set(ox - r, oy + dy, oz + dz);
|
||||||
if (this.isValidWoodTarget(candidate)) {
|
if (this.isValidWoodTarget(candidate)) {
|
||||||
|
|||||||
-3
@@ -669,13 +669,11 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
this.stopActiveMovement();
|
this.stopActiveMovement();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Scales turn rate by intended movement speed so the long body pivots tighter when slow and wider when fast. */
|
|
||||||
private static final class BasiliskMoveControl extends MoveControl {
|
private static final class BasiliskMoveControl extends MoveControl {
|
||||||
private BasiliskMoveControl(Mob mob) {
|
private BasiliskMoveControl(Mob mob) {
|
||||||
super(mob);
|
super(mob);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Call this to prevent the move control from reapplying speed this tick. */
|
|
||||||
public void halt() {
|
public void halt() {
|
||||||
this.operation = MoveControl.Operation.WAIT;
|
this.operation = MoveControl.Operation.WAIT;
|
||||||
}
|
}
|
||||||
@@ -735,7 +733,6 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
|||||||
BasiliskEntity.this.getLookControl().setLookAt(target, 30.0F, 30.0F);
|
BasiliskEntity.this.getLookControl().setLookAt(target, 30.0F, 30.0F);
|
||||||
}
|
}
|
||||||
|
|
||||||
// super handles path recalc and cooldown timer
|
|
||||||
super.tick();
|
super.tick();
|
||||||
|
|
||||||
if (target != null && BasiliskEntity.this.isWithinMeleeAttackRange(target)) {
|
if (target != null && BasiliskEntity.this.isWithinMeleeAttackRange(target)) {
|
||||||
|
|||||||
-2
@@ -113,7 +113,6 @@ public class BrutalflyEntity extends Monster implements GeoEntity {
|
|||||||
private double currentStrafeAngleOffset = this.random.nextDouble() * (Math.PI * 2.0D);
|
private double currentStrafeAngleOffset = this.random.nextDouble() * (Math.PI * 2.0D);
|
||||||
private boolean spawnedDeathButterflies;
|
private boolean spawnedDeathButterflies;
|
||||||
|
|
||||||
// Cocoon state (server-side)
|
|
||||||
@Nullable
|
@Nullable
|
||||||
BlockPos anchorPos;
|
BlockPos anchorPos;
|
||||||
private int cocoonHits;
|
private int cocoonHits;
|
||||||
@@ -312,7 +311,6 @@ public class BrutalflyEntity extends Monster implements GeoEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.getAnimationState() == ANIM_COCOON_IDLE) {
|
if (this.getAnimationState() == ANIM_COCOON_IDLE) {
|
||||||
// Will be reset to COCOON after idle ticks counted down
|
|
||||||
} else if (this.tickCount % 200 == 17 && this.random.nextFloat() < 0.4F) {
|
} else if (this.tickCount % 200 == 17 && this.random.nextFloat() < 0.4F) {
|
||||||
this.setAnimationState(ANIM_COCOON_IDLE);
|
this.setAnimationState(ANIM_COCOON_IDLE);
|
||||||
this.cocoonAnimTicks = COCOON_IDLE_ANIM_TICKS;
|
this.cocoonAnimTicks = COCOON_IDLE_ANIM_TICKS;
|
||||||
|
|||||||
-1
@@ -77,7 +77,6 @@ public class GlimmerAntBehavior implements GlimmerVariantBehavior {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityDimensions adultDimensions() {
|
public EntityDimensions adultDimensions() {
|
||||||
// Matches the real ant's hitbox.
|
|
||||||
return EntityDimensions.scalable(0.6375F, 0.2125F);
|
return EntityDimensions.scalable(0.6375F, 0.2125F);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-1
@@ -80,7 +80,6 @@ public class GlimmerAppleCowBehavior implements GlimmerVariantBehavior {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityDimensions adultDimensions() {
|
public EntityDimensions adultDimensions() {
|
||||||
// Matches the real Apple Cow's hitbox (extends vanilla Cow).
|
|
||||||
return EntityDimensions.scalable(0.9F, 1.4F);
|
return EntityDimensions.scalable(0.9F, 1.4F);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-13
@@ -11,10 +11,6 @@ import net.minecraft.server.level.ServerLevel;
|
|||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraft.world.level.saveddata.SavedData;
|
import net.minecraft.world.level.saveddata.SavedData;
|
||||||
|
|
||||||
/**
|
|
||||||
* Tracks each player's current Glimmer companion so taming a new one despawns the old,
|
|
||||||
* even if the old companion is in a different loaded dimension.
|
|
||||||
*/
|
|
||||||
public class GlimmerCompanionSavedData extends SavedData {
|
public class GlimmerCompanionSavedData extends SavedData {
|
||||||
private static final String ID = "antarchy_glimmer_companions";
|
private static final String ID = "antarchy_glimmer_companions";
|
||||||
private static final String ENTRIES_KEY = "Entries";
|
private static final String ENTRIES_KEY = "Entries";
|
||||||
@@ -56,11 +52,6 @@ public class GlimmerCompanionSavedData extends SavedData {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Records {@code newCompanion} as {@code owner}'s current Glimmer. Any previous
|
|
||||||
* companion found in a currently loaded dimension isn't removed - it just loses
|
|
||||||
* its owner and becomes a wild, re-tameable Glimmer again.
|
|
||||||
*/
|
|
||||||
public static void replaceCompanion(MinecraftServer server, UUID owner, UUID newCompanion) {
|
public static void replaceCompanion(MinecraftServer server, UUID owner, UUID newCompanion) {
|
||||||
GlimmerCompanionSavedData data = get(server);
|
GlimmerCompanionSavedData data = get(server);
|
||||||
UUID previous = data.companionByOwner.put(owner, newCompanion);
|
UUID previous = data.companionByOwner.put(owner, newCompanion);
|
||||||
@@ -80,10 +71,6 @@ public class GlimmerCompanionSavedData extends SavedData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes {@code owner}'s companion record if it currently points at {@code companion},
|
|
||||||
* used when that Glimmer is captured into a bottle rather than replaced by a new one.
|
|
||||||
*/
|
|
||||||
public static void clearCompanion(MinecraftServer server, UUID owner, UUID companion) {
|
public static void clearCompanion(MinecraftServer server, UUID owner, UUID companion) {
|
||||||
GlimmerCompanionSavedData data = get(server);
|
GlimmerCompanionSavedData data = get(server);
|
||||||
if (companion.equals(data.companionByOwner.get(owner))) {
|
if (companion.equals(data.companionByOwner.get(owner))) {
|
||||||
|
|||||||
-15
@@ -147,7 +147,6 @@ public class GlimmerEntity extends TamableAnimal implements GeoEntity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void push(Entity entity) {
|
public void push(Entity entity) {
|
||||||
// no-op: Glimmers pass through other entities
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -179,10 +178,6 @@ public class GlimmerEntity extends TamableAnimal implements GeoEntity {
|
|||||||
this.entityData.set(ABILITY_ANIM_TICKS, ticks);
|
this.entityData.set(ABILITY_ANIM_TICKS, ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Ticks remaining in the daytime despawn fade-out, or 0 if not currently fading.
|
|
||||||
* Used client-side to fade the render alpha to nothing before the entity is removed.
|
|
||||||
*/
|
|
||||||
public int getFadeTicks() {
|
public int getFadeTicks() {
|
||||||
return this.entityData.get(FADE_TICKS);
|
return this.entityData.get(FADE_TICKS);
|
||||||
}
|
}
|
||||||
@@ -499,10 +494,6 @@ public class GlimmerEntity extends TamableAnimal implements GeoEntity {
|
|||||||
return GlimmerVariant.random(this.random);
|
return GlimmerVariant.random(this.random);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Wild Glimmers are common in Glimmering Pools, but only rarely (and only at night)
|
|
||||||
* turn up in Ouranwood Forest, the Elythia Meadow, and the Peach Forest.
|
|
||||||
*/
|
|
||||||
public static boolean checkGlimmerSpawnRules(EntityType<GlimmerEntity> type, ServerLevelAccessor level,
|
public static boolean checkGlimmerSpawnRules(EntityType<GlimmerEntity> type, ServerLevelAccessor level,
|
||||||
MobSpawnType spawnType, BlockPos pos, net.minecraft.util.RandomSource random) {
|
MobSpawnType spawnType, BlockPos pos, net.minecraft.util.RandomSource random) {
|
||||||
if (!net.minecraft.world.entity.animal.Animal.checkAnimalSpawnRules(type, level, spawnType, pos, random)) {
|
if (!net.minecraft.world.entity.animal.Animal.checkAnimalSpawnRules(type, level, spawnType, pos, random)) {
|
||||||
@@ -601,12 +592,6 @@ public class GlimmerEntity extends TamableAnimal implements GeoEntity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* With {@code noPhysics} true, Glimmers never travel through vanilla's normal movement path,
|
|
||||||
* so the usual body-follows-head catch-up never runs and a stationary Glimmer looking around
|
|
||||||
* (LookAtPlayerGoal/RandomLookAroundGoal only move the head) ends up with its head rendered
|
|
||||||
* far past the model's body — this keeps the body snapped within {@link #getMaxHeadYRot()} of it.
|
|
||||||
*/
|
|
||||||
private void clampBodyToHeadRotation() {
|
private void clampBodyToHeadRotation() {
|
||||||
float maxYaw = this.getMaxHeadYRot();
|
float maxYaw = this.getMaxHeadYRot();
|
||||||
float delta = Mth.wrapDegrees(this.yHeadRot - this.yBodyRot);
|
float delta = Mth.wrapDegrees(this.yHeadRot - this.yBodyRot);
|
||||||
|
|||||||
-2
@@ -111,7 +111,6 @@ public class GlimmerFrogBehavior implements GlimmerVariantBehavior {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityDimensions adultDimensions() {
|
public EntityDimensions adultDimensions() {
|
||||||
// Matches vanilla Frog's real hitbox.
|
|
||||||
return EntityDimensions.scalable(0.5F, 0.5F);
|
return EntityDimensions.scalable(0.5F, 0.5F);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +154,6 @@ public class GlimmerFrogBehavior implements GlimmerVariantBehavior {
|
|||||||
|
|
||||||
pending.ticksRemaining--;
|
pending.ticksRemaining--;
|
||||||
if (pending.ticksRemaining == TONGUE_ANIM_TICKS - TONGUE_GRAB_TICK) {
|
if (pending.ticksRemaining == TONGUE_ANIM_TICKS - TONGUE_GRAB_TICK) {
|
||||||
// The tongue "catches" the target partway through the animation and reels it in.
|
|
||||||
entity.playSound(SoundEvents.FROG_TONGUE, 1.0F, 1.0F);
|
entity.playSound(SoundEvents.FROG_TONGUE, 1.0F, 1.0F);
|
||||||
}
|
}
|
||||||
if (pending.ticksRemaining <= TONGUE_ANIM_TICKS - TONGUE_GRAB_TICK) {
|
if (pending.ticksRemaining <= TONGUE_ANIM_TICKS - TONGUE_GRAB_TICK) {
|
||||||
|
|||||||
-67
@@ -10,11 +10,6 @@ import net.minecraft.world.entity.player.Player;
|
|||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
|
||||||
* Per-variant behavior for the composite {@link GlimmerEntity}: AI, model/texture selection, and sounds.
|
|
||||||
* One concrete implementation per {@link GlimmerVariant}, chosen via composition rather than subclassing
|
|
||||||
* so a single EntityType can be reliably reconstructed across save/load.
|
|
||||||
*/
|
|
||||||
public interface GlimmerVariantBehavior {
|
public interface GlimmerVariantBehavior {
|
||||||
void registerGoals(GlimmerEntity entity);
|
void registerGoals(GlimmerEntity entity);
|
||||||
|
|
||||||
@@ -32,124 +27,62 @@ public interface GlimmerVariantBehavior {
|
|||||||
|
|
||||||
SoundEvent deathSound();
|
SoundEvent deathSound();
|
||||||
|
|
||||||
/**
|
|
||||||
* Optional variant-specific interaction (e.g. shearing the Apple Cow variant for a Spirit Apple).
|
|
||||||
* Return null to fall through to the entity's default interaction handling.
|
|
||||||
*/
|
|
||||||
@Nullable
|
@Nullable
|
||||||
default InteractionResult onInteract(GlimmerEntity entity, Player player, ItemStack stack, InteractionHand hand) {
|
default InteractionResult onInteract(GlimmerEntity entity, Player player, ItemStack stack, InteractionHand hand) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Optional per-tick hook for variant-specific server logic (e.g. the Basilisk's petrify gaze).
|
|
||||||
*/
|
|
||||||
default void customTick(GlimmerEntity entity) {
|
default void customTick(GlimmerEntity entity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Optional hook fired after {@code entity} lands a successful hit on {@code target}
|
|
||||||
* (e.g. the Frog variant dropping Lumen Froglight when it kills a small Magma Cube).
|
|
||||||
*/
|
|
||||||
default void onHurtTarget(GlimmerEntity entity, Entity target) {
|
default void onHurtTarget(GlimmerEntity entity, Entity target) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Called periodically (roughly once a second) while this Glimmer is tamed and its
|
|
||||||
* owner is nearby and loaded. Should (re)apply the variant's passive effect with a
|
|
||||||
* short duration so it naturally lapses if the owner leaves range.
|
|
||||||
*/
|
|
||||||
default void tickPassive(GlimmerEntity entity, Player owner) {
|
default void tickPassive(GlimmerEntity entity, Player owner) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Called every server tick (not just the coarse refresh interval) while nearby, for
|
|
||||||
* passives that need finer-grained bookkeeping than a periodic effect refresh (e.g.
|
|
||||||
* the Apple Cow's exhaustion dampening).
|
|
||||||
*/
|
|
||||||
default void tickPassiveEveryTick(GlimmerEntity entity, Player owner) {
|
default void tickPassiveEveryTick(GlimmerEntity entity, Player owner) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Called once the tick the owner leaves range (or the companion is otherwise no
|
|
||||||
* longer eligible) so any directly-applied (non-MobEffect) passive state can be undone.
|
|
||||||
*/
|
|
||||||
default void clearPassive(GlimmerEntity entity, Player owner) {
|
default void clearPassive(GlimmerEntity entity, Player owner) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Animation (from this variant's own animation file) to play while
|
|
||||||
* {@link GlimmerEntity#playAbilityAnimation(int)} is active. Null plays no override.
|
|
||||||
*/
|
|
||||||
@Nullable
|
@Nullable
|
||||||
default software.bernie.geckolib.animation.RawAnimation abilityAnimation() {
|
default software.bernie.geckolib.animation.RawAnimation abilityAnimation() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Animation to play in place of the default walk loop while moving. Null uses the
|
|
||||||
* default walk animation (e.g. the Deer switches to its run clip while following its owner).
|
|
||||||
*/
|
|
||||||
@Nullable
|
@Nullable
|
||||||
default software.bernie.geckolib.animation.RawAnimation movingAnimation(GlimmerEntity entity) {
|
default software.bernie.geckolib.animation.RawAnimation movingAnimation(GlimmerEntity entity) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Animation to play while idle in place of the default idle loop. Null uses the
|
|
||||||
* shared Glimmer idle animation.
|
|
||||||
*/
|
|
||||||
@Nullable
|
@Nullable
|
||||||
default software.bernie.geckolib.animation.RawAnimation idleAnimation(GlimmerEntity entity) {
|
default software.bernie.geckolib.animation.RawAnimation idleAnimation(GlimmerEntity entity) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Navigation speed multiplier used while following the owner (see {@link GlimmerFollowOwnerGoal}).
|
|
||||||
*/
|
|
||||||
default double followSpeedModifier() {
|
default double followSpeedModifier() {
|
||||||
return 1.15D;
|
return 1.15D;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Shared action-bar feedback helper for ability-use messages.
|
|
||||||
*/
|
|
||||||
default void sendAbilityMessage(Player owner, net.minecraft.network.chat.Component message) {
|
default void sendAbilityMessage(Player owner, net.minecraft.network.chat.Component message) {
|
||||||
owner.displayClientMessage(message, true);
|
owner.displayClientMessage(message, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Called every server tick while the owner is nearby and the ability is off cooldown.
|
|
||||||
* Implementations should check their own trigger condition and, if it fires, perform
|
|
||||||
* the ability and call {@link GlimmerEntity#startAbilityCooldown()}.
|
|
||||||
*/
|
|
||||||
default void tickAbilityCheck(GlimmerEntity entity, Player owner) {
|
default void tickAbilityCheck(GlimmerEntity entity, Player owner) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Cooldown duration for this variant's active ability, in ticks.
|
|
||||||
*/
|
|
||||||
default int abilityCooldownTicks() {
|
default int abilityCooldownTicks() {
|
||||||
return 20 * 120;
|
return 20 * 120;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Per-tick shrink/growth-recovery rate used to decay {@link GlimmerEntity#getGrowthScale()}
|
|
||||||
* back toward 1.0 after an ability temporarily changes it. 0 means the variant never changes scale.
|
|
||||||
*/
|
|
||||||
default double growthDecayPerTick() {
|
default double growthDecayPerTick() {
|
||||||
return 0.0D;
|
return 0.0D;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Hitbox size matching the real creature this variant is a "spirit" of, rather than
|
|
||||||
* a single hitbox shared by every variant.
|
|
||||||
*/
|
|
||||||
EntityDimensions adultDimensions();
|
EntityDimensions adultDimensions();
|
||||||
|
|
||||||
/**
|
|
||||||
* Defaults to half the adult size, matching vanilla's typical baby scaling.
|
|
||||||
*/
|
|
||||||
default EntityDimensions babyDimensions() {
|
default EntityDimensions babyDimensions() {
|
||||||
return this.adultDimensions().scale(0.5F);
|
return this.adultDimensions().scale(0.5F);
|
||||||
}
|
}
|
||||||
|
|||||||
-7
@@ -85,7 +85,6 @@ public class KrakenEntity extends Monster implements GeoEntity, MultipartEntityO
|
|||||||
private static final int ATTACK_SWING_RIGHT = 3;
|
private static final int ATTACK_SWING_RIGHT = 3;
|
||||||
private static final int ATTACK_SLAM = 4;
|
private static final int ATTACK_SLAM = 4;
|
||||||
|
|
||||||
// Synced animation state values
|
|
||||||
private static final int ANIM_NONE = 0;
|
private static final int ANIM_NONE = 0;
|
||||||
private static final int ANIM_CRY = 1;
|
private static final int ANIM_CRY = 1;
|
||||||
private static final int ANIM_GRAB = 2;
|
private static final int ANIM_GRAB = 2;
|
||||||
@@ -199,7 +198,6 @@ public class KrakenEntity extends Monster implements GeoEntity, MultipartEntityO
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
|
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
|
||||||
// idle_controller always loops idle; action_controller layers on top when active
|
|
||||||
controllers.add(new AnimationController<>(this, "idle_controller", 0, state -> {
|
controllers.add(new AnimationController<>(this, "idle_controller", 0, state -> {
|
||||||
if (this.getAnimationState() == ANIM_DEATH) {
|
if (this.getAnimationState() == ANIM_DEATH) {
|
||||||
return PlayState.STOP;
|
return PlayState.STOP;
|
||||||
@@ -646,7 +644,6 @@ public class KrakenEntity extends Monster implements GeoEntity, MultipartEntityO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// swingRight=true means ATTACK_SWING_RIGHT, which knocks players to the Kraken's LEFT
|
|
||||||
private void tickSwingAttack(boolean swingRight) {
|
private void tickSwingAttack(boolean swingRight) {
|
||||||
if (this.actionTicks == 10) {
|
if (this.actionTicks == 10) {
|
||||||
this.performSwing(swingRight);
|
this.performSwing(swingRight);
|
||||||
@@ -749,9 +746,6 @@ public class KrakenEntity extends Monster implements GeoEntity, MultipartEntityO
|
|||||||
return attackState == ATTACK_SLAM;
|
return attackState == ATTACK_SLAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determines left vs right based on which side the target is on relative to the Kraken.
|
|
||||||
// Kraken's right vector is forward x world-up. If target is on the Kraken's right side,
|
|
||||||
// use swing_right (which knocks them left). If on the left, use swing_left (knocks them right).
|
|
||||||
private int resolveSwingDirection(LivingEntity target) {
|
private int resolveSwingDirection(LivingEntity target) {
|
||||||
Vec3 forward = this.getViewVector(1.0F);
|
Vec3 forward = this.getViewVector(1.0F);
|
||||||
Vec3 right = forward.cross(new Vec3(0, 1, 0)).normalize();
|
Vec3 right = forward.cross(new Vec3(0, 1, 0)).normalize();
|
||||||
@@ -765,7 +759,6 @@ public class KrakenEntity extends Monster implements GeoEntity, MultipartEntityO
|
|||||||
float damage = (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE);
|
float damage = (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE);
|
||||||
|
|
||||||
Vec3 forward = this.getViewVector(1.0F);
|
Vec3 forward = this.getViewVector(1.0F);
|
||||||
// swingRight knocks to Kraken's left (-right), swingLeft knocks to Kraken's right (+right)
|
|
||||||
Vec3 right = forward.cross(new Vec3(0, 1, 0)).normalize();
|
Vec3 right = forward.cross(new Vec3(0, 1, 0)).normalize();
|
||||||
Vec3 knockDir = swingRight ? right.scale(-1) : right;
|
Vec3 knockDir = swingRight ? right.scale(-1) : right;
|
||||||
|
|
||||||
|
|||||||
-1
@@ -642,7 +642,6 @@ public class NightmareEntity extends Monster implements GeoEntity {
|
|||||||
return this.entityData.get(ANIMATION_STATE);
|
return this.entityData.get(ANIMATION_STATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Selects the looping flight pose for the isolated computer archive preview instance. */
|
|
||||||
public void setArchivePreviewFlying() {
|
public void setArchivePreviewFlying() {
|
||||||
this.setAnimationState(ANIM_FLY);
|
this.setAnimationState(ANIM_FLY);
|
||||||
}
|
}
|
||||||
|
|||||||
-9
@@ -105,7 +105,6 @@ public class KingEntity extends RoyalBossEntity {
|
|||||||
private static final double CHAIN_LIGHTNING_JUMP_RANGE = 9.0D;
|
private static final double CHAIN_LIGHTNING_JUMP_RANGE = 9.0D;
|
||||||
private static final int ICE_FREEZE_PER_TICK = 7;
|
private static final int ICE_FREEZE_PER_TICK = 7;
|
||||||
private static final int BEHAVIOR_SCORE_CAP = 12;
|
private static final int BEHAVIOR_SCORE_CAP = 12;
|
||||||
/** Keep the tree-bound patrol safely inside the authored tree footprint. */
|
|
||||||
private static final double TREE_ORBIT_RADIUS = 128.0D;
|
private static final double TREE_ORBIT_RADIUS = 128.0D;
|
||||||
private static final double TREE_ORBIT_ANGLE_STEP = 0.014D;
|
private static final double TREE_ORBIT_ANGLE_STEP = 0.014D;
|
||||||
private static final int TREE_ORBIT_PATH_SAMPLES = 16;
|
private static final int TREE_ORBIT_PATH_SAMPLES = 16;
|
||||||
@@ -994,8 +993,6 @@ public class KingEntity extends RoyalBossEntity {
|
|||||||
this.kingCombatWaypoint = null;
|
this.kingCombatWaypoint = null;
|
||||||
this.playRoyalSound(AntarchySoundEvents.KING_ROAR.get(), 1.12F);
|
this.playRoyalSound(AntarchySoundEvents.KING_ROAR.get(), 1.12F);
|
||||||
} else {
|
} else {
|
||||||
// Keep Close Quarters from silently dissolving when the first ring is obstructed.
|
|
||||||
// The next aerial tick will retry the expanded landing search.
|
|
||||||
this.kingLandingWaypoint = null;
|
this.kingLandingWaypoint = null;
|
||||||
this.groundAssaultCooldownTicks = 100;
|
this.groundAssaultCooldownTicks = 100;
|
||||||
this.kingLandingRetryTicks = LANDING_RETRY_TICKS;
|
this.kingLandingRetryTicks = LANDING_RETRY_TICKS;
|
||||||
@@ -1077,9 +1074,6 @@ public class KingEntity extends RoyalBossEntity {
|
|||||||
if (this.level().noCollision(this, fallbackBox)) {
|
if (this.level().noCollision(this, fallbackBox)) {
|
||||||
return fallback;
|
return fallback;
|
||||||
}
|
}
|
||||||
// Last resort: land directly beneath the King if the target ring is obstructed.
|
|
||||||
// This still gives Close Quarters a committed ground sequence instead of silently
|
|
||||||
// remaining airborne over difficult tree geometry.
|
|
||||||
double directY = GravityApi.isGravityInverted(this)
|
double directY = GravityApi.isGravityInverted(this)
|
||||||
? this.position().y - 0.1D
|
? this.position().y - 0.1D
|
||||||
: this.groundYBelow(this.getX(), this.getZ()) + 0.1D;
|
: this.groundYBelow(this.getX(), this.getZ()) + 0.1D;
|
||||||
@@ -1143,8 +1137,6 @@ public class KingEntity extends RoyalBossEntity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (orbitWaypoint == null && treeBoundCombat) {
|
if (orbitWaypoint == null && treeBoundCombat) {
|
||||||
// If the tree blocks the next orbital lane, turn away and try the opposite side
|
|
||||||
// before falling back to a clear target-relative position.
|
|
||||||
this.kingStrafeDirection *= -1;
|
this.kingStrafeDirection *= -1;
|
||||||
double angle = currentAngle + this.kingStrafeDirection * COMBAT_ORBIT_ANGLE_STEP;
|
double angle = currentAngle + this.kingStrafeDirection * COMBAT_ORBIT_ANGLE_STEP;
|
||||||
double x = target.getX() + Math.cos(angle) * range;
|
double x = target.getX() + Math.cos(angle) * range;
|
||||||
@@ -1173,7 +1165,6 @@ public class KingEntity extends RoyalBossEntity {
|
|||||||
+ this.random.nextInt(COMBAT_WAYPOINT_VARIANCE + 1);
|
+ this.random.nextInt(COMBAT_WAYPOINT_VARIANCE + 1);
|
||||||
this.kingCombatProgressPosition = this.position();
|
this.kingCombatProgressPosition = this.position();
|
||||||
this.kingCombatProgressTicks = 0;
|
this.kingCombatProgressTicks = 0;
|
||||||
// Keep a consistent orbit direction for several passes so movement reads as circling.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stabilizeKingRotation() {
|
private void stabilizeKingRotation() {
|
||||||
|
|||||||
-1
@@ -248,7 +248,6 @@ public class RoyalBlackHoleEntity extends Entity implements GeoEntity, TimeDilat
|
|||||||
return AntarchySettings.queenBlackHoleBlockSuctionCap();
|
return AntarchySettings.queenBlackHoleBlockSuctionCap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the center of the animated black-hole cube in world coordinates. */
|
|
||||||
@Override
|
@Override
|
||||||
public Vec3 timeDilationCenter() {
|
public Vec3 timeDilationCenter() {
|
||||||
return this.effectCenter();
|
return this.effectCenter();
|
||||||
|
|||||||
-8
@@ -344,7 +344,6 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
|
|||||||
return 0.35D;
|
return 0.35D;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Lets a boss provide a bespoke air/ground cadence without changing the other royal encounter. */
|
|
||||||
protected boolean managesOwnCombatLocomotion() {
|
protected boolean managesOwnCombatLocomotion() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -357,12 +356,10 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
|
|||||||
return 1.3D;
|
return 1.3D;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Prevents normal head/body scheduling while a bespoke movement sequence owns the boss. */
|
|
||||||
protected boolean blocksRoyalAttacksForMovement() {
|
protected boolean blocksRoyalAttacksForMovement() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Prevents new beam volleys while a bespoke attack has reserved the heads. */
|
|
||||||
protected boolean blocksRoyalBeamScheduling() {
|
protected boolean blocksRoyalBeamScheduling() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -380,17 +377,14 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
|
|||||||
protected void onRoyalPhaseTransitionCompleted(Phase nextPhase) {
|
protected void onRoyalPhaseTransitionCompleted(Phase nextPhase) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Allows a boss to tune its head-bite concurrency without changing the other royal boss. */
|
|
||||||
protected int maxConcurrentHeadAttacks(Phase phase) {
|
protected int maxConcurrentHeadAttacks(Phase phase) {
|
||||||
return phase.maxConcurrentHeadAttacks();
|
return phase.maxConcurrentHeadAttacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Allows a boss to tune bite pacing without changing the other royal boss. */
|
|
||||||
protected int biteCooldownTicks(Phase phase) {
|
protected int biteCooldownTicks(Phase phase) {
|
||||||
return Math.max(10, Mth.floor(AntarchySettings.royalBossBiteCooldownTicks() * phase.cooldownScale()));
|
return Math.max(10, Mth.floor(AntarchySettings.royalBossBiteCooldownTicks() * phase.cooldownScale()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Allows either royal boss to tune bite damage without changing the other. */
|
|
||||||
protected double biteDamageMultiplier() {
|
protected double biteDamageMultiplier() {
|
||||||
return AntarchySettings.royalBossBiteDamageMultiplier();
|
return AntarchySettings.royalBossBiteDamageMultiplier();
|
||||||
}
|
}
|
||||||
@@ -825,7 +819,6 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
|
|||||||
return phase.maxConcurrentHeadAttacks();
|
return phase.maxConcurrentHeadAttacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Uses the beam controller's smoothed target point instead of the boss body's forward axis. */
|
|
||||||
protected boolean royalBeamUsesTrackedAim() {
|
protected boolean royalBeamUsesTrackedAim() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -862,7 +855,6 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
|
|||||||
this.onRoyalPhaseTransitionStarted(previousPhase, nextPhase);
|
this.onRoyalPhaseTransitionStarted(previousPhase, nextPhase);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the live players currently participating in the encounter. */
|
|
||||||
protected final List<ServerPlayer> royalEncounterPlayers(ServerLevel level) {
|
protected final List<ServerPlayer> royalEncounterPlayers(ServerLevel level) {
|
||||||
double range = Math.max(32.0D, this.getAttributeValue(Attributes.FOLLOW_RANGE));
|
double range = Math.max(32.0D, this.getAttributeValue(Attributes.FOLLOW_RANGE));
|
||||||
LinkedHashSet<ServerPlayer> players = new LinkedHashSet<>(this.bossEvent.getPlayers());
|
LinkedHashSet<ServerPlayer> players = new LinkedHashSet<>(this.bossEvent.getPlayers());
|
||||||
|
|||||||
-1
@@ -68,7 +68,6 @@ public class RoyalElementalProjectileEntity extends ThrowableProjectile implemen
|
|||||||
return projectile;
|
return projectile;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Solves a discrete ballistic lead against the projectile's drag and gravity. */
|
|
||||||
public static Vec3 aimDirection(Vec3 origin, LivingEntity target, RoyalBeamElement element) {
|
public static Vec3 aimDirection(Vec3 origin, LivingEntity target, RoyalBeamElement element) {
|
||||||
double speed = element == RoyalBeamElement.ICE ? ICEBALL_SPEED : FIREBALL_SPEED;
|
double speed = element == RoyalBeamElement.ICE ? ICEBALL_SPEED : FIREBALL_SPEED;
|
||||||
double gravity = element == RoyalBeamElement.ICE ? 0.006D : 0.018D;
|
double gravity = element == RoyalBeamElement.ICE ? 0.006D : 0.018D;
|
||||||
|
|||||||
-1
@@ -15,7 +15,6 @@ public final class StandYourGroundDecree implements RoyalDecree {
|
|||||||
}
|
}
|
||||||
@Override public Evaluation evaluate(ServerLevel level, KingEntity king, LivingEntity target) {
|
@Override public Evaluation evaluate(ServerLevel level, KingEntity king, LivingEntity target) {
|
||||||
if (target instanceof net.minecraft.server.level.ServerPlayer player && player.isFallFlying()) {
|
if (target instanceof net.minecraft.server.level.ServerPlayer player && player.isFallFlying()) {
|
||||||
// Gliding carries unavoidable momentum; begin measuring again from the landing point.
|
|
||||||
this.anchors.put(target.getUUID(), target.position());
|
this.anchors.put(target.getUUID(), target.position());
|
||||||
return Evaluation.COMPLIANT;
|
return Evaluation.COMPLIANT;
|
||||||
}
|
}
|
||||||
|
|||||||
-1
@@ -20,7 +20,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/** Loads Computer Scientist offers from data/computer_scientist_trades/*.json. */
|
|
||||||
public final class ComputerScientistTradeManager extends SimpleJsonResourceReloadListener {
|
public final class ComputerScientistTradeManager extends SimpleJsonResourceReloadListener {
|
||||||
private static final Gson GSON = new Gson();
|
private static final Gson GSON = new Gson();
|
||||||
private static final String DIRECTORY = "computer_scientist_trades";
|
private static final String DIRECTORY = "computer_scientist_trades";
|
||||||
|
|||||||
-8
@@ -113,13 +113,6 @@ public final class DrTrayaurusTradeManager extends SimpleJsonResourceReloadListe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* One side of a trade. {@code components} is optional: on {@code sell} it is a data component
|
|
||||||
* patch applied to the result (enchantments, custom name, ...); on {@code buy}/{@code second_buy}
|
|
||||||
* it is a component predicate the offered stack must match exactly for each listed component.
|
|
||||||
* It is kept as raw JSON and parsed per offer because components such as enchantments need
|
|
||||||
* registry access, which the reload listener does not have.
|
|
||||||
*/
|
|
||||||
private record StackEntry(ResourceLocation itemId, int count, Optional<JsonElement> components) {
|
private record StackEntry(ResourceLocation itemId, int count, Optional<JsonElement> components) {
|
||||||
private static final Codec<StackEntry> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
private static final Codec<StackEntry> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||||
ResourceLocation.CODEC.fieldOf("item").forGetter(StackEntry::itemId),
|
ResourceLocation.CODEC.fieldOf("item").forGetter(StackEntry::itemId),
|
||||||
@@ -162,7 +155,6 @@ public final class DrTrayaurusTradeManager extends SimpleJsonResourceReloadListe
|
|||||||
if (this.components.isEmpty()) {
|
if (this.components.isEmpty()) {
|
||||||
return Optional.of(new ItemCost(item.get(), this.count));
|
return Optional.of(new ItemCost(item.get(), this.count));
|
||||||
}
|
}
|
||||||
// A predicate that fails to parse drops the trade rather than accepting any stack.
|
|
||||||
return DataComponentPredicate.CODEC
|
return DataComponentPredicate.CODEC
|
||||||
.parse(RegistryOps.create(JsonOps.INSTANCE, registries), this.components.get())
|
.parse(RegistryOps.create(JsonOps.INSTANCE, registries), this.components.get())
|
||||||
.resultOrPartial(message -> LOGGER.error("Dr. Trayaurus trade {}: bad components: {}", this.itemId, message))
|
.resultOrPartial(message -> LOGGER.error("Dr. Trayaurus trade {}: bad components: {}", this.itemId, message))
|
||||||
|
|||||||
-5
@@ -51,11 +51,6 @@ public final class AntarchyFluidChecks {
|
|||||||
return BILE_VEIN_ID.equals(blockId);
|
return BILE_VEIN_ID.equals(blockId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Bile always wins: worldgen foliage must not anchor on or near bile fluid or its solid
|
|
||||||
* bile_vein shell, since cyst/vein features can carve into a neighboring chunk after this
|
|
||||||
* chunk's vegetation has already been placed.
|
|
||||||
*/
|
|
||||||
public static boolean hasBileNearby(LevelAccessor level, BlockPos center, int radius) {
|
public static boolean hasBileNearby(LevelAccessor level, BlockPos center, int radius) {
|
||||||
BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
|
BlockPos.MutableBlockPos mutable = new BlockPos.MutableBlockPos();
|
||||||
for (int dx = -radius; dx <= radius; dx++) {
|
for (int dx = -radius; dx <= radius; dx++) {
|
||||||
|
|||||||
-9
@@ -21,15 +21,6 @@ import net.minecraft.world.phys.AABB;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
|
||||||
* Tops up stink bug / rolly polly populations near players in Cavaryn.
|
|
||||||
*
|
|
||||||
* Vanilla's NaturalSpawner picks a spawn Y uniformly at random between the dimension's min_y
|
|
||||||
* and a column's heightmap top. In Cavaryn that range spans the full 208-block dimension height,
|
|
||||||
* but any given column's actual floor only occupies a sliver of that, so the vanilla algorithm
|
|
||||||
* almost never lands on real ground even though floor itself is common. This scans a column
|
|
||||||
* directly for a real floor spot instead.
|
|
||||||
*/
|
|
||||||
public final class CavarynCreatureSpawner {
|
public final class CavarynCreatureSpawner {
|
||||||
private static final ResourceKey<Level> CAVARYN = ResourceKey.create(
|
private static final ResourceKey<Level> CAVARYN = ResourceKey.create(
|
||||||
net.minecraft.core.registries.Registries.DIMENSION,
|
net.minecraft.core.registries.Registries.DIMENSION,
|
||||||
|
|||||||
+1
-2
@@ -70,7 +70,6 @@ public class BigBerthaItem extends SwordItem implements GeoItem {
|
|||||||
private static final int TORETERROR_COOLDOWN_TICKS = 200;
|
private static final int TORETERROR_COOLDOWN_TICKS = 200;
|
||||||
private static final int TORETERROR_SHAKE_TICKS = 25;
|
private static final int TORETERROR_SHAKE_TICKS = 25;
|
||||||
|
|
||||||
/** Client-side only: how many ticks of camera shake remain from a Toreterror landing. */
|
|
||||||
public static int clientShakeTicks = 0;
|
public static int clientShakeTicks = 0;
|
||||||
private static final ResourceLocation ATTACK_RANGE_MODIFIER_ID = ResourceLocation.fromNamespaceAndPath("antarchy", "big_bertha_attack_range");
|
private static final ResourceLocation ATTACK_RANGE_MODIFIER_ID = ResourceLocation.fromNamespaceAndPath("antarchy", "big_bertha_attack_range");
|
||||||
private final Tier tier;
|
private final Tier tier;
|
||||||
@@ -178,7 +177,7 @@ public class BigBerthaItem extends SwordItem implements GeoItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isToreterrorJumping(stack) && player.getMainHandItem() == stack) {
|
if (isToreterrorJumping(stack) && player.getMainHandItem() == stack) {
|
||||||
player.fallDistance = 0.0F; // prevent fall damage during the crash-down
|
player.fallDistance = 0.0F;
|
||||||
boolean launched = readInt(stack, TORETERROR_LAUNCHED_TAG) == 1;
|
boolean launched = readInt(stack, TORETERROR_LAUNCHED_TAG) == 1;
|
||||||
if (!launched && !player.onGround()) {
|
if (!launched && !player.onGround()) {
|
||||||
CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> tag.putInt(TORETERROR_LAUNCHED_TAG, 1));
|
CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> tag.putInt(TORETERROR_LAUNCHED_TAG, 1));
|
||||||
|
|||||||
-1
@@ -38,7 +38,6 @@ public class BloodCrystalShardItem extends Item {
|
|||||||
return InteractionResultHolder.fail(stack);
|
return InteractionResultHolder.fail(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore armor shields first, then apple shields
|
|
||||||
if (armorLost > 0) {
|
if (armorLost > 0) {
|
||||||
access.antarchy$setArmorShieldsActive(access.antarchy$getArmorShieldsActive() + 1);
|
access.antarchy$setArmorShieldsActive(access.antarchy$getArmorShieldsActive() + 1);
|
||||||
access.antarchy$setArmorShieldLostCount(armorLost - 1);
|
access.antarchy$setArmorShieldLostCount(armorLost - 1);
|
||||||
|
|||||||
-1
@@ -22,7 +22,6 @@ public final class BrutalflyElytraItem extends ElytraItem {
|
|||||||
private static final ResourceLocation ARMOR_MODIFIER_ID = ResourceLocation.fromNamespaceAndPath("antarchy", "brutalfly_elytra_armor");
|
private static final ResourceLocation ARMOR_MODIFIER_ID = ResourceLocation.fromNamespaceAndPath("antarchy", "brutalfly_elytra_armor");
|
||||||
private static final ResourceLocation TOUGHNESS_MODIFIER_ID = ResourceLocation.fromNamespaceAndPath("antarchy", "brutalfly_elytra_toughness");
|
private static final ResourceLocation TOUGHNESS_MODIFIER_ID = ResourceLocation.fromNamespaceAndPath("antarchy", "brutalfly_elytra_toughness");
|
||||||
|
|
||||||
// Set by NeoForge client setup to return the actual bound key name
|
|
||||||
public static Supplier<Component> FLAP_KEY_NAME = () -> Component.literal("Shift");
|
public static Supplier<Component> FLAP_KEY_NAME = () -> Component.literal("Shift");
|
||||||
|
|
||||||
public BrutalflyElytraItem(Properties properties) {
|
public BrutalflyElytraItem(Properties properties) {
|
||||||
|
|||||||
@@ -377,8 +377,6 @@ public class GravityGunItem extends Item implements GeoItem {
|
|||||||
Vec2 holdRotation = getHoldRotation(player);
|
Vec2 holdRotation = getHoldRotation(player);
|
||||||
heldTarget.setNoGravity(true);
|
heldTarget.setNoGravity(true);
|
||||||
|
|
||||||
// Snap back only when the held entity has drifted badly; otherwise drive it with
|
|
||||||
// velocity so the client can interpolate the motion smoothly between server updates.
|
|
||||||
if (movement.lengthSqr() > 16.0D) {
|
if (movement.lengthSqr() > 16.0D) {
|
||||||
heldTarget.moveTo(holdPosition.x, holdPosition.y, holdPosition.z, holdRotation.x, holdRotation.y);
|
heldTarget.moveTo(holdPosition.x, holdPosition.y, holdPosition.z, holdRotation.x, holdRotation.y);
|
||||||
heldTarget.setDeltaMovement(Vec3.ZERO);
|
heldTarget.setDeltaMovement(Vec3.ZERO);
|
||||||
|
|||||||
+2
-15
@@ -11,20 +11,10 @@ import java.util.HashSet;
|
|||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
|
||||||
* Client-side cave finder for Moggles.
|
|
||||||
*
|
|
||||||
* <p>Every {@link #SCAN_INTERVAL} ticks, BFS-maps the player's current connected
|
|
||||||
* air space, then scans outward to find the nearest underground air pocket that
|
|
||||||
* is NOT part of that space. The result is stored in {@link #caveTarget} and
|
|
||||||
* read each tick by the particle renderer.
|
|
||||||
*/
|
|
||||||
public final class MogglesCaveDetector {
|
public final class MogglesCaveDetector {
|
||||||
|
|
||||||
private static final int SCAN_INTERVAL = 40;
|
private static final int SCAN_INTERVAL = 40;
|
||||||
/** How far to flood-fill the player's own air pocket before stopping. */
|
|
||||||
private static final int PLAYER_SPACE_LIMIT = 8;
|
private static final int PLAYER_SPACE_LIMIT = 8;
|
||||||
/** Minimum number of air neighbors a candidate block must have (filters tiny cracks). */
|
|
||||||
private static final int MIN_AIR_NEIGHBORS = 2;
|
private static final int MIN_AIR_NEIGHBORS = 2;
|
||||||
|
|
||||||
private static volatile BlockPos caveTarget = null;
|
private static volatile BlockPos caveTarget = null;
|
||||||
@@ -36,7 +26,6 @@ public final class MogglesCaveDetector {
|
|||||||
return caveTarget;
|
return caveTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Call once per client tick while Moggles are equipped. */
|
|
||||||
public static void tick(Player player, Level level) {
|
public static void tick(Player player, Level level) {
|
||||||
if (--cooldown > 0) return;
|
if (--cooldown > 0) return;
|
||||||
cooldown = SCAN_INTERVAL;
|
cooldown = SCAN_INTERVAL;
|
||||||
@@ -51,11 +40,10 @@ public final class MogglesCaveDetector {
|
|||||||
private static BlockPos scan(Player player, Level level) {
|
private static BlockPos scan(Player player, Level level) {
|
||||||
BlockPos origin = player.blockPosition();
|
BlockPos origin = player.blockPosition();
|
||||||
|
|
||||||
// BFS through air from the player's feet to map their current open space.
|
|
||||||
Set<Long> playerSpace = new HashSet<>();
|
Set<Long> playerSpace = new HashSet<>();
|
||||||
Queue<BlockPos> queue = new ArrayDeque<>();
|
Queue<BlockPos> queue = new ArrayDeque<>();
|
||||||
|
|
||||||
BlockPos eyePos = origin.above(); // also include the eye block
|
BlockPos eyePos = origin.above();
|
||||||
for (BlockPos seed : new BlockPos[]{origin, eyePos}) {
|
for (BlockPos seed : new BlockPos[]{origin, eyePos}) {
|
||||||
if (level.isLoaded(seed) && level.getBlockState(seed).isAir()) {
|
if (level.isLoaded(seed) && level.getBlockState(seed).isAir()) {
|
||||||
long key = seed.asLong();
|
long key = seed.asLong();
|
||||||
@@ -77,7 +65,6 @@ public final class MogglesCaveDetector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan the wider radius for underground air NOT in the player's space.
|
|
||||||
BlockPos nearest = null;
|
BlockPos nearest = null;
|
||||||
double nearestDistSq = Double.MAX_VALUE;
|
double nearestDistSq = Double.MAX_VALUE;
|
||||||
int r = (int) AntarchySettings.mogglesVisionRadius();
|
int r = (int) AntarchySettings.mogglesVisionRadius();
|
||||||
@@ -91,7 +78,7 @@ public final class MogglesCaveDetector {
|
|||||||
if (playerSpace.contains(key)) continue;
|
if (playerSpace.contains(key)) continue;
|
||||||
if (!level.isLoaded(pos)) continue;
|
if (!level.isLoaded(pos)) continue;
|
||||||
if (!level.getBlockState(pos).isAir()) continue;
|
if (!level.getBlockState(pos).isAir()) continue;
|
||||||
if (level.canSeeSky(pos)) continue; // ignore surface air
|
if (level.canSeeSky(pos)) continue;
|
||||||
|
|
||||||
int airNeighbors = 0;
|
int airNeighbors = 0;
|
||||||
for (Direction dir : Direction.values()) {
|
for (Direction dir : Direction.values()) {
|
||||||
|
|||||||
+1
-1
@@ -122,6 +122,6 @@ public class RoyalGuardianShieldItem extends ShieldItem {
|
|||||||
|
|
||||||
private static boolean isInCommandLookCone(Player player, Mob mob) {
|
private static boolean isInCommandLookCone(Player player, Mob mob) {
|
||||||
var direction = mob.getBoundingBox().getCenter().subtract(player.getEyePosition()).normalize();
|
var direction = mob.getBoundingBox().getCenter().subtract(player.getEyePosition()).normalize();
|
||||||
return player.getViewVector(1.0F).dot(direction) >= 0.9063078D; // 25-degree half-angle
|
return player.getViewVector(1.0F).dot(direction) >= 0.9063078D;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
-1
@@ -31,7 +31,6 @@ import net.minecraft.world.phys.AABB;
|
|||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
/** Player-safe kernels for the Royal Guardian Sword's King-derived elemental modes. */
|
|
||||||
public final class RoyalGuardianSwordAbilities {
|
public final class RoyalGuardianSwordAbilities {
|
||||||
private static final ThreadLocal<Integer> SECONDARY_DAMAGE_DEPTH = ThreadLocal.withInitial(() -> 0);
|
private static final ThreadLocal<Integer> SECONDARY_DAMAGE_DEPTH = ThreadLocal.withInitial(() -> 0);
|
||||||
private static final ThreadLocal<MeleeAttackContext> MELEE_ATTACK = new ThreadLocal<>();
|
private static final ThreadLocal<MeleeAttackContext> MELEE_ATTACK = new ThreadLocal<>();
|
||||||
|
|||||||
+1
-3
@@ -31,7 +31,7 @@ import java.util.List;
|
|||||||
|
|
||||||
public class UltimateCrossbowItem extends CrossbowItem {
|
public class UltimateCrossbowItem extends CrossbowItem {
|
||||||
private static final int MAX_ARROWS = 16;
|
private static final int MAX_ARROWS = 16;
|
||||||
private static final int FIRE_COOLDOWN_TICKS = 5; // 4 shots/sec
|
private static final int FIRE_COOLDOWN_TICKS = 5;
|
||||||
private static final float SHOOTING_POWER = 3.15F;
|
private static final float SHOOTING_POWER = 3.15F;
|
||||||
private static final double VANILLA_CROSSBOW_ARROW_DAMAGE = 7.0D;
|
private static final double VANILLA_CROSSBOW_ARROW_DAMAGE = 7.0D;
|
||||||
private static final String RESERVE_PROJECTILES_TAG = "UltimateCrossbowProjectiles";
|
private static final String RESERVE_PROJECTILES_TAG = "UltimateCrossbowProjectiles";
|
||||||
@@ -110,11 +110,9 @@ public class UltimateCrossbowItem extends CrossbowItem {
|
|||||||
toFire.add(arrow);
|
toFire.add(arrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temporarily set only the arrows for this shot so performShooting fires exactly them
|
|
||||||
stack.set(DataComponents.CHARGED_PROJECTILES, ChargedProjectiles.of(toFire));
|
stack.set(DataComponents.CHARGED_PROJECTILES, ChargedProjectiles.of(toFire));
|
||||||
this.performShooting(level, player, hand, stack, SHOOTING_POWER, 1.0F, null);
|
this.performShooting(level, player, hand, stack, SHOOTING_POWER, 1.0F, null);
|
||||||
|
|
||||||
// performShooting clears CHARGED_PROJECTILES; restore remaining valid arrows if any
|
|
||||||
saveLoadedProjectiles(stack, player.registryAccess(), all);
|
saveLoadedProjectiles(stack, player.registryAccess(), all);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-11
@@ -17,17 +17,6 @@ import net.minecraft.world.level.block.state.properties.RailShape;
|
|||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
|
||||||
* A direct mirror of {@code AbstractMinecart.moveAlongTrack}/{@code getPos}/{@code getPosOffs},
|
|
||||||
* adapted for ceiling-mounted track. The world-Y meaning of "ascending"/"descending" does not
|
|
||||||
* need to be sign-flipped anywhere here — lower world Y is lower world Y whether a rail rests on
|
|
||||||
* a floor or hangs from a ceiling. What actually differs from vanilla is: the rail sits near the
|
|
||||||
* top of its cell instead of near the bottom (see {@link AntimetalRailHelper#attachY}), support
|
|
||||||
* is required above instead of below, and the "which cell owns this position" disambiguation
|
|
||||||
* checks the cell above instead of the cell below. Everything else — the exit-projection math,
|
|
||||||
* the slope acceleration constant, the player-push nudge, using real collision-checked
|
|
||||||
* {@code Entity.move} rather than a hand-rolled collision test — is a straight port.
|
|
||||||
*/
|
|
||||||
public final class AntimetalMinecartPhysics {
|
public final class AntimetalMinecartPhysics {
|
||||||
private static final double SLOPE_ACCEL = 0.0078125D;
|
private static final double SLOPE_ACCEL = 0.0078125D;
|
||||||
private static final double MAX_RAIL_SPEED = 0.4D;
|
private static final double MAX_RAIL_SPEED = 0.4D;
|
||||||
|
|||||||
-1
@@ -8,7 +8,6 @@ import net.minecraft.server.level.ServerLevel;
|
|||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
|
||||||
/** Handles Antarchy-specific game progress sent by AntOS game extensions. */
|
|
||||||
public final class AntarchyGameNetworkHandler {
|
public final class AntarchyGameNetworkHandler {
|
||||||
private static BiConsumer<ServerPlayer, AntarchyGameResultPayload> resultSender = (player, result) -> { };
|
private static BiConsumer<ServerPlayer, AntarchyGameResultPayload> resultSender = (player, result) -> { };
|
||||||
|
|
||||||
|
|||||||
-1
@@ -3,7 +3,6 @@ package com.craisinlord.antarchy.content.network;
|
|||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/** Small Antarchy game-progress bridge over the AntOS computer session. */
|
|
||||||
public final class AntarchyGameNetworking {
|
public final class AntarchyGameNetworking {
|
||||||
private static Consumer<AntarchyGamePayload> sender = payload -> { };
|
private static Consumer<AntarchyGamePayload> sender = payload -> { };
|
||||||
private AntarchyGameNetworking() { }
|
private AntarchyGameNetworking() { }
|
||||||
|
|||||||
-6
@@ -13,12 +13,6 @@ import net.minecraft.world.phys.AABB;
|
|||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts an unlit obsidian frame near a killed rainbow ant into a real, permanent Infinite Dimensions
|
|
||||||
* portal to that ant's assigned dimension. Lights the frame as a normal vanilla Nether portal first, then
|
|
||||||
* hands it to Infinity's own portal-creation pipeline (the same one used when a book is thrown into a lit
|
|
||||||
* portal), so the result behaves exactly like any other physical Infinity portal from then on.
|
|
||||||
*/
|
|
||||||
public final class RainbowPortalIgniter {
|
public final class RainbowPortalIgniter {
|
||||||
private static final int SEARCH_RADIUS = 2;
|
private static final int SEARCH_RADIUS = 2;
|
||||||
|
|
||||||
|
|||||||
-1
@@ -170,7 +170,6 @@ public final class PortalGunSavedData extends SavedData {
|
|||||||
return clearMatching(server, record -> record.ownerId() != null && ownerIds.contains(record.ownerId()));
|
return clearMatching(server, record -> record.ownerId() != null && ownerIds.contains(record.ownerId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Clears portal pairs for guns that an owner no longer has in their player inventory. */
|
|
||||||
public static int clearMissingGuns(ServerPlayer player) {
|
public static int clearMissingGuns(ServerPlayer player) {
|
||||||
PortalGunSavedData data = get(player.serverLevel().getServer());
|
PortalGunSavedData data = get(player.serverLevel().getServer());
|
||||||
if (data.pairs.isEmpty()) {
|
if (data.pairs.isEmpty()) {
|
||||||
|
|||||||
@@ -12,16 +12,6 @@ import net.minecraft.world.phys.Vec3;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
|
||||||
* Tracks the path of a taut rope from a fixed anchor point to a moving end point (the
|
|
||||||
* player's eyes), bending around block corners when the straight-line path would otherwise
|
|
||||||
* clip through terrain. The anchor never moves (the worm hook is stuck in a block), so this
|
|
||||||
* only needs to add/remove bends on the player's side of the rope.
|
|
||||||
*
|
|
||||||
* Ported from the corner-wrapping algorithm in Yyon's GrappleMod (GPL-3.0), adapted from a
|
|
||||||
* custom vector class to vanilla Vec3 and from a moving-hook/moving-player pair to a fixed
|
|
||||||
* anchor.
|
|
||||||
*/
|
|
||||||
public final class WormHookRope {
|
public final class WormHookRope {
|
||||||
private static final double BEND_OFFSET = 0.05D;
|
private static final double BEND_OFFSET = 0.05D;
|
||||||
private static final double INTO_BLOCK = 0.05D;
|
private static final double INTO_BLOCK = 0.05D;
|
||||||
@@ -44,7 +34,6 @@ public final class WormHookRope {
|
|||||||
this.prevEnd = end;
|
this.prevEnd = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Recomputes the bend list for the current anchor/end positions. Anchor must stay constant. */
|
|
||||||
public void update(Entity context, Vec3 anchor, Vec3 end, double ropeLength) {
|
public void update(Entity context, Vec3 anchor, Vec3 end, double ropeLength) {
|
||||||
this.ropeLength = ropeLength;
|
this.ropeLength = ropeLength;
|
||||||
Level level = context.level();
|
Level level = context.level();
|
||||||
@@ -52,7 +41,6 @@ public final class WormHookRope {
|
|||||||
points.set(0, anchor);
|
points.set(0, anchor);
|
||||||
points.set(points.size() - 1, end);
|
points.set(points.size() - 1, end);
|
||||||
|
|
||||||
// Unwind bends the rope has swung clear of.
|
|
||||||
while (points.size() > 2) {
|
while (points.size() > 2) {
|
||||||
int index = points.size() - 2;
|
int index = points.size() - 2;
|
||||||
Vec3 closest = points.get(index);
|
Vec3 closest = points.get(index);
|
||||||
@@ -153,12 +141,10 @@ public final class WormHookRope {
|
|||||||
topSides.remove(index);
|
topSides.remove(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The pivot point closest to the moving end: either the anchor, or the last bend before it. */
|
|
||||||
public Vec3 getPivot() {
|
public Vec3 getPivot() {
|
||||||
return points.get(points.size() - 2);
|
return points.get(points.size() - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Rope length used up getting from the anchor to the pivot (0 if the rope has no bends). */
|
|
||||||
public double getConsumedLength() {
|
public double getConsumedLength() {
|
||||||
double dist = 0;
|
double dist = 0;
|
||||||
for (int i = 0; i < points.size() - 2; i++) {
|
for (int i = 0; i < points.size() - 2; i++) {
|
||||||
|
|||||||
-3
@@ -26,7 +26,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/** Applies Antarchy-owned additions to existing vanilla jigsaw pools without replacing them. */
|
|
||||||
public final class VillagePoolAdditions {
|
public final class VillagePoolAdditions {
|
||||||
private static final Gson GSON = new Gson();
|
private static final Gson GSON = new Gson();
|
||||||
private static final String DIRECTORY = "structure_pool_additions";
|
private static final String DIRECTORY = "structure_pool_additions";
|
||||||
@@ -101,8 +100,6 @@ public final class VillagePoolAdditions {
|
|||||||
templates.add(Pair.of(poolElement, weight));
|
templates.add(Pair.of(poolElement, weight));
|
||||||
accessor.integratedapi_setRawTemplates(templates);
|
accessor.integratedapi_setRawTemplates(templates);
|
||||||
|
|
||||||
// StructureTemplatePool caches its weighted list in addition to the raw entries.
|
|
||||||
// Keep both views synchronized so the new house is immediately eligible.
|
|
||||||
ObjectArrayList<StructurePoolElement> expandedTemplates = new ObjectArrayList<>(accessor.integratedapi_getTemplates());
|
ObjectArrayList<StructurePoolElement> expandedTemplates = new ObjectArrayList<>(accessor.integratedapi_getTemplates());
|
||||||
for (int i = 0; i < weight; i++) {
|
for (int i = 0; i < weight; i++) {
|
||||||
expandedTemplates.add(poolElement);
|
expandedTemplates.add(poolElement);
|
||||||
|
|||||||
-1
@@ -34,7 +34,6 @@ public class TermiteNestFeature extends SurfaceAntNestFeature {
|
|||||||
protected BlockPos resolveNestPos(WorldGenLevel level, BlockPos origin) {
|
protected BlockPos resolveNestPos(WorldGenLevel level, BlockPos origin) {
|
||||||
int x = origin.getX();
|
int x = origin.getX();
|
||||||
int z = origin.getZ();
|
int z = origin.getZ();
|
||||||
// Start from the placement height so roofed dimensions like Cavaryn get nests on every cave layer, not just the top one.
|
|
||||||
int startY = Math.min(origin.getY(), level.getHeight(Heightmap.Types.WORLD_SURFACE_WG, x, z) - 1);
|
int startY = Math.min(origin.getY(), level.getHeight(Heightmap.Types.WORLD_SURFACE_WG, x, z) - 1);
|
||||||
int minY = level.getMinBuildHeight() + 1;
|
int minY = level.getMinBuildHeight() + 1;
|
||||||
|
|
||||||
|
|||||||
-6
@@ -8,12 +8,6 @@ import net.minecraft.world.level.LevelAccessor;
|
|||||||
import net.minecraft.world.level.block.VineBlock;
|
import net.minecraft.world.level.block.VineBlock;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
/**
|
|
||||||
* Bile always wins on placement, but once a vine/creeproots/molting-vine column already exists,
|
|
||||||
* bile carving and oozing must not eat the block it's anchored to — otherwise a later-generated
|
|
||||||
* neighboring chunk's bile cyst/vein can undermine foliage placed earlier and leave it floating
|
|
||||||
* or pop it as a dropped item.
|
|
||||||
*/
|
|
||||||
public final class CavarynFoliageGuard {
|
public final class CavarynFoliageGuard {
|
||||||
private CavarynFoliageGuard() {
|
private CavarynFoliageGuard() {
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-7
@@ -67,13 +67,13 @@ public class CoralSpikeFeature extends Feature<NoneFeatureConfiguration> {
|
|||||||
CoralSet[] coralSets = coralSets();
|
CoralSet[] coralSets = coralSets();
|
||||||
CoralSet coral = coralSets[random.nextInt(coralSets.length)];
|
CoralSet coral = coralSets[random.nextInt(coralSets.length)];
|
||||||
|
|
||||||
int baseRadius = 2 + random.nextInt(2); // 2-3 wide at base
|
int baseRadius = 2 + random.nextInt(2);
|
||||||
int totalHeight = 20 + random.nextInt(15); // 20-34 blocks tall
|
int totalHeight = 20 + random.nextInt(15);
|
||||||
|
|
||||||
double curveAngle = random.nextDouble() * Math.PI * 2;
|
double curveAngle = random.nextDouble() * Math.PI * 2;
|
||||||
double curveDX = Math.cos(curveAngle);
|
double curveDX = Math.cos(curveAngle);
|
||||||
double curveDZ = Math.sin(curveAngle);
|
double curveDZ = Math.sin(curveAngle);
|
||||||
double maxCurve = 4.0 + random.nextDouble() * 5.0; // 4-9 block lean at tip
|
double maxCurve = 4.0 + random.nextDouble() * 5.0;
|
||||||
|
|
||||||
boolean placed = false;
|
boolean placed = false;
|
||||||
|
|
||||||
@@ -81,12 +81,10 @@ public class CoralSpikeFeature extends Feature<NoneFeatureConfiguration> {
|
|||||||
int blockY = floorY + dy;
|
int blockY = floorY + dy;
|
||||||
double progress = (double) dy / totalHeight;
|
double progress = (double) dy / totalHeight;
|
||||||
|
|
||||||
// Quadratic lean -- slow at base, bending hard near tip
|
|
||||||
double curveOffset = maxCurve * progress * progress;
|
double curveOffset = maxCurve * progress * progress;
|
||||||
double centerX = origin.getX() + curveDX * curveOffset;
|
double centerX = origin.getX() + curveDX * curveOffset;
|
||||||
double centerZ = origin.getZ() + curveDZ * curveOffset;
|
double centerZ = origin.getZ() + curveDZ * curveOffset;
|
||||||
|
|
||||||
// Taper: full width for bottom 25%, then narrows sharply to a point
|
|
||||||
double taperT = Math.max(0.0, (progress - 0.25) / 0.75);
|
double taperT = Math.max(0.0, (progress - 0.25) / 0.75);
|
||||||
int radius = (int) Math.max(0, baseRadius * (1.0 - taperT * taperT * 1.3));
|
int radius = (int) Math.max(0, baseRadius * (1.0 - taperT * taperT * 1.3));
|
||||||
|
|
||||||
@@ -147,7 +145,6 @@ public class CoralSpikeFeature extends Feature<NoneFeatureConfiguration> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Floor scatter: coral plants, fans, and sea pickles around the base
|
|
||||||
int decorCount = 10 + random.nextInt(12);
|
int decorCount = 10 + random.nextInt(12);
|
||||||
for (int i = 0; i < decorCount; i++) {
|
for (int i = 0; i < decorCount; i++) {
|
||||||
int fx = origin.getX() + random.nextInt(13) - 6;
|
int fx = origin.getX() + random.nextInt(13) - 6;
|
||||||
@@ -192,7 +189,6 @@ public class CoralSpikeFeature extends Feature<NoneFeatureConfiguration> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (decorInWater) {
|
} else if (decorInWater) {
|
||||||
// Sea pickle cluster -- only underwater
|
|
||||||
BlockState pickle = Blocks.SEA_PICKLE.defaultBlockState()
|
BlockState pickle = Blocks.SEA_PICKLE.defaultBlockState()
|
||||||
.setValue(SeaPickleBlock.PICKLES, 1 + random.nextInt(4));
|
.setValue(SeaPickleBlock.PICKLES, 1 + random.nextInt(4));
|
||||||
if (pickle.canSurvive(level, decorPos)) {
|
if (pickle.canSurvive(level, decorPos)) {
|
||||||
|
|||||||
-6
@@ -16,11 +16,6 @@ import net.minecraft.world.level.biome.BiomeSource;
|
|||||||
import net.minecraft.world.level.biome.Climate;
|
import net.minecraft.world.level.biome.Climate;
|
||||||
import net.minecraft.world.level.biome.MultiNoiseBiomeSource;
|
import net.minecraft.world.level.biome.MultiNoiseBiomeSource;
|
||||||
|
|
||||||
/**
|
|
||||||
* Plain multi-noise biome source with one addition: everything at or above
|
|
||||||
* {@code cloud_sea_min_y} is the cloud sea. Below that line, biome selection is
|
|
||||||
* identical to {@code minecraft:multi_noise} over the same list minus the cloud sea entry.
|
|
||||||
*/
|
|
||||||
public final class ElythiaBiomeSource extends BiomeSource {
|
public final class ElythiaBiomeSource extends BiomeSource {
|
||||||
private static final ResourceKey<Biome> CLOUD_SEA = ResourceKey.create(
|
private static final ResourceKey<Biome> CLOUD_SEA = ResourceKey.create(
|
||||||
Registries.BIOME,
|
Registries.BIOME,
|
||||||
@@ -47,7 +42,6 @@ public final class ElythiaBiomeSource extends BiomeSource {
|
|||||||
.filter(holder -> holder.is(CLOUD_SEA))
|
.filter(holder -> holder.is(CLOUD_SEA))
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
// Keep the cloud sea out of the noise search so terrain biomes resolve exactly as before.
|
|
||||||
this.delegate = MultiNoiseBiomeSource.createFromList(new Climate.ParameterList<>(
|
this.delegate = MultiNoiseBiomeSource.createFromList(new Climate.ParameterList<>(
|
||||||
parameters.values().stream()
|
parameters.values().stream()
|
||||||
.filter(entry -> !entry.getSecond().is(CLOUD_SEA))
|
.filter(entry -> !entry.getSecond().is(CLOUD_SEA))
|
||||||
|
|||||||
-7
@@ -10,10 +10,6 @@ import net.minecraft.world.level.levelgen.feature.Feature;
|
|||||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||||
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
|
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
|
||||||
|
|
||||||
/**
|
|
||||||
* Scatters solid puffs of {@link AntarchyObjects#CLOUD_BLOCK} sized and shaped
|
|
||||||
* anywhere from thin wispy veils to large, dense masses, with a softly feathered edge.
|
|
||||||
*/
|
|
||||||
public final class ElythiaCloudFeature extends Feature<NoneFeatureConfiguration> {
|
public final class ElythiaCloudFeature extends Feature<NoneFeatureConfiguration> {
|
||||||
public ElythiaCloudFeature(Codec<NoneFeatureConfiguration> codec) {
|
public ElythiaCloudFeature(Codec<NoneFeatureConfiguration> codec) {
|
||||||
super(codec);
|
super(codec);
|
||||||
@@ -76,9 +72,6 @@ public final class ElythiaCloudFeature extends Feature<NoneFeatureConfiguration>
|
|||||||
int yRange = Math.max(1, radiusY);
|
int yRange = Math.max(1, radiusY);
|
||||||
int zRange = Math.max(1, radiusZ);
|
int zRange = Math.max(1, radiusZ);
|
||||||
BlockState cloud = AntarchyObjects.CLOUD_BLOCK.get().defaultBlockState();
|
BlockState cloud = AntarchyObjects.CLOUD_BLOCK.get().defaultBlockState();
|
||||||
// Clouds are solid puffs, not hollow shells — only the outer rind is feathered for a
|
|
||||||
// soft, ragged edge. Wispy clouds get a lower edge-fill chance so they read as thin
|
|
||||||
// and sparse without turning the whole body into visible holes.
|
|
||||||
float edgeFillChance = size == CloudSize.WISPY ? 0.55F : 0.85F;
|
float edgeFillChance = size == CloudSize.WISPY ? 0.55F : 0.85F;
|
||||||
double edgeStart = 0.7D;
|
double edgeStart = 0.7D;
|
||||||
|
|
||||||
|
|||||||
-22
@@ -5,21 +5,6 @@ import com.mojang.serialization.codecs.RecordCodecBuilder;
|
|||||||
import net.minecraft.util.KeyDispatchDataCodec;
|
import net.minecraft.util.KeyDispatchDataCodec;
|
||||||
import net.minecraft.world.level.levelgen.DensityFunction;
|
import net.minecraft.world.level.levelgen.DensityFunction;
|
||||||
|
|
||||||
/**
|
|
||||||
* Custom density function that carves narrow river channels in Elythia.
|
|
||||||
*
|
|
||||||
* Logic:
|
|
||||||
* - Outside river-erosion territory (erosion <= EROSION_THRESHOLD): behaves identically
|
|
||||||
* to the original "-0.06 * erosion" term in elythia_surface.json.
|
|
||||||
* - Inside river-erosion territory (erosion > EROSION_THRESHOLD): additionally applies
|
|
||||||
* a strong negative carve when the ridges value is near 0, producing a narrow channel.
|
|
||||||
* The carve tapers quadratically from full depth at ridges=0 to zero at |ridges|=CHANNEL_HALF_WIDTH.
|
|
||||||
*
|
|
||||||
* Tuning:
|
|
||||||
* - EROSION_THRESHOLD: raise to make rivers rarer, lower to make them appear in more terrain
|
|
||||||
* - CHANNEL_HALF_WIDTH: controls channel width in blocks (wider noise band = wider river)
|
|
||||||
* - CHANNEL_DEPTH: controls how far below sea level the river floor sits
|
|
||||||
*/
|
|
||||||
public record ElythiaRiverCarveFunction(
|
public record ElythiaRiverCarveFunction(
|
||||||
DensityFunction erosion,
|
DensityFunction erosion,
|
||||||
DensityFunction ridges
|
DensityFunction ridges
|
||||||
@@ -35,16 +20,9 @@ public record ElythiaRiverCarveFunction(
|
|||||||
public static final KeyDispatchDataCodec<ElythiaRiverCarveFunction> KEY_CODEC =
|
public static final KeyDispatchDataCodec<ElythiaRiverCarveFunction> KEY_CODEC =
|
||||||
KeyDispatchDataCodec.of(CODEC);
|
KeyDispatchDataCodec.of(CODEC);
|
||||||
|
|
||||||
// Erosion must exceed this for river carving to engage
|
|
||||||
private static final double EROSION_THRESHOLD = 0.70;
|
private static final double EROSION_THRESHOLD = 0.70;
|
||||||
// Half-width of the channel in ridges-space. Ridges ranges roughly -1 to 1 across
|
|
||||||
// the landscape; this controls the physical width of the carved channel.
|
|
||||||
private static final double CHANNEL_HALF_WIDTH = 0.08;
|
private static final double CHANNEL_HALF_WIDTH = 0.08;
|
||||||
// Maximum density reduction applied at the center of the channel.
|
|
||||||
// ~0.35 pushes the terrain floor roughly 25 blocks below its normal level,
|
|
||||||
// landing below sea level (63) so the channel fills with water naturally.
|
|
||||||
private static final double CHANNEL_DEPTH = 0.35;
|
private static final double CHANNEL_DEPTH = 0.35;
|
||||||
// Matches the original elythia_surface.json erosion multiplier so non-river areas are unchanged
|
|
||||||
private static final double BASE_EROSION_FACTOR = -0.06;
|
private static final double BASE_EROSION_FACTOR = -0.06;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+2
-4
@@ -31,8 +31,8 @@ public class FallenOuranwoodFeature extends Feature<NoneFeatureConfiguration> {
|
|||||||
BlockPos origin = context.origin();
|
BlockPos origin = context.origin();
|
||||||
|
|
||||||
Direction.Axis axis = random.nextBoolean() ? Direction.Axis.X : Direction.Axis.Z;
|
Direction.Axis axis = random.nextBoolean() ? Direction.Axis.X : Direction.Axis.Z;
|
||||||
int length = 36 + random.nextInt(44); // 36–79 blocks long
|
int length = 36 + random.nextInt(44);
|
||||||
int outerRadius = 1 + random.nextInt(3); // 1–3 (cross-section up to 7-wide)
|
int outerRadius = 1 + random.nextInt(3);
|
||||||
boolean hollow = outerRadius >= 2;
|
boolean hollow = outerRadius >= 2;
|
||||||
|
|
||||||
Block ouranwoodLog = BuiltInRegistries.BLOCK.getOptional(
|
Block ouranwoodLog = BuiltInRegistries.BLOCK.getOptional(
|
||||||
@@ -46,7 +46,6 @@ public class FallenOuranwoodFeature extends Feature<NoneFeatureConfiguration> {
|
|||||||
BlockState woodState = AntarchyObjects.MOSSY_OURANWOOD_WOOD.get().defaultBlockState()
|
BlockState woodState = AntarchyObjects.MOSSY_OURANWOOD_WOOD.get().defaultBlockState()
|
||||||
.setValue(RotatedPillarBlock.AXIS, Direction.Axis.Y);
|
.setValue(RotatedPillarBlock.AXIS, Direction.Axis.Y);
|
||||||
|
|
||||||
// Pre-generate a smoothed damage profile along the length (0=solid, 1=gap)
|
|
||||||
float[] damage = new float[length];
|
float[] damage = new float[length];
|
||||||
for (int i = 0; i < length; i++) damage[i] = random.nextFloat();
|
for (int i = 0; i < length; i++) damage[i] = random.nextFloat();
|
||||||
for (int pass = 0; pass < 4; pass++) {
|
for (int pass = 0; pass < 4; pass++) {
|
||||||
@@ -54,7 +53,6 @@ public class FallenOuranwoodFeature extends Feature<NoneFeatureConfiguration> {
|
|||||||
damage[i] = (damage[i - 1] + damage[i] * 2 + damage[i + 1]) / 4f;
|
damage[i] = (damage[i - 1] + damage[i] * 2 + damage[i + 1]) / 4f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Bias upward so more sections are heavily damaged
|
|
||||||
for (int i = 0; i < length; i++) damage[i] = damage[i] * damage[i];
|
for (int i = 0; i < length; i++) damage[i] = damage[i] * damage[i];
|
||||||
|
|
||||||
int anchorY = level.getHeight(Heightmap.Types.WORLD_SURFACE_WG, origin.getX(), origin.getZ());
|
int anchorY = level.getHeight(Heightmap.Types.WORLD_SURFACE_WG, origin.getX(), origin.getZ());
|
||||||
|
|||||||
+1
-2
@@ -39,7 +39,7 @@ public class FungalMushroomFeature extends Feature<NoneFeatureConfiguration> {
|
|||||||
double maxLean = 2.0 + random.nextDouble() * 3.5;
|
double maxLean = 2.0 + random.nextDouble() * 3.5;
|
||||||
|
|
||||||
int baseY = origin.getY();
|
int baseY = origin.getY();
|
||||||
int stemOffset = stemSize == 2 ? 0 : -1; // center 3x3 on origin
|
int stemOffset = stemSize == 2 ? 0 : -1;
|
||||||
|
|
||||||
BlockState stemPore = Blocks.MUSHROOM_STEM.defaultBlockState()
|
BlockState stemPore = Blocks.MUSHROOM_STEM.defaultBlockState()
|
||||||
.setValue(HugeMushroomBlock.NORTH, false)
|
.setValue(HugeMushroomBlock.NORTH, false)
|
||||||
@@ -98,7 +98,6 @@ public class FungalMushroomFeature extends Feature<NoneFeatureConfiguration> {
|
|||||||
double nomRadius = baseCapRadius - cl;
|
double nomRadius = baseCapRadius - cl;
|
||||||
if (nomRadius < 0) break;
|
if (nomRadius < 0) break;
|
||||||
|
|
||||||
// The cap center also shifts slightly with lean for a drooping overhang feel
|
|
||||||
double layerCapX = capCenterX + leanDX * cl * 0.3;
|
double layerCapX = capCenterX + leanDX * cl * 0.3;
|
||||||
double layerCapZ = capCenterZ + leanDZ * cl * 0.3;
|
double layerCapZ = capCenterZ + leanDZ * cl * 0.3;
|
||||||
|
|
||||||
|
|||||||
-1
@@ -30,7 +30,6 @@ import java.util.Set;
|
|||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
|
||||||
/** Places the authored King's Tree as independently generated chunk slices on a fixed world grid. */
|
|
||||||
public final class KingsTreeGridFeature extends Feature<NoneFeatureConfiguration> {
|
public final class KingsTreeGridFeature extends Feature<NoneFeatureConfiguration> {
|
||||||
private static final Map<ServerLevel, Set<Long>> CLAIMED_TREE_KINGS = new WeakHashMap<>();
|
private static final Map<ServerLevel, Set<Long>> CLAIMED_TREE_KINGS = new WeakHashMap<>();
|
||||||
private static final ConcurrentLinkedQueue<PendingKingSpawn> PENDING_KING_SPAWNS = new ConcurrentLinkedQueue<>();
|
private static final ConcurrentLinkedQueue<PendingKingSpawn> PENDING_KING_SPAWNS = new ConcurrentLinkedQueue<>();
|
||||||
|
|||||||
-8
@@ -573,8 +573,6 @@ public class OuranwoodTreeFeature extends Feature<OuranwoodTreeConfiguration> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The tick is scheduled here on the WorldGenLevel because onPlace() is never
|
|
||||||
// called during world generation, so the block cannot self-schedule.
|
|
||||||
int squirrelCount = 1 + random.nextInt(3);
|
int squirrelCount = 1 + random.nextInt(3);
|
||||||
BlockPos markerPos = floorBlocks.get(0);
|
BlockPos markerPos = floorBlocks.get(0);
|
||||||
setBlock(level, markerPos, AntarchyObjects.SQUIRREL_NEST_BLOCK.get().defaultBlockState()
|
setBlock(level, markerPos, AntarchyObjects.SQUIRREL_NEST_BLOCK.get().defaultBlockState()
|
||||||
@@ -687,13 +685,8 @@ public class OuranwoodTreeFeature extends Feature<OuranwoodTreeConfiguration> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void placeCaterpillarChrysalis(WorldGenLevel level, BlockPos origin, OuranwoodTreeConfiguration config, RandomSource random, BlockPos canopyCenter, int canopyRadius, int canopyDepth) {
|
protected void placeCaterpillarChrysalis(WorldGenLevel level, BlockPos origin, OuranwoodTreeConfiguration config, RandomSource random, BlockPos canopyCenter, int canopyRadius, int canopyDepth) {
|
||||||
// Tree-grown chrysalis placement is intentionally disabled for now.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds a log or leaf block in the canopy that has sufficient clear space beneath it.
|
|
||||||
* {@code clearBelow} is the vertical depth to check; {@code clearRadius} is the XZ half-width (0 = 1x1, 1 = 3x3).
|
|
||||||
*/
|
|
||||||
protected @Nullable BlockPos findCanopyAnchor(WorldGenLevel level, RandomSource random, BlockPos canopyCenter, int canopyRadius, int canopyDepth, int clearBelow, int clearRadius, int attempts) {
|
protected @Nullable BlockPos findCanopyAnchor(WorldGenLevel level, RandomSource random, BlockPos canopyCenter, int canopyRadius, int canopyDepth, int clearBelow, int clearRadius, int attempts) {
|
||||||
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
|
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
|
||||||
int r = Math.max(1, canopyRadius - 1);
|
int r = Math.max(1, canopyRadius - 1);
|
||||||
@@ -831,7 +824,6 @@ public class OuranwoodTreeFeature extends Feature<OuranwoodTreeConfiguration> {
|
|||||||
int worldX = origin.getX() + x;
|
int worldX = origin.getX() + x;
|
||||||
int worldZ = origin.getZ() + z;
|
int worldZ = origin.getZ() + z;
|
||||||
|
|
||||||
// Raise soil to form a mound around the base (from adaptTerrain)
|
|
||||||
int currentTopY = level.getHeight(Heightmap.Types.WORLD_SURFACE_WG, worldX, worldZ) - 1;
|
int currentTopY = level.getHeight(Heightmap.Types.WORLD_SURFACE_WG, worldX, worldZ) - 1;
|
||||||
int falloff = (int) Math.floor(Math.sqrt(distanceSq) / 2.1D);
|
int falloff = (int) Math.floor(Math.sqrt(distanceSq) / 2.1D);
|
||||||
int desiredTopY = baseY - falloff + (distanceSq <= trunkRadiusSq ? 0 : random.nextInt(2));
|
int desiredTopY = baseY - falloff + (distanceSq <= trunkRadiusSq ? 0 : random.nextInt(2));
|
||||||
|
|||||||
-3
@@ -4,9 +4,6 @@ import org.spongepowered.asm.mixin.extensibility.IMixinConfig;
|
|||||||
import org.spongepowered.asm.mixin.extensibility.IMixinErrorHandler;
|
import org.spongepowered.asm.mixin.extensibility.IMixinErrorHandler;
|
||||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||||
|
|
||||||
/*
|
|
||||||
* Keeps bad mixins from hard-crashing startup.
|
|
||||||
*/
|
|
||||||
public final class AntarchyMixinErrorHandler implements IMixinErrorHandler {
|
public final class AntarchyMixinErrorHandler implements IMixinErrorHandler {
|
||||||
private static final String BROKEN_MARVEL_STELLARIS_MIXIN =
|
private static final String BROKEN_MARVEL_STELLARIS_MIXIN =
|
||||||
"net.tintankgames.marvel.mixin.integration.stellaris.DimensionOxygenManagerMixin";
|
"net.tintankgames.marvel.mixin.integration.stellaris.DimensionOxygenManagerMixin";
|
||||||
|
|||||||
@@ -7,9 +7,6 @@ import org.spongepowered.asm.mixin.Mixins;
|
|||||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||||
|
|
||||||
/*
|
|
||||||
* Mixin plugin for compat-gated mixins and optional deps.
|
|
||||||
*/
|
|
||||||
public final class AntarchyMixinPlugin implements IMixinConfigPlugin {
|
public final class AntarchyMixinPlugin implements IMixinConfigPlugin {
|
||||||
private static final AntarchyRangedAttackPatcher RANGED_ATTACK_PATCHER = new AntarchyRangedAttackPatcher();
|
private static final AntarchyRangedAttackPatcher RANGED_ATTACK_PATCHER = new AntarchyRangedAttackPatcher();
|
||||||
|
|
||||||
@@ -42,14 +39,9 @@ public final class AntarchyMixinPlugin implements IMixinConfigPlugin {
|
|||||||
&& classPresent("com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod");
|
&& classPresent("com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod");
|
||||||
}
|
}
|
||||||
if (mixinClassName.startsWith("com.craisinlord.antarchy.mixins.compat.alexscaves.")) {
|
if (mixinClassName.startsWith("com.craisinlord.antarchy.mixins.compat.alexscaves.")) {
|
||||||
// The target class was found above. Checking the target itself avoids depending on
|
|
||||||
// whether a loader exposes Alex's Caves' entrypoint resource to this classloader.
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (mixinClassName.endsWith(".VillagerTradesMixin")) {
|
if (mixinClassName.endsWith(".VillagerTradesMixin")) {
|
||||||
// Trade registration is platform-driven on every supported loader now. Keeping the
|
|
||||||
// static VillagerTrades class-init mixin around risks touching AntarchyObjects before
|
|
||||||
// registration is finished on Fabric and duplicates trades on event-driven loaders.
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -15,9 +15,6 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
|||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
@Mixin(BaseFireBlock.class)
|
@Mixin(BaseFireBlock.class)
|
||||||
/*
|
|
||||||
* Lets dream fire pick the floor or ceiling variant from the same support tag.
|
|
||||||
*/
|
|
||||||
public abstract class DreamFireBlockMixin {
|
public abstract class DreamFireBlockMixin {
|
||||||
private static final ResourceLocation DREAM_FIRE_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "dream_fire");
|
private static final ResourceLocation DREAM_FIRE_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "dream_fire");
|
||||||
private static final ResourceLocation DREAM_CEILING_FIRE_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "dream_fire_ceiling");
|
private static final ResourceLocation DREAM_CEILING_FIRE_ID = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "dream_fire_ceiling");
|
||||||
|
|||||||
-1
@@ -13,7 +13,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
|||||||
|
|
||||||
@Mixin(LivingEntity.class)
|
@Mixin(LivingEntity.class)
|
||||||
public abstract class GlimmeringDamageImmunityMixin {
|
public abstract class GlimmeringDamageImmunityMixin {
|
||||||
// Magic damage (potions, spells) is tagged bypasses_armor, so it's excluded
|
|
||||||
@Inject(method = "hurt", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "hurt", at = @At("HEAD"), cancellable = true)
|
||||||
private void antarchy$glimmeringIgnoresAttacks(DamageSource source, float amount, CallbackInfoReturnable<Boolean> cir) {
|
private void antarchy$glimmeringIgnoresAttacks(DamageSource source, float amount, CallbackInfoReturnable<Boolean> cir) {
|
||||||
LivingEntity self = (LivingEntity) (Object) this;
|
LivingEntity self = (LivingEntity) (Object) this;
|
||||||
|
|||||||
-5
@@ -9,8 +9,6 @@ import org.spongepowered.asm.mixin.injection.At;
|
|||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
// LivingEntity.isPushable()/isPickable() are full overrides of Entity's versions (they don't call
|
|
||||||
// super), so this has to target LivingEntity directly, not Entity, or the injected code never runs.
|
|
||||||
@Mixin(LivingEntity.class)
|
@Mixin(LivingEntity.class)
|
||||||
public abstract class GlimmeringPushableMixin {
|
public abstract class GlimmeringPushableMixin {
|
||||||
@Inject(method = "isPushable", at = @At("RETURN"), cancellable = true)
|
@Inject(method = "isPushable", at = @At("RETURN"), cancellable = true)
|
||||||
@@ -26,9 +24,6 @@ public abstract class GlimmeringPushableMixin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Projectiles (and entity-picking in general) skip targets that aren't isPickable(), so this
|
|
||||||
// is what actually lets arrows/tridents/etc. pass through a glimmering entity instead of
|
|
||||||
// colliding with it; the damage-immunity mixin alone only stopped the damage, not the impact.
|
|
||||||
@Inject(method = "isPickable", at = @At("RETURN"), cancellable = true)
|
@Inject(method = "isPickable", at = @At("RETURN"), cancellable = true)
|
||||||
private void antarchy$glimmeringNotPickable(CallbackInfoReturnable<Boolean> cir) {
|
private void antarchy$glimmeringNotPickable(CallbackInfoReturnable<Boolean> cir) {
|
||||||
if (!cir.getReturnValueZ()) {
|
if (!cir.getReturnValueZ()) {
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ public abstract class PoiTypesMixin {
|
|||||||
BuiltInRegistries.POINT_OF_INTEREST_TYPE.getHolder(key)
|
BuiltInRegistries.POINT_OF_INTEREST_TYPE.getHolder(key)
|
||||||
.ifPresent(holder -> callback.setReturnValue(Optional.of(holder)));
|
.ifPresent(holder -> callback.setReturnValue(Optional.of(holder)));
|
||||||
} catch (IllegalStateException ignored) {
|
} catch (IllegalStateException ignored) {
|
||||||
// Registration can be queried during bootstrap before loader bindings finish.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
-1
@@ -8,7 +8,6 @@ import org.spongepowered.asm.mixin.injection.At;
|
|||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
/** Captures attack charge before vanilla resets the player's attack-strength ticker. */
|
|
||||||
@Mixin(Player.class)
|
@Mixin(Player.class)
|
||||||
public abstract class RoyalGuardianPlayerAttackMixin {
|
public abstract class RoyalGuardianPlayerAttackMixin {
|
||||||
@Inject(method = "attack", at = @At("HEAD"))
|
@Inject(method = "attack", at = @At("HEAD"))
|
||||||
|
|||||||
-3
@@ -14,9 +14,6 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
|||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
@Mixin(ServerPlayerGameMode.class)
|
@Mixin(ServerPlayerGameMode.class)
|
||||||
/*
|
|
||||||
* Keeps custom sapling stage updates synced like vanilla.
|
|
||||||
*/
|
|
||||||
public abstract class ServerPlayerGameModeMixin {
|
public abstract class ServerPlayerGameModeMixin {
|
||||||
@Shadow protected ServerLevel level;
|
@Shadow protected ServerLevel level;
|
||||||
@Shadow @Final protected ServerPlayer player;
|
@Shadow @Final protected ServerPlayer player;
|
||||||
|
|||||||
-5
@@ -8,11 +8,6 @@ import org.spongepowered.asm.mixin.injection.At;
|
|||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
/**
|
|
||||||
* Lets the Undertrial's vanilla TrialSpawner path spawn entities whose normal
|
|
||||||
* placement predicate assumes floor support. TrialSpawner already performs
|
|
||||||
* its own no-collision and obstruction checks before this method is reached.
|
|
||||||
*/
|
|
||||||
@Mixin(SpawnPlacements.class)
|
@Mixin(SpawnPlacements.class)
|
||||||
public abstract class UndertrialSpawnPlacementsMixin {
|
public abstract class UndertrialSpawnPlacementsMixin {
|
||||||
@Inject(method = "checkSpawnRules", at = @At("RETURN"), cancellable = true)
|
@Inject(method = "checkSpawnRules", at = @At("RETURN"), cancellable = true)
|
||||||
|
|||||||
Loaded 100 of 132 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user