Skip to content

Commit

Permalink
Port Resource Loader + Add overlay API
Browse files Browse the repository at this point in the history
  • Loading branch information
OroArmor committed Jul 21, 2024
1 parent ac24778 commit 110d052
Show file tree
Hide file tree
Showing 26 changed files with 223 additions and 109 deletions.
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@

import net.minecraft.resource.ResourceIoSupplier;
import net.minecraft.resource.ResourceType;
import net.minecraft.resource.pack.CompositeResourcePack;
import net.minecraft.resource.pack.PackLocationInfo;
import net.minecraft.resource.pack.PackProfile;
import net.minecraft.resource.pack.ResourcePack;
import net.minecraft.resource.pack.metadata.ResourceMetadataSectionReader;
import net.minecraft.text.Text;
Expand All @@ -53,7 +55,6 @@ public abstract class GroupPack implements ResourcePack {
protected final ResourceType type;
protected final List<? extends ResourcePack> packs;
protected final Map<String, List<ResourcePack>> namespacedPacks = new Object2ObjectOpenHashMap<>();
private boolean builtin;

public GroupPack(@NotNull ResourceType type, @NotNull List<? extends ResourcePack> packs) {
this.type = type;
Expand Down Expand Up @@ -150,6 +151,8 @@ public void close() {
this.packs.forEach(ResourcePack::close);
}

public abstract PackProfile.PackFactory wrapToFactory();

/**
* Represents a group resource pack which wraps a "base" resource pack.
*/
Expand Down Expand Up @@ -213,5 +216,39 @@ public String getName() {
return this.getName() + " (" + this.packs.stream().filter(pack -> pack != this.basePack)
.map(ResourcePack::getName).collect(Collectors.joining(", ")) + ")";
}

@Override
public @NotNull ResourcePack createOverlay(String overlay) {
return new Wrapped(
this.type,
this.basePack.createOverlay(overlay),
this.packs.stream().map(pack -> pack.createOverlay(overlay)).toList(),
false
);
}

@Override
public PackProfile.PackFactory wrapToFactory() {
return new PackProfile.PackFactory() {
@Override
public ResourcePack openPrimary(PackLocationInfo locationInfo) {
return Wrapped.this;
}

@Override
public ResourcePack open(PackLocationInfo locationInfo, PackProfile.Metadata metadata) {
if (metadata.overlays().isEmpty()) {
return Wrapped.this;
}

List<ResourcePack> overlays = metadata.overlays()
.stream()
.map(Wrapped.this::createOverlay)
.toList();

return new CompositeResourcePack(Wrapped.this, overlays);
}
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import net.minecraft.resource.ResourceIoSupplier;
import net.minecraft.resource.ResourceType;
import net.minecraft.resource.pack.PackLocationInfo;
import net.minecraft.resource.pack.PackSource;
import net.minecraft.resource.pack.ResourcePack;
import net.minecraft.resource.pack.metadata.ResourceMetadataSectionReader;
import net.minecraft.text.Text;
Expand All @@ -62,6 +63,7 @@
* <p>
* The resources of this pack are stored in memory instead of it being on-disk.
*/
// TODO: Add API for overlays
public abstract class InMemoryPack implements MutablePack {
private static final Logger LOGGER = LogUtils.getLogger();
private static final ExecutorService EXECUTOR_SERVICE;
Expand All @@ -72,6 +74,8 @@ public abstract class InMemoryPack implements MutablePack {
private final Map<Identifier, Supplier<byte[]>> data = new ConcurrentHashMap<>();
private final Map<String, Supplier<byte[]>> root = new ConcurrentHashMap<>();

private final Map<String, ResourcePack> overlays = new ConcurrentHashMap<>();

@Override
public @Nullable ResourceIoSupplier<InputStream> openRoot(String... path) {
String actualPath = String.join("/", path);
Expand Down Expand Up @@ -204,6 +208,11 @@ public void putResource(@NotNull ResourceType type, @NotNull Identifier id, @Not
return future;
}

@Override
public void putOverlay(@NotNull String overlay, ResourcePack pack) {
this.overlays.put(overlay, pack);
}

@Override
public void clearResources(ResourceType type) {
this.getResourceMap(type).clear();
Expand All @@ -212,6 +221,7 @@ public void clearResources(ResourceType type) {
@Override
public void clearResources() {
this.root.clear();
this.overlays.clear();
this.clearResources(ResourceType.CLIENT_RESOURCES);
this.clearResources(ResourceType.SERVER_DATA);
}
Expand All @@ -230,6 +240,14 @@ public void dumpTo(@NotNull Path path) {
this.dumpResource(path, QuiltPack.getResourcePath(ResourceType.CLIENT_RESOURCES, p), resource.get()));
this.data.forEach((p, resource) ->
this.dumpResource(path, QuiltPack.getResourcePath(ResourceType.SERVER_DATA, p), resource.get()));
this.overlays.forEach((overlay, pack) -> {
if (pack instanceof InMemoryPack imp) {
imp.dumpTo(path.resolve(overlay));
return;
}

LOGGER.info("Unable to dump overlay {} ({}) from In Memory Pack {}", overlay, pack.getName(), this.getName());
});
} catch (IOException e) {
LOGGER.error("Failed to write resource pack dump from pack {} to {}.", this.getName(), path, e);
}
Expand Down Expand Up @@ -275,6 +293,10 @@ private Map<Identifier, Supplier<byte[]>> getResourceMap(ResourceType type) {
);
}

protected PackSource getSource() {
return PackSource.PACK_SOURCE_BUILTIN;
}

/**
* Represents an in-memory resource pack with a static name.
*/
Expand All @@ -290,7 +312,7 @@ public PackLocationInfo getLocationInfo() {
return new PackLocationInfo(
this.name,
Text.literal(this.name),
null,
this.getSource(),
Optional.empty()
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.Future;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

Expand Down Expand Up @@ -108,7 +109,7 @@ public interface MutablePack extends ResourcePack {
* @see #putResource(ResourceType, Identifier, Supplier)
*/
@NotNull Future<byte[]> putResourceAsync(@NotNull ResourceType type, @NotNull Identifier id,
@NotNull Function<@NotNull Identifier, byte @NotNull []> resourceFactory);
@NotNull Function<@NotNull Identifier, byte @NotNull []> resourceFactory);

/**
* Puts a text resource into the resource pack's root.
Expand Down Expand Up @@ -180,7 +181,7 @@ default void putText(@NotNull ResourceType type, @NotNull Identifier id, @NotNul
* @see #putResourceAsync(ResourceType, Identifier, Function)
*/
default @NotNull Future<byte[]> putTextAsync(@NotNull ResourceType type, @NotNull Identifier id,
@NotNull Function<@NotNull Identifier, @NotNull String> textFactory) {
@NotNull Function<@NotNull Identifier, @NotNull String> textFactory) {
return this.putResourceAsync(type, id, textFactory.andThen(text -> text.getBytes(StandardCharsets.UTF_8)));
}

Expand Down Expand Up @@ -293,6 +294,14 @@ default void putImage(Identifier id, Supplier<NativeImage> imageSupplier) {
}));
}

/**
* Adds a pack overlay to the mutable pack.
*
* @param overlay the overlay name
* @param pack the pack
*/
void putOverlay(@NotNull String overlay, ResourcePack pack);

/**
* Clears the resource of a specific resource type.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ public interface QuiltPack {
return PackActivationType.NORMAL;
}

/**
* Creates the specified overlay for the pack.
*
* @return the activation type of this resource pack
*/
default @NotNull ResourcePack createOverlay(String overlay) {
return (ResourcePack) this;
}

/**
* {@return the path inside a resource pack of the given resource path}
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ public final class ResourceReloaderKeys {
*
* @see org.quiltmc.qsl.resource.loader.api.ResourceLoader#addReloaderOrdering(Identifier, Identifier)
*/
public static final Identifier BEFORE_VANILLA = new Identifier("quilt", "before_vanilla");
public static final Identifier BEFORE_VANILLA = Identifier.of("quilt", "before_vanilla");
/**
* Represents the application phase after Vanilla resource reloaders are invoked.
* <p>
* No resource reloaders are assigned to this identifier.
*
* @see org.quiltmc.qsl.resource.loader.api.ResourceLoader#addReloaderOrdering(Identifier, Identifier)
*/
public static final Identifier AFTER_VANILLA = new Identifier("quilt", "after_vanilla");
public static final Identifier AFTER_VANILLA = Identifier.of("quilt", "after_vanilla");

/**
* Keys for various client resource reloaders.
Expand Down Expand Up @@ -87,6 +87,6 @@ private ResourceReloaderKeys() {
}

private static Identifier id(String path) {
return new Identifier(Identifier.DEFAULT_NAMESPACE, path);
return Identifier.ofDefault(path);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,19 @@ public void close() {
}
}

@Override
public @NotNull ResourcePack createOverlay(String overlay) {
return new ModNioPack(
this.name,
this.modInfo,
this.displayName,
this.activationType,
this.io.basePath.resolve(overlay),
this.type,
this.closer
);
}

//region metadata
@Override
public String getName() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,8 @@
import net.minecraft.resource.pack.DataPackSettings;
import net.minecraft.resource.pack.PackProfile;
import net.minecraft.resource.pack.ResourcePack;
import net.minecraft.unmapped.C_yzksgymh;

import org.quiltmc.loader.api.ModMetadata;
import org.quiltmc.qsl.resource.loader.api.QuiltPackProfile;

@ApiStatus.Internal
public final class ModPackUtil {
Expand Down Expand Up @@ -99,30 +97,4 @@ public static DataPackSettings createDefaultDataPackSettings(DataPackSettings so

return new DataPackSettings(enabled, disabled);
}

public static PackProfile makeBuiltinPackProfile(ModNioPack pack, PackProfile.Metadata info) {
return PackProfile.of(
pack.getLocationInfo(),
QuiltPackProfile.wrapToFactory(pack),
ResourceType.CLIENT_RESOURCES,
new C_yzksgymh(
true,
PackProfile.InsertionPosition.TOP,
false
)
);
}

static @Nullable PackProfile makeBuiltinPackProfile(ModNioPack pack) {
// I think the resource version really shouldn't matter here, but we'll go for the latest asset version just in case
PackProfile.Metadata info = PackProfile.loadMetadata(pack.getLocationInfo(), QuiltPackProfile.wrapToFactory(pack),
SharedConstants.getGameVersion().getResourceVersion(ResourceType.CLIENT_RESOURCES));

if (info == null) {
LOGGER.warn("Couldn't find pack meta for pack {}.", pack.getName());
return null;
}

return makeBuiltinPackProfile(pack, info);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@
import org.slf4j.Logger;

import net.minecraft.SharedConstants;
import net.minecraft.resource.PackPosition;
import net.minecraft.resource.pack.PackCompatibility;
import net.minecraft.resource.pack.PackProfile;
import net.minecraft.resource.pack.PackSource;
import net.minecraft.resource.pack.ResourcePack;
import net.minecraft.text.Text;
import net.minecraft.unmapped.C_yzksgymh;
import net.minecraft.util.Formatting;

import org.quiltmc.qsl.resource.loader.api.QuiltPackProfile;
Expand Down Expand Up @@ -56,7 +56,7 @@ private QuiltBuiltinPackProfile(ModNioPack pack, Metadata info) {
pack.getLocationInfo(),
QuiltPackProfile.wrapToFactory(pack),
info,
new C_yzksgymh(
new PackPosition(
true,
PackProfile.InsertionPosition.TOP,
false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ private void sort(List<ResourceReloader> reloaders) {
if (currentReloader instanceof IdentifiableResourceReloader identifiable) {
id = identifiable.getQuiltId();
} else {
id = new Identifier("unknown",
id = Identifier.of("unknown",
"private/"
+ currentReloader.getClass().getName()
.replace(".", "/")
Expand Down Expand Up @@ -488,7 +488,7 @@ public static void registerBuiltinPacks(ResourceType type, Consumer<PackProfile>
// Add the built-in pack only if namespaces for the specified resource type are present.
if (!pack.getNamespaces(type).isEmpty()) {
// Make the resource pack profile for built-in pack, should never be always enabled.
var profile = ModPackUtil.makeBuiltinPackProfile(pack);
var profile = QuiltBuiltinPackProfile.of(pack);

if (profile != null) {
profileAdder.accept(profile);
Expand All @@ -511,7 +511,7 @@ public static void appendLanguageEntries(@NotNull Map<String, String> map) {

try (var manager = new MultiPackResourceManager(ResourceType.CLIENT_RESOURCES, List.of(pack))) {
for (var namespace : manager.getAllNamespaces()) {
var langId = new Identifier(namespace, "lang/" + Language.DEFAULT_LANGUAGE + ".json");
var langId = Identifier.of(namespace, "lang/" + Language.DEFAULT_LANGUAGE + ".json");

for (var resource : manager.getAllResources(langId)) {
try (var stream = resource.open()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2024 The Quilt Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.quiltmc.qsl.resource.loader.mixin;

import java.util.List;

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import net.minecraft.resource.pack.CompositeResourcePack;
import net.minecraft.resource.pack.PackLocationInfo;
import net.minecraft.resource.pack.PackProfile;
import net.minecraft.resource.pack.ResourcePack;

@Mixin(targets = {"net/minecraft/resource/pack/BuiltinPackProvider$C_oniaunfd"})
public class BuiltinPackProvider$WrapToFactory$PackFactoryMixin {
@Shadow
ResourcePack resourcePack;

@Inject(method = "open", at = @At("RETURN"), cancellable = true)
private void onRegisterAdditionalPacks(PackLocationInfo locationInfo, PackProfile.Metadata metadata, CallbackInfoReturnable<ResourcePack> ci) {
if (metadata.overlays().isEmpty()) {
return;
}

List<ResourcePack> overlays = metadata.overlays()
.stream()
.map(this.resourcePack::createOverlay)
.toList();

ci.setReturnValue(new CompositeResourcePack(this.resourcePack, overlays));
}
}
Loading

0 comments on commit 110d052

Please sign in to comment.