Feat & Rebuild: Add @PlayerName Reminder in chat.

This commit is contained in:
APairOfMoons 2026-07-06 01:06:30 +08:00
parent 84ee531015
commit 35b829c3db
5 changed files with 135 additions and 14 deletions

View File

@ -1,6 +1,8 @@
package cn.revaria.chatplus;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.minecraft.server.MinecraftServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -12,12 +14,20 @@ public class ChatPlus implements ModInitializer {
// That way, it's clear which mod wrote info, warnings, and errors.
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
private static MinecraftServer server;
public static MinecraftServer getServer() {
return server;
}
@Override
public void onInitialize() {
// This code runs as soon as Minecraft is in a mod-load-ready state.
// However, some things (like resources) may still be uninitialized.
// Proceed with mild caution.
ServerLifecycleEvents.SERVER_STARTING.register(server -> ChatPlus.server = server);
LOGGER.info("Chat Plus loaded");
}
}

View File

@ -0,0 +1,9 @@
package cn.revaria.chatplus.format.formats;
import cn.revaria.chatplus.format.ChatFormat;
import net.minecraft.network.chat.MutableComponent;
public interface ChatInsertFormat extends ChatFormat {
MutableComponent getInsertComponent();
ChatInsertFormat copy();
}

View File

@ -1,10 +1,11 @@
package cn.revaria.chatplus.format.formats;
package cn.revaria.chatplus.format.formats.insertformats;
import cn.revaria.chatplus.format.ChatFormat;
import cn.revaria.chatplus.format.ChatFormatType;
import cn.revaria.chatplus.format.formats.ChatInsertFormat;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.world.item.ItemStack;
public class ChatInsertItemFormat implements ChatFormat {
public class ChatInsertItemFormat implements ChatInsertFormat {
private final ItemStack item;
@ -21,6 +22,10 @@ public class ChatInsertItemFormat implements ChatFormat {
return item;
}
@Override
public MutableComponent getInsertComponent() {
return item.getDisplayName().copy();
}
@Override
public int startingIndex() {
return startingIndex;

View File

@ -0,0 +1,53 @@
package cn.revaria.chatplus.format.formats.insertformats;
import cn.revaria.chatplus.format.ChatFormatType;
import cn.revaria.chatplus.format.formats.ChatInsertFormat;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.TextColor;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
public class ChatInsertReminderFormat implements ChatInsertFormat {
private final ServerPlayer aimPlayer;
private boolean soundPlayed = false;
private final int startingIndex;
private final ChatFormatType formatType = ChatFormatType.INSERT;
public ChatInsertReminderFormat(int startingIndex, ServerPlayer aim) {
this.startingIndex = startingIndex;
this.aimPlayer = aim;
}
public ServerPlayer getAimPlayer() {
return aimPlayer;
}
@Override
public MutableComponent getInsertComponent() {
if (!soundPlayed) {
soundPlayed = true;
aimPlayer.playSound(SoundEvents.EXPERIENCE_ORB_PICKUP, 3, 1);
}
return Component.literal("@").append(aimPlayer.getDisplayName())
.withColor(TextColor.GREEN)
.withStyle(ChatFormatting.BOLD);
}
@Override
public int startingIndex() {
return startingIndex;
}
@Override
public ChatFormatType formatType() {
return formatType;
}
@Override
public ChatInsertFormat copy() {
return new ChatInsertReminderFormat(startingIndex, aimPlayer);
}
}

View File

@ -2,17 +2,20 @@ package cn.revaria.chatplus.util;
#if MC_VER <= MC_1_20
import net.minecraft.network.chat.contents.LiteralContents;
#else
#endif
import cn.revaria.chatplus.ChatPlus;
import cn.revaria.chatplus.format.formats.ChatInsertFormat;
import cn.revaria.chatplus.format.formats.insertformats.ChatInsertReminderFormat;
import cn.revaria.chatplus.format.ChatFormat;
import cn.revaria.chatplus.format.ChatFormatType;
import cn.revaria.chatplus.format.formats.ChatColorFormat;
import cn.revaria.chatplus.format.formats.ChatFontFormat;
import cn.revaria.chatplus.format.formats.ChatInsertItemFormat;
import cn.revaria.chatplus.format.formats.insertformats.ChatInsertItemFormat;
import cn.revaria.chatplus.format.formats.ChatResetFormat;
#endif
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import java.util.*;
@ -69,7 +72,7 @@ public class TextStyleFormatter {
ArrayList<ChatFormat> formatsList = formatsTable.get(i);
if (formatsList.getFirst() instanceof ChatInsertItemFormat insertItem) {
if (formatsList.getFirst() instanceof ChatInsertFormat insertFormat) {
if (i > 0) {
finalText.append(composeChatComponent(
@ -79,7 +82,7 @@ public class TextStyleFormatter {
));
}
finalText.append(insertItem.getItem().getDisplayName());
finalText.append(insertFormat.getInsertComponent());
startIndex = i;
continue;
@ -152,6 +155,9 @@ public class TextStyleFormatter {
StringBuilder textBuilder = new StringBuilder();
MinecraftServer server = ChatPlus.getServer();
String[] playerNames = server.getPlayerList().getPlayerNamesArray();
String itemRegex = "\\[item(?:=([1-9]))?\\]";
Pattern itemPattern = Pattern.compile(itemRegex);
Matcher matcher = itemPattern.matcher(sourceRawText);
@ -268,21 +274,42 @@ public class TextStyleFormatter {
}
}
if ((character >= '0' && character <= '9')
|| (character >= 'a' && character <= 'z')
|| (character >= 'A' && character <= 'Z')
|| character == '_') {
String insertName = matchPlayerName(sourceRawText, playerNames, i);
if (insertName != null) {
if (!formatsTableOutput.containsKey(currentIndex)) {
formatsTableOutput.put(currentIndex, new ArrayList<>());
}
formatsTableOutput.get(currentIndex).add(new ChatInsertReminderFormat(
currentIndex,
server.getPlayerList().getPlayer(insertName)
));
i += insertName.length() - 1;
continue;
}
}
textBuilder.append(character);
}
formatsTableOutput.forEach((i, formatsList) -> {
boolean containsResetFormat = false;
ChatInsertItemFormat containedInsertItemFormat = null;
ChatInsertFormat containedInsertFormat = null;
for (ChatFormat format : formatsList) {
if (format.formatType() == ChatFormatType.RESET) {
containsResetFormat = true;
break;
}
if (format instanceof ChatInsertItemFormat insertItemFormat && format.formatType() == ChatFormatType.INSERT) {
containedInsertItemFormat = insertItemFormat.copy();
if (format instanceof ChatInsertFormat insertFormat && format.formatType() == ChatFormatType.INSERT) {
containedInsertFormat = insertFormat.copy();
break;
}
}
@ -291,12 +318,29 @@ public class TextStyleFormatter {
formatsList.clear();
formatsList.add(new ChatResetFormat(i));
}
if (containedInsertItemFormat != null) {
if (containedInsertFormat != null) {
formatsList.clear();
formatsList.add(containedInsertItemFormat);
formatsList.add(containedInsertFormat);
}
});
return textBuilder.toString();
}
private static String matchPlayerName(String chatText, String[] playerNames, int startingIndex) {
String aimName = null;
for (String name : playerNames) {
if (chatText.startsWith(name, startingIndex)) {
if (aimName == null || aimName.length() < name.length()) {
aimName = name;
}
}
}
return aimName;
}
}