Skip to content

Latest commit

 

History

History
524 lines (396 loc) · 14.3 KB

File metadata and controls

524 lines (396 loc) · 14.3 KB

import { Tab, Tabs } from 'nextra-theme-docs'

Team Module

Overview

The team module will allow you to interact with the Team View mod in Lunar Client.

  • Interact with the Team View mod
    • Create, delete and update teams
    • Enables displaying a marker above the head of teammates
    • Set custom team marker color

Team Module Example

Teammates will have markers over their head, appear on Minimap Mod, and appear in the Direction HUD mod!

Integration

Sample Code

Explore each integration by cycling through each tab, to find the best fit for your requirements and needs.

<Tabs items={['Apollo API', 'apollo-protos library', 'Manual JSON Object Construction']}>

private final Map<UUID, Team> teamsByTeamId = Maps.newHashMap();
private final Map<UUID, Team> teamsByPlayerUuid = Maps.newHashMap();

public TeamApiExample() {
    if (ServerUtil.isFolia()) {
        this.runFoliaTeamUpdateTask();
    } else {
        this.runBukkitTeamUpdateTask();
    }

    Bukkit.getPluginManager().registerEvents(this, ApolloExamplePlugin.getInstance());
}

@EventHandler
private void onPlayerQuit(PlayerQuitEvent event) {
    Player player = event.getPlayer();

    this.getByPlayerUuid(player.getUniqueId()).ifPresent(team -> {
        team.removeMember(player);
    });
}

public Optional<Team> getByPlayerUuid(UUID playerUuid) {
    return Optional.ofNullable(this.teamsByPlayerUuid.get(playerUuid));
}

public Optional<Team> getByTeamId(UUID teamId) {
    return Optional.ofNullable(this.teamsByTeamId.get(teamId));
}

public Team createTeam() {
    Team team = new Team();
    this.teamsByTeamId.put(team.getTeamId(), team);

    return team;
}

public void deleteTeam(UUID teamId) {
    Team team = this.teamsByTeamId.remove(teamId);

    if (team != null) {
        team.getMembers().forEach(team::removeMember);
    }
}

private void runBukkitTeamUpdateTask() {
    Bukkit.getScheduler().runTaskTimerAsynchronously(ApolloExamplePlugin.getInstance(), () -> {
        this.teamsByTeamId.values().forEach(Team::refresh);
    }, 1L, 1L);
}

private void runFoliaTeamUpdateTask() {
    Bukkit.getAsyncScheduler().runAtFixedRate(ApolloExamplePlugin.getInstance(), task -> {
        this.teamsByTeamId.values().forEach(Team::refresh);
    }, 50L, 50L, TimeUnit.MILLISECONDS);
}

public class Team {

    private final UUID teamId;
    private final Map<UUID, Player> members;

    public Team() {
        this.teamId = UUID.randomUUID();
        this.members = new HashMap<>();
    }

    public void addMember(Player player) {
        this.members.put(player.getUniqueId(), player);
        TeamApiExample.this.teamsByPlayerUuid.put(player.getUniqueId(), this);
    }

    public void removeMember(Player player) {
        this.members.remove(player.getUniqueId());
        TeamApiExample.this.teamsByPlayerUuid.remove(player.getUniqueId());

        Apollo.getPlayerManager().getPlayer(player.getUniqueId())
            .ifPresent(TeamApiExample.this.teamModule::resetTeamMembers);
    }

    private TeamMember createTeamMember(Player member) {
        Location location = member.getLocation();

        return TeamMember.builder()
            .playerUuid(member.getUniqueId())
            .displayName(Component.text()
                .content(member.getName())
                .color(NamedTextColor.WHITE)
                .build())
            .markerColor(Color.WHITE)
            .location(ApolloLocation.builder()
                .world(location.getWorld().getName())
                .x(location.getX())
                .y(location.getY())
                .z(location.getZ())
                .build())
            .build();
    }

    // The refresh method used for updating members locations
    public void refresh() {
        List<TeamMember> teammates = this.members.values()
            .stream().filter(Player::isOnline)
            .map(this::createTeamMember)
            .collect(Collectors.toList());

        this.members.values().forEach(member -> Apollo.getPlayerManager().getPlayer(member.getUniqueId())
            .ifPresent(apolloPlayer -> TeamApiExample.this.teamModule.updateTeamMembers(apolloPlayer, teammates)));
    }

    public UUID getTeamId() {
        return this.teamId;
    }

    public Collection<Player> getMembers() {
        return this.members.values();
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }

        if (other == null || other.getClass() != this.getClass()) {
            return false;
        }

        Team team = (Team) other;
        return this.teamId.equals(team.getTeamId());
    }

    @Override
    public int hashCode() {
        return this.teamId.hashCode();
    }
}

TeamMember Options

.playerUuid(java.util.UUID) member UUID.

.playerUuid(UUID)

.displayName(Component) is the display name that will be shown whenever the observer is outside view distance, but hovers over the player marker. See the chat components page for more.

.displayName(Component.text()
    .content(member.getName())
    .color(NamedTextColor.WHITE)
    .build())

.markerColor(java.awt.Color) is how you dictate the color of the marker. See the colors page for more.

Color Types

<Tabs items={['Java Presets', 'Minecraft Presets', 'Hex & RGB']}>

The java.awt.Color class statically exposes some colors, although they do not correspond to any existing colors used in Minecraft.

.color(Color.CYAN)

The ApolloColors class statically exposes colors that correspond to Bukkit/Spigot's ChatColor enum.

.color(ApolloColors.LIGHT_PURPLE)

Custom colors can be created from any RGB values using new Color(int red, int green, int blue), or from any hex color using Color.decode(String hex).

.color(Color.decode("#FF00FF"))

.location(ApolloLocation) is using the ApolloLocation builder to create the location. See the locations page for more.

.location(ApolloLocation.builder()
    .world("world")
    .x(5)
    .y(100)
    .z(0)
    .build()
)
private final Map<UUID, Team> teamsByTeamId = Maps.newHashMap();
private final Map<UUID, Team> teamsByPlayerUuid = Maps.newHashMap();

public TeamProtoExample() {
    if (ServerUtil.isFolia()) {
        this.runFoliaTeamUpdateTask();
    } else {
        this.runBukkitTeamUpdateTask();
    }

    Bukkit.getPluginManager().registerEvents(this, ApolloExamplePlugin.getInstance());
}

@EventHandler
private void onPlayerQuit(PlayerQuitEvent event) {
    Player player = event.getPlayer();

    this.getByPlayerUuid(player.getUniqueId()).ifPresent(team -> {
        team.removeMember(player);
    });
}

public Optional<Team> getByPlayerUuid(UUID playerUuid) {
    return Optional.ofNullable(this.teamsByPlayerUuid.get(playerUuid));
}

public Optional<Team> getByTeamId(UUID teamId) {
    return Optional.ofNullable(this.teamsByTeamId.get(teamId));
}

public Team createTeam() {
    Team team = new Team();
    this.teamsByTeamId.put(team.getTeamId(), team);

    return team;
}

public void deleteTeam(UUID teamId) {
    Team team = this.teamsByTeamId.remove(teamId);

    if (team != null) {
        team.getMembers().forEach(team::removeMember);
    }
}

private void runBukkitTeamUpdateTask() {
    Bukkit.getScheduler().runTaskTimerAsynchronously(ApolloExamplePlugin.getInstance(), () -> {
        this.teamsByTeamId.values().forEach(Team::refresh);
    }, 1L, 1L);
}

private void runFoliaTeamUpdateTask() {
    Bukkit.getAsyncScheduler().runAtFixedRate(ApolloExamplePlugin.getInstance(), task -> {
        this.teamsByTeamId.values().forEach(Team::refresh);
    }, 50L, 50L, TimeUnit.MILLISECONDS);
}

public class Team {

    private final UUID teamId;
    private final Map<UUID, Player> members;

    public Team() {
        this.teamId = UUID.randomUUID();
        this.members = new HashMap<>();
    }

    public void addMember(Player player) {
        this.members.put(player.getUniqueId(), player);
        TeamProtoExample.this.teamsByPlayerUuid.put(player.getUniqueId(), this);
    }

    public void removeMember(Player player) {
        this.members.remove(player.getUniqueId());
        TeamProtoExample.this.teamsByPlayerUuid.remove(player.getUniqueId());

        ResetTeamMembersMessage message = ResetTeamMembersMessage.getDefaultInstance();
        ProtobufPacketUtil.sendPacket(player, message);
    }

    private TeamMember createTeamMember(Player member) {
        return TeamMember.newBuilder()
            .setPlayerUuid(ProtobufUtil.createUuidProto(member.getUniqueId()))
            .setAdventureJsonPlayerName(AdventureUtil.toJson(
                Component.text()
                    .content(member.getName())
                    .color(NamedTextColor.WHITE)
                    .build()
            ))
            .setMarkerColor(ProtobufUtil.createColorProto(Color.WHITE))
            .setLocation(ProtobufUtil.createLocationProto(member.getLocation()))
            .build();
    }

    // The refresh method used for updating members locations
    public void refresh() {
        List<TeamMember> teammates = this.members.values().stream().filter(Player::isOnline)
            .map(this::createTeamMember)
            .collect(Collectors.toList());

        UpdateTeamMembersMessage message = UpdateTeamMembersMessage.newBuilder()
            .addAllMembers(teammates)
            .build();

        this.members.values().forEach(member -> ProtobufPacketUtil.sendPacket(member, message));
    }

    public UUID getTeamId() {
        return this.teamId;
    }

    public Collection<Player> getMembers() {
        return this.members.values();
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }

        if (other == null || other.getClass() != this.getClass()) {
            return false;
        }

        Team team = (Team) other;
        return this.teamId.equals(team.getTeamId());
    }

    @Override
    public int hashCode() {
        return this.teamId.hashCode();
    }
}
private final Map<UUID, Team> teamsByTeamId = Maps.newHashMap();
private final Map<UUID, Team> teamsByPlayerUuid = Maps.newHashMap();

public TeamJsonExample() {
    if (ServerUtil.isFolia()) {
        this.runFoliaTeamUpdateTask();
    } else {
        this.runBukkitTeamUpdateTask();
    }

    Bukkit.getPluginManager().registerEvents(this, ApolloExamplePlugin.getInstance());
}

@EventHandler
private void onPlayerQuit(PlayerQuitEvent event) {
    Player player = event.getPlayer();

    this.getByPlayerUuid(player.getUniqueId()).ifPresent(team -> {
        team.removeMember(player);
    });
}

public Optional<Team> getByPlayerUuid(UUID playerUuid) {
    return Optional.ofNullable(this.teamsByPlayerUuid.get(playerUuid));
}

public Optional<Team> getByTeamId(UUID teamId) {
    return Optional.ofNullable(this.teamsByTeamId.get(teamId));
}

public Team createTeam() {
    Team team = new Team();
    this.teamsByTeamId.put(team.getTeamId(), team);

    return team;
}

public void deleteTeam(UUID teamId) {
    Team team = this.teamsByTeamId.remove(teamId);

    if (team != null) {
        team.getMembers().forEach(team::removeMember);
    }
}

private void runBukkitTeamUpdateTask() {
    Bukkit.getScheduler().runTaskTimerAsynchronously(ApolloExamplePlugin.getInstance(), () -> {
        this.teamsByTeamId.values().forEach(Team::refresh);
    }, 1L, 1L);
}

private void runFoliaTeamUpdateTask() {
    Bukkit.getAsyncScheduler().runAtFixedRate(ApolloExamplePlugin.getInstance(), task -> {
        this.teamsByTeamId.values().forEach(Team::refresh);
    }, 50L, 50L, TimeUnit.MILLISECONDS);
}

public class Team {

    private final UUID teamId;
    private final Map<UUID, Player> members;

    public Team() {
        this.teamId = UUID.randomUUID();
        this.members = new HashMap<>();
    }

    public void addMember(Player player) {
        this.members.put(player.getUniqueId(), player);
        TeamJsonExample.this.teamsByPlayerUuid.put(player.getUniqueId(), this);
    }

    public void removeMember(Player player) {
        this.members.remove(player.getUniqueId());
        TeamJsonExample.this.teamsByPlayerUuid.remove(player.getUniqueId());

        JsonObject message = new JsonObject();
        message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.team.v1.ResetTeamMembersMessage");

        JsonPacketUtil.sendPacket(player, message);
    }

    private JsonObject createTeamMember(Player member) {
        JsonObject message = new JsonObject();
        message.add("player_uuid", JsonUtil.createUuidObject(member.getUniqueId()));
        message.addProperty("adventure_json_player_name", AdventureUtil.toJson(
            Component.text()
                .content(member.getName())
                .color(NamedTextColor.WHITE)
                .build()
        ));
        message.add("marker_color", JsonUtil.createColorObject(Color.WHITE));
        message.add("location", JsonUtil.createLocationObject(member.getLocation()));

        return message;
    }

    // The refresh method used for updating members locations
    public void refresh() {
        JsonArray teammates = this.members.values()
            .stream().filter(Player::isOnline)
            .map(this::createTeamMember)
            .collect(JsonArray::new, JsonArray::add, JsonArray::addAll);

        JsonObject message = new JsonObject();
        message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.team.v1.UpdateTeamMembersMessage");
        message.add("members", teammates);

        this.members.values().forEach(member -> JsonPacketUtil.sendPacket(member, message));
    }

    public UUID getTeamId() {
        return this.teamId;
    }

    public Collection<Player> getMembers() {
        return this.members.values();
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }

        if (other == null || other.getClass() != this.getClass()) {
            return false;
        }

        Team team = (Team) other;
        return this.teamId.equals(team.getTeamId());
    }

    @Override
    public int hashCode() {
        return this.teamId.hashCode();
    }
}