130 lines
4.4 KiB
Java
130 lines
4.4 KiB
Java
package net.minecraft.world.entity.monster.warden;
|
|
|
|
import com.mojang.serialization.Codec;
|
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
|
import java.util.Comparator;
|
|
import java.util.List;
|
|
import java.util.Optional;
|
|
import java.util.OptionalInt;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.server.level.ServerPlayer;
|
|
import net.minecraft.util.ExtraCodecs;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.world.phys.AABB;
|
|
import net.minecraft.world.phys.Vec3;
|
|
|
|
public class WardenSpawnTracker {
|
|
public static final Codec<WardenSpawnTracker> CODEC = RecordCodecBuilder.create(
|
|
instance -> instance.group(
|
|
ExtraCodecs.NON_NEGATIVE_INT.fieldOf("ticks_since_last_warning").orElse(0).forGetter(wardenSpawnTracker -> wardenSpawnTracker.ticksSinceLastWarning),
|
|
ExtraCodecs.NON_NEGATIVE_INT.fieldOf("warning_level").orElse(0).forGetter(wardenSpawnTracker -> wardenSpawnTracker.warningLevel),
|
|
ExtraCodecs.NON_NEGATIVE_INT.fieldOf("cooldown_ticks").orElse(0).forGetter(wardenSpawnTracker -> wardenSpawnTracker.cooldownTicks)
|
|
)
|
|
.apply(instance, WardenSpawnTracker::new)
|
|
);
|
|
public static final int MAX_WARNING_LEVEL = 4;
|
|
private static final double PLAYER_SEARCH_RADIUS = 16.0;
|
|
private static final int WARNING_CHECK_DIAMETER = 48;
|
|
private static final int DECREASE_WARNING_LEVEL_EVERY_INTERVAL = 12000;
|
|
private static final int WARNING_LEVEL_INCREASE_COOLDOWN = 200;
|
|
private int ticksSinceLastWarning;
|
|
private int warningLevel;
|
|
private int cooldownTicks;
|
|
|
|
public WardenSpawnTracker(int ticksSinceLastWarning, int warningLevel, int cooldownTicks) {
|
|
this.ticksSinceLastWarning = ticksSinceLastWarning;
|
|
this.warningLevel = warningLevel;
|
|
this.cooldownTicks = cooldownTicks;
|
|
}
|
|
|
|
public WardenSpawnTracker() {
|
|
this(0, 0, 0);
|
|
}
|
|
|
|
public void tick() {
|
|
if (this.ticksSinceLastWarning >= 12000) {
|
|
this.decreaseWarningLevel();
|
|
this.ticksSinceLastWarning = 0;
|
|
} else {
|
|
this.ticksSinceLastWarning++;
|
|
}
|
|
|
|
if (this.cooldownTicks > 0) {
|
|
this.cooldownTicks--;
|
|
}
|
|
}
|
|
|
|
public void reset() {
|
|
this.ticksSinceLastWarning = 0;
|
|
this.warningLevel = 0;
|
|
this.cooldownTicks = 0;
|
|
}
|
|
|
|
public static OptionalInt tryWarn(ServerLevel level, BlockPos pos, ServerPlayer player) {
|
|
if (hasNearbyWarden(level, pos)) {
|
|
return OptionalInt.empty();
|
|
} else {
|
|
List<ServerPlayer> list = getNearbyPlayers(level, pos);
|
|
if (!list.contains(player)) {
|
|
list.add(player);
|
|
}
|
|
|
|
if (list.stream().anyMatch(serverPlayer -> (Boolean)serverPlayer.getWardenSpawnTracker().map(WardenSpawnTracker::onCooldown).orElse(false))) {
|
|
return OptionalInt.empty();
|
|
} else {
|
|
Optional<WardenSpawnTracker> optional = list.stream()
|
|
.flatMap(serverPlayer -> serverPlayer.getWardenSpawnTracker().stream())
|
|
.max(Comparator.comparingInt(WardenSpawnTracker::getWarningLevel));
|
|
if (optional.isPresent()) {
|
|
WardenSpawnTracker wardenSpawnTracker = (WardenSpawnTracker)optional.get();
|
|
wardenSpawnTracker.increaseWarningLevel();
|
|
list.forEach(serverPlayer -> serverPlayer.getWardenSpawnTracker().ifPresent(wardenSpawnTracker2 -> wardenSpawnTracker2.copyData(wardenSpawnTracker)));
|
|
return OptionalInt.of(wardenSpawnTracker.warningLevel);
|
|
} else {
|
|
return OptionalInt.empty();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private boolean onCooldown() {
|
|
return this.cooldownTicks > 0;
|
|
}
|
|
|
|
private static boolean hasNearbyWarden(ServerLevel level, BlockPos pos) {
|
|
AABB aABB = AABB.ofSize(Vec3.atCenterOf(pos), 48.0, 48.0, 48.0);
|
|
return !level.getEntitiesOfClass(Warden.class, aABB).isEmpty();
|
|
}
|
|
|
|
private static List<ServerPlayer> getNearbyPlayers(ServerLevel level, BlockPos pos) {
|
|
Vec3 vec3 = Vec3.atCenterOf(pos);
|
|
return level.getPlayers(serverPlayer -> !serverPlayer.isSpectator() && serverPlayer.position().closerThan(vec3, 16.0) && serverPlayer.isAlive());
|
|
}
|
|
|
|
private void increaseWarningLevel() {
|
|
if (!this.onCooldown()) {
|
|
this.ticksSinceLastWarning = 0;
|
|
this.cooldownTicks = 200;
|
|
this.setWarningLevel(this.getWarningLevel() + 1);
|
|
}
|
|
}
|
|
|
|
private void decreaseWarningLevel() {
|
|
this.setWarningLevel(this.getWarningLevel() - 1);
|
|
}
|
|
|
|
public void setWarningLevel(int warningLevel) {
|
|
this.warningLevel = Mth.clamp(warningLevel, 0, 4);
|
|
}
|
|
|
|
public int getWarningLevel() {
|
|
return this.warningLevel;
|
|
}
|
|
|
|
private void copyData(WardenSpawnTracker other) {
|
|
this.warningLevel = other.warningLevel;
|
|
this.cooldownTicks = other.cooldownTicks;
|
|
this.ticksSinceLastWarning = other.ticksSinceLastWarning;
|
|
}
|
|
}
|