diff --git a/core/src/main/java/org/geysermc/geyser/event/type/SessionLoadResourcePacksEventImpl.java b/core/src/main/java/org/geysermc/geyser/event/type/SessionLoadResourcePacksEventImpl.java index cfa93fd3b..241f5d170 100644 --- a/core/src/main/java/org/geysermc/geyser/event/type/SessionLoadResourcePacksEventImpl.java +++ b/core/src/main/java/org/geysermc/geyser/event/type/SessionLoadResourcePacksEventImpl.java @@ -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 ""; + } } diff --git a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java index ec606f205..d91f42e3b 100644 --- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java @@ -92,9 +92,10 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { private final Deque 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 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 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; } } diff --git a/core/src/main/java/org/geysermc/geyser/util/WebUtils.java b/core/src/main/java/org/geysermc/geyser/util/WebUtils.java index ba17a559a..8bac97b1b 100644 --- a/core/src/main/java/org/geysermc/geyser/util/WebUtils.java +++ b/core/src/main/java/org/geysermc/geyser/util/WebUtils.java @@ -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,