2.2.9
2.2.9
This commit is contained in:
222 files changed
+2778
-1495
No files matched your search
@@ -10,9 +10,6 @@ allprojects {
|
||||
group = rootProject.maven_group
|
||||
|
||||
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 {
|
||||
name = "CurseMaven"
|
||||
url = "https://www.cursemaven.com"
|
||||
@@ -63,13 +60,10 @@ allprojects {
|
||||
|
||||
}
|
||||
|
||||
// Don't build the root project itself.
|
||||
tasks.named('jar') {
|
||||
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 forge1201Wrapper = providers.systemProperty('os.name').get().toLowerCase().contains('win')
|
||||
? 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 fabric120Wrapper = providers.systemProperty('os.name').get().toLowerCase().contains('win')
|
||||
? new File(fabric120Dir, 'gradlew.bat')
|
||||
|
||||
@@ -6,7 +6,6 @@ base {
|
||||
archivesName = "${mod_id}-common-1.20.1"
|
||||
}
|
||||
|
||||
// Source-only module — each loader module compiles these sources itself.
|
||||
tasks.named('compileJava').configure {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
@@ -107,6 +107,9 @@ public final class AntarchySettings {
|
||||
private static int ultimateCrossbowEnchantability = 20;
|
||||
private static int ultimateMaceEnchantability = 20;
|
||||
private static boolean ultimateToolsThreeByThreeEnabled = true;
|
||||
private static boolean ultimateToolsVeinMiningEnabled = true;
|
||||
private static int ultimateToolsVeinMiningMaxBlocks = 64;
|
||||
private static int ultimateToolsTreeFellingMaxLogs = 128;
|
||||
private static boolean ultimateArmorComesEnchanted = true;
|
||||
private static int ultimateHelmetArmorValue = 6;
|
||||
private static int ultimateChestplateArmorValue = 11;
|
||||
@@ -299,6 +302,7 @@ public final class AntarchySettings {
|
||||
private static double royalBossKnockbackResistance = 1.0D;
|
||||
private static double royalBossStepHeight = 3.0D;
|
||||
private static double royalBossMaxSingleHitDamage = 250.0D;
|
||||
private static double royalBossHitOverflowRate = 0.25D;
|
||||
private static double royalBossBiteReach = 12.0D;
|
||||
private static double royalBossBiteDamageMultiplier = 1.6D;
|
||||
private static int royalBossBiteCooldownTicks = 45;
|
||||
@@ -974,6 +978,18 @@ public final class AntarchySettings {
|
||||
return ultimateToolsThreeByThreeEnabled;
|
||||
}
|
||||
|
||||
public static boolean ultimateToolsVeinMiningEnabled() {
|
||||
return ultimateToolsVeinMiningEnabled;
|
||||
}
|
||||
|
||||
public static int ultimateToolsVeinMiningMaxBlocks() {
|
||||
return ultimateToolsVeinMiningMaxBlocks;
|
||||
}
|
||||
|
||||
public static int ultimateToolsTreeFellingMaxLogs() {
|
||||
return ultimateToolsTreeFellingMaxLogs;
|
||||
}
|
||||
|
||||
public static boolean ultimateArmorComesEnchanted() {
|
||||
return ultimateArmorComesEnchanted;
|
||||
}
|
||||
@@ -1624,6 +1640,18 @@ public final class AntarchySettings {
|
||||
ultimateToolsThreeByThreeEnabled = value;
|
||||
}
|
||||
|
||||
public static void setUltimateToolsVeinMiningEnabled(boolean value) {
|
||||
ultimateToolsVeinMiningEnabled = value;
|
||||
}
|
||||
|
||||
public static void setUltimateToolsVeinMiningMaxBlocks(int value) {
|
||||
ultimateToolsVeinMiningMaxBlocks = value;
|
||||
}
|
||||
|
||||
public static void setUltimateToolsTreeFellingMaxLogs(int value) {
|
||||
ultimateToolsTreeFellingMaxLogs = value;
|
||||
}
|
||||
|
||||
public static void setUltimateArmorComesEnchanted(boolean value) {
|
||||
ultimateArmorComesEnchanted = value;
|
||||
}
|
||||
@@ -2229,6 +2257,9 @@ public final class AntarchySettings {
|
||||
public static double royalBossMaxSingleHitDamage() { return royalBossMaxSingleHitDamage; }
|
||||
public static void setRoyalBossMaxSingleHitDamage(double v) { royalBossMaxSingleHitDamage = v; }
|
||||
|
||||
public static double royalBossHitOverflowRate() { return royalBossHitOverflowRate; }
|
||||
public static void setRoyalBossHitOverflowRate(double v) { royalBossHitOverflowRate = v; }
|
||||
|
||||
public static double royalBossBiteReach() { return royalBossBiteReach; }
|
||||
public static void setRoyalBossBiteReach(double v) { royalBossBiteReach = v; }
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
|
||||
public final class AntarchyTags {
|
||||
@@ -157,4 +158,11 @@ public final class AntarchyTags {
|
||||
private Biomes() {
|
||||
}
|
||||
}
|
||||
|
||||
public static final class DimensionTypes {
|
||||
public static final TagKey<DimensionType> NO_MANTIS_CLIMB = TagKey.create(Registries.DIMENSION_TYPE, id("no_mantis_climb"));
|
||||
|
||||
private DimensionTypes() {
|
||||
}
|
||||
}
|
||||
}
|
||||
-1
@@ -17,7 +17,6 @@ public final class MoonSkyTracker {
|
||||
private static final long MAX_AGE_MILLIS = 1500L;
|
||||
private static final double AIM_COSINE = Math.cos(Math.toRadians(PortalGunMoonMath.AIM_TOLERANCE_DEGREES));
|
||||
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 long recordedAt;
|
||||
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 float MISSING_BRIGHTNESS = 0.3F;
|
||||
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 long cachedGameTime = Long.MIN_VALUE;
|
||||
private static UUID cachedGunId;
|
||||
|
||||
-1
@@ -12,7 +12,6 @@ import net.minecraft.client.multiplayer.ClientLevel;
|
||||
|
||||
public final class PortalGunIndicatorClientState {
|
||||
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 long lastRequestTick = Long.MIN_VALUE;
|
||||
private static UUID lastRequestedGun;
|
||||
|
||||
+11
@@ -11,6 +11,12 @@ import software.bernie.geckolib.model.GeoModel;
|
||||
|
||||
public class RoyalMountModel extends GeoModel<RoyalMountEntity> {
|
||||
private static final String[] HEADS = {"head_left", "head", "head_right"};
|
||||
private static final String[] RIDDEN_NECK_CHAIN = {
|
||||
"neck", "neck2", "neck3", "head",
|
||||
"neck_left", "neck_left2", "neck_left3", "head_left",
|
||||
"neck_right", "neck_right2", "neck_right3", "head_right"
|
||||
};
|
||||
private static final float RIDDEN_NECK_RAISE = 0.35F;
|
||||
|
||||
@Override
|
||||
public ResourceLocation getModelResource(RoyalMountEntity animatable) {
|
||||
@@ -31,6 +37,11 @@ public class RoyalMountModel extends GeoModel<RoyalMountEntity> {
|
||||
public void setCustomAnimations(RoyalMountEntity animatable, long instanceId,
|
||||
AnimationState<RoyalMountEntity> animationState) {
|
||||
super.setCustomAnimations(animatable, instanceId, animationState);
|
||||
if (animatable.isVehicle()) {
|
||||
for (String name : RIDDEN_NECK_CHAIN) {
|
||||
this.getBone(name).ifPresent(bone -> bone.setRotX(bone.getRotX() * RIDDEN_NECK_RAISE));
|
||||
}
|
||||
}
|
||||
for (String head : HEADS) {
|
||||
this.getBone(head).ifPresent(bone -> bone.setTrackingMatrices(true));
|
||||
}
|
||||
|
||||
+1
@@ -21,6 +21,7 @@ public final class BloodglassWardEffect extends MobEffect {
|
||||
public void addAttributeModifiers(net.minecraft.world.entity.LivingEntity livingEntity, AttributeMap attributeMap, int amplifier) {
|
||||
AttributeInstance instance = attributeMap.getInstance(AntarchyObjects.BLOODGLASS_MAX_HEARTS.get());
|
||||
if (instance == null) return;
|
||||
instance.removeModifier(MODIFIER_ID);
|
||||
instance.addTransientModifier(
|
||||
new AttributeModifier(MODIFIER_ID, "bloodglass_ward_hearts", amplifier + 1, AttributeModifier.Operation.ADDITION)
|
||||
);
|
||||
|
||||
+26
-3
@@ -392,6 +392,9 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
|
||||
if (this.isKnockedDown()) {
|
||||
this.tickKnockedDown();
|
||||
} else if (this.isLeashed()) {
|
||||
if (this.chargeTicksRemaining > 0 || this.isChargeAnimationActive()) {
|
||||
this.endChargeState();
|
||||
}
|
||||
this.getNavigation().stop();
|
||||
this.setTarget(null);
|
||||
this.updateAmbientAnimation();
|
||||
@@ -484,6 +487,10 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
|
||||
}
|
||||
|
||||
private void tickCharge() {
|
||||
if (this.chargeTicksRemaining <= 0) {
|
||||
this.endChargeState();
|
||||
return;
|
||||
}
|
||||
if (this.getAnimationState() != ANIM_CHARGE) {
|
||||
this.setAnimationState(ANIM_CHARGE);
|
||||
}
|
||||
@@ -910,6 +917,9 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
|
||||
if (!this.isFlying() && !mountedCharge) {
|
||||
this.pendingChargeStart = true;
|
||||
this.requestFlightStart();
|
||||
if (this.getAnimationState() != ANIM_OPEN_WINGS) {
|
||||
this.pendingChargeStart = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.beginChargeStart(this.chargeDirection, this.pendingChargeDuration, mountedCharge);
|
||||
@@ -979,13 +989,23 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
|
||||
serverLevel.sendParticles(ParticleTypes.CRIT, this.getX(), this.getY() + 0.8D, this.getZ(), 20, 2.0D, 0.6D, 2.0D, 0.08D);
|
||||
this.broadcastImpactShake(serverLevel);
|
||||
|
||||
if (this.onGround()) {
|
||||
this.endChargeState();
|
||||
}
|
||||
|
||||
private void endChargeState() {
|
||||
this.chargeTicksRemaining = 0;
|
||||
this.groundedMountedCharge = false;
|
||||
this.noPhysics = false;
|
||||
this.setAnimationState(this.isFlying() ? ANIM_FLY : ANIM_IDLE);
|
||||
if (!this.isVehicle() && this.isFlying() && this.hasGroundBelow()) {
|
||||
this.requestFlightStop();
|
||||
} else {
|
||||
this.updateAmbientAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasGroundBelow() {
|
||||
return !this.level().noCollision(this, this.getBoundingBox().move(this.toWorld(0.0D, -0.2D, 0.0D)));
|
||||
}
|
||||
|
||||
private void breakBlocksForChargeImpact(ServerLevel level) {
|
||||
if (!this.isHerculesBeetleGriefingEnabled(level)) {
|
||||
return;
|
||||
@@ -1424,6 +1444,9 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
|
||||
this.chargeCooldown = tag.getInt("ChargeCooldown");
|
||||
this.attackCooldown = tag.getInt("AttackCooldown");
|
||||
this.combatCryDone = tag.getBoolean("CombatCryDone");
|
||||
if (this.isChargeAnimationActive()) {
|
||||
this.setAnimationState(this.isFlying() ? ANIM_FLY : ANIM_IDLE);
|
||||
}
|
||||
if (this.isKnockedDown() && this.getAnimationState() != ANIM_KNOCKED_DOWN_IDLE) {
|
||||
this.setAnimationState(ANIM_KNOCKED_DOWN_IDLE);
|
||||
}
|
||||
|
||||
+19
-2
@@ -40,6 +40,8 @@ import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal;
|
||||
import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation;
|
||||
import net.minecraft.world.entity.ai.navigation.PathNavigation;
|
||||
import net.minecraft.world.entity.monster.Monster;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.ServerLevelAccessor;
|
||||
import net.minecraft.world.level.Level;
|
||||
@@ -85,7 +87,7 @@ public class BrutalflyEntity extends Monster implements GeoEntity {
|
||||
private static final int SPIT_WINDUP_TICKS = 16;
|
||||
private static final int SWIPE_TICKS = 18;
|
||||
private static final float SWIPE_KNOCKBACK = 2.8F;
|
||||
private static final int COCOON_HIT_THRESHOLD = 3;
|
||||
private static final int COCOON_HIT_THRESHOLD = 5;
|
||||
private static final int COCOON_HIT_COOLDOWN_TICKS = 60;
|
||||
private static final int COCOON_HIT_ANIM_TICKS = 30;
|
||||
private static final int COCOON_HATCH_ANIM_TICKS = 40;
|
||||
@@ -337,6 +339,12 @@ public class BrutalflyEntity extends Monster implements GeoEntity {
|
||||
if (nearbyPlayer != null && !nearbyPlayer.isCreative() && !nearbyPlayer.isSpectator()) {
|
||||
this.setTarget(nearbyPlayer);
|
||||
}
|
||||
this.spitCooldown = 0;
|
||||
}
|
||||
|
||||
public float getDamageScale() {
|
||||
double base = AntarchySettings.brutalflySwipeDamage();
|
||||
return base <= 0.0D ? 1.0F : (float) (this.getAttributeValue(Attributes.ATTACK_DAMAGE) / base);
|
||||
}
|
||||
|
||||
public boolean isCocooned() {
|
||||
@@ -514,6 +522,11 @@ public class BrutalflyEntity extends Monster implements GeoEntity {
|
||||
this.playSound(AntarchySoundEvents.BRUTALFLY_SPIT.get(), 1.0F, 0.9F + this.random.nextFloat() * 0.2F);
|
||||
switch (this.getFightPhase()) {
|
||||
case PHASE_THREE -> {
|
||||
this.launchOrb(serverLevel, origin, target, BrutalflyOrbEntity.OrbVariant.POISON, -14.0F);
|
||||
this.launchOrb(serverLevel, origin, target, BrutalflyOrbEntity.OrbVariant.STICKY, 0.0F);
|
||||
this.launchOrb(serverLevel, origin, target, BrutalflyOrbEntity.OrbVariant.POISON, 14.0F);
|
||||
}
|
||||
case PHASE_TWO -> {
|
||||
this.launchOrb(serverLevel, origin, target, BrutalflyOrbEntity.OrbVariant.POISON, -8.0F);
|
||||
this.launchOrb(serverLevel, origin, target, BrutalflyOrbEntity.OrbVariant.STICKY, 8.0F);
|
||||
}
|
||||
@@ -586,7 +599,8 @@ public class BrutalflyEntity extends Monster implements GeoEntity {
|
||||
}
|
||||
|
||||
private void performSwipeHit() {
|
||||
float swipeDamage = (float) AntarchySettings.brutalflySwipeDamage();
|
||||
float swipeDamage = (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE);
|
||||
boolean finalPhase = this.getFightPhase() == FightPhase.PHASE_THREE;
|
||||
AABB attackBox = this.getBoundingBox().inflate(4.8D, 2.4D, 4.8D).expandTowards(0.0D, -2.5D, 0.0D);
|
||||
for (LivingEntity target : this.level().getEntitiesOfClass(
|
||||
LivingEntity.class,
|
||||
@@ -598,6 +612,9 @@ public class BrutalflyEntity extends Monster implements GeoEntity {
|
||||
}
|
||||
|
||||
target.hurt(this.damageSources().mobAttack(this), swipeDamage);
|
||||
if (finalPhase) {
|
||||
target.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 60, 1, false, true));
|
||||
}
|
||||
|
||||
double dx = target.getX() - this.getX();
|
||||
double dz = target.getZ() - this.getZ();
|
||||
|
||||
+3
@@ -162,6 +162,9 @@ public class BrutalflyOrbEntity extends ThrowableItemProjectile {
|
||||
if (!this.level().isClientSide && result.getEntity() instanceof LivingEntity livingTarget) {
|
||||
float directHitDamage = (float) AntarchySettings.brutalflySpitDamage();
|
||||
Entity owner = this.getOwner();
|
||||
if (owner instanceof BrutalflyEntity brutalfly) {
|
||||
directHitDamage *= brutalfly.getDamageScale();
|
||||
}
|
||||
if (owner instanceof LivingEntity livingOwner) {
|
||||
livingTarget.hurt(this.damageSources().mobProjectile(this, livingOwner), directHitDamage);
|
||||
} else {
|
||||
|
||||
+129
@@ -3,13 +3,31 @@ package com.craisinlord.antarchy.content.entity.royal;
|
||||
import com.craisinlord.antarchy.config.AntarchySettings;
|
||||
import com.craisinlord.antarchy.content.AntarchyObjects;
|
||||
import com.craisinlord.antarchy.content.AntarchySoundEvents;
|
||||
import com.craisinlord.antarchy.content.effect.RoyalEffectEligibility;
|
||||
import com.craisinlord.antarchy.content.effect.RoyalEffectHooks;
|
||||
import com.craisinlord.antarchy.content.entity.royal.beam.RoyalBeamElement;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import net.minecraft.core.particles.DustParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||||
import net.minecraft.world.entity.monster.Enemy;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
public class PrinceEntity extends RoyalMountEntity {
|
||||
private static final DustParticleOptions COMMAND_DUST = new DustParticleOptions(new Vector3f(1.0F, 0.75F, 0.15F), 1.6F);
|
||||
|
||||
public PrinceEntity(EntityType<? extends PrinceEntity> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
}
|
||||
@@ -40,6 +58,117 @@ public class PrinceEntity extends RoyalMountEntity {
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ParticleOptions beamWindupParticle() {
|
||||
return switch (this.getBeamElement()) {
|
||||
case FIRE -> ParticleTypes.FLAME;
|
||||
case ICE -> ParticleTypes.SNOWFLAKE;
|
||||
default -> ParticleTypes.ELECTRIC_SPARK;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float beamBaseDamage() {
|
||||
return 12.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean prefersAerialCombat() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double preferredCombatRange() {
|
||||
return 0.0D;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float biteWeight() {
|
||||
return 3.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float spitWeight() {
|
||||
return 1.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float beamWeight() {
|
||||
return 1.2F;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float signatureWeight() {
|
||||
return 4.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int signatureCooldownTicks() {
|
||||
return 360;
|
||||
}
|
||||
|
||||
private double commandRadius() {
|
||||
return 14.0D + 2.0D * this.getGrowthScale();
|
||||
}
|
||||
|
||||
private int commandLimit() {
|
||||
return 3 + Mth.floor(this.getGrowthScale());
|
||||
}
|
||||
|
||||
private List<Mob> commandCandidates(Vec3 center) {
|
||||
double radius = this.commandRadius();
|
||||
return this.level().getEntitiesOfClass(Mob.class, this.getBoundingBox().inflate(radius), mob ->
|
||||
mob != this && mob.isAlive() && mob instanceof Enemy && !mob.isAlliedTo(this)
|
||||
&& !(mob instanceof RoyalBossEntity) && RoyalEffectEligibility.canApplyCommanded(mob)
|
||||
&& RoyalEffectHooks.commandedHolder() != null
|
||||
&& !mob.hasEffect(RoyalEffectHooks.commandedHolder())
|
||||
&& mob.distanceToSqr(center) <= radius * radius);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSignatureUseful(LivingEntity target) {
|
||||
return RoyalEffectHooks.commandedHolder() != null && this.commandCandidates(this.position()).size() >= 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void signatureTelegraph(ServerLevel level, int tick, @Nullable LivingEntity target, @Nullable Vec3 aimPoint) {
|
||||
if (tick % 3 != 0) {
|
||||
return;
|
||||
}
|
||||
double radius = (this.getBbWidth() * 0.5D + 1.0D) + tick * 0.25D * this.getGrowthScale();
|
||||
for (int i = 0; i < 16; i++) {
|
||||
double angle = i * Mth.TWO_PI / 16.0D + tick * 0.1D;
|
||||
level.sendParticles(COMMAND_DUST, this.getX() + Math.cos(angle) * radius, this.getY() + 0.3D,
|
||||
this.getZ() + Math.sin(angle) * radius, 1, 0.0D, 0.05D, 0.0D, 0.0D);
|
||||
}
|
||||
if (tick == 3) {
|
||||
level.sendParticles(ParticleTypes.ENCHANTED_HIT, this.getX(), this.getY() + this.getBbHeight(), this.getZ(),
|
||||
20, this.getBbWidth() * 0.3D, 0.3D, this.getBbWidth() * 0.3D, 0.1D);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean performSignature(ServerLevel level, @Nullable LivingEntity target, @Nullable Vec3 aimPoint, boolean ridden) {
|
||||
if (RoyalEffectHooks.commandedHolder() == null) {
|
||||
return false;
|
||||
}
|
||||
Vec3 center = this.position();
|
||||
List<Mob> candidates = this.commandCandidates(center);
|
||||
candidates.sort(Comparator.comparingDouble(mob -> mob.distanceToSqr(center)));
|
||||
int applied = 0;
|
||||
for (Mob mob : candidates) {
|
||||
if (applied >= this.commandLimit()) {
|
||||
break;
|
||||
}
|
||||
if (mob.addEffect(new MobEffectInstance(RoyalEffectHooks.commandedHolder(), 300 + 20 * Mth.floor(this.getGrowthScale())), this)) {
|
||||
applied++;
|
||||
level.sendParticles(COMMAND_DUST, mob.getX(), mob.getY() + mob.getBbHeight() + 0.3D, mob.getZ(), 8, 0.25D, 0.2D, 0.25D, 0.0D);
|
||||
}
|
||||
}
|
||||
level.sendParticles(ParticleTypes.SONIC_BOOM, this.getX(), this.getY() + this.getBbHeight() * 0.6D, this.getZ(), 1, 0.0D, 0.0D, 0.0D, 0.0D);
|
||||
return applied > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String geoName() {
|
||||
return "prince";
|
||||
|
||||
+122
-5
@@ -4,10 +4,18 @@ import com.craisinlord.antarchy.config.AntarchySettings;
|
||||
import com.craisinlord.antarchy.content.AntarchyObjects;
|
||||
import com.craisinlord.antarchy.content.AntarchySoundEvents;
|
||||
import com.craisinlord.antarchy.content.entity.royal.beam.RoyalBeamElement;
|
||||
import com.craisinlord.anthology.time.TimeDilationApi;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PrincessEntity extends RoyalMountEntity {
|
||||
public PrincessEntity(EntityType<? extends PrincessEntity> entityType, Level level) {
|
||||
@@ -24,11 +32,120 @@ public class PrincessEntity extends RoyalMountEntity {
|
||||
|
||||
@Override
|
||||
protected RoyalBeamElement boltElement(int lateralIndex) {
|
||||
return switch (lateralIndex) {
|
||||
case -1 -> RoyalBeamElement.FIRE;
|
||||
case 1 -> RoyalBeamElement.ICE;
|
||||
default -> RoyalBeamElement.LIGHTNING;
|
||||
};
|
||||
return RoyalBeamElement.GENERIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Vec3 boltOrigin(int lateralIndex) {
|
||||
float scale = this.getGrowthScale();
|
||||
Vec3 forward = Vec3.directionFromRotation(0.0F, this.getYRot());
|
||||
Vec3 side = new Vec3(-forward.z, 0.0D, forward.x);
|
||||
return this.position()
|
||||
.add(0.0D, (lateralIndex == 0 ? 0.4D : 0.33D) * scale, 0.0D)
|
||||
.add(forward.scale((lateralIndex == 0 ? 0.32D : 0.23D) * scale + this.getBbWidth() * 0.15D))
|
||||
.add(side.scale(lateralIndex * 0.24D * scale));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int nextBeamHead(int previous) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ParticleOptions beamWindupParticle() {
|
||||
return ParticleTypes.REVERSE_PORTAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float beamBaseDamage() {
|
||||
return 10.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean prefersAerialCombat() {
|
||||
return this.canFly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double preferredCombatRange() {
|
||||
return 8.0D + 1.5D * this.getGrowthScale();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float biteWeight() {
|
||||
return 1.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float spitWeight() {
|
||||
return 2.5F;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float beamWeight() {
|
||||
return 1.6F;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float signatureWeight() {
|
||||
return 2.5F;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int signatureCooldownTicks() {
|
||||
return 300;
|
||||
}
|
||||
|
||||
private double fieldRadius() {
|
||||
return 5.0D + 0.8D * this.getGrowthScale();
|
||||
}
|
||||
|
||||
private boolean ownerInside(Vec3 center) {
|
||||
LivingEntity owner = this.getOwner();
|
||||
if (owner == null || owner.level() != this.level() || this.hasPassenger(owner)) {
|
||||
return false;
|
||||
}
|
||||
double clearance = this.fieldRadius() + 1.5D;
|
||||
return owner.position().distanceToSqr(center) < clearance * clearance;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSignatureUseful(LivingEntity target) {
|
||||
return this.combatGap(target) < 10.0D + 1.5D * this.getGrowthScale() && !this.ownerInside(target.position());
|
||||
}
|
||||
|
||||
private Vec3 fieldCenter(@Nullable LivingEntity target, @Nullable Vec3 aimPoint) {
|
||||
if (target != null && target.isAlive()) {
|
||||
return target.position();
|
||||
}
|
||||
return aimPoint != null ? aimPoint : this.position().add(Vec3.directionFromRotation(0.0F, this.getYRot()).scale(this.getBbWidth() + 6.0D));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void signatureTelegraph(ServerLevel level, int tick, @Nullable LivingEntity target, @Nullable Vec3 aimPoint) {
|
||||
if (tick % 2 != 0) {
|
||||
return;
|
||||
}
|
||||
Vec3 center = this.fieldCenter(target, aimPoint);
|
||||
double radius = this.fieldRadius() * (1.0D - tick / 24.0D) + 0.5D;
|
||||
for (int i = 0; i < 12; i++) {
|
||||
double angle = i * Mth.TWO_PI / 12.0D - tick * 0.15D;
|
||||
level.sendParticles(ParticleTypes.REVERSE_PORTAL, center.x + Math.cos(angle) * radius, center.y + 0.2D,
|
||||
center.z + Math.sin(angle) * radius, 1, 0.0D, 0.05D, 0.0D, 0.0D);
|
||||
}
|
||||
Vec3 orb = this.boltOrigin(0);
|
||||
level.sendParticles(ParticleTypes.END_ROD, orb.x, orb.y, orb.z, 2, 0.1D, 0.1D, 0.1D, 0.01D);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean performSignature(ServerLevel level, @Nullable LivingEntity target, @Nullable Vec3 aimPoint, boolean ridden) {
|
||||
Vec3 center = this.fieldCenter(target, aimPoint);
|
||||
if (this.ownerInside(center)) {
|
||||
return false;
|
||||
}
|
||||
TimeDilationApi.createField(level, center, this.fieldRadius(), 0.35D, 100 + 10 * Mth.floor(this.getGrowthScale()), this.getUUID());
|
||||
level.sendParticles(ParticleTypes.END_ROD, center.x, center.y + 0.5D, center.z, 36, this.fieldRadius() * 0.3D, 0.6D, this.fieldRadius() * 0.3D, 0.03D);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+17
@@ -86,6 +86,14 @@ public class RoyalBoltEntity extends AbstractHurtingProjectile {
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canHitEntity(Entity target) {
|
||||
if (this.getOwner() instanceof RoyalMountEntity mount && mount.isFriendlyTo(target)) {
|
||||
return false;
|
||||
}
|
||||
return super.canHitEntity(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHitEntity(EntityHitResult result) {
|
||||
super.onHitEntity(result);
|
||||
@@ -101,7 +109,13 @@ public class RoyalBoltEntity extends AbstractHurtingProjectile {
|
||||
&& royal.isTame() && other.isTame()) {
|
||||
return;
|
||||
}
|
||||
if (owner instanceof RoyalMountEntity mount && mount.isFriendlyTo(target)) {
|
||||
return;
|
||||
}
|
||||
float damage = (float) AntarchySettings.royalBoltDamage();
|
||||
if (owner instanceof RoyalMountEntity mount) {
|
||||
damage *= mount.projectileDamageMultiplier();
|
||||
}
|
||||
target.hurt(this.damageSources().mobProjectile(this, owner instanceof LivingEntity le ? le : null), damage);
|
||||
if (target instanceof LivingEntity living) {
|
||||
living.knockback(0.35D, this.getX() - target.getX(), this.getZ() - target.getZ());
|
||||
@@ -125,6 +139,9 @@ public class RoyalBoltEntity extends AbstractHurtingProjectile {
|
||||
}
|
||||
}
|
||||
case GENERIC -> {
|
||||
if (owner instanceof PrincessEntity) {
|
||||
living.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 60, 1), owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -2006,7 +2006,8 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
|
||||
if (source.is(DamageTypes.GENERIC_KILL)) {
|
||||
return super.hurt(source, amount);
|
||||
}
|
||||
float cappedAmount = (float) Math.min(amount, AntarchySettings.royalBossMaxSingleHitDamage());
|
||||
float cap = (float) AntarchySettings.royalBossMaxSingleHitDamage();
|
||||
float cappedAmount = amount <= cap ? amount : cap + (amount - cap) * (float) AntarchySettings.royalBossHitOverflowRate();
|
||||
return super.hurt(source, cappedAmount);
|
||||
}
|
||||
|
||||
|
||||
+239
@@ -0,0 +1,239 @@
|
||||
package com.craisinlord.antarchy.content.entity.royal;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.ai.goal.Goal;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class RoyalMountCombatGoal extends Goal {
|
||||
private static final int FLIGHT_DECISION_INTERVAL = 40;
|
||||
|
||||
private final RoyalMountEntity mount;
|
||||
private LivingEntity target;
|
||||
private int repathTicks;
|
||||
private int flightDecisionTicks;
|
||||
private boolean wantsFlight;
|
||||
private int stuckTicks;
|
||||
private Vec3 lastCheckPosition = Vec3.ZERO;
|
||||
private float orbitAngle;
|
||||
private int orbitDirection = 1;
|
||||
private int diveTicks;
|
||||
private int unseenTicks;
|
||||
|
||||
public RoyalMountCombatGoal(RoyalMountEntity mount) {
|
||||
this.mount = mount;
|
||||
this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
LivingEntity candidate = this.mount.getTarget();
|
||||
if (!this.isValid(candidate)) {
|
||||
return false;
|
||||
}
|
||||
this.target = candidate;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canContinueToUse() {
|
||||
LivingEntity current = this.mount.getTarget();
|
||||
if (current != this.target || !this.isValid(current)) {
|
||||
return false;
|
||||
}
|
||||
double range = this.mount.getAttributeValue(net.minecraft.world.entity.ai.attributes.Attributes.FOLLOW_RANGE) * 1.2D;
|
||||
return this.mount.distanceToSqr(current) < range * range && this.unseenTicks < 200;
|
||||
}
|
||||
|
||||
private boolean isValid(LivingEntity candidate) {
|
||||
return candidate != null && candidate.isAlive() && !this.mount.isVehicle() && !this.mount.isOrderedToSit()
|
||||
&& candidate.level() == this.mount.level() && this.mount.canAttack(candidate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
this.repathTicks = 0;
|
||||
this.flightDecisionTicks = 0;
|
||||
this.wantsFlight = false;
|
||||
this.stuckTicks = 0;
|
||||
this.unseenTicks = 0;
|
||||
this.diveTicks = 0;
|
||||
this.lastCheckPosition = this.mount.position();
|
||||
Vec3 offset = this.mount.position().subtract(this.target.position());
|
||||
this.orbitAngle = (float) Mth.atan2(offset.z, offset.x);
|
||||
this.orbitDirection = this.mount.getRandom().nextBoolean() ? 1 : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
this.target = null;
|
||||
this.mount.getNavigation().stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresUpdateEveryTick() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
LivingEntity current = this.target;
|
||||
if (current == null) {
|
||||
return;
|
||||
}
|
||||
boolean canSee = this.mount.getSensing().hasLineOfSight(current);
|
||||
this.unseenTicks = canSee ? 0 : this.unseenTicks + 1;
|
||||
double gap = this.mount.combatGap(current);
|
||||
this.mount.getLookControl().setLookAt(current, 30.0F, 30.0F);
|
||||
this.trackStuck();
|
||||
this.updateFlightDecision(current, gap);
|
||||
|
||||
if (this.mount.isActing()) {
|
||||
this.holdDuringAction(current);
|
||||
return;
|
||||
}
|
||||
|
||||
int chosen = this.mount.chooseCombatAction(current, gap, canSee);
|
||||
if (chosen != RoyalMountEntity.ACTION_NONE && this.isFacing(current, this.facingTolerance(chosen))) {
|
||||
if (this.mount.startAction(chosen, current, current.getEyePosition(), false)) {
|
||||
this.diveTicks = 0;
|
||||
this.holdDuringAction(current);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (chosen != RoyalMountEntity.ACTION_NONE) {
|
||||
this.mount.turnTowards(current.position(), 18.0F);
|
||||
}
|
||||
|
||||
if (this.mount.isFlying()) {
|
||||
this.tickAerial(current, gap);
|
||||
} else {
|
||||
this.tickGround(current, gap, canSee);
|
||||
}
|
||||
}
|
||||
|
||||
private float facingTolerance(int action) {
|
||||
return switch (action) {
|
||||
case RoyalMountEntity.ACTION_BITE -> 50.0F;
|
||||
case RoyalMountEntity.ACTION_SIGNATURE -> 180.0F;
|
||||
default -> 120.0F;
|
||||
};
|
||||
}
|
||||
|
||||
private boolean isFacing(LivingEntity current, float tolerance) {
|
||||
Vec3 toTarget = current.position().subtract(this.mount.position());
|
||||
float desired = (float) (Mth.atan2(toTarget.z, toTarget.x) * Mth.RAD_TO_DEG) - 90.0F;
|
||||
return Math.abs(Mth.wrapDegrees(desired - this.mount.getYRot())) <= tolerance;
|
||||
}
|
||||
|
||||
private void holdDuringAction(LivingEntity current) {
|
||||
this.mount.getNavigation().stop();
|
||||
if (this.mount.isFlying()) {
|
||||
this.mount.claimFlight();
|
||||
if (this.mount.currentAction() == RoyalMountEntity.ACTION_BITE) {
|
||||
this.mount.getMoveControl().setWantedPosition(current.getX(), current.getY() + current.getBbHeight() * 0.5D, current.getZ(), 0.6D);
|
||||
} else {
|
||||
this.mount.getMoveControl().setWantedPosition(this.mount.getX(), this.mount.getY(), this.mount.getZ(), 0.4D);
|
||||
}
|
||||
} else if (this.mount.currentAction() != RoyalMountEntity.ACTION_BITE) {
|
||||
this.mount.setDeltaMovement(this.mount.getDeltaMovement().multiply(0.5D, 1.0D, 0.5D));
|
||||
}
|
||||
}
|
||||
|
||||
private void trackStuck() {
|
||||
if (this.mount.tickCount % 20 != 0) {
|
||||
return;
|
||||
}
|
||||
Vec3 position = this.mount.position();
|
||||
boolean trying = !this.mount.getNavigation().isDone() || this.mount.isFlying();
|
||||
if (trying && position.distanceToSqr(this.lastCheckPosition) < 1.0D) {
|
||||
this.stuckTicks += 20;
|
||||
} else {
|
||||
this.stuckTicks = 0;
|
||||
}
|
||||
this.lastCheckPosition = position;
|
||||
}
|
||||
|
||||
private void updateFlightDecision(LivingEntity current, double gap) {
|
||||
if (!this.mount.canFly()) {
|
||||
this.wantsFlight = false;
|
||||
return;
|
||||
}
|
||||
if (--this.flightDecisionTicks <= 0 || this.stuckTicks >= 40) {
|
||||
this.flightDecisionTicks = FLIGHT_DECISION_INTERVAL;
|
||||
boolean targetAbove = current.getY() - this.mount.getY() > 4.0D + this.mount.getBbHeight() * 0.25D;
|
||||
boolean targetAirborne = !current.onGround() && !current.isInWater() && RoyalMountEntity.isAirborne(current) || targetAbove;
|
||||
boolean groundBlocked = !this.mount.isFlying() && (this.stuckTicks >= 40
|
||||
|| this.mount.getNavigation().isDone() && gap > 4.0D && this.mount.getNavigation().createPath(current, 0) == null);
|
||||
boolean prefersAir = this.mount.prefersAerialCombat() && gap > 3.0D;
|
||||
this.wantsFlight = targetAirborne || groundBlocked || prefersAir || (this.mount.isFlying() && this.diveTicks > 0);
|
||||
if (this.stuckTicks >= 40) {
|
||||
this.stuckTicks = 0;
|
||||
}
|
||||
}
|
||||
if (this.wantsFlight) {
|
||||
this.mount.claimFlight();
|
||||
}
|
||||
}
|
||||
|
||||
private void tickAerial(LivingEntity current, double gap) {
|
||||
if (!this.wantsFlight) {
|
||||
return;
|
||||
}
|
||||
this.mount.claimFlight();
|
||||
float scale = this.mount.getGrowthScale();
|
||||
boolean wantsBite = this.mount.isActionAvailable(RoyalMountEntity.ACTION_BITE)
|
||||
&& (!this.mount.prefersAerialCombat() || gap < this.mount.preferredCombatRange() * 0.5D || this.diveTicks > 0);
|
||||
if (wantsBite && this.mount.isActionReady()) {
|
||||
this.diveTicks++;
|
||||
Vec3 approach = current.position().subtract(this.mount.position()).multiply(1.0D, 0.0D, 1.0D);
|
||||
Vec3 offset = approach.lengthSqr() > 1.0E-4D ? approach.normalize().scale(-(this.mount.getBbWidth() * 0.5D + 0.6D * scale)) : Vec3.ZERO;
|
||||
this.mount.getMoveControl().setWantedPosition(current.getX() + offset.x, current.getY() + 0.2D, current.getZ() + offset.z, 1.4D);
|
||||
if (this.diveTicks > 80) {
|
||||
this.diveTicks = 0;
|
||||
this.orbitDirection = -this.orbitDirection;
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.diveTicks = 0;
|
||||
double radius = Math.max(6.0D + 1.5D * scale, this.mount.preferredCombatRange()) + this.mount.getBbWidth() * 0.5D;
|
||||
this.orbitAngle += this.orbitDirection * (float) Math.min(0.08D, 1.2D / radius);
|
||||
double x = current.getX() + Math.cos(this.orbitAngle) * radius;
|
||||
double z = current.getZ() + Math.sin(this.orbitAngle) * radius;
|
||||
double y = current.getY() + 3.0D + 0.8D * scale;
|
||||
if (!this.mount.canOccupy(x, y, z)) {
|
||||
this.orbitDirection = -this.orbitDirection;
|
||||
y += 2.0D + scale;
|
||||
}
|
||||
this.mount.getMoveControl().setWantedPosition(x, y, z, 1.1D);
|
||||
}
|
||||
|
||||
private void tickGround(LivingEntity current, double gap, boolean canSee) {
|
||||
double preferred = this.mount.preferredCombatRange();
|
||||
boolean ranged = preferred > 0.0D && this.mount.canSpit();
|
||||
if (ranged && canSee && gap < preferred * 0.5D && !this.mount.isActionAvailable(RoyalMountEntity.ACTION_BITE)) {
|
||||
Vec3 away = this.mount.position().subtract(current.position()).multiply(1.0D, 0.0D, 1.0D);
|
||||
if (away.lengthSqr() > 1.0E-4D && --this.repathTicks <= 0) {
|
||||
this.repathTicks = 10;
|
||||
Vec3 destination = this.mount.position().add(away.normalize().scale(4.0D + this.mount.getBbWidth() * 0.5D));
|
||||
this.mount.getNavigation().moveTo(destination.x, destination.y, destination.z, 1.2D);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (ranged && canSee && gap <= preferred && gap >= preferred * 0.5D && !this.mount.isActionAvailable(RoyalMountEntity.ACTION_BITE)) {
|
||||
this.mount.getNavigation().stop();
|
||||
this.mount.turnTowards(current.position(), 12.0F);
|
||||
return;
|
||||
}
|
||||
if (this.mount.canBiteReach(current)) {
|
||||
this.mount.getNavigation().stop();
|
||||
this.mount.turnTowards(current.position(), 18.0F);
|
||||
return;
|
||||
}
|
||||
if (--this.repathTicks <= 0) {
|
||||
this.repathTicks = 6 + this.mount.getRandom().nextInt(6);
|
||||
this.mount.getNavigation().moveTo(current, 1.2D);
|
||||
}
|
||||
}
|
||||
}
|
||||
+175
@@ -0,0 +1,175 @@
|
||||
package com.craisinlord.antarchy.content.entity.royal;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.ai.goal.Goal;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class RoyalMountCompanionGoal extends Goal {
|
||||
private static final double MAX_OWNER_DISTANCE = 40.0D;
|
||||
|
||||
private final RoyalMountEntity mount;
|
||||
private LivingEntity owner;
|
||||
private int side = 1;
|
||||
private float orbitAngle;
|
||||
private int repathTicks;
|
||||
private int settledTicks;
|
||||
private int cooldown;
|
||||
private Vec3 spot;
|
||||
|
||||
public RoyalMountCompanionGoal(RoyalMountEntity mount) {
|
||||
this.mount = mount;
|
||||
this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK));
|
||||
}
|
||||
|
||||
private boolean isEligible(LivingEntity candidate) {
|
||||
return candidate != null && candidate.isAlive() && !candidate.isSpectator()
|
||||
&& candidate.level() == this.mount.level()
|
||||
&& this.mount.isTame() && !this.mount.isVehicle() && !this.mount.isOrderedToSit()
|
||||
&& !this.mount.isLeashed() && this.mount.getTarget() == null && !this.mount.isActing()
|
||||
&& this.mount.distanceToSqr(candidate) < MAX_OWNER_DISTANCE * MAX_OWNER_DISTANCE;
|
||||
}
|
||||
|
||||
private double settleDistance() {
|
||||
return 4.0D + this.mount.getBbWidth() * 0.6D;
|
||||
}
|
||||
|
||||
private boolean needsToReposition(LivingEntity candidate) {
|
||||
if (this.mount.canFly() && RoyalMountEntity.isAirborne(candidate)) {
|
||||
return true;
|
||||
}
|
||||
if (this.mount.isFlying()) {
|
||||
return true;
|
||||
}
|
||||
double settle = this.settleDistance() + 2.0D;
|
||||
return this.mount.distanceToSqr(candidate) > settle * settle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
if (this.cooldown > 0) {
|
||||
this.cooldown--;
|
||||
return false;
|
||||
}
|
||||
LivingEntity candidate = this.mount.getOwner();
|
||||
if (!this.isEligible(candidate) || !this.needsToReposition(candidate)) {
|
||||
return false;
|
||||
}
|
||||
this.owner = candidate;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canContinueToUse() {
|
||||
return this.isEligible(this.owner) && this.owner == this.mount.getOwner() && this.settledTicks < 40;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
this.side = this.mount.getRandom().nextBoolean() ? 1 : -1;
|
||||
this.repathTicks = 0;
|
||||
this.settledTicks = 0;
|
||||
this.spot = null;
|
||||
Vec3 offset = this.mount.position().subtract(this.owner.position());
|
||||
this.orbitAngle = (float) Mth.atan2(offset.z, offset.x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
this.owner = null;
|
||||
this.spot = null;
|
||||
this.cooldown = 20;
|
||||
this.mount.getNavigation().stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresUpdateEveryTick() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
float scale = this.mount.getGrowthScale();
|
||||
if (this.mount.canFly() && RoyalMountEntity.isAirborne(this.owner)) {
|
||||
this.settledTicks = 0;
|
||||
this.spot = null;
|
||||
this.mount.claimFlight();
|
||||
this.circleOwner(scale);
|
||||
return;
|
||||
}
|
||||
|
||||
if (--this.repathTicks <= 0 || this.spot == null) {
|
||||
this.repathTicks = 20;
|
||||
this.spot = this.pickSpotBesideOwner();
|
||||
}
|
||||
|
||||
if (this.mount.isFlying()) {
|
||||
this.settledTicks = 0;
|
||||
this.mount.getLookControl().setLookAt(this.owner, 10.0F, this.mount.getMaxHeadXRot());
|
||||
if (this.mount.onGround() || this.mount.isInWater()) {
|
||||
this.mount.setFlying(false);
|
||||
return;
|
||||
}
|
||||
this.mount.claimFlight();
|
||||
Vec3 target = this.spot != null ? this.spot : this.owner.position();
|
||||
double horizontal = Math.sqrt(Mth.square(target.x - this.mount.getX()) + Mth.square(target.z - this.mount.getZ()));
|
||||
double y = horizontal > 3.0D + scale ? Math.max(target.y + 1.5D * scale, this.mount.getY() - 2.0D) : target.y - 0.5D;
|
||||
this.mount.getMoveControl().setWantedPosition(target.x, y, target.z, 1.0D);
|
||||
return;
|
||||
}
|
||||
|
||||
double settle = this.settleDistance();
|
||||
boolean nearOwner = this.mount.distanceToSqr(this.owner) <= settle * settle;
|
||||
boolean nearSpot = this.spot != null && this.mount.position().distanceToSqr(this.spot) <= Mth.square(1.5D + 0.5D * scale);
|
||||
if (nearOwner || nearSpot) {
|
||||
this.mount.getNavigation().stop();
|
||||
if (this.settledTicks == 0) {
|
||||
this.mount.turnTowards(this.mount.position().add(this.owner.getLookAngle().multiply(1.0D, 0.0D, 1.0D)), 30.0F);
|
||||
if (this.mount.getRandom().nextInt(4) == 0) {
|
||||
this.mount.triggerQuirk();
|
||||
}
|
||||
}
|
||||
this.mount.getLookControl().setLookAt(this.owner, 10.0F, this.mount.getMaxHeadXRot());
|
||||
this.settledTicks++;
|
||||
return;
|
||||
}
|
||||
this.settledTicks = 0;
|
||||
this.mount.getLookControl().setLookAt(this.owner, 10.0F, this.mount.getMaxHeadXRot());
|
||||
if (this.repathTicks == 20) {
|
||||
Vec3 destination = this.spot != null ? this.spot : this.owner.position();
|
||||
if (!this.mount.getNavigation().moveTo(destination.x, destination.y, destination.z, 1.0D)) {
|
||||
this.mount.getNavigation().moveTo(this.owner, 1.0D);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void circleOwner(float scale) {
|
||||
double radius = 5.0D + this.mount.getBbWidth() * 0.75D;
|
||||
this.orbitAngle += this.side * (float) Math.min(0.07D, 1.0D / radius);
|
||||
double x = this.owner.getX() + Math.cos(this.orbitAngle) * radius;
|
||||
double z = this.owner.getZ() + Math.sin(this.orbitAngle) * radius;
|
||||
double y = this.owner.getY() + 2.0D + 0.6D * scale;
|
||||
if (!this.mount.canOccupy(x, y, z)) {
|
||||
y += 2.0D + scale;
|
||||
}
|
||||
this.mount.getMoveControl().setWantedPosition(x, y, z, 1.2D);
|
||||
this.mount.getLookControl().setLookAt(this.owner, 10.0F, this.mount.getMaxHeadXRot());
|
||||
}
|
||||
|
||||
private Vec3 pickSpotBesideOwner() {
|
||||
Vec3 facing = Vec3.directionFromRotation(0.0F, this.owner.getYRot());
|
||||
Vec3 right = new Vec3(-facing.z, 0.0D, facing.x);
|
||||
double distance = this.mount.getBbWidth() * 0.5D + 1.5D;
|
||||
for (int attempt = 0; attempt < 2; attempt++) {
|
||||
int currentSide = attempt == 0 ? this.side : -this.side;
|
||||
Vec3 base = this.owner.position().add(right.scale(currentSide * distance));
|
||||
double ground = this.mount.findGroundY(base.x, this.owner.getY() + 3.0D, base.z, 10);
|
||||
if (!Double.isNaN(ground) && this.mount.canOccupy(base.x, ground, base.z)) {
|
||||
this.side = currentSide;
|
||||
return new Vec3(base.x, ground, base.z);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+924
-324
File diff suppressed because it is too large.
Load diff
+86
-62
@@ -1,81 +1,76 @@
|
||||
package com.craisinlord.antarchy.content.entity.royal;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import java.util.EnumSet;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.ai.goal.Goal;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public class RoyalMountFollowOwnerGoal extends Goal {
|
||||
private static final double START_DISTANCE = 12.0D;
|
||||
private static final double STOP_DISTANCE = 6.0D;
|
||||
private static final double TELEPORT_DISTANCE = 48.0D;
|
||||
|
||||
private final RoyalMountEntity mount;
|
||||
private LivingEntity owner;
|
||||
private int recalcTimer;
|
||||
private int stuckTicks;
|
||||
private int teleportCooldown;
|
||||
private Vec3 lastCheckPosition = Vec3.ZERO;
|
||||
|
||||
public RoyalMountFollowOwnerGoal(RoyalMountEntity mount) {
|
||||
this.mount = mount;
|
||||
this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK));
|
||||
}
|
||||
|
||||
private double startDistance() {
|
||||
return 14.0D + 2.0D * this.mount.getGrowthScale();
|
||||
}
|
||||
|
||||
private double stopDistance() {
|
||||
return 6.0D + 1.5D * this.mount.getGrowthScale();
|
||||
}
|
||||
|
||||
private double teleportDistance() {
|
||||
return 48.0D + 4.0D * this.mount.getGrowthScale();
|
||||
}
|
||||
|
||||
private boolean canFollow(LivingEntity candidate) {
|
||||
return candidate != null && candidate.isAlive() && !candidate.isSpectator()
|
||||
&& candidate.level() == this.mount.level()
|
||||
&& this.mount.isTame() && !this.mount.isVehicle() && !this.mount.isOrderedToSit()
|
||||
&& !this.mount.isLeashed() && this.mount.getTarget() == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
if (!this.mount.isTame() || this.mount.isVehicle() || this.mount.isOrderedToSit()) {
|
||||
LivingEntity candidate = this.mount.getOwner();
|
||||
if (!this.canFollow(candidate)) {
|
||||
return false;
|
||||
}
|
||||
LivingEntity potentialOwner = this.mount.getOwner();
|
||||
if (potentialOwner == null || potentialOwner.isSpectator()) {
|
||||
double start = this.startDistance();
|
||||
if (this.mount.distanceToSqr(candidate) < start * start) {
|
||||
return false;
|
||||
}
|
||||
if (this.mount.distanceToSqr(potentialOwner) < START_DISTANCE * START_DISTANCE) {
|
||||
return false;
|
||||
}
|
||||
this.owner = potentialOwner;
|
||||
this.owner = candidate;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canContinueToUse() {
|
||||
return !this.mount.getNavigation().isDone()
|
||||
&& this.mount.distanceToSqr(this.owner) > STOP_DISTANCE * STOP_DISTANCE
|
||||
&& !this.mount.isOrderedToSit();
|
||||
if (!this.canFollow(this.owner) || this.owner != this.mount.getOwner()) {
|
||||
return false;
|
||||
}
|
||||
double stop = this.stopDistance();
|
||||
return this.mount.distanceToSqr(this.owner) > stop * stop;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
this.recalcTimer = 0;
|
||||
this.stuckTicks = 0;
|
||||
this.lastCheckPosition = this.mount.position();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
this.owner = null;
|
||||
this.mount.getNavigation().stop();
|
||||
this.mount.setFlying(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
this.mount.getLookControl().setLookAt(this.owner, 10.0F, this.mount.getMaxHeadXRot());
|
||||
|
||||
double distanceSqr = this.mount.distanceToSqr(this.owner);
|
||||
if (distanceSqr > TELEPORT_DISTANCE * TELEPORT_DISTANCE) {
|
||||
this.trySafeTeleport();
|
||||
return;
|
||||
}
|
||||
|
||||
boolean ownerAirborne = !this.owner.onGround() || (this.owner.getY() - this.mount.getY()) > 3.0D;
|
||||
this.mount.setFlying(ownerAirborne || distanceSqr > 24.0D * 24.0D);
|
||||
|
||||
if (--this.recalcTimer <= 0) {
|
||||
this.recalcTimer = 10;
|
||||
if (this.mount.isFlying()) {
|
||||
Vec3 to = this.owner.position().subtract(this.mount.position());
|
||||
Vec3 step = this.mount.position().add(to.normalize().scale(Math.min(to.length(), 8.0D)));
|
||||
this.mount.getMoveControl().setWantedPosition(step.x, step.y + 1.0D, step.z, 1.2D);
|
||||
} else {
|
||||
this.mount.getNavigation().moveTo(this.owner, 1.1D);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -83,28 +78,57 @@ public class RoyalMountFollowOwnerGoal extends Goal {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void trySafeTeleport() {
|
||||
Vec3 ownerPosition = this.owner.position();
|
||||
BlockPos ownerBlock = this.owner.blockPosition();
|
||||
for (int radius = 0; radius <= 2; radius++) {
|
||||
for (int dx = -radius; dx <= radius; dx++) {
|
||||
for (int dz = -radius; dz <= radius; dz++) {
|
||||
for (int dy = -1; dy <= 2; dy++) {
|
||||
double x = ownerPosition.x + dx + 0.5D;
|
||||
double y = ownerBlock.getY() + dy;
|
||||
double z = ownerPosition.z + dz + 0.5D;
|
||||
BlockPos floor = BlockPos.containing(x, y - 0.1D, z);
|
||||
var destination = this.mount.getBoundingBox().move(x - this.mount.getX(), y - this.mount.getY(), z - this.mount.getZ());
|
||||
if (!this.mount.level().noCollision(this.mount, destination)) {
|
||||
continue;
|
||||
}
|
||||
if (this.mount.isFlying() || !this.mount.level().getBlockState(floor).getCollisionShape(this.mount.level(), floor).isEmpty()) {
|
||||
this.mount.teleportTo(x, y, z);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void tick() {
|
||||
this.mount.getLookControl().setLookAt(this.owner, 10.0F, this.mount.getMaxHeadXRot());
|
||||
if (this.teleportCooldown > 0) {
|
||||
this.teleportCooldown--;
|
||||
}
|
||||
this.trackStuck();
|
||||
|
||||
double distance = this.mount.distanceTo(this.owner);
|
||||
if ((distance > this.teleportDistance() || this.stuckTicks >= 100 && distance > 24.0D) && this.teleportCooldown <= 0) {
|
||||
this.teleportCooldown = 20;
|
||||
if (this.mount.tryTeleportNear(this.owner)) {
|
||||
this.stuckTicks = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
boolean ownerAirborne = RoyalMountEntity.isAirborne(this.owner);
|
||||
boolean wantsFlight = this.mount.canFly() && (ownerAirborne || distance > 24.0D + this.mount.getBbWidth()
|
||||
|| this.stuckTicks >= 40 || this.owner.getY() - this.mount.getY() > 4.0D);
|
||||
if (wantsFlight && this.mount.claimFlight()) {
|
||||
if (--this.recalcTimer <= 0) {
|
||||
this.recalcTimer = 5;
|
||||
float scale = this.mount.getGrowthScale();
|
||||
Vec3 destination = this.owner.position().add(0.0D, 2.0D + 0.6D * scale, 0.0D);
|
||||
Vec3 to = destination.subtract(this.mount.position());
|
||||
double stepLength = Math.min(to.length(), 12.0D + 2.0D * scale);
|
||||
Vec3 step = to.lengthSqr() > 1.0E-4D ? this.mount.position().add(to.normalize().scale(stepLength)) : destination;
|
||||
this.mount.getMoveControl().setWantedPosition(step.x, step.y, step.z, 1.3D);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (this.mount.isFlying()) {
|
||||
return;
|
||||
}
|
||||
if (--this.recalcTimer <= 0) {
|
||||
this.recalcTimer = 10;
|
||||
this.mount.getNavigation().moveTo(this.owner, 1.2D);
|
||||
}
|
||||
}
|
||||
|
||||
private void trackStuck() {
|
||||
if (this.mount.tickCount % 20 != 0) {
|
||||
return;
|
||||
}
|
||||
Vec3 position = this.mount.position();
|
||||
if (position.distanceToSqr(this.lastCheckPosition) < 1.0D) {
|
||||
this.stuckTicks += 20;
|
||||
} else {
|
||||
this.stuckTicks = 0;
|
||||
}
|
||||
this.lastCheckPosition = position;
|
||||
}
|
||||
}
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
package com.craisinlord.antarchy.content.entity.royal;
|
||||
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.ai.goal.Goal;
|
||||
|
||||
public class RoyalMountSpitGoal extends Goal {
|
||||
private final RoyalMountEntity mount;
|
||||
private int cooldown;
|
||||
|
||||
public RoyalMountSpitGoal(RoyalMountEntity mount) {
|
||||
this.mount = mount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
if (this.mount.isVehicle() || this.mount.isOrderedToSit()) {
|
||||
return false;
|
||||
}
|
||||
LivingEntity target = this.mount.getTarget();
|
||||
if (target == null || !target.isAlive() || !this.mount.canAttack(target)) {
|
||||
return false;
|
||||
}
|
||||
double distance = this.mount.distanceTo(target);
|
||||
return distance > 5.0D && distance < 20.0D && this.mount.hasLineOfSight(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
this.cooldown = 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
LivingEntity target = this.mount.getTarget();
|
||||
if (target == null || !this.mount.canAttack(target)) {
|
||||
return;
|
||||
}
|
||||
this.mount.getLookControl().setLookAt(target, 30.0F, 30.0F);
|
||||
if (this.cooldown-- <= 0) {
|
||||
this.mount.startSpitVolley(target);
|
||||
this.cooldown = 60;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresUpdateEveryTick() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+8
@@ -29,6 +29,14 @@ public class AttitudeAdjusterItem extends SwordItem {
|
||||
this.tier = tier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.google.common.collect.Multimap<net.minecraft.world.entity.ai.attributes.Attribute, net.minecraft.world.entity.ai.attributes.AttributeModifier> getDefaultAttributeModifiers(net.minecraft.world.entity.EquipmentSlot slot) {
|
||||
if (slot != net.minecraft.world.entity.EquipmentSlot.MAINHAND) {
|
||||
return super.getDefaultAttributeModifiers(slot);
|
||||
}
|
||||
return com.craisinlord.antarchy.compat.item.WeaponAttributes.base(this.tier, (float) Math.round(AntarchySettings.attitudeAdjusterBaseDamage()), ATTACK_SPEED).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHoverText(ItemStack stack, Level level, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
|
||||
tooltipComponents.add(Component.translatable("tooltip.antarchy.attitude_adjuster.grounded").withStyle(ChatFormatting.DARK_GRAY));
|
||||
|
||||
+8
@@ -21,6 +21,14 @@ public class BasiliskDaggerItem extends SwordItem {
|
||||
this.attackSpeed = attackSpeed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.google.common.collect.Multimap<net.minecraft.world.entity.ai.attributes.Attribute, net.minecraft.world.entity.ai.attributes.AttributeModifier> getDefaultAttributeModifiers(net.minecraft.world.entity.EquipmentSlot slot) {
|
||||
if (slot != net.minecraft.world.entity.EquipmentSlot.MAINHAND) {
|
||||
return super.getDefaultAttributeModifiers(slot);
|
||||
}
|
||||
return com.craisinlord.antarchy.compat.item.WeaponAttributes.base(this.tier, (float) Math.round(AntarchySettings.basiliskDaggerAttackDamage()), (float) AntarchySettings.basiliskDaggerAttackSpeed()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hurtEnemy(ItemStack stack, LivingEntity target, LivingEntity attacker) {
|
||||
boolean didHurt = super.hurtEnemy(stack, target, attacker);
|
||||
|
||||
@@ -2,13 +2,23 @@ package com.craisinlord.antarchy.content.item;
|
||||
|
||||
import com.craisinlord.antarchy.config.AntarchySettings;
|
||||
import com.craisinlord.antarchy.content.client.model.ResourceBackedGeoItemModel;
|
||||
import com.craisinlord.antarchy.content.item.ultimate.UltimateToolHelper;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.DoubleSupplier;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.item.AxeItem;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Tier;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import software.bernie.geckolib.animatable.GeoItem;
|
||||
import com.craisinlord.antarchy.content.client.AntarchyGeoItemRenderer;
|
||||
import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache;
|
||||
@@ -34,6 +44,33 @@ public class BattleAxeItem extends AxeItem implements GeoItem, com.craisinlord.a
|
||||
GeoItem.registerSyncedAnimatable(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.google.common.collect.Multimap<net.minecraft.world.entity.ai.attributes.Attribute, net.minecraft.world.entity.ai.attributes.AttributeModifier> getDefaultAttributeModifiers(net.minecraft.world.entity.EquipmentSlot slot) {
|
||||
if (slot != net.minecraft.world.entity.EquipmentSlot.MAINHAND) {
|
||||
return super.getDefaultAttributeModifiers(slot);
|
||||
}
|
||||
return com.craisinlord.antarchy.compat.item.WeaponAttributes.base(this.tier, (float) this.attackDamage.getAsDouble(), (float) AntarchySettings.battleAxeAttackSpeed()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHoverText(ItemStack stack, Level level, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
|
||||
super.appendHoverText(stack, level, tooltipComponents, tooltipFlag);
|
||||
if (AntarchySettings.ultimateToolsVeinMiningEnabled()) {
|
||||
tooltipComponents.add(Component.translatable("tooltip.antarchy.battle_axe_tree_felling").withStyle(ChatFormatting.GRAY));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mineBlock(ItemStack stack, Level level, BlockState state, BlockPos pos, LivingEntity miningEntity) {
|
||||
boolean result = super.mineBlock(stack, level, state, pos, miningEntity);
|
||||
if (AntarchySettings.ultimateToolsVeinMiningEnabled()
|
||||
&& miningEntity instanceof ServerPlayer player
|
||||
&& !player.isShiftKeyDown()) {
|
||||
UltimateToolHelper.mineTree(stack, level, state, pos, player, AntarchySettings.ultimateToolsTreeFellingMaxLogs());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnchantable(ItemStack stack) {
|
||||
return stack.getCount() == 1;
|
||||
|
||||
+9
-1
@@ -31,10 +31,18 @@ public class UltimateAxeItem extends AxeItem {
|
||||
this.attackSpeed = attackSpeed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.google.common.collect.Multimap<net.minecraft.world.entity.ai.attributes.Attribute, net.minecraft.world.entity.ai.attributes.AttributeModifier> getDefaultAttributeModifiers(net.minecraft.world.entity.EquipmentSlot slot) {
|
||||
if (slot != net.minecraft.world.entity.EquipmentSlot.MAINHAND) {
|
||||
return super.getDefaultAttributeModifiers(slot);
|
||||
}
|
||||
return com.craisinlord.antarchy.compat.item.WeaponAttributes.base(this.tier, (float) this.attackDamage.getAsDouble(), (float) AntarchySettings.ultimateAxeAttackSpeed()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHoverText(ItemStack stack, Level level, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
|
||||
super.appendHoverText(stack, level, tooltipComponents, tooltipFlag);
|
||||
UltimateToolHelper.appendThreeByThreeTooltip(tooltipComponents);
|
||||
UltimateToolHelper.appendModeTooltip(UltimateToolHelper.ToolKind.AXE, tooltipComponents);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+9
-1
@@ -31,10 +31,18 @@ public class UltimateHoeItem extends HoeItem {
|
||||
this.attackSpeed = attackSpeed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.google.common.collect.Multimap<net.minecraft.world.entity.ai.attributes.Attribute, net.minecraft.world.entity.ai.attributes.AttributeModifier> getDefaultAttributeModifiers(net.minecraft.world.entity.EquipmentSlot slot) {
|
||||
if (slot != net.minecraft.world.entity.EquipmentSlot.MAINHAND) {
|
||||
return super.getDefaultAttributeModifiers(slot);
|
||||
}
|
||||
return com.craisinlord.antarchy.compat.item.WeaponAttributes.base(this.tier, (float) Math.round(this.attackDamage.getAsDouble()), (float) AntarchySettings.ultimateHoeAttackSpeed()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHoverText(ItemStack stack, Level level, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
|
||||
super.appendHoverText(stack, level, tooltipComponents, tooltipFlag);
|
||||
UltimateToolHelper.appendThreeByThreeTooltip(tooltipComponents);
|
||||
UltimateToolHelper.appendModeTooltip(UltimateToolHelper.ToolKind.HOE, tooltipComponents);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+9
-1
@@ -31,10 +31,18 @@ public class UltimatePickaxeItem extends PickaxeItem {
|
||||
this.attackSpeed = attackSpeed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.google.common.collect.Multimap<net.minecraft.world.entity.ai.attributes.Attribute, net.minecraft.world.entity.ai.attributes.AttributeModifier> getDefaultAttributeModifiers(net.minecraft.world.entity.EquipmentSlot slot) {
|
||||
if (slot != net.minecraft.world.entity.EquipmentSlot.MAINHAND) {
|
||||
return super.getDefaultAttributeModifiers(slot);
|
||||
}
|
||||
return com.craisinlord.antarchy.compat.item.WeaponAttributes.base(this.tier, (float) Math.round(this.attackDamage.getAsDouble()), (float) AntarchySettings.ultimatePickaxeAttackSpeed()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHoverText(ItemStack stack, Level level, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
|
||||
super.appendHoverText(stack, level, tooltipComponents, tooltipFlag);
|
||||
UltimateToolHelper.appendThreeByThreeTooltip(tooltipComponents);
|
||||
UltimateToolHelper.appendModeTooltip(UltimateToolHelper.ToolKind.PICKAXE, tooltipComponents);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+8
@@ -19,6 +19,14 @@ public class UltimateSwordItem extends SwordItem {
|
||||
this.attackSpeed = attackSpeed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.google.common.collect.Multimap<net.minecraft.world.entity.ai.attributes.Attribute, net.minecraft.world.entity.ai.attributes.AttributeModifier> getDefaultAttributeModifiers(net.minecraft.world.entity.EquipmentSlot slot) {
|
||||
if (slot != net.minecraft.world.entity.EquipmentSlot.MAINHAND) {
|
||||
return super.getDefaultAttributeModifiers(slot);
|
||||
}
|
||||
return com.craisinlord.antarchy.compat.item.WeaponAttributes.base(this.tier, (float) Math.round(this.attackDamage.getAsDouble()), (float) AntarchySettings.ultimateSwordAttackSpeed()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnchantable(ItemStack stack) {
|
||||
return stack.getCount() == 1;
|
||||
|
||||
+182
-26
@@ -3,12 +3,16 @@ package com.craisinlord.antarchy.content.item.ultimate;
|
||||
import com.craisinlord.antarchy.config.AntarchySettings;
|
||||
import com.craisinlord.antarchy.content.item.GiantFryingPanItem;
|
||||
import com.craisinlord.antarchy.content.item.GiantFryingPanToolHelper;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
@@ -23,12 +27,16 @@ import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Tier;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
public final class UltimateToolHelper {
|
||||
private static final String THREE_BY_THREE_TAG = "antarchy.ultimate_three_by_three";
|
||||
private static final String MINING_MODE_TAG = "antarchy.ultimate_mining_mode";
|
||||
private static final ThreadLocal<Boolean> BREAKING_EXTRA_BLOCKS = ThreadLocal.withInitial(() -> false);
|
||||
private static final float GENERAL_MINING_MULTIPLIER = 1.1F;
|
||||
private static final float ULTIMATE_SHOVEL_MINING_SPEED = 24.0F;
|
||||
@@ -38,26 +46,43 @@ public final class UltimateToolHelper {
|
||||
|
||||
public static InteractionResultHolder<ItemStack> handleToggleUse(Level level, Player player, InteractionHand hand) {
|
||||
ItemStack stack = player.getItemInHand(hand);
|
||||
if (!AntarchySettings.ultimateToolsThreeByThreeEnabled() || !player.isShiftKeyDown()) {
|
||||
if (!player.isShiftKeyDown() || availableModes(toolKindOf(stack.getItem())).size() < 2) {
|
||||
return InteractionResultHolder.pass(stack);
|
||||
}
|
||||
|
||||
toggleThreeByThree(level, player, stack);
|
||||
cycleMiningMode(level, player, stack);
|
||||
return InteractionResultHolder.sidedSuccess(stack, level.isClientSide);
|
||||
}
|
||||
|
||||
public static InteractionResult handleToggleUseOn(UseOnContext context) {
|
||||
Player player = context.getPlayer();
|
||||
if (!AntarchySettings.ultimateToolsThreeByThreeEnabled() || player == null || !player.isShiftKeyDown()) {
|
||||
if (player == null || !player.isShiftKeyDown() || availableModes(toolKindOf(context.getItemInHand().getItem())).size() < 2) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
toggleThreeByThree(context.getLevel(), player, context.getItemInHand());
|
||||
cycleMiningMode(context.getLevel(), player, context.getItemInHand());
|
||||
return InteractionResult.sidedSuccess(context.getLevel().isClientSide);
|
||||
}
|
||||
|
||||
public static boolean isThreeByThreeEnabled(ItemStack stack) {
|
||||
return stack.hasTag() && stack.getTag().getBoolean(THREE_BY_THREE_TAG);
|
||||
return getMiningMode(stack) == MiningMode.THREE_BY_THREE;
|
||||
}
|
||||
|
||||
public static boolean isVeinEnabled(ItemStack stack) {
|
||||
return getMiningMode(stack) == MiningMode.VEIN;
|
||||
}
|
||||
|
||||
public static MiningMode getMiningMode(ItemStack stack) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
if (tag == null) {
|
||||
return MiningMode.DEFAULT;
|
||||
}
|
||||
if (tag.contains(MINING_MODE_TAG)) {
|
||||
int index = tag.getByte(MINING_MODE_TAG);
|
||||
MiningMode[] modes = MiningMode.values();
|
||||
return index >= 0 && index < modes.length ? modes[index] : MiningMode.DEFAULT;
|
||||
}
|
||||
return tag.getBoolean(THREE_BY_THREE_TAG) ? MiningMode.THREE_BY_THREE : MiningMode.DEFAULT;
|
||||
}
|
||||
|
||||
public static float getDestroySpeed(ToolKind toolKind, Tier tier, ItemStack stack, BlockState state, float defaultSpeed) {
|
||||
@@ -74,23 +99,127 @@ public final class UltimateToolHelper {
|
||||
return defaultSpeed * GENERAL_MINING_MULTIPLIER;
|
||||
}
|
||||
|
||||
public static void appendThreeByThreeTooltip(List<Component> tooltip) {
|
||||
if (!AntarchySettings.ultimateToolsThreeByThreeEnabled()) {
|
||||
public static void appendModeTooltip(ToolKind toolKind, List<Component> tooltip) {
|
||||
List<MiningMode> modes = availableModes(toolKind);
|
||||
boolean area = modes.contains(MiningMode.THREE_BY_THREE);
|
||||
boolean vein = modes.contains(MiningMode.VEIN);
|
||||
String key;
|
||||
if (area && vein) {
|
||||
key = "tooltip.antarchy.ultimate_tools_3x3_vein";
|
||||
} else if (area) {
|
||||
key = "tooltip.antarchy.ultimate_tools_3x3";
|
||||
} else if (vein) {
|
||||
key = "tooltip.antarchy.ultimate_tools_vein";
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
tooltip.add(Component.translatable("tooltip.antarchy.ultimate_tools_3x3").withStyle(ChatFormatting.GRAY));
|
||||
tooltip.add(Component.translatable(key).withStyle(ChatFormatting.GRAY));
|
||||
}
|
||||
|
||||
public static void handleAreaMining(ToolKind toolKind, ItemStack stack, Level level, BlockState originState, BlockPos origin, LivingEntity entity) {
|
||||
if (!AntarchySettings.ultimateToolsThreeByThreeEnabled()
|
||||
|| level.isClientSide
|
||||
if (level.isClientSide
|
||||
|| BREAKING_EXTRA_BLOCKS.get()
|
||||
|| !isThreeByThreeEnabled(stack)
|
||||
|| !(entity instanceof ServerPlayer player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mineArea(toolKind, stack, level, originState, origin, player, 1);
|
||||
MiningMode mode = getMiningMode(stack);
|
||||
if (mode == MiningMode.DEFAULT || !availableModes(toolKind).contains(mode)) {
|
||||
return;
|
||||
}
|
||||
if (mode == MiningMode.THREE_BY_THREE) {
|
||||
mineArea(toolKind, stack, level, originState, origin, player, 1);
|
||||
} else {
|
||||
mineVein(toolKind, stack, level, originState, origin, player, veinLimit(originState));
|
||||
}
|
||||
}
|
||||
|
||||
public static int veinLimit(BlockState state) {
|
||||
return state.is(BlockTags.LOGS)
|
||||
? AntarchySettings.ultimateToolsTreeFellingMaxLogs()
|
||||
: AntarchySettings.ultimateToolsVeinMiningMaxBlocks();
|
||||
}
|
||||
|
||||
public static void mineVein(ToolKind toolKind, ItemStack stack, Level level, BlockState originState, BlockPos origin, ServerPlayer player, int maxBlocks) {
|
||||
if (level.isClientSide || BREAKING_EXTRA_BLOCKS.get() || maxBlocks <= 0 || !matchesToolKind(toolKind, originState)) {
|
||||
return;
|
||||
}
|
||||
|
||||
breakAll(toolKind, stack, level, player, collectConnected(level, origin, originState.getBlock(), maxBlocks, false));
|
||||
}
|
||||
|
||||
public static void mineTree(ItemStack stack, Level level, BlockState originState, BlockPos origin, ServerPlayer player, int maxBlocks) {
|
||||
if (level.isClientSide || BREAKING_EXTRA_BLOCKS.get() || maxBlocks <= 0 || !originState.is(BlockTags.LOGS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
breakAll(ToolKind.AXE, stack, level, player, collectConnected(level, origin, originState.getBlock(), maxBlocks, true));
|
||||
}
|
||||
|
||||
private static void breakAll(ToolKind toolKind, ItemStack stack, Level level, ServerPlayer player, List<BlockPos> targets) {
|
||||
if (targets.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
BREAKING_EXTRA_BLOCKS.set(true);
|
||||
try {
|
||||
for (BlockPos targetPos : targets) {
|
||||
if (!canBreak(toolKind, player, stack, level, targetPos, level.getBlockState(targetPos))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
player.gameMode.destroyBlock(targetPos);
|
||||
if (stack.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
BREAKING_EXTRA_BLOCKS.set(false);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<BlockPos> collectConnected(Level level, BlockPos origin, Block block, int maxBlocks, boolean requireFoliage) {
|
||||
List<BlockPos> found = new ArrayList<>();
|
||||
Set<BlockPos> visited = new HashSet<>();
|
||||
ArrayDeque<BlockPos> queue = new ArrayDeque<>();
|
||||
visited.add(origin);
|
||||
queue.add(origin);
|
||||
boolean foliage = false;
|
||||
|
||||
while (!queue.isEmpty() && found.size() < maxBlocks) {
|
||||
BlockPos current = queue.poll();
|
||||
for (int dx = -1; dx <= 1 && found.size() < maxBlocks; dx++) {
|
||||
for (int dy = -1; dy <= 1 && found.size() < maxBlocks; dy++) {
|
||||
for (int dz = -1; dz <= 1 && found.size() < maxBlocks; dz++) {
|
||||
if (dx == 0 && dy == 0 && dz == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BlockPos next = current.offset(dx, dy, dz);
|
||||
if (!visited.add(next) || !level.isLoaded(next)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BlockState state = level.getBlockState(next);
|
||||
if (state.is(block)) {
|
||||
found.add(next);
|
||||
queue.add(next);
|
||||
} else if (requireFoliage && !foliage && isNaturalFoliage(state)) {
|
||||
foliage = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requireFoliage && !foliage ? List.of() : found;
|
||||
}
|
||||
|
||||
private static boolean isNaturalFoliage(BlockState state) {
|
||||
if (state.is(BlockTags.LEAVES)) {
|
||||
return !state.hasProperty(BlockStateProperties.PERSISTENT) || !state.getValue(BlockStateProperties.PERSISTENT);
|
||||
}
|
||||
return state.is(BlockTags.WART_BLOCKS) || state.is(Blocks.SHROOMLIGHT);
|
||||
}
|
||||
|
||||
public static void mineArea(ToolKind toolKind, ItemStack stack, Level level, BlockState originState, BlockPos origin, ServerPlayer player, int radius) {
|
||||
@@ -211,23 +340,50 @@ public final class UltimateToolHelper {
|
||||
HOE
|
||||
}
|
||||
|
||||
private static void toggleThreeByThree(Level level, Player player, ItemStack stack) {
|
||||
boolean enabled = !isThreeByThreeEnabled(stack);
|
||||
if (enabled) {
|
||||
stack.getOrCreateTag().putBoolean(THREE_BY_THREE_TAG, true);
|
||||
} else if (stack.hasTag()) {
|
||||
stack.getTag().remove(THREE_BY_THREE_TAG);
|
||||
public enum MiningMode {
|
||||
DEFAULT,
|
||||
THREE_BY_THREE,
|
||||
VEIN
|
||||
}
|
||||
|
||||
private static List<MiningMode> availableModes(ToolKind toolKind) {
|
||||
List<MiningMode> modes = new ArrayList<>(3);
|
||||
if (toolKind == null) {
|
||||
return modes;
|
||||
}
|
||||
modes.add(MiningMode.DEFAULT);
|
||||
if (AntarchySettings.ultimateToolsThreeByThreeEnabled()) {
|
||||
modes.add(MiningMode.THREE_BY_THREE);
|
||||
}
|
||||
if (AntarchySettings.ultimateToolsVeinMiningEnabled() && (toolKind == ToolKind.PICKAXE || toolKind == ToolKind.AXE)) {
|
||||
modes.add(MiningMode.VEIN);
|
||||
}
|
||||
return modes;
|
||||
}
|
||||
|
||||
private static void cycleMiningMode(Level level, Player player, ItemStack stack) {
|
||||
List<MiningMode> modes = availableModes(toolKindOf(stack.getItem()));
|
||||
int current = modes.indexOf(getMiningMode(stack));
|
||||
MiningMode next = modes.get((current + 1) % modes.size());
|
||||
if (next == MiningMode.DEFAULT) {
|
||||
CompoundTag tag = stack.getTag();
|
||||
if (tag != null) {
|
||||
tag.remove(THREE_BY_THREE_TAG);
|
||||
tag.remove(MINING_MODE_TAG);
|
||||
}
|
||||
} else {
|
||||
CompoundTag tag = stack.getOrCreateTag();
|
||||
tag.remove(THREE_BY_THREE_TAG);
|
||||
tag.putByte(MINING_MODE_TAG, (byte) next.ordinal());
|
||||
}
|
||||
|
||||
if (!level.isClientSide) {
|
||||
player.displayClientMessage(
|
||||
Component.translatable(
|
||||
enabled
|
||||
? "message.antarchy.ultimate_tool.mode_3x3"
|
||||
: "message.antarchy.ultimate_tool.mode_default"
|
||||
),
|
||||
true
|
||||
);
|
||||
String key = switch (next) {
|
||||
case DEFAULT -> "message.antarchy.ultimate_tool.mode_default";
|
||||
case THREE_BY_THREE -> "message.antarchy.ultimate_tool.mode_3x3";
|
||||
case VEIN -> "message.antarchy.ultimate_tool.mode_vein";
|
||||
};
|
||||
player.displayClientMessage(Component.translatable(key), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-1
@@ -34,10 +34,18 @@ public class UtlimateShovelItem extends ShovelItem {
|
||||
this.attackSpeed = attackSpeed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.google.common.collect.Multimap<net.minecraft.world.entity.ai.attributes.Attribute, net.minecraft.world.entity.ai.attributes.AttributeModifier> getDefaultAttributeModifiers(net.minecraft.world.entity.EquipmentSlot slot) {
|
||||
if (slot != net.minecraft.world.entity.EquipmentSlot.MAINHAND) {
|
||||
return super.getDefaultAttributeModifiers(slot);
|
||||
}
|
||||
return com.craisinlord.antarchy.compat.item.WeaponAttributes.base(this.tier, (float) this.attackDamage.getAsDouble(), (float) AntarchySettings.ultimateShovelAttackSpeed()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHoverText(ItemStack stack, Level level, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
|
||||
super.appendHoverText(stack, level, tooltipComponents, tooltipFlag);
|
||||
UltimateToolHelper.appendThreeByThreeTooltip(tooltipComponents);
|
||||
UltimateToolHelper.appendModeTooltip(UltimateToolHelper.ToolKind.SHOVEL, tooltipComponents);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
@@ -12,6 +12,8 @@ public record RoyalMountActionPayload(int action) implements CustomPacketPayload
|
||||
public static final int BITE = 1;
|
||||
public static final int SPIT = 2;
|
||||
public static final int MOUNT = 3;
|
||||
public static final int BEAM = 4;
|
||||
public static final int SIGNATURE = 5;
|
||||
|
||||
public static final Type<RoyalMountActionPayload> TYPE =
|
||||
new Type<>(new ResourceLocation(Antarchy.MODID, "royal_mount_action"));
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ public class TermiteNestFeature extends SurfaceAntNestFeature {
|
||||
protected BlockPos resolveNestPos(WorldGenLevel level, BlockPos origin) {
|
||||
int x = origin.getX();
|
||||
int z = origin.getZ();
|
||||
int startY = 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;
|
||||
|
||||
for (int y = startY; y >= minY; y--) {
|
||||
|
||||
+2
@@ -1,5 +1,6 @@
|
||||
package com.craisinlord.antarchy.mixins;
|
||||
|
||||
import com.craisinlord.antarchy.content.AntarchyTags;
|
||||
import com.craisinlord.antarchy.content.item.MantisClawItem;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
@@ -91,6 +92,7 @@ public abstract class MantisClawWallClimbMixin extends LivingEntity {
|
||||
Player player = (Player) (Object) this;
|
||||
return MantisClawItem.isDualWielding(player)
|
||||
&& this.horizontalCollision
|
||||
&& !this.level().dimensionTypeRegistration().is(AntarchyTags.DimensionTypes.NO_MANTIS_CLIMB)
|
||||
&& !this.onGround()
|
||||
&& !this.isInWaterOrBubble()
|
||||
&& !this.isPassenger()
|
||||
|
||||
+19
@@ -1,6 +1,7 @@
|
||||
package com.craisinlord.antarchy.mixins.client;
|
||||
|
||||
import com.craisinlord.antarchy.content.entity.HerculesBeetleEntity;
|
||||
import com.craisinlord.antarchy.content.entity.royal.RoyalMountEntity;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
@@ -10,6 +11,7 @@ import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(Camera.class)
|
||||
@@ -23,6 +25,18 @@ public abstract class MountedVehicleCameraMixin {
|
||||
@Shadow
|
||||
protected abstract void setPosition(Vec3 position);
|
||||
|
||||
@ModifyArg(
|
||||
method = "setup",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Camera;getMaxZoom(D)D"),
|
||||
index = 0
|
||||
)
|
||||
private double antarchy$extendRoyalMountZoom(double distance) {
|
||||
if (this.entity != null && this.entity.getVehicle() instanceof RoyalMountEntity mount) {
|
||||
return distance + mount.thirdPersonCameraBonus();
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
|
||||
@Inject(method = "setup", at = @At("RETURN"))
|
||||
private void antarchy$adjustMountedCamera(
|
||||
BlockGetter level,
|
||||
@@ -32,6 +46,11 @@ public abstract class MountedVehicleCameraMixin {
|
||||
float partialTick,
|
||||
CallbackInfo ci
|
||||
) {
|
||||
if (this.detached && this.entity != null && this.entity.getVehicle() instanceof RoyalMountEntity mount) {
|
||||
Camera camera = (Camera) (Object) this;
|
||||
this.setPosition(camera.getPosition().add(new Vec3(camera.getUpVector()).scale(mount.thirdPersonCameraLift())));
|
||||
return;
|
||||
}
|
||||
if (!this.antarchy$ridingHerculesBeetle()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -517,6 +517,7 @@
|
||||
"message.antarchy.big_bertha.mode.molevore": "Molevore",
|
||||
"message.antarchy.big_bertha.mode.toreterror": "Toreterror",
|
||||
"message.antarchy.ultimate_tool.mode_3x3": "Auf 3x3-Abbau umgeschaltet",
|
||||
"message.antarchy.ultimate_tool.mode_vein": "Auf Adernabbau umgeschaltet",
|
||||
"message.antarchy.ultimate_tool.mode_default": "Auf normalen Abbau umgeschaltet",
|
||||
"advancements.antarchy.hey_listen.title": "Hey, hör zu!",
|
||||
"advancements.antarchy.hey_listen.description": "Eine Reverie hat sich dir angeschlossen.",
|
||||
@@ -549,6 +550,9 @@
|
||||
"tooltip.antarchy.big_bertha.mode.molevore": "Rechtsklick, um dich drehend nach vorn zu bohren und Molevore-Blöcke zu durchdringen.",
|
||||
"tooltip.antarchy.big_bertha.mode.toreterror": "Rechtsklick, um in die Luft zu springen und mit einer Flächenschockwelle herabzustürzen.",
|
||||
"tooltip.antarchy.ultimate_tools_3x3": "Umschalt-Rechtsklick, um 3x3-Abbau umzuschalten.",
|
||||
"tooltip.antarchy.ultimate_tools_vein": "Umschalt-Rechtsklick, um Adernabbau umzuschalten.",
|
||||
"tooltip.antarchy.ultimate_tools_3x3_vein": "Umschalt-Rechtsklick wechselt zwischen 3x3-Abbau und Adernabbau.",
|
||||
"tooltip.antarchy.battle_axe_tree_felling": "Fällt ganze Bäume. Schleichen, um einen einzelnen Stamm zu hacken.",
|
||||
"tooltip.antarchy.moggles.reveal": "Gewährt Nachtsicht und weist auf nahe Höhlen hin.",
|
||||
"tooltip.antarchy.moggles.underground": "Funktioniert nur, wenn du keinen freien Blick zum Himmel hast.",
|
||||
"tooltip.antarchy.cornea_ear.vision": "Gewährt %s Sekunden lang Nachtsicht.",
|
||||
|
||||
@@ -604,6 +604,16 @@
|
||||
"message.antarchy.royal_boundary.activated": "Royal Boundary raised",
|
||||
"message.antarchy.royal_boundary.recharging": "Royal Boundary is recharging",
|
||||
"key.antarchy.mount_flight_toggle": "Mount: Toggle Flight",
|
||||
"key.antarchy.mount_beam": "Royal Mount: Beam",
|
||||
"key.antarchy.mount_signature": "Royal Mount: Command / Time Field",
|
||||
"entity.antarchy.royal_mount.stage.hatchling": "Hatchling",
|
||||
"entity.antarchy.royal_mount.stage.juvenile": "Juvenile",
|
||||
"entity.antarchy.royal_mount.stage.adult": "Adult",
|
||||
"message.antarchy.royal_mount.stage_up": "%s has reached the %s stage!",
|
||||
"message.antarchy.royal_mount.growth": "%s: %s, %s%% grown",
|
||||
"message.antarchy.royal_mount.too_young_ride": "%s must reach the %s stage before it can be ridden",
|
||||
"message.antarchy.royal_mount.too_young_fly": "%s must reach the %s stage before it can fly",
|
||||
"message.antarchy.royal_mount.too_young_ability": "%s must reach the %s stage to use that",
|
||||
"item.antarchy.springbug_leg": "Springbug Leg",
|
||||
"item.antarchy.springy_boots": "Springy Boots",
|
||||
"tooltip.antarchy.springy_boots": "Sneak to charge, then jump to spring upward.",
|
||||
@@ -791,6 +801,7 @@
|
||||
"message.antarchy.big_bertha.mode.molevore": "Molevore",
|
||||
"message.antarchy.big_bertha.mode.toreterror": "Toreterror",
|
||||
"message.antarchy.ultimate_tool.mode_3x3": "Switched to 3x3 Mining",
|
||||
"message.antarchy.ultimate_tool.mode_vein": "Switched to Vein Mining",
|
||||
"message.antarchy.ultimate_tool.mode_default": "Switched to Default Mining",
|
||||
"advancements.antarchy.hey_listen.title": "Hey Listen",
|
||||
"advancements.antarchy.hey_listen.description": "A Reverie has joined you.",
|
||||
@@ -829,6 +840,9 @@
|
||||
"tooltip.antarchy.big_bertha.mode.molevore": "Use to spin forward and drill through Molevore blocks.",
|
||||
"tooltip.antarchy.big_bertha.mode.toreterror": "Use to launch into the air and crash down with an AOE shockwave.",
|
||||
"tooltip.antarchy.ultimate_tools_3x3": "Shift + use to toggle 3x3 Mining.",
|
||||
"tooltip.antarchy.ultimate_tools_vein": "Shift + use to toggle Vein Mining.",
|
||||
"tooltip.antarchy.ultimate_tools_3x3_vein": "Shift + use to cycle 3x3 and Vein Mining.",
|
||||
"tooltip.antarchy.battle_axe_tree_felling": "Fells whole trees. Sneak to chop a single log.",
|
||||
"tooltip.antarchy.moggles.reveal": "Gives night vision and points to nearby caves.",
|
||||
"tooltip.antarchy.moggles.underground": "Works only while you have no sky access.",
|
||||
"tooltip.antarchy.cornea_ear.vision": "Grants Night Vision for %s seconds.",
|
||||
@@ -1644,12 +1658,12 @@
|
||||
,"guide.antarchy.entry.queen.description6": "In her final phase she also casts her own time dilation field, slowing anyone caught inside it."
|
||||
,"guide.antarchy.entry.prince.title": "Prince"
|
||||
,"guide.antarchy.entry.prince.subtitle": "Royal mount record"
|
||||
,"guide.antarchy.entry.prince.description": "Prince Eggs hatch into small Princes that grow when fed golden items."
|
||||
,"guide.antarchy.entry.prince.description2": "A grown Prince can be tamed and saddled for flight, fires elemental bolts at your enemies, and can command nearby hostile mobs. Feed responsibly; you are raising a small flying warlord."
|
||||
,"guide.antarchy.entry.prince.description": "Prince Eggs hatch into Hatchlings bonded to whoever placed the egg. Golden apples grow them a little and enchanted golden apples grow them a lot: Juveniles can be ridden and spit bolts, and Adults can fly, fire beams, and use their signature ability."
|
||||
,"guide.antarchy.entry.prince.description2": "The Prince is a ground brawler: he closes in to bite with all three heads, spits fire, ice, and lightning, and as an Adult commands nearby hostile mobs to fight for him. Feed responsibly; you are raising a small flying warlord."
|
||||
,"guide.antarchy.entry.princess.title": "Princess"
|
||||
,"guide.antarchy.entry.princess.subtitle": "Royal mount record"
|
||||
,"guide.antarchy.entry.princess.description": "Princess Eggs hatch into small Princesses that grow when fed golden items."
|
||||
,"guide.antarchy.entry.princess.description2": "A grown Princess can be tamed and saddled for flight, fires elemental bolts, and creates time-dilation fields around enemies."
|
||||
,"guide.antarchy.entry.princess.description": "Princess Eggs hatch into Hatchlings bonded to whoever placed the egg. Golden apples grow them a little and enchanted golden apples grow them a lot: Juveniles can be ridden and spit bolts, and Adults can fly, fire beams, and use their signature ability."
|
||||
,"guide.antarchy.entry.princess.description2": "The Princess fights at range: she keeps her distance, fires slowing bolts from her orbs, and as an Adult hovers above her foes and traps them in time-dilation fields."
|
||||
,"subtitles.antarchy.hoverboard_mount": "Hoverboard starts"
|
||||
,"subtitles.antarchy.hoverboard_dismount": "Hoverboard stops"
|
||||
,"subtitles.antarchy.hoverboard_idle": "Hoverboard hums"
|
||||
|
||||
@@ -517,6 +517,7 @@
|
||||
"message.antarchy.big_bertha.mode.molevore": "Molevore",
|
||||
"message.antarchy.big_bertha.mode.toreterror": "Toreterror",
|
||||
"message.antarchy.ultimate_tool.mode_3x3": "Cambiado a minería 3x3",
|
||||
"message.antarchy.ultimate_tool.mode_vein": "Cambiado a minería de vetas",
|
||||
"message.antarchy.ultimate_tool.mode_default": "Cambiado a minería normal",
|
||||
"advancements.antarchy.hey_listen.title": "¡Oye, escucha!",
|
||||
"advancements.antarchy.hey_listen.description": "Una Reverie se ha unido a ti.",
|
||||
@@ -549,6 +550,9 @@
|
||||
"tooltip.antarchy.big_bertha.mode.molevore": "Clic derecho para girar hacia delante y perforar bloques de Molevore.",
|
||||
"tooltip.antarchy.big_bertha.mode.toreterror": "Clic derecho para lanzarte al aire y caer con una onda de choque en área.",
|
||||
"tooltip.antarchy.ultimate_tools_3x3": "Mayús + clic derecho para alternar la minería 3x3.",
|
||||
"tooltip.antarchy.ultimate_tools_vein": "Mayús + clic derecho para alternar la minería de vetas.",
|
||||
"tooltip.antarchy.ultimate_tools_3x3_vein": "Mayús + clic derecho para alternar entre minería 3x3 y de vetas.",
|
||||
"tooltip.antarchy.battle_axe_tree_felling": "Tala árboles enteros. Agáchate para cortar un solo tronco.",
|
||||
"tooltip.antarchy.moggles.reveal": "Otorga Visión nocturna y señala cuevas cercanas.",
|
||||
"tooltip.antarchy.moggles.underground": "Solo funciona cuando no tienes acceso al cielo.",
|
||||
"tooltip.antarchy.cornea_ear.vision": "Otorga Visión nocturna durante %s segundos.",
|
||||
|
||||
@@ -517,6 +517,7 @@
|
||||
"message.antarchy.big_bertha.mode.molevore": "Molevore",
|
||||
"message.antarchy.big_bertha.mode.toreterror": "Toreterror",
|
||||
"message.antarchy.ultimate_tool.mode_3x3": "Mode minage 3x3 activé",
|
||||
"message.antarchy.ultimate_tool.mode_vein": "Mode minage de filons activé",
|
||||
"message.antarchy.ultimate_tool.mode_default": "Mode minage normal activé",
|
||||
"advancements.antarchy.hey_listen.title": "Hé, écoute !",
|
||||
"advancements.antarchy.hey_listen.description": "Une Reverie vous a rejoint.",
|
||||
@@ -549,6 +550,9 @@
|
||||
"tooltip.antarchy.big_bertha.mode.molevore": "Clic droit pour tournoyer vers l’avant et forer les blocs de Molevore.",
|
||||
"tooltip.antarchy.big_bertha.mode.toreterror": "Clic droit pour bondir dans les airs et retomber avec une onde de choc de zone.",
|
||||
"tooltip.antarchy.ultimate_tools_3x3": "Maj + clic droit pour activer ou désactiver le minage 3x3.",
|
||||
"tooltip.antarchy.ultimate_tools_vein": "Maj + clic droit pour activer ou désactiver le minage de filons.",
|
||||
"tooltip.antarchy.ultimate_tools_3x3_vein": "Maj + clic droit pour alterner entre minage 3x3 et minage de filons.",
|
||||
"tooltip.antarchy.battle_axe_tree_felling": "Abat des arbres entiers. Accroupis-toi pour couper une seule bûche.",
|
||||
"tooltip.antarchy.moggles.reveal": "Accorde Vision nocturne et indique les grottes proches.",
|
||||
"tooltip.antarchy.moggles.underground": "Fonctionne uniquement lorsque vous n’avez pas accès au ciel.",
|
||||
"tooltip.antarchy.cornea_ear.vision": "Accorde Vision nocturne pendant %s secondes.",
|
||||
|
||||
@@ -517,6 +517,7 @@
|
||||
"message.antarchy.big_bertha.mode.molevore": "Molevore",
|
||||
"message.antarchy.big_bertha.mode.toreterror": "Toreterror",
|
||||
"message.antarchy.ultimate_tool.mode_3x3": "Scavo 3×3 attivato",
|
||||
"message.antarchy.ultimate_tool.mode_vein": "Scavo di vene attivato",
|
||||
"message.antarchy.ultimate_tool.mode_default": "Scavo normale attivato",
|
||||
"advancements.antarchy.hey_listen.title": "Ehi, ascolta!",
|
||||
"advancements.antarchy.hey_listen.description": "Una Reverie si è unita a te.",
|
||||
@@ -549,6 +550,9 @@
|
||||
"tooltip.antarchy.big_bertha.mode.molevore": "Fai clic destro per ruotare in avanti e perforare i blocchi di Molevore.",
|
||||
"tooltip.antarchy.big_bertha.mode.toreterror": "Fai clic destro per balzare in aria e schiantarti con un’onda d’urto ad area.",
|
||||
"tooltip.antarchy.ultimate_tools_3x3": "Maiusc + clic destro per attivare o disattivare lo scavo 3×3.",
|
||||
"tooltip.antarchy.ultimate_tools_vein": "Maiusc + clic destro per attivare o disattivare lo scavo di vene.",
|
||||
"tooltip.antarchy.ultimate_tools_3x3_vein": "Maiusc + clic destro per alternare scavo 3×3 e scavo di vene.",
|
||||
"tooltip.antarchy.battle_axe_tree_felling": "Abbatte alberi interi. Accovacciati per tagliare un solo tronco.",
|
||||
"tooltip.antarchy.moggles.reveal": "Fornisce Visione notturna e indica le grotte vicine.",
|
||||
"tooltip.antarchy.moggles.underground": "Funziona solo quando non puoi vedere il cielo.",
|
||||
"tooltip.antarchy.cornea_ear.vision": "Conferisce Visione notturna per %s secondi.",
|
||||
|
||||
@@ -517,6 +517,7 @@
|
||||
"message.antarchy.big_bertha.mode.molevore": "モールヴォア",
|
||||
"message.antarchy.big_bertha.mode.toreterror": "トアテラー",
|
||||
"message.antarchy.ultimate_tool.mode_3x3": "3×3採掘に切り替えました",
|
||||
"message.antarchy.ultimate_tool.mode_vein": "鉱脈採掘に切り替えました",
|
||||
"message.antarchy.ultimate_tool.mode_default": "通常採掘に切り替えました",
|
||||
"advancements.antarchy.hey_listen.title": "ねえ、聞いて!",
|
||||
"advancements.antarchy.hey_listen.description": "レヴェリーが仲間になりました。",
|
||||
@@ -549,6 +550,9 @@
|
||||
"tooltip.antarchy.big_bertha.mode.molevore": "右クリックで回転しながら前進し、モールヴォアブロックを掘り抜きます。",
|
||||
"tooltip.antarchy.big_bertha.mode.toreterror": "右クリックで空中へ飛び上がり、範囲衝撃波とともに落下します。",
|
||||
"tooltip.antarchy.ultimate_tools_3x3": "シフトキー+右クリックで3×3採掘を切り替えます。",
|
||||
"tooltip.antarchy.ultimate_tools_vein": "シフトキー+右クリックで鉱脈採掘を切り替えます。",
|
||||
"tooltip.antarchy.ultimate_tools_3x3_vein": "シフトキー+右クリックで3×3採掘と鉱脈採掘を切り替えます。",
|
||||
"tooltip.antarchy.battle_axe_tree_felling": "木を丸ごと伐採します。スニーク中は原木を1つだけ切ります。",
|
||||
"tooltip.antarchy.moggles.reveal": "暗視を付与し、近くの洞窟を示します。",
|
||||
"tooltip.antarchy.moggles.underground": "空が見えない場所でのみ機能します。",
|
||||
"tooltip.antarchy.cornea_ear.vision": "%s秒間暗視を付与します。",
|
||||
|
||||
@@ -792,6 +792,7 @@
|
||||
"message.antarchy.big_bertha.mode.molevore": "몰레보어",
|
||||
"message.antarchy.big_bertha.mode.toreterror": "토레테러",
|
||||
"message.antarchy.ultimate_tool.mode_3x3": "3x3 채굴 모드로 전환됨",
|
||||
"message.antarchy.ultimate_tool.mode_vein": "광맥 채굴 모드로 전환됨",
|
||||
"message.antarchy.ultimate_tool.mode_default": "기본 채굴 모드로 전환됨",
|
||||
"advancements.antarchy.hey_listen.title": "야, 들어봐!",
|
||||
"advancements.antarchy.hey_listen.description": "레버리가 당신과 함께합니다.",
|
||||
@@ -830,6 +831,9 @@
|
||||
"tooltip.antarchy.big_bertha.mode.molevore": "공격 시 추가 피해를 입히고 대상을 공중 높이 띄웁니다.",
|
||||
"tooltip.antarchy.big_bertha.mode.toreterror": "사용하여 앞으로 회전하며 몰레보어 블록을 뚫고 나아갑니다.",
|
||||
"tooltip.antarchy.ultimate_tools_3x3": "Shift + 사용: 3x3 채굴을 켜거나 끕니다.",
|
||||
"tooltip.antarchy.ultimate_tools_vein": "Shift + 사용: 광맥 채굴을 켜거나 끕니다.",
|
||||
"tooltip.antarchy.ultimate_tools_3x3_vein": "Shift + 사용: 3x3 채굴과 광맥 채굴을 전환합니다.",
|
||||
"tooltip.antarchy.battle_axe_tree_felling": "나무 전체를 벱니다. 웅크리면 통나무 하나만 벱니다.",
|
||||
"tooltip.antarchy.moggles.reveal": "야간 시야를 부여하고 근처 동굴을 가리킵니다.",
|
||||
"tooltip.antarchy.moggles.underground": "하늘이 가려진 곳에서만 작동합니다.",
|
||||
"tooltip.antarchy.cornea_ear.vision": "%s초 동안 야간 시야를 부여합니다.",
|
||||
|
||||
@@ -517,6 +517,7 @@
|
||||
"message.antarchy.big_bertha.mode.molevore": "Molevore",
|
||||
"message.antarchy.big_bertha.mode.toreterror": "Toreterror",
|
||||
"message.antarchy.ultimate_tool.mode_3x3": "Alternado para Mineração 3x3",
|
||||
"message.antarchy.ultimate_tool.mode_vein": "Alternado para Mineração de Veios",
|
||||
"message.antarchy.ultimate_tool.mode_default": "Alternado para Mineração Padrão",
|
||||
"advancements.antarchy.hey_listen.title": "Ei, Escute!",
|
||||
"advancements.antarchy.hey_listen.description": "Uma Reverie se juntou a você.",
|
||||
@@ -549,6 +550,9 @@
|
||||
"tooltip.antarchy.big_bertha.mode.molevore": "Clique com o botão direito para girar para a frente e perfurar blocos de Molevore.",
|
||||
"tooltip.antarchy.big_bertha.mode.toreterror": "Clique com o botão direito para se lançar ao ar e cair com uma onda de choque em área.",
|
||||
"tooltip.antarchy.ultimate_tools_3x3": "Shift + clique com o botão direito para alternar a Mineração 3x3.",
|
||||
"tooltip.antarchy.ultimate_tools_vein": "Shift + clique com o botão direito para alternar a Mineração de Veios.",
|
||||
"tooltip.antarchy.ultimate_tools_3x3_vein": "Shift + clique com o botão direito para alternar entre Mineração 3x3 e de Veios.",
|
||||
"tooltip.antarchy.battle_axe_tree_felling": "Derruba árvores inteiras. Agache para cortar um único tronco.",
|
||||
"tooltip.antarchy.moggles.reveal": "Concede Visão Noturna e aponta para cavernas próximas.",
|
||||
"tooltip.antarchy.moggles.underground": "Funciona apenas quando você não tem acesso ao céu.",
|
||||
"tooltip.antarchy.cornea_ear.vision": "Concede Visão Noturna por %s segundos.",
|
||||
|
||||
@@ -488,6 +488,7 @@
|
||||
"message.antarchy.big_bertha.mode.molevore": "Кротожор",
|
||||
"message.antarchy.big_bertha.mode.toreterror": "Тортеррор",
|
||||
"message.antarchy.ultimate_tool.mode_3x3": "Включено копание 3x3",
|
||||
"message.antarchy.ultimate_tool.mode_vein": "Включена добыча жил",
|
||||
"message.antarchy.ultimate_tool.mode_default": "Включено обычное копание",
|
||||
"advancements.antarchy.hey_listen.title": "Эй, послушай",
|
||||
"advancements.antarchy.hey_listen.description": "К вам присоединилась грёза.",
|
||||
@@ -520,6 +521,9 @@
|
||||
"tooltip.antarchy.big_bertha.mode.molevore": "ПКМ для рывка вперёд и бурения сквозь блоки кротожора.",
|
||||
"tooltip.antarchy.big_bertha.mode.toreterror": "ПКМ запускает вас в воздух и обрушивает вниз с ударной волной по площади.",
|
||||
"tooltip.antarchy.ultimate_tools_3x3": "Shift + ПКМ для переключения режима копания 3x3.",
|
||||
"tooltip.antarchy.ultimate_tools_vein": "Shift + ПКМ для переключения добычи жил.",
|
||||
"tooltip.antarchy.ultimate_tools_3x3_vein": "Shift + ПКМ переключает копание 3x3 и добычу жил.",
|
||||
"tooltip.antarchy.battle_axe_tree_felling": "Срубает дерево целиком. Присядьте, чтобы срубить одно бревно.",
|
||||
"tooltip.antarchy.moggles.reveal": "Дают ночное зрение и указывают на ближайшие пещеры.",
|
||||
"tooltip.antarchy.moggles.underground": "Работает только если над вами нет открытого неба.",
|
||||
"tooltip.antarchy.cornea_ear.vision": "Даёт Ночное зрение на %s секунд.",
|
||||
|
||||
@@ -517,6 +517,7 @@
|
||||
"message.antarchy.big_bertha.mode.molevore": "莫尔沃尔",
|
||||
"message.antarchy.big_bertha.mode.toreterror": "托尔泰罗尔",
|
||||
"message.antarchy.ultimate_tool.mode_3x3": "已切换至3×3挖掘",
|
||||
"message.antarchy.ultimate_tool.mode_vein": "已切换至连锁挖矿",
|
||||
"message.antarchy.ultimate_tool.mode_default": "已切换至默认挖掘",
|
||||
"advancements.antarchy.hey_listen.title": "嘿,听着!",
|
||||
"advancements.antarchy.hey_listen.description": "一只雷弗里加入了你。",
|
||||
@@ -549,6 +550,9 @@
|
||||
"tooltip.antarchy.big_bertha.mode.molevore": "右键旋转向前并钻穿莫尔沃尔方块。",
|
||||
"tooltip.antarchy.big_bertha.mode.toreterror": "右键跃向空中并以范围冲击波砸落。",
|
||||
"tooltip.antarchy.ultimate_tools_3x3": "潜行键+右键切换3×3挖掘。",
|
||||
"tooltip.antarchy.ultimate_tools_vein": "潜行键+右键切换连锁挖矿。",
|
||||
"tooltip.antarchy.ultimate_tools_3x3_vein": "潜行键+右键在3×3挖掘与连锁挖矿之间切换。",
|
||||
"tooltip.antarchy.battle_axe_tree_felling": "一次砍倒整棵树。潜行时只砍一块原木。",
|
||||
"tooltip.antarchy.moggles.reveal": "获得夜视并指向附近洞穴。",
|
||||
"tooltip.antarchy.moggles.underground": "仅在无法接触天空时生效。",
|
||||
"tooltip.antarchy.cornea_ear.vision": "获得%s秒夜视。",
|
||||
|
||||
@@ -517,6 +517,7 @@
|
||||
"message.antarchy.big_bertha.mode.molevore": "莫爾沃爾",
|
||||
"message.antarchy.big_bertha.mode.toreterror": "托爾泰羅爾",
|
||||
"message.antarchy.ultimate_tool.mode_3x3": "已切換至3×3挖掘",
|
||||
"message.antarchy.ultimate_tool.mode_vein": "已切換至連鎖挖礦",
|
||||
"message.antarchy.ultimate_tool.mode_default": "已切換至預設挖掘",
|
||||
"advancements.antarchy.hey_listen.title": "嘿,聽著!",
|
||||
"advancements.antarchy.hey_listen.description": "一隻雷弗里加入了你。",
|
||||
@@ -549,6 +550,9 @@
|
||||
"tooltip.antarchy.big_bertha.mode.molevore": "右鍵旋轉向前並鑽穿莫爾沃爾方塊。",
|
||||
"tooltip.antarchy.big_bertha.mode.toreterror": "右鍵躍向空中並以範圍衝擊波砸落。",
|
||||
"tooltip.antarchy.ultimate_tools_3x3": "潛行鍵+右鍵切換3×3挖掘。",
|
||||
"tooltip.antarchy.ultimate_tools_vein": "潛行鍵+右鍵切換連鎖挖礦。",
|
||||
"tooltip.antarchy.ultimate_tools_3x3_vein": "潛行鍵+右鍵在3×3挖掘與連鎖挖礦之間切換。",
|
||||
"tooltip.antarchy.battle_axe_tree_felling": "一次砍倒整棵樹。潛行時只砍一塊原木。",
|
||||
"tooltip.antarchy.moggles.reveal": "獲得夜視並指向附近洞穴。",
|
||||
"tooltip.antarchy.moggles.underground": "僅在無法接觸天空時生效。",
|
||||
"tooltip.antarchy.cornea_ear.vision": "獲得%s秒夜視。",
|
||||
|
||||
+2
-1
@@ -55,7 +55,8 @@
|
||||
],
|
||||
[
|
||||
"antarchy:moleworm_caves_creepvine",
|
||||
"antarchy:moleworm_caves_hanging_creeproots"
|
||||
"antarchy:moleworm_caves_hanging_creeproots",
|
||||
"antarchy:termite_nest"
|
||||
],
|
||||
[]
|
||||
],
|
||||
|
||||
@@ -52,7 +52,8 @@
|
||||
"antarchy:wormy_caves_creepvine",
|
||||
"antarchy:wormy_caves_hanging_creeproots",
|
||||
"antarchy:wormy_caves_molting_vines",
|
||||
"antarchy:wormy_caves_ground_molting_vines"
|
||||
"antarchy:wormy_caves_ground_molting_vines",
|
||||
"antarchy:termite_nest"
|
||||
],
|
||||
[]
|
||||
],
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
"placement": [
|
||||
{
|
||||
"type": "minecraft:rarity_filter",
|
||||
"chance": 24
|
||||
"chance": 8
|
||||
},
|
||||
{
|
||||
"type": "minecraft:in_square"
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
"placement": [
|
||||
{
|
||||
"type": "minecraft:rarity_filter",
|
||||
"chance": 24
|
||||
"chance": 8
|
||||
},
|
||||
{
|
||||
"type": "minecraft:in_square"
|
||||
|
||||
+11
-3
@@ -3,14 +3,22 @@
|
||||
"placement": [
|
||||
{
|
||||
"type": "minecraft:rarity_filter",
|
||||
"chance": 88
|
||||
"chance": 24
|
||||
},
|
||||
{
|
||||
"type": "minecraft:in_square"
|
||||
},
|
||||
{
|
||||
"type": "minecraft:heightmap",
|
||||
"heightmap": "WORLD_SURFACE_WG"
|
||||
"type": "minecraft:height_range",
|
||||
"height": {
|
||||
"type": "minecraft:uniform",
|
||||
"min_inclusive": {
|
||||
"absolute": 8
|
||||
},
|
||||
"max_inclusive": {
|
||||
"absolute": 190
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "minecraft:biome"
|
||||
|
||||
+11
-3
@@ -3,14 +3,22 @@
|
||||
"placement": [
|
||||
{
|
||||
"type": "minecraft:rarity_filter",
|
||||
"chance": 44
|
||||
"chance": 16
|
||||
},
|
||||
{
|
||||
"type": "minecraft:in_square"
|
||||
},
|
||||
{
|
||||
"type": "minecraft:heightmap",
|
||||
"heightmap": "WORLD_SURFACE_WG"
|
||||
"type": "minecraft:height_range",
|
||||
"height": {
|
||||
"type": "minecraft:uniform",
|
||||
"min_inclusive": {
|
||||
"absolute": 8
|
||||
},
|
||||
"max_inclusive": {
|
||||
"absolute": 190
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "minecraft:biome"
|
||||
|
||||
-5
@@ -31,11 +31,6 @@ public interface InfinityCompatBridge {
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -107,6 +107,9 @@ public final class AntarchySettings {
|
||||
private static int ultimateCrossbowEnchantability = 20;
|
||||
private static int ultimateMaceEnchantability = 20;
|
||||
private static boolean ultimateToolsThreeByThreeEnabled = true;
|
||||
private static boolean ultimateToolsVeinMiningEnabled = true;
|
||||
private static int ultimateToolsVeinMiningMaxBlocks = 64;
|
||||
private static int ultimateToolsTreeFellingMaxLogs = 128;
|
||||
private static boolean ultimateArmorComesEnchanted = true;
|
||||
private static int ultimateHelmetArmorValue = 6;
|
||||
private static int ultimateChestplateArmorValue = 11;
|
||||
@@ -299,6 +302,7 @@ public final class AntarchySettings {
|
||||
private static double royalBossKnockbackResistance = 1.0D;
|
||||
private static double royalBossStepHeight = 3.0D;
|
||||
private static double royalBossMaxSingleHitDamage = 250.0D;
|
||||
private static double royalBossHitOverflowRate = 0.25D;
|
||||
private static double royalBossBiteReach = 12.0D;
|
||||
private static double royalBossBiteDamageMultiplier = 1.6D;
|
||||
private static int royalBossBiteCooldownTicks = 45;
|
||||
@@ -563,7 +567,6 @@ public final class AntarchySettings {
|
||||
private static int bloodCrystalAppleDurationTicks = 2400;
|
||||
private static int bloodCrystalAppleShieldRechargeTicks = 600;
|
||||
private static int bloodCrystalHardMaxShields = 10;
|
||||
// Armor stats (iron defense, gold durability, 0 toughness by default)
|
||||
private static int bloodCrystalHelmetDefense = 3;
|
||||
private static int bloodCrystalChestplateDefense = 7;
|
||||
private static int bloodCrystalLeggingsDefense = 6;
|
||||
@@ -975,6 +978,18 @@ public final class AntarchySettings {
|
||||
return ultimateToolsThreeByThreeEnabled;
|
||||
}
|
||||
|
||||
public static boolean ultimateToolsVeinMiningEnabled() {
|
||||
return ultimateToolsVeinMiningEnabled;
|
||||
}
|
||||
|
||||
public static int ultimateToolsVeinMiningMaxBlocks() {
|
||||
return ultimateToolsVeinMiningMaxBlocks;
|
||||
}
|
||||
|
||||
public static int ultimateToolsTreeFellingMaxLogs() {
|
||||
return ultimateToolsTreeFellingMaxLogs;
|
||||
}
|
||||
|
||||
public static boolean ultimateArmorComesEnchanted() {
|
||||
return ultimateArmorComesEnchanted;
|
||||
}
|
||||
@@ -1625,6 +1640,18 @@ public final class AntarchySettings {
|
||||
ultimateToolsThreeByThreeEnabled = value;
|
||||
}
|
||||
|
||||
public static void setUltimateToolsVeinMiningEnabled(boolean value) {
|
||||
ultimateToolsVeinMiningEnabled = value;
|
||||
}
|
||||
|
||||
public static void setUltimateToolsVeinMiningMaxBlocks(int value) {
|
||||
ultimateToolsVeinMiningMaxBlocks = value;
|
||||
}
|
||||
|
||||
public static void setUltimateToolsTreeFellingMaxLogs(int value) {
|
||||
ultimateToolsTreeFellingMaxLogs = value;
|
||||
}
|
||||
|
||||
public static void setUltimateArmorComesEnchanted(boolean value) {
|
||||
ultimateArmorComesEnchanted = value;
|
||||
}
|
||||
@@ -2230,6 +2257,9 @@ public final class AntarchySettings {
|
||||
public static double royalBossMaxSingleHitDamage() { return royalBossMaxSingleHitDamage; }
|
||||
public static void setRoyalBossMaxSingleHitDamage(double v) { royalBossMaxSingleHitDamage = v; }
|
||||
|
||||
public static double royalBossHitOverflowRate() { return royalBossHitOverflowRate; }
|
||||
public static void setRoyalBossHitOverflowRate(double v) { royalBossHitOverflowRate = v; }
|
||||
|
||||
public static double royalBossBiteReach() { return royalBossBiteReach; }
|
||||
public static void setRoyalBossBiteReach(double v) { royalBossBiteReach = v; }
|
||||
|
||||
@@ -2499,7 +2529,6 @@ public final class AntarchySettings {
|
||||
public static int reverieDuplicationCooldownTicks() { return reverieDuplicationCooldownTicks; }
|
||||
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 reveriePreferredFollowMaxDistance() { return reveriePreferredFollowMaxDistance; }
|
||||
public static double reverieCatchUpDistance() { return reverieCatchUpDistance; }
|
||||
|
||||
@@ -11,6 +11,7 @@ import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
|
||||
public final class AntarchyTags {
|
||||
@@ -157,4 +158,11 @@ public final class AntarchyTags {
|
||||
private Biomes() {
|
||||
}
|
||||
}
|
||||
|
||||
public static final class DimensionTypes {
|
||||
public static final TagKey<DimensionType> NO_MANTIS_CLIMB = TagKey.create(Registries.DIMENSION_TYPE, id("no_mantis_climb"));
|
||||
|
||||
private DimensionTypes() {
|
||||
}
|
||||
}
|
||||
}
|
||||
-5
@@ -30,11 +30,6 @@ public final class AntarchyAdvancementTriggers {
|
||||
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) {
|
||||
registrar.accept(ResourceLocation.fromNamespaceAndPath("antarchy", "crossed_gravity_throat"), CROSSING);
|
||||
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_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 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.phys.BlockHitResult;
|
||||
|
||||
/** A two-block-tall, light-emitting reed found around Lumen pools. */
|
||||
public final class GlimmeringReedBlock extends DoublePlantBlock implements BonemealableBlock {
|
||||
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 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 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.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 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) {
|
||||
BlockPos above = pos.above();
|
||||
if (!FallingBlock.isFree(level.getBlockState(above)) || above.getY() > level.getMaxBuildHeight()) {
|
||||
|
||||
-2
@@ -65,8 +65,6 @@ public final class QueenTrailSpawnMarkerBlockEntity extends BlockEntity {
|
||||
if (!nearbyPlayer) {
|
||||
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 chunkZ = (marker.spawnPos.getZ() - 16) >> 4; chunkZ <= (marker.spawnPos.getZ() + 16) >> 4; 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) {
|
||||
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();
|
||||
if (state.getValue(UnderVaultBlock.STATE) == VaultState.INACTIVE && playerNearby && !blockEntity.playerWasNearby) {
|
||||
state = state.setValue(UnderVaultBlock.STATE, VaultState.ACTIVE);
|
||||
|
||||
-5
@@ -1,10 +1,5 @@
|
||||
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 {
|
||||
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) {
|
||||
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.markUpdated();
|
||||
}
|
||||
|
||||
-1
@@ -6,7 +6,6 @@ import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
||||
/** Client state for Antarchy-owned games hosted by AntOS. */
|
||||
public final class AntarchyGameClientState {
|
||||
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 double AIM_COSINE = Math.cos(Math.toRadians(PortalGunMoonMath.AIM_TOLERANCE_DEGREES));
|
||||
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 long recordedAt;
|
||||
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 float MISSING_BRIGHTNESS = 0.3F;
|
||||
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 long cachedGameTime = Long.MIN_VALUE;
|
||||
private static UUID cachedGunId;
|
||||
|
||||
-1
@@ -12,7 +12,6 @@ import net.minecraft.client.multiplayer.ClientLevel;
|
||||
|
||||
public final class PortalGunIndicatorClientState {
|
||||
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 long lastRequestTick = Long.MIN_VALUE;
|
||||
private static UUID lastRequestedGun;
|
||||
|
||||
-3
@@ -8,14 +8,11 @@ import net.minecraft.resources.ResourceLocation;
|
||||
import java.util.function.IntPredicate;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/** Registers Antarchy's native games with the AntOS Games app. */
|
||||
public final class AntarchyComputerGames {
|
||||
private AntarchyComputerGames() {}
|
||||
|
||||
public static void register() {
|
||||
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 -> {});
|
||||
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.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> {
|
||||
private final ModelPart root;
|
||||
private final ModelPart head;
|
||||
|
||||
-1
@@ -9,7 +9,6 @@ public class AlphaMantisRenderer extends GeoEntityRenderer<AlphaMantisEntity> {
|
||||
public AlphaMantisRenderer(EntityRendererProvider.Context context) {
|
||||
super(context, new AlphaMantisModel());
|
||||
this.shadowRadius = 1.5F;
|
||||
// Mantis renders at 1.25x; the alpha is 1.5x bigger overall
|
||||
this.withScale(1.875F);
|
||||
}
|
||||
}
|
||||
+4
-9
@@ -74,7 +74,6 @@ public final class ElythiaSkyRenderer {
|
||||
float starBrightness = level.getStarBrightness(partialTick) * (1.0F - rainLevel);
|
||||
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 nightPurpleG = 0.010F;
|
||||
float nightPurpleB = 0.120F;
|
||||
@@ -169,10 +168,10 @@ public final class ElythiaSkyRenderer {
|
||||
|
||||
private static float[] pickStarColor(Random random) {
|
||||
float roll = random.nextFloat();
|
||||
if (roll < 0.80F) return new float[]{1.0F, 1.0F, 1.0F}; // white
|
||||
if (roll < 0.87F) return new float[]{0.85F, 0.60F, 1.00F}; // light purple
|
||||
if (roll < 0.94F) return new float[]{1.00F, 0.95F, 0.50F}; // yellow
|
||||
return new float[]{1.0F, 0.45F, 0.45F}; // red
|
||||
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};
|
||||
if (roll < 0.94F) return new float[]{1.00F, 0.95F, 0.50F};
|
||||
return new float[]{1.0F, 0.45F, 0.45F};
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
// Purple sun
|
||||
float sun1Orbit = orbitAngle(timeDegrees, 1.0D, 0.0D);
|
||||
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));
|
||||
|
||||
// Orange sub
|
||||
float sun2Orbit = orbitAngle(timeDegrees, 0.73D, 54.0D);
|
||||
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));
|
||||
|
||||
// Dark green moon
|
||||
float moon2Orbit = orbitAngle(timeDegrees, 1.27D, 228.0D);
|
||||
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));
|
||||
|
||||
// Light green moon
|
||||
float moon3Orbit = orbitAngle(timeDegrees, 0.38D, 122.0D);
|
||||
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));
|
||||
|
||||
-3
@@ -193,9 +193,6 @@ public class RoyalBossRenderer extends GeoEntityRenderer<RoyalBossEntity> {
|
||||
float outerV = -time * 0.25F;
|
||||
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 pitch = (float) Math.acos(dir.y);
|
||||
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, 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, 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);
|
||||
|
||||
-4
@@ -22,9 +22,6 @@ import net.minecraft.world.level.block.state.BlockState;
|
||||
public final class TigerEyeCamouflageTextureResolver {
|
||||
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 Map<Integer, ResolvedTexture> CACHE = new ConcurrentHashMap<>();
|
||||
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)) {
|
||||
int tileWidth = sourceImage.getWidth();
|
||||
// Animated block textures stack frames vertically below a square first frame.
|
||||
int tileHeight = tileWidth <= sourceImage.getHeight() ? tileWidth : sourceImage.getHeight();
|
||||
|
||||
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, 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, 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();
|
||||
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);
|
||||
poseStack.mulPose(Axis.YP.rotationDegrees(180.0F - bodyYaw));
|
||||
poseStack.scale(-1.0F, -1.0F, 1.0F);
|
||||
|
||||
-1
@@ -82,7 +82,6 @@ public final class QueenLocateCommand {
|
||||
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) {
|
||||
int cellX = Math.floorDiv(originX, 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.phys.AABB;
|
||||
|
||||
/** Archive coordinate lookups for royals that live on grids rather than in vanilla structures. */
|
||||
public final class AntarchyArchiveLocators {
|
||||
private AntarchyArchiveLocators() {
|
||||
}
|
||||
|
||||
-1
@@ -10,7 +10,6 @@ import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.world.level.saveddata.SavedData;
|
||||
|
||||
/** Persistent Antarchy game progress keyed by AntOS computer location. */
|
||||
public final class AntarchyGameSavedData extends SavedData {
|
||||
private static final String ID = "antarchy_computer_games";
|
||||
private final Map<String, GameState> games = new HashMap<>();
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ public final class BloodglassWardEffect extends MobEffect {
|
||||
public void addAttributeModifiers(AttributeMap attributeMap, int amplifier) {
|
||||
AttributeInstance instance = attributeMap.getInstance(AntarchyObjects.BLOODGLASS_MAX_HEARTS.get());
|
||||
if (instance == null) return;
|
||||
instance.addTransientModifier(
|
||||
instance.addOrUpdateTransientModifier(
|
||||
new AttributeModifier(MODIFIER_ID, amplifier + 1, AttributeModifier.Operation.ADD_VALUE)
|
||||
);
|
||||
}
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ public final class GrowthMobEffect extends MobEffect {
|
||||
AttributeInstance instance = attributeMap.getInstance(Attributes.SCALE);
|
||||
if (instance == null) return;
|
||||
double amount = AntarchySettings.growthPotionDelta() * (amplifier + 1);
|
||||
instance.addTransientModifier(
|
||||
instance.addOrUpdateTransientModifier(
|
||||
new AttributeModifier(MODIFIER_ID, amount, AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL)
|
||||
);
|
||||
}
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
package com.craisinlord.antarchy.content.effect;
|
||||
|
||||
/** Synchronized, presentation-only state for the short-lived Royal Judgment mark. */
|
||||
public interface JudgmentMarkAccess {
|
||||
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.player.Player;
|
||||
|
||||
/** Server-owned, player-specific Judgment marks. The visible bit is synchronized by vanilla entity data. */
|
||||
public final class JudgmentMarkManager {
|
||||
private static final Map<ServerLevel, MarkBook> MARKS = new WeakHashMap<>();
|
||||
|
||||
private JudgmentMarkManager() {
|
||||
}
|
||||
|
||||
/** Returns true when this owner had already marked this target before the current hit. */
|
||||
public static boolean recordSuccessfulHit(Player owner, LivingEntity target) {
|
||||
if (!(owner instanceof ServerPlayer serverPlayer) || !(target.level() instanceof ServerLevel level)
|
||||
|| 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;
|
||||
}
|
||||
|
||||
/** Prunes marks from this target and updates the vanilla-synchronized render bit. */
|
||||
public static void tickTarget(LivingEntity target) {
|
||||
if (!(target.level() instanceof ServerLevel level)) {
|
||||
return;
|
||||
|
||||
-4
@@ -23,7 +23,6 @@ import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
/** Server-authoritative Royal Guardian chestplate field and temporary projectile arrest state. */
|
||||
public final class RoyalBoundaryManager {
|
||||
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);
|
||||
@@ -51,7 +50,6 @@ public final class RoyalBoundaryManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Called from ServerPlayer.tick; ends fields immediately when their owner can no longer sustain them. */
|
||||
public static void tickOwner(ServerPlayer owner) {
|
||||
if (!(owner.level() instanceof ServerLevel level)) return;
|
||||
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) {
|
||||
if (!(projectile.level() instanceof ServerLevel level) || projectile.isRemoved()) return;
|
||||
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) {
|
||||
if (!(projectile.level() instanceof ServerLevel level)) return;
|
||||
Map<UUID, ArrestedProjectile> arrested = ARRESTED.get(level);
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ public final class RoyalVitalityPenaltyEffect extends MobEffect {
|
||||
public void addAttributeModifiers(AttributeMap attributeMap, int amplifier) {
|
||||
AttributeInstance maxHealth = attributeMap.getInstance(Attributes.MAX_HEALTH);
|
||||
if (maxHealth == null) return;
|
||||
maxHealth.addTransientModifier(new AttributeModifier(
|
||||
maxHealth.addOrUpdateTransientModifier(new AttributeModifier(
|
||||
MODIFIER_ID, -0.5D, AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL));
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ public final class ShrinkMobEffect extends MobEffect {
|
||||
AttributeInstance instance = attributeMap.getInstance(Attributes.SCALE);
|
||||
if (instance == null) return;
|
||||
double amount = -(AntarchySettings.shrinkingPotionDelta() * (amplifier + 1));
|
||||
instance.addTransientModifier(
|
||||
instance.addOrUpdateTransientModifier(
|
||||
new AttributeModifier(MODIFIER_ID, amount, AttributeModifier.Operation.ADD_MULTIPLIED_TOTAL)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -408,10 +408,6 @@ public class FlytrapEntity extends Monster implements GeoEntity {
|
||||
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());
|
||||
candidate.hurt(AntarchyDamageSources.flytrapMauling(serverLevel, this), (float) AntarchySettings.flytrapAttackDamage());
|
||||
}
|
||||
|
||||
+26
-3
@@ -391,6 +391,9 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
|
||||
if (this.isKnockedDown()) {
|
||||
this.tickKnockedDown();
|
||||
} else if (this.isLeashed()) {
|
||||
if (this.chargeTicksRemaining > 0 || this.isChargeAnimationActive()) {
|
||||
this.endChargeState();
|
||||
}
|
||||
this.getNavigation().stop();
|
||||
this.setTarget(null);
|
||||
this.updateAmbientAnimation();
|
||||
@@ -483,6 +486,10 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
|
||||
}
|
||||
|
||||
private void tickCharge() {
|
||||
if (this.chargeTicksRemaining <= 0) {
|
||||
this.endChargeState();
|
||||
return;
|
||||
}
|
||||
if (this.getAnimationState() != ANIM_CHARGE) {
|
||||
this.setAnimationState(ANIM_CHARGE);
|
||||
}
|
||||
@@ -909,6 +916,9 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
|
||||
if (!this.isFlying() && !mountedCharge) {
|
||||
this.pendingChargeStart = true;
|
||||
this.requestFlightStart();
|
||||
if (this.getAnimationState() != ANIM_OPEN_WINGS) {
|
||||
this.pendingChargeStart = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.beginChargeStart(this.chargeDirection, this.pendingChargeDuration, mountedCharge);
|
||||
@@ -978,13 +988,23 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
|
||||
serverLevel.sendParticles(ParticleTypes.CRIT, this.getX(), this.getY() + 0.8D, this.getZ(), 20, 2.0D, 0.6D, 2.0D, 0.08D);
|
||||
this.broadcastImpactShake(serverLevel);
|
||||
|
||||
if (this.onGround()) {
|
||||
this.endChargeState();
|
||||
}
|
||||
|
||||
private void endChargeState() {
|
||||
this.chargeTicksRemaining = 0;
|
||||
this.groundedMountedCharge = false;
|
||||
this.noPhysics = false;
|
||||
this.setAnimationState(this.isFlying() ? ANIM_FLY : ANIM_IDLE);
|
||||
if (!this.isVehicle() && this.isFlying() && this.hasGroundBelow()) {
|
||||
this.requestFlightStop();
|
||||
} else {
|
||||
this.updateAmbientAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasGroundBelow() {
|
||||
return !this.level().noCollision(this, this.getBoundingBox().move(this.toWorld(0.0D, -0.2D, 0.0D)));
|
||||
}
|
||||
|
||||
private void breakBlocksForChargeImpact(ServerLevel level) {
|
||||
if (!this.isHerculesBeetleGriefingEnabled(level)) {
|
||||
return;
|
||||
@@ -1423,6 +1443,9 @@ public class HerculesBeetleEntity extends TamableAnimal implements GeoEntity, Fl
|
||||
this.chargeCooldown = tag.getInt("ChargeCooldown");
|
||||
this.attackCooldown = tag.getInt("AttackCooldown");
|
||||
this.combatCryDone = tag.getBoolean("CombatCryDone");
|
||||
if (this.isChargeAnimationActive()) {
|
||||
this.setAnimationState(this.isFlying() ? ANIM_FLY : ANIM_IDLE);
|
||||
}
|
||||
if (this.isKnockedDown() && this.getAnimationState() != ANIM_KNOCKED_DOWN_IDLE) {
|
||||
this.setAnimationState(ANIM_KNOCKED_DOWN_IDLE);
|
||||
}
|
||||
|
||||
@@ -149,12 +149,10 @@ public class MantisEntity extends Monster implements GeoEntity {
|
||||
|
||||
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)) {
|
||||
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)) {
|
||||
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);
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
+1
-10
@@ -88,7 +88,6 @@ public class OctopusBombEntity extends Monster implements GeoEntity {
|
||||
|
||||
private boolean spawnedByKraken;
|
||||
|
||||
// Explosive impact (fired from the R.P.O. Launcher)
|
||||
private boolean explosiveImpact;
|
||||
private java.util.UUID explosiveLauncherId;
|
||||
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(6, new RandomLookAroundGoal(this));
|
||||
|
||||
// Only retaliate when hit — neutral otherwise
|
||||
this.targetSelector.addGoal(1, new HurtByTargetGoal(this));
|
||||
// When spawned by Kraken and flying, target nearest player
|
||||
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.inkSprayCooldown > 0) this.inkSprayCooldown--;
|
||||
|
||||
// Ink spray — always active regardless of aggro state
|
||||
this.tickInkSpray();
|
||||
|
||||
LivingEntity target = this.getTarget();
|
||||
@@ -375,10 +371,9 @@ public class OctopusBombEntity extends Monster implements GeoEntity {
|
||||
float angle = this.random.nextFloat() * (float) (Math.PI * 2);
|
||||
this.wanderDx = Mth.cos(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;
|
||||
if (!this.level().getFluidState(this.blockPosition().above()).is(net.minecraft.tags.FluidTags.WATER)) {
|
||||
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 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_UNROLL = 4;
|
||||
|
||||
// wheel_mode is 0.75s, normal_mode is ~0.42s
|
||||
private static final int ROLL_UP_TICKS = 15;
|
||||
private static final int UNROLL_TICKS = 9;
|
||||
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) {
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
// Curled-up or tamed rolly pollies stand their ground
|
||||
return !RollyPollyEntity.this.isRolled() && !RollyPollyEntity.this.isTame() && super.canUse();
|
||||
}
|
||||
});
|
||||
@@ -318,7 +316,6 @@ public class RollyPollyEntity extends TamableAnimal implements GeoEntity {
|
||||
amount *= 0.25F;
|
||||
}
|
||||
boolean hurt = super.hurt(source, amount);
|
||||
// Wild rolly pollies curl up defensively when attacked
|
||||
if (hurt && !this.level().isClientSide && !this.isTame() && this.isAlive()
|
||||
&& !this.isRolled() && this.rollTransitionTicks <= 0) {
|
||||
this.defensiveCurlTicks = DEFENSIVE_CURL_TICKS;
|
||||
|
||||
-8
@@ -111,9 +111,6 @@ public class ScorpionEntity extends Monster implements GeoEntity {
|
||||
|| spawnReason == MobSpawnType.COMMAND) {
|
||||
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()) {
|
||||
return false;
|
||||
}
|
||||
@@ -356,8 +353,6 @@ public class ScorpionEntity extends Monster implements GeoEntity {
|
||||
ScorpionEntity.this.getNavigation().stop();
|
||||
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();
|
||||
if (target != null && ThoraxisUndersideManager.shouldInvertInUnderside(ScorpionEntity.this)) {
|
||||
ScorpionEntity.this.getNavigation().stop();
|
||||
@@ -379,9 +374,6 @@ public class ScorpionEntity extends Monster implements GeoEntity {
|
||||
if (ScorpionEntity.this.isAttackLocked()) {
|
||||
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) {
|
||||
ScorpionEntity.this.beginAttack(enemy);
|
||||
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 dy = diff.y;
|
||||
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 vx = diff.x / t;
|
||||
double vz = diff.z / t;
|
||||
// Compensate for gravity accumulating over t ticks
|
||||
double vy = dy / t + 0.5 * gravity * t;
|
||||
return new Vec3(vx, vy, vz);
|
||||
}
|
||||
|
||||
-6
@@ -46,10 +46,6 @@ public class UpwardFallingBlockEntity extends Entity {
|
||||
|
||||
public UpwardFallingBlockEntity(EntityType<UpwardFallingBlockEntity> type, Level 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;
|
||||
}
|
||||
|
||||
@@ -148,8 +144,6 @@ public class UpwardFallingBlockEntity extends Entity {
|
||||
BlockPos headPos = BlockPos.containing(getX(), getBoundingBox().maxY, getZ());
|
||||
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) {
|
||||
dropAndRemove(blockState);
|
||||
return;
|
||||
|
||||
-4
@@ -15,10 +15,6 @@ import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.EntityHitResult;
|
||||
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 {
|
||||
private boolean stuck = false;
|
||||
|
||||
|
||||
-15
@@ -302,8 +302,6 @@ public final class AntTeleportHelper {
|
||||
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);
|
||||
Vec3 expandedSafePos = findSafeArrivalPositionInYRange(
|
||||
player, destination, preferredPos, yRange[0], yRange[1],
|
||||
@@ -393,11 +391,6 @@ public final class AntTeleportHelper {
|
||||
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) {
|
||||
ChunkPos center = new ChunkPos(preferredPos);
|
||||
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) {
|
||||
if (candidate.getY() < minY || candidate.getY() > maxY) {
|
||||
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) {
|
||||
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 xOff = -radius; xOff <= radius; xOff++) {
|
||||
for (int zOff = -radius; zOff <= radius; zOff++) {
|
||||
|
||||
-5
@@ -78,11 +78,6 @@ public class RainbowAntEntity extends BaseAntEntity implements GeoEntity {
|
||||
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() {
|
||||
if (!this.infinityActivated) {
|
||||
return false;
|
||||
|
||||
-2
@@ -260,7 +260,6 @@ public class TermiteEntity extends BaseAntEntity implements GeoEntity {
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// North/South faces (dz = ±r)
|
||||
for (int dx = -r; dx <= r; dx++) {
|
||||
candidate.set(ox + dx, oy + dy, oz - r);
|
||||
if (this.isValidWoodTarget(candidate)) {
|
||||
@@ -273,7 +272,6 @@ public class TermiteEntity extends BaseAntEntity implements GeoEntity {
|
||||
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++) {
|
||||
candidate.set(ox - r, oy + dy, oz + dz);
|
||||
if (this.isValidWoodTarget(candidate)) {
|
||||
|
||||
-3
@@ -669,13 +669,11 @@ public class BasiliskEntity extends Monster implements GeoEntity {
|
||||
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 BasiliskMoveControl(Mob mob) {
|
||||
super(mob);
|
||||
}
|
||||
|
||||
/** Call this to prevent the move control from reapplying speed this tick. */
|
||||
public void halt() {
|
||||
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);
|
||||
}
|
||||
|
||||
// super handles path recalc and cooldown timer
|
||||
super.tick();
|
||||
|
||||
if (target != null && BasiliskEntity.this.isWithinMeleeAttackRange(target)) {
|
||||
|
||||
Loaded 100 of 222 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user