Skip to content

Commit

Permalink
Draw faces!
Browse files Browse the repository at this point in the history
  • Loading branch information
bazke committed Oct 28, 2023
1 parent bd844e5 commit 7830bc9
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, Poi> POIS = new HashMap<>();
private static final Map<UUID, ResourceLocation> FACES = new HashMap<>();

public static void updatePoi(final Poi poi, boolean delete) {
if (delete) {
Expand All @@ -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();
}
}
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -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<UUID> 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
Expand Down
10 changes: 6 additions & 4 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,9 +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 boolean markSpecial = false;
final List<UUID> 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;
Expand Down Expand Up @@ -237,9 +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 boolean markSpecial = false;
final List<UUID> faces = List.of();

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

private static Stream<String> suggestGlobalPos(CommandContext<CommandSourceStack> ctx) {
Expand Down
69 changes: 42 additions & 27 deletions src/main/java/com/lovetropics/extras/data/poi/MapPoiManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,15 @@
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;
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.entity.player.Player;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import net.minecraft.world.level.saveddata.SavedData;
import net.minecraftforge.event.TickEvent;
Expand Down Expand Up @@ -87,53 +84,71 @@ public Set<Poi> 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<ServerPlayer> firstHost = event.getServer().getPlayerList().getPlayers()
final Set<ServerPlayer> 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<Poi> closestEnabledPoi = manager.getEnabledPois()
.stream()
.min(Comparator.comparingDouble(p -> p.globalPos().pos().distSqr(hostPosition)));
for (ServerPlayer host : hosts) {
final BlockPos hostPosition = host.blockPosition();
final Optional<Poi> 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();
}
Expand Down
32 changes: 24 additions & 8 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,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<Poi> CODEC = RecordCodecBuilder.create(i -> i.group(
Expand All @@ -16,29 +20,29 @@ 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;
private final Component description;
private final ResourceLocation resourceLocation;
private final GlobalPos globalPos;
private boolean enabled;
private boolean markSpecial;
private List<UUID> faces;

public Poi(
String name,
Component description,
ResourceLocation resourceLocation,
GlobalPos globalPos,
boolean enabled,
boolean markSpecial) {
List<UUID> 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
Expand Down Expand Up @@ -75,15 +79,23 @@ public boolean enabled() {
return enabled;
}

public boolean isMarkSpecial() {
return markSpecial;
public List<UUID> 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[" +
Expand All @@ -97,4 +109,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 @@ -14,7 +14,7 @@ public ClientboundPoiPacket(final FriendlyByteBuf input) {
input.readResourceLocation(),
input.readGlobalPos(),
input.readBoolean(),
input.readBoolean()),
input.readList(FriendlyByteBuf::readUUID)),
input.readBoolean());
}

Expand All @@ -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);
}

Expand Down

0 comments on commit 7830bc9

Please sign in to comment.