diff --git a/build.gradle b/build.gradle index 861bbf523b..ddcc981b79 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { id "idea" id "maven-publish" id 'jacoco' - id "fabric-loom" version "1.6.3" apply false + id "fabric-loom" version "1.6.5" apply false id "com.diffplug.spotless" version "6.20.0" id "org.ajoberstar.grgit" version "3.1.0" id "me.modmuss50.remotesign" version "0.4.0" apply false diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/block/entity/FabricBlockEntityType.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/block/entity/FabricBlockEntityType.java new file mode 100644 index 0000000000..7aeba75362 --- /dev/null +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/block/entity/FabricBlockEntityType.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.object.builder.v1.block.entity; + +import com.mojang.datafixers.types.Type; + +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityType; + +/** + * General-purpose Fabric-provided extensions for {@link BlockEntityType}. + */ +public interface FabricBlockEntityType { + /** + * General-purpose Fabric-provided extensions for {@link BlockEntityType.Builder}. + * + *

Note: This interface is automatically implemented on {@link BlockEntityType.Builder} via Mixin and interface injection. + */ + interface Builder { + /** + * Builds the {@link BlockEntityType}, see {@link BlockEntityType.Builder#build(Type)}. + * + * @return the built {@link BlockEntityType} + */ + default BlockEntityType build() { + throw new AssertionError("Implemented in Mixin"); + } + } +} diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/block/entity/FabricBlockEntityTypeBuilder.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/block/entity/FabricBlockEntityTypeBuilder.java index 1229c3d11c..898afc17ef 100644 --- a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/block/entity/FabricBlockEntityTypeBuilder.java +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/block/entity/FabricBlockEntityTypeBuilder.java @@ -33,7 +33,10 @@ * *

Alternatively, use the access widener for {@link BlockEntityType.BlockEntityFactory} * in Fabric Transitive Access Wideners (v1). + * + * @deprecated Use {@link BlockEntityType.Builder} directly. */ +@Deprecated public final class FabricBlockEntityTypeBuilder { private final Factory factory; private final List blocks; @@ -43,6 +46,10 @@ private FabricBlockEntityTypeBuilder(Factory factory, List b this.blocks = blocks; } + /** + * @deprecated Use {@link BlockEntityType.Builder#create(BlockEntityType.BlockEntityFactory, Block...)}. + */ + @Deprecated public static FabricBlockEntityTypeBuilder create(Factory factory, Block... blocks) { List blocksList = new ArrayList<>(blocks.length); Collections.addAll(blocksList, blocks); @@ -55,7 +62,9 @@ public static FabricBlockEntityTypeBuilder create(Fac * * @param block the supported block * @return this builder + * @deprecated Use {@link BlockEntityType.Builder#create(BlockEntityType.BlockEntityFactory, Block...)}. */ + @Deprecated public FabricBlockEntityTypeBuilder addBlock(Block block) { this.blocks.add(block); return this; @@ -66,22 +75,36 @@ public FabricBlockEntityTypeBuilder addBlock(Block block) { * * @param blocks the supported blocks * @return this builder + * @deprecated Use {@link BlockEntityType.Builder#create(BlockEntityType.BlockEntityFactory, Block...)}. */ + @Deprecated public FabricBlockEntityTypeBuilder addBlocks(Block... blocks) { Collections.addAll(this.blocks, blocks); return this; } + /** + * @deprecated Use {@link BlockEntityType.Builder#build()}. + */ + @Deprecated public BlockEntityType build() { return build(null); } + /** + * @deprecated Use {@link BlockEntityType.Builder#build(Type)}. + */ + @Deprecated public BlockEntityType build(Type type) { return BlockEntityType.Builder.create(factory::create, blocks.toArray(new Block[0])) .build(type); } + /** + * @deprecated Use {@link BlockEntityType.BlockEntityFactory}. + */ @FunctionalInterface + @Deprecated public interface Factory { T create(BlockPos blockPos, BlockState blockState); } diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityType.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityType.java new file mode 100644 index 0000000000..7f60377ac3 --- /dev/null +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityType.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.object.builder.v1.entity; + +import java.util.function.Supplier; +import java.util.function.UnaryOperator; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.SpawnGroup; +import net.minecraft.entity.SpawnRestriction; +import net.minecraft.entity.attribute.DefaultAttributeContainer; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.world.Heightmap; + +import net.fabricmc.fabric.impl.object.builder.FabricEntityTypeImpl; + +/** + * General-purpose Fabric-provided extensions for {@link EntityType}. + */ +public interface FabricEntityType { + /** + * General-purpose Fabric-provided extensions for {@link EntityType.Builder}. + * + *

Note: This interface is automatically implemented on {@link EntityType.Builder} via Mixin and interface injection. + */ + interface Builder { + /** + * Sets whether the entity's velocity should always be updated. + * + * @param alwaysUpdateVelocity whether the entity's velocity should always be updated + * @return this builder + */ + default EntityType.Builder alwaysUpdateVelocity(boolean alwaysUpdateVelocity) { + throw new AssertionError("Implemented in Mixin"); + } + + /** + * Build the entity type from the builder. Same as {@link EntityType.Builder#build(String)} but without an id. + * + * @return the entity type instance + */ + default EntityType build() { + throw new AssertionError("Implemented in Mixin"); + } + + /** + * Creates an entity type builder for a living entity. + * + *

This entity's spawn group will automatically be set to {@link SpawnGroup#MISC}. + * + * @param the type of entity + * @param livingBuilder a function to configure living entity specific properties + * + * @return a new living entity type builder + */ + static EntityType.Builder createLiving(EntityType.EntityFactory factory, SpawnGroup spawnGroup, UnaryOperator> livingBuilder) { + return FabricEntityTypeImpl.Builder.createLiving(factory, spawnGroup, livingBuilder); + } + + /** + * Creates an entity type builder for a mob entity. + * + * @param the type of entity + * @param mobBuilder a function to configure mob entity specific properties + * + * @return a new mob entity type builder + */ + static EntityType.Builder createMob(EntityType.EntityFactory factory, SpawnGroup spawnGroup, UnaryOperator> mobBuilder) { + return FabricEntityTypeImpl.Builder.createMob(factory, spawnGroup, mobBuilder); + } + + /** + * A builder for additional properties of a living entity, use via {@link #createLiving(EntityType.EntityFactory, SpawnGroup, UnaryOperator)}. + * @param the type of living entity + */ + interface Living { + /** + * Sets the default attributes for a type of living entity. + * + * @param defaultAttributeBuilder a function to generate the default attribute builder from the entity type + * @return this builder for chaining + */ + Living defaultAttributes(Supplier defaultAttributeBuilder); + } + + /** + * A builder for additional properties of a mob entity, use via {@link #createMob(EntityType.EntityFactory, SpawnGroup, UnaryOperator)}. + * @param the type of mob entity + */ + interface Mob extends Living { + /** + * Registers a spawn restriction for this entity. + * + *

This is used by mobs to determine whether Minecraft should spawn an entity within a certain context. + * + * @return this builder for chaining. + */ + Mob spawnRestriction(SpawnRestriction.Location location, Heightmap.Type heightmap, SpawnRestriction.SpawnPredicate spawnPredicate); + + /** + * Sets the default attributes for a type of mob entity. + * + * @param defaultAttributeBuilder a function to generate the default attribute builder from the entity type + * @return this builder for chaining + */ + @Override + Mob defaultAttributes(Supplier defaultAttributeBuilder); + } + } +} diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityTypeBuilder.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityTypeBuilder.java index d8d1b02f43..da52194975 100644 --- a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityTypeBuilder.java +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityTypeBuilder.java @@ -18,6 +18,7 @@ import java.util.Objects; import java.util.function.Supplier; +import java.util.function.UnaryOperator; import com.google.common.collect.ImmutableSet; import org.jetbrains.annotations.Nullable; @@ -33,19 +34,13 @@ import net.minecraft.entity.attribute.DefaultAttributeContainer; import net.minecraft.entity.mob.MobEntity; import net.minecraft.resource.featuretoggle.FeatureFlag; -import net.minecraft.resource.featuretoggle.FeatureFlags; -import net.minecraft.resource.featuretoggle.FeatureSet; import net.minecraft.world.Heightmap; import net.minecraft.world.World; -import net.fabricmc.fabric.impl.object.builder.FabricEntityType; - /** - * Extended version of {@link EntityType.Builder} with added registration for - * server->client entity tracking values. - * - * @param Entity class. + * @deprecated replace with {@link EntityType.Builder} */ +@Deprecated public class FabricEntityTypeBuilder { private SpawnGroup spawnGroup; private EntityType.EntityFactory factory; @@ -59,7 +54,8 @@ public class FabricEntityTypeBuilder { private EntityDimensions dimensions = EntityDimensions.changing(-1.0f, -1.0f); private ImmutableSet specificSpawnBlocks = ImmutableSet.of(); - private FeatureSet requiredFeatures = FeatureFlags.VANILLA_FEATURES; + @Nullable + private FeatureFlag[] requiredFeatures = null; protected FabricEntityTypeBuilder(SpawnGroup spawnGroup, EntityType.EntityFactory factory) { this.spawnGroup = spawnGroup; @@ -75,7 +71,9 @@ protected FabricEntityTypeBuilder(SpawnGroup spawnGroup, EntityType.EntityFactor * @param the type of entity * * @return a new entity type builder + * @deprecated use {@link EntityType.Builder#create(SpawnGroup)} */ + @Deprecated public static FabricEntityTypeBuilder create() { return create(SpawnGroup.MISC); } @@ -87,7 +85,9 @@ public static FabricEntityTypeBuilder create() { * @param the type of entity * * @return a new entity type builder + * @deprecated use {@link EntityType.Builder#create(SpawnGroup)} */ + @Deprecated public static FabricEntityTypeBuilder create(SpawnGroup spawnGroup) { return create(spawnGroup, FabricEntityTypeBuilder::emptyFactory); } @@ -100,7 +100,9 @@ public static FabricEntityTypeBuilder create(SpawnGroup sp * @param the type of entity * * @return a new entity type builder + * @deprecated use {@link EntityType.Builder#create(EntityType.EntityFactory, SpawnGroup)} */ + @Deprecated public static FabricEntityTypeBuilder create(SpawnGroup spawnGroup, EntityType.EntityFactory factory) { return new FabricEntityTypeBuilder<>(spawnGroup, factory); } @@ -113,7 +115,9 @@ public static FabricEntityTypeBuilder create(SpawnGroup sp * @param the type of entity * * @return a new living entity type builder + * @deprecated use {@link FabricEntityType.Builder#createLiving(UnaryOperator)} */ + @Deprecated public static FabricEntityTypeBuilder.Living createLiving() { return new FabricEntityTypeBuilder.Living<>(SpawnGroup.MISC, FabricEntityTypeBuilder::emptyFactory); } @@ -124,6 +128,7 @@ public static FabricEntityTypeBuilder.Living createL * @param the type of entity * * @return a new mob entity type builder + * @deprecated use {@link FabricEntityType.Builder#createMob(UnaryOperator)} */ public static FabricEntityTypeBuilder.Mob createMob() { return new FabricEntityTypeBuilder.Mob<>(SpawnGroup.MISC, FabricEntityTypeBuilder::emptyFactory); @@ -133,12 +138,14 @@ private static T emptyFactory(EntityType type, World world return null; } + @Deprecated public FabricEntityTypeBuilder spawnGroup(SpawnGroup group) { Objects.requireNonNull(group, "Spawn group cannot be null"); this.spawnGroup = group; return this; } + @Deprecated public FabricEntityTypeBuilder entityFactory(EntityType.EntityFactory factory) { Objects.requireNonNull(factory, "Entity Factory cannot be null"); this.factory = (EntityType.EntityFactory) factory; @@ -149,12 +156,18 @@ public FabricEntityTypeBuilder entityFactory(EntityType.EntityF * Whether this entity type is summonable using the {@code /summon} command. * * @return this builder for chaining + * @deprecated use {@link EntityType.Builder#disableSummon()} */ + @Deprecated public FabricEntityTypeBuilder disableSummon() { this.summonable = false; return this; } + /** + * @deprecated use {@link EntityType.Builder#disableSaving()} + */ + @Deprecated public FabricEntityTypeBuilder disableSaving() { this.saveable = false; return this; @@ -164,7 +177,9 @@ public FabricEntityTypeBuilder disableSaving() { * Sets this entity type to be fire immune. * * @return this builder for chaining + * @deprecated use {@link EntityType.Builder#makeFireImmune()} */ + @Deprecated public FabricEntityTypeBuilder fireImmune() { this.fireImmune = true; return this; @@ -174,7 +189,9 @@ public FabricEntityTypeBuilder fireImmune() { * Sets whether this entity type can be spawned far away from a player. * * @return this builder for chaining + * @deprecated use {@link EntityType.Builder#spawnableFarFromPlayer()} */ + @Deprecated public FabricEntityTypeBuilder spawnableFarFromPlayer() { this.spawnableFarFromPlayer = true; return this; @@ -186,7 +203,9 @@ public FabricEntityTypeBuilder spawnableFarFromPlayer() { * @param dimensions the dimensions representing the entity's size * * @return this builder for chaining + * @deprecated use {@link EntityType.Builder#setDimensions(float, float)} */ + @Deprecated public FabricEntityTypeBuilder dimensions(EntityDimensions dimensions) { Objects.requireNonNull(dimensions, "Cannot set null dimensions"); this.dimensions = dimensions; @@ -218,7 +237,9 @@ public FabricEntityTypeBuilder trackable(int trackRangeBlocks, int trackedUpd * @param range the tracking range in chunks * * @return this builder for chaining + * @deprecated use {@link FabricEntityTypeBuilder#trackRangeBlocks(int)} */ + @Deprecated public FabricEntityTypeBuilder trackRangeChunks(int range) { this.trackRange = range; return this; @@ -230,16 +251,26 @@ public FabricEntityTypeBuilder trackRangeChunks(int range) { * @param range the tracking range in blocks * * @return this builder for chaining + * @deprecated use {@link FabricEntityTypeBuilder#trackRangeChunks(int)} */ + @Deprecated public FabricEntityTypeBuilder trackRangeBlocks(int range) { return trackRangeChunks((range + 15) / 16); } + /** + * @deprecated use {@link FabricEntityTypeBuilder#trackRangeBlocks(int)} + */ + @Deprecated public FabricEntityTypeBuilder trackedUpdateRate(int rate) { this.trackedUpdateRate = rate; return this; } + /** + * @deprecated use {@link FabricEntityTypeBuilder#trackRangeBlocks(int)} + */ + @Deprecated public FabricEntityTypeBuilder forceTrackedVelocityUpdates(boolean forceTrackedVelocityUpdates) { this.forceTrackedVelocityUpdates = forceTrackedVelocityUpdates; return this; @@ -250,7 +281,9 @@ public FabricEntityTypeBuilder forceTrackedVelocityUpdates(boolean forceTrack * * @param blocks the blocks the entity can spawn on * @return this builder for chaining + * @deprecated use {@link EntityType.Builder#allowSpawningInside(Block...)} */ + @Deprecated public FabricEntityTypeBuilder specificSpawnBlocks(Block... blocks) { this.specificSpawnBlocks = ImmutableSet.copyOf(blocks); return this; @@ -261,9 +294,11 @@ public FabricEntityTypeBuilder specificSpawnBlocks(Block... blocks) { * the entity cannot be spawned, and existing ones will despawn immediately. * @param requiredFeatures the features * @return this builder for chaining + * @deprecated use {@link EntityType.Builder#requires(FeatureFlag...)} */ + @Deprecated public FabricEntityTypeBuilder requires(FeatureFlag... requiredFeatures) { - this.requiredFeatures = FeatureFlags.FEATURE_MANAGER.featureSetOf(requiredFeatures); + this.requiredFeatures = requiredFeatures; return this; } @@ -271,19 +306,50 @@ public FabricEntityTypeBuilder requires(FeatureFlag... requiredFeatures) { * Creates the entity type. * * @return a new {@link EntityType} + * @deprecated use {@link EntityType.Builder#build()} */ + @Deprecated public EntityType build() { - // Modded DFU is a dream, currently not possible without screwing it up. + EntityType.Builder builder = EntityType.Builder.create(this.factory, this.spawnGroup) + .allowSpawningInside(specificSpawnBlocks.toArray(Block[]::new)) + .maxTrackingRange(this.trackRange) + .trackingTickInterval(this.trackedUpdateRate) + .setDimensions(this.dimensions.width, this.dimensions.height); + + if (!this.saveable) { + builder = builder.disableSaving(); + } - //TODO 1.20.5, new field - return new FabricEntityType<>(this.factory, this.spawnGroup, this.saveable, this.summonable, this.fireImmune, this.spawnableFarFromPlayer, this.specificSpawnBlocks, dimensions, 1, trackRange, trackedUpdateRate, forceTrackedVelocityUpdates, this.requiredFeatures); + if (!this.summonable) { + builder = builder.disableSummon(); + } + + if (this.fireImmune) { + builder = builder.makeFireImmune(); + } + + if (this.spawnableFarFromPlayer) { + builder = builder.spawnableFarFromPlayer(); + } + + if (this.requiredFeatures != null) { + builder = builder.requires(this.requiredFeatures); + } + + if (this.forceTrackedVelocityUpdates != null) { + builder = builder.alwaysUpdateVelocity(this.forceTrackedVelocityUpdates); + } + + return builder.build(null); } /** * An extended version of {@link FabricEntityTypeBuilder} with support for features on present on {@link LivingEntity living entities}, such as default attributes. * * @param Entity class. + * @deprecated use {@link EntityType.Builder#createLiving(UnaryOperator)} */ + @Deprecated public static class Living extends FabricEntityTypeBuilder { @Nullable private Supplier defaultAttributeBuilder; @@ -399,13 +465,16 @@ public FabricEntityTypeBuilder.Living specificSpawnBlocks(Block... blocks) { * * @param defaultAttributeBuilder a function to generate the default attribute builder from the entity type * @return this builder for chaining + * @deprecated use {@link FabricEntityType.Builder.Living#defaultAttributes(Supplier)} */ + @Deprecated public FabricEntityTypeBuilder.Living defaultAttributes(Supplier defaultAttributeBuilder) { Objects.requireNonNull(defaultAttributeBuilder, "Cannot set null attribute builder"); this.defaultAttributeBuilder = defaultAttributeBuilder; return this; } + @Deprecated @Override public EntityType build() { final EntityType type = super.build(); @@ -423,6 +492,7 @@ public EntityType build() { * * @param Entity class. */ + @Deprecated public static class Mob extends FabricEntityTypeBuilder.Living { private SpawnLocation spawnLocation; private Heightmap.Type restrictionHeightmap; @@ -536,7 +606,9 @@ public FabricEntityTypeBuilder.Mob defaultAttributes(SupplierThis is used by mobs to determine whether Minecraft should spawn an entity within a certain context. * * @return this builder for chaining. + * @deprecated use {@link FabricEntityType.Builder.Mob#spawnRestriction(SpawnRestriction.Location, Heightmap.Type, SpawnRestriction.SpawnPredicate)} */ + @Deprecated public FabricEntityTypeBuilder.Mob spawnRestriction(SpawnLocation spawnLocation, Heightmap.Type heightmap, SpawnRestriction.SpawnPredicate spawnPredicate) { this.spawnLocation = Objects.requireNonNull(spawnLocation, "Spawn location cannot be null."); this.restrictionHeightmap = Objects.requireNonNull(heightmap, "Heightmap type cannot be null."); diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/FabricEntityType.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/FabricEntityType.java deleted file mode 100644 index dde18eec8c..0000000000 --- a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/FabricEntityType.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2016, 2017, 2018, 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.fabric.impl.object.builder; - -import com.google.common.collect.ImmutableSet; - -import net.minecraft.block.Block; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityDimensions; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.SpawnGroup; -import net.minecraft.resource.featuretoggle.FeatureSet; - -public class FabricEntityType extends EntityType { - private final Boolean alwaysUpdateVelocity; - - public FabricEntityType(EntityType.EntityFactory factory, SpawnGroup spawnGroup, boolean bl, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet spawnBlocks, EntityDimensions entityDimensions, float field_50125, int maxTrackDistance, int trackTickInterval, Boolean alwaysUpdateVelocity, FeatureSet featureSet) { - super(factory, spawnGroup, bl, summonable, fireImmune, spawnableFarFromPlayer, spawnBlocks, entityDimensions, field_50125, maxTrackDistance, trackTickInterval, featureSet); - this.alwaysUpdateVelocity = alwaysUpdateVelocity; - } - - @Override - public boolean alwaysUpdateVelocity() { - if (alwaysUpdateVelocity != null) { - return alwaysUpdateVelocity; - } - - return super.alwaysUpdateVelocity(); - } -} diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/FabricEntityTypeImpl.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/FabricEntityTypeImpl.java new file mode 100644 index 0000000000..3a563912b6 --- /dev/null +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/FabricEntityTypeImpl.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.impl.object.builder; + +import java.util.Objects; +import java.util.function.Supplier; +import java.util.function.UnaryOperator; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.SpawnGroup; +import net.minecraft.entity.SpawnRestriction; +import net.minecraft.entity.attribute.DefaultAttributeContainer; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.world.Heightmap; + +import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry; +import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityType; + +public interface FabricEntityTypeImpl { + void fabric_setAlwaysUpdateVelocity(Boolean alwaysUpdateVelocity); + + interface Builder { + void fabric_setLivingEntityBuilder(Living livingBuilder); + + void fabric_setMobEntityBuilder(Mob mobBuilder); + + static EntityType.Builder createLiving(EntityType.EntityFactory factory, SpawnGroup spawnGroup, UnaryOperator> livingBuilder) { + EntityType.Builder builder = EntityType.Builder.create(factory, spawnGroup); + Living builderImpl = new Living<>(); + livingBuilder.apply(builderImpl); + ((Builder) builder).fabric_setLivingEntityBuilder(builderImpl); + return builder; + } + + static EntityType.Builder createMob(EntityType.EntityFactory factory, SpawnGroup spawnGroup, UnaryOperator> mobBuilder) { + EntityType.Builder builder = EntityType.Builder.create(factory, spawnGroup); + Mob builderImpl = new Mob<>(); + mobBuilder.apply(builderImpl); + ((Builder) builder).fabric_setMobEntityBuilder(builderImpl); + return builder; + } + + sealed class Living implements FabricEntityType.Builder.Living permits Mob { + @Nullable + private Supplier defaultAttributeBuilder; + + @Override + public FabricEntityType.Builder.Living defaultAttributes(Supplier defaultAttributeBuilder) { + Objects.requireNonNull(defaultAttributeBuilder, "Cannot set null attribute builder"); + this.defaultAttributeBuilder = defaultAttributeBuilder; + return this; + } + + public void onBuild(EntityType type) { + if (this.defaultAttributeBuilder != null) { + FabricDefaultAttributeRegistry.register(type, this.defaultAttributeBuilder.get()); + } + } + } + + final class Mob extends Living implements FabricEntityType.Builder.Mob { + private SpawnRestriction.Location restrictionLocation; + private Heightmap.Type restrictionHeightmap; + private SpawnRestriction.SpawnPredicate spawnPredicate; + + @Override + public FabricEntityType.Builder.Mob spawnRestriction(SpawnRestriction.Location location, Heightmap.Type heightmap, SpawnRestriction.SpawnPredicate spawnPredicate) { + this.restrictionLocation = Objects.requireNonNull(location, "Location cannot be null."); + this.restrictionHeightmap = Objects.requireNonNull(heightmap, "Heightmap type cannot be null."); + this.spawnPredicate = Objects.requireNonNull(spawnPredicate, "Spawn predicate cannot be null."); + return this; + } + + @Override + public FabricEntityType.Builder.Mob defaultAttributes(Supplier defaultAttributeBuilder) { + super.defaultAttributes(defaultAttributeBuilder); + return this; + } + + public void onBuild(EntityType type) { + super.onBuild(type); + + if (this.spawnPredicate != null) { + SpawnRestriction.register(type, this.restrictionLocation, this.restrictionHeightmap, this.spawnPredicate); + } + } + } + } +} diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/BlockEntityTypeBuilderMixin.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/BlockEntityTypeBuilderMixin.java new file mode 100644 index 0000000000..5d9342ec1f --- /dev/null +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/BlockEntityTypeBuilderMixin.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.object.builder; + +import com.mojang.datafixers.types.Type; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityType; + +import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityType; + +@Mixin(BlockEntityType.Builder.class) +public abstract class BlockEntityTypeBuilderMixin implements FabricBlockEntityType.Builder { + @Shadow + public abstract BlockEntityType build(Type type); + + @Override + public BlockEntityType build() { + return build(null); + } +} diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/EntityTypeBuilderMixin.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/EntityTypeBuilderMixin.java new file mode 100644 index 0000000000..286dfdde15 --- /dev/null +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/EntityTypeBuilderMixin.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.object.builder; + +import java.util.Objects; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.mojang.datafixers.DSL; +import com.mojang.datafixers.types.Type; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.mob.MobEntity; + +import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityType; +import net.fabricmc.fabric.impl.object.builder.FabricEntityTypeImpl; + +@Mixin(EntityType.Builder.class) +public abstract class EntityTypeBuilderMixin implements FabricEntityType.Builder, FabricEntityTypeImpl.Builder { + @Shadow + public abstract EntityType build(String id); + + @Unique + private Boolean alwaysUpdateVelocity = null; + + @Unique + private FabricEntityTypeImpl.Builder.Living livingBuilder = null; + @Unique + private FabricEntityTypeImpl.Builder.Mob mobBuilder = null; + + @Override + public EntityType.Builder alwaysUpdateVelocity(boolean forceTrackedVelocityUpdates) { + alwaysUpdateVelocity = forceTrackedVelocityUpdates; + return (EntityType.Builder) (Object) this; + } + + @Override + public EntityType build() { + return build(null); + } + + @Inject(method = "build", at = @At("RETURN")) + private void applyChildBuilders(String id, CallbackInfoReturnable> cir) { + if (!(cir.getReturnValue() instanceof FabricEntityTypeImpl entityType)) { + throw new IllegalStateException(); + } + + entityType.fabric_setAlwaysUpdateVelocity(alwaysUpdateVelocity); + + if (livingBuilder != null) { + livingBuilder.onBuild(castLiving(cir.getReturnValue())); + } + + if (mobBuilder != null) { + mobBuilder.onBuild(castMob(cir.getReturnValue())); + } + } + + @SuppressWarnings("unchecked") + @Unique + private static EntityType castLiving(EntityType type) { + return (EntityType) type; + } + + @SuppressWarnings("unchecked") + @Unique + private static EntityType castMob(EntityType type) { + return (EntityType) type; + } + + @WrapOperation(method = "build", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Util;getChoiceType(Lcom/mojang/datafixers/DSL$TypeReference;Ljava/lang/String;)Lcom/mojang/datafixers/types/Type;")) + private @Nullable Type allowNullId(DSL.TypeReference typeReference, String id, Operation> original) { + if (id == null) { + return null; + } + + return original.call(typeReference, id); + } + + @Override + public void fabric_setLivingEntityBuilder(FabricEntityTypeImpl.Builder.Living livingBuilder) { + Objects.requireNonNull(livingBuilder, "Cannot set null living entity builder"); + this.livingBuilder = livingBuilder; + } + + @Override + public void fabric_setMobEntityBuilder(FabricEntityTypeImpl.Builder.Mob mobBuilder) { + Objects.requireNonNull(mobBuilder, "Cannot set null mob entity builder"); + this.mobBuilder = mobBuilder; + } +} diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/EntityTypeMixin.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/EntityTypeMixin.java new file mode 100644 index 0000000000..4d493d6d61 --- /dev/null +++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/mixin/object/builder/EntityTypeMixin.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.mixin.object.builder; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.entity.EntityType; + +import net.fabricmc.fabric.impl.object.builder.FabricEntityTypeImpl; + +@Mixin(EntityType.class) +public abstract class EntityTypeMixin implements FabricEntityTypeImpl { + @Unique + private Boolean alwaysUpdateVelocity; + + @Inject(method = "alwaysUpdateVelocity", at = @At("HEAD"), cancellable = true) + public void alwaysUpdateVelocity(CallbackInfoReturnable cir) { + if (alwaysUpdateVelocity != null) { + cir.setReturnValue(alwaysUpdateVelocity); + } + } + + @Override + public void fabric_setAlwaysUpdateVelocity(Boolean alwaysUpdateVelocity) { + this.alwaysUpdateVelocity = alwaysUpdateVelocity; + } +} diff --git a/fabric-object-builder-api-v1/src/main/resources/fabric-object-builder-v1.mixins.json b/fabric-object-builder-api-v1/src/main/resources/fabric-object-builder-v1.mixins.json index a5c4f877c0..22d799f1ed 100644 --- a/fabric-object-builder-api-v1/src/main/resources/fabric-object-builder-v1.mixins.json +++ b/fabric-object-builder-api-v1/src/main/resources/fabric-object-builder-v1.mixins.json @@ -5,9 +5,12 @@ "mixins": [ "AbstractBlockAccessor", "AbstractBlockSettingsAccessor", + "BlockEntityTypeBuilderMixin", "DefaultAttributeRegistryAccessor", "DefaultAttributeRegistryMixin", "DetectorRailBlockMixin", + "EntityTypeBuilderMixin", + "EntityTypeMixin", "PersistentStateManagerMixin", "TradeOffersTypeAwareBuyForOneEmeraldFactoryMixin" ], diff --git a/fabric-object-builder-api-v1/src/main/resources/fabric.mod.json b/fabric-object-builder-api-v1/src/main/resources/fabric.mod.json index 940c46c6d7..8aa8fb234f 100644 --- a/fabric-object-builder-api-v1/src/main/resources/fabric.mod.json +++ b/fabric-object-builder-api-v1/src/main/resources/fabric.mod.json @@ -29,6 +29,10 @@ ], "accessWidener" : "fabric-object-builder-api-v1.accesswidener", "custom": { - "fabric-api:module-lifecycle": "stable" + "fabric-api:module-lifecycle": "stable", + "loom:injected_interfaces": { + "net/minecraft/class_1299\u0024class_1300": ["net/fabricmc/fabric/api/object/builder/v1/entity/FabricEntityType\u0024Builder"], + "net/minecraft/class_2591\u0024class_2592": ["net/fabricmc/fabric/api/object/builder/v1/block/entity/FabricBlockEntityType\u0024Builder"] + } } } diff --git a/fabric-object-builder-api-v1/src/test/java/net/fabricmc/fabric/test/object/builder/FabricEntityTypeTest.java b/fabric-object-builder-api-v1/src/test/java/net/fabricmc/fabric/test/object/builder/FabricEntityTypeTest.java new file mode 100644 index 0000000000..f3f477518c --- /dev/null +++ b/fabric-object-builder-api-v1/src/test/java/net/fabricmc/fabric/test/object/builder/FabricEntityTypeTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.test.object.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import net.minecraft.Bootstrap; +import net.minecraft.SharedConstants; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.SpawnGroup; +import net.minecraft.entity.SpawnRestriction; +import net.minecraft.entity.attribute.DefaultAttributeContainer; +import net.minecraft.entity.attribute.DefaultAttributeRegistry; +import net.minecraft.entity.attribute.EntityAttributes; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.entity.passive.PigEntity; +import net.minecraft.world.Heightmap; + +import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityType; + +public class FabricEntityTypeTest { + @BeforeAll + static void beforeAll() { + SharedConstants.createGameVersion(); + Bootstrap.initialize(); + } + + @Test + void buildEntityType() { + EntityType type = EntityType.Builder.create(SpawnGroup.MISC) + .alwaysUpdateVelocity(true) + .build(); + + assertNotNull(type); + assertTrue(type.alwaysUpdateVelocity()); + } + + @Test + void buildLivingEntityType() { + EntityType type = FabricEntityType.Builder.createLiving((t, w) -> null, SpawnGroup.MISC, living -> living + .defaultAttributes(FabricEntityTypeTest::createAttributes) + ).build(); + + assertNotNull(type); + assertNotNull(DefaultAttributeRegistry.get(type)); + } + + @Test + void buildMobEntityType() { + EntityType type = FabricEntityType.Builder.createMob((t, w) -> null, SpawnGroup.MISC, mob -> mob + .spawnRestriction(SpawnRestriction.Location.ON_GROUND, Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, PigEntity::canMobSpawn) + .defaultAttributes(FabricEntityTypeTest::createAttributes) + ).build(); + + assertNotNull(type); + assertEquals(SpawnRestriction.Location.ON_GROUND, SpawnRestriction.getLocation(type)); + assertNotNull(DefaultAttributeRegistry.get(type)); + } + + private static DefaultAttributeContainer.Builder createAttributes() { + return MobEntity.createMobAttributes() + .add(EntityAttributes.GENERIC_MAX_HEALTH, 10.0) + .add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.25); + } +}