fix some additional issues.

This commit is contained in:
2026-07-20 03:03:02 +02:00
parent d93ea10bf8
commit a0ca350526
7 changed files with 40 additions and 34 deletions
@@ -132,15 +132,14 @@ public final class AdaptiveSpecialAbilities {
if (event.phase != TickEvent.Phase.END || event.getServer() == null) { if (event.phase != TickEvent.Phase.END || event.getServer() == null) {
return; return;
} }
long now = event.getServer().overworld().getGameTime();
Iterator<TemporaryBlock> blockIterator = TEMPORARY_BLOCKS.iterator(); Iterator<TemporaryBlock> blockIterator = TEMPORARY_BLOCKS.iterator();
while (blockIterator.hasNext()) { while (blockIterator.hasNext()) {
TemporaryBlock block = blockIterator.next(); TemporaryBlock block = blockIterator.next();
if (now < block.expireTick) { ServerLevel level = block.server == event.getServer() ? event.getServer().getLevel(block.dimension) : null;
if (level == null || level.getGameTime() < block.expireTick) {
continue; continue;
} }
ServerLevel level = block.server == event.getServer() ? event.getServer().getLevel(block.dimension) : null; if (level.getBlockState(block.pos).is(Blocks.COBWEB)) {
if (level != null && level.getBlockState(block.pos).is(Blocks.COBWEB)) {
level.removeBlock(block.pos, false); level.removeBlock(block.pos, false);
} }
blockIterator.remove(); blockIterator.remove();
@@ -149,12 +148,12 @@ public final class AdaptiveSpecialAbilities {
Iterator<DelayedReappear> reappearIterator = DELAYED_REAPPEARS.iterator(); Iterator<DelayedReappear> reappearIterator = DELAYED_REAPPEARS.iterator();
while (reappearIterator.hasNext()) { while (reappearIterator.hasNext()) {
DelayedReappear pending = reappearIterator.next(); DelayedReappear pending = reappearIterator.next();
if (now < pending.tick) { ServerLevel level = pending.server == event.getServer() ? event.getServer().getLevel(pending.dimension) : null;
if (level == null || level.getGameTime() < pending.tick) {
continue; continue;
} }
ServerLevel level = pending.server == event.getServer() ? event.getServer().getLevel(pending.dimension) : null; Entity mobEntity = level.getEntity(pending.mobId);
Entity mobEntity = level == null ? null : level.getEntity(pending.mobId); Entity targetEntity = level.getEntity(pending.targetId);
Entity targetEntity = level == null ? null : level.getEntity(pending.targetId);
if (mobEntity instanceof Silverfish mob && targetEntity instanceof LivingEntity target if (mobEntity instanceof Silverfish mob && targetEntity instanceof LivingEntity target
&& mob.isAlive() && AdaptiveAIGoalUtils.isValidAdaptiveTarget(target) && mob.canAttack(target)) { && mob.isAlive() && AdaptiveAIGoalUtils.isValidAdaptiveTarget(target) && mob.canAttack(target)) {
Vec3 side = AdaptivePositioningUtils.sidePosition(mob, target, 1.6D, Vec3 side = AdaptivePositioningUtils.sidePosition(mob, target, 1.6D,
@@ -56,8 +56,9 @@ public final class AdaptiveMobsCommands {
} }
private static int setTier(CommandSourceStack source, int tier) { private static int setTier(CommandSourceStack source, int tier) {
AdaptiveSavedData.get(source.getLevel()).setManualGlobalTier(Math.min(tier, AMConfig.maxTier)); int appliedTier = Math.min(tier, AMConfig.maxTier);
source.sendSuccess(() -> Component.literal("Adaptive Mobs: manual global tier set to " + tier), true); AdaptiveSavedData.get(source.getLevel()).setManualGlobalTier(appliedTier);
source.sendSuccess(() -> Component.literal("Adaptive Mobs: manual global tier set to " + appliedTier), true);
return 1; return 1;
} }
@@ -268,12 +268,10 @@ public final class AMConfig {
} }
public static int tierValueInt(List<? extends Integer> list, int tier1based) { public static int tierValueInt(List<? extends Integer> list, int tier1based) {
if (list == null || list.isEmpty()) { if (list == null || tier1based <= 0 || tier1based > list.size()) {
return Integer.MAX_VALUE; return Integer.MAX_VALUE;
} }
int idx = Math.min(tier1based, list.size()) - 1; return list.get(tier1based - 1);
idx = Math.max(0, idx);
return list.get(idx);
} }
public static int aiScanCooldown(net.minecraft.util.RandomSource random) { public static int aiScanCooldown(net.minecraft.util.RandomSource random) {
@@ -86,7 +86,8 @@ public final class AdaptiveDifficultyManager {
private static int tierFromDay(long day) { private static int tierFromDay(long day) {
int tier = 0; int tier = 0;
for (int t = 1; t <= 5; t++) { int configuredTiers = Math.min(5, AMConfig.DAY_THRESHOLDS.get().size());
for (int t = 1; t <= configuredTiers; t++) {
if (day >= AMConfig.tierValueInt(AMConfig.DAY_THRESHOLDS.get(), t)) { if (day >= AMConfig.tierValueInt(AMConfig.DAY_THRESHOLDS.get(), t)) {
tier = t; tier = t;
} }
@@ -96,7 +97,8 @@ public final class AdaptiveDifficultyManager {
private static int tierFromKills(long kills) { private static int tierFromKills(long kills) {
int tier = 0; int tier = 0;
for (int t = 1; t <= 5; t++) { int configuredTiers = Math.min(5, AMConfig.KILL_THRESHOLDS.get().size());
for (int t = 1; t <= configuredTiers; t++) {
if (kills >= AMConfig.tierValueInt(AMConfig.KILL_THRESHOLDS.get(), t)) { if (kills >= AMConfig.tierValueInt(AMConfig.KILL_THRESHOLDS.get(), t)) {
tier = t; tier = t;
} }
@@ -31,13 +31,14 @@ import net.minecraftforge.event.level.LevelEvent;
import net.minecraftforge.event.level.BlockEvent.EntityPlaceEvent; import net.minecraftforge.event.level.BlockEvent.EntityPlaceEvent;
import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.server.ServerStoppingEvent; import net.minecraftforge.event.server.ServerStoppingEvent;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
public class AdaptiveMobsEvents { public class AdaptiveMobsEvents {
private static final String FRIENDLY_FIRE_SOURCE_KEY = "am_friendly_fire_source";
private static final String FRIENDLY_FIRE_COUNT_KEY = "am_friendly_fire_count"; private static final String FRIENDLY_FIRE_COUNT_KEY = "am_friendly_fire_count";
private static final String FRIENDLY_FIRE_EXPIRES_KEY = "am_friendly_fire_expires"; private static final String FRIENDLY_FIRE_EXPIRES_KEY = "am_friendly_fire_expires";
private static final String PENDING_SPAWN_PROCESSING_KEY = "am_pending_spawn_processing";
private static final int FRIENDLY_FIRE_WINDOW_TICKS = 100; private static final int FRIENDLY_FIRE_WINDOW_TICKS = 100;
@SubscribeEvent @SubscribeEvent
@@ -69,13 +70,10 @@ public class AdaptiveMobsEvents {
} }
long now = level.getGameTime(); long now = level.getGameTime();
String source = attacker.getUUID().toString(); boolean sameVolley = victim.getPersistentData().getLong(FRIENDLY_FIRE_EXPIRES_KEY) >= now;
boolean sameVolley = source.equals(victim.getPersistentData().getString(FRIENDLY_FIRE_SOURCE_KEY))
&& victim.getPersistentData().getLong(FRIENDLY_FIRE_EXPIRES_KEY) >= now;
int hits = sameVolley ? victim.getPersistentData().getInt(FRIENDLY_FIRE_COUNT_KEY) + 1 : 1; int hits = sameVolley ? victim.getPersistentData().getInt(FRIENDLY_FIRE_COUNT_KEY) + 1 : 1;
int toleratedHits = Math.min(4, tier - 1); int toleratedHits = Math.min(4, tier - 1);
if (hits <= toleratedHits) { if (hits <= toleratedHits) {
victim.getPersistentData().putString(FRIENDLY_FIRE_SOURCE_KEY, source);
victim.getPersistentData().putInt(FRIENDLY_FIRE_COUNT_KEY, hits); victim.getPersistentData().putInt(FRIENDLY_FIRE_COUNT_KEY, hits);
victim.getPersistentData().putLong(FRIENDLY_FIRE_EXPIRES_KEY, now + FRIENDLY_FIRE_WINDOW_TICKS); victim.getPersistentData().putLong(FRIENDLY_FIRE_EXPIRES_KEY, now + FRIENDLY_FIRE_WINDOW_TICKS);
event.setCanceled(true); event.setCanceled(true);
@@ -85,7 +83,7 @@ public class AdaptiveMobsEvents {
clearFriendlyFireTolerance(victim); clearFriendlyFireTolerance(victim);
} }
@SubscribeEvent @SubscribeEvent(priority = EventPriority.LOWEST, receiveCanceled = false)
public void onLivingHurt(LivingHurtEvent event) { public void onLivingHurt(LivingHurtEvent event) {
AdaptiveSpecialAbilities.onLivingHurt(event); AdaptiveSpecialAbilities.onLivingHurt(event);
if (!AMConfig.enabled || !AMConfig.ENABLE_THREAT_MEMORY_AI.get()) { if (!AMConfig.enabled || !AMConfig.ENABLE_THREAT_MEMORY_AI.get()) {
@@ -128,7 +126,7 @@ public class AdaptiveMobsEvents {
} }
} }
@SubscribeEvent @SubscribeEvent(priority = EventPriority.LOWEST, receiveCanceled = false)
public void onFinalizeSpawn(MobSpawnEvent.FinalizeSpawn event) { public void onFinalizeSpawn(MobSpawnEvent.FinalizeSpawn event) {
if (!AMConfig.enabled || !(event.getLevel() instanceof ServerLevel level)) { if (!AMConfig.enabled || !(event.getLevel() instanceof ServerLevel level)) {
return; return;
@@ -138,10 +136,8 @@ public class AdaptiveMobsEvents {
return; return;
} }
mob.getPersistentData().putBoolean(PENDING_SPAWN_PROCESSING_KEY, true);
int tier = AdaptiveDifficultyManager.getMobTier(level, mob.getType()); int tier = AdaptiveDifficultyManager.getMobTier(level, mob.getType());
MobStatScaler.applyScaling(mob, tier);
GearScaler.applyGear(mob, tier);
AdaptiveGoalInjector.inject(mob, level, tier);
SpawnPressureHelper.maybeSpawnExtra(level, mob, tier, event.getSpawnType()); SpawnPressureHelper.maybeSpawnExtra(level, mob, tier, event.getSpawnType());
} }
@@ -153,6 +149,14 @@ public class AdaptiveMobsEvents {
return; return;
} }
Entity entity = event.getEntity(); Entity entity = event.getEntity();
if (AMConfig.enabled && entity instanceof Mob mob && mob instanceof Enemy
&& AMConfig.isMobEnabled(mob.getType())
&& mob.getPersistentData().getBoolean(PENDING_SPAWN_PROCESSING_KEY)) {
mob.getPersistentData().remove(PENDING_SPAWN_PROCESSING_KEY);
int tier = AdaptiveDifficultyManager.getMobTier(level, mob.getType());
MobStatScaler.applyScaling(mob, tier);
GearScaler.applyGear(mob, tier);
}
// Install dormant, config-gated goals on every supported hostile so a later config reload // Install dormant, config-gated goals on every supported hostile so a later config reload
// can enable them without requiring the entity to unload and join again. // can enable them without requiring the entity to unload and join again.
if (entity instanceof Mob mob && mob instanceof Enemy) { if (entity instanceof Mob mob && mob instanceof Enemy) {
@@ -192,7 +196,6 @@ public class AdaptiveMobsEvents {
} }
private static void clearFriendlyFireTolerance(Mob mob) { private static void clearFriendlyFireTolerance(Mob mob) {
mob.getPersistentData().remove(FRIENDLY_FIRE_SOURCE_KEY);
mob.getPersistentData().remove(FRIENDLY_FIRE_COUNT_KEY); mob.getPersistentData().remove(FRIENDLY_FIRE_COUNT_KEY);
mob.getPersistentData().remove(FRIENDLY_FIRE_EXPIRES_KEY); mob.getPersistentData().remove(FRIENDLY_FIRE_EXPIRES_KEY);
} }
@@ -21,6 +21,8 @@ import net.minecraft.world.item.enchantment.Enchantments;
*/ */
public final class GearScaler { public final class GearScaler {
private static final String GEAR_APPLIED_KEY = "am_gear_applied";
// Material ranks (low -> high) used both to pick new gear and to compare against existing gear. // Material ranks (low -> high) used both to pick new gear and to compare against existing gear.
private static final Item[] HELMETS = {Items.LEATHER_HELMET, Items.GOLDEN_HELMET, Items.CHAINMAIL_HELMET, Items.IRON_HELMET, Items.DIAMOND_HELMET}; private static final Item[] HELMETS = {Items.LEATHER_HELMET, Items.GOLDEN_HELMET, Items.CHAINMAIL_HELMET, Items.IRON_HELMET, Items.DIAMOND_HELMET};
private static final Item[] CHESTS = {Items.LEATHER_CHESTPLATE, Items.GOLDEN_CHESTPLATE, Items.CHAINMAIL_CHESTPLATE, Items.IRON_CHESTPLATE, Items.DIAMOND_CHESTPLATE}; private static final Item[] CHESTS = {Items.LEATHER_CHESTPLATE, Items.GOLDEN_CHESTPLATE, Items.CHAINMAIL_CHESTPLATE, Items.IRON_CHESTPLATE, Items.DIAMOND_CHESTPLATE};
@@ -32,6 +34,10 @@ public final class GearScaler {
} }
public static void applyGear(Mob mob, int tier) { public static void applyGear(Mob mob, int tier) {
if (mob.getPersistentData().getBoolean(GEAR_APPLIED_KEY)) {
return;
}
mob.getPersistentData().putBoolean(GEAR_APPLIED_KEY, true);
if (!AMConfig.GEAR_SCALING_ENABLED.get() || tier <= 0) { if (!AMConfig.GEAR_SCALING_ENABLED.get() || tier <= 0) {
return; return;
} }
@@ -2,8 +2,6 @@ package net.fretux.adaptivemobs.spawn;
import net.fretux.adaptivemobs.AdaptiveMobs; import net.fretux.adaptivemobs.AdaptiveMobs;
import net.fretux.adaptivemobs.config.AMConfig; import net.fretux.adaptivemobs.config.AMConfig;
import net.fretux.adaptivemobs.gear.GearScaler;
import net.fretux.adaptivemobs.scaling.MobStatScaler;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource; import net.minecraft.util.RandomSource;
@@ -13,6 +11,7 @@ import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.MobSpawnType; import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.entity.monster.Monster; import net.minecraft.world.entity.monster.Monster;
import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.AABB;
import net.minecraftforge.event.ForgeEventFactory;
/** /**
* Adds modest spawn pressure: on a natural hostile spawn there is a tier-scaled chance to spawn * Adds modest spawn pressure: on a natural hostile spawn there is a tier-scaled chance to spawn
@@ -75,12 +74,10 @@ public final class SpawnPressureHelper {
random.nextFloat() * 360.0F, 0.0F); random.nextFloat() * 360.0F, 0.0F);
// Honour collision, light/biome spawn rules and obstruction checks. // Honour collision, light/biome spawn rules and obstruction checks.
if (level.noCollision(extra) if (level.noCollision(extra)
&& extra.checkSpawnRules(level, MobSpawnType.NATURAL) && extra.checkSpawnRules(level, spawnType)
&& extra.checkSpawnObstruction(level)) { && extra.checkSpawnObstruction(level)) {
extra.finalizeSpawn(level, level.getCurrentDifficultyAt(extra.blockPosition()), ForgeEventFactory.onFinalizeSpawn(extra, level,
MobSpawnType.NATURAL, null, null); level.getCurrentDifficultyAt(extra.blockPosition()), spawnType, null, null);
MobStatScaler.applyScaling(extra, tier);
GearScaler.applyGear(extra, tier);
level.addFreshEntity(extra); level.addFreshEntity(extra);
if (AMConfig.debug) { if (AMConfig.debug) {
AdaptiveMobs.LOGGER.info("[AdaptiveMobs] Extra spawn ({}) at tier {} near {}", AdaptiveMobs.LOGGER.info("[AdaptiveMobs] Extra spawn ({}) at tier {} near {}",