1
0
mirror of https://github.com/GeyserMC/Geyser.git synced 2025-12-28 11:19:11 +00:00

Resolve some CDN pack related issues

This commit is contained in:
onebeastchris
2025-06-19 22:50:51 +02:00
parent baec73d38d
commit b96373a33f
3 changed files with 53 additions and 10 deletions

View File

@@ -36,6 +36,7 @@ import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.event.bedrock.SessionLoadResourcePacksEvent;
import org.geysermc.geyser.api.pack.ResourcePack;
import org.geysermc.geyser.api.pack.ResourcePackManifest;
import org.geysermc.geyser.api.pack.UrlPackCodec;
import org.geysermc.geyser.api.pack.exception.ResourcePackException;
import org.geysermc.geyser.api.pack.option.PriorityOption;
import org.geysermc.geyser.api.pack.option.ResourcePackOption;
@@ -205,7 +206,7 @@ public class SessionLoadResourcePacksEventImpl extends SessionLoadResourcePacksE
ResourcePackManifest.Header header = pack.manifest().header();
entries.add(new ResourcePacksInfoPacket.Entry(
header.uuid(), header.version().toString(), pack.codec().size(), pack.contentKey(),
subpackName(pack), header.uuid().toString(), false, false, false, subpackName(pack))
subpackName(pack), header.uuid().toString(), false, false, false, cdnUrl(pack))
);
}
@@ -229,4 +230,11 @@ public class SessionLoadResourcePacksEventImpl extends SessionLoadResourcePacksE
private String subpackName(GeyserResourcePack pack) {
return value(pack.uuid(), ResourcePackOption.Type.SUBPACK, "");
}
private String cdnUrl(GeyserResourcePack pack) {
if (pack.codec() instanceof UrlPackCodec urlPackCodec) {
return urlPackCodec.url();
}
return "";
}
}

View File

@@ -92,9 +92,10 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
private final Deque<String> packsToSend = new ArrayDeque<>();
private final CompressionStrategy compressionStrategy;
private static final int PACKET_SEND_DELAY = 4 * 50; // DELAY THE SEND OF PACKETS TO AVOID BURSTING SLOWER AND/OR HIGHER PING CLIENTS
// Avoid overloading consoles when downloading larger resource packs
private static final int PACKET_SEND_DELAY = 4 * 50;
private final Queue<ResourcePackChunkRequestPacket> chunkRequestQueue = new ConcurrentLinkedQueue<>();
private boolean sendingChunks = false;
private boolean currentlySendingChunks = false;
private SessionLoadResourcePacksEventImpl resourcePackLoadEvent;
@@ -305,10 +306,12 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
@Override
public PacketSignal handle(ResourcePackChunkRequestPacket packet) {
// Resolve some console pack downloading issues.
// See <https://github.com/PowerNukkitX/PowerNukkitX/pull/1997> for reference
chunkRequestQueue.add(packet);
if (isConsole()) {
if (!sendingChunks) {
sendingChunks = true;
if (!currentlySendingChunks) {
currentlySendingChunks = true;
processNextChunk();
}
} else {
@@ -320,7 +323,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
public void processNextChunk() {
ResourcePackChunkRequestPacket packet = chunkRequestQueue.poll();
if (packet == null) {
sendingChunks = false;
currentlySendingChunks = false;
return;
}
@@ -329,7 +332,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
if (holder == null) {
GeyserImpl.getInstance().getLogger().debug("Client {0} tried to request pack id {1} not sent to it!",
session.bedrockUsername(), packet.getPackId());
sendingChunks = false;
currentlySendingChunks = false;
session.disconnect("disconnectionScreen.resourcePack");
return;
}
@@ -344,7 +347,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
if (!resourcePackLoadEvent.value(pack.uuid(), ResourcePackOption.Type.FALLBACK, true)) {
session.disconnect("Unable to provide downloaded resource pack. Contact an administrator!");
sendingChunks = false;
currentlySendingChunks = false;
return;
}
}

View File

@@ -33,8 +33,18 @@ import org.geysermc.geyser.GeyserLogger;
import javax.naming.directory.Attribute;
import javax.naming.directory.InitialDirContext;
import java.io.*;
import java.net.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -44,6 +54,7 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import java.util.zip.ZipFile;
public class WebUtils {
@@ -183,6 +194,27 @@ public class WebUtils {
.formatted(url, downloadSize, size));
}
try {
boolean shouldDeleteEnclosing = false;
var originalZip = downloadLocation;
try (ZipFile zip = new ZipFile(downloadLocation.toFile())) {
// This can (or should???) contain a zip
if (zip.stream().allMatch(name -> name.getName().endsWith(".zip"))) {
// Unzip the pack, as that's what we're after
downloadLocation = REMOTE_PACK_CACHE.resolve(url.hashCode() + "_" + System.currentTimeMillis() + "_unzipped.zip");
Files.copy(zip.getInputStream(zip.entries().nextElement()), downloadLocation, StandardCopyOption.REPLACE_EXISTING);
shouldDeleteEnclosing = true;
}
} finally {
if (shouldDeleteEnclosing) {
// We don't need the original zip anymore
Files.delete(originalZip);
}
}
} catch (IOException e) {
throw new IllegalArgumentException("Encountered exception while reading downloaded resource pack at url: %s".formatted(url), e);
}
try {
Files.write(
packMetadata,