Skip to content

Commit

Permalink
feat(deco): datagen loottables
Browse files Browse the repository at this point in the history
  • Loading branch information
CallMeEchoCodes committed Oct 12, 2024
1 parent 87d7ae2 commit 4e5078f
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 78 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// 1.21.1 2024-10-12T12:28:23.167856044 Loot Tables
f89288b131086917a8df3e5fdc5fa21884d02965 data/armistice/loot_table/blocks/iron_grate.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "armistice:iron_grate"
}
],
"rolls": 1.0
}
],
"random_sequence": "armistice:blocks/iron_grate"
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,10 @@ private static void onGatherData(GatherDataEvent event) {
event.includeServer(),
new ArmisticeBlockStateProvider(output, existingFileHelper)
);

generator.addProvider(
event.includeServer(),
new ArmisticeLootTableProvider(output, lookupProvider)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package symbolics.division.armistice.datagen;

import net.minecraft.core.HolderLookup;
import net.minecraft.data.PackOutput;
import net.minecraft.data.loot.BlockLootSubProvider;
import net.minecraft.data.loot.LootTableProvider;
import net.minecraft.world.flag.FeatureFlags;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
import org.jetbrains.annotations.NotNull;
import symbolics.division.armistice.registry.ArmisticeBlockRegistrar;
import symbolics.division.armistice.util.registrar.Registrar;

import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;

public class ArmisticeLootTableProvider extends LootTableProvider {
public ArmisticeLootTableProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> registries) {
super(output, Set.of(), List.of(
new SubProviderEntry(
BlockSubProvider::new,
LootContextParamSets.BLOCK
)
), registries);
}

public static class BlockSubProvider extends BlockLootSubProvider {
public BlockSubProvider(HolderLookup.Provider lookupProvider) {
super(Set.of(), FeatureFlags.DEFAULT_FLAGS, lookupProvider);
}

@NotNull
@Override
protected Iterable<Block> getKnownBlocks() {
return Registrar.getObjects(ArmisticeBlockRegistrar.class, Block.class);
}

@Override
protected void generate() {
dropSelf(ArmisticeBlockRegistrar.IRON_GRATE);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package symbolics.division.armistice.util.registrar;

import com.google.common.collect.ImmutableList;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.neoforged.neoforge.registries.RegisterEvent;
Expand All @@ -11,98 +12,111 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
* A registrar registers all static fields in within itself to a registry.
*
* @param <T> Type of object to register
*/
public interface Registrar<T> {
/**
* Process a registrar class and register all objects.
*
* @param clazz Registrar class to process
* @param namespace Namespace to register objects in
*/
static <T> void process(Class<? extends Registrar<T>> clazz, String namespace, RegisterEvent event) {
Registrar<T> registrar = ReflectionHelper.instantiate(clazz);
registrar.init(namespace, event);
}
/**
* Process a registrar class and register all objects.
*
* @param clazz Registrar class to process
* @param namespace Namespace to register objects in
*/
static <T> void process(Class<? extends Registrar<T>> clazz, String namespace, RegisterEvent event) {
Registrar<T> registrar = ReflectionHelper.instantiate(clazz);
registrar.init(namespace, event);
}

/**
* Initialize the registrar and register all objects.
* Do not call this method directly, use {@link Registrar#process(Class, String, RegisterEvent)} instead.
*
* @param namespace Namespace to register objects in
*/
@ApiStatus.Internal
default void init(String namespace, RegisterEvent event) {
event.register(
getRegistry().key(),
registry -> {
ReflectionHelper.forEachStaticField(this.getClass(), getObjectType(), (value, name, field) -> {
if (field.isAnnotationPresent(Ignore.class)) return;
static <T> Iterable<T> getObjects(Class<? extends Registrar<T>> clazz, Class<T> type) {
List<T> objects = new ArrayList<>();

String objectName = ReflectionHelper.getAnnotation(field, Name.class)
.map(Name::value)
.orElseGet(name::toLowerCase);
ReflectionHelper.forEachStaticField(clazz, type, (value, name, field) -> {
if (field.isAnnotationPresent(Ignore.class)) return;
objects.add(value);
});

register(objectName, namespace, value, field, registry);
});
}
);
}
return ImmutableList.copyOf(objects);
}

/**
* Register an object to the registry.
*
* @param name Name of the object
* @param namespace Namespace to register the object in
* @param object Object to register
* @param field Field the object is stored in
*/
default void register(String name, String namespace, T object, Field field, RegisterEvent.RegisterHelper<T> helper) {
helper.register(ResourceLocation.fromNamespaceAndPath(namespace, name), object);
}
/**
* Workaround for Java's type erasure.
* Use this if {@link T} has a generic type of ?.
*/
@SuppressWarnings("unchecked")
static <T> Class<T> fixGenerics(Class<?> clazz) {
return (Class<T>) clazz;
}

/**
* Get the type of object to register.
* If {@link T} has a generic type of ?, use {@link Registrar#fixGenerics(Class)} to force the correct type.
*
* @return The type of object to register
*/
Class<T> getObjectType();
/**
* Initialize the registrar and register all objects.
* Do not call this method directly, use {@link Registrar#process(Class, String, RegisterEvent)} instead.
*
* @param namespace Namespace to register objects in
*/
@ApiStatus.Internal
default void init(String namespace, RegisterEvent event) {
event.register(
getRegistry().key(),
registry -> {
ReflectionHelper.forEachStaticField(this.getClass(), getObjectType(), (value, name, field) -> {
if (field.isAnnotationPresent(Ignore.class)) return;

/**
* Get the registry to register objects in.
*
* @return The registry to register objects in
*/
Registry<T> getRegistry();
String objectName = ReflectionHelper.getAnnotation(field, Name.class)
.map(Name::value)
.orElseGet(name::toLowerCase);

/**
* Workaround for Java's type erasure.
* Use this if {@link T} has a generic type of ?.
*/
@SuppressWarnings("unchecked")
static <T> Class<T> fixGenerics(Class<?> clazz) {
return (Class<T>) clazz;
}
register(objectName, namespace, value, field, registry);
});
}
);
}

/**
* Ignore a field when registering objects.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Ignore {
}
/**
* Register an object to the registry.
*
* @param name Name of the object
* @param namespace Namespace to register the object in
* @param object Object to register
* @param field Field the object is stored in
*/
default void register(String name, String namespace, T object, Field field, RegisterEvent.RegisterHelper<T> helper) {
helper.register(ResourceLocation.fromNamespaceAndPath(namespace, name), object);
}

/**
* Set the name of the object to register.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Name {
String value();
}
/**
* Get the type of object to register.
* If {@link T} has a generic type of ?, use {@link Registrar#fixGenerics(Class)} to force the correct type.
*
* @return The type of object to register
*/
Class<T> getObjectType();

/**
* Get the registry to register objects in.
*
* @return The registry to register objects in
*/
Registry<T> getRegistry();

/**
* Ignore a field when registering objects.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Ignore {
}

/**
* Set the name of the object to register.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Name {
String value();
}
}

0 comments on commit 4e5078f

Please sign in to comment.