mirror of
https://github.com/FabricMC/fabric.git
synced 2025-05-12 14:21:01 -04:00
parent
3f161dddc9
commit
c327076adb
52 changed files with 405 additions and 786 deletions
fabric-object-builder-api-v1/src
main
java/net/fabricmc/fabric
api/object/builder/v1
impl/object/builder
mixin/object/builder
resources
testmod/java/net/fabricmc/fabric/test/object/builder
|
@ -22,6 +22,7 @@ import java.util.function.Consumer;
|
|||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.village.TradeOffers;
|
||||
import net.minecraft.village.VillagerProfession;
|
||||
|
@ -49,7 +50,7 @@ public final class TradeOfferHelper {
|
|||
* @param level the profession level the villager must be to offer the trades
|
||||
* @param factories a consumer to provide the factories
|
||||
*/
|
||||
public static void registerVillagerOffers(VillagerProfession profession, int level, Consumer<List<TradeOffers.Factory>> factories) {
|
||||
public static void registerVillagerOffers(RegistryKey<VillagerProfession> profession, int level, Consumer<List<TradeOffers.Factory>> factories) {
|
||||
TradeOfferInternals.registerVillagerOffers(profession, level, (trades, rebalanced) -> factories.accept(trades));
|
||||
}
|
||||
|
||||
|
@ -74,7 +75,7 @@ public final class TradeOfferHelper {
|
|||
* @param factories a consumer to provide the factories
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
public static void registerVillagerOffers(VillagerProfession profession, int level, VillagerOffersAdder factories) {
|
||||
public static void registerVillagerOffers(RegistryKey<VillagerProfession> profession, int level, VillagerOffersAdder factories) {
|
||||
TradeOfferInternals.registerVillagerOffers(profession, level, factories);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,185 +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.api.object.builder.v1.villager;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.entry.RegistryEntry;
|
||||
import net.minecraft.sound.SoundEvent;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.village.TradeOffers;
|
||||
import net.minecraft.village.VillagerProfession;
|
||||
import net.minecraft.world.poi.PointOfInterestType;
|
||||
|
||||
/**
|
||||
* Allows for the creation of new {@link VillagerProfession}s.
|
||||
*
|
||||
* <p>The texture for the villagers are located at <code>assets/IDENTIFIER_NAMESPACE/textures/entity/villager/profession/IDENTIFIER_PATH.png</code>
|
||||
*
|
||||
* <p>A corresponding <code>IDENTIFIER_PATH.mcmeta</code> file exits in the same directory to define properties such as the {@link net.minecraft.client.render.entity.feature.VillagerResourceMetadata.HatType HatType} this profession would use.
|
||||
*
|
||||
* <p>Note this does not register any trades to these villagers. To register trades, add a new entry with your profession as the key to {@link TradeOffers#PROFESSION_TO_LEVELED_TRADE}.
|
||||
*
|
||||
* @deprecated Replaced by access widener for {@link VillagerProfession#VillagerProfession}
|
||||
* in Fabric Transitive Access Wideners (v1).
|
||||
*/
|
||||
@Deprecated
|
||||
public final class VillagerProfessionBuilder {
|
||||
private final ImmutableSet.Builder<Item> gatherableItemsBuilder = ImmutableSet.builder();
|
||||
private final ImmutableSet.Builder<Block> secondaryJobSiteBlockBuilder = ImmutableSet.builder();
|
||||
private Identifier identifier;
|
||||
private Predicate<RegistryEntry<PointOfInterestType>> pointOfInterestType;
|
||||
private Predicate<RegistryEntry<PointOfInterestType>> acquirableJobSite;
|
||||
@Nullable
|
||||
private SoundEvent workSoundEvent;
|
||||
|
||||
private VillagerProfessionBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a builder instance to allow for creation of a {@link VillagerProfession}.
|
||||
*
|
||||
* @return A new builder.
|
||||
*/
|
||||
public static VillagerProfessionBuilder create() {
|
||||
return new VillagerProfessionBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* The Identifier used to identify this villager profession.
|
||||
*
|
||||
* @param id The identifier to assign to this profession.
|
||||
* @return this builder
|
||||
*/
|
||||
public VillagerProfessionBuilder id(Identifier id) {
|
||||
this.identifier = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link PointOfInterestType} the Villager of this profession will search for when finding a workstation.
|
||||
*
|
||||
* @param key The {@link PointOfInterestType} the Villager will attempt to find.
|
||||
* @return this builder.
|
||||
*/
|
||||
public VillagerProfessionBuilder workstation(RegistryKey<PointOfInterestType> key) {
|
||||
jobSite(entry -> entry.matchesKey(key));
|
||||
return workstation(entry -> entry.matchesKey(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link PointOfInterestType} the Villager of this profession will search for when finding a workstation.
|
||||
*
|
||||
* @param predicate The {@link PointOfInterestType} the Villager will attempt to find.
|
||||
* @return this builder.
|
||||
*/
|
||||
public VillagerProfessionBuilder workstation(Predicate<RegistryEntry<PointOfInterestType>> predicate) {
|
||||
this.pointOfInterestType = predicate;
|
||||
return this;
|
||||
}
|
||||
|
||||
public VillagerProfessionBuilder jobSite(Predicate<RegistryEntry<PointOfInterestType>> predicate) {
|
||||
this.acquirableJobSite = predicate;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Items that a Villager may harvest in this profession.
|
||||
*
|
||||
* <p>In Vanilla, this is used by the farmer to define what type of crops the farmer can harvest.
|
||||
*
|
||||
* @param items Items harvestable by this profession.
|
||||
* @return this builder.
|
||||
*/
|
||||
public VillagerProfessionBuilder harvestableItems(Item... items) {
|
||||
this.gatherableItemsBuilder.add(items);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Items that a Villager may harvest in this profession.
|
||||
*
|
||||
* <p>In Vanilla, this is used by the farmer to define what type of crops the farmer can harvest.
|
||||
*
|
||||
* @param items Items harvestable by this profession.
|
||||
* @return this builder.
|
||||
*/
|
||||
public VillagerProfessionBuilder harvestableItems(Iterable<Item> items) {
|
||||
this.gatherableItemsBuilder.addAll(items);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A collection of blocks blocks which may suffice as a secondary job site for a Villager.
|
||||
*
|
||||
* <p>In Vanilla, this is used by the {@link VillagerProfession#FARMER Farmer} to stay near {@link Blocks#FARMLAND Farmland} when at it's job site.
|
||||
*
|
||||
* @param blocks Collection of secondary job site blocks.
|
||||
* @return this builder.
|
||||
*/
|
||||
public VillagerProfessionBuilder secondaryJobSites(Block... blocks) {
|
||||
this.secondaryJobSiteBlockBuilder.add(blocks);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A collection of blocks blocks which may suffice as a secondary job site for a Villager.
|
||||
*
|
||||
* <p>In Vanilla, this is used by the {@link VillagerProfession#FARMER Farmer} to stay near {@link Blocks#FARMLAND Farmland} when at it's job site.
|
||||
*
|
||||
* @param blocks Collection of secondary job site blocks.
|
||||
* @return this builder.
|
||||
*/
|
||||
public VillagerProfessionBuilder secondaryJobSites(Iterable<Block> blocks) {
|
||||
this.secondaryJobSiteBlockBuilder.addAll(blocks);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the sound made when a Villager works.
|
||||
*
|
||||
* @param workSoundEvent The {@link SoundEvent} to be played.
|
||||
* @return this builder.
|
||||
*/
|
||||
public VillagerProfessionBuilder workSound(@Nullable SoundEvent workSoundEvent) {
|
||||
this.workSoundEvent = workSoundEvent;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the {@link VillagerProfession}.
|
||||
*
|
||||
* @return a new {@link VillagerProfession}.
|
||||
* @throws IllegalStateException if the builder is missing an {@link Identifier id} and {@link PointOfInterestType workstation}.
|
||||
*/
|
||||
public VillagerProfession build() {
|
||||
checkState(this.identifier != null, "An Identifier is required to build a new VillagerProfession.");
|
||||
checkState(this.pointOfInterestType != null, "A PointOfInterestType is required to build a new VillagerProfession.");
|
||||
checkState(this.acquirableJobSite != null, "A PointOfInterestType is required for the acquirableJobSite to build a new VillagerProfession.");
|
||||
|
||||
return new VillagerProfession(this.identifier.toString(), this.pointOfInterestType, this.acquirableJobSite, this.gatherableItemsBuilder.build(), this.secondaryJobSiteBlockBuilder.build(), this.workSoundEvent);
|
||||
}
|
||||
}
|
|
@ -1,79 +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.api.object.builder.v1.villager;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.village.VillagerProfession;
|
||||
import net.minecraft.village.VillagerType;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
|
||||
/**
|
||||
* Utilities related to the creation of {@link VillagerType}s.
|
||||
* Not to be confused with a {@link VillagerProfession}, a villager type defines the appearance of a villager.
|
||||
*
|
||||
* <p>Creation and registration of custom villager types may be done by using {@link VillagerTypeHelper#register(Identifier)}.
|
||||
*
|
||||
* <p>Creation and registration of a villager type does not guarantee villagers of a specific type will be created in a world.
|
||||
* Typically the villager type is bound to a specific group of biomes.
|
||||
* To allow a villager type to be spawned in a specific biome, use {@link VillagerTypeHelper#addVillagerTypeToBiome(RegistryKey, VillagerType)}.
|
||||
*
|
||||
* <p>The texture used for the appearance of the villager is located at {@code assets/IDENTIFIER_NAMESPACE/textures/entity/villager/type/IDENTIFIER_PATH.png}.
|
||||
*
|
||||
* @deprecated Replaced by access wideners for {@link VillagerType#create} and {@link VillagerType#BIOME_TO_TYPE}
|
||||
* in Fabric Transitive Access Wideners (v1).
|
||||
*/
|
||||
@Deprecated
|
||||
public final class VillagerTypeHelper {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(VillagerTypeHelper.class);
|
||||
|
||||
/**
|
||||
* Creates and registers a new villager type.
|
||||
*
|
||||
* @param id the id of the villager type
|
||||
* @return a new villager type
|
||||
*/
|
||||
public static VillagerType register(Identifier id) {
|
||||
Objects.requireNonNull(id, "Id of villager type cannot be null");
|
||||
return Registry.register(Registries.VILLAGER_TYPE, id, new VillagerType(id.toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the biome a villager type can spawn in.
|
||||
*
|
||||
* @param biomeKey the registry key of the biome
|
||||
* @param villagerType the villager type
|
||||
*/
|
||||
public static void addVillagerTypeToBiome(RegistryKey<Biome> biomeKey, VillagerType villagerType) {
|
||||
Objects.requireNonNull(biomeKey, "Biome registry key cannot be null");
|
||||
Objects.requireNonNull(villagerType, "Villager type cannot be null");
|
||||
|
||||
if (VillagerType.BIOME_TO_TYPE.put(biomeKey, villagerType) != null) {
|
||||
LOGGER.debug("Overriding existing Biome -> VillagerType registration for Biome {}", biomeKey.getValue().toString());
|
||||
}
|
||||
}
|
||||
|
||||
private VillagerTypeHelper() {
|
||||
}
|
||||
}
|
|
@ -32,6 +32,7 @@ import org.apache.commons.lang3.tuple.Pair;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Util;
|
||||
import net.minecraft.village.TradeOffers;
|
||||
|
@ -51,9 +52,9 @@ public final class TradeOfferInternals {
|
|||
*/
|
||||
private static void initVillagerTrades() {
|
||||
if (!(TradeOffers.REBALANCED_PROFESSION_TO_LEVELED_TRADE instanceof HashMap)) {
|
||||
Map<VillagerProfession, Int2ObjectMap<TradeOffers.Factory[]>> map = new HashMap<>(TradeOffers.REBALANCED_PROFESSION_TO_LEVELED_TRADE);
|
||||
Map<RegistryKey<VillagerProfession>, Int2ObjectMap<TradeOffers.Factory[]>> map = new HashMap<>(TradeOffers.REBALANCED_PROFESSION_TO_LEVELED_TRADE);
|
||||
|
||||
for (Map.Entry<VillagerProfession, Int2ObjectMap<TradeOffers.Factory[]>> trade : TradeOffers.PROFESSION_TO_LEVELED_TRADE.entrySet()) {
|
||||
for (Map.Entry<RegistryKey<VillagerProfession>, Int2ObjectMap<TradeOffers.Factory[]>> trade : TradeOffers.PROFESSION_TO_LEVELED_TRADE.entrySet()) {
|
||||
if (!map.containsKey(trade.getKey())) map.put(trade.getKey(), trade.getValue());
|
||||
}
|
||||
|
||||
|
@ -63,7 +64,7 @@ public final class TradeOfferInternals {
|
|||
|
||||
// synchronized guards against concurrent modifications - Vanilla does not mutate the underlying arrays (as of 1.16),
|
||||
// so reads will be fine without locking.
|
||||
public static synchronized void registerVillagerOffers(VillagerProfession profession, int level, TradeOfferHelper.VillagerOffersAdder factory) {
|
||||
public static synchronized void registerVillagerOffers(RegistryKey<VillagerProfession> profession, int level, TradeOfferHelper.VillagerOffersAdder factory) {
|
||||
Objects.requireNonNull(profession, "VillagerProfession may not be null.");
|
||||
initVillagerTrades();
|
||||
registerOffers(TradeOffers.PROFESSION_TO_LEVELED_TRADE.computeIfAbsent(profession, key -> new Int2ObjectOpenHashMap<>()), level, trades -> factory.onRegister(trades, false));
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package net.fabricmc.fabric.mixin.object.builder;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
|
@ -26,7 +27,7 @@ import org.spongepowered.asm.mixin.injection.Redirect;
|
|||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.registry.DefaultedRegistry;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
import net.minecraft.village.TradeOffer;
|
||||
import net.minecraft.village.TradeOffers;
|
||||
|
@ -41,8 +42,8 @@ public abstract class TradeOffersTypeAwareBuyForOneEmeraldFactoryMixin {
|
|||
* We want to prevent this default logic so modded villager types will work.
|
||||
* So we return an empty stream so an exception is never thrown.
|
||||
*/
|
||||
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/registry/DefaultedRegistry;stream()Ljava/util/stream/Stream;"))
|
||||
private <T> Stream<T> disableVanillaCheck(DefaultedRegistry<VillagerType> instance) {
|
||||
@Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Ljava/util/Set;stream()Ljava/util/stream/Stream;"))
|
||||
private <T> Stream<T> disableVanillaCheck(Set<RegistryKey<VillagerType>> instance) {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ mutable field net/minecraft/village/TradeOffers REBALANCED_WANDERING_TRADER_TRAD
|
|||
accessible method net/minecraft/entity/SpawnRestriction register (Lnet/minecraft/entity/EntityType;Lnet/minecraft/entity/SpawnLocation;Lnet/minecraft/world/Heightmap$Type;Lnet/minecraft/entity/SpawnRestriction$SpawnPredicate;)V
|
||||
|
||||
accessible field net/minecraft/village/VillagerType BIOME_TO_TYPE Ljava/util/Map;
|
||||
accessible method net/minecraft/village/VillagerType <init> (Ljava/lang/String;)V
|
||||
|
||||
accessible method net/minecraft/block/WoodType register (Lnet/minecraft/block/WoodType;)Lnet/minecraft/block/WoodType;
|
||||
accessible method net/minecraft/block/BlockSetType register (Lnet/minecraft/block/BlockSetType;)Lnet/minecraft/block/BlockSetType;
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
|
||||
package net.fabricmc.fabric.test.object.builder;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.EquipmentSlot;
|
||||
|
@ -60,11 +58,6 @@ final class EntityTypeBuilderGenericsTest {
|
|||
super(entityType, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<ItemStack> getArmorItems() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getEquippedStack(EquipmentSlot slot) {
|
||||
return ItemStack.EMPTY;
|
||||
|
|
|
@ -19,14 +19,11 @@ package net.fabricmc.fabric.test.object.builder;
|
|||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.test.GameTest;
|
||||
import net.minecraft.test.TestContext;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import net.fabricmc.fabric.api.gametest.v1.FabricGameTest;
|
||||
|
||||
public class ObjectBuilderGameTest {
|
||||
@GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE)
|
||||
// @GameTest(templateName = FabricGameTest.EMPTY_STRUCTURE) TODO 1.21.5 tests
|
||||
public void testBlockUse(TestContext context) {
|
||||
List<Block> blocks = List.of(BlockEntityTypeBuilderTest.INITIAL_BETRAYAL_BLOCK, BlockEntityTypeBuilderTest.ADDED_BETRAYAL_BLOCK, BlockEntityTypeBuilderTest.FIRST_MULTI_BETRAYAL_BLOCK, BlockEntityTypeBuilderTest.SECOND_MULTI_BETRAYAL_BLOCK);
|
||||
BlockPos.Mutable pos = BlockPos.ORIGIN.up().mutableCopy();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue