From 7830bc9d73e02cd2ce1f45516f3371bd65b0bb24 Mon Sep 17 00:00:00 2001 From: bazke Date: Sat, 28 Oct 2023 20:04:03 +0200 Subject: [PATCH] Draw faces! --- .../extras/client/ClientMapPoiManager.java | 25 +++++++ .../extras/client/screen/map/PoiButton.java | 24 ++++++- .../extras/command/PoiCommand.java | 10 +-- .../extras/data/poi/MapPoiManager.java | 69 +++++++++++-------- .../com/lovetropics/extras/data/poi/Poi.java | 32 ++++++--- .../extras/network/ClientboundPoiPacket.java | 4 +- 6 files changed, 121 insertions(+), 43 deletions(-) diff --git a/src/main/java/com/lovetropics/extras/client/ClientMapPoiManager.java b/src/main/java/com/lovetropics/extras/client/ClientMapPoiManager.java index 4dbf8a41..3a957d27 100644 --- a/src/main/java/com/lovetropics/extras/client/ClientMapPoiManager.java +++ b/src/main/java/com/lovetropics/extras/client/ClientMapPoiManager.java @@ -4,19 +4,26 @@ 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.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 { private static final Map POIS = new HashMap<>(); + private static final Map FACES = new HashMap<>(); public static void updatePoi(final Poi poi, boolean delete) { if (delete) { @@ -37,5 +44,23 @@ public static void openScreen(final Player player) { @SubscribeEvent public static void onLoggingOut(final ClientPlayerNetworkEvent.LoggingOut event) { POIS.clear(); + FACES.clear(); + } + + public static ResourceLocation getFace(final UUID uuid) { + return FACES.getOrDefault(uuid, getPlayerSkinOrDefault(uuid)); + } + + private static ResourceLocation getPlayerSkinOrDefault(final UUID uuid) { + //TODO deal with players changing skin somehow? + final ClientPacketListener connection = Minecraft.getInstance().getConnection(); + if (connection == null) { + return DefaultPlayerSkin.getDefaultSkin(uuid); + } + final PlayerInfo playerInfo = connection.getPlayerInfo(uuid); + if (playerInfo == null) { + return DefaultPlayerSkin.getDefaultSkin(uuid); + } + return playerInfo.getSkinLocation(); } } diff --git a/src/main/java/com/lovetropics/extras/client/screen/map/PoiButton.java b/src/main/java/com/lovetropics/extras/client/screen/map/PoiButton.java index 0c1212f2..04131171 100644 --- a/src/main/java/com/lovetropics/extras/client/screen/map/PoiButton.java +++ b/src/main/java/com/lovetropics/extras/client/screen/map/PoiButton.java @@ -1,16 +1,26 @@ 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 { @@ -94,9 +104,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); - if (poi.isMarkSpecial()) { - graphics.blit(SPECIAL_MARKER, getX() + BORDER_SIZE + HALF_ICON_SIZE, getY() + BORDER_SIZE + HALF_ICON_SIZE, zOffset, 0.0f, 0.0f, HALF_ICON_SIZE, HALF_ICON_SIZE, HALF_ICON_SIZE, HALF_ICON_SIZE); + + List faces = new ArrayList<>(); + faces.addAll(poi.faces()); + faces.addAll(poi.faces()); + faces.addAll(poi.faces()); //TODO just for testing more than 1 face + graphics.pose().pushPose(); + graphics.pose().translate(0.0f, 0.0f, zOffset); + for (int i = 0; i < faces.size(); i++) { + UUID uuid = faces.get(i); + ResourceLocation face = ClientMapPoiManager.getFace(uuid); + PlayerFaceRenderer.draw(graphics, face, getX() + BORDER_SIZE + i * 4 + i, getY() + ICON_SIZE, ICON_SIZE / 4); } + graphics.pose().popPose(); } @Override diff --git a/src/main/java/com/lovetropics/extras/command/PoiCommand.java b/src/main/java/com/lovetropics/extras/command/PoiCommand.java index 798d004c..7962ccd3 100644 --- a/src/main/java/com/lovetropics/extras/command/PoiCommand.java +++ b/src/main/java/com/lovetropics/extras/command/PoiCommand.java @@ -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; @@ -154,9 +156,9 @@ private static int addWithDefaults(CommandContext 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 boolean markSpecial = false; + final List faces = List.of(); - final Poi newPoi = new Poi(name, description, icon, globalPos, enabled, markSpecial); + 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; @@ -237,9 +239,9 @@ private static Poi createPoiFromCtx(CommandContext 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 boolean markSpecial = false; + final List faces = List.of(); - return new Poi(name, description, icon, globalPos, enabled, markSpecial); + return new Poi(name, description, icon, globalPos, enabled, faces); } private static Stream suggestGlobalPos(CommandContext ctx) { diff --git a/src/main/java/com/lovetropics/extras/data/poi/MapPoiManager.java b/src/main/java/com/lovetropics/extras/data/poi/MapPoiManager.java index 6a7bae57..01a14540 100644 --- a/src/main/java/com/lovetropics/extras/data/poi/MapPoiManager.java +++ b/src/main/java/com/lovetropics/extras/data/poi/MapPoiManager.java @@ -3,10 +3,8 @@ import com.lovetropics.extras.LTExtras; import com.lovetropics.extras.network.ClientboundPoiPacket; import com.lovetropics.extras.network.LTExtrasNetwork; -import com.lovetropics.extras.schedule.StreamSchedule; import com.lovetropics.lib.permission.PermissionsApi; import com.lovetropics.lib.permission.role.RoleOverrideType; -import com.lovetropics.lib.permission.role.RoleReader; import com.mojang.serialization.Codec; import net.minecraft.Util; import net.minecraft.core.BlockPos; @@ -14,7 +12,6 @@ import net.minecraft.nbt.NbtOps; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.levelgen.structure.BoundingBox; import net.minecraft.world.level.saveddata.SavedData; import net.minecraftforge.event.TickEvent; @@ -87,53 +84,71 @@ public Set getEnabledPois() { @SubscribeEvent public static void onServerTick(TickEvent.ServerTickEvent event) { - if (event.getServer().getTickCount() % 20 != 0) { + if (event.phase == TickEvent.Phase.START && event.getServer().getTickCount() % 20 != 0) { return; } final MapPoiManager manager = MapPoiManager.get(event.getServer()); - final Optional firstHost = event.getServer().getPlayerList().getPlayers() + final Set hosts = event.getServer().getPlayerList().getPlayers() .stream() - .filter(SPECIAL_RULE) - .findFirst(); + .filter(DEBUG_SPECIAL_RULE) + .collect(Collectors.toSet()); + - if (firstHost.isEmpty()) { - manager.clearSpecials(); + if (hosts.isEmpty()) { + manager.clearFaces(); return; } - final ServerPlayer hostPlayer = firstHost.get(); - final BlockPos hostPosition = hostPlayer.blockPosition(); - final Optional closestEnabledPoi = manager.getEnabledPois() - .stream() - .min(Comparator.comparingDouble(p -> p.globalPos().pos().distSqr(hostPosition))); + for (ServerPlayer host : hosts) { + final BlockPos hostPosition = host.blockPosition(); + final Optional closestEnabledPoi = manager.getEnabledPois() + .stream() + .min(Comparator.comparingDouble(p -> p.globalPos().pos().distSqr(hostPosition))); - if (closestEnabledPoi.isEmpty()) { - return; - } - final Poi nearestPoi = closestEnabledPoi.get(); - if (nearestPoi.isMarkSpecial() || hostPlayer.level().dimension() != closestEnabledPoi.get().globalPos().dimension()) { - return; + if (closestEnabledPoi.isEmpty()) { + return; + } + final Poi nearestPoi = closestEnabledPoi.get(); + + if (!nearestPoi.faces().contains(host.getUUID()) && host.level().dimension() == closestEnabledPoi.get().globalPos().dimension()) { + manager.addFace(nearestPoi.name(), host.getUUID()); + } } - manager.markSpecial(nearestPoi.name()); + //TODO consider the case: 2 active hosts. one host is removed -> what happens? iterate all POIs and check if face is host? + //maybe something like below? + for (Poi poi : manager.getAllPois()) { + for (UUID face : poi.faces()) { + if (hosts.stream().noneMatch(p -> p.getUUID().equals(face))) { + manager.removeFace(poi.name(), face); + } + } + } } - public void markSpecial(String name) { - clearSpecials(); + 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) { - poi.setMarkSpecial(true); + poi.addFace(face); LTExtrasNetwork.CHANNEL.send(PacketDistributor.ALL.noArg(), new ClientboundPoiPacket(poi, false)); } setDirty(); } - public void clearSpecials() { + public void clearFaces() { pois.values() .stream() - .filter(Poi::isMarkSpecial) - .map(p -> p.setMarkSpecial(false)) + .filter(Poi::hasFaces) + .map(Poi::clearFaces) .forEach(p -> LTExtrasNetwork.CHANNEL.send(PacketDistributor.ALL.noArg(), new ClientboundPoiPacket(p, false))); setDirty(); } diff --git a/src/main/java/com/lovetropics/extras/data/poi/Poi.java b/src/main/java/com/lovetropics/extras/data/poi/Poi.java index bd3ebea9..07dcb145 100644 --- a/src/main/java/com/lovetropics/extras/data/poi/Poi.java +++ b/src/main/java/com/lovetropics/extras/data/poi/Poi.java @@ -3,11 +3,15 @@ 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.util.ArrayList; +import java.util.List; import java.util.Objects; +import java.util.UUID; public final class Poi { public static final Codec CODEC = RecordCodecBuilder.create(i -> i.group( @@ -16,7 +20,7 @@ public final class Poi { ResourceLocation.CODEC.fieldOf("resourceLocation").forGetter(Poi::resourceLocation), GlobalPos.CODEC.fieldOf("blockPos").forGetter(Poi::globalPos), Codec.BOOL.fieldOf("enabled").forGetter(Poi::enabled), - Codec.BOOL.fieldOf("markSpecial").forGetter(Poi::isMarkSpecial) + Codec.list(UUIDUtil.CODEC).fieldOf("faces").forGetter(Poi::faces) ).apply(i, Poi::new)); private final String name; @@ -24,7 +28,7 @@ public final class Poi { private final ResourceLocation resourceLocation; private final GlobalPos globalPos; private boolean enabled; - private boolean markSpecial; + private List faces; public Poi( String name, @@ -32,13 +36,13 @@ public Poi( ResourceLocation resourceLocation, GlobalPos globalPos, boolean enabled, - boolean markSpecial) { + List faces) { this.name = name; this.description = description; this.resourceLocation = resourceLocation; this.globalPos = globalPos; this.enabled = enabled; - this.markSpecial = markSpecial; + this.faces = new ArrayList<>(faces); } //Use only the name for equals&hashCode. Maybe tiny bit risky but dupe handling is free @@ -75,15 +79,23 @@ public boolean enabled() { return enabled; } - public boolean isMarkSpecial() { - return markSpecial; + public List faces() { + return faces; } - public Poi setMarkSpecial(boolean markSpecial) { - this.markSpecial = markSpecial; + 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[" + @@ -97,4 +109,8 @@ public String toString() { public void setEnabled(boolean enabled) { this.enabled = enabled; } + + public void removeFace(final UUID face) { + faces.remove(face); + } } diff --git a/src/main/java/com/lovetropics/extras/network/ClientboundPoiPacket.java b/src/main/java/com/lovetropics/extras/network/ClientboundPoiPacket.java index f158faec..3382ccb2 100644 --- a/src/main/java/com/lovetropics/extras/network/ClientboundPoiPacket.java +++ b/src/main/java/com/lovetropics/extras/network/ClientboundPoiPacket.java @@ -14,7 +14,7 @@ public ClientboundPoiPacket(final FriendlyByteBuf input) { input.readResourceLocation(), input.readGlobalPos(), input.readBoolean(), - input.readBoolean()), + input.readList(FriendlyByteBuf::readUUID)), input.readBoolean()); } @@ -24,7 +24,7 @@ public void write(final FriendlyByteBuf output) { output.writeResourceLocation(poi.resourceLocation()); output.writeGlobalPos(poi.globalPos()); output.writeBoolean(poi.enabled()); - output.writeBoolean(poi.isMarkSpecial()); + output.writeCollection(poi.faces(), FriendlyByteBuf::writeUUID); output.writeBoolean(delete); }