Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement sending remote resource packs to Bedrock clients #4205

Closed
wants to merge 51 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
68516a8
Initial stab at implementing 1.20.30's new CDN feature for resource p…
onebeastchris Oct 10, 2023
02d6473
Small tweaks: record formatting/javadocs
onebeastchris Oct 10, 2023
dbfc153
- Don't require configuring the packId, just the link instead
onebeastchris Oct 10, 2023
f74d36a
Remove forRemoval
onebeastchris Oct 10, 2023
94f2ea9
Rename cdn-resource-packs to resource-pack-urls, fix test, remove dup…
onebeastchris Oct 10, 2023
fd69b0c
Rename CDN entry list
onebeastchris Oct 10, 2023
c0227d3
Move loading cdn entries to separate function
onebeastchris Oct 11, 2023
b9c5bdd
Remove CDNEntry; those do not work as expected.
onebeastchris Oct 17, 2023
27c1562
remove outdated javadocs
onebeastchris Oct 17, 2023
5d06edd
Fallback system - download the pack to serve the client in case cdn f…
onebeastchris Oct 18, 2023
880de2d
Ensure GeyserUrlPackCodec.create returns a ResourcePack with the URL …
onebeastchris Oct 18, 2023
76a62ab
Check downloaded resource packs, yeet cdn naming scheme
onebeastchris Oct 18, 2023
3670914
start on proper url checking (application type/size)
onebeastchris Oct 24, 2023
498a415
Change fallback system
onebeastchris Nov 9, 2023
0004f5b
Testing: Don't require `application/zip` or `size` or weird zip forma…
onebeastchris Nov 9, 2023
cdd2aba
Merge remote-tracking branch 'upstream/master' into rp
onebeastchris Nov 9, 2023
15b8b93
We need to ensure no invalid packs end up being loaded - otherwise, c…
onebeastchris Nov 9, 2023
d4f0d8a
Re-add debug: Apparently, not just `application/zip` works....???
onebeastchris Nov 10, 2023
0ac91eb
Merge remote-tracking branch 'upstream/master' into rp
onebeastchris Dec 21, 2023
626189f
remove debug, ensure we fully check failed packs, merge master
onebeastchris Dec 21, 2023
f121299
More robust downloading/caching
onebeastchris Dec 22, 2023
303327a
oops
onebeastchris Dec 22, 2023
d2622a4
Add a registerAll method to register a collection of resource packs e…
onebeastchris Jan 15, 2024
4d99250
Merge remote-tracking branch 'upstream/master' into rp
onebeastchris Jan 25, 2024
2e776c4
Allow null content key
onebeastchris Jan 26, 2024
a4fa2e6
Merge remote-tracking branch 'upstream/master' into rp
onebeastchris Feb 16, 2024
b8fa18a
start: don't try to delete broken packs while we are still delivering…
onebeastchris Feb 19, 2024
c6511a0
update to "new" pack requirements
onebeastchris Feb 22, 2024
507a79e
Merge remote-tracking branch 'refs/remotes/upstream/master' into rp
onebeastchris Jun 19, 2024
86f6458
Code cleanup, less futures, more exceptions when needed
onebeastchris Jun 19, 2024
6053b7d
Yeet unused, update optionalpack link
onebeastchris Jun 19, 2024
2683b59
Minor cleanup
onebeastchris Jun 20, 2024
ba78dba
Add url codec creation method with no content key, remove boolean ret…
onebeastchris Jun 20, 2024
f56c182
Merge branch 'master' into rp
onebeastchris Jun 20, 2024
de54a5b
Ensure packs actually load
onebeastchris Jun 20, 2024
86f1389
Merge remote-tracking branch 'origin/rp' into rp
onebeastchris Jun 20, 2024
27659d0
Add device type to debug to be able to isolate platform specific requ…
onebeastchris Jun 24, 2024
9241957
Automatically download newer pack versions from urls, properly get ri…
onebeastchris Jun 25, 2024
3638d4d
Merge branch 'master' into rp
onebeastchris Jun 25, 2024
8b87c08
Fix typo's
onebeastchris Jun 25, 2024
b6d404e
Merge remote-tracking branch 'origin/rp' into rp
onebeastchris Jun 25, 2024
e214fbe
javadoc typos, log application type as info for now
onebeastchris Jun 27, 2024
1608746
Warn about content-type being null/not application/zip
onebeastchris Jul 1, 2024
f116382
Proper warning about version/uuid changes
onebeastchris Jul 3, 2024
5b52769
Merge branch 'master' into rp
onebeastchris Jul 3, 2024
5649574
Merge branch 'master' into rp
onebeastchris Jul 6, 2024
61f5294
Merge branch 'master' into rp
onebeastchris Jul 9, 2024
226bf38
Merge branch 'master' into rp
onebeastchris Jul 13, 2024
bddd9ac
Merge branch 'master' into rp
onebeastchris Jul 21, 2024
b43e2db
Merge branch 'master' into rp
onebeastchris Aug 2, 2024
20e4919
Merge branch 'GeyserMC:master' into rp
onebeastchris Aug 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.geysermc.geyser.api.event.connection.ConnectionEvent;
import org.geysermc.geyser.api.pack.ResourcePack;

import java.util.Collection;
import java.util.List;
import java.util.UUID;

Expand All @@ -42,7 +43,7 @@ public SessionLoadResourcePacksEvent(@NonNull GeyserConnection connection) {
}

/**
* Gets an unmodifiable list of {@link ResourcePack}s that will be sent to the client.
* Gets an unmodifiable list of {@link ResourcePack}'s that will be sent to the client.
*
* @return an unmodifiable list of resource packs that will be sent to the client.
*/
Expand All @@ -58,10 +59,17 @@ public SessionLoadResourcePacksEvent(@NonNull GeyserConnection connection) {
public abstract boolean register(@NonNull ResourcePack resourcePack);

/**
* Unregisters a resource pack from being sent to the client.
* Registers a collection of {@link ResourcePack}'s to be sent to clients.
*
* @param uuid the UUID of the resource pack
* @return true whether the resource pack was removed from the list of resource packs.
* @param resourcePacks collection of resource pack's that will be sent to clients
*/
public abstract void registerAll(@NonNull Collection<ResourcePack> resourcePacks);

/**
* Unregisters a {@link ResourcePack} from being sent to the client.
*
* @param uuid the UUID of the resource pack to remove.
* @return true whether the resource pack was removed successfully.
*/
public abstract boolean unregister(@NonNull UUID uuid);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2019-2023 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.event.lifecycle;

import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.event.Event;
import org.geysermc.geyser.api.pack.ResourcePack;

import java.util.Collection;
import java.util.List;
import java.util.UUID;

/**
* Called when {@link ResourcePack}'s are loaded within Geyser.
*/
public abstract class GeyserDefineResourcePacksEvent implements Event {

/**
* Gets an unmodifiable list of {@link ResourcePack}'s that will be sent to clients.
*
* @return an unmodifiable list of resource packs that will be sent to clients.
*/
public abstract @NonNull List<ResourcePack> resourcePacks();

/**
* Registers a {@link ResourcePack} to be sent to clients.
*
* @param resourcePack a resource pack that will be sent to clients.
* @return true if the resource pack was added successfully,
* or false if already present
*/
public abstract boolean register(@NonNull ResourcePack resourcePack);

/**
* Registers a collection of {@link ResourcePack}'s to be sent to clients.
*
* @param resourcePacks a collection of resource pack's that will be sent to clients.
*/
public abstract void registerAll(@NonNull Collection<ResourcePack> resourcePacks);


/**
* Unregisters a {@link ResourcePack} from being sent to clients.
*
* @param uuid the UUID of the resource pack to remove.
* @return true whether the resource pack was removed successfully.
*/
public abstract boolean unregister(@NonNull UUID uuid);
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,11 @@

/**
* Called when resource packs are loaded within Geyser.
* @deprecated Use {@link GeyserDefineResourcePacksEvent} instead.
*
* @param resourcePacks a mutable list of the currently listed resource packs
*/

@Deprecated
public record GeyserLoadResourcePacksEvent(@NonNull List<Path> resourcePacks) implements Event {
}
24 changes: 24 additions & 0 deletions api/src/main/java/org/geysermc/geyser/api/pack/PackCodec.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
package org.geysermc.geyser.api.pack;

import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.api.GeyserApi;

import java.io.IOException;
Expand Down Expand Up @@ -79,4 +80,27 @@ public abstract class PackCodec {
public static PackCodec path(@NonNull Path path) {
return GeyserApi.api().provider(PathPackCodec.class, path);
}

/**
* Creates a new pack provider from the given url with no content key.
*
* @param url the url to create the pack provider from
* @return the new pack provider
*/
@NonNull
public static PackCodec url(@NonNull String url) {
return url(url, null);
}

/**
* Creates a new pack provider from the given url and content key.
*
* @param url the url to create the pack provider from
* @param contentKey the content key, leave empty or null if pack is not encrypted
* @return the new pack provider
*/
@NonNull
public static PackCodec url(@NonNull String url, @Nullable String contentKey) {
return GeyserApi.api().provider(UrlPackCodec.class, url, contentKey);
}
}
58 changes: 58 additions & 0 deletions api/src/main/java/org/geysermc/geyser/api/pack/UrlPackCodec.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright (c) 2019-2023 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;

import org.checkerframework.checker.nullness.qual.NonNull;

/**
* Represents a pack codec that creates a resource
* pack from a URL.
* <p>
* Due to Bedrock limitations, the URL must:
* <ul>
* <li>be a direct download link to a .zip or .mcpack resource pack</li>
* <li>use the application type `application/zip` and set a correct content length</li>
* </ul>
*/
public abstract class UrlPackCodec extends PackCodec {

/**
* Gets the URL to the resource pack location.
*
* @return the URL of the resource pack
*/
@NonNull
public abstract String url();

/**
* If the remote pack has an encryption key, it must be specified here.
* This will return empty if none is specified.
*
* @return the encryption key of the resource pack
*/
@NonNull
public abstract String contentKey();
onebeastchris marked this conversation as resolved.
Show resolved Hide resolved
}
3 changes: 2 additions & 1 deletion core/src/main/java/org/geysermc/geyser/GeyserImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
import org.geysermc.geyser.network.netty.GeyserServer;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.loader.ResourcePackLoader;
import org.geysermc.geyser.registry.provider.ProviderSupplier;
import org.geysermc.geyser.scoreboard.ScoreboardUpdater;
import org.geysermc.geyser.session.GeyserSession;
Expand Down Expand Up @@ -719,7 +720,7 @@ public void disable() {
runIfNonNull(newsHandler, NewsHandler::shutdown);
runIfNonNull(erosionUnixListener, UnixSocketClientListener::close);

Registries.RESOURCE_PACKS.get().clear();
ResourcePackLoader.clear();

this.setEnabled(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ public interface GeyserConfiguration {

boolean isForceResourcePacks();

List<String> getResourcePackUrls();

@SuppressWarnings("BooleanMethodIsAlwaysInverted")
boolean isXboxAchievementsEnabled();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
@JsonProperty("force-resource-packs")
private boolean forceResourcePacks = true;

@JsonProperty("resource-pack-urls")
private List<String> resourcePackUrls = new ArrayList<>();

@JsonProperty("xbox-achievements-enabled")
private boolean xboxAchievementsEnabled = false;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2019-2023 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.event.type;

import lombok.Getter;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.event.lifecycle.GeyserDefineResourcePacksEvent;
import org.geysermc.geyser.api.pack.ResourcePack;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Getter
public class GeyserDefineResourcePacksEventImpl extends GeyserDefineResourcePacksEvent {

private final Map<String, ResourcePack> packs;

public GeyserDefineResourcePacksEventImpl(Map<String, ResourcePack> packMap) {
this.packs = packMap;
}

@Override
public @NonNull List<ResourcePack> resourcePacks() {
return List.copyOf(packs.values());
}

@Override
public boolean register(@NonNull ResourcePack resourcePack) {
String packID = resourcePack.manifest().header().uuid().toString();
if (packs.containsValue(resourcePack) || packs.containsKey(packID)) {
return false;
}
packs.put(resourcePack.manifest().header().uuid().toString(), resourcePack);
return true;
}

@Override
public void registerAll(@NonNull Collection<ResourcePack> resourcePacks) {
resourcePacks.forEach(this::register);
}

@Override
public boolean unregister(@NonNull UUID uuid) {
return packs.remove(uuid.toString()) != null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,28 +25,26 @@

package org.geysermc.geyser.event.type;

import lombok.Getter;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.event.bedrock.SessionLoadResourcePacksEvent;
import org.geysermc.geyser.api.pack.ResourcePack;
import org.geysermc.geyser.session.GeyserSession;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;

public class SessionLoadResourcePacksEventImpl extends SessionLoadResourcePacksEvent {

@Getter
private final Map<String, ResourcePack> packs;

public SessionLoadResourcePacksEventImpl(GeyserSession session, Map<String, ResourcePack> packMap) {
super(session);
this.packs = packMap;
}

public @NonNull Map<String, ResourcePack> getPacks() {
return packs;
}

@Override
public @NonNull List<ResourcePack> resourcePacks() {
return List.copyOf(packs.values());
Expand All @@ -62,6 +60,11 @@ public boolean register(@NonNull ResourcePack resourcePack) {
return true;
}

@Override
public void registerAll(@NonNull Collection<ResourcePack> resourcePacks) {
resourcePacks.forEach(this::register);
}

@Override
public boolean unregister(@NonNull UUID uuid) {
return packs.remove(uuid.toString()) != null;
Expand Down
Loading