package net.minecraft.server.commands; import com.mojang.brigadier.CommandDispatcher; import java.util.Optional; import java.util.Set; import java.util.function.Consumer; import java.util.function.Function; import net.minecraft.ChatFormatting; import net.minecraft.commands.CommandBuildContext; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.commands.arguments.ColorArgument; import net.minecraft.commands.arguments.EntityArgument; import net.minecraft.commands.arguments.HexColorArgument; import net.minecraft.commands.arguments.ResourceLocationArgument; import net.minecraft.commands.arguments.WaypointArgument; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.ClickEvent; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.ComponentUtils; import net.minecraft.network.chat.HoverEvent; import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.ARGB; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.waypoints.Waypoint; import net.minecraft.world.waypoints.WaypointStyleAsset; import net.minecraft.world.waypoints.WaypointStyleAssets; import net.minecraft.world.waypoints.WaypointTransmitter; public class WaypointCommand { public static void register(CommandDispatcher dispatcher, CommandBuildContext buildContext) { dispatcher.register( Commands.literal("waypoint") .requires(Commands.hasPermission(2)) .then(Commands.literal("list").executes(commandContext -> listWaypoints(commandContext.getSource()))) .then( Commands.literal("modify") .then( Commands.argument("waypoint", EntityArgument.entity()) .then( Commands.literal("color") .then( Commands.argument("color", ColorArgument.color()) .executes( commandContext -> setWaypointColor( commandContext.getSource(), WaypointArgument.getWaypoint(commandContext, "waypoint"), ColorArgument.getColor(commandContext, "color") ) ) ) .then( Commands.literal("hex") .then( Commands.argument("color", HexColorArgument.hexColor()) .executes( commandContext -> setWaypointColor( commandContext.getSource(), WaypointArgument.getWaypoint(commandContext, "waypoint"), HexColorArgument.getHexColor(commandContext, "color") ) ) ) ) .then( Commands.literal("reset") .executes(commandContext -> resetWaypointColor(commandContext.getSource(), WaypointArgument.getWaypoint(commandContext, "waypoint"))) ) ) .then( Commands.literal("style") .then( Commands.literal("reset") .executes( commandContext -> setWaypointStyle( commandContext.getSource(), WaypointArgument.getWaypoint(commandContext, "waypoint"), WaypointStyleAssets.DEFAULT ) ) ) .then( Commands.literal("set") .then( Commands.argument("style", ResourceLocationArgument.id()) .executes( commandContext -> setWaypointStyle( commandContext.getSource(), WaypointArgument.getWaypoint(commandContext, "waypoint"), ResourceKey.create(WaypointStyleAssets.ROOT_ID, ResourceLocationArgument.getId(commandContext, "style")) ) ) ) ) ) ) ) ); } private static int setWaypointStyle(CommandSourceStack source, WaypointTransmitter waypoint, ResourceKey style) { mutateIcon(source, waypoint, icon -> icon.style = style); source.sendSuccess(() -> Component.translatable("commands.waypoint.modify.style"), false); return 0; } private static int setWaypointColor(CommandSourceStack source, WaypointTransmitter waypoint, ChatFormatting color) { mutateIcon(source, waypoint, icon -> icon.color = Optional.of(color.getColor())); source.sendSuccess(() -> Component.translatable("commands.waypoint.modify.color", Component.literal(color.getName()).withStyle(color)), false); return 0; } private static int setWaypointColor(CommandSourceStack source, WaypointTransmitter waypoint, Integer color) { mutateIcon(source, waypoint, icon -> icon.color = Optional.of(color)); source.sendSuccess( () -> Component.translatable("commands.waypoint.modify.color", Component.literal(String.format("%06X", ARGB.color(0, color))).withColor(color)), false ); return 0; } private static int resetWaypointColor(CommandSourceStack source, WaypointTransmitter waypoint) { mutateIcon(source, waypoint, icon -> icon.color = Optional.empty()); source.sendSuccess(() -> Component.translatable("commands.waypoint.modify.color.reset"), false); return 0; } private static int listWaypoints(CommandSourceStack source) { ServerLevel serverLevel = source.getLevel(); Set set = serverLevel.getWaypointManager().transmitters(); String string = serverLevel.dimension().location().toString(); if (set.isEmpty()) { source.sendSuccess(() -> Component.translatable("commands.waypoint.list.empty", string), false); return 0; } else { Component component = ComponentUtils.formatList( set.stream() .map( waypointTransmitter -> { if (waypointTransmitter instanceof LivingEntity livingEntity) { BlockPos blockPos = livingEntity.blockPosition(); return livingEntity.getFeedbackDisplayName() .copy() .withStyle( style -> style.withClickEvent( new ClickEvent.SuggestCommand("/execute in " + string + " run tp @s " + blockPos.getX() + " " + blockPos.getY() + " " + blockPos.getZ()) ) .withHoverEvent(new HoverEvent.ShowText(Component.translatable("chat.coordinates.tooltip"))) .withColor((Integer)waypointTransmitter.waypointIcon().color.orElse(-1)) ); } else { return Component.literal(waypointTransmitter.toString()); } } ) .toList(), Function.identity() ); source.sendSuccess(() -> Component.translatable("commands.waypoint.list.success", set.size(), string, component), false); return set.size(); } } private static void mutateIcon(CommandSourceStack source, WaypointTransmitter waypoint, Consumer mutator) { ServerLevel serverLevel = source.getLevel(); serverLevel.getWaypointManager().untrackWaypoint(waypoint); mutator.accept(waypoint.waypointIcon()); serverLevel.getWaypointManager().trackWaypoint(waypoint); } }