Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a01da8a677 | ||
|
|
77a6d74739 | ||
|
|
d12bb8041f | ||
|
|
44cbaad197 |
No files matched your search
+22
-2
@@ -9,8 +9,11 @@ import ac.grim.grimac.platform.bukkit.entity.BukkitGrimEntity;
|
||||
import ac.grim.grimac.platform.bukkit.utils.anticheat.MultiLibUtil;
|
||||
import ac.grim.grimac.platform.bukkit.utils.convert.BukkitConversionUtils;
|
||||
import ac.grim.grimac.platform.bukkit.utils.reflection.PaperUtils;
|
||||
import ac.grim.grimac.utils.common.arguments.CommonGrimArguments;
|
||||
import ac.grim.grimac.utils.math.Location;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
import com.github.retrooper.packetevents.protocol.player.User;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
|
||||
import lombok.Getter;
|
||||
@@ -27,6 +30,7 @@ import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class BukkitPlatformPlayer extends BukkitGrimEntity implements PlatformPlayer {
|
||||
|
||||
private static final BukkitAudiences audiences = BukkitAudiences.create(GrimACBukkitLoaderPlugin.LOADER);
|
||||
|
||||
@Getter
|
||||
@@ -34,10 +38,18 @@ public class BukkitPlatformPlayer extends BukkitGrimEntity implements PlatformPl
|
||||
@Getter
|
||||
private final PlatformInventory inventory;
|
||||
|
||||
private final @Nullable User user;
|
||||
|
||||
public BukkitPlatformPlayer(Player bukkitPlayer) {
|
||||
super(bukkitPlayer);
|
||||
this.bukkitPlayer = bukkitPlayer;
|
||||
this.inventory = new BukkitPlatformInventory(bukkitPlayer);
|
||||
if (CommonGrimArguments.USE_CHAT_FAST_BYPASS.value()) {
|
||||
Object channel = PacketEvents.getAPI().getProtocolManager().getChannel(bukkitPlayer.getUniqueId());
|
||||
this.user = PacketEvents.getAPI().getProtocolManager().getUser(channel);
|
||||
} else {
|
||||
this.user = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -67,12 +79,20 @@ public class BukkitPlatformPlayer extends BukkitGrimEntity implements PlatformPl
|
||||
|
||||
@Override
|
||||
public void sendMessage(String message) {
|
||||
bukkitPlayer.sendMessage(message);
|
||||
if (CommonGrimArguments.USE_CHAT_FAST_BYPASS.value() && user != null) {
|
||||
user.sendMessage(message);
|
||||
} else {
|
||||
bukkitPlayer.sendMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(Component message) {
|
||||
audiences.player(bukkitPlayer).sendMessage(message);
|
||||
if (CommonGrimArguments.USE_CHAT_FAST_BYPASS.value() && user != null) {
|
||||
user.sendMessage(message);
|
||||
} else {
|
||||
audiences.player(bukkitPlayer).sendMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -54,22 +54,85 @@ public class MessageUtil {
|
||||
return replacePlaceholders(player == null ? null : GrimAPI.INSTANCE.getPlayerDataManager().getPlayer(player.getUniqueId()), player, string, false);
|
||||
}
|
||||
|
||||
private static final Pattern UNIFIED_PLACEHOLDER_PATTERN = Pattern.compile("%([a-zA-Z0-9_]+)%");
|
||||
|
||||
@Contract("_, _, null, _ -> null; _, _, !null, _ -> !null")
|
||||
private @Nullable String replacePlaceholders(@Nullable GrimPlayer grimPlayer, @Nullable PlatformPlayer platformPlayer, @Nullable String string, boolean removeFormatting) {
|
||||
if (string == null) return null;
|
||||
for (Map.Entry<String, String> entry : GrimAPI.INSTANCE.getExternalAPI().getStaticReplacements().entrySet()) {
|
||||
string = string.replace(entry.getKey(), entry.getValue());
|
||||
|
||||
// --- OPTIMIZATION 1: THE FAST PATH ---
|
||||
// If the string contains no '%' characters, it's impossible for it to have placeholders.
|
||||
// indexOf() is a JVM intrinsic and is magnitudes faster than even creating a Matcher.
|
||||
if (string.indexOf('%') == -1) {
|
||||
// Since there are no % signs we can skip calling papi or our own replacement code
|
||||
return string;
|
||||
}
|
||||
|
||||
if (grimPlayer != null) {
|
||||
for (Map.Entry<String, Function<GrimUser, String>> entry : GrimAPI.INSTANCE.getExternalAPI().getVariableReplacements().entrySet()) {
|
||||
String value = entry.getValue().apply(grimPlayer).replace('%', PLACEHOLDER_ESCAPE_CHAR);
|
||||
if (removeFormatting) value = filterDiscordText(value);
|
||||
string = string.replace(entry.getKey(), value);
|
||||
final Matcher matcher = UNIFIED_PLACEHOLDER_PATTERN.matcher(string);
|
||||
|
||||
// If matcher.find() is false, it means '%' existed but not in a valid %...% pattern.
|
||||
// This avoids allocating a StringBuilder unless absolutely necessary.
|
||||
if (!matcher.find()) {
|
||||
return GrimAPI.INSTANCE.getMessagePlaceHolderManager().replacePlaceholders(platformPlayer, string);
|
||||
}
|
||||
|
||||
// Get references to the maps once, outside the loop.
|
||||
final Map<String, String> staticReplacements = GrimAPI.INSTANCE.getExternalAPI().getStaticReplacements();
|
||||
final Map<String, Function<GrimUser, String>> variableReplacements = GrimAPI.INSTANCE.getExternalAPI().getVariableReplacements();
|
||||
final StringBuilder sb = new StringBuilder(string.length() + 32); // Pre-size with a little extra room
|
||||
|
||||
// --- OPTIMIZATION 2: THE UNIFIED SINGLE-PASS LOOP ---
|
||||
// We use a do-while loop because we already performed the first matcher.find().
|
||||
do {
|
||||
// The full placeholder, e.g., "%tps%" or "%prefix%"
|
||||
final String keyWithPercent = matcher.group(0);
|
||||
String value = null;
|
||||
|
||||
// --- OPTIMIZATION 3: UNIFIED LOOKUP ---
|
||||
// We check the static map first. This is a single, O(1) hash map lookup.
|
||||
String staticValue = staticReplacements.get(keyWithPercent);
|
||||
|
||||
if (staticValue != null) {
|
||||
value = staticValue;
|
||||
} else if (grimPlayer != null) {
|
||||
// If it's not a static placeholder, check if it's a dynamic one.
|
||||
// This is a second, O(1) hash map lookup.
|
||||
final Function<GrimUser, String> func = variableReplacements.get(keyWithPercent);
|
||||
if (func != null) {
|
||||
// LAZY EVALUATION: We only call the expensive function (like getTPS)
|
||||
// if we actually found its placeholder in the string.
|
||||
value = func.apply(grimPlayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GrimAPI.INSTANCE.getMessagePlaceHolderManager().replacePlaceholders(platformPlayer, string).replace(PLACEHOLDER_ESCAPE_CHAR, '%');
|
||||
// If we found no replacement, `value` will be null.
|
||||
// In that case, we treat the placeholder as literal text by appending the original key.
|
||||
if (value == null) {
|
||||
value = keyWithPercent;
|
||||
}
|
||||
|
||||
// --- OPTIMIZATION 4: CONDITIONAL FORMATTING ---
|
||||
// The check for `removeFormatting` is inside the loop, but it's a simple boolean
|
||||
// check and the cost is negligible compared to the string operations.
|
||||
if (removeFormatting) {
|
||||
// Note: This assumes `filterDiscordText` is reasonably fast.
|
||||
// If it's slow, there are further micro-optimizations, but this is the right place for it.
|
||||
value = filterDiscordText(value);
|
||||
}
|
||||
|
||||
// `appendReplacement` efficiently appends the text between matches and our replacement value.
|
||||
// `Matcher.quoteReplacement` should handle any '$' or '\' in the replacement value.
|
||||
matcher.appendReplacement(sb, Matcher.quoteReplacement(value));
|
||||
|
||||
} while (matcher.find());
|
||||
|
||||
// Append the final part of the string after the last found placeholder.
|
||||
matcher.appendTail(sb);
|
||||
|
||||
// Create the final string from our builder.
|
||||
String grimReplaced = sb.toString();
|
||||
|
||||
return GrimAPI.INSTANCE.getMessagePlaceHolderManager().replacePlaceholders(platformPlayer, grimReplaced).replace(PLACEHOLDER_ESCAPE_CHAR, '%');
|
||||
}
|
||||
|
||||
public static String filterDiscordText(String message) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
||||
@@ -17,4 +17,16 @@ public class CommonGrimArguments {
|
||||
public final static SystemArgument<String> PASTE_URL = FACTORY.create(string("PasteUrl", "https://paste.grim.ac/"));
|
||||
public final static SystemArgument<Platform> PLATFORM_OVERRIDE = FACTORY.create(platform("PlatformOverride"));
|
||||
|
||||
/**
|
||||
* Enables "Fast Bypass" mode for chat messages sent by GrimAC.
|
||||
* <p>
|
||||
* <b>BENEFIT:</b> Messages are sent directly as packets, significantly improving
|
||||
* performance and reducing server overhead especially when lots of alerts are being sent.
|
||||
* <p>
|
||||
* <b>TRADE-OFF:</b> This completely bypasses the platform's event system (e.g., Bukkit's chat events).
|
||||
* Other plugins will NOT be able to see, format, or cancel these messages.
|
||||
* <p>
|
||||
* This setting is opt-in (default: false) and requires a server restart to change.
|
||||
*/
|
||||
public final static SystemArgument<Boolean> USE_CHAT_FAST_BYPASS = FACTORY.create(string("ChatFastBypass", true));
|
||||
}
|
||||
+23
-2
@@ -1,28 +1,41 @@
|
||||
package ac.grim.grimac.platform.fabric.player;
|
||||
|
||||
import ac.grim.grimac.GrimAPI;
|
||||
import ac.grim.grimac.platform.api.entity.GrimEntity;
|
||||
import ac.grim.grimac.platform.api.player.PlatformInventory;
|
||||
import ac.grim.grimac.platform.api.player.PlatformPlayer;
|
||||
import ac.grim.grimac.platform.fabric.GrimACFabricLoaderPlugin;
|
||||
import ac.grim.grimac.platform.fabric.entity.AbstractFabricGrimEntity;
|
||||
import ac.grim.grimac.platform.fabric.utils.convert.FabricConversionUtil;
|
||||
import ac.grim.grimac.utils.common.arguments.CommonGrimArguments;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||
import com.github.retrooper.packetevents.protocol.player.User;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class AbstractFabricPlatformPlayer extends AbstractFabricGrimEntity implements PlatformPlayer {
|
||||
protected ServerPlayerEntity fabricPlayer;
|
||||
protected final AbstractFabricPlatformInventory inventory;
|
||||
private final @Nullable User user;
|
||||
|
||||
public AbstractFabricPlatformPlayer(ServerPlayerEntity player) {
|
||||
super(player);
|
||||
this.fabricPlayer = player;
|
||||
this.inventory = GrimACFabricLoaderPlugin.LOADER.getPlatformPlayerFactory().getPlatformInventory(player);
|
||||
if (CommonGrimArguments.USE_CHAT_FAST_BYPASS.value()) {
|
||||
Object channel = PacketEvents.getAPI().getProtocolManager().getChannel(fabricPlayer.getUuid());
|
||||
this.user = PacketEvents.getAPI().getProtocolManager().getUser(channel);
|
||||
} else {
|
||||
this.user = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -42,12 +55,20 @@ public abstract class AbstractFabricPlatformPlayer extends AbstractFabricGrimEnt
|
||||
|
||||
@Override
|
||||
public void sendMessage(String message) {
|
||||
fabricPlayer.sendMessage(GrimACFabricLoaderPlugin.LOADER.getFabricMessageUtils().textLiteral(message), false);
|
||||
if (CommonGrimArguments.USE_CHAT_FAST_BYPASS.value() && user != null) {
|
||||
user.sendMessage(message);
|
||||
} else {
|
||||
fabricPlayer.sendMessage(GrimACFabricLoaderPlugin.LOADER.getFabricMessageUtils().textLiteral(message), false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(Component message) {
|
||||
fabricPlayer.sendMessage(GrimACFabricLoaderPlugin.LOADER.getFabricConversionUtil().toNativeText(message), false);
|
||||
if (CommonGrimArguments.USE_CHAT_FAST_BYPASS.value() && user != null) {
|
||||
user.sendMessage(message);
|
||||
} else {
|
||||
fabricPlayer.sendMessage(GrimACFabricLoaderPlugin.LOADER.getFabricConversionUtil().toNativeText(message), false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in new issue
Block a user