diff --git a/README.md b/README.md index 2758dfaf..1ce5e6ee 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ https://www.curseforge.com/minecraft/mc-mods/antarchy ANTS! ANTS! ANTS! + +Antarchy requires Architectury API, AntOS, Integrated API, GeckoLib, and Sizeable Folia. + +## Credits + +Russian localization: suheckii diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchySettings.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchySettings.java index 89665261..0d030a03 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchySettings.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchySettings.java @@ -285,6 +285,10 @@ public final class AntarchySettings { private static int queenBlackHoleActiveTicks = 120; private static double queenBlackHolePullStrength = 0.16D; private static int queenBlackHoleBlockSuctionCap = 160; + private static double axeBlackHoleRadius = 28.0D; + private static int axeBlackHoleActiveTicks = 120; + private static double axeBlackHolePullStrength = 0.16D; + private static int axeBlackHoleBlockSuctionCap = 160; private static double kingFireballDamage = 48.0D; private static double kingFireballRadius = 4.5D; private static int kingFireballCooldownTicks = 150; @@ -576,8 +580,8 @@ public final class AntarchySettings { private static double crawlingBlightAttackDamage = 6.0D; private static double skulkingFrightHealth = 15.0D; private static double skulkingFrightAttackDamage = 6.0D; - private static double manticoreHealth = 40.0D; - private static double manticoreAttackDamage = 7.0D; + private static double manticoreHealth = 60.0D; + private static double manticoreAttackDamage = 11.0D; private static int manticoreStingPoisonTicks = 100; private static int queenManticoreCap = 15; private static int queenManticoreSummonCooldownTicks = 800; @@ -2167,6 +2171,14 @@ public final class AntarchySettings { public static void setQueenBlackHolePullStrength(double v) { queenBlackHolePullStrength = v; } public static int queenBlackHoleBlockSuctionCap() { return queenBlackHoleBlockSuctionCap; } public static void setQueenBlackHoleBlockSuctionCap(int v) { queenBlackHoleBlockSuctionCap = v; } + public static double axeBlackHoleRadius() { return axeBlackHoleRadius; } + public static void setAxeBlackHoleRadius(double v) { axeBlackHoleRadius = v; } + public static int axeBlackHoleActiveTicks() { return axeBlackHoleActiveTicks; } + public static void setAxeBlackHoleActiveTicks(int v) { axeBlackHoleActiveTicks = v; } + public static double axeBlackHolePullStrength() { return axeBlackHolePullStrength; } + public static void setAxeBlackHolePullStrength(double v) { axeBlackHolePullStrength = v; } + public static int axeBlackHoleBlockSuctionCap() { return axeBlackHoleBlockSuctionCap; } + public static void setAxeBlackHoleBlockSuctionCap(int v) { axeBlackHoleBlockSuctionCap = v; } public static double kingFireballDamage() { return kingFireballDamage; } public static void setKingFireballDamage(double v) { kingFireballDamage = v; } public static double kingFireballRadius() { return kingFireballRadius; } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/QueenMusicHandler.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/QueenMusicHandler.java index 3ddb1729..822424ee 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/QueenMusicHandler.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/QueenMusicHandler.java @@ -18,7 +18,6 @@ public final class QueenMusicHandler { private static final int RESTART_COOLDOWN_TICKS = 100; private static QueenMusicSound music; private static int cooldownTicks; - private static boolean wasInEncounter; private QueenMusicHandler() { } @@ -38,21 +37,16 @@ public final class QueenMusicHandler { QueenEntity queen = minecraft.level.getEntitiesOfClass( QueenEntity.class, minecraft.player.getBoundingBox().inflate(STOP_RADIUS), - QueenEntity::shouldPlayQueenMusic + entity -> entity.isQueenMusicActive() || entity.shouldPlayQueenMusic() ).stream() .min(Comparator.comparingDouble(entity -> entity.distanceToSqr(minecraft.player))) .orElse(null); if (queen == null) { stop(minecraft); - if (wasInEncounter) { - cooldownTicks = Math.max(cooldownTicks, RESTART_COOLDOWN_TICKS); - } - wasInEncounter = false; return; } - wasInEncounter = true; if (music != null && !minecraft.getSoundManager().isActive(music)) { music = null; cooldownTicks = Math.max(cooldownTicks, RESTART_COOLDOWN_TICKS); @@ -82,7 +76,6 @@ public final class QueenMusicHandler { private static void reset(Minecraft minecraft) { stop(minecraft); cooldownTicks = 0; - wasInEncounter = false; } private static final class QueenMusicSound extends AbstractTickableSoundInstance { diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/creative/CreativeTabContents.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/creative/CreativeTabContents.java index 2f8f2274..573d0ca6 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/creative/CreativeTabContents.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/creative/CreativeTabContents.java @@ -650,6 +650,9 @@ public final class CreativeTabContents { public static boolean populateNeoForgeVanillaTab(ResourceKey tabKey, HolderLookup.Provider holders, NeoForgeVanillaTabOutput output) { + if (!ResourceLocation.DEFAULT_NAMESPACE.equals(tabKey.location().getNamespace())) { + return false; + } String tabPath = tabKey.location().getPath(); boolean matched = false; for (CatalogEntry entry : CATALOG) { diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/ManticoreEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/ManticoreEntity.java index 8559d19f..b36b9587 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/ManticoreEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/ManticoreEntity.java @@ -59,7 +59,6 @@ import software.bernie.geckolib.util.GeckoLibUtil; public class ManticoreEntity extends Monster implements GeoEntity { private static final String SUMMONER_KEY = "QueenSummoner"; private static final String PLAYER_SUMMONER_KEY = "PlayerSummoner"; - private static final String PLAYER_SUMMON_LIFETIME_KEY = "PlayerSummonLifetime"; private static final int LOST_SUMMONER_GRACE_TICKS = 200; private static final int TAKEOFF_COOLDOWN_TICKS = 40; private static final int STING_COOLDOWN_TICKS = 60; @@ -81,8 +80,6 @@ public class ManticoreEntity extends Monster implements GeoEntity { private UUID summonerId; @Nullable private UUID playerSummonerId; - private int playerSummonLifetime; - private int playerSummonAge; private int lostSummonerTicks; private int takeoffCooldown; private int stingCooldown; @@ -102,8 +99,8 @@ public class ManticoreEntity extends Monster implements GeoEntity { public static AttributeSupplier.Builder createAttributes() { return Mob.createMobAttributes() .add(Attributes.MAX_HEALTH, AntarchySettings.manticoreHealth()) - .add(Attributes.MOVEMENT_SPEED, 0.45D) - .add(Attributes.FLYING_SPEED, 2.0D) + .add(Attributes.MOVEMENT_SPEED, 0.55D) + .add(Attributes.FLYING_SPEED, 2.6D) .add(Attributes.ATTACK_DAMAGE, AntarchySettings.manticoreAttackDamage()) .add(Attributes.FOLLOW_RANGE, 28.0D) .add(Attributes.KNOCKBACK_RESISTANCE, 0.2D); @@ -161,11 +158,9 @@ public class ManticoreEntity extends Monster implements GeoEntity { this.setPersistenceRequired(); } - public void markPlayerSummoned(UUID playerId, int lifetimeTicks) { + public void markPlayerSummoned(UUID playerId) { this.playerSummonerId = playerId; this.summonerId = null; - this.playerSummonLifetime = lifetimeTicks; - this.playerSummonAge = 0; this.lostSummonerTicks = 0; this.setPersistenceRequired(); } @@ -202,7 +197,7 @@ public class ManticoreEntity extends Monster implements GeoEntity { @Override public boolean removeWhenFarAway(double distanceToClosestPlayer) { - return this.summonerId == null && super.removeWhenFarAway(distanceToClosestPlayer); + return this.summonerId == null && this.playerSummonerId == null && super.removeWhenFarAway(distanceToClosestPlayer); } @Override @@ -236,8 +231,9 @@ public class ManticoreEntity extends Monster implements GeoEntity { } this.tickQueenSummonCleanup(); + this.tickPlayerSummonCleanup(); - this.tickPlayerSummon(); + this.tickPlayerSummonTarget(); this.tickQueenSummonTarget(); LivingEntity target = this.getTarget(); @@ -252,17 +248,12 @@ public class ManticoreEntity extends Monster implements GeoEntity { } } - private void tickPlayerSummon() { + private void tickPlayerSummonTarget() { if (this.playerSummonerId == null || !(this.level() instanceof ServerLevel serverLevel)) { return; } - if (++this.playerSummonAge >= this.playerSummonLifetime) { - this.discard(); - return; - } Entity entity = serverLevel.getEntity(this.playerSummonerId); if (!(entity instanceof Player player) || !player.isAlive()) { - this.discard(); return; } LivingEntity target = player.getLastHurtMob(); @@ -328,6 +319,20 @@ public class ManticoreEntity extends Monster implements GeoEntity { } } + private void tickPlayerSummonCleanup() { + if (this.playerSummonerId == null || !(this.level() instanceof ServerLevel serverLevel)) { + return; + } + Entity summoner = serverLevel.getEntity(this.playerSummonerId); + if (summoner instanceof Player player && player.isAlive()) { + this.lostSummonerTicks = 0; + return; + } + if (++this.lostSummonerTicks > LOST_SUMMONER_GRACE_TICKS) { + this.discard(); + } + } + private void takeoff() { this.takeoffCooldown = TAKEOFF_COOLDOWN_TICKS; this.setDeltaMovement(this.getDeltaMovement().add(0.0D, 0.55D, 0.0D)); @@ -461,7 +466,6 @@ public class ManticoreEntity extends Monster implements GeoEntity { } if (this.playerSummonerId != null) { tag.putUUID(PLAYER_SUMMONER_KEY, this.playerSummonerId); - tag.putInt(PLAYER_SUMMON_LIFETIME_KEY, this.playerSummonLifetime); } } @@ -470,8 +474,6 @@ public class ManticoreEntity extends Monster implements GeoEntity { super.readAdditionalSaveData(tag); this.summonerId = tag.hasUUID(SUMMONER_KEY) ? tag.getUUID(SUMMONER_KEY) : null; this.playerSummonerId = tag.hasUUID(PLAYER_SUMMONER_KEY) ? tag.getUUID(PLAYER_SUMMONER_KEY) : null; - this.playerSummonLifetime = tag.getInt(PLAYER_SUMMON_LIFETIME_KEY); - this.playerSummonAge = 0; this.lostSummonerTicks = 0; } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/portal/DimensionalTearEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/portal/DimensionalTearEntity.java index 6758adb8..f9afee78 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/portal/DimensionalTearEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/portal/DimensionalTearEntity.java @@ -12,9 +12,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; -import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance; -import net.minecraft.client.sounds.SoundManager; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.core.HolderSet; @@ -79,8 +76,6 @@ public class DimensionalTearEntity extends Entity implements GeoEntity { private static final Map> QUEEN_TEAR_IDS = new HashMap<>(); private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this); - @Nullable - private TearIdleSoundInstance idleSound; private UUID linkedTearId; @Nullable private DimensionalTearEntity linkedTear; @@ -147,7 +142,6 @@ public class DimensionalTearEntity extends Entity implements GeoEntity { super.tick(); if (this.level().isClientSide) { this.tickClientParticles(); - this.tickIdleSound(); return; } @@ -295,12 +289,12 @@ public class DimensionalTearEntity extends Entity implements GeoEntity { continue; } manticore.finalizeSpawn(level, level.getCurrentDifficultyAt(BlockPos.containing(exit)), MobSpawnType.MOB_SUMMONED, null); - manticore.markPlayerSummoned(player.getUUID(), 20 * 30); + manticore.markPlayerSummoned(player.getUUID()); if (player.getLastHurtMob() != null && player.getLastHurtMob().isAlive()) { manticore.setTarget(player.getLastHurtMob()); } - manticore.setDeltaMovement(this.getViewVector(1.0F).scale(0.2D).add(0.0D, 0.08D, 0.0D)); - manticore.setNoGravity(true); + manticore.setDeltaMovement(this.getViewVector(1.0F).scale(0.7D).add(0.0D, 0.18D, 0.0D)); + manticore.setNoGravity(false); level.addFreshEntity(manticore); } } @@ -439,16 +433,8 @@ public class DimensionalTearEntity extends Entity implements GeoEntity { this.entityData.set(STATE, state.ordinal()); } - private void tickIdleSound() { - SoundManager soundManager = Minecraft.getInstance().getSoundManager(); - if (this.getTearState() == TearState.OPENING) { - return; - } - if (this.idleSound != null && soundManager.isActive(this.idleSound)) { - return; - } - this.idleSound = new TearIdleSoundInstance(this); - soundManager.play(this.idleSound); + public boolean shouldPlayIdleSound() { + return this.getTearState() != TearState.OPENING; } private void tickClientParticles() { @@ -572,36 +558,4 @@ public class DimensionalTearEntity extends Entity implements GeoEntity { public AnimatableInstanceCache getAnimatableInstanceCache() { return this.geoCache; } - - private static final class TearIdleSoundInstance extends AbstractTickableSoundInstance { - private final DimensionalTearEntity tear; - - private TearIdleSoundInstance(DimensionalTearEntity tear) { - super(AntarchySoundEvents.DIMENSIONAL_TEAR_IDLE.get(), SoundSource.HOSTILE, tear.random); - this.tear = tear; - this.looping = true; - this.delay = 0; - this.volume = 0.6F; - this.pitch = 1.0F; - this.x = tear.getX(); - this.y = tear.getY(); - this.z = tear.getZ(); - } - - @Override - public void tick() { - if (this.tear.isRemoved() || this.tear.getTearState() == TearState.COLLAPSING) { - this.stop(); - return; - } - this.x = this.tear.getX(); - this.y = this.tear.getY(); - this.z = this.tear.getZ(); - } - - @Override - public boolean canStartSilent() { - return true; - } - } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/QueenEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/QueenEntity.java index 7d4b22a7..3eb64b6a 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/QueenEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/QueenEntity.java @@ -24,6 +24,9 @@ import net.minecraft.core.particles.DustParticleOptions; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.network.syncher.EntityDataSerializers; +import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; @@ -59,6 +62,8 @@ import net.minecraft.world.entity.player.Player; import org.jetbrains.annotations.Nullable; public class QueenEntity extends RoyalBossEntity { + private static final EntityDataAccessor QUEEN_MUSIC_ACTIVE = + SynchedEntityData.defineId(QueenEntity.class, EntityDataSerializers.BOOLEAN); static final double TIME_FIELD_RADIUS_SCALE = 3.0D; private static final String SUMMON_COOLDOWN_KEY = "ManticoreSummonCooldownTicks"; private static final int FAILED_SUMMON_RETRY_TICKS = 20; @@ -196,6 +201,12 @@ public class QueenEntity extends RoyalBossEntity { super(entityType, level); } + @Override + protected void defineSynchedData(SynchedEntityData.Builder builder) { + super.defineSynchedData(builder); + builder.define(QUEEN_MUSIC_ACTIVE, false); + } + public static AttributeSupplier.Builder createAttributes() { return createBaseAttributes(AntarchySettings.queenHealth(), AntarchySettings.queenAttackDamage()); } @@ -348,6 +359,10 @@ public class QueenEntity extends RoyalBossEntity { return !this.isDeadOrDying() && target != null && target.isAlive() && this.canAttack(target); } + public boolean isQueenMusicActive() { + return this.entityData.get(QUEEN_MUSIC_ACTIVE); + } + @Override protected SoundEvent royalFlyLoopSound() { return AntarchySoundEvents.QUEEN_FLY_LOOP.get(); @@ -442,6 +457,9 @@ public class QueenEntity extends RoyalBossEntity { @Override public void tick() { super.tick(); + if (!this.level().isClientSide) { + this.entityData.set(QUEEN_MUSIC_ACTIVE, this.shouldPlayQueenMusic()); + } if (this.level().isClientSide || this.isDeadOrDying()) { return; } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalAssailantBlackHoleEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalAssailantBlackHoleEntity.java index 790c49e7..76b2222f 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalAssailantBlackHoleEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalAssailantBlackHoleEntity.java @@ -17,8 +17,8 @@ public final class RoyalAssailantBlackHoleEntity extends RoyalBlackHoleEntity { public static RoyalAssailantBlackHoleEntity create(ServerLevel level, Vec3 center, @Nullable UUID ownerId) { RoyalAssailantBlackHoleEntity hole = new RoyalAssailantBlackHoleEntity( AntarchyObjects.ROYAL_ASSAILANT_BLACK_HOLE.get(), level); - hole.configure(center, AntarchySettings.queenBlackHoleRadius(), - AntarchySettings.queenBlackHoleActiveTicks(), ownerId); + hole.configure(center, AntarchySettings.axeBlackHoleRadius(), + AntarchySettings.axeBlackHoleActiveTicks(), ownerId); return hole; } @@ -54,6 +54,16 @@ public final class RoyalAssailantBlackHoleEntity extends RoyalBlackHoleEntity { @Override protected boolean pullsTerrainBlocks() { - return false; + return true; + } + + @Override + protected double pullStrength() { + return AntarchySettings.axeBlackHolePullStrength(); + } + + @Override + protected int blockSuctionCap() { + return AntarchySettings.axeBlackHoleBlockSuctionCap(); } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBlackHoleEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBlackHoleEntity.java index 45309fa4..ed289d0c 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBlackHoleEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBlackHoleEntity.java @@ -238,6 +238,14 @@ public class RoyalBlackHoleEntity extends Entity implements GeoEntity { return this.effectRadius() * QUEEN_PULL_RADIUS_SCALE; } + protected double pullStrength() { + return AntarchySettings.queenBlackHolePullStrength(); + } + + protected int blockSuctionCap() { + return AntarchySettings.queenBlackHoleBlockSuctionCap(); + } + /** Returns the center of the animated black-hole cube in world coordinates. */ public Vec3 effectCenter() { double animationSeconds = Math.min(CORE_RISE_END_SECONDS, this.animationAge / 20.0D); @@ -295,7 +303,7 @@ public class RoyalBlackHoleEntity extends Entity implements GeoEntity { if (distance > radius) { continue; } - double strength = AntarchySettings.queenBlackHolePullStrength() * (1.0D - distance / radius); + double strength = this.pullStrength() * (1.0D - distance / radius); Vec3 pull = toCenter.scale(strength / distance); entity.setDeltaMovement(entity.getDeltaMovement().scale(0.86D).add(pull)); entity.hasImpulse = true; @@ -304,7 +312,7 @@ public class RoyalBlackHoleEntity extends Entity implements GeoEntity { } private void pullTerrainBlocks(ServerLevel level) { - int cap = AntarchySettings.queenBlackHoleBlockSuctionCap(); + int cap = this.blockSuctionCap(); if (cap <= 0 || this.suckedBlocks >= cap || !level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { return; diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portal/PermanentPortalShape.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portal/PermanentPortalShape.java index 244643da..267a54d3 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portal/PermanentPortalShape.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portal/PermanentPortalShape.java @@ -19,7 +19,7 @@ public final class PermanentPortalShape { public static final int MIN_WIDTH = 2; public static final int MIN_HEIGHT = 3; public static final int MAX_SIZE = 21; - public static final int ACTIVE_SEARCH_RADIUS = 24; + public static final int ACTIVE_SEARCH_RADIUS = 128; private final TagKey frameTag; private final Block portalBlock; @@ -227,10 +227,6 @@ public final class PermanentPortalShape { for (int y = -1; y <= 3; y++) { for (int x = -1; x <= 2; x++) { BlockPos pos = bottomLeft.relative(widthDirection, x).above(y); - boolean cornerSpot = (x == -1 || x == 2) && (y == -1 || y == 3); - if (cornerSpot) { - continue; - } if (x == -1 || x == 2 || y == -1 || y == 3) { level.setBlock(pos, frameState, Block.UPDATE_ALL); } else { @@ -250,10 +246,6 @@ public final class PermanentPortalShape { BlockPos pos = bottomLeft.relative(widthDirection, x).above(y); BlockState state = level.getBlockState(pos); boolean frameSpot = x == -1 || x == 2 || y == -1 || y == 3; - boolean cornerSpot = (x == -1 || x == 2) && (y == -1 || y == 3); - if (cornerSpot) { - continue; - } if (frameSpot) { if (y != -1 && !state.isAir() && !state.is(frameBlock) && !state.canBeReplaced()) { return false; diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portal/PermanentPortalTeleporter.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portal/PermanentPortalTeleporter.java index 10ff1077..a4f1ba7a 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portal/PermanentPortalTeleporter.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/portal/PermanentPortalTeleporter.java @@ -12,6 +12,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.vehicle.DismountHelper; +import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; @@ -23,7 +24,7 @@ import org.jetbrains.annotations.Nullable; public final class PermanentPortalTeleporter { private static final int SEARCH_RADIUS = 24; private static final int VERTICAL_SEARCH = 24; - private static final int EXISTING_PORTAL_SEARCH_RADIUS = 48; + private static final int EXISTING_PORTAL_SEARCH_RADIUS = 128; private PermanentPortalTeleporter() { } @@ -46,7 +47,7 @@ public final class PermanentPortalTeleporter { return new DimensionTransition(sourceLevel, entity, DimensionTransition.DO_NOTHING); } - Vec3 arrival = findArrivalPosition(entity, destination, portalPos, type); + Vec3 arrival = findArrivalPosition(sourceLevel, entity, destination, portalPos, type); if (arrival == null) { if (entity instanceof ServerPlayer player) { player.displayClientMessage(net.minecraft.network.chat.Component.translatable("message.antarchy.teleport_arrival_failed"), true); @@ -65,7 +66,9 @@ public final class PermanentPortalTeleporter { } @Nullable - private static Vec3 findArrivalPosition(Entity entity, ServerLevel destination, BlockPos preferredPos, PermanentPortalType type) { + private static Vec3 findArrivalPosition(ServerLevel source, Entity entity, ServerLevel destination, BlockPos preferredPos, PermanentPortalType type) { + double scale = DimensionType.getTeleportationScale(source.dimensionType(), destination.dimensionType()); + preferredPos = BlockPos.containing(preferredPos.getX() * scale, preferredPos.getY(), preferredPos.getZ() * scale); PermanentPortalShape active = PermanentPortalShape.findActiveNear(destination, preferredPos, type); if (active != null) { Vec3 safePortalPosition = tryFindSafePosition(entity, destination, BlockPos.containing(active.center())); diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/worldgen/elythia/ElythiaBiomeSource.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/worldgen/elythia/ElythiaBiomeSource.java index 9968acfe..b0923609 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/worldgen/elythia/ElythiaBiomeSource.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/worldgen/elythia/ElythiaBiomeSource.java @@ -16,148 +16,46 @@ import net.minecraft.world.level.biome.BiomeSource; import net.minecraft.world.level.biome.Climate; import net.minecraft.world.level.biome.MultiNoiseBiomeSource; -public class ElythiaBiomeSource extends BiomeSource { - private static final ResourceKey MOLEWORM_CAVES = ResourceKey.create( - Registries.BIOME, - ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "moleworm_caves") - ); - private static final ResourceKey ELYTHIA_LUSH_CAVES = ResourceKey.create( - Registries.BIOME, - ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "elythia_lush_caves") - ); - private static final ResourceKey ELYTHIA_OCEAN = ResourceKey.create( - Registries.BIOME, - ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "elythia_ocean") - ); - private static final ResourceKey ELYTHIA_CORAL_SPIKES = ResourceKey.create( - Registries.BIOME, - ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "elythia_coral_spikes") - ); - private static final ResourceKey ELYTHIA_BEACH = ResourceKey.create( - Registries.BIOME, - ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "elythia_beach") - ); - private static final ResourceKey OURANWOOD_FOREST = ResourceKey.create( - Registries.BIOME, - ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "ouranwood_forest") - ); - private static final ResourceKey SPARSE_OURANWOOD_FOREST = ResourceKey.create( - Registries.BIOME, - ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "sparse_ouranwood_forest") - ); - private static final ResourceKey PEACH_FOREST = ResourceKey.create( - Registries.BIOME, - ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "peach_forest") - ); - private static final ResourceKey FUNGAL_OURANWOOD_FOREST = ResourceKey.create( - Registries.BIOME, - ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "fungal_ouranwood_forest") - ); - private static final ResourceKey GLIMMERING_POOLS = ResourceKey.create( - Registries.BIOME, - ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "glimmering_pools") - ); +public final class ElythiaBiomeSource extends BiomeSource { private static final ResourceKey CLOUD_SEA = ResourceKey.create( Registries.BIOME, ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "cloud_sea") ); - private static final int[] SURFACE_FALLBACK_BLOCK_YS = new int[]{192, 160, 128, 96, 64, 32, 0}; - - private static final class ColumnBiomeCache { - long key = Long.MIN_VALUE; - Holder value; - } - - private final ThreadLocal molewormSurfaceFallbackCache = ThreadLocal.withInitial(ColumnBiomeCache::new); - private final ThreadLocal peachForestSurfaceFallbackCache = ThreadLocal.withInitial(ColumnBiomeCache::new); - private final ThreadLocal landFallbackCache = ThreadLocal.withInitial(ColumnBiomeCache::new); - - private static long packColumnKey(int x, int z) { - return ((long) x << 32) ^ (z & 0xFFFFFFFFL); - } public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( MultiNoiseBiomeSource.DIRECT_CODEC.forGetter(ElythiaBiomeSource::parameters), - Codec.INT.optionalFieldOf("moleworm_caves_max_y", 72).forGetter(ElythiaBiomeSource::molewormCavesMaxY), - Codec.INT.optionalFieldOf("surface_biome_sample_y", 160).forGetter(ElythiaBiomeSource::surfaceBiomeSampleY), - Codec.INT.optionalFieldOf("ocean_max_y", 85).forGetter(ElythiaBiomeSource::oceanMaxY), - Codec.INT.optionalFieldOf("sea_level", 78).forGetter(ElythiaBiomeSource::seaLevel), - Codec.INT.optionalFieldOf("cloud_sea_min_y", 360).forGetter(ElythiaBiomeSource::cloudSeaMinY) + Codec.INT.optionalFieldOf("cloud_sea_min_y", 250).forGetter(ElythiaBiomeSource::cloudSeaMinY) ).apply(instance, ElythiaBiomeSource::new)); private final Climate.ParameterList> parameters; private final MultiNoiseBiomeSource delegate; - private final int molewormCavesMaxY; - private final int surfaceBiomeSampleY; - private final int oceanMaxY; - private final int seaLevel; - private final int cloudSeaMinY; - private final int molewormCavesMaxQuartY; - private final int surfaceBiomeSampleQuartY; - private final int oceanMaxQuartY; - private final int seaLevelQuartY; - private final int undergroundGuardMaxQuartY; private final int cloudSeaMinQuartY; - private final Holder oceanHolder; - private final Holder defaultLandHolder; - private final Holder glimmeringPoolsHolder; - private final Holder ouranwoodForestHolder; private final Holder cloudSeaHolder; - private final Holder firstConfiguredHolder; + private final Holder fallbackHolder; - public ElythiaBiomeSource(Climate.ParameterList> parameters, int molewormCavesMaxY, int surfaceBiomeSampleY, int oceanMaxY, int seaLevel, int cloudSeaMinY) { + public ElythiaBiomeSource(Climate.ParameterList> parameters, int cloudSeaMinY) { this.parameters = parameters; this.delegate = MultiNoiseBiomeSource.createFromList(parameters); - this.molewormCavesMaxY = molewormCavesMaxY; - this.surfaceBiomeSampleY = surfaceBiomeSampleY; - this.oceanMaxY = oceanMaxY; - this.seaLevel = seaLevel; - this.cloudSeaMinY = cloudSeaMinY; - this.molewormCavesMaxQuartY = QuartPos.fromBlock(molewormCavesMaxY); - this.surfaceBiomeSampleQuartY = QuartPos.fromBlock(surfaceBiomeSampleY); - this.oceanMaxQuartY = QuartPos.fromBlock(oceanMaxY); - this.seaLevelQuartY = QuartPos.fromBlock(seaLevel); - this.undergroundGuardMaxQuartY = QuartPos.fromBlock(molewormCavesMaxY + 40); this.cloudSeaMinQuartY = QuartPos.fromBlock(cloudSeaMinY); - this.oceanHolder = parameters.values().stream() - .map(Pair::getSecond) - .filter(h -> h.is(ELYTHIA_OCEAN)) - .findFirst() - .orElse(null); - this.glimmeringPoolsHolder = parameters.values().stream() - .map(Pair::getSecond) - .filter(h -> h.is(GLIMMERING_POOLS)) - .findFirst() - .orElse(null); - this.ouranwoodForestHolder = parameters.values().stream() - .map(Pair::getSecond) - .filter(h -> h.is(OURANWOOD_FOREST)) - .findFirst() - .orElse(null); - this.defaultLandHolder = parameters.values().stream() - .map(Pair::getSecond) - .filter(h -> !isOceanBiome(h) && !h.is(ELYTHIA_BEACH) - && !h.is(MOLEWORM_CAVES) && !h.is(ELYTHIA_LUSH_CAVES) - && !h.is(GLIMMERING_POOLS)) - .findFirst() - .orElse(null); this.cloudSeaHolder = parameters.values().stream() .map(Pair::getSecond) - .filter(h -> h.is(CLOUD_SEA)) + .filter(holder -> holder.is(CLOUD_SEA)) .findFirst() .orElse(null); - this.firstConfiguredHolder = parameters.values().stream() + this.fallbackHolder = parameters.values().stream() .map(Pair::getSecond) + .filter(holder -> !holder.is(CLOUD_SEA)) .findFirst() .orElse(null); } - private Climate.ParameterList> parameters() { return this.parameters; } - private int molewormCavesMaxY() { return this.molewormCavesMaxY; } - private int surfaceBiomeSampleY() { return this.surfaceBiomeSampleY; } - private int oceanMaxY() { return this.oceanMaxY; } - private int seaLevel() { return this.seaLevel; } - private int cloudSeaMinY() { return this.cloudSeaMinY; } + private Climate.ParameterList> parameters() { + return this.parameters; + } + + private int cloudSeaMinY() { + return this.cloudSeaMinQuartY * 4; + } @Override protected MapCodec codec() { @@ -168,236 +66,17 @@ public class ElythiaBiomeSource extends BiomeSource { protected Stream> collectPossibleBiomes() { return this.delegate.possibleBiomes().stream(); } - private static final long OCEAN_CONTINENTALNESS_THRESHOLD = Climate.quantizeCoord(-0.87f); - private static final int CLOUD_SEA_CELL_SIZE = 96; - private static final long CLOUD_SEA_CHANCE_DENOMINATOR = 5L; // 1-in-5 columns == ~20% @Override public Holder getNoiseBiome(int x, int y, int z, Climate.Sampler sampler) { - // Only some sky columns are the cloud sea — everywhere else, altitude above the cloud - // floor just falls through to whatever biome would normally be there. Decided before - // touching the (expensive) delegate at all, both for correctness (multi-noise has no - // real notion of raw Y to gate a biome on) and as a speed win for the common case. - if (this.cloudSeaHolder != null && y >= this.cloudSeaMinQuartY && isCloudSeaColumn(x, z)) { + if (this.cloudSeaHolder != null && y >= this.cloudSeaMinQuartY) { return this.cloudSeaHolder; } Holder biome = this.delegate.getNoiseBiome(x, y, z, sampler); - if (biome == null) { - return resolveConfiguredFallback(x, y, z, sampler); + if (biome != null && !biome.is(CLOUD_SEA)) { + return biome; } - - // Defensive: cloud_sea's multi-noise parameter point is reserved far off in "offset" - // so it shouldn't win nearest-neighbor on its own, but if it ever does for a query - // below the cloud floor, treat it like any other biome that has no business at that - // altitude and fall back to a real land biome instead of leaking clouds into terrain. - if (biome.is(CLOUD_SEA)) { - return resolveLandFallback(x, z, sampler); - } - - if (biome.is(MOLEWORM_CAVES) && y > this.molewormCavesMaxQuartY) { - return resolveSurfaceFallback(x, z, sampler, this.molewormSurfaceFallbackCache, MOLEWORM_CAVES, GLIMMERING_POOLS, CLOUD_SEA); - } - - Climate.TargetPoint target = sampler.sample(x, this.seaLevelQuartY, z); - if (target.continentalness() < OCEAN_CONTINENTALNESS_THRESHOLD && y <= this.oceanMaxQuartY) { - if (biome.is(MOLEWORM_CAVES) || biome.is(ELYTHIA_LUSH_CAVES)) return biome; - Holder seaLevelBiome = this.delegate.getNoiseBiome(x, this.seaLevelQuartY, z, sampler); - if (isOceanBiome(seaLevelBiome)) return seaLevelBiome; - return oceanHolder != null ? oceanHolder : nullToConfiguredFallback(seaLevelBiome, x, y, z, sampler); - } - if (y <= this.seaLevelQuartY && oceanHolder != null && !allowedBelowSeaLevel(biome)) { - return oceanHolder; - } - - if (isOceanBiome(biome)) { - return resolveLandFallback(x, z, sampler); - } - - if (biome.is(SPARSE_OURANWOOD_FOREST) && !isSparseOuranwoodCandidate(target, x, z)) { - biome = this.ouranwoodForestHolder != null ? this.ouranwoodForestHolder : biome; - } - - if (isGlimmeringPoolsCandidate(biome, target, x, z)) { - biome = this.glimmeringPoolsHolder != null ? this.glimmeringPoolsHolder : biome; - } - if ((biome.is(PEACH_FOREST) || biome.is(GLIMMERING_POOLS)) && y <= this.undergroundGuardMaxQuartY) { - return resolveSurfaceFallback(x, z, sampler, this.peachForestSurfaceFallbackCache, PEACH_FOREST, GLIMMERING_POOLS, CLOUD_SEA); - } - - return biome; - } - - private static boolean allowedBelowSeaLevel(Holder biome) { - return biome != null && (biome.is(MOLEWORM_CAVES) || biome.is(ELYTHIA_LUSH_CAVES) - || biome.is(ELYTHIA_OCEAN) || biome.is(ELYTHIA_CORAL_SPIKES)); - } - - private static boolean isOceanBiome(Holder biome) { - return biome != null && (biome.is(ELYTHIA_OCEAN) || biome.is(ELYTHIA_CORAL_SPIKES)); - } - - private static boolean isOuranwoodBiome(Holder biome) { - return biome != null && (biome.is(OURANWOOD_FOREST) || biome.is(SPARSE_OURANWOOD_FOREST) - || biome.is(FUNGAL_OURANWOOD_FOREST)); - } - - private static boolean isGlimmeringPoolsCandidate(Holder biome, Climate.TargetPoint target, int x, int z) { - if (!isOuranwoodBiome(biome)) { - return false; - } - - long humidity = target.humidity(); - long continentalness = target.continentalness(); - long weirdness = target.weirdness(); - long depth = target.depth(); - - if (humidity < Climate.quantizeCoord(0.64F) || humidity > Climate.quantizeCoord(1.0F)) { - return false; - } - if (continentalness < Climate.quantizeCoord(0.29F) || continentalness > Climate.quantizeCoord(0.90F)) { - return false; - } - if (weirdness < Climate.quantizeCoord(-0.88F) || weirdness > Climate.quantizeCoord(0.33F)) { - return false; - } - if (depth < Climate.quantizeCoord(0.0F) || depth > Climate.quantizeCoord(0.80F)) { - return false; - } - - long cellX = Math.floorDiv(x, 11); - long cellZ = Math.floorDiv(z, 11); - long gate = Math.floorMod(cellX * 73428767L + cellZ * 912931L, 5L); - return gate <= 3L; - } - - private static boolean isCloudSeaColumn(int x, int z) { - long cellX = Math.floorDiv(x, CLOUD_SEA_CELL_SIZE); - long cellZ = Math.floorDiv(z, CLOUD_SEA_CELL_SIZE); - long gate = Math.floorMod(cellX * 668265263L + cellZ * 2246822519L, CLOUD_SEA_CHANCE_DENOMINATOR); - return gate == 0L; - } - - private static boolean isSparseOuranwoodCandidate(Climate.TargetPoint target, int x, int z) { - if (target.temperature() > Climate.quantizeCoord(0.24F)) { - return false; - } - if (target.humidity() > Climate.quantizeCoord(0.70F)) { - return false; - } - if (target.continentalness() < Climate.quantizeCoord(0.90F)) { - return false; - } - if (target.erosion() > Climate.quantizeCoord(-0.22F)) { - return false; - } - if (target.weirdness() < Climate.quantizeCoord(0.92F)) { - return false; - } - - long cellX = Math.floorDiv(x, 24); - long cellZ = Math.floorDiv(z, 24); - long gate = Math.floorMod(cellX * 1103515245L + cellZ * 2147483647L, 12L); - return gate == 0L; - } - - @SafeVarargs - private Holder resolveSurfaceFallback(int x, int z, Climate.Sampler sampler, ThreadLocal cacheHolder, ResourceKey... excluded) { - ColumnBiomeCache cache = cacheHolder.get(); - long key = packColumnKey(x, z); - if (cache.key == key) { - return cache.value; - } - - Holder result = this.delegate.getNoiseBiome(x, this.surfaceBiomeSampleQuartY, z, sampler); - if (isExcluded(result, excluded)) { - for (int sampleBlockY : SURFACE_FALLBACK_BLOCK_YS) { - Holder candidate = this.delegate.getNoiseBiome(x, QuartPos.fromBlock(sampleBlockY), z, sampler); - if (!isExcluded(candidate, excluded)) { - result = candidate; - break; - } - } - } - result = nullToConfiguredFallback(result, x, this.surfaceBiomeSampleQuartY, z, sampler); - if (result != null && result.is(CLOUD_SEA) && this.defaultLandHolder != null) { - result = this.defaultLandHolder; - } - - cache.key = key; - cache.value = result; - return result; - } - - private Holder resolveLandFallback(int x, int z, Climate.Sampler sampler) { - ColumnBiomeCache cache = this.landFallbackCache.get(); - long key = packColumnKey(x, z); - if (cache.key == key) { - return cache.value; - } - - Holder result = this.delegate.getNoiseBiome(x, this.surfaceBiomeSampleQuartY, z, sampler); - if (isOceanOrCave(result)) { - Holder resolved = null; - for (int sampleBlockY : SURFACE_FALLBACK_BLOCK_YS) { - Holder candidate = this.delegate.getNoiseBiome(x, QuartPos.fromBlock(sampleBlockY), z, sampler); - if (!isOceanOrCave(candidate)) { - resolved = candidate; - break; - } - } - result = resolved != null ? resolved : (defaultLandHolder != null ? defaultLandHolder : result); - } - result = nullToConfiguredFallback(result, x, this.surfaceBiomeSampleQuartY, z, sampler); - - cache.key = key; - cache.value = result; - return result; - } - - @SafeVarargs - private static boolean isExcluded(Holder biome, ResourceKey... excluded) { - if (biome == null) { - return true; - } - for (ResourceKey key : excluded) { - if (biome.is(key)) return true; - } - return false; - } - - private static boolean isOceanOrCave(Holder biome) { - return biome == null || isOceanBiome(biome) || biome.is(ELYTHIA_BEACH) - || biome.is(MOLEWORM_CAVES) || biome.is(ELYTHIA_LUSH_CAVES) - || biome.is(GLIMMERING_POOLS) || biome.is(CLOUD_SEA); - } - - private Holder nullToConfiguredFallback(Holder biome, int x, int y, int z, Climate.Sampler sampler) { - return biome != null ? biome : resolveConfiguredFallback(x, y, z, sampler); - } - - private Holder resolveConfiguredFallback(int x, int y, int z, Climate.Sampler sampler) { - if (y <= this.oceanMaxQuartY && this.oceanHolder != null) { - Climate.TargetPoint target = sampler.sample(x, this.seaLevelQuartY, z); - if (target.continentalness() < OCEAN_CONTINENTALNESS_THRESHOLD) { - return this.oceanHolder; - } - } - if (this.defaultLandHolder != null) return this.defaultLandHolder; - if (this.ouranwoodForestHolder != null) return this.ouranwoodForestHolder; - if (this.glimmeringPoolsHolder != null) return this.glimmeringPoolsHolder; - if (this.oceanHolder != null) return this.oceanHolder; - return this.firstConfiguredHolder; - } - - @Override - public void addDebugInfo(java.util.List debug, net.minecraft.core.BlockPos pos, Climate.Sampler sampler) { - try { - this.delegate.addDebugInfo(debug, pos, sampler); - } catch (NullPointerException ignored) { - } - debug.add("Elythia mole cave cap: y<=" + this.molewormCavesMaxY); - debug.add("Elythia sea level: " + this.seaLevel); - debug.add("Elythia cloud sea: y>=" + this.cloudSeaMinY + " in ~1/" + CLOUD_SEA_CHANCE_DENOMINATOR + " columns"); + return this.fallbackHolder != null ? this.fallbackHolder : biome; } } diff --git a/common-1.21.1/src/main/resources/assets/antarchy/textures/item/spirit_apple.png b/common-1.21.1/src/main/resources/assets/antarchy/textures/item/spirit_apple.png index 118f47e5..b2d128d7 100644 Binary files a/common-1.21.1/src/main/resources/assets/antarchy/textures/item/spirit_apple.png and b/common-1.21.1/src/main/resources/assets/antarchy/textures/item/spirit_apple.png differ diff --git a/common-1.21.1/src/main/resources/data/antarchy/dimension/elythia.json b/common-1.21.1/src/main/resources/data/antarchy/dimension/elythia.json index 655912d3..13aa0378 100644 --- a/common-1.21.1/src/main/resources/data/antarchy/dimension/elythia.json +++ b/common-1.21.1/src/main/resources/data/antarchy/dimension/elythia.json @@ -4,7 +4,8 @@ "type": "minecraft:noise", "settings": "antarchy:elythia", "biome_source": { - "type": "minecraft:multi_noise", + "type": "antarchy:elythia_biome_source", + "cloud_sea_min_y": 250, "biomes": [ { "biome": "antarchy:elythia_ocean", @@ -113,6 +114,18 @@ "depth": [0.0, 0.35], "offset": 0.0 } + }, + { + "biome": "antarchy:cloud_sea", + "parameters": { + "temperature": [-1.0, 1.0], + "humidity": [-1.0, 1.0], + "continentalness": [-1.0, 1.0], + "erosion": [-1.0, 1.0], + "weirdness": [-1.0, 1.0], + "depth": [-1.0, 1.0], + "offset": 1.0 + } } ] } diff --git a/common-1.21.1/src/main/resources/data/antarchy/worldgen/structure/tigers_eye_shrine.json b/common-1.21.1/src/main/resources/data/antarchy/worldgen/structure/tigers_eye_shrine.json index ed4432fa..4afe9bca 100644 --- a/common-1.21.1/src/main/resources/data/antarchy/worldgen/structure/tigers_eye_shrine.json +++ b/common-1.21.1/src/main/resources/data/antarchy/worldgen/structure/tigers_eye_shrine.json @@ -2,8 +2,6 @@ "type": "integrated_api:generic_structure", "start_pool": "antarchy:tigers_eye_shrine/tigers_eye_shrine", "size": 1, - "terrain_height_radius_check": 4, - "allowed_terrain_height_range": 14, "valid_biome_radius_check": 1, "biomes": "#antarchy:has_structure/tigers_eye_shrine_biomes", "step": "underground_structures", diff --git a/fabric-1.21.1/build.gradle b/fabric-1.21.1/build.gradle index 02718db5..12466645 100644 --- a/fabric-1.21.1/build.gradle +++ b/fabric-1.21.1/build.gradle @@ -38,8 +38,7 @@ dependencies { modImplementation "net.fabricmc:fabric-loader:${fabric_loader_version_1_21_1}" modApi "net.fabricmc.fabric-api:fabric-api:${fabric_api_version_1_21_1}" modImplementation "software.bernie.geckolib:geckolib-fabric-1.21.1:${geckolib_version}" - // AntOS is developed beside Antarchy as a separate local project. - modImplementation files("$rootDir/../AntOS/fabric-1.21.1/build/libs/antos-fabric-1.21.1-1.0.1.jar") + modImplementation("curse.maven:antos-${antos_curseforge_id}:${antos_curseforge_file_id_fabric}") modCompileOnly("curse.maven:intapi-${intapi_curseforge_id}:${intapi_curseforge_file_id_fabric}") modLocalRuntime("curse.maven:intapi-${intapi_curseforge_id}:${intapi_curseforge_file_id_fabric}") modLocalRuntime("dev.architectury:architectury-fabric:${architectury_api_version}") @@ -90,6 +89,7 @@ tasks.named('processResources', ProcessResources).configure { version : project.version, minecraft_version : "1.21.1", fabric_loader_version: fabric_loader_version_1_21_1, + architectury_api_version: architectury_api_version, mod_id : mod_id, mod_name : mod_name, mod_description : mod_description, diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabricContent.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabricContent.java index 7aee173c..029b4107 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabricContent.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabricContent.java @@ -111,6 +111,7 @@ public final class AntarchyFabricContent { AntarchyFabricMisc.ARMOR_MATERIALS.register(); AntarchyFabricMisc.FLUIDS.register(); AntarchyFabricBlocks.BLOCKS.register(); + AntarchyFabricBlocks.registerStripping(); AntarchyFabricEntities.ENTITY_TYPES.register(); AntarchyFabricMisc.ATTRIBUTES.register(); AntarchyFabricEntityAttributes.register(); diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/AntarchyFabricClientBootstrap.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/AntarchyFabricClientBootstrap.java index 87e5e4a0..d2cd07d4 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/AntarchyFabricClientBootstrap.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/AntarchyFabricClientBootstrap.java @@ -129,6 +129,8 @@ public final class AntarchyFabricClientBootstrap { EntityRendererRegistry.register(AntarchyFabricEntities.NADIR_CHEST_BOAT_ENTITY.get(), context -> new PeachBoatRenderer<>(context, ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/chest_boat/nadir.png"), true)); EntityRendererRegistry.register(AntarchyFabricEntities.ROYAL_BOAT_ENTITY.get(), context -> new PeachBoatRenderer<>(context, ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/boat/royal.png"), false)); EntityRendererRegistry.register(AntarchyFabricEntities.ROYAL_CHEST_BOAT_ENTITY.get(), context -> new PeachBoatRenderer<>(context, ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/chest_boat/royal.png"), true)); + EntityRendererRegistry.register(AntarchyFabricEntities.TRUFFALO_BOAT_ENTITY.get(), context -> new PeachBoatRenderer<>(context, ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/boat/truffalo.png"), false)); + EntityRendererRegistry.register(AntarchyFabricEntities.TRUFFALO_CHEST_BOAT_ENTITY.get(), context -> new PeachBoatRenderer<>(context, ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/chest_boat/truffalo.png"), true)); EntityRendererRegistry.register(AntarchyFabricEntities.APPLE_COW.get(), context -> withTemporalGeoLayer(new AppleCowRenderer(context))); EntityRendererRegistry.register(AntarchyFabricEntities.GOLDEN_APPLE_COW.get(), context -> withTemporalGeoLayer(new AppleCowRenderer(context))); EntityRendererRegistry.register(AntarchyFabricEntities.ENCHANTED_GOLDEN_APPLE_COW.get(), context -> withTemporalGeoLayer(new AppleCowRenderer(context))); @@ -590,6 +592,7 @@ public final class AntarchyFabricClientBootstrap { ElythiaFireflyManager.register(); LucidSoundHandler.register(); + TearIdleSoundHandler.register(); MogglesClientRenderer.register(); StinkySoundHandler.register(); ReverieTrailHandler.register(); diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/KeybindingConflictFixStore.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/KeybindingConflictFixStore.java index c65f50a0..80d3b36d 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/KeybindingConflictFixStore.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/KeybindingConflictFixStore.java @@ -9,13 +9,14 @@ import net.minecraft.client.KeyMapping; public final class KeybindingConflictFixStore { private static final String ANTARCHY_KEY_PREFIX = "key.antarchy."; + private static final String SPRINT_KEY = "key.sprint"; private static final Map> MAPPINGS = new HashMap<>(); private KeybindingConflictFixStore() { } public static void add(InputConstants.Key key, KeyMapping mapping) { - if (!mapping.getName().startsWith(ANTARCHY_KEY_PREFIX)) { + if (!isTracked(mapping)) { return; } List mappings = MAPPINGS.computeIfAbsent(key, ignored -> new ArrayList<>()); @@ -41,4 +42,12 @@ public final class KeybindingConflictFixStore { } return others; } + + public static boolean isSprint(KeyMapping mapping) { + return SPRINT_KEY.equals(mapping.getName()); + } + + private static boolean isTracked(KeyMapping mapping) { + return mapping.getName().startsWith(ANTARCHY_KEY_PREFIX) || isSprint(mapping); + } } diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/TearIdleSoundHandler.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/TearIdleSoundHandler.java new file mode 100644 index 00000000..34352e1f --- /dev/null +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/client/TearIdleSoundHandler.java @@ -0,0 +1,112 @@ +package com.craisinlord.antarchy.fabric.client; + +import com.craisinlord.antarchy.content.AntarchySoundEvents; +import com.craisinlord.antarchy.content.entity.portal.DimensionalTearEntity; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance; +import net.minecraft.sounds.SoundSource; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public final class TearIdleSoundHandler { + private static final double START_SCAN_RADIUS = 64.0D; + private static final int DISCOVERY_SCAN_INTERVAL_TICKS = 10; + private static final Map ACTIVE_LOOPS = new HashMap<>(); + private static long nextDiscoveryScanTick; + + private TearIdleSoundHandler() { + } + + public static void register() { + ClientTickEvents.END_CLIENT_TICK.register(client -> { + if (client.level == null || client.player == null || client.isPaused()) { + resetAll(client); + return; + } + + pruneStaleLoops(client); + + long gameTime = client.level.getGameTime(); + if (gameTime >= nextDiscoveryScanTick) { + nextDiscoveryScanTick = gameTime + DISCOVERY_SCAN_INTERVAL_TICKS; + discoverNearbyTears(client); + } + }); + } + + private static void discoverNearbyTears(Minecraft mc) { + List tears = mc.level.getEntitiesOfClass( + DimensionalTearEntity.class, + mc.player.getBoundingBox().inflate(START_SCAN_RADIUS) + ); + + for (DimensionalTearEntity tear : tears) { + if (!tear.shouldPlayIdleSound() || ACTIVE_LOOPS.containsKey(tear.getUUID())) { + continue; + } + TearIdleSound sound = new TearIdleSound(tear); + ACTIVE_LOOPS.put(tear.getUUID(), sound); + mc.getSoundManager().play(sound); + } + } + + private static void pruneStaleLoops(Minecraft mc) { + Iterator> iterator = ACTIVE_LOOPS.entrySet().iterator(); + while (iterator.hasNext()) { + TearIdleSound sound = iterator.next().getValue(); + if (!sound.isValid()) { + mc.getSoundManager().stop(sound); + iterator.remove(); + } + } + } + + private static void resetAll(Minecraft mc) { + for (TearIdleSound sound : ACTIVE_LOOPS.values()) { + mc.getSoundManager().stop(sound); + } + ACTIVE_LOOPS.clear(); + nextDiscoveryScanTick = 0L; + } + + private static final class TearIdleSound extends AbstractTickableSoundInstance { + private final DimensionalTearEntity tear; + + private TearIdleSound(DimensionalTearEntity tear) { + super(AntarchySoundEvents.DIMENSIONAL_TEAR_IDLE.get(), SoundSource.HOSTILE, tear.getRandom()); + this.tear = tear; + this.looping = true; + this.delay = 0; + this.volume = 0.6F; + this.pitch = 1.0F; + this.x = tear.getX(); + this.y = tear.getY(); + this.z = tear.getZ(); + } + + private boolean isValid() { + return !this.tear.isRemoved() && this.tear.shouldPlayIdleSound(); + } + + @Override + public void tick() { + if (!this.isValid()) { + this.stop(); + return; + } + this.x = this.tear.getX(); + this.y = this.tear.getY(); + this.z = this.tear.getZ(); + } + + @Override + public boolean canStartSilent() { + return true; + } + } +} diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/mixin/client/KeybindingConflictFixMixin.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/mixin/client/KeybindingConflictFixMixin.java index f7141bf8..5d67b246 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/mixin/client/KeybindingConflictFixMixin.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/mixin/client/KeybindingConflictFixMixin.java @@ -19,6 +19,7 @@ public abstract class KeybindingConflictFixMixin { @Shadow @Final private static Map ALL; @Shadow private InputConstants.Key key; @Shadow private boolean isDown; + @Shadow private int clickCount; @Inject(method = "(Ljava/lang/String;Lcom/mojang/blaze3d/platform/InputConstants$Type;ILjava/lang/String;)V", at = @At("TAIL")) private void antarchy$addInitialMapping(String name, InputConstants.Type type, int key, String category, CallbackInfo ci) { @@ -44,8 +45,31 @@ public abstract class KeybindingConflictFixMixin { } } + @Inject(method = "click", at = @At("TAIL")) + private static void antarchy$clickConflicts(InputConstants.Key key, CallbackInfo ci) { + if (!AntarchySettings.fabricKeybindingConflictFixEnabled()) { + return; + } + KeyMapping active = MAP.get(key); + for (KeyMapping mapping : KeybindingConflictFixStore.others(key, active)) { + if (((KeybindingConflictFixMixin) (Object) mapping).antarchy$isSprint()) { + ((KeybindingConflictFixMixin) (Object) mapping).antarchy$click(); + } + } + } + @Unique private void antarchy$setDown(boolean down) { this.isDown = down; } + + @Unique + private boolean antarchy$isSprint() { + return KeybindingConflictFixStore.isSprint((KeyMapping) (Object) this); + } + + @Unique + private void antarchy$click() { + this.clickCount++; + } } diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricBlocks.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricBlocks.java index 391615cc..b7de8e40 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricBlocks.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricBlocks.java @@ -51,6 +51,7 @@ import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.block.Mirror; import net.minecraft.world.level.block.Rotation; +import net.fabricmc.fabric.api.registry.StrippableBlockRegistry; public final class AntarchyFabricBlocks { @@ -1759,4 +1760,17 @@ public final class AntarchyFabricBlocks { BLOCK_ENTITY_TYPES.register(); } + public static void registerStripping() { + StrippableBlockRegistry.register(OURANWOOD_LOG.get(), STRIPPED_OURANWOOD_LOG.get()); + StrippableBlockRegistry.register(OURANWOOD_WOOD.get(), STRIPPED_OURANWOOD_WOOD.get()); + StrippableBlockRegistry.register(PEACH_LOG.get(), STRIPPED_PEACH_LOG.get()); + StrippableBlockRegistry.register(PEACH_WOOD.get(), STRIPPED_PEACH_WOOD.get()); + StrippableBlockRegistry.register(NADIR_LOG.get(), STRIPPED_NADIR_LOG.get()); + StrippableBlockRegistry.register(NADIR_WOOD.get(), STRIPPED_NADIR_WOOD.get()); + StrippableBlockRegistry.register(ROYAL_LOG.get(), STRIPPED_ROYAL_LOG.get()); + StrippableBlockRegistry.register(ROYAL_WOOD.get(), STRIPPED_ROYAL_WOOD.get()); + StrippableBlockRegistry.register(TRUFFALO_LOG.get(), STRIPPED_TRUFFALO_LOG.get()); + StrippableBlockRegistry.register(TRUFFALO_WOOD.get(), STRIPPED_TRUFFALO_WOOD.get()); + } + } diff --git a/fabric-1.21.1/src/main/resources/fabric.mod.json b/fabric-1.21.1/src/main/resources/fabric.mod.json index 941f4981..0a2aa49f 100644 --- a/fabric-1.21.1/src/main/resources/fabric.mod.json +++ b/fabric-1.21.1/src/main/resources/fabric.mod.json @@ -36,6 +36,7 @@ "minecraft": "~${minecraft_version}", "java": ">=21", "fabric-api": "*", + "architectury": "${architectury_api_version}", "integrated_api": "*", "geckolib": "*", "sizeable_foliage": "*" diff --git a/gradle.properties b/gradle.properties index 6125eb47..fd23f8a6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ org.gradle.configureondemand=true minecraft_version_1_21_1=1.21.1 modid=antarchy mod_id=antarchy -mod_version=2.0.0 +mod_version=2.0.2 maven_group=com.craisinlord mixin_version=0.15.4+mixin.0.8.7 @@ -57,6 +57,10 @@ intapi_curseforge_file_id_neoforge = 7921681 intapi_curseforge_file_id_fabric = 7921674 intapi_curseforge_file_id_common = 5178461 +antos_curseforge_id = 1700593 +antos_curseforge_file_id_neoforge = 8936372 +antos_curseforge_file_id_fabric = 8936369 + create_curseforge_id_neoforge = 328085 #create_curseforge_id_fabric = 624165 create_curseforge_file_id_neoforge = 7408951 diff --git a/neoforge-1.21.1/build.gradle b/neoforge-1.21.1/build.gradle index ec401387..06e66f62 100644 --- a/neoforge-1.21.1/build.gradle +++ b/neoforge-1.21.1/build.gradle @@ -46,9 +46,8 @@ neoForge { } dependencies { - // AntOS is developed beside Antarchy as a separate local project. - compileOnly(files("$rootDir/../AntOS/neoforge-1.21.1/build/libs/antos-neoforge-1.21.1-1.0.1.jar")) - runtimeOnly(files("$rootDir/../AntOS/neoforge-1.21.1/build/libs/antos-neoforge-1.21.1-1.0.1.jar")) + compileOnly("curse.maven:antos-${antos_curseforge_id}:${antos_curseforge_file_id_neoforge}") + runtimeOnly("curse.maven:antos-${antos_curseforge_id}:${antos_curseforge_file_id_neoforge}") compileOnly("curse.maven:intapi-${intapi_curseforge_id}:${intapi_curseforge_file_id_neoforge}") runtimeOnly("curse.maven:intapi-${intapi_curseforge_id}:${intapi_curseforge_file_id_neoforge}") implementation "software.bernie.geckolib:geckolib-neoforge-1.21.1:${geckolib_version}" @@ -79,7 +78,10 @@ dependencies { tasks.withType(ProcessResources).configureEach { duplicatesStrategy = DuplicatesStrategy.EXCLUDE - var replaceProperties = [version: project.version] + var replaceProperties = [ + version: project.version, + architectury_api_version: architectury_api_version + ] inputs.properties replaceProperties filesMatching('META-INF/neoforge.mods.toml') { diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMobsConfig.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMobsConfig.java index 2d63eac4..55c654d7 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMobsConfig.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMobsConfig.java @@ -993,8 +993,8 @@ public final class AntarchyMobsConfig { b.pop(); b.push("manticore"); - MANTICORE_HEALTH = b.comment("Base max health.").defineInRange("health", 40.0D, 1.0D, 32768.0D); - MANTICORE_ATTACK_DAMAGE = b.comment("Base attack damage for bites and stings.").defineInRange("attackDamage", 7.0D, 0.0D, 1024.0D); + MANTICORE_HEALTH = b.comment("Base max health.").defineInRange("health", 60.0D, 1.0D, 32768.0D); + MANTICORE_ATTACK_DAMAGE = b.comment("Base attack damage for bites and stings.").defineInRange("attackDamage", 11.0D, 0.0D, 1024.0D); MANTICORE_STING_POISON_TICKS = b.comment("Poison duration in ticks applied by a Manticore sting.").defineInRange("stingPoisonTicks", 100, 0, 12000); QUEEN_MANTICORE_CAP = b.comment("Maximum number of living Manticores a single Queen may keep summoned.").defineInRange("queenSummonCap", 6, 1, 200); QUEEN_MANTICORE_SUMMON_COOLDOWN_TICKS = b.comment("Ticks between Queen Manticore summon attempts.").defineInRange("queenSummonCooldownTicks", 800, 20, 200000); diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/AntarchyNeoForgeClient.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/AntarchyNeoForgeClient.java index c449801e..9b200354 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/AntarchyNeoForgeClient.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/AntarchyNeoForgeClient.java @@ -83,6 +83,8 @@ public final class AntarchyNeoForgeClient { private static final ResourceLocation NADIR_CHEST_BOAT_TEXTURE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/chest_boat/nadir.png"); private static final ResourceLocation ROYAL_BOAT_TEXTURE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/boat/royal.png"); private static final ResourceLocation ROYAL_CHEST_BOAT_TEXTURE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/chest_boat/royal.png"); + private static final ResourceLocation TRUFFALO_BOAT_TEXTURE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/boat/truffalo.png"); + private static final ResourceLocation TRUFFALO_CHEST_BOAT_TEXTURE = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/chest_boat/truffalo.png"); private static final ResourceLocation WATER_STILL = ResourceLocation.withDefaultNamespace("block/water_still"); private static final ResourceLocation WATER_FLOW = ResourceLocation.withDefaultNamespace("block/water_flow"); private static final ResourceLocation WATER_OVERLAY = ResourceLocation.withDefaultNamespace("block/water_overlay"); @@ -134,6 +136,8 @@ public final class AntarchyNeoForgeClient { event.registerEntityRenderer(AntarchyNeoforgeEntites.NADIR_CHEST_BOAT_ENTITY.get(), context -> new PeachBoatRenderer<>(context, NADIR_CHEST_BOAT_TEXTURE, true)); event.registerEntityRenderer(AntarchyNeoforgeEntites.ROYAL_BOAT_ENTITY.get(), context -> new PeachBoatRenderer<>(context, ROYAL_BOAT_TEXTURE, false)); event.registerEntityRenderer(AntarchyNeoforgeEntites.ROYAL_CHEST_BOAT_ENTITY.get(), context -> new PeachBoatRenderer<>(context, ROYAL_CHEST_BOAT_TEXTURE, true)); + event.registerEntityRenderer(AntarchyNeoforgeEntites.TRUFFALO_BOAT_ENTITY.get(), context -> new PeachBoatRenderer<>(context, TRUFFALO_BOAT_TEXTURE, false)); + event.registerEntityRenderer(AntarchyNeoforgeEntites.TRUFFALO_CHEST_BOAT_ENTITY.get(), context -> new PeachBoatRenderer<>(context, TRUFFALO_CHEST_BOAT_TEXTURE, true)); event.registerEntityRenderer(AntarchyNeoforgeEntites.APPLE_COW.get(), context -> withParalyzedGeoLayer(new AppleCowRenderer(context))); event.registerEntityRenderer(AntarchyNeoforgeEntites.GOLDEN_APPLE_COW.get(), context -> withParalyzedGeoLayer(new AppleCowRenderer(context))); event.registerEntityRenderer(AntarchyNeoforgeEntites.ENCHANTED_GOLDEN_APPLE_COW.get(), context -> withParalyzedGeoLayer(new AppleCowRenderer(context))); diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/TearIdleSoundHandler.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/TearIdleSoundHandler.java new file mode 100644 index 00000000..85d619ac --- /dev/null +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/client/TearIdleSoundHandler.java @@ -0,0 +1,117 @@ +package com.craisinlord.antarchy.neoforge.client; + +import com.craisinlord.antarchy.Antarchy; +import com.craisinlord.antarchy.content.AntarchySoundEvents; +import com.craisinlord.antarchy.content.entity.portal.DimensionalTearEntity; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance; +import net.minecraft.sounds.SoundSource; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.event.ClientTickEvent; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +@EventBusSubscriber(modid = Antarchy.MODID, value = Dist.CLIENT) +public final class TearIdleSoundHandler { + private static final double START_SCAN_RADIUS = 64.0D; + private static final int DISCOVERY_SCAN_INTERVAL_TICKS = 10; + private static final Map ACTIVE_LOOPS = new HashMap<>(); + private static long nextDiscoveryScanTick; + + private TearIdleSoundHandler() { + } + + @SubscribeEvent + public static void onClientTick(ClientTickEvent.Post event) { + Minecraft mc = Minecraft.getInstance(); + if (mc.level == null || mc.player == null || mc.isPaused()) { + resetAll(mc); + return; + } + + pruneStaleLoops(mc); + + long gameTime = mc.level.getGameTime(); + if (gameTime >= nextDiscoveryScanTick) { + nextDiscoveryScanTick = gameTime + DISCOVERY_SCAN_INTERVAL_TICKS; + discoverNearbyTears(mc); + } + } + + private static void discoverNearbyTears(Minecraft mc) { + List tears = mc.level.getEntitiesOfClass( + DimensionalTearEntity.class, + mc.player.getBoundingBox().inflate(START_SCAN_RADIUS) + ); + + for (DimensionalTearEntity tear : tears) { + if (!tear.shouldPlayIdleSound() || ACTIVE_LOOPS.containsKey(tear.getUUID())) { + continue; + } + TearIdleSound sound = new TearIdleSound(tear); + ACTIVE_LOOPS.put(tear.getUUID(), sound); + mc.getSoundManager().play(sound); + } + } + + private static void pruneStaleLoops(Minecraft mc) { + Iterator> iterator = ACTIVE_LOOPS.entrySet().iterator(); + while (iterator.hasNext()) { + TearIdleSound sound = iterator.next().getValue(); + if (!sound.isValid()) { + mc.getSoundManager().stop(sound); + iterator.remove(); + } + } + } + + private static void resetAll(Minecraft mc) { + for (TearIdleSound sound : ACTIVE_LOOPS.values()) { + mc.getSoundManager().stop(sound); + } + ACTIVE_LOOPS.clear(); + nextDiscoveryScanTick = 0L; + } + + private static final class TearIdleSound extends AbstractTickableSoundInstance { + private final DimensionalTearEntity tear; + + private TearIdleSound(DimensionalTearEntity tear) { + super(AntarchySoundEvents.DIMENSIONAL_TEAR_IDLE.get(), SoundSource.HOSTILE, tear.getRandom()); + this.tear = tear; + this.looping = true; + this.delay = 0; + this.volume = 0.6F; + this.pitch = 1.0F; + this.x = tear.getX(); + this.y = tear.getY(); + this.z = tear.getZ(); + } + + private boolean isValid() { + return !this.tear.isRemoved() && this.tear.shouldPlayIdleSound(); + } + + @Override + public void tick() { + if (!this.isValid()) { + this.stop(); + return; + } + this.x = this.tear.getX(); + this.y = this.tear.getY(); + this.z = this.tear.getZ(); + } + + @Override + public boolean canStartSilent() { + return true; + } + } +} diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeBlocks.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeBlocks.java index 12ec828b..65d25465 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeBlocks.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeBlocks.java @@ -32,6 +32,7 @@ import net.minecraft.core.registries.Registries; import net.minecraft.sounds.SoundEvent; import net.minecraft.util.valueproviders.UniformInt; import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.block.*; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockBehaviour; @@ -43,6 +44,8 @@ import net.minecraft.world.level.block.state.properties.WoodType; import net.minecraft.world.level.material.FlowingFluid; import net.minecraft.world.level.material.FluidState; import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.common.ItemAbilities; +import net.neoforged.neoforge.common.ItemAbility; import net.neoforged.neoforge.fluids.BaseFlowingFluid; import net.neoforged.neoforge.registries.DeferredBlock; import net.neoforged.neoforge.registries.DeferredHolder; @@ -265,9 +268,25 @@ public final class AntarchyNeoforgeBlocks { public static final DeferredBlock ROYAL_WALL_HANGING_SIGN = BLOCKS.register("royal_wall_hanging_sign", () -> new WallHangingSignBlock(AntarchyWoodTypes.ROYAL, BlockBehaviour.Properties.ofFullCopy(Blocks.JUNGLE_WALL_HANGING_SIGN))); public static final DeferredBlock TRUFFALO_LOG = BLOCKS.register("truffalo_log", - () -> new TruffaloLogBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.JUNGLE_LOG))); + () -> new TruffaloLogBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.JUNGLE_LOG)) { + @Override + public BlockState getToolModifiedState(BlockState state, UseOnContext context, ItemAbility itemAbility, boolean simulate) { + if (itemAbility == ItemAbilities.AXE_STRIP) { + return STRIPPED_TRUFFALO_LOG.get().withPropertiesOf(state); + } + return super.getToolModifiedState(state, context, itemAbility, simulate); + } + }); public static final DeferredBlock TRUFFALO_WOOD = BLOCKS.register("truffalo_wood", - () -> new RotatedPillarBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.JUNGLE_WOOD))); + () -> new RotatedPillarBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.JUNGLE_WOOD)) { + @Override + public BlockState getToolModifiedState(BlockState state, UseOnContext context, ItemAbility itemAbility, boolean simulate) { + if (itemAbility == ItemAbilities.AXE_STRIP) { + return STRIPPED_TRUFFALO_WOOD.get().withPropertiesOf(state); + } + return super.getToolModifiedState(state, context, itemAbility, simulate); + } + }); public static final DeferredBlock STRIPPED_TRUFFALO_LOG = BLOCKS.register("stripped_truffalo_log", () -> new TruffaloLogBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.STRIPPED_JUNGLE_LOG))); public static final DeferredBlock STRIPPED_TRUFFALO_WOOD = BLOCKS.register("stripped_truffalo_wood", diff --git a/neoforge-1.21.1/src/main/resources/META-INF/neoforge.mods.toml b/neoforge-1.21.1/src/main/resources/META-INF/neoforge.mods.toml index 4367d003..8ceb2e7c 100644 --- a/neoforge-1.21.1/src/main/resources/META-INF/neoforge.mods.toml +++ b/neoforge-1.21.1/src/main/resources/META-INF/neoforge.mods.toml @@ -26,7 +26,14 @@ displayURL="https://www.curseforge.com/minecraft/mc-mods/antarchy" versionRange="[1.21.1,)" [[dependencies.antarchy]] - modId="antos" + modId="architectury" + type="required" + versionRange="[${architectury_api_version},)" + ordering="AFTER" + side="BOTH" + +[[dependencies.antarchy]] +modId="antos" type="required" versionRange="*" ordering="AFTER"