HTTPS
https://git.nageyqma.icu/nageyqma/blade-addons-next.git
SSH
git@git.nageyqma.icu:nageyqma/blade-addons-next.git
HTTPS 链接可直接 git clone;推送代码请使用 SSH。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
package blade.addon.features.dungeon;
import blade.addon.utils.Location;
import blade.addon.utils.Scheduler;
import blade.addon.utils.config.components.Categories;
import blade.addon.utils.config.components.CombineableNotification;
import blade.addon.utils.config.values.Dungeons;
import blade.addon.utils.data.PartyUtil;
import blade.addon.utils.dungeon.Phase;
import blade.addon.utils.events.Events;
import config.practical.hud.HUDCategory;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.network.chat.Component;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.scores.PlayerTeam;
import net.minecraft.world.scores.Scoreboard;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RunStartValidator extends CombineableNotification {
private static final Pattern STARTING_PATTERN = Pattern.compile("^Starting in \\d second(s)?");
private static final Pattern CLASS_PATTERN = Pattern.compile("\\[([ABHMT])]");
private static final Component DUPE_CLASS_TEXT = Component.literal("§cDuplicate Class Detected");
private static final Component PLAYER_COUNT_TEXT = Component.literal("§cNot enough players");
private static boolean hasDupeClasses = false;
private static boolean notEnoughPlayers = false;
private static boolean hasTicked = false;
public RunStartValidator() {
super("Run start validator");
}
public void init() {
Events.ON_GAME_MESSAGE.register(message -> {
if (!Location.inDungeon() || Phase.runStarted() || !Dungeons.detectDuplicateClass) return false;
Matcher matcher = STARTING_PATTERN.matcher(message.getString());
if (!matcher.find()) return false;
hasTicked = true;
if (validate()) {
Scheduler.scheduleSound(SoundEvents.NOTE_BLOCK_PLING.value(), 2, 1);
}
return false;
});
Events.ON_LOCATION_CHANGE.register(_ -> {
if (Location.inDungeon()) {
PartyUtil.sendPacket();
resetInfo();
}
return false;
});
Events.ON_PLAYER_ENTRY.register(_ -> {
//will only check after the first game message in case of false positives
if (!hasTicked) return false;
if (!Location.inDungeon() || Phase.runStarted() || (!Dungeons.detectDuplicateClass && !Dungeons.detectPlayerCount))
return false;
validate();
return false;
});
}
@Override
public boolean shouldRender() {
return Location.inDungeon() && !Phase.runStarted() && (hasDupeClasses || notEnoughPlayers);
}
@Override
public List<HUDCategory> categories() {
return List.of(Categories.CLEAR);
}
@Override
public boolean enabled() {
return (Dungeons.detectDuplicateClass || Dungeons.detectPlayerCount);
}
@Override
public Component getText() {
if (hasDupeClasses) return DUPE_CLASS_TEXT;
else if (notEnoughPlayers) return PLAYER_COUNT_TEXT;
else return Component.literal("§cSome warning text");
}
private boolean validate() {
ClientLevel world = Minecraft.getInstance().level;
LocalPlayer player = Minecraft.getInstance().player;
if (world == null || player == null) return false;
Scoreboard scoreboard = world.getScoreboard();
HashMap<String, Integer> map = readScoreBoard(scoreboard);
checkPlayerCount(map);
checkDuplicateClasses(map);
return hasDupeClasses || notEnoughPlayers;
}
private void checkDuplicateClasses(HashMap<String, Integer> map) {
for (Map.Entry<String, Integer> entry : map.entrySet()) {
String clazz = entry.getKey();
Integer count = entry.getValue();
if (clazz.equals("M") && Dungeons.ignoreDupeMage) continue;
if (count > 1) {
hasDupeClasses = true;
return;
}
}
hasDupeClasses = false;
}
private void checkPlayerCount(HashMap<String, Integer> map) {
if (!Dungeons.detectPlayerCount) {
notEnoughPlayers = false;
return;
}
int count = 0;
for (int num : map.values()) {
count += num;
}
notEnoughPlayers = count < PartyUtil.getPlayerCount();
}
private void resetInfo() {
hasDupeClasses = false;
notEnoughPlayers = false;
hasTicked = false;
}
private HashMap<String, Integer> readScoreBoard(Scoreboard scoreboard) {
HashMap<String, Integer> map = new HashMap<>();
for (PlayerTeam team : scoreboard.getPlayerTeams()) {
String teamStr = team.getPlayerPrefix().getString() + team.getPlayerSuffix().getString();
Matcher matcher = CLASS_PATTERN.matcher(teamStr);
if (!matcher.find()) continue;
String clazz = matcher.group(1);
Integer count = map.get(clazz);
if (count == null) count = 0;
map.put(clazz, count + 1);
}
return map;
}
}