Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-10-03 16:31:14 +02:00
Attempt at making a proper builder for resource pack options (content key, default subpack), and a ResourcePackOption system to register packs with further options
Dieser Commit ist enthalten in:
Ursprung
87829c9d0a
Commit
033d2d6d8c
@ -29,7 +29,9 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
|||||||
import org.geysermc.geyser.api.connection.GeyserConnection;
|
import org.geysermc.geyser.api.connection.GeyserConnection;
|
||||||
import org.geysermc.geyser.api.event.connection.ConnectionEvent;
|
import org.geysermc.geyser.api.event.connection.ConnectionEvent;
|
||||||
import org.geysermc.geyser.api.pack.ResourcePack;
|
import org.geysermc.geyser.api.pack.ResourcePack;
|
||||||
|
import org.geysermc.geyser.api.pack.option.ResourcePackOption;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ -57,6 +59,34 @@ public abstract class SessionLoadResourcePacksEvent extends ConnectionEvent {
|
|||||||
*/
|
*/
|
||||||
public abstract boolean register(@NonNull ResourcePack resourcePack);
|
public abstract boolean register(@NonNull ResourcePack resourcePack);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a {@link ResourcePack} to be sent to the client, but alongside
|
||||||
|
* specific options.
|
||||||
|
*
|
||||||
|
* @param resourcePack a resource pack that will be sent to the client.
|
||||||
|
* @return true if the resource pack was added successfully,
|
||||||
|
* or false if already present
|
||||||
|
*/
|
||||||
|
public abstract boolean register(@NonNull ResourcePack resourcePack, ResourcePackOption... resourcePackOptions);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the subpack options set for a specific resource pack.
|
||||||
|
*
|
||||||
|
* @param resourcePack the resourcePack for which the options are set
|
||||||
|
* @return a list of {@link ResourcePackOption}
|
||||||
|
*/
|
||||||
|
Collection<ResourcePackOption> options(ResourcePack resourcePack) {
|
||||||
|
return options(resourcePack.manifest().header().uuid());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the subpack options set for a specific resource pack uuid.
|
||||||
|
*
|
||||||
|
* @param resourcePack the resourcePack for which the options are set
|
||||||
|
* @return a list of {@link ResourcePackOption}
|
||||||
|
*/
|
||||||
|
public abstract Collection<ResourcePackOption> options(UUID resourcePack);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregisters a resource pack from being sent to the client.
|
* Unregisters a resource pack from being sent to the client.
|
||||||
*
|
*
|
||||||
@ -64,4 +94,5 @@ public abstract class SessionLoadResourcePacksEvent extends ConnectionEvent {
|
|||||||
* @return true whether the resource pack was removed from the list of resource packs.
|
* @return true whether the resource pack was removed from the list of resource packs.
|
||||||
*/
|
*/
|
||||||
public abstract boolean unregister(@NonNull UUID uuid);
|
public abstract boolean unregister(@NonNull UUID uuid);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -53,13 +53,21 @@ public abstract class PackCodec {
|
|||||||
public abstract long size();
|
public abstract long size();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serializes the given resource pack into a byte buffer.
|
* Use {@link #serialize()} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public SeekableByteChannel serialize(@NonNull ResourcePack resourcePack) throws IOException {
|
||||||
|
return serialize();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes the given codec into a byte buffer.
|
||||||
*
|
*
|
||||||
* @param resourcePack the resource pack to serialize
|
|
||||||
* @return the serialized resource pack
|
* @return the serialized resource pack
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public abstract SeekableByteChannel serialize(@NonNull ResourcePack resourcePack) throws IOException;
|
public abstract SeekableByteChannel serialize() throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new resource pack from this codec.
|
* Creates a new resource pack from this codec.
|
||||||
@ -69,6 +77,13 @@ public abstract class PackCodec {
|
|||||||
@NonNull
|
@NonNull
|
||||||
protected abstract ResourcePack create();
|
protected abstract ResourcePack create();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new resource pack builder from this codec.
|
||||||
|
*
|
||||||
|
* @return the new resource pack builder
|
||||||
|
*/
|
||||||
|
protected abstract ResourcePack.@NonNull Builder createBuilder();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new pack provider from the given path.
|
* Creates a new pack provider from the given path.
|
||||||
*
|
*
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
package org.geysermc.geyser.api.pack;
|
package org.geysermc.geyser.api.pack;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.geysermc.geyser.api.GeyserApi;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a resource pack sent to Bedrock clients
|
* Represents a resource pack sent to Bedrock clients
|
||||||
@ -63,23 +63,12 @@ public interface ResourcePack {
|
|||||||
String contentKey();
|
String contentKey();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the content key of the resource pack. Lack of a content key can be represented by an empty string.
|
* The default subpack to tell Bedrock clients to load. Lack of a subpack to load is represented by an empty string.
|
||||||
*/
|
|
||||||
void contentKey(@NonNull String contentKey);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The subpack to tell Bedrock clients to load. Lack of a subpack to load is represented by an empty string.
|
|
||||||
*
|
*
|
||||||
* @return the subpack name, or an empty string if not set.
|
* @return the subpack name, or an empty string if not set.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
String subpackName();
|
String defaultSubpackName();
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the subpack name that clients should load.
|
|
||||||
* It must match one of the subpacks that can be found in the manifest.
|
|
||||||
*/
|
|
||||||
void subpackName(@Nullable String subpackName);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a resource pack with the given {@link PackCodec}.
|
* Creates a resource pack with the given {@link PackCodec}.
|
||||||
@ -91,4 +80,36 @@ public interface ResourcePack {
|
|||||||
static ResourcePack create(@NonNull PackCodec codec) {
|
static ResourcePack create(@NonNull PackCodec codec) {
|
||||||
return codec.create();
|
return codec.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link Builder} for a resource pack.
|
||||||
|
* It can be used to set a content key, or a default subpack.
|
||||||
|
*
|
||||||
|
* @param codec the {@link PackCodec} to base the builder on
|
||||||
|
* @return a {@link Builder} to build a resource pack.
|
||||||
|
*/
|
||||||
|
static Builder builder(@NonNull PackCodec codec) {
|
||||||
|
return GeyserApi.api().provider(Builder.class, codec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A builder for a resource pack. It allows providing a content key manually, or
|
||||||
|
* setting a default subpack.
|
||||||
|
*/
|
||||||
|
interface Builder {
|
||||||
|
|
||||||
|
ResourcePackManifest manifest();
|
||||||
|
|
||||||
|
PackCodec codec();
|
||||||
|
|
||||||
|
String contentKey();
|
||||||
|
|
||||||
|
String defaultSubpackName();
|
||||||
|
|
||||||
|
Builder contentKey(@NonNull String contentKey);
|
||||||
|
|
||||||
|
Builder defaultSubpackName(@NonNull String subpackName);
|
||||||
|
|
||||||
|
ResourcePack build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
public interface PriorityOption extends ResourcePackOption {
|
||||||
|
|
||||||
|
PriorityOption HIGH = PriorityOption.priority(10);
|
||||||
|
PriorityOption NORMAL = PriorityOption.priority(5);
|
||||||
|
PriorityOption LOW = PriorityOption.priority(0);
|
||||||
|
|
||||||
|
int priority();
|
||||||
|
|
||||||
|
static PriorityOption priority(int priority) {
|
||||||
|
if (priority < 0 || priority > 10) {
|
||||||
|
throw new IllegalArgumentException("Priority must be between 0 and 10 inclusive!");
|
||||||
|
}
|
||||||
|
return GeyserApi.api().provider(PriorityOption.class, priority);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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.pack.ResourcePack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a resource pack option that can be used to specify how a resource
|
||||||
|
* pack is sent to Bedrock clients.
|
||||||
|
*/
|
||||||
|
public interface ResourcePackOption {
|
||||||
|
|
||||||
|
Type type();
|
||||||
|
|
||||||
|
void validate(ResourcePack pack);
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
SUBPACK("subpack"),
|
||||||
|
PRIORITY("priority");
|
||||||
|
|
||||||
|
Type(String name) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
import org.geysermc.geyser.api.pack.ResourcePackManifest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be used to specify which subpack from a resource pack a player should load.
|
||||||
|
* Available subpacks can be seen in a resource pack manifest {@link ResourcePackManifest#subpacks()}
|
||||||
|
*/
|
||||||
|
public interface SubpackOption extends ResourcePackOption {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a subpack option based on a {@link ResourcePackManifest.Subpack}
|
||||||
|
*
|
||||||
|
* @param subpack the chosen subpack
|
||||||
|
* @return a subpack option specifying that subpack
|
||||||
|
*/
|
||||||
|
static SubpackOption subpack(ResourcePackManifest.Subpack subpack) {
|
||||||
|
return named(subpack.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a subpack option based on a subpack name.
|
||||||
|
*
|
||||||
|
* @param subpackName the name of the subpack
|
||||||
|
* @return a subpack option specifying a subpack with that name
|
||||||
|
*/
|
||||||
|
static SubpackOption named(String subpackName) {
|
||||||
|
return GeyserApi.api().provider(SubpackOption.class, subpackName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the subpack name of the chosen subpack.
|
||||||
|
*/
|
||||||
|
String subpackName();
|
||||||
|
}
|
@ -25,11 +25,18 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser.event.type;
|
package org.geysermc.geyser.event.type;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.geysermc.geyser.api.event.bedrock.SessionLoadResourcePacksEvent;
|
import org.geysermc.geyser.api.event.bedrock.SessionLoadResourcePacksEvent;
|
||||||
import org.geysermc.geyser.api.pack.ResourcePack;
|
import org.geysermc.geyser.api.pack.ResourcePack;
|
||||||
|
import org.geysermc.geyser.api.pack.option.PriorityOption;
|
||||||
|
import org.geysermc.geyser.api.pack.option.ResourcePackOption;
|
||||||
|
import org.geysermc.geyser.registry.Registries;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -37,10 +44,12 @@ import java.util.UUID;
|
|||||||
public class SessionLoadResourcePacksEventImpl extends SessionLoadResourcePacksEvent {
|
public class SessionLoadResourcePacksEventImpl extends SessionLoadResourcePacksEvent {
|
||||||
|
|
||||||
private final Map<String, ResourcePack> packs;
|
private final Map<String, ResourcePack> packs;
|
||||||
|
private final Map<String, Collection<ResourcePackOption>> options;
|
||||||
|
|
||||||
public SessionLoadResourcePacksEventImpl(GeyserSession session, Map<String, ResourcePack> packMap) {
|
public SessionLoadResourcePacksEventImpl(GeyserSession session) {
|
||||||
super(session);
|
super(session);
|
||||||
this.packs = packMap;
|
this.packs = new Object2ObjectLinkedOpenHashMap<>(Registries.RESOURCE_PACKS.get());
|
||||||
|
this.options = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NonNull Map<String, ResourcePack> getPacks() {
|
public @NonNull Map<String, ResourcePack> getPacks() {
|
||||||
@ -54,16 +63,35 @@ public class SessionLoadResourcePacksEventImpl extends SessionLoadResourcePacksE
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean register(@NonNull ResourcePack resourcePack) {
|
public boolean register(@NonNull ResourcePack resourcePack) {
|
||||||
|
return register(resourcePack, PriorityOption.NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean register(@NonNull ResourcePack resourcePack, ResourcePackOption... resourcePackOptions) {
|
||||||
|
for (ResourcePackOption option : resourcePackOptions) {
|
||||||
|
option.validate(resourcePack);
|
||||||
|
}
|
||||||
|
|
||||||
String packID = resourcePack.manifest().header().uuid().toString();
|
String packID = resourcePack.manifest().header().uuid().toString();
|
||||||
if (packs.containsValue(resourcePack) || packs.containsKey(packID)) {
|
if (packs.containsValue(resourcePack) || packs.containsKey(packID)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
packs.put(resourcePack.manifest().header().uuid().toString(), resourcePack);
|
|
||||||
|
String uuid = resourcePack.manifest().header().uuid().toString();
|
||||||
|
packs.put(uuid, resourcePack);
|
||||||
|
options.put(uuid, List.of(resourcePackOptions));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<ResourcePackOption> options(UUID resourcePack) {
|
||||||
|
Collection<ResourcePackOption> packOptions = options.get(resourcePack.toString());
|
||||||
|
return packOptions == null ? List.of() : Collections.unmodifiableCollection(packOptions);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean unregister(@NonNull UUID uuid) {
|
public boolean unregister(@NonNull UUID uuid) {
|
||||||
|
options.remove(uuid.toString());
|
||||||
return packs.remove(uuid.toString()) != null;
|
return packs.remove(uuid.toString()) != null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,6 @@ import java.nio.ByteBuffer;
|
|||||||
import java.nio.channels.SeekableByteChannel;
|
import java.nio.channels.SeekableByteChannel;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.OptionalInt;
|
import java.util.OptionalInt;
|
||||||
|
|
||||||
public class UpstreamPacketHandler extends LoggingPacketHandler {
|
public class UpstreamPacketHandler extends LoggingPacketHandler {
|
||||||
@ -200,7 +199,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
|
|||||||
|
|
||||||
geyser.getSessionManager().addPendingSession(session);
|
geyser.getSessionManager().addPendingSession(session);
|
||||||
|
|
||||||
this.resourcePackLoadEvent = new SessionLoadResourcePacksEventImpl(session, new HashMap<>(Registries.RESOURCE_PACKS.get()));
|
this.resourcePackLoadEvent = new SessionLoadResourcePacksEventImpl(session);
|
||||||
this.geyser.eventBus().fire(this.resourcePackLoadEvent);
|
this.geyser.eventBus().fire(this.resourcePackLoadEvent);
|
||||||
|
|
||||||
ResourcePacksInfoPacket resourcePacksInfo = new ResourcePacksInfoPacket();
|
ResourcePacksInfoPacket resourcePacksInfo = new ResourcePacksInfoPacket();
|
||||||
@ -208,7 +207,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
|
|||||||
ResourcePackManifest.Header header = pack.manifest().header();
|
ResourcePackManifest.Header header = pack.manifest().header();
|
||||||
resourcePacksInfo.getResourcePackInfos().add(new ResourcePacksInfoPacket.Entry(
|
resourcePacksInfo.getResourcePackInfos().add(new ResourcePacksInfoPacket.Entry(
|
||||||
header.uuid().toString(), header.version().toString(), pack.codec().size(), pack.contentKey(),
|
header.uuid().toString(), header.version().toString(), pack.codec().size(), pack.contentKey(),
|
||||||
pack.subpackName(), header.uuid().toString(), false, false));
|
pack.defaultSubpackName(), header.uuid().toString(), false, false));
|
||||||
}
|
}
|
||||||
resourcePacksInfo.setForcedToAccept(GeyserImpl.getInstance().getConfig().isForceResourcePacks());
|
resourcePacksInfo.setForcedToAccept(GeyserImpl.getInstance().getConfig().isForceResourcePacks());
|
||||||
session.sendUpstreamPacket(resourcePacksInfo);
|
session.sendUpstreamPacket(resourcePacksInfo);
|
||||||
|
@ -25,62 +25,90 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser.pack;
|
package org.geysermc.geyser.pack;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.geysermc.geyser.api.pack.PackCodec;
|
import org.geysermc.geyser.api.pack.PackCodec;
|
||||||
import org.geysermc.geyser.api.pack.ResourcePack;
|
import org.geysermc.geyser.api.pack.ResourcePack;
|
||||||
import org.geysermc.geyser.api.pack.ResourcePackManifest;
|
import org.geysermc.geyser.api.pack.ResourcePackManifest;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
public record GeyserResourcePack(
|
||||||
public class GeyserResourcePack implements ResourcePack {
|
PackCodec codec,
|
||||||
|
ResourcePackManifest manifest,
|
||||||
|
String contentKey,
|
||||||
|
String defaultSubpackName
|
||||||
|
) implements ResourcePack {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The size of each chunk to use when sending the resource packs to clients in bytes
|
* The size of each chunk to use when sending the resource packs to clients in bytes
|
||||||
*/
|
*/
|
||||||
public static final int CHUNK_SIZE = 102400;
|
public static final int CHUNK_SIZE = 102400;
|
||||||
|
|
||||||
private final PackCodec codec;
|
|
||||||
private final ResourcePackManifest manifest;
|
|
||||||
private String contentKey;
|
|
||||||
private String subpackName;
|
|
||||||
|
|
||||||
public GeyserResourcePack(PackCodec codec, ResourcePackManifest manifest, String contentKey) {
|
public GeyserResourcePack(PackCodec codec, ResourcePackManifest manifest, String contentKey) {
|
||||||
this(codec, manifest);
|
this(codec, manifest, contentKey, "");
|
||||||
this.contentKey = contentKey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NonNull PackCodec codec() {
|
|
||||||
return this.codec;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public static class Builder implements ResourcePack.Builder {
|
||||||
public @NonNull ResourcePackManifest manifest() {
|
|
||||||
return this.manifest;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public Builder(PackCodec codec, ResourcePackManifest manifest) {
|
||||||
public @NonNull String contentKey() {
|
this.codec = codec;
|
||||||
return this.contentKey == null ? "" : this.contentKey;
|
this.manifest = manifest;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Builder(PackCodec codec, ResourcePackManifest manifest, String contentKey) {
|
||||||
public void contentKey(@Nullable String contentKey) {
|
this.codec = codec;
|
||||||
this.contentKey = contentKey;
|
this.manifest = manifest;
|
||||||
}
|
this.contentKey = contentKey;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
private final PackCodec codec;
|
||||||
public @NonNull String subpackName() {
|
private final ResourcePackManifest manifest;
|
||||||
return this.subpackName == null ? "" : this.subpackName;
|
private String contentKey;
|
||||||
}
|
private String defaultSubpackName;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void subpackName(@Nullable String subpackName) {
|
public ResourcePackManifest manifest() {
|
||||||
if (manifest.subpacks().stream().anyMatch(subpack -> subpack.name().equals(subpackName))) {
|
return manifest;
|
||||||
this.subpackName = subpackName;
|
}
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("A subpack with the name '" + subpackName + "' does not exist!");
|
@Override
|
||||||
|
public PackCodec codec() {
|
||||||
|
return codec;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String contentKey() {
|
||||||
|
return this.contentKey == null ? "" : this.contentKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String defaultSubpackName() {
|
||||||
|
return this.defaultSubpackName == null ? "" : this.defaultSubpackName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder contentKey(@Nullable String contentKey) {
|
||||||
|
this.contentKey = contentKey;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder defaultSubpackName(@Nullable String subpackName) {
|
||||||
|
if (manifest.subpacks().stream().anyMatch(subpack -> subpack.name().equals(subpackName))) {
|
||||||
|
this.defaultSubpackName = subpackName;
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("A subpack with the name '" + subpackName + "' does not exist!");
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GeyserResourcePack build() {
|
||||||
|
if (contentKey == null) {
|
||||||
|
contentKey = "";
|
||||||
|
}
|
||||||
|
if (defaultSubpackName == null) {
|
||||||
|
defaultSubpackName = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return new GeyserResourcePack(codec, manifest, contentKey, defaultSubpackName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* 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.geysermc.geyser.api.pack.ResourcePack;
|
||||||
|
import org.geysermc.geyser.api.pack.option.PriorityOption;
|
||||||
|
|
||||||
|
public class GeyserPriorityOption implements PriorityOption {
|
||||||
|
|
||||||
|
private final int priority;
|
||||||
|
|
||||||
|
public int priority() {
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GeyserPriorityOption(int priority) {
|
||||||
|
if (priority < 0 || priority > 10) {
|
||||||
|
throw new IllegalArgumentException("Priority must be between 0 and 10 inclusive!");
|
||||||
|
}
|
||||||
|
this.priority = priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type type() {
|
||||||
|
return Type.PRIORITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validate(ResourcePack pack) {
|
||||||
|
if (priority <= 10 && priority > 0) {
|
||||||
|
throw new IllegalArgumentException("Priority must be between 0 and 10 inclusive!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* 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.geysermc.geyser.api.pack.ResourcePack;
|
||||||
|
import org.geysermc.geyser.api.pack.ResourcePackManifest;
|
||||||
|
import org.geysermc.geyser.api.pack.option.SubpackOption;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be used to specify which subpack from a resource pack a player should load.
|
||||||
|
* Available subpacks can be seen in a resource pack manifest {@link ResourcePackManifest#subpacks()}
|
||||||
|
*/
|
||||||
|
public class GeyserSubpackOption implements SubpackOption {
|
||||||
|
|
||||||
|
private final String subpackName;
|
||||||
|
|
||||||
|
public GeyserSubpackOption(String subpackName) {
|
||||||
|
this.subpackName = subpackName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type type() {
|
||||||
|
return Type.SUBPACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validate(ResourcePack pack) {
|
||||||
|
if (pack.manifest().subpacks().stream().noneMatch(subpack -> subpack.name().equals(subpackName))) {
|
||||||
|
throw new IllegalArgumentException("No subpack with the name %s found!".formatted(subpackName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String subpackName() {
|
||||||
|
return subpackName;
|
||||||
|
}
|
||||||
|
}
|
@ -79,15 +79,20 @@ public class GeyserPathPackCodec extends PathPackCodec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NonNull SeekableByteChannel serialize(@NonNull ResourcePack resourcePack) throws IOException {
|
public @NonNull SeekableByteChannel serialize() throws IOException {
|
||||||
return FileChannel.open(this.path);
|
return FileChannel.open(this.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected @NonNull ResourcePack create() {
|
protected ResourcePack.@NonNull Builder createBuilder() {
|
||||||
return ResourcePackLoader.readPack(this.path);
|
return ResourcePackLoader.readPack(this.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NonNull ResourcePack create() {
|
||||||
|
return createBuilder().build();
|
||||||
|
}
|
||||||
|
|
||||||
private void checkLastModified() {
|
private void checkLastModified() {
|
||||||
try {
|
try {
|
||||||
FileTime lastModified = Files.getLastModifiedTime(this.path);
|
FileTime lastModified = Files.getLastModifiedTime(this.path);
|
||||||
|
@ -40,10 +40,12 @@ import org.geysermc.geyser.api.item.custom.CustomItemData;
|
|||||||
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
|
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
|
||||||
import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData;
|
import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData;
|
||||||
import org.geysermc.geyser.api.pack.PathPackCodec;
|
import org.geysermc.geyser.api.pack.PathPackCodec;
|
||||||
import org.geysermc.geyser.impl.camera.GeyserCameraFade;
|
import org.geysermc.geyser.api.pack.option.PriorityOption;
|
||||||
import org.geysermc.geyser.impl.camera.GeyserCameraPosition;
|
import org.geysermc.geyser.api.pack.option.SubpackOption;
|
||||||
import org.geysermc.geyser.event.GeyserEventRegistrar;
|
import org.geysermc.geyser.event.GeyserEventRegistrar;
|
||||||
import org.geysermc.geyser.extension.command.GeyserExtensionCommand;
|
import org.geysermc.geyser.extension.command.GeyserExtensionCommand;
|
||||||
|
import org.geysermc.geyser.impl.camera.GeyserCameraFade;
|
||||||
|
import org.geysermc.geyser.impl.camera.GeyserCameraPosition;
|
||||||
import org.geysermc.geyser.item.GeyserCustomItemData;
|
import org.geysermc.geyser.item.GeyserCustomItemData;
|
||||||
import org.geysermc.geyser.item.GeyserCustomItemOptions;
|
import org.geysermc.geyser.item.GeyserCustomItemOptions;
|
||||||
import org.geysermc.geyser.item.GeyserNonVanillaCustomItemData;
|
import org.geysermc.geyser.item.GeyserNonVanillaCustomItemData;
|
||||||
@ -53,6 +55,8 @@ import org.geysermc.geyser.level.block.GeyserGeometryComponent;
|
|||||||
import org.geysermc.geyser.level.block.GeyserJavaBlockState;
|
import org.geysermc.geyser.level.block.GeyserJavaBlockState;
|
||||||
import org.geysermc.geyser.level.block.GeyserMaterialInstance;
|
import org.geysermc.geyser.level.block.GeyserMaterialInstance;
|
||||||
import org.geysermc.geyser.level.block.GeyserNonVanillaCustomBlockData;
|
import org.geysermc.geyser.level.block.GeyserNonVanillaCustomBlockData;
|
||||||
|
import org.geysermc.geyser.pack.option.GeyserPriorityOption;
|
||||||
|
import org.geysermc.geyser.pack.option.GeyserSubpackOption;
|
||||||
import org.geysermc.geyser.pack.path.GeyserPathPackCodec;
|
import org.geysermc.geyser.pack.path.GeyserPathPackCodec;
|
||||||
import org.geysermc.geyser.registry.provider.ProviderSupplier;
|
import org.geysermc.geyser.registry.provider.ProviderSupplier;
|
||||||
|
|
||||||
@ -66,9 +70,10 @@ public class ProviderRegistryLoader implements RegistryLoader<Map<Class<?>, Prov
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<Class<?>, ProviderSupplier> load(Map<Class<?>, ProviderSupplier> providers) {
|
public Map<Class<?>, ProviderSupplier> load(Map<Class<?>, ProviderSupplier> providers) {
|
||||||
// misc
|
// commands
|
||||||
providers.put(Command.Builder.class, args -> new GeyserExtensionCommand.Builder<>((Extension) args[0]));
|
providers.put(Command.Builder.class, args -> new GeyserExtensionCommand.Builder<>((Extension) args[0]));
|
||||||
|
|
||||||
|
// custom blocks
|
||||||
providers.put(CustomBlockComponents.Builder.class, args -> new GeyserCustomBlockComponents.Builder());
|
providers.put(CustomBlockComponents.Builder.class, args -> new GeyserCustomBlockComponents.Builder());
|
||||||
providers.put(CustomBlockData.Builder.class, args -> new GeyserCustomBlockData.Builder());
|
providers.put(CustomBlockData.Builder.class, args -> new GeyserCustomBlockData.Builder());
|
||||||
providers.put(JavaBlockState.Builder.class, args -> new GeyserJavaBlockState.Builder());
|
providers.put(JavaBlockState.Builder.class, args -> new GeyserJavaBlockState.Builder());
|
||||||
@ -76,8 +81,13 @@ public class ProviderRegistryLoader implements RegistryLoader<Map<Class<?>, Prov
|
|||||||
providers.put(MaterialInstance.Builder.class, args -> new GeyserMaterialInstance.Builder());
|
providers.put(MaterialInstance.Builder.class, args -> new GeyserMaterialInstance.Builder());
|
||||||
providers.put(GeometryComponent.Builder.class, args -> new GeyserGeometryComponent.Builder());
|
providers.put(GeometryComponent.Builder.class, args -> new GeyserGeometryComponent.Builder());
|
||||||
|
|
||||||
|
// misc
|
||||||
providers.put(EventRegistrar.class, args -> new GeyserEventRegistrar(args[0]));
|
providers.put(EventRegistrar.class, args -> new GeyserEventRegistrar(args[0]));
|
||||||
|
|
||||||
|
// packs
|
||||||
providers.put(PathPackCodec.class, args -> new GeyserPathPackCodec((Path) args[0]));
|
providers.put(PathPackCodec.class, args -> new GeyserPathPackCodec((Path) args[0]));
|
||||||
|
providers.put(PriorityOption.class, args -> new GeyserPriorityOption((int) args[0]));
|
||||||
|
providers.put(SubpackOption.class, args -> new GeyserSubpackOption((String) args[0]));
|
||||||
|
|
||||||
// items
|
// items
|
||||||
providers.put(CustomItemData.Builder.class, args -> new GeyserCustomItemData.Builder());
|
providers.put(CustomItemData.Builder.class, args -> new GeyserCustomItemData.Builder());
|
||||||
|
@ -99,7 +99,7 @@ public class ResourcePackLoader implements RegistryLoader<Path, Map<String, Reso
|
|||||||
|
|
||||||
for (Path path : event.resourcePacks()) {
|
for (Path path : event.resourcePacks()) {
|
||||||
try {
|
try {
|
||||||
GeyserResourcePack pack = readPack(path);
|
GeyserResourcePack pack = readPack(path).build();
|
||||||
packMap.put(pack.manifest().header().uuid().toString(), pack);
|
packMap.put(pack.manifest().header().uuid().toString(), pack);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -113,10 +113,10 @@ public class ResourcePackLoader implements RegistryLoader<Path, Map<String, Reso
|
|||||||
* but suffixed by ".key", containing the content key. If such file does not exist, no content key is stored.
|
* but suffixed by ".key", containing the content key. If such file does not exist, no content key is stored.
|
||||||
*
|
*
|
||||||
* @param path the file to read from, in ZIP format
|
* @param path the file to read from, in ZIP format
|
||||||
* @return a {@link ResourcePack} representation
|
* @return a {@link ResourcePack.Builder} representation
|
||||||
* @throws IllegalArgumentException if the pack manifest was invalid or there was any processing exception
|
* @throws IllegalArgumentException if the pack manifest was invalid or there was any processing exception
|
||||||
*/
|
*/
|
||||||
public static GeyserResourcePack readPack(Path path) throws IllegalArgumentException {
|
public static GeyserResourcePack.Builder readPack(Path path) throws IllegalArgumentException {
|
||||||
if (!path.getFileName().toString().endsWith(".mcpack") && !path.getFileName().toString().endsWith(".zip")) {
|
if (!path.getFileName().toString().endsWith(".mcpack") && !path.getFileName().toString().endsWith(".zip")) {
|
||||||
throw new IllegalArgumentException("Resource pack " + path.getFileName() + " must be a .zip or .mcpack file!");
|
throw new IllegalArgumentException("Resource pack " + path.getFileName() + " must be a .zip or .mcpack file!");
|
||||||
}
|
}
|
||||||
@ -155,7 +155,7 @@ public class ResourcePackLoader implements RegistryLoader<Path, Map<String, Reso
|
|||||||
Path keyFile = path.resolveSibling(path.getFileName().toString() + ".key");
|
Path keyFile = path.resolveSibling(path.getFileName().toString() + ".key");
|
||||||
String contentKey = Files.exists(keyFile) ? Files.readString(keyFile, StandardCharsets.UTF_8) : "";
|
String contentKey = Files.exists(keyFile) ? Files.readString(keyFile, StandardCharsets.UTF_8) : "";
|
||||||
|
|
||||||
return new GeyserResourcePack(new GeyserPathPackCodec(path), manifest, contentKey);
|
return new GeyserResourcePack.Builder(new GeyserPathPackCodec(path), manifest, contentKey);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IllegalArgumentException(GeyserLocale.getLocaleStringLog("geyser.resource_pack.broken", path.getFileName()), e);
|
throw new IllegalArgumentException(GeyserLocale.getLocaleStringLog("geyser.resource_pack.broken", path.getFileName()), e);
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ public class ResourcePackLoaderTest {
|
|||||||
public void testPack() throws Exception {
|
public void testPack() throws Exception {
|
||||||
// this mcpack only contains a folder, which the manifest is in
|
// this mcpack only contains a folder, which the manifest is in
|
||||||
Path path = getResource("empty_pack.mcpack");
|
Path path = getResource("empty_pack.mcpack");
|
||||||
ResourcePack pack = ResourcePackLoader.readPack(path);
|
ResourcePack pack = ResourcePackLoader.readPack(path).build();
|
||||||
assertEquals("", pack.contentKey());
|
assertEquals("", pack.contentKey());
|
||||||
// should probably add some more tests here related to the manifest
|
// should probably add some more tests here related to the manifest
|
||||||
}
|
}
|
||||||
@ -71,7 +71,7 @@ public class ResourcePackLoaderTest {
|
|||||||
public void testEncryptedPack() throws Exception {
|
public void testEncryptedPack() throws Exception {
|
||||||
// this zip only contains a contents.json and manifest.json at the root
|
// this zip only contains a contents.json and manifest.json at the root
|
||||||
Path path = getResource("encrypted_pack.zip");
|
Path path = getResource("encrypted_pack.zip");
|
||||||
ResourcePack pack = ResourcePackLoader.readPack(path);
|
ResourcePack pack = ResourcePackLoader.readPack(path).build();
|
||||||
assertEquals("JAGcSXcXwcODc1YS70GzeWAUKEO172UA", pack.contentKey());
|
assertEquals("JAGcSXcXwcODc1YS70GzeWAUKEO172UA", pack.contentKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren