diff --git a/README.md b/README.md index f7ca3bd2..a45d3ef5 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,14 @@ # ucutils -UCUtils is a utility mod for the UnicaCity roleplay server, inspired by the former UnicacityAddon. It provides useful commands, QoL features, and custom tools tailored for UnicaCity, enhancing gameplay and making everyday interactions smoother and more enjoyable. +UCUtils is a utility mod for the UnicaCity roleplay server, inspired by the former UnicacityAddon. It provides useful commands, QoL +features, and custom tools tailored for UnicaCity, enhancing gameplay and making everyday interactions smoother and more enjoyable. ## Features & Funktionen ### Allgemein -- Sollte ein Command mit einem Großbuchstaben eingegeben werden (z. B. `/Afk` statt `/afk`) wird dieser Command automatisch zu einem gültigen Command umgewandelt + +- Sollte ein Command mit einem Großbuchstaben eingegeben werden (z. B. `/Afk` statt `/afk`) wird dieser Command automatisch zu einem + gültigen Command umgewandelt - Die Tabliste wird nach Teammitgliedern und Fraktionen (FBI, Polizei, Rettungsdienst, News) sortiert - Als Business-Besitzer wird in der Business-Info ein Button angezeigt, um die Einnahmen direkt abzubuchen - Wirft man eine Glasflasche in der Nähe eines Shops weg, wird diese als Pfand abgegeben @@ -13,20 +16,22 @@ UCUtils is a utility mod for the UnicaCity roleplay server, inspired by the form - Es werden Sounds abgespielt für Notrufe, Bomben und weitere Situationen ### Auto + - Das Auf-/Abschließen eines Fahrzeuges wurde teilweise automatisiert (automatisches Klicken des Items im Inventar) - Beim Rechtsklick auf das eigene Fahrzeug wird automatisch `/car lock` ausgeführt - Steigt man in ein Fahrzeug ein, wird dieses automatisch gestartet und abgeschlossen ### Fraktionen + - Hinter dem Spielernamen befindet sich ein Symbol, um die dazugehörige Fraktion zu erkennen (auch für bewusstlose Personen) -- Sollte ein Spieler Contract, auf der Blacklist stehen, Hausverbot oder Wanted-Punkte haben, wird der Name dementsprechend eingefärbt und in der Spielerliste angezeigt -- Es werden für alle Fraktionen verschiedene Aktivitäten wie Reinforcements, Verhaftungen, Wiederbelebungen und weiteres gezählt +- Sollte ein Spieler Contract, auf der Blacklist stehen, Hausverbot oder Wanted-Punkte haben, wird der Name dementsprechend eingefärbt + und in der Spielerliste angezeigt - Das Design der Reinforcements ist so überarbeitet, dass diese besser auffallen - Für das FBI, die Polizei und den Rettungsdienst gibt es einen Timer, der die Dauer der Bombe anzeigt -- Für die Polizei wurde ein Minuspunkte-System hinzugefügt - Mit einem Rechtsklick auf ein Fraktionstor (nicht Fraktionstür) wird dieses automatisch geöffnet oder geschlossen ### Jobs + - Bei Transport-Jobs werden nach der Eingabe des `/droptransport` alle weiteren Kisten automatisch abgegeben - Beim Hochseefischer-Job wird das Netz automatisch ausgeworfen und der gefangene Fisch am Ende automatisch abgegeben - Für den Transport des Tabaks zur Shisha-Bar wird der Tabak am Ende automatisch abgegeben @@ -34,8 +39,10 @@ UCUtils is a utility mod for the UnicaCity roleplay server, inspired by the form - Für den Pizzalieferanten-Job wird `/getpizza` automatisch ausgeführt, bis 10 Pizzen gesammelt wurden - Es werden Countdowns angezeigt, bis ein Job wieder ausgeführt werden kann - Bei der Abgabe von Uran am Atomkraftwerk muss man nicht mehr aus dem Auto aussteigen +- Aktive Mining XP-Booster werden angezeigt ### Widgets + - Aktuelles Datum und Uhrzeit - Informationen über den PayDay (Dauer bis zum nächsten PayDay, Gehalt und Erfahrung) - Status des Autos (offen/abgeschlossen) @@ -45,14 +52,13 @@ UCUtils is a utility mod for the UnicaCity roleplay server, inspired by the form **Allgemein** -| Befehl | Beschreibung | -|----------------------------------|----------------------------------------------------------------------------------------| -| `/ucutils` | Zeigt nützliche Status-Informationen über das Projekt an | -| `/sync` | Startet die Synchronisierung um Daten wie Fraktionsmitglieder mit der Mod abzugleichen | -| `/todo` | Zeigt eine Todoliste an (`/todo add `) | -| `/mi` | Alias für `/memberinfo` | -| `/mia` | Alias für `/memberinfoall` | -| `/todo` (`/todo add `) | Zeigt eine Todoliste an | +| Befehl | Beschreibung | +|----------------------------------|---------------------------------------------------------------------------------------------| +| `/ucutils` (`/ucutils sync`) | Zeigt nützliche Status-Informationen über das Projekt an oder startet eine Synchronisierung | +| `/todo` | Zeigt eine Todoliste an (`/todo add `) | +| `/mi` | Alias für `/memberinfo` | +| `/mia` | Alias für `/memberinfoall` | +| `/todo` (`/todo add `) | Zeigt eine Todoliste an | **Chat** @@ -64,11 +70,11 @@ UCUtils is a utility mod for the UnicaCity roleplay server, inspired by the form **Fraktionen** -| Befehl | Beschreibung | -|----------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------| -| `/asetbl` | Setzt Blacklist-Gründe automatisch (Blacklist-Gründe können mit einem Ticket auf dem Discord beantragt werden) | -| `/eigenbedarf` | Nimmt eine eingestellte Menge an Drogen aus der Drogenbank einer Fraktion oder gibt diese an einen Spieler | -| `schwarzmarkt` | Zeigt alle Schwarzmärkte an einschließlich des Zeitpunkts des letzten Besuchs des Ortes und einer Markierung ob sich der Schwarzmarkt dort befand | +| Befehl | Beschreibung | +|-----------------|---------------------------------------------------------------------------------------------------------------------------------------------------| +| `/asetbl` | Setzt Blacklist-Gründe automatisch (Blacklist-Gründe können mit einem Ticket auf dem Discord beantragt werden) | +| `/eigenbedarf` | Nimmt eine eingestellte Menge an Drogen aus der Drogenbank einer Fraktion oder gibt diese an einen Spieler | +| `/schwarzmarkt` | Zeigt alle Schwarzmärkte an einschließlich des Zeitpunkts des letzten Besuchs des Ortes und einer Markierung ob sich der Schwarzmarkt dort befand | **Geld** @@ -80,7 +86,7 @@ UCUtils is a utility mod for the UnicaCity roleplay server, inspired by the form **Handy** -| Befehl | Beschreibung | -|-----------------------------------|------------------------------------------------------------------------------------| -| `/acall ` | Ermöglicht das Anrufen mittels Spielername statt der Nummer | -| `/asms ` | Ermöglicht das Schreiben einer SMS mittels Spielername statt der Nummer | +| Befehl | Beschreibung | +|-----------------------------------|-------------------------------------------------------------------------| +| `/acall ` | Ermöglicht das Anrufen mittels Spielername statt der Nummer | +| `/asms ` | Ermöglicht das Schreiben einer SMS mittels Spielername statt der Nummer | diff --git a/gradle.properties b/gradle.properties index cd1e5d90..7409cb56 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,10 +10,10 @@ org.gradle.configuration-cache=false minecraft_version=1.21.10 yarn_mappings=1.21.10+build.2 loader_version=0.17.3 -loom_version=1.14.1 +loom_version=1.14.4 # Mod Properties -mod_version=2.0.1 +mod_version=2.1.0 maven_group=de.rettichlp archives_base_name=ucutils diff --git a/src/main/java/de/rettichlp/ucutils/UCUtils.java b/src/main/java/de/rettichlp/ucutils/UCUtils.java index 4cc385b4..4002c5a1 100644 --- a/src/main/java/de/rettichlp/ucutils/UCUtils.java +++ b/src/main/java/de/rettichlp/ucutils/UCUtils.java @@ -54,6 +54,8 @@ public class UCUtils implements ModInitializer { public void onInitialize() { // This entrypoint is suitable for setting up client-specific logic, such as rendering. + syncService.syncFactionMembers(); + this.registry.registerSounds(); ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> { @@ -64,6 +66,7 @@ public void onInitialize() { client.execute(() -> { this.registry.registerListeners(); renderService.initializeWidgets(); + syncService.syncFactionSpecificData(); syncService.checkForUpdates(); }); }); diff --git a/src/main/java/de/rettichlp/ucutils/command/ModCommand.java b/src/main/java/de/rettichlp/ucutils/command/ModCommand.java index 531f12aa..9a0b129d 100644 --- a/src/main/java/de/rettichlp/ucutils/command/ModCommand.java +++ b/src/main/java/de/rettichlp/ucutils/command/ModCommand.java @@ -1,35 +1,25 @@ package de.rettichlp.ucutils.command; -import com.mojang.authlib.GameProfile; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import de.rettichlp.ucutils.common.registry.CommandBase; import de.rettichlp.ucutils.common.registry.UCUtilsCommand; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.metadata.Person; -import net.minecraft.client.network.PlayerListEntry; import net.minecraft.text.ClickEvent; import org.jetbrains.annotations.NotNull; -import java.time.LocalDateTime; import java.util.Collection; -import java.util.List; import java.util.StringJoiner; -import static com.mojang.brigadier.arguments.StringArgumentType.word; import static de.rettichlp.ucutils.UCUtils.MOD_ID; -import static de.rettichlp.ucutils.UCUtils.commandService; import static de.rettichlp.ucutils.UCUtils.messageService; -import static de.rettichlp.ucutils.UCUtils.networkHandler; import static de.rettichlp.ucutils.UCUtils.player; import static de.rettichlp.ucutils.UCUtils.storage; import static de.rettichlp.ucutils.UCUtils.syncService; import static de.rettichlp.ucutils.UCUtils.utilService; import static java.net.URI.create; -import static java.time.LocalDateTime.MIN; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; -import static net.minecraft.command.CommandSource.suggestMatching; import static net.minecraft.text.Text.empty; import static net.minecraft.text.Text.of; import static net.minecraft.util.Formatting.DARK_GRAY; @@ -42,56 +32,18 @@ public class ModCommand extends CommandBase { @Override public LiteralArgumentBuilder execute(@NotNull LiteralArgumentBuilder node) { return node - .then(literal("userinfo") - .requires(fabricClientCommandSource -> commandService.isSuperUser()) - .then(argument("player", word()) - .suggests((context, builder) -> { - List list = networkHandler.getPlayerList().stream() - .map(PlayerListEntry::getProfile) - .map(GameProfile::name) - .toList(); - return suggestMatching(list, builder); - }) - .executes(context -> { - String playerName = context.getArgument("player", String.class); -// api.getUserInfo(playerName, response -> { -// -// player.sendMessage(empty(), false); -// -// messageService.sendModMessage("UCUtils User Information - " + playerName, false); -// -// messageService.sendModMessage(empty() -// .append(of("Version").copy().formatted(GRAY)) -// .append(of(":").copy().formatted(DARK_GRAY)).append(" ") -// .append(of(response.version()).copy().formatted(WHITE)), false); -// -// messageService.sendModMessage(empty() -// .append(of("Aktivitäten").copy().formatted(GRAY)) -// .append(of(":").copy().formatted(DARK_GRAY)).append(" ") -// .append(of("Klick ↗").copy().styled(style -> style -// .withColor(WHITE) -// .withClickEvent(new ClickEvent.SuggestCommand("/activity player " + playerName)))), false); -// -// player.sendMessage(empty(), false); -// }); - - return 1; - }))) .then(literal("sync") - .then(literal("faction") - .executes(context -> { - syncService.syncFactionMembersWithCommand(() -> {}); - return 1; - })) .executes(context -> { + syncService.syncFactionMembers(); syncService.checkForUpdates(); - syncService.syncFactionSpecificData(); + + utilService.delayedAction(syncService::syncFactionSpecificData, 2000); + return 1; })) .executes(context -> { String version = utilService.getVersion(); String authors = getAuthors(); - LocalDateTime lastSyncTimestamp = syncService.getLastSyncTimestamp(); player.sendMessage(empty(), false); @@ -116,13 +68,6 @@ public LiteralArgumentBuilder execute(@NotNull Litera .withColor(WHITE) .withClickEvent(new ClickEvent.OpenUrl(create("https://github.com/UnicacityAddon/ucutils"))))), false); - messageService.sendModMessage(empty() - .append(of("Letzte Synchronisierung").copy().formatted(GRAY)) - .append(of(":").copy().formatted(DARK_GRAY)).append(" ") - .append(of(lastSyncTimestamp.equals(MIN) - ? "Nie" - : messageService.dateTimeToFriendlyString(lastSyncTimestamp)).copy().formatted(WHITE)), false); - player.sendMessage(empty(), false); storage.print(); diff --git a/src/main/java/de/rettichlp/ucutils/common/Storage.java b/src/main/java/de/rettichlp/ucutils/common/Storage.java index fad25442..d3a2e953 100644 --- a/src/main/java/de/rettichlp/ucutils/common/Storage.java +++ b/src/main/java/de/rettichlp/ucutils/common/Storage.java @@ -169,7 +169,7 @@ public Faction getCachedFaction(String playerName) { public Faction getFaction(String playerName) { Faction faction = this.factionEntries.stream() .filter(factionEntry -> factionEntry.members().stream() - .anyMatch(factionMember -> factionMember.playerName().equalsIgnoreCase(playerName))) + .anyMatch(factionMember -> factionMember.username().equalsIgnoreCase(playerName))) .findFirst() .map(FactionEntry::faction) .orElse(NULL); diff --git a/src/main/java/de/rettichlp/ucutils/common/api/Api.java b/src/main/java/de/rettichlp/ucutils/common/api/Api.java index b6074cff..3e56f984 100644 --- a/src/main/java/de/rettichlp/ucutils/common/api/Api.java +++ b/src/main/java/de/rettichlp/ucutils/common/api/Api.java @@ -8,6 +8,8 @@ import com.google.gson.reflect.TypeToken; import com.mojang.authlib.GameProfile; import de.rettichlp.ucutils.common.api.response.ErrorResponse; +import de.rettichlp.ucutils.common.models.Faction; +import de.rettichlp.ucutils.common.models.FactionMember; import lombok.Getter; import net.minecraft.client.MinecraftClient; import org.jetbrains.annotations.Contract; @@ -69,6 +71,10 @@ public void getModrinthVersions(Consumer>> callback) { get("https://api.modrinth.com/v2/project/ucutils/version", new TypeToken<>() {}, callback); } + public void getFactionMembers(@NotNull Faction faction, Consumer> callback) { + get("https://api.unicacity.eu/api/factions/" + faction.getApiKey() + "/members", new TypeToken<>() {}, callback); + } + private void get(@NotNull String uri, TypeToken typeToken, Consumer callback) { HttpRequest httpRequest = this.requestBuilder.copy() .uri(uri.startsWith("https://") ? create(uri) : create(this.baseUrl + uri)) diff --git a/src/main/java/de/rettichlp/ucutils/common/models/Countdown.java b/src/main/java/de/rettichlp/ucutils/common/models/Countdown.java index ae64195c..c20c0ab5 100644 --- a/src/main/java/de/rettichlp/ucutils/common/models/Countdown.java +++ b/src/main/java/de/rettichlp/ucutils/common/models/Countdown.java @@ -1,6 +1,7 @@ package de.rettichlp.ucutils.common.models; import de.rettichlp.ucutils.common.gui.widgets.CountdownWidget; +import lombok.Getter; import lombok.RequiredArgsConstructor; import net.minecraft.text.Text; @@ -16,6 +17,7 @@ import static net.minecraft.util.Formatting.GRAY; import static net.minecraft.util.Formatting.WHITE; +@Getter @RequiredArgsConstructor public class Countdown { diff --git a/src/main/java/de/rettichlp/ucutils/common/models/Faction.java b/src/main/java/de/rettichlp/ucutils/common/models/Faction.java index 689d5b45..803f34ad 100644 --- a/src/main/java/de/rettichlp/ucutils/common/models/Faction.java +++ b/src/main/java/de/rettichlp/ucutils/common/models/Faction.java @@ -33,25 +33,26 @@ @AllArgsConstructor public enum Faction { - NULL("", false, GRAY, ""), - POLIZEI("Polizei", false, BLUE, "✯"), - FBI("FBI", false, DARK_BLUE, "✯"), - RETTUNGSDIENST("Rettungsdienst", false, DARK_RED, "✚"), + NULL("", "", false, GRAY, ""), + POLIZEI("Polizei", "police", false, BLUE, "✯"), + FBI("FBI", "fbi", false, DARK_BLUE, "✯"), + RETTUNGSDIENST("Rettungsdienst", "medic", false, DARK_RED, "✚"), - LA_COSA_NOSTRA("La Cosa Nostra", true, DARK_AQUA, "⚜"), - WESTSIDE_BALLAS("Westside Ballas", true, DARK_PURPLE, "☠"), - CALDERON_KARTELL("Calderón Kartell", true, GOLD, "☀"), - KERZAKOV_FAMILIE("Kerzakov Familie", true, RED, "✮"), - HAYAT_KARTELL("Hayat Kartell", true, DARK_GREEN, "Ħ"), - YAKUZA("Yakuza", true, GREEN, "☯"), - VELENTZAS("Velentzas", true, WHITE, "δ"), + LA_COSA_NOSTRA("La Cosa Nostra", "mafia", true, DARK_AQUA, "⚜"), + WESTSIDE_BALLAS("Westside Ballas", "gang", true, DARK_PURPLE, "☠"), + CALDERON_KARTELL("Calderón Kartell", "mexican", true, GOLD, "☀"), + KERZAKOV_FAMILIE("Kerzakov Familie", "kerzakov", true, RED, "✮"), + HAYAT_KARTELL("Hayat Kartell", "hayat_kartell", true, DARK_GREEN, "Ħ"), + YAKUZA("Yakuza", "yakuza", true, GREEN, "☯"), + VELENTZAS("Velentzas", "velentzas", true, WHITE, "δ"), - HITMAN("Hitman", false, AQUA, "➹"), - TERRORISTEN("Terroristen", false, GRAY, "❇"), - KIRCHE("Kirche", false, LIGHT_PURPLE, "†"), - NEWS("News", false, YELLOW, "✉"); + HITMAN("Hitman", "hitman", false, AQUA, "➹"), + TERRORISTEN("Terroristen", "terror", false, GRAY, "❇"), + KIRCHE("Kirche", "church", false, LIGHT_PURPLE, "†"), + NEWS("News", "news", false, YELLOW, "✉"); private final String displayName; + private final String apiKey; private final boolean isBadFaction; private final Formatting color; private final String icon; diff --git a/src/main/java/de/rettichlp/ucutils/common/models/FactionMember.java b/src/main/java/de/rettichlp/ucutils/common/models/FactionMember.java index f2375776..9683adea 100644 --- a/src/main/java/de/rettichlp/ucutils/common/models/FactionMember.java +++ b/src/main/java/de/rettichlp/ucutils/common/models/FactionMember.java @@ -1,5 +1,7 @@ package de.rettichlp.ucutils.common.models; -public record FactionMember(String playerName, int rank) { +import java.util.UUID; + +public record FactionMember(int id, String username, UUID uuid, int rankNumber, String rankName, boolean isLeader, String gender) { } diff --git a/src/main/java/de/rettichlp/ucutils/common/services/SyncService.java b/src/main/java/de/rettichlp/ucutils/common/services/SyncService.java index bcdf3f0e..a095b80e 100644 --- a/src/main/java/de/rettichlp/ucutils/common/services/SyncService.java +++ b/src/main/java/de/rettichlp/ucutils/common/services/SyncService.java @@ -1,12 +1,12 @@ package de.rettichlp.ucutils.common.services; import de.rettichlp.ucutils.common.models.Faction; +import de.rettichlp.ucutils.common.models.FactionEntry; import lombok.Getter; -import java.time.LocalDateTime; -import java.util.List; import java.util.Map; +import static de.rettichlp.ucutils.UCUtils.LOGGER; import static de.rettichlp.ucutils.UCUtils.api; import static de.rettichlp.ucutils.UCUtils.commandService; import static de.rettichlp.ucutils.UCUtils.notificationService; @@ -16,9 +16,6 @@ import static de.rettichlp.ucutils.common.models.Faction.NULL; import static de.rettichlp.ucutils.common.services.CommandService.COMMAND_COOLDOWN_MILLIS; import static java.awt.Color.MAGENTA; -import static java.time.LocalDateTime.MIN; -import static java.time.LocalDateTime.now; -import static java.util.Arrays.stream; import static java.util.Objects.nonNull; import static java.util.Objects.requireNonNull; import static java.util.concurrent.TimeUnit.MINUTES; @@ -31,31 +28,29 @@ public class SyncService { - @Getter - private LocalDateTime lastSyncTimestamp = MIN; @Getter private boolean gameSyncProcessActive = false; - public void syncFactionMembersWithCommand(Runnable runAfter) { - this.gameSyncProcessActive = true; + public void syncFactionMembers() { + for (Faction faction : Faction.values()) { + if (faction == NULL) { + continue; + } - List factionMemberInfoCommands = stream(Faction.values()) - .filter(faction -> faction != NULL) - .map(faction -> "memberinfoall " + faction.getDisplayName()) - .toList(); + storage.getFactionEntries().clear(); - commandService.sendCommands(factionMemberInfoCommands, 1000); + api.getFactionMembers(faction, factionMembers -> { + // to faction entry + FactionEntry factionEntry = new FactionEntry(faction, factionMembers); - utilService.delayedAction(() -> { - this.gameSyncProcessActive = false; - notificationService.sendSuccessNotification("Fraktionsmitglieder synchronisiert"); - runAfter.run(); - }, Faction.values().length * 1000L + 1000); + storage.getFactionEntries().add(factionEntry); + LOGGER.info("Faction members for faction {} synced ({} members)", faction, factionMembers.size()); + }); + } } public void syncFactionSpecificData() { this.gameSyncProcessActive = true; - this.lastSyncTimestamp = now(); // parse from faction-related init commands after all faction members are synced utilService.delayedAction(() -> { diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyService.java b/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyService.java index 8812d771..71970ab4 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyService.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/EconomyService.java @@ -47,6 +47,7 @@ public class EconomyService implements IMessageReceiveListener { // payday private static final Pattern PAYDAY_TIME_PATTERN = compile("^- Zeit seit PayDay: (?\\d+)/60 Minuten$"); private static final Pattern PAYDAY_SALARY_PATTERN = compile("^\\[PayDay] Du bekommst dein Gehalt von (?\\d+)\\$ am PayDay ausgezahlt\\.$"); + private static final Pattern PAYDAY_MINE_SALARY_PATTERN = compile("^\\[PayDay] Du bekommst deine Mine Einnahmen von (?\\d+)\\$ am PayDay ausgezahlt\\.$"); // other private static final Pattern ATM_MONEY_AMOUNT_PATTERN = compile("ATM \\d+: (?\\d+)\\$/100000\\$"); @@ -193,6 +194,13 @@ public boolean onMessageReceive(Text text, String message) { return true; } + Matcher paydayMineSalaryMatcher = PAYDAY_MINE_SALARY_PATTERN.matcher(message); + if (paydayMineSalaryMatcher.find()) { + int money = parseInt(paydayMineSalaryMatcher.group("money")); + configuration.addPredictedPayDaySalary(money); + return true; + } + Matcher moneyAtmAmountMatcher = ATM_MONEY_AMOUNT_PATTERN.matcher(message); if (moneyAtmAmountMatcher.find()) { int moneyAtmAmount = parseInt(moneyAtmAmountMatcher.group("moneyAtmAmount")); diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/SyncListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/SyncListener.java deleted file mode 100644 index bb1b2086..00000000 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/SyncListener.java +++ /dev/null @@ -1,52 +0,0 @@ -package de.rettichlp.ucutils.listener.impl; - -import de.rettichlp.ucutils.common.registry.UCUtilsListener; -import de.rettichlp.ucutils.listener.ICommandSendListener; -import de.rettichlp.ucutils.listener.IMessageReceiveListener; -import net.minecraft.text.Text; -import org.jetbrains.annotations.NotNull; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static de.rettichlp.ucutils.UCUtils.notificationService; -import static de.rettichlp.ucutils.UCUtils.syncService; -import static java.util.regex.Pattern.compile; - -@UCUtilsListener -public class SyncListener implements ICommandSendListener, IMessageReceiveListener { - - private static final Pattern SERVER_PASSWORD_MISSING_PATTERN = compile("^» Schütze deinen Account mit /passwort new \\[Passwort].$"); - private static final Pattern SERVER_PASSWORD_ACCEPTED_PATTERN = compile("^Du hast deinen Account freigeschaltet\\.$"); - - @Override - public boolean onCommandSend(@NotNull String command) { - if (syncService.isGameSyncProcessActive() && !command.contains("memberinfoall") && !command.contains("wanteds") && !command.contains("contractlist") && !command.contains("hausverbot") && !command.contains("blacklist")) { - notificationService.sendWarningNotification("Synchronisierung aktiv - Befehle blockiert"); - return false; - } - - return true; - } - - @Override - public boolean onMessageReceive(Text text, String message) { - // SERVER INIT - - // if a password is not set, start the game sync process - Matcher serverPasswordMissingMatcher = SERVER_PASSWORD_MISSING_PATTERN.matcher(message); - if (serverPasswordMissingMatcher.find()) { - syncService.syncFactionMembersWithCommand(syncService::syncFactionSpecificData); - return true; - } - - // if a password is accepted, start the game sync process - Matcher serverPasswordAcceptedMatcher = SERVER_PASSWORD_ACCEPTED_PATTERN.matcher(message); - if (serverPasswordAcceptedMatcher.find()) { - syncService.syncFactionMembersWithCommand(syncService::syncFactionSpecificData); - return true; - } - - return true; - } -} diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/FactionListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/FactionListener.java index baaf5739..b01e1f9d 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/faction/FactionListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/faction/FactionListener.java @@ -3,8 +3,6 @@ import de.rettichlp.ucutils.common.Storage; import de.rettichlp.ucutils.common.models.BlackMarket; import de.rettichlp.ucutils.common.models.Faction; -import de.rettichlp.ucutils.common.models.FactionEntry; -import de.rettichlp.ucutils.common.models.FactionMember; import de.rettichlp.ucutils.common.models.Reinforcement; import de.rettichlp.ucutils.common.registry.UCUtilsListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; @@ -18,7 +16,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; -import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.function.Predicate; @@ -30,13 +27,10 @@ import static de.rettichlp.ucutils.UCUtils.configuration; import static de.rettichlp.ucutils.UCUtils.player; import static de.rettichlp.ucutils.UCUtils.storage; -import static de.rettichlp.ucutils.UCUtils.syncService; import static de.rettichlp.ucutils.common.Storage.ToggledChat.NONE; import static de.rettichlp.ucutils.common.configuration.options.Options.ReinforcementType.UNICACITYADDON; import static de.rettichlp.ucutils.common.models.Faction.FBI; import static de.rettichlp.ucutils.common.models.Faction.RETTUNGSDIENST; -import static de.rettichlp.ucutils.common.models.Faction.fromDisplayName; -import static java.lang.Integer.parseInt; import static java.lang.System.currentTimeMillis; import static java.time.LocalDateTime.now; import static java.util.Arrays.stream; @@ -55,9 +49,6 @@ @UCUtilsListener public class FactionListener implements IMessageReceiveListener, IMessageSendListener, IMoveListener { - private static final Pattern FACTION_MEMBER_ALL_HEADER = compile("^==== Mitglieder von (?.+) \\(\\d+/\\d+\\) ====$"); - private static final Pattern FACTION_MEMBER_ALL_ENTRY = compile("^\\s*-\\s*(?\\d)\\s*\\|\\s*(?.+)$"); - private static final Pattern REINFORCEMENT_PATTERN = compile("^(?:(?.+)! )?(?.+) (?:\\[UC])?(?[a-zA-Z0-9_]+) benötigt Unterstützung in der Nähe von (?.+)! \\((?\\d+) Meter entfernt\\)$"); private static final Pattern REINFORCEMENT_BUTTON_PATTERN = compile("^ §7» §cRoute anzeigen §7\\| §cUnterwegs$"); private static final Pattern REINFORCMENT_ON_THE_WAY_PATTERN = compile("^(?.+) (?:\\[UC])?(?[a-zA-Z0-9_]+) kommt zum Verstärkungsruf von (?:\\[UC])?(?[a-zA-Z0-9_]+)! \\((?\\d+) Meter entfernt\\)$"); @@ -86,41 +77,6 @@ public class FactionListener implements IMessageReceiveListener, IMessageSendLis @Override public boolean onMessageReceive(Text text, String message) { - Matcher factionMemberAllHeaderMatcher = FACTION_MEMBER_ALL_HEADER.matcher(message); - if (factionMemberAllHeaderMatcher.find()) { - String factionDisplayName = factionMemberAllHeaderMatcher.group("faction"); - fromDisplayName(factionDisplayName).ifPresentOrElse(faction -> this.factionToCheck = faction, - () -> LOGGER.warn("Could not find faction for display name '{}'", factionDisplayName)); - - // clear old faction entry - storage.getFactionEntries().removeIf(factionEntry -> factionEntry.faction() == this.factionToCheck); - storage.getFactionEntries().add(new FactionEntry(this.factionToCheck, new ArrayList<>())); - - return !syncService.isGameSyncProcessActive(); - } - - Matcher factionMemberAllEntryMatcher = FACTION_MEMBER_ALL_ENTRY.matcher(message); - if (factionMemberAllEntryMatcher.find() && this.factionToCheck != null) { - int rank = parseInt(factionMemberAllEntryMatcher.group("rank")); - String[] playerNames = factionMemberAllEntryMatcher.group("playerNames").split(", "); - - List factionMembersForRank = stream(playerNames) - .map(playerName -> new FactionMember(playerName, rank)) - .toList(); - - storage.getFactionEntries().stream() - .filter(factionEntry -> factionEntry.faction() == this.factionToCheck) - .findFirst() - .ifPresent(factionEntry -> factionEntry.members().addAll(factionMembersForRank)); - - LOGGER.info("Retrieved {} members for faction {}[rank={}] from command", factionMembersForRank.size(), this.factionToCheck.name(), rank); - - // clear nametag render cache - storage.getPlayerFactionCache().clear(); - - return !syncService.isGameSyncProcessActive(); - } - Matcher reinforcementMatcher = REINFORCEMENT_PATTERN.matcher(message); if (reinforcementMatcher.find()) { String type = ofNullable(reinforcementMatcher.group("type")).orElse("Reinforcement"); diff --git a/src/main/java/de/rettichlp/ucutils/listener/impl/job/JobListener.java b/src/main/java/de/rettichlp/ucutils/listener/impl/job/JobListener.java index 5722a907..c4610d1f 100644 --- a/src/main/java/de/rettichlp/ucutils/listener/impl/job/JobListener.java +++ b/src/main/java/de/rettichlp/ucutils/listener/impl/job/JobListener.java @@ -1,5 +1,6 @@ package de.rettichlp.ucutils.listener.impl.job; +import de.rettichlp.ucutils.common.models.Countdown; import de.rettichlp.ucutils.common.models.Job; import de.rettichlp.ucutils.common.registry.UCUtilsListener; import de.rettichlp.ucutils.listener.IMessageReceiveListener; @@ -8,6 +9,7 @@ import net.minecraft.text.Text; import net.minecraft.util.math.BlockPos; +import java.time.LocalDateTime; import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -19,6 +21,9 @@ import static de.rettichlp.ucutils.common.models.Job.PIZZA_DELIVERY; import static de.rettichlp.ucutils.common.models.Job.TOBACCO_PLANTATION; import static de.rettichlp.ucutils.common.models.Job.URANIUM_TRANSPORT; +import static java.lang.Integer.parseInt; +import static java.time.Duration.between; +import static java.time.LocalDateTime.now; import static java.util.Arrays.stream; import static java.util.Objects.isNull; import static java.util.concurrent.TimeUnit.SECONDS; @@ -27,9 +32,13 @@ @UCUtilsListener public class JobListener implements IMessageReceiveListener, IMoveListener, INaviSpotReachedListener { + private static final String MINING_BOOSTER_COUNTDOWN_TITLE = "Mining XP-Booster"; private static final Pattern TRANSPORT_DELIVER_PATTERN = compile("^\\[Transport] Du hast (eine Holz Lieferung|eine Kiste|eine Waffenkiste|ein Weizen Paket|eine Schwarzpulverkiste) abgeliefert( bei .+)?\\.$"); private static final Pattern DRINK_TRANSPORT_DELIVER_PATTERN = compile("^\\[Bar] Du hast eine Flasche abgegeben!$"); private static final Pattern PIZZA_JOB_TRANSPORT_GET_PIZZA_PATTERN = compile("^\\[Pizzalieferant] Sobald du 10 Pizzen dabei hast, wird dir deine erste Route angezeigt\\.$"); + private static final Pattern MINING_BOOSTER_PATTERN = compile("^ᴍɪɴɪɴɢ ┃ XP-Booster aktiviert: \\+(?\\d+)% für (?\\d+)s$"); + + private LocalDateTime miningBoosterExpirationTime; @Override public boolean onMessageReceive(Text text, String message) { @@ -51,6 +60,20 @@ public boolean onMessageReceive(Text text, String message) { return true; } + Matcher miningBoosterMatcher = MINING_BOOSTER_PATTERN.matcher(message); + if (miningBoosterMatcher.find()) { + int seconds = parseInt(miningBoosterMatcher.group("seconds")); + LocalDateTime now = now(); + + this.miningBoosterExpirationTime = this.miningBoosterExpirationTime != null && this.miningBoosterExpirationTime.isAfter(now) + ? this.miningBoosterExpirationTime.plusSeconds(seconds) + : now.plusSeconds(seconds); + + storage.getCountdowns().removeIf(countdown -> countdown.getTitle().equals(MINING_BOOSTER_COUNTDOWN_TITLE)); + storage.getCountdowns().add(new Countdown(MINING_BOOSTER_COUNTDOWN_TITLE, between(now, this.miningBoosterExpirationTime), () -> {})); + return true; + } + // refresh job cooldowns Optional optionalJob = stream(Job.values()) .filter(job -> job.getJobStartPattern().matcher(message).find())