Skip to content

Commit

Permalink
Draw host faces on POIs
Browse files Browse the repository at this point in the history
  • Loading branch information
bazke authored and itsbazke committed Oct 29, 2023
1 parent b6bf2c0 commit 2d40371
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,22 @@
import com.lovetropics.extras.client.screen.map.TropicalMapScreen;
import com.lovetropics.extras.data.poi.Poi;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.client.multiplayer.PlayerInfo;
import net.minecraft.client.resources.DefaultPlayerSkin;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.ClientPlayerNetworkEvent;
import net.minecraftforge.event.entity.EntityLeaveLevelEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Mod.EventBusSubscriber(modid = LTExtras.MODID, value = Dist.CLIENT)
public class ClientMapPoiManager {
Expand All @@ -38,4 +45,18 @@ public static void openScreen(final Player player) {
public static void onLoggingOut(final ClientPlayerNetworkEvent.LoggingOut event) {
POIS.clear();
}

public static ResourceLocation getFace(final UUID uuid) {
return getPlayerSkinOrDefault(uuid);
}

private static ResourceLocation getPlayerSkinOrDefault(final UUID uuid) {
final ClientPacketListener connection = Minecraft.getInstance().getConnection();

final PlayerInfo playerInfo;
if (connection == null || (playerInfo = connection.getPlayerInfo(uuid)) == null) {
return DefaultPlayerSkin.getDefaultSkin(uuid);
}
return playerInfo.getSkinLocation();
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
package com.lovetropics.extras.client.screen.map;

import com.lovetropics.extras.client.ClientMapPoiManager;
import com.lovetropics.extras.data.poi.Poi;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.AbstractButton;
import net.minecraft.client.gui.components.PlayerFaceRenderer;
import net.minecraft.client.gui.narration.NarrationElementOutput;
import net.minecraft.client.multiplayer.PlayerInfo;
import net.minecraft.client.resources.DefaultPlayerSkin;
import net.minecraft.client.resources.SkinManager;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.CommonColors;
import net.minecraft.util.Mth;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.function.Consumer;

class PoiButton extends AbstractButton {
private static final int ICON_SIZE = 16;
private static final int HALF_ICON_SIZE = ICON_SIZE / 2;
private static final int BORDER_SIZE = 3;
private static final int SIZE = ICON_SIZE + BORDER_SIZE * 2;
private static final int TOOLTIP_HEIGHT = 18;
Expand Down Expand Up @@ -91,6 +102,19 @@ protected void renderWidget(final GuiGraphics graphics, final int mouseX, final

final ResourceLocation icon = poi.resourceLocation();
graphics.blit(icon, getX() + BORDER_SIZE, getY() + BORDER_SIZE, zOffset, 0.0f, 0.0f, ICON_SIZE, ICON_SIZE, ICON_SIZE, ICON_SIZE);

final List<UUID> faces = poi.faces();
if (!faces.isEmpty()) {
final int faceFactor = faces.size() > 2 ? 2 : 1;
graphics.pose().pushPose();
graphics.pose().translate(0.0f, 0.0f, zOffset);
for (int i = 0; i < faces.size(); i++) {
final UUID uuid = faces.get(i);
final ResourceLocation face = ClientMapPoiManager.getFace(uuid);
PlayerFaceRenderer.draw(graphics, face, getX() + BORDER_SIZE + i * HALF_ICON_SIZE / faceFactor + i, getY() + ICON_SIZE, HALF_ICON_SIZE / faceFactor);
}
graphics.pose().popPose();
}
}

@Override
Expand Down
8 changes: 6 additions & 2 deletions src/main/java/com/lovetropics/extras/command/PoiCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;

import java.util.List;
import java.util.UUID;
import java.util.stream.Stream;

import static com.mojang.brigadier.arguments.BoolArgumentType.bool;
Expand Down Expand Up @@ -154,8 +156,9 @@ private static int addWithDefaults(CommandContext<CommandSourceStack> ctx) {
final ResourceLocation icon = getId(ctx, "icon");
final GlobalPos globalPos = GlobalPos.of(ctx.getSource().getLevel().dimension(), ctx.getSource().getPlayer().getOnPos().above());
final boolean enabled = false;
final List<UUID> faces = List.of();

final Poi newPoi = new Poi(name, description, icon, globalPos, enabled);
final Poi newPoi = new Poi(name, description, icon, globalPos, enabled, faces);
MapPoiManager.get(ctx.getSource().getServer()).add(newPoi);
ctx.getSource().sendSuccess(() -> Component.literal("Added new disabled POI " + newPoi.name() + " at your current position"), false);
return Command.SINGLE_SUCCESS;
Expand Down Expand Up @@ -236,8 +239,9 @@ private static Poi createPoiFromCtx(CommandContext<CommandSourceStack> ctx) {
final WorldCoordinates worldCoordinates = ctx.getArgument("blockpos", WorldCoordinates.class);
final GlobalPos globalPos = GlobalPos.of(ctx.getSource().getLevel().dimension(), worldCoordinates.getBlockPos(ctx.getSource()));
final boolean enabled = getBool(ctx, "enabled");
final List<UUID> faces = List.of();

return new Poi(name, description, icon, globalPos, enabled);
return new Poi(name, description, icon, globalPos, enabled, faces);
}

private static Stream<String> suggestGlobalPos(CommandContext<CommandSourceStack> ctx) {
Expand Down
100 changes: 96 additions & 4 deletions src/main/java/com/lovetropics/extras/data/poi/MapPoiManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,25 @@
import com.lovetropics.extras.LTExtras;
import com.lovetropics.extras.network.ClientboundPoiPacket;
import com.lovetropics.extras.network.LTExtrasNetwork;
import com.lovetropics.lib.permission.PermissionsApi;
import com.lovetropics.lib.permission.role.RoleOverrideType;
import com.mojang.serialization.Codec;
import net.minecraft.Util;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import net.minecraft.world.level.saveddata.SavedData;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.network.PacketDistributor;

import javax.annotation.Nullable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

Expand All @@ -33,8 +34,11 @@ public class MapPoiManager extends SavedData {
public static final BoundingBox MAP_BB = new BoundingBox(2013, 0, 1883, 2910, 0, 2799);
private static final Codec<Map<String, Poi>> CODEC = Codec.unboundedMap(Codec.STRING, Poi.CODEC);
private static final String STORAGE_ID = LTExtras.MODID + "_map_poi";
private static final RoleOverrideType<Boolean> HOST_ROLE = (RoleOverrideType<Boolean>) RoleOverrideType.byId("host");
private static final Predicate<ServerPlayer> SPECIAL_RULE = p -> PermissionsApi.lookup().byPlayer(p).overrides().test(HOST_ROLE);
private final Map<String, Poi> pois;


public MapPoiManager(final Map<String, Poi> pois) {
this.pois = pois;
}
Expand Down Expand Up @@ -77,6 +81,37 @@ public Set<Poi> getEnabledPois() {
.collect(Collectors.toSet());
}

private void removeFace(String name, UUID face) {
final Poi poi = pois.get(name);
if (poi != null) {
poi.removeFace(face);
LTExtrasNetwork.CHANNEL.send(PacketDistributor.ALL.noArg(), new ClientboundPoiPacket(poi, false));
}
setDirty();
}

public void addFace(String name, UUID face) {
final Poi poi = pois.get(name);
if (poi != null) {
getAllPois().stream()
.filter(p -> p != poi)
.filter(p -> p.faces().contains(face))
.forEach(p -> removeFace(p.name(), face));
poi.addFace(face);
setDirty();
LTExtrasNetwork.CHANNEL.send(PacketDistributor.ALL.noArg(), new ClientboundPoiPacket(poi, false));
}
}

public void clearFaces() {
pois.values()
.stream()
.filter(Poi::hasFaces)
.map(Poi::clearFaces)
.forEach(p -> LTExtrasNetwork.CHANNEL.send(PacketDistributor.ALL.noArg(), new ClientboundPoiPacket(p, false)));
setDirty();
}

public Set<Poi> getDisabledPois() {
return pois.values().stream()
.filter(Predicate.not(Poi::enabled))
Expand Down Expand Up @@ -126,4 +161,61 @@ public void remove(String name) {
setDirty();
LTExtrasNetwork.CHANNEL.send(PacketDistributor.ALL.noArg(), new ClientboundPoiPacket(poi, true));
}

@SubscribeEvent
public static void onServerTick(TickEvent.ServerTickEvent event) {
if (event.phase != TickEvent.Phase.START || event.getServer().getTickCount() % 20 != 0) {
return;
}
final MapPoiManager manager = MapPoiManager.get(event.getServer());
final Set<ServerPlayer> hosts = getHosts(event.getServer());

if (hosts.isEmpty()) {
manager.clearFaces();
return;
}

addNewFacesToPois(manager, hosts);
removeNoLongerHostingFaces(manager, hosts);
removeFacesInWrongDimensions(manager, hosts);
}

private static void removeFacesInWrongDimensions(MapPoiManager manager, Set<ServerPlayer> hosts) {
for (Poi poi : manager.getAllPois()) {
for (ServerPlayer host : hosts) {
if (poi.faces().contains(host.getUUID()) && poi.globalPos().dimension() != host.level().dimension()) {
manager.removeFace(poi.name(), host.getUUID());
}
}
}
}

private static Set<ServerPlayer> getHosts(final MinecraftServer server) {
return server.getPlayerList().getPlayers()
.stream()
.filter(SPECIAL_RULE)
.collect(Collectors.toSet());
}

private static void addNewFacesToPois(final MapPoiManager manager, final Set<ServerPlayer> hosts) {
for (ServerPlayer host : hosts) {
final BlockPos hostPosition = host.blockPosition();
manager.getEnabledPois()
.stream()
.filter(p -> p.globalPos().dimension() == host.level().dimension())
.min(Comparator.comparingDouble(p -> p.globalPos().pos().distSqr(hostPosition)))
.filter(p -> !p.faces().contains(host.getUUID()))
.ifPresent(p -> manager.addFace(p.name(), host.getUUID()));
}
}

private static void removeNoLongerHostingFaces(final MapPoiManager manager, final Set<ServerPlayer> currentHosts) {
for (Poi poi : manager.getAllPois()) {
for (UUID face : poi.faces()) {
if (currentHosts.stream().noneMatch(p -> p.getUUID().equals(face))) {
manager.removeFace(poi.name(), face);
}
}
}
}
}
43 changes: 43 additions & 0 deletions src/main/java/com/lovetropics/extras/data/poi/Poi.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.GlobalPos;
import net.minecraft.core.UUIDUtil;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.ExtraCodecs;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

public final class Poi {
public static final Codec<Poi> CODEC = RecordCodecBuilder.create(i -> i.group(
Expand All @@ -23,6 +28,22 @@ public final class Poi {
private final ResourceLocation resourceLocation;
private final GlobalPos globalPos;
private boolean enabled;
private List<UUID> faces;

public Poi(
String name,
Component description,
ResourceLocation resourceLocation,
GlobalPos globalPos,
boolean enabled,
List<UUID> faces) {
this.name = name;
this.description = description;
this.resourceLocation = resourceLocation;
this.globalPos = globalPos;
this.enabled = enabled;
this.faces = new ArrayList<>(faces);
}

public Poi(
String name,
Expand All @@ -35,6 +56,7 @@ public Poi(
this.resourceLocation = resourceLocation;
this.globalPos = globalPos;
this.enabled = enabled;
this.faces = new ArrayList<>();
}

//Use only the name for equals&hashCode. Maybe tiny bit risky but dupe handling is free
Expand Down Expand Up @@ -71,6 +93,23 @@ public boolean enabled() {
return enabled;
}

public List<UUID> faces() {
return List.copyOf(faces);
}

public boolean hasFaces() {
return !faces.isEmpty();
}

public Poi clearFaces() {
faces.clear();
return this;
}

public void addFace(UUID face) {
faces.add(face);
}

@Override
public String toString() {
return "Poi[" +
Expand All @@ -84,4 +123,8 @@ public String toString() {
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}

public void removeFace(final UUID face) {
faces.remove(face);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.lovetropics.extras.client.ClientMapPoiManager;
import com.lovetropics.extras.data.poi.Poi;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.network.NetworkEvent;

import java.util.function.Supplier;
Expand All @@ -14,7 +13,8 @@ public ClientboundPoiPacket(final FriendlyByteBuf input) {
input.readComponent(),
input.readResourceLocation(),
input.readGlobalPos(),
input.readBoolean()),
input.readBoolean(),
input.readList(FriendlyByteBuf::readUUID)),
input.readBoolean());
}

Expand All @@ -24,6 +24,7 @@ public void write(final FriendlyByteBuf output) {
output.writeResourceLocation(poi.resourceLocation());
output.writeGlobalPos(poi.globalPos());
output.writeBoolean(poi.enabled());
output.writeCollection(poi.faces(), FriendlyByteBuf::writeUUID);
output.writeBoolean(delete);
}

Expand Down

0 comments on commit 2d40371

Please sign in to comment.