Skip to content

Commit

Permalink
Add support for atlas format
Browse files Browse the repository at this point in the history
  • Loading branch information
Patbox committed Dec 6, 2024
1 parent 0e60130 commit c4f39c9
Show file tree
Hide file tree
Showing 19 changed files with 667 additions and 61 deletions.
28 changes: 26 additions & 2 deletions polymer-core/src/testmod/java/eu/pb4/polymertest/TestMod.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
import eu.pb4.polymer.core.impl.client.InternalClientRegistry;
import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils;
import eu.pb4.polymer.resourcepack.extras.api.ResourcePackExtras;
import eu.pb4.polymer.resourcepack.extras.api.format.atlas.AtlasAsset;
import eu.pb4.polymer.resourcepack.extras.api.format.item.ItemAsset;
import eu.pb4.polymer.resourcepack.extras.api.format.model.Model;
import eu.pb4.polymer.resourcepack.extras.api.format.model.ModelAsset;
import eu.pb4.polymer.virtualentity.api.tracker.EntityTrackedData;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.ModInitializer;
Expand Down Expand Up @@ -503,6 +504,7 @@ public void onInitialize() {
var vanillaJar = PolymerCommonUtils.getClientJarRoot();
var itemsBase = vanillaJar.resolve("/assets/minecraft/items/");
var modelsBase = vanillaJar.resolve("/assets/minecraft/models/");
var atlasBase = vanillaJar.resolve("/assets/minecraft/atlases/");

try {
var value = new MutableInt();
Expand Down Expand Up @@ -535,7 +537,7 @@ public void onInitialize() {
}
count.increment();
try {
var asset = Model.fromJson(Files.readString(path));
var asset = ModelAsset.fromJson(Files.readString(path));
//System.out.println(path + ">" + asset);
value.increment();
} catch (Throwable e) {
Expand All @@ -548,6 +550,28 @@ public void onInitialize() {
e.printStackTrace();
}

try {
var value = new MutableInt();
var count = new MutableInt();
Files.walk(atlasBase).forEach(path -> {
if (!path.toString().endsWith(".json")) {
return;
}
count.increment();
try {
var asset = AtlasAsset.fromJson(Files.readString(path));
//System.out.println(path + ">" + asset);
value.increment();
} catch (Throwable e) {
System.err.println("Error while parsing file: " + path);
e.printStackTrace();
}
});
System.out.println("Parsed " + value + " out of " + count + " atlases!");
} catch (IOException e) {
e.printStackTrace();
}


}).run();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public static Identifier bridgeModel(Identifier model) {
/**
* Adds a bridge, allowing you to access any model from selected folder as `namespace:-/modelpath`.
*
* @param modelFolderId Model folder to bridge. For example "mod:block" will bridge all models from "assets/mod/models/block"
* @param modelFolderId ModelAsset folder to bridge. For example "mod:block" will bridge all models from "assets/mod/models/block"
* @return Success of addition.
*/
public boolean addBridgedModelsFolder(Identifier modelFolderId) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package eu.pb4.polymer.resourcepack.extras.api.format.atlas;

import com.google.gson.JsonParser;
import com.mojang.serialization.Codec;
import com.mojang.serialization.JsonOps;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import eu.pb4.polymer.resourcepack.api.WritableAsset;
import eu.pb4.polymer.resourcepack.mixin.accessors.BlockEntryAccessor;
import net.minecraft.resource.metadata.BlockEntry;
import net.minecraft.util.Identifier;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.regex.Pattern;

public record AtlasAsset(List<AtlasSource> sources) implements WritableAsset.Json {
public static final Codec<AtlasAsset> CODEC = RecordCodecBuilder.create(instance -> instance.group(
AtlasSource.CODEC.listOf().fieldOf("sources").forGetter(AtlasAsset::sources)
).apply(instance, AtlasAsset::new));

public String toJson() {
return CODEC.encodeStart(JsonOps.INSTANCE, this).getOrThrow().toString();
}

public static AtlasAsset fromJson(String json) {
return CODEC.decode(JsonOps.INSTANCE, JsonParser.parseString(json)).getOrThrow().getFirst();
}

public static Builder builder() {
return new Builder();
}

public static class Builder {
private final List<AtlasSource> sources = new ArrayList<>();

private Builder() {}

public Builder single(Identifier resource, Identifier sprite) {
return this.add(new SingleAtlasSource(resource, Optional.ofNullable(sprite)));
}

public Builder single(Identifier resource) {
return this.add(new SingleAtlasSource(resource, Optional.empty()));
}

public Builder directory(String source, String prefix) {
return this.add(new DirectoryAtlasSource(source, prefix));
}

public Builder filter(BlockEntry entry) {
return this.add(new FilterAtlasSource(entry));
}

public Builder filter(Pattern namespace, Pattern path) {
return this.add(new FilterAtlasSource(BlockEntryAccessor.createBlockEntry(Optional.ofNullable(namespace), Optional.ofNullable(path))));
}

public Builder filterNamespace(Pattern namespace) {
return this.add(new FilterAtlasSource(BlockEntryAccessor.createBlockEntry(Optional.ofNullable(namespace), Optional.empty())));
}

public Builder filterPath(Pattern path) {
return this.add(new FilterAtlasSource(BlockEntryAccessor.createBlockEntry(Optional.empty(), Optional.ofNullable(path))));
}

public Builder unstitch(Identifier resource, double divisorX, double divisorY, Consumer<RegionConsumer> regionConsumer) {
var arr = new ArrayList<UnstitchAtlasSource.Region>();
regionConsumer.accept(arr::add);
return this.add(new UnstitchAtlasSource(resource, arr, divisorX, divisorY));
}

public Builder unstitch(Identifier resource, Consumer<RegionConsumer> regionConsumer) {
var arr = new ArrayList<UnstitchAtlasSource.Region>();
regionConsumer.accept(arr::add);
return this.add(new UnstitchAtlasSource(resource, arr));
}

public Builder palettedPermutations(List<Identifier> textures, Identifier paletteKey, Map<String, Identifier> permutations) {
return this.add(new PalettedPermutationsAtlasSource(textures, paletteKey, permutations));
}

public Builder palettedPermutations(PalettedPermutationsAtlasSource.Builder builder) {
return this.add(builder.build());
}

public Builder palettedPermutations(Identifier paletteKey, Consumer<PalettedPermutationsAtlasSource.Builder> builderConsumer) {
var builder = PalettedPermutationsAtlasSource.builder(paletteKey);
builderConsumer.accept(builder);
return this.add(builder.build());
}

public Builder add(AtlasSource source) {
this.sources.add(source);
return this;
}

public AtlasAsset build() {
return new AtlasAsset(sources);
}

public interface RegionConsumer extends Consumer<UnstitchAtlasSource.Region> {
default void accept(Identifier sprite, double x, double y, double width, double height) {
this.accept(new UnstitchAtlasSource.Region(sprite, x, y, width, height));
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package eu.pb4.polymer.resourcepack.extras.api.format.atlas;

import com.google.gson.JsonParser;
import com.mojang.serialization.Codec;
import com.mojang.serialization.JsonOps;
import com.mojang.serialization.MapCodec;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.minecraft.util.dynamic.Codecs;

import java.util.List;
import java.util.function.Function;

public interface AtlasSource {
Codec<AtlasSource> CODEC = Codec.lazyInitialized(() -> AtlasSource.TYPES.getCodec(Identifier.CODEC).dispatch(AtlasSource::codec, Function.identity()));
Codecs.IdMapper<Identifier, MapCodec<? extends AtlasSource>> TYPES = Util.make(new Codecs.IdMapper<>(), m -> {
m.put(Identifier.ofVanilla("single"), SingleAtlasSource.CODEC);
m.put(Identifier.ofVanilla("directory"), DirectoryAtlasSource.CODEC);
m.put(Identifier.ofVanilla("filter"), FilterAtlasSource.CODEC);
m.put(Identifier.ofVanilla("unstitch"), UnstitchAtlasSource.CODEC);
m.put(Identifier.ofVanilla("paletted_permutations"), PalettedPermutationsAtlasSource.CODEC);
});

MapCodec<? extends AtlasSource> codec();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package eu.pb4.polymer.resourcepack.extras.api.format.atlas;

import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;

public record DirectoryAtlasSource(String source, String prefix) implements AtlasSource {
public static final MapCodec<DirectoryAtlasSource> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
Codec.STRING.fieldOf("source").forGetter(DirectoryAtlasSource::source),
Codec.STRING.fieldOf("prefix").forGetter(DirectoryAtlasSource::prefix))
.apply(instance, DirectoryAtlasSource::new));

@Override
public MapCodec<? extends AtlasSource> codec() {
return CODEC;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package eu.pb4.polymer.resourcepack.extras.api.format.atlas;

import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import eu.pb4.polymer.resourcepack.mixin.accessors.BlockEntryAccessor;
import net.minecraft.resource.metadata.BlockEntry;

import java.util.Optional;
import java.util.regex.Pattern;

public record FilterAtlasSource(BlockEntry pattern) implements AtlasSource {
public static final MapCodec<FilterAtlasSource> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
BlockEntry.CODEC.fieldOf("pattern").forGetter(FilterAtlasSource::pattern))
.apply(instance, FilterAtlasSource::new));

public FilterAtlasSource(Optional<Pattern> namespace, Optional<Pattern> path) {
this(BlockEntryAccessor.createBlockEntry(namespace, path));
}

public FilterAtlasSource(Pattern namespace, Pattern path) {
this(Optional.ofNullable(namespace), Optional.ofNullable(path));
}
@Override
public MapCodec<? extends AtlasSource> codec() {
return CODEC;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package eu.pb4.polymer.resourcepack.extras.api.format.atlas;

import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.util.Identifier;

import java.util.*;

public record PalettedPermutationsAtlasSource(List<Identifier> textures, Identifier paletteKey, Map<String, Identifier> permutations) implements AtlasSource {
public static final MapCodec<PalettedPermutationsAtlasSource> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
Codec.list(Identifier.CODEC).fieldOf("textures").forGetter(PalettedPermutationsAtlasSource::textures),
Identifier.CODEC.fieldOf("palette_key").forGetter(PalettedPermutationsAtlasSource::paletteKey),
Codec.unboundedMap(Codec.STRING, Identifier.CODEC).fieldOf("permutations").forGetter(PalettedPermutationsAtlasSource::permutations)
).apply(instance, PalettedPermutationsAtlasSource::new));

@Override
public MapCodec<? extends AtlasSource> codec() {
return CODEC;
}

public static Builder builder(Identifier paletteKey) {
return new Builder(paletteKey);
}

public static class Builder {
private final Identifier paletteKey;
private final List<Identifier> textures = new ArrayList<>();
private final Map<String, Identifier> permutations = new HashMap<>();
private Builder(Identifier paletteKey) {
this.paletteKey = paletteKey;
}

public Builder texture(Identifier texture) {
this.textures.add(texture);
return this;
}

public Builder textures(Collection<Identifier> textures) {
this.textures.addAll(textures);
return this;
}

public Builder permutation(String suffix, Identifier paletteKey) {
this.permutations.put(suffix, paletteKey);
return this;
}

public Builder permutations(Map<String, Identifier> permutations) {
this.permutations.putAll(permutations);
return this;
}

public PalettedPermutationsAtlasSource build() {
return new PalettedPermutationsAtlasSource(new ArrayList<>(this.textures), paletteKey, new HashMap<>(permutations));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package eu.pb4.polymer.resourcepack.extras.api.format.atlas;

import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.util.Identifier;

import java.util.Optional;

public record SingleAtlasSource(Identifier resource, Optional<Identifier> sprite) implements AtlasSource {
public static final MapCodec<SingleAtlasSource> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
Identifier.CODEC.fieldOf("resource").forGetter(SingleAtlasSource::resource),
Identifier.CODEC.optionalFieldOf("sprite").forGetter(SingleAtlasSource::sprite)
).apply(instance, SingleAtlasSource::new));

@Override
public MapCodec<? extends AtlasSource> codec() {
return CODEC;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package eu.pb4.polymer.resourcepack.extras.api.format.atlas;

import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.util.Identifier;
import net.minecraft.util.dynamic.Codecs;

import java.util.List;

public record UnstitchAtlasSource(Identifier resource, List<Region> regions, double divisorX,
double divisorY) implements AtlasSource {
public static final MapCodec<UnstitchAtlasSource> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
Identifier.CODEC.fieldOf("resource").forGetter(UnstitchAtlasSource::resource),
Codecs.nonEmptyList(Region.CODEC.listOf()).fieldOf("regions").forGetter(UnstitchAtlasSource::regions),
Codec.DOUBLE.optionalFieldOf("divisor_x", 1.0).forGetter(UnstitchAtlasSource::divisorX),
Codec.DOUBLE.optionalFieldOf("divisor_y", 1.0).forGetter(UnstitchAtlasSource::divisorY)
).apply(instance, UnstitchAtlasSource::new));

public UnstitchAtlasSource(Identifier resource, List<Region> regions) {
this(resource, regions, 1, 1);
}

@Override
public MapCodec<? extends AtlasSource> codec() {
return CODEC;
}

public record Region(Identifier sprite, double x, double y, double width, double height) {
public static final Codec<Region> CODEC = RecordCodecBuilder.create(instance -> instance.group(
Identifier.CODEC.fieldOf("sprite").forGetter(Region::sprite),
Codec.DOUBLE.fieldOf("x").forGetter(Region::x),
Codec.DOUBLE.fieldOf("y").forGetter(Region::y),
Codec.DOUBLE.fieldOf("width").forGetter(Region::width),
Codec.DOUBLE.fieldOf("height").forGetter(Region::height)
).apply(instance, Region::new));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
import com.mojang.serialization.JsonOps;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import eu.pb4.polymer.resourcepack.api.WritableAsset;
import eu.pb4.polymer.resourcepack.extras.api.format.item.model.ItemModel;

public record ItemAsset(ItemModel model, Properties properties) {
public record ItemAsset(ItemModel model, Properties properties) implements WritableAsset.Json {
public static final Codec<ItemAsset> CODEC = RecordCodecBuilder.create(instance -> instance.group(
ItemModel.CODEC.fieldOf("model").forGetter(ItemAsset::model),
Properties.CODEC.forGetter(ItemAsset::properties)
Expand Down
Loading

0 comments on commit c4f39c9

Please sign in to comment.