3
0
Mirror von https://github.com/GeyserMC/Geyser.git synchronisiert 2024-11-20 15:00:11 +01:00

smol cleanup: don't register packs if their options failed to register; clean up holders, fluent accessors

Dieser Commit ist enthalten in:
onebeastchris 2024-09-18 20:55:19 +08:00
Ursprung 19954a201c
Commit 3bf5da1476
6 geänderte Dateien mit 94 neuen und 86 gelöschten Zeilen

Datei anzeigen

@ -32,6 +32,7 @@ import org.geysermc.geyser.api.GeyserApi;
* 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.
* By default, {@link UrlFallbackOption#TRUE} is set.
*/
public interface UrlFallbackOption extends ResourcePackOption<Boolean> {

Datei anzeigen

@ -63,10 +63,8 @@ public class GeyserDefineResourcePacksEventImpl extends GeyserDefineResourcePack
}
ResourcePackHolder holder = ResourcePackHolder.of(pack);
packs.put(uuid, holder);
// register options
registerOption(holder, options);
packs.put(uuid, holder);
return true;
}
@ -75,12 +73,12 @@ public class GeyserDefineResourcePacksEventImpl extends GeyserDefineResourcePack
Objects.requireNonNull(uuid);
Objects.requireNonNull(options);
ResourcePackHolder packHolder = packs.get(uuid);
if (packHolder == null) {
throw new IllegalArgumentException("ResourcePack with " + uuid + " not found, unable to provide options");
ResourcePackHolder holder = packs.get(uuid);
if (holder == null) {
throw new IllegalArgumentException("resource pack with uuid " + uuid + " not found, unable to register options");
}
registerOption(packHolder, options);
registerOption(holder, options);
}
@Override
@ -88,7 +86,7 @@ public class GeyserDefineResourcePacksEventImpl extends GeyserDefineResourcePack
Objects.requireNonNull(uuid);
ResourcePackHolder packHolder = packs.get(uuid);
if (packHolder == null) {
throw new IllegalArgumentException("ResourcePack with " + uuid + " not found, unable to provide options");
throw new IllegalArgumentException("resource pack with uuid " + uuid + " not found, unable to provide options");
}
return packHolder.optionHolder().immutableValues();
@ -101,7 +99,7 @@ public class GeyserDefineResourcePacksEventImpl extends GeyserDefineResourcePack
ResourcePackHolder packHolder = packs.get(uuid);
if (packHolder == null) {
throw new IllegalArgumentException("ResourcePack with " + uuid + " not found, unable to provide options");
throw new IllegalArgumentException("resource pack with uuid " + uuid + " not found, unable to provide option");
}
return packHolder.optionHolder().get(type);
@ -117,8 +115,7 @@ public class GeyserDefineResourcePacksEventImpl extends GeyserDefineResourcePack
return;
}
holder.optionHolder().add(options);
holder.optionHolder().validateOptions(holder.pack());
holder.optionHolder().validateAndAdd(holder.pack(), options);
}
private GeyserResourcePack validate(@NonNull ResourcePack resourcePack) {
@ -126,7 +123,7 @@ public class GeyserDefineResourcePacksEventImpl extends GeyserDefineResourcePack
if (resourcePack instanceof GeyserResourcePack geyserResourcePack) {
return geyserResourcePack;
} else {
throw new IllegalArgumentException("Unknown resource pack implementation: %s".
throw new IllegalArgumentException("unknown resource pack implementation: %s".
formatted(resourcePack.getClass().getSuperclass().getName()));
}
}

Datei anzeigen

@ -55,14 +55,24 @@ import java.util.UUID;
public class SessionLoadResourcePacksEventImpl extends SessionLoadResourcePacksEvent {
/**
* The packs for this Session. A {@link ResourcePackHolder} may contain resource pack options registered
* during the {@link org.geysermc.geyser.api.event.lifecycle.GeyserDefineResourcePacksEvent}.
*/
@Getter
private final Map<UUID, ResourcePackHolder> packs;
private final Map<UUID, OptionHolder> options;
/**
* The additional, per-session options for the resource packs of this session.
* These options are prioritized over the "default" options registered
* in the {@link org.geysermc.geyser.api.event.lifecycle.GeyserDefineResourcePacksEvent}
*/
private final Map<UUID, OptionHolder> sessionPackOptionOverrides;
public SessionLoadResourcePacksEventImpl(GeyserSession session) {
super(session);
this.packs = new Object2ObjectLinkedOpenHashMap<>(Registries.RESOURCE_PACKS.get());
this.options = new Object2ObjectOpenHashMap<>();
this.sessionPackOptionOverrides = new Object2ObjectOpenHashMap<>();
}
@Override
@ -84,20 +94,18 @@ public class SessionLoadResourcePacksEventImpl extends SessionLoadResourcePacksE
return false;
}
registerOption(pack, options);
packs.put(uuid, ResourcePackHolder.of(pack));
// register options
registerOption(resourcePack, options);
return true;
}
@Override
public void registerOptions(@NonNull UUID uuid, @NonNull ResourcePackOption<?>... options) {
Objects.requireNonNull(uuid);
Objects.requireNonNull(options);
Objects.requireNonNull(uuid, "uuid cannot be null");
Objects.requireNonNull(options, "options cannot be null");
ResourcePackHolder holder = packs.get(uuid);
if (holder == null) {
throw new IllegalArgumentException("ResourcePack with " + uuid + " not found, unable to provide options");
throw new IllegalArgumentException("resource pack with uuid " + uuid + " not found, unable to register options");
}
registerOption(holder.pack(), options);
@ -108,10 +116,16 @@ public class SessionLoadResourcePacksEventImpl extends SessionLoadResourcePacksE
Objects.requireNonNull(uuid);
ResourcePackHolder packHolder = packs.get(uuid);
if (packHolder == null) {
throw new IllegalArgumentException("ResourcePack with " + uuid + " not found, unable to provide options");
throw new IllegalArgumentException("resource pack with uuid " + uuid + " not found, unable to provide options");
}
OptionHolder optionHolder = sessionPackOptionOverrides.get(uuid);
if (optionHolder == null) {
// Not creating a new option holder here since it would
// override the default priority option
return packHolder.optionHolder().immutableValues();
}
OptionHolder optionHolder = options.getOrDefault(uuid, new OptionHolder());
return optionHolder.immutableValues(packHolder.optionHolder());
}
@ -122,32 +136,29 @@ public class SessionLoadResourcePacksEventImpl extends SessionLoadResourcePacksE
ResourcePackHolder packHolder = packs.get(uuid);
if (packHolder == null) {
throw new IllegalArgumentException("ResourcePack with " + uuid + " not found, unable to provide options");
throw new IllegalArgumentException("resource pack with uuid " + uuid + " not found, unable to provide option");
}
OptionHolder holder = options.get(uuid);
@Nullable OptionHolder additionalOptions = sessionPackOptionOverrides.get(uuid);
OptionHolder defaultHolder = packHolder.optionHolder();
Objects.requireNonNull(defaultHolder); // should never be null
return OptionHolder.getOptionByType(type, holder, defaultHolder);
return OptionHolder.optionByType(type, additionalOptions, defaultHolder);
}
@Override
public boolean unregister(@NonNull UUID uuid) {
options.remove(uuid);
sessionPackOptionOverrides.remove(uuid);
return packs.remove(uuid) != null;
}
private void registerOption(@NonNull ResourcePack resourcePack, @Nullable ResourcePackOption<?>... options) {
private void registerOption(@NonNull GeyserResourcePack pack, @Nullable ResourcePackOption<?>... options) {
if (options == null) {
return;
}
GeyserResourcePack pack = validate(resourcePack);
OptionHolder holder = this.options.computeIfAbsent(pack.uuid(), $ -> new OptionHolder());
holder.add(options);
holder.validateOptions(pack);
OptionHolder holder = this.sessionPackOptionOverrides.computeIfAbsent(pack.uuid(), $ -> new OptionHolder());
holder.validateAndAdd(pack, options);
}
// Methods used internally for e.g. ordered packs, or resource pack entries
@ -190,10 +201,11 @@ public class SessionLoadResourcePacksEventImpl extends SessionLoadResourcePacksE
for (ResourcePackHolder holder : this.packs.values()) {
GeyserResourcePack pack = holder.pack();
ResourcePackManifest.Header header = pack.manifest().header();
if (pack.codec() instanceof UrlPackCodec urlPackCodec) {
ResourcePackManifest.Header header = pack.manifest().header();
entries.add(new ResourcePacksInfoPacket.CDNEntry(
header.uuid() + "_" + header.version(), urlPackCodec.url()));
header.uuid() + "_" + header.version(), urlPackCodec.url())
);
}
}
@ -202,20 +214,20 @@ public class SessionLoadResourcePacksEventImpl extends SessionLoadResourcePacksE
// Helper methods to get the options for a ResourcePack
public <T> T getValue(UUID uuid, ResourcePackOption.Type type, T defaultValue) {
OptionHolder holder = options.get(uuid);
public <T> T value(UUID uuid, ResourcePackOption.Type type, T defaultValue) {
OptionHolder holder = sessionPackOptionOverrides.get(uuid);
OptionHolder defaultHolder = packs.get(uuid).optionHolder();
Objects.requireNonNull(defaultHolder); // should never be null
return OptionHolder.getWithFallbacks(type, holder, defaultHolder, defaultValue);
return OptionHolder.valueOrFallback(type, holder, defaultHolder, defaultValue);
}
private double priority(GeyserResourcePack pack) {
return getValue(pack.uuid(), ResourcePackOption.Type.PRIORITY, 5);
return value(pack.uuid(), ResourcePackOption.Type.PRIORITY, PriorityOption.NORMAL.value());
}
private String subpackName(GeyserResourcePack pack) {
return getValue(pack.uuid(), ResourcePackOption.Type.SUBPACK, "");
return value(pack.uuid(), ResourcePackOption.Type.SUBPACK, "");
}
// Helper method to validate a pack

Datei anzeigen

@ -316,7 +316,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
if (codec instanceof UrlPackCodec urlPackCodec) {
ResourcePackLoader.testRemotePack(session, urlPackCodec, packet.getPackId(), packet.getPackVersion());
if (!resourcePackLoadEvent.getValue(pack.uuid(), ResourcePackOption.Type.FALLBACK, true)) {
if (!resourcePackLoadEvent.value(pack.uuid(), ResourcePackOption.Type.FALLBACK, true)) {
session.disconnect("Unable to provide downloaded resource pack. Contact an administrator!");
return PacketSignal.HANDLED;
}

Datei anzeigen

@ -27,6 +27,7 @@ package org.geysermc.geyser.pack;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.pack.ResourcePack;
import org.geysermc.geyser.api.pack.option.PriorityOption;
import org.geysermc.geyser.pack.option.OptionHolder;
public record ResourcePackHolder(
@ -35,7 +36,7 @@ public record ResourcePackHolder(
) {
public static ResourcePackHolder of(GeyserResourcePack pack) {
return new ResourcePackHolder(pack, new OptionHolder());
return new ResourcePackHolder(pack, new OptionHolder(PriorityOption.NORMAL));
}
public ResourcePack resourcePack() {

Datei anzeigen

@ -39,93 +39,90 @@ import java.util.Map;
public class OptionHolder extends HashMap<ResourcePackOption.Type, ResourcePackOption<?>> {
public void add(ResourcePackOption<?> option) {
if (super.containsKey(option.type())) {
super.replace(option.type(), option);
} else {
super.put(option.type(), option);
}
public OptionHolder() {
super();
}
public void add(ResourcePackOption<?>... options) {
// Used when adding resource packs initially to ensure that a priority option is always set
// It is however NOT used for session-options, as then the "normal" prio might override
// the resource pack option
public OptionHolder(PriorityOption option) {
super();
put(option.type(), option);
}
public void validateAndAdd(ResourcePack pack, ResourcePackOption<?>... options) {
for (ResourcePackOption<?> option : options) {
add(option);
// Validate before adding
option.validate(pack);
// Ensure that we do not have duplicate types.
if (super.containsKey(option.type())) {
super.replace(option.type(), option);
} else {
super.put(option.type(), option);
}
}
}
@SuppressWarnings("unchecked")
public static <T> T getWithFallbacks(ResourcePackOption.@NonNull Type type,
@Nullable OptionHolder holder,
@NonNull OptionHolder defaultHolder,
@NonNull T defaultValue) {
public static <T> T valueOrFallback(ResourcePackOption.@NonNull Type type,
@Nullable OptionHolder sessionPackOptions,
@NonNull OptionHolder resourcePackOptions,
@NonNull T defaultValue) {
ResourcePackOption<?> option;
// First: the optionHolder's option, if it exists
if (holder != null) {
option = holder.get(type);
// First: the session's options, if they exist
if (sessionPackOptions != null) {
option = sessionPackOptions.get(type);
if (option != null) {
return ((ResourcePackOption<T>) option).value();
return (T) option.value();
}
}
// Second: check the default optionHolder for the option, if it exists
option = defaultHolder.get(type);
// Second: check the resource pack options
option = resourcePackOptions.get(type);
if (option != null) {
return ((ResourcePackOption<T>) option).value();
return (T) option.value();
}
// Finally: Fallback to default
// Finally: return default
return defaultValue;
}
public static ResourcePackOption<?> getOptionByType(ResourcePackOption.@NonNull Type type,
@Nullable OptionHolder holder,
@NonNull OptionHolder defaultHolder) {
ResourcePackOption<?> option;
public static @Nullable ResourcePackOption<?> optionByType(ResourcePackOption.@NonNull Type type,
@Nullable OptionHolder sessionPackOptions,
@NonNull OptionHolder resourcePackOptions) {
// First: the optionHolder's option, if it exists
if (holder != null) {
option = holder.get(type);
// First: the session-specific options, if these exist
if (sessionPackOptions != null) {
ResourcePackOption<?> option = sessionPackOptions.get(type);
if (option != null) {
return option;
}
}
// Second: check the default optionHolder for the option, if it exists;
// Second: check the default holder for the option, if it exists;
// Or return null if the option isn't set.
option = defaultHolder.get(type);
return option;
return resourcePackOptions.get(type);
}
public void remove(ResourcePackOption<?> option) {
super.remove(option.type());
}
public OptionHolder() {
super();
add(PriorityOption.NORMAL);
}
public void validateOptions(ResourcePack pack) {
values().forEach(option -> option.validate(pack));
}
/**
* @return the options of this option optionHolder in an immutable collection
* @return the options of this holder in an immutable collection
*/
public Collection<ResourcePackOption<?>> immutableValues() {
return Collections.unmodifiableCollection(values());
}
/**
* @return the options of this option optionHolder, with fallbacks to options of a {@link GeyserResourcePack}
* @return the options of this option holder, with fallbacks to options of a {@link GeyserResourcePack}
* if they're not already overridden here
*/
public Collection<ResourcePackOption<?>> immutableValues(OptionHolder defaultValues) {
if (defaultValues.isEmpty()) {
return immutableValues();
}
// Create a map to hold the combined values
Map<ResourcePackOption.Type, ResourcePackOption<?>> combinedOptions = new HashMap<>(this);