diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/trade/TradeOfferHelper.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/trade/TradeOfferHelper.java
index ebbfe25258..35572fd9dd 100644
--- a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/trade/TradeOfferHelper.java
+++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/trade/TradeOfferHelper.java
@@ -18,10 +18,12 @@
import java.util.Collection;
import java.util.List;
+import java.util.Set;
import java.util.function.Consumer;
import org.jetbrains.annotations.ApiStatus;
+import net.minecraft.util.Identifier;
import net.minecraft.village.TradeOffers;
import net.minecraft.village.VillagerProfession;
@@ -130,94 +132,104 @@ public interface VillagerOffersAdder {
@ApiStatus.Experimental
public interface WanderingTraderOffersBuilder {
/**
- * The pool index for the "buy items" pool.
+ * The pool ID for the "buy items" pool.
* Two trade offers are picked from this pool.
*
*
In vanilla, this pool contains offers to buy water buckets, baked potatoes, etc.
* for emeralds.
*/
- int BUY_ITEMS_POOL = 0;
+ Identifier BUY_ITEMS_POOL = new Identifier("minecraft", "buy_items");
/**
- * The pool index for the "sell special items" pool.
+ * The pool ID for the "sell special items" pool.
* Two trade offers are picked from this pool.
*
*
In vanilla, this pool contains offers to sell logs, enchanted iron pickaxes, etc.
*/
- int SELL_SPECIAL_ITEMS_POOL = 1;
+ Identifier SELL_SPECIAL_ITEMS_POOL = new Identifier("minecraft", "sell_special_items");
/**
- * The pool index for the "sell common items" pool.
+ * The pool ID for the "sell common items" pool.
* Five trade offers are picked from this pool.
*
*
In vanilla, this pool contains offers to sell flowers, saplings, etc.
*/
- int SELL_COMMON_ITEMS_POOL = 2;
+ Identifier SELL_COMMON_ITEMS_POOL = new Identifier("minecraft", "sell_common_items");
/**
* Adds a new pool to the offer list. Exactly {@code count} offers are picked from
* {@code factories} and offered to customers.
+ * @param id the ID to be assigned to this pool, to allow further modification
* @param count the number of offers to be picked from {@code factories}
* @param factories the trade offer factories
* @return this builder, for chaining
* @throws IllegalArgumentException if {@code count} is not positive or if {@code factories} is empty
*/
- WanderingTraderOffersBuilder pool(int count, TradeOffers.Factory... factories);
+ WanderingTraderOffersBuilder pool(Identifier id, int count, TradeOffers.Factory... factories);
/**
* Adds a new pool to the offer list. Exactly {@code count} offers are picked from
* {@code factories} and offered to customers.
+ * @param id the ID to be assigned to this pool, to allow further modification
* @param count the number of offers to be picked from {@code factories}
* @param factories the trade offer factories
* @return this builder, for chaining
* @throws IllegalArgumentException if {@code count} is not positive or if {@code factories} is empty
*/
- default WanderingTraderOffersBuilder pool(int count, Collection extends TradeOffers.Factory> factories) {
- return pool(count, factories.toArray(TradeOffers.Factory[]::new));
+ default WanderingTraderOffersBuilder pool(Identifier id, int count, Collection extends TradeOffers.Factory> factories) {
+ return pool(id, count, factories.toArray(TradeOffers.Factory[]::new));
}
/**
* Adds trade offers to the offer list. All offers from {@code factories} are
* offered to each customer.
+ * @param id the ID to be assigned to this pool, to allow further modification
* @param factories the trade offer factories
* @return this builder, for chaining
* @throws IllegalArgumentException if {@code factories} is empty
*/
- default WanderingTraderOffersBuilder addAll(Collection extends TradeOffers.Factory> factories) {
- return pool(factories.size(), factories);
+ default WanderingTraderOffersBuilder addAll(Identifier id, Collection extends TradeOffers.Factory> factories) {
+ return pool(id, factories.size(), factories);
}
/**
* Adds trade offers to the offer list. All offers from {@code factories} are
* offered to each customer.
+ * @param id the ID to be assigned to this pool, to allow further modification
* @param factories the trade offer factories
* @return this builder, for chaining
* @throws IllegalArgumentException if {@code factories} is empty
*/
- default WanderingTraderOffersBuilder addAll(TradeOffers.Factory... factories) {
- return pool(factories.length, factories);
+ default WanderingTraderOffersBuilder addAll(Identifier id, TradeOffers.Factory... factories) {
+ return pool(id, factories.length, factories);
}
/**
- * Adds trade offers to an existing pool.
+ * Adds trade offers to an existing pool identified by an ID.
*
- *
See the constants for vanilla trade offer pool indices that are always available.
- * @param poolIndex the pool index
+ *
See the constants for vanilla trade offer pool IDs that are always available.
+ * @param pool the pool ID
* @param factories the trade offer factories
* @return this builder, for chaining
- * @throws IndexOutOfBoundsException if {@code poolIndex} is out of bounds
+ * @throws IndexOutOfBoundsException if {@code pool} is out of bounds
*/
- WanderingTraderOffersBuilder addOffersToPool(int poolIndex, TradeOffers.Factory... factories);
+ WanderingTraderOffersBuilder addOffersToPool(Identifier pool, TradeOffers.Factory... factories);
/**
- * Adds trade offers to an existing pool.
+ * Adds trade offers to an existing pool identified by an ID.
*
- *
See the constants for vanilla trade offer pool indices that are always available.
- * @param poolIndex the pool index
+ *
See the constants for vanilla trade offer pool IDs that are always available.
+ * @param pool the pool ID
* @param factories the trade offer factories
* @return this builder, for chaining
- * @throws IndexOutOfBoundsException if {@code poolIndex} is out of bounds
+ * @throws IndexOutOfBoundsException if {@code pool} is out of bounds
*/
- default WanderingTraderOffersBuilder addOffersToPool(int poolIndex, Collection factories) {
- return addOffersToPool(poolIndex, factories.toArray(TradeOffers.Factory[]::new));
+ default WanderingTraderOffersBuilder addOffersToPool(Identifier pool, Collection factories) {
+ return addOffersToPool(pool, factories.toArray(TradeOffers.Factory[]::new));
}
+
+ /**
+ * Returns all registered pool IDs, including vanilla ones.
+ * @return an unmodifiable set containing all registered pool IDs
+ */
+ Set getPoolIds();
}
}
diff --git a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/TradeOfferInternals.java b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/TradeOfferInternals.java
index e0801f426a..a167b8be23 100644
--- a/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/TradeOfferInternals.java
+++ b/fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/impl/object/builder/TradeOfferInternals.java
@@ -17,19 +17,25 @@
package net.fabricmc.fabric.impl.object.builder;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.function.Consumer;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
+import it.unimi.dsi.fastutil.objects.Object2IntMap;
+import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import net.minecraft.util.Identifier;
+import net.minecraft.util.Util;
import net.minecraft.village.TradeOffers;
import net.minecraft.village.VillagerProfession;
@@ -88,6 +94,12 @@ public static void printRefreshOffersWarning() {
}
public static class WanderingTraderOffersBuilderImpl implements TradeOfferHelper.WanderingTraderOffersBuilder {
+ static final Object2IntMap ID_TO_INDEX = Util.make(new Object2IntOpenHashMap<>(), idToIndex -> {
+ idToIndex.put(BUY_ITEMS_POOL, 0);
+ idToIndex.put(SELL_SPECIAL_ITEMS_POOL, 1);
+ idToIndex.put(SELL_COMMON_ITEMS_POOL, 2);
+ });
+
/**
* Make the trade list modifiable.
*/
@@ -98,24 +110,35 @@ static void initWanderingTraderTrades() {
}
@Override
- public TradeOfferHelper.WanderingTraderOffersBuilder pool(int count, TradeOffers.Factory... factories) {
+ public TradeOfferHelper.WanderingTraderOffersBuilder pool(Identifier id, int count, TradeOffers.Factory... factories) {
if (factories.length == 0) throw new IllegalArgumentException("cannot add empty pool");
if (count <= 0) throw new IllegalArgumentException("count must be positive");
+ Objects.requireNonNull(id, "id cannot be null");
Pair pool = Pair.of(factories, count);
initWanderingTraderTrades();
+ ID_TO_INDEX.put(id, TradeOffers.REBALANCED_WANDERING_TRADER_TRADES.size());
TradeOffers.REBALANCED_WANDERING_TRADER_TRADES.add(pool);
return this;
}
@Override
- public TradeOfferHelper.WanderingTraderOffersBuilder addOffersToPool(int poolIndex, TradeOffers.Factory... factories) {
- Objects.checkIndex(poolIndex, TradeOffers.REBALANCED_WANDERING_TRADER_TRADES.size());
+ public TradeOfferHelper.WanderingTraderOffersBuilder addOffersToPool(Identifier pool, TradeOffers.Factory... factories) {
+ if (!ID_TO_INDEX.containsKey(pool)) {
+ throw new IllegalArgumentException("pool %s is not registered".formatted(pool));
+ }
+
+ int poolIndex = ID_TO_INDEX.getInt(pool);
initWanderingTraderTrades();
- Pair pool = TradeOffers.REBALANCED_WANDERING_TRADER_TRADES.get(poolIndex);
- TradeOffers.Factory[] modified = ArrayUtils.addAll(pool.getLeft(), factories);
- TradeOffers.REBALANCED_WANDERING_TRADER_TRADES.set(poolIndex, Pair.of(modified, pool.getRight()));
+ Pair poolPair = TradeOffers.REBALANCED_WANDERING_TRADER_TRADES.get(poolIndex);
+ TradeOffers.Factory[] modified = ArrayUtils.addAll(poolPair.getLeft(), factories);
+ TradeOffers.REBALANCED_WANDERING_TRADER_TRADES.set(poolIndex, Pair.of(modified, poolPair.getRight()));
return this;
}
+
+ @Override
+ public Set getPoolIds() {
+ return Collections.unmodifiableSet(ID_TO_INDEX.keySet());
+ }
}
}
diff --git a/fabric-object-builder-api-v1/src/testmod/java/net/fabricmc/fabric/test/object/builder/VillagerTypeTest1.java b/fabric-object-builder-api-v1/src/testmod/java/net/fabricmc/fabric/test/object/builder/VillagerTypeTest1.java
index 06d68e3662..d66b3489a3 100644
--- a/fabric-object-builder-api-v1/src/testmod/java/net/fabricmc/fabric/test/object/builder/VillagerTypeTest1.java
+++ b/fabric-object-builder-api-v1/src/testmod/java/net/fabricmc/fabric/test/object/builder/VillagerTypeTest1.java
@@ -30,6 +30,7 @@
import net.minecraft.item.Items;
import net.minecraft.registry.Registries;
import net.minecraft.text.Text;
+import net.minecraft.util.Identifier;
import net.minecraft.util.math.random.Random;
import net.minecraft.village.TradeOffer;
import net.minecraft.village.TradeOffers;
@@ -40,6 +41,9 @@
import net.fabricmc.fabric.api.object.builder.v1.trade.TradeOfferHelper;
public class VillagerTypeTest1 implements ModInitializer {
+ private static final Identifier FOOD_POOL_ID = ObjectBuilderTestConstants.id("food");
+ private static final Identifier THING_POOL_ID = ObjectBuilderTestConstants.id("thing");
+
@Override
public void onInitialize() {
TradeOfferHelper.registerVillagerOffers(VillagerProfession.ARMORER, 1, (factories, rebalanced) -> {
@@ -58,12 +62,14 @@ public void onInitialize() {
TradeOfferHelper.registerRebalancedWanderingTraderOffers(builder -> {
builder.pool(
- 1,
+ FOOD_POOL_ID,
+ 5,
Registries.ITEM.stream().filter(item -> item.getFoodComponent() != null).map(
item -> new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.NETHERITE_INGOT), new ItemStack(item), 3, 4, 0.15F))
).toList()
);
builder.addAll(
+ THING_POOL_ID,
new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.NETHERITE_INGOT), new ItemStack(Items.MOJANG_BANNER_PATTERN), 1, 4, 0.15F))
);
builder.addOffersToPool(
@@ -78,6 +84,10 @@ public void onInitialize() {
new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.DIAMOND, 16), new ItemStack(Items.ELYTRA, 1), 1, 4, 0.15F)),
new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.EMERALD, 3), new ItemStack(Items.LEAD, 2), 3, 4, 0.15F))
);
+ builder.addOffersToPool(
+ FOOD_POOL_ID,
+ new SimpleTradeFactory(new TradeOffer(new ItemStack(Items.NETHERITE_INGOT), new ItemStack(Items.EGG), 3, 4, 0.15F))
+ );
});
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {