mirror of
https://github.com/CPTProgrammer/ChatPlus.git
synced 2026-09-19 23:23:38 +08:00
Rewrite entire project for v1.0.0
- Remove legacy code and replace with new implementation - Update version to 1.0.0 - Adjust build configurations and dependencies.
This commit is contained in:
@@ -5,10 +5,12 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ChatPlus implements ModInitializer {
|
||||
public static final String MOD_ID = "chat-plus";
|
||||
|
||||
// This logger is used to write text to the console and the log file.
|
||||
// It is considered best practice to use your mod id as the logger's name.
|
||||
// That way, it's clear which mod wrote info, warnings, and errors.
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger("Chat Plus");
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
@@ -16,6 +18,6 @@ public class ChatPlus implements ModInitializer {
|
||||
// However, some things (like resources) may still be uninitialized.
|
||||
// Proceed with mild caution.
|
||||
|
||||
LOGGER.info("§2ChatPlus Loaded!");
|
||||
LOGGER.info("Chat Plus loaded");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package cn.revaria.chatplus.mixin;
|
||||
|
||||
#if MC_VER <= MC_1_19
|
||||
import net.minecraft.server.filter.FilteredMessage;
|
||||
import net.minecraft.util.registry.RegistryKey;
|
||||
#endif
|
||||
|
||||
import cn.revaria.chatplus.plugin.annotation.DisableIfModsLoaded;
|
||||
import net.minecraft.network.message.MessageType;
|
||||
import net.minecraft.network.message.SignedMessage;
|
||||
import net.minecraft.server.PlayerManager;
|
||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
import static cn.revaria.chatplus.util.TextStyleFormatter.applyStyle;
|
||||
|
||||
@DisableIfModsLoaded("styledchat")
|
||||
@Mixin(ServerPlayNetworkHandler.class)
|
||||
public abstract class ChatMixin {
|
||||
@Redirect(method = "handleDecoratedMessage", at = @At(value = "INVOKE", target =
|
||||
#if MC_VER <= MC_1_19
|
||||
"Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/server/filter/FilteredMessage;Lnet/minecraft/server/network/ServerPlayerEntity;Lnet/minecraft/util/registry/RegistryKey;)V"
|
||||
#else
|
||||
"Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/network/message/SignedMessage;Lnet/minecraft/server/network/ServerPlayerEntity;Lnet/minecraft/network/message/MessageType$Parameters;)V"
|
||||
#endif
|
||||
))
|
||||
#if MC_VER <= MC_1_19
|
||||
private void replaceText(PlayerManager instance, FilteredMessage<SignedMessage> message, ServerPlayerEntity sender, RegistryKey<MessageType> typeKey) {
|
||||
var newMessage = new FilteredMessage<>(
|
||||
message.raw().withUnsigned(applyStyle(message.raw().getContent(), sender)),
|
||||
message.filtered() != null ? message.filtered().withUnsigned(applyStyle(message.filtered().getContent(), sender)) : null
|
||||
);
|
||||
instance.broadcast(newMessage, sender, typeKey);
|
||||
}
|
||||
#else
|
||||
private void replaceText(PlayerManager instance, SignedMessage message, ServerPlayerEntity sender, MessageType.Parameters params) {
|
||||
instance.broadcast(message.withUnsignedContent(applyStyle(message.getContent(), sender)), sender, params);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
package cn.revaria.chatplus.mixin;
|
||||
|
||||
import net.minecraft.MinecraftVersion;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.ClientConnection;
|
||||
import net.minecraft.network.message.*;
|
||||
import net.minecraft.network.packet.c2s.play.ChatMessageC2SPacket;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.filter.FilteredMessage;
|
||||
import net.minecraft.server.network.ConnectedClientData;
|
||||
import net.minecraft.server.network.ServerCommonNetworkHandler;
|
||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.MutableText;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.StringHelper;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Mixin(ServerPlayNetworkHandler.class)
|
||||
public abstract class MixinChat extends ServerCommonNetworkHandler {
|
||||
public MixinChat(MinecraftServer server, ClientConnection connection, ConnectedClientData clientData) {
|
||||
super(server, connection, clientData);
|
||||
}
|
||||
|
||||
@Final
|
||||
@Shadow
|
||||
private MessageChainTaskQueue messageChainTaskQueue;
|
||||
|
||||
@Shadow
|
||||
public ServerPlayerEntity player;
|
||||
|
||||
// @Shadow protected abstract Optional<LastSeenMessageList> validateMessage(LastSeenMessageList.Acknowledgment acknowledgment);
|
||||
|
||||
@Shadow protected abstract Optional<LastSeenMessageList> validateAcknowledgment(LastSeenMessageList.Acknowledgment acknowledgment);
|
||||
|
||||
@Shadow protected abstract SignedMessage getSignedMessage(ChatMessageC2SPacket packet, LastSeenMessageList lastSeenMessages) throws MessageChain.MessageChainException;
|
||||
|
||||
@Shadow protected abstract void handleMessageChainException(MessageChain.MessageChainException exception);
|
||||
|
||||
@Shadow protected abstract void handleDecoratedMessage(SignedMessage message);
|
||||
|
||||
@Shadow protected abstract CompletableFuture<FilteredMessage> filterText(String text);
|
||||
|
||||
@Inject(method = "onChatMessage", at = @At("HEAD"), cancellable = true)
|
||||
public void onChatMessage(ChatMessageC2SPacket packet, CallbackInfo ci) {
|
||||
// LOGGER.info("CHAT_MESSAGE: " + packet.chatMessage());
|
||||
|
||||
if (hasIllegalCharacter(packet.chatMessage())) {
|
||||
disconnect(Text.translatable("multiplayer.disconnect.illegal_characters"));
|
||||
} else {
|
||||
Optional<LastSeenMessageList> optional = this.validateAcknowledgment(packet.acknowledgment());
|
||||
if (optional.isPresent()) {
|
||||
if (!packet.chatMessage().startsWith("/")){
|
||||
|
||||
String changedMessage = packet.chatMessage().replace('&', '§');
|
||||
String regex = "\\[item(?:=([1-9]))?\\]";
|
||||
String[] messages = changedMessage.split(regex, -1);
|
||||
Deque<Integer> itemDeque = new ArrayDeque<>();
|
||||
|
||||
Matcher matcher = Pattern.compile(regex).matcher(changedMessage);
|
||||
while (matcher.find()){
|
||||
String digit = matcher.group(1);
|
||||
if (digit == null){
|
||||
itemDeque.addLast(-1);
|
||||
}else {
|
||||
itemDeque.addLast(Integer.parseInt(digit));
|
||||
}
|
||||
}
|
||||
|
||||
MutableText changedText = Text.empty();
|
||||
for (String message : messages) {
|
||||
changedText.append(Text.of(message));
|
||||
if (!itemDeque.isEmpty()) {
|
||||
ItemStack itemStack;
|
||||
if (itemDeque.getFirst() == -1) {
|
||||
itemStack = player.getMainHandStack();
|
||||
} else {
|
||||
itemStack = player.getInventory().getStack(itemDeque.getFirst() - 1);
|
||||
}
|
||||
changedText.append(itemStack.toHoverableText());
|
||||
itemDeque.removeFirst();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
SignedMessage signedMessage = getSignedMessage(packet, (LastSeenMessageList) optional.get());
|
||||
server.getPlayerManager().broadcast(signedMessage.withUnsignedContent(
|
||||
changedText
|
||||
), player, MessageType.params(MessageType.CHAT, player));
|
||||
|
||||
// Compatible with mod "Discord Integration"
|
||||
try {
|
||||
Class<?> DiscordIntegrationMod = Class.forName("de.erdbeerbaerlp.dcintegration.architectury.DiscordIntegrationMod");
|
||||
Method handleChatMessage = DiscordIntegrationMod.getMethod("handleChatMessage", SignedMessage.class, ServerPlayerEntity.class);
|
||||
handleChatMessage.invoke(null, signedMessage.withUnsignedContent(changedText), player);
|
||||
} catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException |
|
||||
IllegalAccessException ignored) { }
|
||||
|
||||
// Compatible with mod "Dynmap"
|
||||
String[] minecraftVersion = MinecraftVersion.CURRENT.getName().split("\\.");
|
||||
int minecraftPatchVersion = minecraftVersion.length == 3 ? Integer.parseInt(minecraftVersion[2]) : 0;
|
||||
for (int i = minecraftPatchVersion; i >= 0; i--){
|
||||
String version = minecraftVersion[0] + "." + minecraftVersion[1] + (i == 0 ? "" : ("." + i));
|
||||
try {
|
||||
/*
|
||||
Warning: Using reflection can make the code harder to maintain, debug, and understand.
|
||||
Statement: DynmapMod.plugin.chathandler.handleChat()
|
||||
*/
|
||||
Class<?> DynmapMod = Class.forName("org.dynmap.fabric_" + version.replaceAll("\\.", "_") + ".DynmapMod");
|
||||
Field pluginField = DynmapMod.getField("plugin");
|
||||
Object plugin = pluginField.get(null);
|
||||
Class<?> pluginClass = plugin.getClass();
|
||||
Field chatHandlerField = pluginClass.getDeclaredField("chathandler");
|
||||
chatHandlerField.setAccessible(true);
|
||||
Object chatHandler = chatHandlerField.get(plugin);
|
||||
Class<?> chatHandlerClass = chatHandler.getClass();
|
||||
Method handleChat = chatHandlerClass.getMethod("handleChat", ServerPlayerEntity.class, String.class);
|
||||
handleChat.invoke(chatHandler, player, signedMessage.withUnsignedContent(changedText).getContent().getString());
|
||||
break;
|
||||
} catch (ClassNotFoundException | NoSuchMethodException | NoSuchFieldException | NullPointerException |
|
||||
IllegalAccessException | InvocationTargetException ignored) { }
|
||||
}
|
||||
|
||||
} catch (MessageChain.MessageChainException e) {
|
||||
handleMessageChainException(e);
|
||||
}
|
||||
} else {
|
||||
this.server.submit(() -> {
|
||||
SignedMessage signedMessage;
|
||||
try {
|
||||
signedMessage = this.getSignedMessage(packet, optional.get());
|
||||
} catch (MessageChain.MessageChainException var6) {
|
||||
handleMessageChainException(var6);
|
||||
return;
|
||||
}
|
||||
|
||||
CompletableFuture<FilteredMessage> completableFuture = filterText(signedMessage.getSignedContent());
|
||||
Text decoratedMessage = this.server.getMessageDecorator().decorate(this.player, signedMessage.getContent());
|
||||
messageChainTaskQueue.append(completableFuture, filteredMessage -> {
|
||||
SignedMessage message = signedMessage.withUnsignedContent(decoratedMessage).withFilterMask(filteredMessage.mask());
|
||||
this.handleDecoratedMessage(message);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ci.cancel();
|
||||
}
|
||||
|
||||
private static boolean hasIllegalCharacter(String message) {
|
||||
for(int i = 0; i < message.length(); ++i) {
|
||||
if (!StringHelper.isValidChar(message.charAt(i))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package cn.revaria.chatplus.mixin.compat;
|
||||
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import com.llamalad7.mixinextras.sugar.ref.LocalRef;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.Text;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Pseudo;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import static cn.revaria.chatplus.util.TextStyleFormatter.applyStyle;
|
||||
|
||||
@Pseudo
|
||||
@Mixin(targets =
|
||||
#if MC_VER <= MC_1_19
|
||||
"org.dynmap.fabric_1_19.DynmapPlugin$ChatHandler"
|
||||
#elif MC_VER <= MC_1_19_1
|
||||
"org.dynmap.fabric_1_19_1.DynmapPlugin$ChatHandler"
|
||||
#elif MC_VER <= MC_1_19_3
|
||||
{"org.dynmap.fabric_1_19_3.DynmapPlugin$ChatHandler", "org.dynmap.fabric_1_19_4.DynmapPlugin$ChatHandler"}
|
||||
#elif MC_VER <= MC_1_20
|
||||
{"org.dynmap.fabric_1_20.DynmapPlugin$ChatHandler", "org.dynmap.fabric_1_20_2.DynmapPlugin$ChatHandler"}
|
||||
#elif MC_VER <= MC_1_20_3
|
||||
{"org.dynmap.fabric_1_20_4.DynmapPlugin$ChatHandler", "org.dynmap.fabric_1_20_6.DynmapPlugin$ChatHandler"}
|
||||
#elif MC_VER <= MC_1_21
|
||||
{
|
||||
"org.dynmap.fabric_1_21.DynmapPlugin$ChatHandler",
|
||||
"org.dynmap.fabric_1_21_1.DynmapPlugin$ChatHandler",
|
||||
"org.dynmap.fabric_1_21_3.DynmapPlugin$ChatHandler",
|
||||
"org.dynmap.fabric_1_21_5.DynmapPlugin$ChatHandler"
|
||||
}
|
||||
#endif
|
||||
)
|
||||
public abstract class DynmapMixin {
|
||||
@Inject(method = "handleChat", at = @At("HEAD"), remap = false)
|
||||
private void modifyMessage(ServerPlayerEntity player, String message, CallbackInfo ci, @Local(argsOnly = true) LocalRef<String> messageRef) {
|
||||
messageRef.set(applyStyle(Text.of(message), player).getString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package cn.revaria.chatplus.mixin.compat;
|
||||
|
||||
import eu.pb4.placeholders.api.PlaceholderContext;
|
||||
import eu.pb4.styledchat.StyledChatUtils;
|
||||
import net.minecraft.text.Text;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Pseudo;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import static cn.revaria.chatplus.util.TextStyleFormatter.applyStyle;
|
||||
|
||||
@Pseudo
|
||||
@Mixin(StyledChatUtils.class)
|
||||
public abstract class StyledChatMixin {
|
||||
@Inject(method = "formatFor(Leu/pb4/placeholders/api/PlaceholderContext;Ljava/lang/String;)Lnet/minecraft/text/Text;", at = @At("RETURN"), cancellable = true)
|
||||
private static void modifyText(PlaceholderContext context, String input, CallbackInfoReturnable<Text> cir) {
|
||||
cir.setReturnValue(applyStyle(cir.getReturnValue(), context.player()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package cn.revaria.chatplus.plugin;
|
||||
|
||||
import cn.revaria.chatplus.plugin.annotation.DisableIfModsLoaded;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class MixinConfigPlugin implements IMixinConfigPlugin {
|
||||
@Override
|
||||
public void onLoad(String mixinPackage) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRefMapperConfig() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
||||
try {
|
||||
Class<?> mixinClass = Class.forName(mixinClassName);
|
||||
DisableIfModsLoaded annotation = mixinClass.getAnnotation(DisableIfModsLoaded.class);
|
||||
if (annotation != null) {
|
||||
return Arrays.stream(annotation.value()).noneMatch(modId -> FabricLoader.getInstance().isModLoaded(modId));
|
||||
}
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getMixins() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package cn.revaria.chatplus.plugin.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Conditionally disables the annotated mixin when specified mods are loaded.
|
||||
*
|
||||
* <p>When applied, the mixin config plugin should disable the annotated class
|
||||
* if any mod ID in the value list is present in the runtime environment.</p>
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DisableIfModsLoaded {
|
||||
String[] value();
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package cn.revaria.chatplus.util;
|
||||
|
||||
#if MC_VER <= MC_1_20
|
||||
import net.minecraft.text.LiteralTextContent;
|
||||
#else
|
||||
import net.minecraft.text.PlainTextContent.Literal;
|
||||
#endif
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.MutableText;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class TextStyleFormatter {
|
||||
public static int MAIN_HAND = -1; // Must be smaller than or equal to 0
|
||||
|
||||
/**
|
||||
* Processes text styling with two key functions:
|
||||
* <p>
|
||||
* 1. Replaces {@code &} with {@code §}, using {@code &&} to escape literal {@code &}<br>
|
||||
* 2. Substitutes {@code [item]} with main-hand item hover text and {@code [item=N]} with Nth slot's hover text
|
||||
* </p>
|
||||
* Recursively processes nested text components.
|
||||
*
|
||||
* @param sourceText Original text to process (supports nested text components)
|
||||
* @param sourcePlayer Player used for item stack references
|
||||
* @return Processed text with styling and item hover elements
|
||||
*/
|
||||
public static MutableText applyStyle(Text sourceText, ServerPlayerEntity sourcePlayer) {
|
||||
MutableText sourceMutableText = sourceText.copy();
|
||||
|
||||
MutableText finalText = Text.empty().setStyle(sourceMutableText.getStyle());
|
||||
|
||||
if (sourceText.getContent() instanceof #if MC_VER <= MC_1_20 LiteralTextContent #else Literal #endif plainTextContent) {
|
||||
String changedMessage = plainTextContent.string()
|
||||
.replace('&', '§')
|
||||
.replace("§§", "&");
|
||||
String regex = "\\[item(?:=([1-9]))?\\]";
|
||||
String[] messages = changedMessage.split(regex, -1);
|
||||
Deque<Integer> itemDeque = new ArrayDeque<>();
|
||||
|
||||
Matcher matcher = Pattern.compile(regex).matcher(changedMessage);
|
||||
while (matcher.find()) {
|
||||
String digit = matcher.group(1);
|
||||
if (digit == null) {
|
||||
itemDeque.addLast(MAIN_HAND);
|
||||
} else {
|
||||
itemDeque.addLast(Integer.parseInt(digit));
|
||||
}
|
||||
}
|
||||
|
||||
for (String message : messages) {
|
||||
finalText.append(Text.literal(message));
|
||||
if (!itemDeque.isEmpty()) {
|
||||
ItemStack itemStack;
|
||||
if (itemDeque.getFirst() == MAIN_HAND) {
|
||||
itemStack = sourcePlayer.getMainHandStack();
|
||||
} else {
|
||||
itemStack = sourcePlayer.getInventory().getStack(itemDeque.getFirst() - 1);
|
||||
}
|
||||
finalText.append(itemStack.toHoverableText());
|
||||
itemDeque.removeFirst();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<Text> sourceTexts = sourceMutableText.getSiblings();
|
||||
for (Text text : sourceTexts) {
|
||||
finalText.append(applyStyle(text, sourcePlayer));
|
||||
}
|
||||
|
||||
return finalText;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
@@ -1,11 +1,13 @@
|
||||
{
|
||||
"required": true,
|
||||
"package": "cn.revaria.chatplus.mixin",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"plugin": "cn.revaria.chatplus.plugin.MixinConfigPlugin",
|
||||
"mixins": [
|
||||
"MixinChat"
|
||||
"ChatMixin",
|
||||
"compat.DynmapMixin",
|
||||
"compat.StyledChatMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"id": "chat-plus",
|
||||
"version": "${version}",
|
||||
"name": "Chat Plus",
|
||||
"description": "Add bukkit style with an & and [item] for Fabric Server",
|
||||
"description": "Add Bukkit-style color codes (using \"&\") and \"[item]\" display in chat.",
|
||||
"authors": [
|
||||
"Rev_Aria"
|
||||
],
|
||||
@@ -12,7 +12,7 @@
|
||||
"sources": "https://github.com/CPTProgrammer/ChatPlus/",
|
||||
"issues": "https://github.com/CPTProgrammer/ChatPlus/issues"
|
||||
},
|
||||
"license": "CC0-1.0",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"icon": "assets/chat-plus/icon.png",
|
||||
"environment": "*",
|
||||
"entrypoints": {
|
||||
@@ -21,19 +21,12 @@
|
||||
]
|
||||
},
|
||||
"mixins": [
|
||||
"chat-plus.mixins.json",
|
||||
{
|
||||
"config": "chat-plus.client.mixins.json",
|
||||
"environment": "client"
|
||||
}
|
||||
"chat-plus.mixins.json"
|
||||
],
|
||||
"depends": {
|
||||
"fabricloader": ">=0.16.9",
|
||||
"minecraft": "~1.21.4",
|
||||
"java": ">=17",
|
||||
"fabric-api": "*"
|
||||
},
|
||||
"suggests": {
|
||||
"another-mod": "*"
|
||||
"fabricloader": "${fabric_loader_version_range}",
|
||||
"minecraft": "~${minecraft_version}",
|
||||
"java": ">=${java_version}",
|
||||
"${fabric_api_mod_id}": ">=${fabric_api_version}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user