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 4 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 @@ -29,6 +29,7 @@
import org.geysermc.geyser.api.connection.GeyserConnection;
import org.geysermc.geyser.api.event.connection.ConnectionEvent;
import org.geysermc.geyser.api.pack.ResourcePack;
import org.geysermc.geyser.api.pack.ResourcePackCDNEntry;

import java.util.List;
import java.util.UUID;
Expand All @@ -48,6 +49,13 @@ public SessionLoadResourcePacksEvent(@NonNull GeyserConnection connection) {
*/
public abstract @NonNull List<ResourcePack> resourcePacks();

/**
* Gets an unmodifiable list of {@link ResourcePackCDNEntry}s that will be sent to the client.
*
* @return an unmodifiable list of resource pack CDN entries that will be sent to the client.
*/
public abstract @NonNull List<ResourcePackCDNEntry> cdnEntries();
onebeastchris marked this conversation as resolved.
Show resolved Hide resolved

/**
* Registers a {@link ResourcePack} to be sent to the client.
*
Expand All @@ -58,10 +66,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 {@link ResourcePackCDNEntry} to be sent to the client.
*
* @param entry CDN entry that will be sent to the client to download a resource pack from.
*/
public abstract boolean register(@NonNull ResourcePackCDNEntry entry);

/**
* Unregisters a {@link ResourcePack} or {@link ResourcePackCDNEntry} from being sent to the client.
*
* @param uuid the UUID of the resource pack
* @return true whether the resource pack was removed from the list of resource packs.
* @param uuid the UUID of the resource pack/CDN entry to remove.
* @return true whether the resource pack/CDN entry was removed successfully.
*/
public abstract boolean unregister(@NonNull UUID uuid);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* 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 org.geysermc.geyser.api.pack.ResourcePackCDNEntry;

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

/**
* Called when {@link ResourcePack}'s and {@link ResourcePackCDNEntry}'s are loaded within Geyser.
*
*/
public abstract class GeyserDefineResourcePacksEvent implements Event {
onebeastchris marked this conversation as resolved.
Show resolved Hide resolved

/**
* 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();

/**
* Gets an unmodifiable list of {@link ResourcePackCDNEntry}s that will be sent to clients.
*
* @return an unmodifiable list of resource pack CDN entries that will be sent to clients.
*/
public abstract @NonNull List<ResourcePackCDNEntry> cdnEntries();

/**
* 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 {@link ResourcePackCDNEntry} to be sent to clients.
*
* @param entry CDN entry that will be sent to the client to download a resource pack from.
*/
public abstract boolean register(@NonNull ResourcePackCDNEntry entry);

/**
* Unregisters a {@link ResourcePack} or {@link ResourcePackCDNEntry} from being sent to clients.
*
* @param uuid the UUID of the resource pack/CDN entry to remove.
* @return true whether the resource pack/CDN entry 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
*/
public record GeyserLoadResourcePacksEvent(@NonNull List<Path> resourcePacks) implements Event {

@Deprecated
public record GeyserLoadResourcePacksEvent(@Deprecated @NonNull List<Path> resourcePacks) implements Event {
onebeastchris marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* 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 java.util.UUID;

/**
* Represents a CDN entry for a resource pack.
* The URL must be a direct download link to a Bedrock edition resource pack.
* The UUID must be the UUID of the resource pack.
*
* @param url URL from which the pack should be downloaded
* @param uuid UUID of the pack
*/
public record ResourcePackCDNEntry(String url, UUID uuid) {
}

Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ public interface GeyserConfiguration {

boolean isForceResourcePacks();

List<String> getCdnResourcePacks();

boolean isXboxAchievementsEnabled();

int getCacheImages();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
Expand Down Expand Up @@ -136,6 +137,9 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
@JsonProperty("force-resource-packs")
private boolean forceResourcePacks = true;

@JsonProperty("cdn-resource-packs")
private List<String> cdnResourcePacks = 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,93 @@
/*
* 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 org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.event.lifecycle.GeyserDefineResourcePacksEvent;
import org.geysermc.geyser.api.pack.ResourcePack;
import org.geysermc.geyser.api.pack.ResourcePackCDNEntry;

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

public class GeyserDefineResourcePacksEventImpl extends GeyserDefineResourcePacksEvent {

private final Map<String, ResourcePack> packs;
private final Map<String, ResourcePackCDNEntry> cdnEntries;

public GeyserDefineResourcePacksEventImpl(Map<String, ResourcePack> packMap, List<ResourcePackCDNEntry> cdnEntries) {
this.packs = packMap;
this.cdnEntries = new HashMap<>();
cdnEntries.forEach(entry -> this.cdnEntries.put(entry.uuid().toString(), entry));
}

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

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

@Override
public @NonNull List<ResourcePackCDNEntry> cdnEntries() {
return List.copyOf(cdnEntries.values());
}

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

@Override
public boolean register(@NonNull ResourcePackCDNEntry entry) {
String packID = entry.uuid().toString();
if (packs.containsKey(packID) || cdnEntries.containsValue(entry) || cdnEntries.containsKey(packID)) {
return false;
}
cdnEntries.put(packID, entry);
return true;
}

@Override
public boolean unregister(@NonNull UUID uuid) {
if (packs.containsKey(uuid.toString())) {
return packs.remove(uuid.toString()) != null;
} else if (cdnEntries.containsKey(uuid.toString())) {
return cdnEntries.remove(uuid.toString()) != null;
} else {
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,24 @@
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.api.pack.ResourcePackCDNEntry;
import org.geysermc.geyser.session.GeyserSession;

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

public class SessionLoadResourcePacksEventImpl extends SessionLoadResourcePacksEvent {

private final Map<String, ResourcePack> packs;
private final Map<String, ResourcePackCDNEntry> cdnEntries;

public SessionLoadResourcePacksEventImpl(GeyserSession session, Map<String, ResourcePack> packMap) {
public SessionLoadResourcePacksEventImpl(GeyserSession session, Map<String, ResourcePack> packMap, List<ResourcePackCDNEntry> cdnEntries) {
super(session);
this.packs = packMap;
this.cdnEntries = new HashMap<>();
cdnEntries.forEach(entry -> this.cdnEntries.put(entry.uuid().toString(), entry));
}

public @NonNull Map<String, ResourcePack> getPacks() {
Expand All @@ -52,18 +57,39 @@ public SessionLoadResourcePacksEventImpl(GeyserSession session, Map<String, Reso
return List.copyOf(packs.values());
}

@Override
public @NonNull List<ResourcePackCDNEntry> cdnEntries() {
return List.copyOf(cdnEntries.values());
}

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

@Override
public boolean register(@NonNull ResourcePackCDNEntry entry) {
String packID = entry.uuid().toString();
if (packs.containsKey(packID) || cdnEntries.containsKey(packID) || cdnEntries.containsValue(entry)) {
return false;
}
cdnEntries.put(packID, entry);
return true;
}

@Override
public boolean unregister(@NonNull UUID uuid) {
return packs.remove(uuid.toString()) != null;
if (packs.containsKey(uuid.toString())) {
return packs.remove(uuid.toString()) != null;
} else if (cdnEntries.containsKey(uuid.toString())) {
return cdnEntries.remove(uuid.toString()) != null;
} else {
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ public static boolean isPre1_20_10(GeyserSession session) {
return session.getUpstream().getProtocolVersion() < Bedrock_v594.CODEC.getProtocolVersion();
}

public static boolean isPre1_20_30(GeyserSession session) {
return session.getUpstream().getProtocolVersion() < Bedrock_v618.CODEC.getProtocolVersion();
}

/**
* Gets the {@link PacketCodec} for Minecraft: Java Edition.
*
Expand Down
Loading
Loading