Skip to content

Commit

Permalink
Refactor code to merge duplicate resources in a pack
Browse files Browse the repository at this point in the history
  • Loading branch information
portlek committed Jul 12, 2024
1 parent 97bdd51 commit 8903cf9
Show file tree
Hide file tree
Showing 18 changed files with 385 additions and 110 deletions.
55 changes: 1 addition & 54 deletions blank/src/main/java/net/infumia/pack/BlankSlot.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,7 @@

import net.kyori.adventure.key.Key;
import net.kyori.adventure.key.KeyPattern;
import team.unnamed.creative.atlas.Atlas;
import team.unnamed.creative.atlas.AtlasSource;
import team.unnamed.creative.base.Writable;
import team.unnamed.creative.model.ItemOverride;
import team.unnamed.creative.model.ItemPredicate;
import team.unnamed.creative.model.Model;
import team.unnamed.creative.model.ModelTexture;
import team.unnamed.creative.model.ModelTextures;
import team.unnamed.creative.texture.Texture;

/**
* Utility class for creating and retrieving blank slot file resources.
Expand All @@ -26,51 +18,6 @@ public static FileResource get() {
return Internal0.BLANK_SLOT.get();
}

/**
* Creates a blank slot file resource with the specified parameters.
*
* @param itemKey The key for the item. Cannot be null.
* @param baseKey The key for the base model. Cannot be null.
* @param blankSlotImage The writable image for the blank slot. Cannot be null.
* @param customModelData The custom model data value.
* @return A {@link FileResource} representing the created blank slot.
*/
public static FileResource create(
final Key itemKey,
final Key baseKey,
final Writable blankSlotImage,
final int customModelData
) {
return FileResources.all(
FileResources.model(
Model.model()
.key(itemKey)
.parent(Model.ITEM_GENERATED)
.textures(ModelTextures.builder().layers(ModelTexture.ofKey(itemKey)).build())
.build()
),
FileResources.model(
Model.model()
.key(baseKey)
.parent(Model.ITEM_GENERATED)
.textures(ModelTextures.builder().layers(ModelTexture.ofKey(baseKey)).build())
.overrides(
ItemOverride.of(itemKey, ItemPredicate.customModelData(customModelData))
)
.build()
),
FileResources.texture(
Texture.texture(Internal.keyWithPngExtension(itemKey), blankSlotImage)
),
FileResources.atlas(
Atlas.atlas()
.key(Atlas.BLOCKS)
.sources(AtlasSource.directory(itemKey.namespace(), itemKey.namespace() + "/"))
.build()
)
);
}

/**
* Creates a blank slot file resource with the specified parameters.
*
Expand All @@ -88,7 +35,7 @@ public static FileResource create(
final Writable blankSlotImage,
final int customModelData
) {
return BlankSlot.create(
return ResourceProducers.item(
Key.key(namespace, itemId),
baseKey,
blankSlotImage,
Expand Down
4 changes: 1 addition & 3 deletions common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,4 @@ import net.infumia.gradle.publish

publish()

dependencies {
compileOnly(libs.creative.api)
}
dependencies { compileOnly(libs.creative.api) }
2 changes: 1 addition & 1 deletion common/src/main/java/net/infumia/pack/FileResourceAll.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

final class FileResourceAll implements FileResource {

private final Collection<FileResource> resources;
final Collection<FileResource> resources;

FileResourceAll(final Collection<FileResource> resources) {
this.resources = resources;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

final class FileResourceAtlas implements FileResource {

private final Atlas atlas;
final Atlas atlas;

FileResourceAtlas(final Atlas atlas) {
this.atlas = atlas;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

final class FileResourceFont implements FileResource {

private final Font font;
final Font font;

FileResourceFont(final Font font) {
this.font = font;
Expand Down
21 changes: 21 additions & 0 deletions common/src/main/java/net/infumia/pack/FileResourceMerger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package net.infumia.pack;

import java.util.Collection;
import team.unnamed.creative.atlas.Atlas;
import team.unnamed.creative.model.Model;

/**
* Represents a file resource merger that can merge a collection of file resources.
*/
public interface FileResourceMerger {
/**
* Merges a collection of {@link FileResources} into a unified resource.
* <p>
* Tries to merge duplicate {@link Atlas}s and {@link Model}s.
*
* @param resources the collection of {@link FileResources} to merge. Cannot be null.
*
* @return the merged collection of {@link FileResource}s. Cannot be null.
*/
Collection<FileResource> merge(Collection<FileResource> resources);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package net.infumia.pack;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.stream.Collectors;
import net.kyori.adventure.key.Key;
import team.unnamed.creative.atlas.Atlas;
import team.unnamed.creative.model.Model;

final class FileResourceMergerDefault implements FileResourceMerger {

static final FileResourceMerger INSTANCE = new FileResourceMergerDefault();

private FileResourceMergerDefault() {}

@Override
public Collection<FileResource> merge(final Collection<FileResource> resources) {
final Collection<FileResource> simplified = new HashSet<>(resources.size());
for (final FileResource resource : resources) {
simplified.addAll(this.simplify(resource));
}

final MultiMap<Key, Atlas> atlases = new MultiMap<>();
final MultiMap<Key, Model> models = new MultiMap<>();
for (final FileResource resource : simplified) {
if (resource instanceof FileResourceAtlas) {
final Atlas atlas = ((FileResourceAtlas) resource).atlas;
atlases.put(atlas.key(), atlas);
} else if (resource instanceof FileResourceModel) {
final Model model = ((FileResourceModel) resource).model;
models.put(model.key(), model);
}
// TODO: portlek, Merge more things.
}

final Collection<Atlas> mergedAtlases = new HashSet<>(atlases.keys().size());
for (final Key key : atlases.keys()) {
final Collection<Atlas> duplicates = atlases.get(key);
final Atlas merged = Atlas.atlas()
.key(key)
.sources(
duplicates
.stream()
.map(Atlas::sources)
.flatMap(Collection::stream)
.collect(Collectors.toList())
)
.build();
mergedAtlases.add(merged);
}

final Collection<Model> mergedModels = new HashSet<>(models.keys().size());
for (final Key key : models.keys()) {
final Collection<Model> duplicates = models.get(key);
final Model.Builder builder = Model.model().key(key);
// TODO: portlek, Find a way to merge these too.
for (final Model duplicate : duplicates) {
builder
.guiLight(duplicate.guiLight())
.elements(duplicate.elements())
.parent(duplicate.parent())
.ambientOcclusion(duplicate.ambientOcclusion())
.display(duplicate.display())
.textures(duplicate.textures());
}
builder.overrides(
duplicates
.stream()
.map(Model::overrides)
.flatMap(Collection::stream)
.collect(Collectors.toList())
);
mergedModels.add(builder.build());
}

final Collection<FileResource> mergedResources = mergedAtlases
.stream()
.map(FileResources::atlas)
.collect(Collectors.toSet());
mergedResources.addAll(
mergedModels.stream().map(FileResources::model).collect(Collectors.toSet())
);
return mergedResources;
}

private Collection<FileResource> simplify(final FileResource resource) {
if (resource instanceof FileResourceAll) {
return ((FileResourceAll) resource).resources.stream()
.map(this::simplify)
.flatMap(Collection::stream)
.collect(Collectors.toSet());
} else {
return Collections.singleton(resource);
}
}
}
20 changes: 20 additions & 0 deletions common/src/main/java/net/infumia/pack/FileResourceMergers.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package net.infumia.pack;

/**
* Utility class for providing various implementations of {@link FileResourceMerger}.
*/
public final class FileResourceMergers {

/**
* Returns a simple file resource merger implementation.
*
* @return A {@link FileResourceMerger} representing the simple file resource merger.
*/
public static FileResourceMerger simple() {
return FileResourceMergerDefault.INSTANCE;
}

private FileResourceMergers() {
throw new IllegalStateException("Utility class");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

final class FileResourceModel implements FileResource {

private final Model model;
final Model model;

FileResourceModel(final Model model) {
this.model = model;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

final class FileResourceTexture implements FileResource {

private final Texture texture;
final Texture texture;

FileResourceTexture(final Texture texture) {
this.texture = texture;
Expand Down
41 changes: 41 additions & 0 deletions common/src/main/java/net/infumia/pack/MultiMap.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package net.infumia.pack;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

final class MultiMap<K, V> {

private final Map<K, Collection<V>> map = new HashMap<>();

MultiMap() {}

void put(final K key, final V value) {
this.map.computeIfAbsent(key, __ -> new HashSet<>()).add(value);
}

Collection<V> get(final K key) {
return this.map.get(key);
}

boolean remove(final K key, final V value) {
final Collection<V> values = this.map.get(key);
if (values == null) {
return false;
}
final boolean removed = values.remove(value);
if (values.isEmpty()) {
this.map.remove(key);
}
return removed;
}

void clear() {
this.map.clear();
}

Collection<K> keys() {
return this.map.keySet();
}
}
7 changes: 6 additions & 1 deletion common/src/main/java/net/infumia/pack/PackDefault.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
final class PackDefault implements Pack {

private final FileResourceCompiler compiler;
private final FileResourceMerger merger;
private final Map<String, ResourceProducer> raw = new HashMap<>();
private final Map<String, ResourceProducer> compiled = new HashMap<>();
private final Set<FileResource> resources = new HashSet<>();

PackDefault(final FileResourceCompiler compiler) {
PackDefault(final FileResourceCompiler compiler, final FileResourceMerger merger) {
this.compiler = compiler;
this.merger = merger;
}

@Override
Expand All @@ -29,6 +31,9 @@ public Collection<FileResource> all() {
public void compileAll() {
final Collection<FileResource> resources = this.compiler.compile(this.raw.values());
this.resources.addAll(resources);
final Collection<FileResource> mergedResources = this.merger.merge(this.resources);
this.resources.clear();
this.resources.addAll(mergedResources);
this.compiled.putAll(this.raw);
this.raw.clear();
}
Expand Down
10 changes: 7 additions & 3 deletions common/src/main/java/net/infumia/pack/Packs.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ public final class Packs {
* Creates a new Pack instance with the specified file resource compiler.
*
* @param compiler The file resource compiler to use. Cannot be null.
* @param merger The merger to be used to merge same file resources. Cannot be null.
* @return A new Pack instance.
*/
public static Pack create(final FileResourceCompiler compiler) {
return new PackDefault(compiler);
public static Pack create(
final FileResourceCompiler compiler,
final FileResourceMerger merger
) {
return new PackDefault(compiler, merger);
}

/**
Expand All @@ -21,7 +25,7 @@ public static Pack create(final FileResourceCompiler compiler) {
* @return A new Pack instance.
*/
public static Pack create() {
return Packs.create(FileResourceCompilers.simple());
return Packs.create(FileResourceCompilers.simple(), FileResourceMergers.simple());
}

private Packs() {
Expand Down
Loading

0 comments on commit 8903cf9

Please sign in to comment.