HTTPS
https://git.nageyqma.icu/nageyqma/blade-addons-next.git
SSH
git@git.nageyqma.icu:nageyqma/blade-addons-next.git
HTTPS 链接可直接 git clone;推送代码请使用 SSH。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
package blade.addon.utils.dungeon;
import blade.addon.utils.Constants;
import blade.addon.utils.JsonUtility;
import blade.addon.utils.Location;
import blade.addon.utils.Misc;
import blade.addon.utils.Scheduler;
import blade.addon.utils.events.Events;
import blade.addon.utils.events.interfaces.PhaseEvent;
import blade.addon.utils.events.interfaces.RunEndEvent;
import config.practical.hud.HUDComponent;
import config.practical.hud.SimpleHUDComponent;
import config.practical.manager.ConfigValue;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.network.chat.Component;
public class Phase {
private static final Pattern END_PATTERN = Pattern.compile("^\\s*☠ Defeated (.+) in 0?([\\dhms ]+)\\s*(\\(NEW RECORD!\\))?$");
private static final Pattern SEARCH_PATTERN = Pattern.compile("The Catacombs .*$");
private static final Split DUMMY_SPLIT = new Split("test split", "if this is called idk", "if this is called idk", 43690);
private static final HashMap<String, ArrayList<Split>> FLOOR_SPLITS = JsonUtility.readSplits("/data/splits.json");
private static final int DUMMY_SIZE = 10;
public static final int SPLIT_LENGTH = 165;
private static ArrayList<Split> currentSplits;
private static int currentPhase = -1;
private static String floor = "";
private static boolean inMasterMode = false;
private static boolean inFloor7 = false;
private static boolean stormDead = false;
private static boolean runOver = false;
@ConfigValue
public static boolean enableSplits = false;
@ConfigValue
public static boolean includeTotalTime = false;
@ConfigValue
public static boolean sendSplitInChat = false;
@ConfigValue
public static boolean onlyShowActivatedSplits = false;
public static void init() {
Events.ON_SERVER_TICK.register(() -> {
if (currentSplits == null || runOver) return false;
for (Split split : currentSplits) {
split.tick();
}
return false;
});
Events.ON_LOCATION_CHANGE.register(_ -> {
reset();
return false;
});
Events.ON_GAME_MESSAGE.register(Phase::parseGameMessage);
Events.ON_TEAM.register(Phase::detectFloor);
}
private static boolean detectFloor(String line) {
if (!Location.inDungeon() || floor != null) return false;
Matcher matcher = SEARCH_PATTERN.matcher(line);
if (!matcher.find()) return false;
int start = line.indexOf("(");
int end = line.indexOf(")");
floor = line.substring(start + 1, end);
currentSplits = FLOOR_SPLITS.get(floor);
if (currentSplits != null) {
for (Split split : currentSplits) {
split.reset();
}
}
if (floor != null) {
if (floor.contains("7")) inFloor7 = true;
if (floor.contains("M")) inMasterMode = true;
}
return false;
}
private static void reset() {
currentSplits = null;
floor = null;
currentPhase = -1;
inFloor7 = false;
inMasterMode = false;
stormDead = false;
runOver = false;
}
public static boolean parseGameMessage(Component message) {
if (!Location.inDungeon()) return false;
String string = message.getString();
if (currentSplits == null) return false;
if (runOver) return false;
for (int i = 0; i < currentSplits.size(); i++) {
Split currentSplit = currentSplits.get(i);
if (currentSplit.ended()) continue;
currentSplit.parseMessage(string);
if (currentSplit.ended()) {
if (sendSplitInChat) {
Scheduler.scheduleTask(() -> Misc.addChatMessage(currentSplit.createNameText().append(currentSplit.createTimeText())), 2);
//Misc.addChatMessage(currentSplit.createNameText().append(currentSplit.createTimeText()));
}
currentPhase = i + 1;
Events.ON_PHASE_CHANGE.invoke(PhaseEvent::onPhaseChange);
}
//just for starting the run
if (currentSplit.started() && currentPhase == -1) {
currentPhase = i;
Events.ON_PHASE_CHANGE.invoke(PhaseEvent::onPhaseChange);
}
}
Matcher matcher = END_PATTERN.matcher(string);
if (matcher.find()) {
endRun();
}
if (inP2()) {
if (string.equals("[BOSS] Storm: I should have known that I stood no chance.")) {
stormDead = true;
}
}
return false;
}
private static void endRun() {
runOver = true;
currentPhase = currentSplits.size();
Scheduler.scheduleTask(Phase::printSplits, 2);
Events.ON_RUN_END.invoke(RunEndEvent::onRunEnd);
}
private static void printSplits() {
Misc.addChatMessage(Component.literal("§aSplits: "));
for (Split split : currentSplits) {
split.end();
Misc.addChatMessage(split.createNameText().append(split.createTimeText()));
}
if (!currentSplits.isEmpty()) {
double time = currentSplits.getLast().getTimeDiffrence();
Component timeLost = Component.literal("§aApproximately §e" + Constants.DECIMAL_FORMAT.format(time) + "s §alost to lag.");
Misc.addChatMessage(timeLost);
}
}
public static int getPhase() {
return currentPhase;
}
public static boolean isInFloor7() {
return inFloor7;
}
public static boolean isInMasterMode() {
return inMasterMode;
}
public static boolean runStarted() {
return currentPhase >= 0;
}
public static boolean runJustStarted() {
return currentPhase == 0;
}
public static boolean inBoss() {
return currentPhase > 3;
}
public static boolean inP1() {
return currentPhase == 4 && inFloor7;
}
public static boolean inP2() {
return currentPhase == 5 && inFloor7;
}
public static boolean stormDead() {
return stormDead;
}
public static boolean inTerminals() {
return currentPhase == 6 && inFloor7;
}
public static boolean inGoldorTunnel() {
return currentPhase == 7 && inFloor7;
}
public static boolean inP3() {
return (currentPhase == 6 || currentPhase == 7) && inFloor7;
}
public static boolean inP5() {
return currentPhase == 9 && inFloor7 && inMasterMode;
}
public static boolean runOver() {
return runOver;
}
public static double getPhaseTime(int index) {
if (index < 0 || index >= currentSplits.size()) return 0;
return currentSplits.get(index).getRealTime();
}
@ConfigValue
public static HUDComponent splitTimer = new SimpleHUDComponent(0, 0, SPLIT_LENGTH, 100, 1, "Splits",
() -> Location.inDungeon() && enableSplits && Phase.runStarted(),
((hudComponent, drawContext) -> {
int x = hudComponent.getScaledX();
int y = hudComponent.getScaledY();
Font textRenderer = Minecraft.getInstance().font;
if (currentSplits != null) {
int splitCount = currentSplits.size();
if (!includeTotalTime) splitCount--;
int height = 0;
for (int i = 0; i < splitCount; i++) {
Split split = currentSplits.get(i);
if (Phase.onlyShowActivatedSplits && !(split.started() || split.ended())) continue;
split.drawSplit(drawContext, textRenderer, x, y + Constants.TEXT_HEIGHT * height, SPLIT_LENGTH);
height++;
}
} else {
for (int i = 0; i < DUMMY_SIZE; i++) {
DUMMY_SPLIT.drawSplit(drawContext, textRenderer, x, y + Constants.TEXT_HEIGHT * i, SPLIT_LENGTH);
}
}
}), () -> enableSplits
);
}