From b10bbd11ddc7af2a840d65dd407adcbdac9e7a0a Mon Sep 17 00:00:00 2001 From: Tenzin Pelletier Date: Wed, 12 Jan 2022 12:13:36 -0500 Subject: [PATCH] Advancement sync --- .../java/com/t2pellet/teams/TeamsMod.java | 2 + .../t2pellet/teams/core/EventHandlers.java | 10 ++ .../java/com/t2pellet/teams/core/Team.java | 120 ++++++++++++------ .../teams/events/AdvancementEvents.java | 22 ++++ .../teams/mixin/AdvancementAccessor.java | 16 +++ .../teams/mixin/AdvancementMixin.java | 25 ++++ src/main/resources/teams.mixins.json | 4 +- 7 files changed, 160 insertions(+), 39 deletions(-) create mode 100644 src/main/java/com/t2pellet/teams/events/AdvancementEvents.java create mode 100644 src/main/java/com/t2pellet/teams/mixin/AdvancementAccessor.java create mode 100644 src/main/java/com/t2pellet/teams/mixin/AdvancementMixin.java diff --git a/src/main/java/com/t2pellet/teams/TeamsMod.java b/src/main/java/com/t2pellet/teams/TeamsMod.java index 6b47d98..719e462 100644 --- a/src/main/java/com/t2pellet/teams/TeamsMod.java +++ b/src/main/java/com/t2pellet/teams/TeamsMod.java @@ -4,6 +4,7 @@ import com.t2pellet.teams.config.TeamsConfig; import com.t2pellet.teams.core.EventHandlers; import com.t2pellet.teams.core.TeamDB; +import com.t2pellet.teams.events.AdvancementEvents; import com.t2pellet.teams.events.PlayerUpdateEvents; import com.t2pellet.teams.network.PacketHandler; import com.t2pellet.teams.network.TeamPackets; @@ -87,5 +88,6 @@ public void onInitialize() { ServerPlayConnectionEvents.DISCONNECT.register(EventHandlers.playerDisconnect); PlayerUpdateEvents.PLAYER_HEALTH_UPDATE.register(EventHandlers.playerHealthUpdate); PlayerUpdateEvents.PLAYER_COPY.register(EventHandlers.playerCopy); + AdvancementEvents.ADVANCEMENT_GRANTED.register(EventHandlers.playerAdvancement); } } diff --git a/src/main/java/com/t2pellet/teams/core/EventHandlers.java b/src/main/java/com/t2pellet/teams/core/EventHandlers.java index 52fdcef..a263c33 100644 --- a/src/main/java/com/t2pellet/teams/core/EventHandlers.java +++ b/src/main/java/com/t2pellet/teams/core/EventHandlers.java @@ -1,5 +1,6 @@ package com.t2pellet.teams.core; +import com.t2pellet.teams.events.AdvancementEvents; import com.t2pellet.teams.events.PlayerUpdateEvents; import com.t2pellet.teams.network.PacketHandler; import com.t2pellet.teams.network.packets.TeamDataPacket; @@ -13,11 +14,13 @@ private EventHandlers() { } public static ServerPlayConnectionEvents.Join playerConnect = (handler, sender, server) -> { + // Mark online ServerPlayerEntity player = handler.getPlayer(); Team team = TeamDB.INSTANCE.getTeam(player); if (team != null) { team.playerOnline(player, true); } + // Send packets var teams = TeamDB.INSTANCE.getTeams().map(t -> t.name).toArray(String[]::new); var onlineTeams = TeamDB.INSTANCE.getTeams().filter(t -> t.getOnlinePlayers().findAny().isPresent()).map(t -> t.name).toArray(String[]::new); PacketHandler.INSTANCE.sendTo(new TeamDataPacket(TeamDataPacket.Type.ADD, teams), player); @@ -48,4 +51,11 @@ private EventHandlers() { } }; + public static AdvancementEvents.PlayerAdvancement playerAdvancement = (player, advancement) -> { + Team team = TeamDB.INSTANCE.getTeam(player); + if (team != null) { + team.addAdvancement(advancement); + } + }; + } diff --git a/src/main/java/com/t2pellet/teams/core/Team.java b/src/main/java/com/t2pellet/teams/core/Team.java index ac5abd2..e6ef96a 100644 --- a/src/main/java/com/t2pellet/teams/core/Team.java +++ b/src/main/java/com/t2pellet/teams/core/Team.java @@ -2,12 +2,15 @@ import com.mojang.authlib.GameProfile; import com.t2pellet.teams.TeamsMod; +import com.t2pellet.teams.mixin.AdvancementAccessor; import com.t2pellet.teams.network.PacketHandler; import com.t2pellet.teams.network.packets.TeamClearPacket; import com.t2pellet.teams.network.packets.TeamDataPacket; import com.t2pellet.teams.network.packets.TeamInitPacket; import com.t2pellet.teams.network.packets.TeamPlayerDataPacket; import com.t2pellet.teams.network.packets.toasts.TeamUpdatePacket; +import net.minecraft.advancement.Advancement; +import net.minecraft.advancement.AdvancementProgress; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; import net.minecraft.nbt.NbtList; @@ -17,6 +20,7 @@ import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.Formatting; +import net.minecraft.util.Identifier; import java.util.*; import java.util.stream.Stream; @@ -26,6 +30,7 @@ public class Team extends AbstractTeam { public final String name; private Set players; private Map onlinePlayers; + private final Set advancements = new LinkedHashSet<>(); private net.minecraft.scoreboard.Team scoreboardTeam; Team(String name) { @@ -69,40 +74,22 @@ public void addPlayer(ServerPlayerEntity player) { addPlayer(player.getUuid()); } - private void addPlayer(UUID player) { - players.add(player); - String playerName = getNameFromUUID(player); - var playerScoreboardTeam = TeamsMod.getScoreboard().getPlayerTeam(playerName); - if (playerScoreboardTeam == null || !playerScoreboardTeam.isEqual(scoreboardTeam)) { - TeamsMod.getScoreboard().addPlayerToTeam(playerName, scoreboardTeam); - } - var playerEntity = TeamsMod.getServer().getPlayerManager().getPlayer(player); - if (playerEntity != null) { - PacketHandler.INSTANCE.sendTo(new TeamUpdatePacket(name, playerName, TeamUpdatePacket.Action.JOINED, true), playerEntity); - PacketHandler.INSTANCE.sendTo(new TeamUpdatePacket(name, playerName, TeamUpdatePacket.Action.JOINED, false), getOnlinePlayers().toArray(ServerPlayerEntity[]::new)); - playerOnline(playerEntity, true); - } - } - public void removePlayer(ServerPlayerEntity player) { removePlayer(player.getUuid()); } - void removePlayer(UUID player) { - players.remove(player); - String playerName = getNameFromUUID(player); - var playerScoreboardTeam = TeamsMod.getScoreboard().getPlayerTeam(playerName); - if (playerScoreboardTeam != null && playerScoreboardTeam.isEqual(scoreboardTeam)) { - TeamsMod.getScoreboard().removePlayerFromTeam(playerName, scoreboardTeam); - } - var playerEntity = TeamsMod.getServer().getPlayerManager().getPlayer(player); - if (playerEntity != null) { - playerOffline(playerEntity, true); - PacketHandler.INSTANCE.sendTo(new TeamClearPacket(), playerEntity); - PacketHandler.INSTANCE.sendTo(new TeamUpdatePacket(name, playerName, TeamUpdatePacket.Action.LEFT, true), playerEntity); - PacketHandler.INSTANCE.sendTo(new TeamUpdatePacket(name, playerName, TeamUpdatePacket.Action.LEFT, false), getOnlinePlayers().toArray(ServerPlayerEntity[]::new)); - ((IHasTeam) playerEntity).setTeam(null); - } + public void clear() { + var playersCopy = new ArrayList<>(players); + playersCopy.forEach(this::removePlayer); + advancements.clear(); + } + + public void addAdvancement(Advancement advancement) { + advancements.add(advancement); + } + + public Set getAdvancements() { + return advancements; } void playerOnline(ServerPlayerEntity player, boolean sendPackets) { @@ -121,6 +108,13 @@ void playerOnline(ServerPlayerEntity player, boolean sendPackets) { PacketHandler.INSTANCE.sendTo(new TeamPlayerDataPacket(teammate, TeamPlayerDataPacket.Type.ADD), player); } } + // Advancement Sync + for (Advancement advancement : getAdvancements()) { + AdvancementProgress progress = player.getAdvancementTracker().getProgress(advancement); + for (String criterion : progress.getUnobtainedCriteria()) { + player.getAdvancementTracker().grantCriterion(advancement, criterion); + } + } } void playerOffline(ServerPlayerEntity player, boolean sendPackets) { @@ -136,9 +130,47 @@ void playerOffline(ServerPlayerEntity player, boolean sendPackets) { } } - void clear() { - var playersCopy = new ArrayList<>(players); - playersCopy.forEach(this::removePlayer); + private void addPlayer(UUID player) { + players.add(player); + String playerName = getNameFromUUID(player); + // Scoreboard + var playerScoreboardTeam = TeamsMod.getScoreboard().getPlayerTeam(playerName); + if (playerScoreboardTeam == null || !playerScoreboardTeam.isEqual(scoreboardTeam)) { + TeamsMod.getScoreboard().addPlayerToTeam(playerName, scoreboardTeam); + } + var playerEntity = TeamsMod.getServer().getPlayerManager().getPlayer(player); + if (playerEntity != null) { + // Packets + PacketHandler.INSTANCE.sendTo(new TeamUpdatePacket(name, playerName, TeamUpdatePacket.Action.JOINED, true), playerEntity); + PacketHandler.INSTANCE.sendTo(new TeamUpdatePacket(name, playerName, TeamUpdatePacket.Action.JOINED, false), getOnlinePlayers().toArray(ServerPlayerEntity[]::new)); + playerOnline(playerEntity, true); + // Advancement Sync + Set advancements = ((AdvancementAccessor) playerEntity.getAdvancementTracker()).getVisibleAdvancements(); + for (Advancement advancement : advancements) { + if (playerEntity.getAdvancementTracker().getProgress(advancement).isDone()) { + addAdvancement(advancement); + } + } + } + } + + private void removePlayer(UUID player) { + players.remove(player); + String playerName = getNameFromUUID(player); + // Scoreboard + var playerScoreboardTeam = TeamsMod.getScoreboard().getPlayerTeam(playerName); + if (playerScoreboardTeam != null && playerScoreboardTeam.isEqual(scoreboardTeam)) { + TeamsMod.getScoreboard().removePlayerFromTeam(playerName, scoreboardTeam); + } + // Packets + var playerEntity = TeamsMod.getServer().getPlayerManager().getPlayer(player); + if (playerEntity != null) { + playerOffline(playerEntity, true); + PacketHandler.INSTANCE.sendTo(new TeamClearPacket(), playerEntity); + PacketHandler.INSTANCE.sendTo(new TeamUpdatePacket(name, playerName, TeamUpdatePacket.Action.LEFT, true), playerEntity); + PacketHandler.INSTANCE.sendTo(new TeamUpdatePacket(name, playerName, TeamUpdatePacket.Action.LEFT, false), getOnlinePlayers().toArray(ServerPlayerEntity[]::new)); + ((IHasTeam) playerEntity).setTeam(null); + } } private String getNameFromUUID(UUID id) { @@ -155,11 +187,17 @@ static Team fromNBT(NbtCompound compound) { .setShowFriendlyInvisibles(compound.getBoolean("showInvisible")) .complete(); - NbtList list = compound.getList("players", NbtElement.STRING_TYPE); - for (var elem : list) { + NbtList players = compound.getList("players", NbtElement.STRING_TYPE); + for (var elem : players) { team.addPlayer(UUID.fromString(elem.asString())); } + NbtList advancements = compound.getList("advancement", NbtElement.STRING_TYPE); + for (var adv : advancements) { + Identifier id = Identifier.tryParse(adv.asString()); + team.addAdvancement(TeamsMod.getServer().getAdvancementLoader().get(id)); + } + return team; } @@ -173,11 +211,17 @@ NbtCompound toNBT() { compound.putBoolean("friendlyFire", scoreboardTeam.isFriendlyFireAllowed()); compound.putBoolean("showInvisible", scoreboardTeam.shouldShowFriendlyInvisibles()); - NbtList list = new NbtList(); + NbtList playerList = new NbtList(); for (var player : players) { - list.add(NbtString.of(player.toString())); + playerList.add(NbtString.of(player.toString())); + } + compound.put("players", playerList); + + NbtList advList = new NbtList(); + for (var advancement : advancements) { + advList.add(NbtString.of(advancement.getId().toString())); } - compound.put("players", list); + compound.put("advancements", advList); return compound; } diff --git a/src/main/java/com/t2pellet/teams/events/AdvancementEvents.java b/src/main/java/com/t2pellet/teams/events/AdvancementEvents.java new file mode 100644 index 0000000..1bb2732 --- /dev/null +++ b/src/main/java/com/t2pellet/teams/events/AdvancementEvents.java @@ -0,0 +1,22 @@ +package com.t2pellet.teams.events; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.advancement.Advancement; +import net.minecraft.server.network.ServerPlayerEntity; + +public class AdvancementEvents { + + public static final Event ADVANCEMENT_GRANTED = EventFactory.createArrayBacked(PlayerAdvancement.class, + listeners -> (player, advancement) -> { + for (PlayerAdvancement listener : listeners) { + listener.onPlayerAdvancement(player, advancement); + } + }); + + @FunctionalInterface + public interface PlayerAdvancement { + void onPlayerAdvancement(ServerPlayerEntity player, Advancement advancement); + } + +} diff --git a/src/main/java/com/t2pellet/teams/mixin/AdvancementAccessor.java b/src/main/java/com/t2pellet/teams/mixin/AdvancementAccessor.java new file mode 100644 index 0000000..9dc1366 --- /dev/null +++ b/src/main/java/com/t2pellet/teams/mixin/AdvancementAccessor.java @@ -0,0 +1,16 @@ +package com.t2pellet.teams.mixin; + +import net.minecraft.advancement.Advancement; +import net.minecraft.advancement.PlayerAdvancementTracker; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.Set; + +@Mixin(PlayerAdvancementTracker.class) +public interface AdvancementAccessor { + + @Accessor("visibleAdvancements") + Set getVisibleAdvancements(); + +} diff --git a/src/main/java/com/t2pellet/teams/mixin/AdvancementMixin.java b/src/main/java/com/t2pellet/teams/mixin/AdvancementMixin.java new file mode 100644 index 0000000..40f4228 --- /dev/null +++ b/src/main/java/com/t2pellet/teams/mixin/AdvancementMixin.java @@ -0,0 +1,25 @@ +package com.t2pellet.teams.mixin; + +import com.t2pellet.teams.TeamsMod; +import com.t2pellet.teams.events.AdvancementEvents; +import net.minecraft.advancement.Advancement; +import net.minecraft.advancement.PlayerAdvancementTracker; +import net.minecraft.server.network.ServerPlayerEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(PlayerAdvancementTracker.class) +public class AdvancementMixin { + + @Shadow private ServerPlayerEntity owner; + + @Inject(method = "grantCriterion", at = @At(value = "INVOKE", target = "Lnet/minecraft/advancement/PlayerAdvancementTracker;updateDisplay(Lnet/minecraft/advancement/Advancement;)V")) + public void advancementCompleted(Advancement advancement, String criterionName, CallbackInfoReturnable ci) { + if (!TeamsMod.getServer().getOverworld().isClient) { + AdvancementEvents.ADVANCEMENT_GRANTED.invoker().onPlayerAdvancement(owner, advancement); + } + } +} diff --git a/src/main/resources/teams.mixins.json b/src/main/resources/teams.mixins.json index 78dbaaa..05299eb 100644 --- a/src/main/resources/teams.mixins.json +++ b/src/main/resources/teams.mixins.json @@ -4,7 +4,9 @@ "package": "com.t2pellet.teams.mixin", "compatibilityLevel": "JAVA_16", "mixins": [ - "PlayerMixin" + "PlayerMixin", + "AdvancementMixin", + "AdvancementAccessor" ], "client": [ "InventoryMixin",