Skip to content

Commit

Permalink
IT WORKS... flawlessly.
Browse files Browse the repository at this point in the history
yet i still havent figured out how to add chat highlight hahaye
  • Loading branch information
Flamarine committed Aug 17, 2022
1 parent a4d439a commit a864399
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 21 deletions.
14 changes: 9 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ version = project.mod_version + "+mc" + project.minecraft_version
group = project.maven_group

repositories {
// Add repositories to retrieve artifacts from in here.
// You should only use this when depending on other mods because
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
// for more information about repositories.
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
content {
includeGroup "maven.modrinth"
}
}
}

loom {
Expand All @@ -38,6 +40,8 @@ dependencies {

// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"

modRuntimeOnly "maven.modrinth:mixintrace:1.1.1+1.17"
}

processResources {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package dev.intelligentcreations.pingme.inject;

import net.minecraft.network.MessageType;
import net.minecraft.text.Text;
import net.minecraft.util.Util;

import java.util.UUID;

public interface ServerPlayerEntityHelper {
default void internalSendMessage(Text message, MessageType type, UUID sender) {
}

default void internalSendMessage(Text message, boolean actionBar) {
this.internalSendMessage(message, actionBar ? MessageType.GAME_INFO : MessageType.CHAT, Util.NIL_UUID);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package dev.intelligentcreations.pingme.mixin;

import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import dev.intelligentcreations.pingme.util.TextUtil;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.CommandSuggestor;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.command.CommandSource;
import org.jetbrains.annotations.Nullable;
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.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.regex.Pattern;

@Mixin(CommandSuggestor.class)
public abstract class CommandSuggestorMixin {
private static final Pattern COLON_PATTERN = Pattern.compile("(@)");
private static final Pattern WHITESPACE_PATTERN = Pattern.compile("(\\s+)");

@Shadow @Final TextFieldWidget textField;

@Shadow @Final private boolean slashOptional;

@Shadow @Final private MinecraftClient client;

@Shadow @Nullable private CompletableFuture<Suggestions> pendingSuggestions;

@Shadow public abstract void showSuggestions(boolean narrateFirstSuggestion);

@Inject(
method = "refresh",
at = @At("TAIL"),
cancellable = true
)
public void onRefresh(CallbackInfo ci) {
if (!this.client.isInSingleplayer()) {
String message = this.textField.getText();
StringReader reader = new StringReader(message);
boolean hasSlash = reader.canRead() && reader.peek() == '/';
if (hasSlash) reader.skip();
boolean isCommand = this.slashOptional || hasSlash;
int cursor = this.textField.getCursor();
if (!isCommand) {
String textUptoCursor = message.substring(0, cursor);
int start = Math.max(TextUtil.getLastPattern(textUptoCursor, COLON_PATTERN) - 1, 0);
int whitespace = TextUtil.getLastPattern(textUptoCursor, WHITESPACE_PATTERN);
if (start < textUptoCursor.length() && start >= whitespace) {
if (textUptoCursor.charAt(start) == '@') {
List<String> playerNames = new ArrayList<>();
ClientPlayNetworkHandler networkHandler = this.client.getNetworkHandler();
if (networkHandler != null) {
networkHandler.getPlayerList().forEach(entry ->
playerNames.add("@" + entry.getProfile().getName())
);
this.pendingSuggestions = CommandSource.suggestMatching(playerNames, new SuggestionsBuilder(textUptoCursor, start));
this.pendingSuggestions.thenRun(() -> {
if (this.pendingSuggestions.isDone()) return;
this.showSuggestions(false);
});
ci.cancel();
}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package dev.intelligentcreations.pingme.mixin;

import dev.intelligentcreations.pingme.inject.ServerPlayerEntityHelper;
import net.minecraft.network.MessageType;
import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayNetworkHandler;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.Formatting;
import net.minecraft.util.Language;
import net.minecraft.util.Util;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
Expand All @@ -18,9 +24,13 @@
import java.util.UUID;

@Mixin(ServerPlayerEntity.class)
public abstract class ServerPlayerEntityMixin {
public abstract class ServerPlayerEntityMixin implements ServerPlayerEntityHelper {
@Shadow @Final public MinecraftServer server;

@Shadow protected abstract boolean acceptsMessage(MessageType type);

@Shadow public ServerPlayNetworkHandler networkHandler;

@Inject(
method = "sendMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/MessageType;Ljava/util/UUID;)V",
at = @At(
Expand All @@ -29,37 +39,60 @@ public abstract class ServerPlayerEntityMixin {
)
)
public void onSendMessage(Text message, MessageType type, UUID sender, CallbackInfo ci) {
String processString = message.getString();
while (processString.contains("@")) {
processString = processString.substring(processString.indexOf("@"));
Text playerName = this.server.getPlayerManager().getPlayer(sender) != null ?
this.server.getPlayerManager().getPlayer(sender).getName()
: new LiteralText(sender.toString());
if (processString.contains(" ")) {
String name = processString.substring(processString.indexOf("@") + 1, processString.indexOf(" "));
doPing(playerName, name);
} else {
String name = processString.substring(processString.indexOf("@") + 1);
doPing(playerName, name);
if (!this.server.isSingleplayer()) {
String processString = message.getString();
while (processString.contains("@")) {
processString = processString.substring(processString.indexOf("@"));
Text playerName = this.server.getPlayerManager().getPlayer(sender) != null ?
this.server.getPlayerManager().getPlayer(sender).getName()
: new LiteralText(sender.toString());
if (processString.contains(" ")) {
String name = processString.substring(processString.indexOf("@") + 1, processString.indexOf(" "));
doPing(playerName, name);
} else {
String name = processString.substring(processString.indexOf("@") + 1);
doPing(playerName, name);
}
processString = processString.substring(1);
}
processString = processString.substring(processString.indexOf("@", processString.indexOf("@") + 1));
}
}

private void doPing(Text playerName, String name) {
Text pingMessage = Language.getInstance().hasTranslation("message.pingme.ping") ?
new TranslatableText("message.pingme.ping", playerName)
: new LiteralText(playerName.getString() + " just pinged you in the chat!");
if (name.equals("everyone")) {
this.server.getPlayerManager().getPlayerList().forEach(player -> {
if (player.getName() != playerName) {
player.sendMessage(new TranslatableText("message.pingme.ping", playerName), true);
player.internalSendMessage(pingMessage, true);
player.playSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.MASTER, 1.0f, 1.0f);
}
});
} else {
ServerPlayerEntity player = this.server.getPlayerManager().getPlayer(name);
if (player != null) {
player.sendMessage(new TranslatableText("message.pingme.ping", playerName), true);
player.internalSendMessage(pingMessage, true);
player.playSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.MASTER, 1.0f, 1.0f);
}
}
}

@Override
public void internalSendMessage(Text message, MessageType type, UUID sender) {
if (this.acceptsMessage(type)) {
this.networkHandler.sendPacket(new GameMessageS2CPacket(message, type, sender), (future) -> {
if (!future.isSuccess() && (type == MessageType.GAME_INFO || type == MessageType.SYSTEM) && this.acceptsMessage(MessageType.SYSTEM)) {
String string = message.asTruncatedString(256);
Text text2 = (new LiteralText(string)).formatted(Formatting.YELLOW);
this.networkHandler.sendPacket(new GameMessageS2CPacket((new TranslatableText("multiplayer.message_not_delivered", new Object[]{text2})).formatted(Formatting.RED), MessageType.SYSTEM, sender));
}
});
}
}

@Override
public void internalSendMessage(Text message, boolean actionBar) {
this.internalSendMessage(message, actionBar ? MessageType.GAME_INFO : MessageType.CHAT, Util.NIL_UUID);
}
}
20 changes: 20 additions & 0 deletions src/main/java/dev/intelligentcreations/pingme/util/TextUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dev.intelligentcreations.pingme.util;

import com.google.common.base.Strings;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TextUtil {
public static int getLastPattern(String input, Pattern pattern){
if (Strings.isNullOrEmpty(input)) {
return 0;
}
int i = 0;
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
i = matcher.end();
}
return i;
}
}
5 changes: 5 additions & 0 deletions src/main/resources/fabric.mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
"mixins": [
"pingme.mixins.json"
],
"custom": {
"loom:injected_interfaces": {
"net/minecraft/class_3222": ["dev/intelligentcreations/pingme/inject/ServerPlayerEntityHelper"]
}
},

"depends": {
"fabricloader": ">=0.14.6",
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/pingme.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"ServerPlayerEntityMixin"
],
"client": [
"CommandSuggestorMixin"
],
"injectors": {
"defaultRequire": 1
Expand Down

0 comments on commit a864399

Please sign in to comment.