Skip to content

Commit

Permalink
Advancement sync
Browse files Browse the repository at this point in the history
  • Loading branch information
Tenzin Pelletier committed Jan 12, 2022
1 parent a634776 commit b10bbd1
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 39 deletions.
2 changes: 2 additions & 0 deletions src/main/java/com/t2pellet/teams/TeamsMod.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}
10 changes: 10 additions & 0 deletions src/main/java/com/t2pellet/teams/core/EventHandlers.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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);
}
};

}
120 changes: 82 additions & 38 deletions src/main/java/com/t2pellet/teams/core/Team.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -26,6 +30,7 @@ public class Team extends AbstractTeam {
public final String name;
private Set<UUID> players;
private Map<UUID, ServerPlayerEntity> onlinePlayers;
private final Set<Advancement> advancements = new LinkedHashSet<>();
private net.minecraft.scoreboard.Team scoreboardTeam;

Team(String name) {
Expand Down Expand Up @@ -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<Advancement> getAdvancements() {
return advancements;
}

void playerOnline(ServerPlayerEntity player, boolean sendPackets) {
Expand All @@ -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) {
Expand All @@ -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<Advancement> 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) {
Expand All @@ -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;
}

Expand All @@ -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;
}
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/com/t2pellet/teams/events/AdvancementEvents.java
Original file line number Diff line number Diff line change
@@ -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<PlayerAdvancement> 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);
}

}
16 changes: 16 additions & 0 deletions src/main/java/com/t2pellet/teams/mixin/AdvancementAccessor.java
Original file line number Diff line number Diff line change
@@ -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<Advancement> getVisibleAdvancements();

}
25 changes: 25 additions & 0 deletions src/main/java/com/t2pellet/teams/mixin/AdvancementMixin.java
Original file line number Diff line number Diff line change
@@ -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<Boolean> ci) {
if (!TeamsMod.getServer().getOverworld().isClient) {
AdvancementEvents.ADVANCEMENT_GRANTED.invoker().onPlayerAdvancement(owner, advancement);
}
}
}
4 changes: 3 additions & 1 deletion src/main/resources/teams.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
"package": "com.t2pellet.teams.mixin",
"compatibilityLevel": "JAVA_16",
"mixins": [
"PlayerMixin"
"PlayerMixin",
"AdvancementMixin",
"AdvancementAccessor"
],
"client": [
"InventoryMixin",
Expand Down

0 comments on commit b10bbd1

Please sign in to comment.