Skip to content

Commit

Permalink
Rewrite datagen
Browse files Browse the repository at this point in the history
Plus a bit of the client tag manager, since some of the data stuff is used for it
  • Loading branch information
dhyces committed May 29, 2024
1 parent 1a0a77e commit 9aa5ca2
Show file tree
Hide file tree
Showing 19 changed files with 373 additions and 298 deletions.
11 changes: 8 additions & 3 deletions common/src/main/java/dev/dhyces/trimmed/api/KeyResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.resources.ResourceKey;
import org.jetbrains.annotations.Nullable;

public interface KeyResolver<T> {
Expand All @@ -13,16 +14,20 @@ public interface KeyResolver<T> {
StreamCodec<RegistryFriendlyByteBuf, T> getStreamCodec();
boolean requiresActiveWorld();

record RegistryWrapper<T>(Registry<T> registry, boolean requiresActiveWorld) implements KeyResolver<T> {
record RegistryWrapper<T>(ResourceKey<? extends Registry<T>> registryKey, Codec<T> byNameCodec, boolean requiresActiveWorld) implements KeyResolver<T> {
public static <T> RegistryWrapper<T> createStatic(Registry<T> registry) {
return new RegistryWrapper<>(registry.key(), registry.byNameCodec(), false);
}


@Override
public Codec<T> getCodec() {
return registry.byNameCodec();
return byNameCodec;
}

@Override
public StreamCodec<RegistryFriendlyByteBuf, T> getStreamCodec() {
return ByteBufCodecs.registry(registry.key());
return ByteBufCodecs.registry(registryKey);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package dev.dhyces.trimmed.api.data.client.tag;

import dev.dhyces.trimmed.api.KeyResolver;
import dev.dhyces.trimmed.api.client.tag.ClientTagKey;
import dev.dhyces.trimmed.api.data.tag.ClientTagBuilder;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import net.minecraft.data.DataProvider;
import net.minecraft.data.PackOutput;
import net.minecraft.resources.ResourceLocation;

import java.util.Map;

public abstract class BaseClientTagDataProvider<T, R extends KeyResolver<T>> implements DataProvider {
protected final PackOutput packOutput;
protected final PackOutput.PathProvider pathProvider;
protected final String modid;
protected final Map<ResourceLocation, ClientTagBuilder<T>> builders = new Object2ObjectLinkedOpenHashMap<>();
protected final R keyResolver;

public BaseClientTagDataProvider(PackOutput packOutput, String modid, String prefix, R keyResolver) {
this.packOutput = packOutput;
this.modid = modid;
this.pathProvider = packOutput.createPathProvider(PackOutput.Target.RESOURCE_PACK, prefix);
this.keyResolver = keyResolver;
}

protected ClientTagBuilder<T> getOrCreateBuilder(ClientTagKey<T> clientTagKey) {
return this.builders.computeIfAbsent(clientTagKey.getTagId(), resourceLocation -> {
onBuilderCreation(resourceLocation);
return new ClientTagBuilder<>(clientTagKey.getKeyResolver());
});
}

protected void onBuilderCreation(ResourceLocation id) {}

protected boolean doesTagExist(ClientTagKey<T> clientTagKey) {
return builders.get(clientTagKey.getTagId()) != null;
}
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,40 @@
package dev.dhyces.trimmed.api.data.client.tag.appenders;

import dev.dhyces.trimmed.api.client.tag.ClientTagKey;
import dev.dhyces.trimmed.api.data.tag.ClientTagBuilder;
import net.minecraft.Util;
import net.minecraft.core.HolderLookup;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagBuilder;

import java.util.Map;
import java.util.function.Supplier;

public class ClientRegistryTagAppender<T> {
private final TagBuilder backed;
private final ClientTagBuilder<T> builder;
private final HolderLookup.RegistryLookup<T> lookup;
private final Map<T, ResourceLocation> reverseLookup;

public ClientRegistryTagAppender(TagBuilder builder, HolderLookup.RegistryLookup<T> lookup) {
this.backed = builder;
public ClientRegistryTagAppender(ClientTagBuilder<T> builder, HolderLookup.RegistryLookup<T> lookup) {
this.builder = builder;
this.lookup = lookup;
this.reverseLookup = lookup.listElements().map(tReference -> Map.entry(tReference.value(), tReference.key().location())).collect(Util.toMap());
}

protected T lookupOrThrow(ResourceKey<T> key) {
return lookup.getOrThrow(key).value();
}

public ClientRegistryTagAppender<T> add(T element, boolean isRequired) {
if (!reverseLookup.containsKey(element)) {
throw new IllegalArgumentException("Element is not a member of the registry \"" + lookup.key() + "\"");
}
builder.add(element, isRequired);
return this;
}

public ClientRegistryTagAppender<T> add(T element) {
add(reverseLookup.get(element));
add(element, true);
return this;
}

Expand All @@ -32,7 +44,7 @@ public ClientRegistryTagAppender<T> add(Supplier<T> element) {
}

public ClientRegistryTagAppender<T> addOptional(T element) {
addOptional(reverseLookup.get(element));
addOptional(element);
return this;
}

Expand All @@ -41,45 +53,34 @@ public ClientRegistryTagAppender<T> addOptional(Supplier<T> element) {
return this;
}

public ClientRegistryTagAppender<T> add(ResourceLocation element) {
backed.addElement(element);
return this;
}

public ClientRegistryTagAppender<T> add(ResourceKey<T> element) {
if (!element.registry().equals(lookup.key().location())) {
throw new IllegalArgumentException("Element " + element.location() + " is not for registry " + lookup.key() + "!");
}
backed.addElement(element.location());
add(lookupOrThrow(element));
return this;
}

public ClientRegistryTagAppender<T> addTag(ClientTagKey<T> tagKey) {
public ClientRegistryTagAppender<T> addTag(ClientTagKey<T> tagKey, boolean isRequired) {
if (!tagKey.getTagId().equals(lookup.key().location())) {
throw new IllegalArgumentException("TagKey " + tagKey + " is not for registry " + lookup.key() + "!");
}
backed.addTag(tagKey.getTagId());
builder.addTag(tagKey, isRequired);
return this;
}

public ClientRegistryTagAppender<T> addOptional(ResourceLocation optionalElement) {
backed.addOptionalElement(optionalElement);
public ClientRegistryTagAppender<T> addTag(ClientTagKey<T> tagKey) {
addTag(tagKey, true);
return this;
}

public ClientRegistryTagAppender<T> addOptional(ResourceKey<T> element) {
if (!element.registry().equals(lookup.key().location())) {
throw new IllegalArgumentException("Element " + element.location() + " is not for registry " + lookup.key() + "!");
}
backed.addOptionalElement(element.location());
add(lookupOrThrow(element), false);
return this;
}

public ClientRegistryTagAppender<T> addOptionalTag(ClientTagKey<T> optionalTagKey) {
if (!optionalTagKey.getTagId().equals(lookup.key().location())) {
throw new IllegalArgumentException("TagKey " + optionalTagKey + " is not for registry " + lookup.key() + "!");
}
backed.addOptionalTag(optionalTagKey.getTagId());
addTag(optionalTagKey, false);
return this;
}
}
Original file line number Diff line number Diff line change
@@ -1,86 +1,64 @@
package dev.dhyces.trimmed.api.data.client.tag.appenders;

import dev.dhyces.trimmed.api.client.tag.ClientTagKey;
import dev.dhyces.trimmed.api.data.tag.ClientTagBuilder;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagBuilder;

public class ClientTagAppender {
private final TagBuilder backed;
private final String namespace;
public class ClientTagAppender<T> {
private final ClientTagBuilder<T> builder;

public ClientTagAppender(String namespace, TagBuilder builder) {
this.backed = builder;
this.namespace = namespace;
public ClientTagAppender(ClientTagBuilder<T> builder) {
this.builder = builder;
}

public ClientTagAppender add(String element) {
backed.addElement(new ResourceLocation(namespace, element));
public ClientTagAppender<T> add(T element) {
builder.add(element, true);
return this;
}

public ClientTagAppender add(String... elements) {
for (String s : elements) {
backed.addElement(new ResourceLocation(namespace, s));
@SafeVarargs
public final ClientTagAppender<T> add(T... elements) {
for (T element : elements) {
builder.add(element, true);
}
return this;
}

public ClientTagAppender add(ResourceLocation element) {
backed.addElement(element);
public ClientTagAppender<T> addTag(ClientTagKey<T> tagKey) {
builder.addTag(tagKey, true);
return this;
}

public ClientTagAppender add(ResourceLocation... elements) {
for (ResourceLocation elem : elements) {
backed.addElement(elem);
@SafeVarargs
public final ClientTagAppender<T> addTags(ClientTagKey<T>... tagKeys) {
for (ClientTagKey<T> key : tagKeys) {
builder.addTag(key, true);
}
return this;
}

public ClientTagAppender addTag(ClientTagKey tagKey) {
backed.addTag(tagKey.getTagId());
public ClientTagAppender<T> addOptional(T element) {
builder.add(element, false);
return this;
}

public ClientTagAppender addTags(ClientTagKey... tagKeys) {
for (ClientTagKey key : tagKeys) {
backed.addTag(key.getTagId());
@SafeVarargs
public final ClientTagAppender<T> addOptional(T... elements) {
for (T elem : elements) {
builder.add(elem, false);
}
return this;
}

public ClientTagAppender addOptional(String element) {
backed.addOptionalElement(new ResourceLocation(namespace, element));
public ClientTagAppender<T> addOptionalTag(ClientTagKey<T> tagKey) {
builder.addTag(tagKey, false);
return this;
}

public ClientTagAppender addOptional(String... elements) {
for (String elem : elements) {
backed.addOptionalElement(new ResourceLocation(namespace, elem));
}
return this;
}

public ClientTagAppender addOptional(ResourceLocation element) {
backed.addOptionalElement(element);
return this;
}

public ClientTagAppender addOptional(ResourceLocation... elements) {
for (ResourceLocation elem : elements) {
backed.addOptionalElement(elem);
}
return this;
}

public ClientTagAppender addOptionalTag(ClientTagKey tagKey) {
backed.addOptionalTag(tagKey.getTagId());
return this;
}

public ClientTagAppender addOptionalTags(ClientTagKey... tagKeys) {
for (ClientTagKey key : tagKeys) {
backed.addOptionalTag(key.getTagId());
@SafeVarargs
public final ClientTagAppender<T> addOptionalTags(ClientTagKey<T>... tagKeys) {
for (ClientTagKey<T> key : tagKeys) {
builder.addTag(key, false);
}
return this;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package dev.dhyces.trimmed.api.data.tag;

import dev.dhyces.trimmed.api.KeyResolver;
import dev.dhyces.trimmed.api.client.tag.ClientTagKey;
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;

import java.util.Set;

public class ClientTagBuilder<T> {
private final KeyResolver<T> keyResolver;
private final Set<ClientTagEntry<T>> elements;
private boolean replaces;

public ClientTagBuilder(KeyResolver<T> keyResolver) {
this.keyResolver = keyResolver;
this.elements = new ObjectLinkedOpenHashSet<>();
}

public ClientTagBuilder<T> add(T element, boolean isRequired) {
this.elements.add(ClientTagEntry.element(element, isRequired));
return this;
}

public ClientTagBuilder<T> addTag(ClientTagKey<T> clientTagKey, boolean isRequired) {
this.elements.add(ClientTagEntry.clientTagKey(clientTagKey, isRequired));
return this;
}

public ClientTagBuilder<T> setReplaces(boolean doesReplace) {
this.replaces = doesReplace;
return this;
}

public ClientTagFile<T> build() {
return new ClientTagFile<>(elements, replaces);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package dev.dhyces.trimmed.api.data.tag;

import com.mojang.datafixers.util.Either;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import dev.dhyces.trimmed.api.KeyResolver;
import dev.dhyces.trimmed.api.client.tag.ClientTagKey;
import org.jetbrains.annotations.Nullable;

import java.util.function.Predicate;

public record ClientTagEntry<T>(Either<T, ClientTagKey<T>> element, boolean isRequired) {
public static <T> Codec<Either<T, ClientTagKey<T>>> elementOrTagCodec(KeyResolver<T> keyResolver) {
return Codec.either(keyResolver.getCodec(), ClientTagKey.tagCodec(keyResolver));
}
public static <T> Codec<ClientTagEntry<T>> fullCodec(KeyResolver<T> keyResolver) {
return RecordCodecBuilder.create(instance ->
instance.group(
elementOrTagCodec(keyResolver).fieldOf("value").forGetter(ClientTagEntry::element),
Codec.BOOL.fieldOf("required").forGetter(ClientTagEntry::isRequired)
).apply(instance, ClientTagEntry::new)
);
}
public static <T> Codec<ClientTagEntry<T>> codec(KeyResolver<T> keyResolver) {
return Codec.withAlternative(elementOrTagCodec(keyResolver).xmap(
either -> new ClientTagEntry<>(either, true),
ClientTagEntry::element), fullCodec(keyResolver)
);
}

public boolean isTag() {
return element.right().isPresent();
}

@Nullable
public T getElement() {
return element.left().orElse(null);
}

@Nullable
public ClientTagKey<T> getTag() {
return element.right().orElse(null);
}

public boolean verifyExists(Predicate<T> elementPredicate, Predicate<ClientTagKey<T>> keyPredicate) {
return element.map(elementPredicate::test, keyPredicate::test);
}

public static <T> ClientTagEntry<T> element(T element, boolean isRequired) {
return new ClientTagEntry<>(Either.left(element), isRequired);
}

public static <T> ClientTagEntry<T> clientTagKey(ClientTagKey<T> clientTagKey, boolean isRequired) {
return new ClientTagEntry<>(Either.right(clientTagKey), isRequired);
}
}
Loading

0 comments on commit 9aa5ca2

Please sign in to comment.