mirror of
https://github.com/LeavesMC/Leaves.git
synced 2025-12-19 14:59:32 +00:00
Support chatimage protocol (#447)
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lumine1909 <133463833+Lumine1909@users.noreply.github.com>
|
||||
Date: Sun, 30 Mar 2025 21:53:45 +0800
|
||||
Subject: [PATCH] Vanilla player display name
|
||||
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index eba1717566a8ea534bbf149e0593cc7656df2db9..311d4abc9cbd99e6b03135dadbd8ee93e7bc4a48 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -449,7 +449,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
|
||||
// CraftBukkit start
|
||||
this.displayName = this.getScoreboardName();
|
||||
- this.adventure$displayName = net.kyori.adventure.text.Component.text(this.getScoreboardName()); // Paper
|
||||
+ this.adventure$displayName = org.leavesmc.leaves.LeavesConfig.fix.vanillaDisplayName ? io.papermc.paper.adventure.PaperAdventure.asAdventure(this.getDisplayName()) : net.kyori.adventure.text.Component.text(this.getScoreboardName()); // Paper // Leaves - Vanilla display name
|
||||
this.bukkitPickUpLoot = true;
|
||||
this.maxHealthCache = this.getMaxHealth();
|
||||
}
|
||||
@@ -844,6 +844,9 @@ public final class LeavesConfig {
|
||||
@GlobalConfig("rei-server-protocol")
|
||||
public boolean reiServerProtocol = false;
|
||||
|
||||
@GlobalConfig("chat-image-protocol")
|
||||
public boolean chatImageProtocol = false;
|
||||
|
||||
@GlobalConfig("recipe-send-all")
|
||||
public boolean recipeSendAll = false;
|
||||
}
|
||||
@@ -1032,6 +1035,9 @@ public final class LeavesConfig {
|
||||
@GlobalConfig("vanilla-hopper")
|
||||
public boolean vanillaHopper = false;
|
||||
|
||||
@GlobalConfig("vanilla-display-name")
|
||||
public boolean vanillaDisplayName = false;
|
||||
|
||||
@RemovedConfig(name = "spigot-EndPlatform-destroy", category = "fix")
|
||||
private final boolean spigotEndPlatformDestroy = false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.leavesmc.leaves.protocol.chatimage;
|
||||
|
||||
public class ChatImageIndex {
|
||||
|
||||
public int index;
|
||||
public int total;
|
||||
public String url;
|
||||
public String bytes;
|
||||
|
||||
public ChatImageIndex(int index, int total, String url, String bytes) {
|
||||
this.index = index;
|
||||
this.total = total;
|
||||
this.url = url;
|
||||
this.bytes = bytes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package org.leavesmc.leaves.protocol.chatimage;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.leavesmc.leaves.LeavesConfig;
|
||||
import org.leavesmc.leaves.protocol.core.LeavesProtocol;
|
||||
import org.leavesmc.leaves.protocol.core.ProtocolHandler;
|
||||
import org.leavesmc.leaves.protocol.core.ProtocolUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.leavesmc.leaves.protocol.chatimage.ServerBlockCache.SERVER_BLOCK_CACHE;
|
||||
|
||||
@LeavesProtocol(namespace = "chatimage")
|
||||
public class ChatImageProtocol {
|
||||
|
||||
public static final String PROTOCOL_ID = "chatimage";
|
||||
public static final Gson gson = new Gson();
|
||||
|
||||
@Contract("_ -> new")
|
||||
public static ResourceLocation id(String path) {
|
||||
return ResourceLocation.tryBuild(PROTOCOL_ID, path);
|
||||
}
|
||||
|
||||
@ProtocolHandler.PayloadReceiver(payload = FileChannelPayload.class, payloadId = "get_file_channel")
|
||||
public static void serverFileChannelReceived(ServerPlayer player, FileChannelPayload payload) {
|
||||
if (!LeavesConfig.protocol.chatImageProtocol) {
|
||||
return;
|
||||
}
|
||||
|
||||
MinecraftServer server = MinecraftServer.getServer();
|
||||
String res = payload.message();
|
||||
ChatImageIndex title = gson.fromJson(res, ChatImageIndex.class);
|
||||
Map<Integer, String> blocks = SERVER_BLOCK_CACHE.createBlock(title, res);
|
||||
if (title.total != blocks.size()) {
|
||||
return;
|
||||
}
|
||||
List<UUID> names = SERVER_BLOCK_CACHE.getUsers(title.url);
|
||||
if (names == null || player == null) {
|
||||
return;
|
||||
}
|
||||
for (UUID uuid : names) {
|
||||
ServerPlayer serverPlayer = server.getPlayerList().getPlayer(uuid);
|
||||
if (serverPlayer != null) {
|
||||
ProtocolUtils.sendPayloadPacket(serverPlayer, new FileInfoChannelPayload("true->" + title.url));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ProtocolHandler.PayloadReceiver(payload = FileInfoChannelPayload.class, payloadId = "file_info")
|
||||
public static void serverGetFileChannelReceived(ServerPlayer player, FileInfoChannelPayload packet) {
|
||||
if (!LeavesConfig.protocol.chatImageProtocol) {
|
||||
return;
|
||||
}
|
||||
|
||||
String url = packet.message();
|
||||
Map<Integer, String> list = SERVER_BLOCK_CACHE.getBlock(url);
|
||||
if (list == null) {
|
||||
ProtocolUtils.sendPayloadPacket(player, new FileInfoChannelPayload("null->" + url));
|
||||
SERVER_BLOCK_CACHE.tryAddUser(url, player.getUUID());
|
||||
return;
|
||||
}
|
||||
for (Map.Entry<Integer, String> entry : list.entrySet()) {
|
||||
ProtocolUtils.sendPayloadPacket(player, new DownloadFileChannelPayload(entry.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package org.leavesmc.leaves.protocol.chatimage;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||
import net.minecraft.network.codec.ByteBufCodecs;
|
||||
import net.minecraft.network.codec.StreamCodec;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.leavesmc.leaves.protocol.core.LeavesCustomPayload;
|
||||
import org.leavesmc.leaves.protocol.core.ProtocolUtils;
|
||||
|
||||
public record DownloadFileChannelPayload(String message) implements LeavesCustomPayload<DownloadFileChannelPayload> {
|
||||
|
||||
private static final ResourceLocation ID = ChatImageProtocol.id("download_file_channel");
|
||||
|
||||
private static final StreamCodec<RegistryFriendlyByteBuf, DownloadFileChannelPayload> CODEC =
|
||||
StreamCodec.composite(ByteBufCodecs.STRING_UTF8, DownloadFileChannelPayload::message, DownloadFileChannelPayload::new);
|
||||
|
||||
@Override
|
||||
public void write(FriendlyByteBuf buf) {
|
||||
CODEC.encode(ProtocolUtils.decorate(buf), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@New
|
||||
public static DownloadFileChannelPayload create(ResourceLocation location, FriendlyByteBuf buf) {
|
||||
return CODEC.decode(ProtocolUtils.decorate(buf));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package org.leavesmc.leaves.protocol.chatimage;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||
import net.minecraft.network.codec.ByteBufCodecs;
|
||||
import net.minecraft.network.codec.StreamCodec;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.leavesmc.leaves.protocol.core.LeavesCustomPayload;
|
||||
import org.leavesmc.leaves.protocol.core.ProtocolUtils;
|
||||
|
||||
public record FileChannelPayload(String message) implements LeavesCustomPayload<FileChannelPayload> {
|
||||
|
||||
private static final ResourceLocation ID = ChatImageProtocol.id("get_file_channel");
|
||||
|
||||
private static final StreamCodec<RegistryFriendlyByteBuf, FileChannelPayload> CODEC =
|
||||
StreamCodec.composite(ByteBufCodecs.STRING_UTF8, FileChannelPayload::message, FileChannelPayload::new);
|
||||
|
||||
@Override
|
||||
public void write(FriendlyByteBuf buf) {
|
||||
CODEC.encode(ProtocolUtils.decorate(buf), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@New
|
||||
public static FileChannelPayload create(ResourceLocation location, FriendlyByteBuf buf) {
|
||||
return CODEC.decode(ProtocolUtils.decorate(buf));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package org.leavesmc.leaves.protocol.chatimage;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||
import net.minecraft.network.codec.ByteBufCodecs;
|
||||
import net.minecraft.network.codec.StreamCodec;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.leavesmc.leaves.protocol.core.LeavesCustomPayload;
|
||||
import org.leavesmc.leaves.protocol.core.ProtocolUtils;
|
||||
|
||||
public record FileInfoChannelPayload(String message) implements LeavesCustomPayload<FileInfoChannelPayload> {
|
||||
|
||||
private static final ResourceLocation ID = ChatImageProtocol.id("file_info");
|
||||
|
||||
private static final StreamCodec<RegistryFriendlyByteBuf, FileInfoChannelPayload> CODEC =
|
||||
StreamCodec.composite(ByteBufCodecs.STRING_UTF8, FileInfoChannelPayload::message, FileInfoChannelPayload::new);
|
||||
|
||||
@Override
|
||||
public void write(FriendlyByteBuf buf) {
|
||||
CODEC.encode(ProtocolUtils.decorate(buf), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@New
|
||||
public static FileInfoChannelPayload create(ResourceLocation location, FriendlyByteBuf buf) {
|
||||
return CODEC.decode(ProtocolUtils.decorate(buf));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.leavesmc.leaves.protocol.chatimage;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.leavesmc.leaves.LeavesLogger;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ServerBlockCache {
|
||||
|
||||
public static final ServerBlockCache SERVER_BLOCK_CACHE = new ServerBlockCache();
|
||||
|
||||
public Cache<String, List<UUID>> userCache = CacheBuilder.newBuilder().expireAfterAccess(60, TimeUnit.SECONDS).build();
|
||||
public Cache<String, Map<Integer, String>> blockCache = CacheBuilder.newBuilder().expireAfterAccess(60, TimeUnit.SECONDS).build();
|
||||
public Cache<String, Integer> fileCount = CacheBuilder.newBuilder().expireAfterAccess(60, TimeUnit.SECONDS).build();
|
||||
|
||||
public Map<Integer, String> createBlock(ChatImageIndex title, String imgBytes) {
|
||||
try {
|
||||
Map<Integer, String> blocks = this.blockCache.get(title.url, HashMap::new);
|
||||
blocks.put(title.index, imgBytes);
|
||||
this.blockCache.put(title.url, blocks);
|
||||
this.fileCount.put(title.url, title.total);
|
||||
return blocks;
|
||||
} catch (Exception e) {
|
||||
LeavesLogger.LOGGER.warning("Failed to create block for title " + title.url + ": " + e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Map<Integer, String> getBlock(String url) {
|
||||
Map<Integer, String> list;
|
||||
Integer total;
|
||||
if ((list = this.blockCache.getIfPresent(url)) != null && (total = this.fileCount.getIfPresent(url)) != null) {
|
||||
if (total == list.size()) {
|
||||
return list;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void tryAddUser(String url, UUID uuid) {
|
||||
try {
|
||||
List<UUID> names = this.userCache.get(url, Lists::newArrayList);
|
||||
names.add(uuid);
|
||||
this.userCache.put(url, names);
|
||||
} catch (Exception e) {
|
||||
LeavesLogger.LOGGER.warning("Failed to add user " + uuid + ": " + e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<UUID> getUsers(String url) {
|
||||
List<UUID> names;
|
||||
if ((names = this.userCache.getIfPresent(url)) != null) {
|
||||
this.userCache.put(url, Lists.newArrayList());
|
||||
return names;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user