Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add EntityType DeferredRegister #1854

Open
wants to merge 1 commit into
base: 1.21.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
Expand Down Expand Up @@ -170,6 +173,18 @@ public static DataComponents createDataComponents(ResourceKey<Registry<DataCompo
return new DataComponents(registryKey, modid);
}

/**
* Factory for a specialized DeferredRegister for {@link EntityType EntityTypes}.
*
* @param modid The namespace for all objects registered to this DeferredRegister
* @see #create(Registry, String)
* @see #create(ResourceKey, String)
* @see #create(ResourceLocation, String)
*/
public static EntityTypes createEntityTypes(String modid) {
return new EntityTypes(modid);
}

private final ResourceKey<? extends Registry<T>> registryKey;
private final String namespace;
private final Map<DeferredHolder<T, ? extends T>, Supplier<? extends T>> entries = new LinkedHashMap<>();
Expand Down Expand Up @@ -648,6 +663,29 @@ public <D> DeferredHolder<DataComponentType<?>, DataComponentType<D>> registerCo
}
}

/**
* Specialized DeferredRegister for {@link EntityType EntityTypes}.
*/
public static class EntityTypes extends DeferredRegister<EntityType<?>> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it should be called Entities to match DataComponents above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I called it $EntityTypes as that is what the test framework class calls them; however I can rename if desired.

protected EntityTypes(String namespace) {
super(Registries.ENTITY_TYPE, namespace);
}

/**
* Convenience method that constructs a builder for use in the operator. Use this to avoid inference issues.
*
* @param name The name for this entity type. It will automatically have the {@linkplain #getNamespace() namespace} prefixed.
* @param factory The factory used to typically construct the entity when using an existing helper from the type.
* @param category The category of the entity, typically {@link MobCategory#MISC} for non-living entities, or one of the others for living entities.
* @param builder The unary operator, which is passed a new builder for user operators, then builds it upon registration.
* @return A {@link DeferredHolder} which reflects the data that will be registered.
* @param <E> the type of the entity
*/
public <E extends Entity> DeferredHolder<EntityType<?>, EntityType<E>> registerType(String name, EntityType.EntityFactory<E> factory, MobCategory category, UnaryOperator<EntityType.Builder<E>> builder) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it should be called registerEntityType to match registerComponentType above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no opinion on this, so I can rename if desired.

return this.register(name, key -> builder.apply(EntityType.Builder.of(factory, category)).build(ResourceKey.create(Registries.ENTITY_TYPE, key)));
}
}

private static class RegistryHolder<V> implements Supplier<Registry<V>> {
private final ResourceKey<? extends Registry<V>> registryKey;
private Registry<V> registry = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@

package net.neoforged.testframework.registration;

import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobCategory;
import net.neoforged.neoforge.registries.DeferredRegister;

public class DeferredEntityTypes extends DeferredRegister<EntityType<?>> {
public class DeferredEntityTypes extends DeferredRegister.EntityTypes {
private final RegistrationHelper helper;

public DeferredEntityTypes(String namespace, RegistrationHelper helper) {
super(Registries.ENTITY_TYPE, namespace);
super(namespace);
this.helper = helper;
}

Expand All @@ -27,7 +27,8 @@ protected <I extends EntityType<?>> DeferredEntityTypeBuilder createHolder(Resou
return new DeferredEntityTypeBuilder(ResourceKey.create(registryKey, key), helper);
}

public <E extends Entity> DeferredEntityTypeBuilder<E, EntityType<E>> registerType(String name, Supplier<EntityType.Builder<E>> sup) {
return (DeferredEntityTypeBuilder<E, EntityType<E>>) super.register(name, rl -> sup.get().build(ResourceKey.create(getRegistryKey(), rl)));
@Override
public <E extends Entity> DeferredEntityTypeBuilder<E, EntityType<E>> registerType(String name, EntityType.EntityFactory<E> factory, MobCategory category, UnaryOperator<EntityType.Builder<E>> builder) {
return (DeferredEntityTypeBuilder<E, EntityType<E>>) super.registerType(name, factory, category, builder);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ static void register(final TestFramework framework) {
@EmptyTemplate(floor = true)
@TestHolder(description = "Tests if custom EntityDataSerializers are properly handled")
static void customEntityDataSerializer(final DynamicTest test, final RegistrationHelper reg) {
var testEntity = reg.entityTypes().registerType("serializer_test_entity", () -> EntityType.Builder.of(TestEntity::new, MobCategory.CREATURE)
.sized(1, 1)).withRenderer(() -> TestEntityRenderer::new);
var testEntity = reg.entityTypes().registerType("serializer_test_entity", TestEntity::new, MobCategory.CREATURE, builder -> builder.sized(1, 1))
.withRenderer(() -> TestEntityRenderer::new);

test.onGameTest(helper -> {
var entity = helper.spawn(testEntity.get(), 1, 2, 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ public class EntityTests {
@EmptyTemplate
@TestHolder(description = "Tests if custom fence gates without wood types work, allowing for the use of the vanilla block for non-wooden gates")
static void customSpawnLogic(final DynamicTest test, final RegistrationHelper reg) {
final var usingForgeAdvancedSpawn = reg.entityTypes().registerType("complex_spawn", () -> EntityType.Builder.of(CustomComplexSpawnEntity::new, MobCategory.AMBIENT)
.sized(1, 1)).withLang("Custom complex spawn egg").withRenderer(() -> NoopRenderer::new);
final var usingCustomPayloadsSpawn = reg.entityTypes().registerType("adapted_spawn", () -> EntityType.Builder.of(AdaptedSpawnEntity::new, MobCategory.AMBIENT)
.sized(1, 1)).withLang("Adapted complex spawn egg").withRenderer(() -> NoopRenderer::new);
final var simpleSpawn = reg.entityTypes().registerType("simple_spawn", () -> EntityType.Builder.of(SimpleEntity::new, MobCategory.AMBIENT)
.sized(1, 1)).withLang("Simple spawn egg").withRenderer(() -> NoopRenderer::new);
final var usingForgeAdvancedSpawn = reg.entityTypes().registerType("complex_spawn", CustomComplexSpawnEntity::new, MobCategory.AMBIENT, builder -> builder.sized(1, 1))
.withLang("Custom complex spawn egg").withRenderer(() -> NoopRenderer::new);
final var usingCustomPayloadsSpawn = reg.entityTypes().registerType("adapted_spawn", AdaptedSpawnEntity::new, MobCategory.AMBIENT, builder -> builder.sized(1, 1))
.withLang("Adapted complex spawn egg").withRenderer(() -> NoopRenderer::new);
final var simpleSpawn = reg.entityTypes().registerType("simple_spawn", SimpleEntity::new, MobCategory.AMBIENT, builder -> builder.sized(1, 1))
.withLang("Simple spawn egg").withRenderer(() -> NoopRenderer::new);

reg.eventListeners().accept((Consumer<RegisterPayloadHandlersEvent>) event -> event.registrar("1")
.playToClient(EntityTests.CustomSyncPayload.TYPE, CustomSyncPayload.STREAM_CODEC, (payload, context) -> {}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
package net.neoforged.neoforge.debug.entity.vehicle;

import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.entity.vehicle.Boat;
import net.minecraft.world.entity.vehicle.ChestBoat;
import net.minecraft.world.entity.vehicle.ChestRaft;
import net.minecraft.world.entity.vehicle.Raft;
import net.minecraft.world.item.BoatItem;
import net.minecraft.world.item.Item;
import net.neoforged.testframework.DynamicTest;
import net.neoforged.testframework.Test;
import net.neoforged.testframework.annotation.ForEachTest;
Expand All @@ -32,10 +32,10 @@ public class CustomBoatTest {
@EmptyTemplate
@TestHolder(description = "Tests that custom boat types work")
static void customBoatType(final DynamicTest test, final RegistrationHelper reg) {
Supplier<EntityType<Boat>> paperBoat = reg.entityTypes().registerType("paper_boat", () -> EntityType.Builder.<Boat>of((type, level) -> new Boat(type, level, (Supplier<Item>) () -> paperBoatItem.get()), MobCategory.MISC));
Supplier<EntityType<ChestBoat>> paperChestBoat = reg.entityTypes().registerType("paper_chest_boat", () -> EntityType.Builder.<ChestBoat>of((type, level) -> new ChestBoat(type, level, (Supplier<Item>) () -> paperChestBoatItem.get()), MobCategory.MISC));
Supplier<EntityType<Raft>> paperRaft = reg.entityTypes().registerType("paper_raft", () -> EntityType.Builder.<Raft>of((type, level) -> new Raft(type, level, (Supplier<Item>) () -> paperRaftItem.get()), MobCategory.MISC));
Supplier<EntityType<ChestRaft>> paperChestRaft = reg.entityTypes().registerType("paper_chest_raft", () -> EntityType.Builder.<ChestRaft>of((type, level) -> new ChestRaft(type, level, (Supplier<Item>) () -> paperChestRaftItem.get()), MobCategory.MISC));
Supplier<EntityType<Boat>> paperBoat = reg.entityTypes().registerType("paper_boat", (type, level) -> new Boat(type, level, () -> paperBoatItem.get()), MobCategory.MISC, UnaryOperator.identity());
Supplier<EntityType<ChestBoat>> paperChestBoat = reg.entityTypes().registerType("paper_chest_boat", (type, level) -> new ChestBoat(type, level, () -> paperChestBoatItem.get()), MobCategory.MISC, UnaryOperator.identity());
Supplier<EntityType<Raft>> paperRaft = reg.entityTypes().registerType("paper_raft", (type, level) -> new Raft(type, level, () -> paperRaftItem.get()), MobCategory.MISC, UnaryOperator.identity());
Supplier<EntityType<ChestRaft>> paperChestRaft = reg.entityTypes().registerType("paper_chest_raft", (type, level) -> new ChestRaft(type, level, () -> paperChestRaftItem.get()), MobCategory.MISC, UnaryOperator.identity());

paperBoatItem = reg.items().registerItem("paper_boat", props -> new BoatItem(paperBoat.get(), props))
.withLang("Paper Boat");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,7 @@ public ItemStack execute(BlockSource p_302435_, ItemStack p_123562_) {
"Tests if the forge spawn egg works"
})
static void forgeSpawnEggTest(final DynamicTest test, final RegistrationHelper reg) {
final var testEntity = reg.entityTypes().registerType("test_entity", () -> EntityType.Builder.of(Pig::new, MobCategory.CREATURE)
.sized(1, 1))
final var testEntity = reg.entityTypes().registerType("test_entity", Pig::new, MobCategory.CREATURE, builder -> builder.sized(1, 1))
.withAttributes(Pig::createAttributes)
.withRenderer(() -> PigRenderer::new)
.withLang("Test Pig spawn egg");
Expand Down
Loading