From 31605375735683a8225612405db54761ccafc932 Mon Sep 17 00:00:00 2001 From: onebeastchris Date: Wed, 21 Aug 2024 11:46:37 +0200 Subject: [PATCH] Add UrlFallbackOption --- .../geyser/api/pack/ResourcePack.java | 5 +- .../api/pack/option/ResourcePackOption.java | 3 +- .../api/pack/option/UrlFallbackOption.java | 50 ++++++++++++++++++ .../SessionLoadResourcePacksEventImpl.java | 20 ++++--- .../geyser/network/UpstreamPacketHandler.java | 6 +++ .../pack/option/GeyserUrlFallbackOption.java | 52 +++++++++++++++++++ .../registry/loader/ResourcePackLoader.java | 3 +- 7 files changed, 123 insertions(+), 16 deletions(-) create mode 100644 api/src/main/java/org/geysermc/geyser/api/pack/option/UrlFallbackOption.java create mode 100644 core/src/main/java/org/geysermc/geyser/pack/option/GeyserUrlFallbackOption.java diff --git a/api/src/main/java/org/geysermc/geyser/api/pack/ResourcePack.java b/api/src/main/java/org/geysermc/geyser/api/pack/ResourcePack.java index 646c59e1d..75e0ba7c8 100644 --- a/api/src/main/java/org/geysermc/geyser/api/pack/ResourcePack.java +++ b/api/src/main/java/org/geysermc/geyser/api/pack/ResourcePack.java @@ -83,7 +83,7 @@ public interface ResourcePack { /** * Returns a {@link Builder} for a resource pack. - * It can be used to set a content key, or a default subpack. + * It can be used to set a content key. * * @param codec the {@link PackCodec} to base the builder on * @return a {@link Builder} to build a resource pack. @@ -93,8 +93,7 @@ public interface ResourcePack { } /** - * A builder for a resource pack. It allows providing a content key manually, or - * setting a default subpack. + * A builder for a resource pack. It allows providing a content key manually. */ interface Builder { diff --git a/api/src/main/java/org/geysermc/geyser/api/pack/option/ResourcePackOption.java b/api/src/main/java/org/geysermc/geyser/api/pack/option/ResourcePackOption.java index bedbf71ba..c2c0ad198 100644 --- a/api/src/main/java/org/geysermc/geyser/api/pack/option/ResourcePackOption.java +++ b/api/src/main/java/org/geysermc/geyser/api/pack/option/ResourcePackOption.java @@ -54,7 +54,8 @@ public interface ResourcePackOption { enum Type { SUBPACK, - PRIORITY + PRIORITY, + FALLBACK } } diff --git a/api/src/main/java/org/geysermc/geyser/api/pack/option/UrlFallbackOption.java b/api/src/main/java/org/geysermc/geyser/api/pack/option/UrlFallbackOption.java new file mode 100644 index 000000000..49e67f39f --- /dev/null +++ b/api/src/main/java/org/geysermc/geyser/api/pack/option/UrlFallbackOption.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.api.pack.option; + +import org.geysermc.geyser.api.GeyserApi; + +/** + * Can be used for resource packs using the {@link org.geysermc.geyser.api.pack.UrlPackCodec}. + * When a Bedrock client is unable to download a resource pack from a URL, Geyser will, by default, + * serve the resource pack over raknet (as packs are served with the {@link org.geysermc.geyser.api.pack.PathPackCodec}). + * This option can be used to disable that behavior, and disconnect the player instead. + */ +public interface UrlFallbackOption extends ResourcePackOption { + + UrlFallbackOption TRUE = fallback(true); + UrlFallbackOption FALSE = fallback(false); + + /** + * Whether to fall back to serving packs over the raknet connection + * @param fallback whether to fall back + * @return a UrlFallbackOption with the specified behavior + */ + static UrlFallbackOption fallback(boolean fallback) { + return GeyserApi.api().provider(UrlFallbackOption.class, fallback); + } + +} 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 74570b773..c81adfb08 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 @@ -188,22 +188,20 @@ public class SessionLoadResourcePacksEventImpl extends SessionLoadResourcePacksE // Helper methods to get the options for a ResourcePack - private double priority(GeyserResourcePack pack) { - OptionHolder holder = options.get(pack.uuid()); - OptionHolder defaultHolder = packs.get(pack.uuid()).optionHolder(); + public T getValue(UUID uuid, ResourcePackOption.Type type, T defaultValue) { + OptionHolder holder = options.get(uuid); + OptionHolder defaultHolder = packs.get(uuid).optionHolder(); Objects.requireNonNull(defaultHolder); // should never be null - return OptionHolder.getWithFallbacks(ResourcePackOption.Type.PRIORITY, - holder, defaultHolder, 5); + return OptionHolder.getWithFallbacks(type, holder, defaultHolder, defaultValue); + } + + private double priority(GeyserResourcePack pack) { + return getValue(pack.uuid(), ResourcePackOption.Type.PRIORITY, 5); } private String subpackName(GeyserResourcePack pack) { - OptionHolder holder = options.get(pack.uuid()); - OptionHolder defaultHolder = packs.get(pack.uuid()).optionHolder(); - Objects.requireNonNull(defaultHolder); // should never be null - - return OptionHolder.getWithFallbacks(ResourcePackOption.Type.SUBPACK, - holder, defaultHolder, ""); + return getValue(pack.uuid(), ResourcePackOption.Type.SUBPACK, ""); } // Helper method to validate a pack 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 39ce47526..1516e8b1e 100644 --- a/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java +++ b/core/src/main/java/org/geysermc/geyser/network/UpstreamPacketHandler.java @@ -60,6 +60,7 @@ import org.geysermc.geyser.api.pack.PackCodec; 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.option.ResourcePackOption; import org.geysermc.geyser.event.type.SessionLoadResourcePacksEventImpl; import org.geysermc.geyser.pack.GeyserResourcePack; import org.geysermc.geyser.pack.ResourcePackHolder; @@ -314,6 +315,11 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { // If a remote pack ends up here, that usually implies that a client was not able to download the pack if (codec instanceof UrlPackCodec urlPackCodec) { ResourcePackLoader.testRemotePack(session, urlPackCodec, packet.getPackId(), packet.getPackVersion()); + + if (!resourcePackLoadEvent.getValue(pack.uuid(), ResourcePackOption.Type.FALLBACK, true)) { + session.disconnect("Unable to provide downloaded resource pack. Contact an administrator!"); + return PacketSignal.HANDLED; + } } data.setChunkIndex(packet.getChunkIndex()); diff --git a/core/src/main/java/org/geysermc/geyser/pack/option/GeyserUrlFallbackOption.java b/core/src/main/java/org/geysermc/geyser/pack/option/GeyserUrlFallbackOption.java new file mode 100644 index 000000000..75a09b559 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/pack/option/GeyserUrlFallbackOption.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.pack.option; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.pack.ResourcePack; +import org.geysermc.geyser.api.pack.UrlPackCodec; +import org.geysermc.geyser.api.pack.option.UrlFallbackOption; + +public record GeyserUrlFallbackOption(Boolean enabled) implements UrlFallbackOption { + + @Override + public @NonNull Type type() { + return Type.FALLBACK; + } + + @Override + public @NonNull Boolean value() { + return enabled; + } + + @Override + public void validate(@NonNull ResourcePack pack) { + if (!(pack.codec() instanceof UrlPackCodec)) { + throw new IllegalArgumentException("UrlFallbackOption cannot be set on resource packs that do not use" + + "the url pack codec!"); + } + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/ResourcePackLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/ResourcePackLoader.java index 7e5aa7c7e..4a78069b4 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/ResourcePackLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/ResourcePackLoader.java @@ -116,10 +116,11 @@ public class ResourcePackLoader implements RegistryLoader