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/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/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");