diff --git a/src/main/java/net/minecraftforge/common/BasicTrade.java b/src/main/java/net/minecraftforge/common/BasicTrade.java new file mode 100644 index 0000000000..4a9c7f6842 --- /dev/null +++ b/src/main/java/net/minecraftforge/common/BasicTrade.java @@ -0,0 +1,78 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2019. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.common; + +import java.util.Random; + +import javax.annotation.Nullable; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.merchant.villager.VillagerTrades.ITrade; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.item.MerchantOffer; + +/** + * A default, exposed implementation of ITrade. All of the other implementations of ITrade (in VillagerTrades) are not public. + * This class contains everything needed to make a MerchantOffer, the actual "trade" object shown in trading guis. + */ +public class BasicTrade implements ITrade +{ + + protected final ItemStack price; + protected final ItemStack price2; + protected final ItemStack forSale; + protected final int maxTrades; + protected final int xp; + protected final float priceMult; + + public BasicTrade(ItemStack price, ItemStack price2, ItemStack forSale, int maxTrades, int xp, float priceMult) + { + this.price = price; + this.price2 = price2; + this.forSale = forSale; + this.maxTrades = maxTrades; + this.xp = xp; + this.priceMult = priceMult; + } + + public BasicTrade(ItemStack price, ItemStack forSale, int maxTrades, int xp, float priceMult) + { + this(price, ItemStack.EMPTY, forSale, maxTrades, xp, priceMult); + } + + public BasicTrade(int emeralds, ItemStack forSale, int maxTrades, int xp, float mult) + { + this(new ItemStack(Items.EMERALD, emeralds), forSale, maxTrades, xp, mult); + } + + public BasicTrade(int emeralds, ItemStack forSale, int maxTrades, int xp) + { + this(new ItemStack(Items.EMERALD, emeralds), forSale, maxTrades, xp, 1); + } + + @Override + @Nullable + public MerchantOffer getOffer(Entity merchant, Random rand) + { + return new MerchantOffer(price, price2, forSale, maxTrades, xp, priceMult); + } + +} \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/common/ForgeMod.java b/src/main/java/net/minecraftforge/common/ForgeMod.java index b82c11ce5e..d9e319d32f 100644 --- a/src/main/java/net/minecraftforge/common/ForgeMod.java +++ b/src/main/java/net/minecraftforge/common/ForgeMod.java @@ -124,6 +124,7 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook CapabilityFluidHandler.register(); CapabilityAnimation.register(); CapabilityEnergy.register(); + MinecraftForge.EVENT_BUS.addListener(VillagerTradingManager::loadTrades); MinecraftForge.EVENT_BUS.register(MinecraftForge.INTERNAL_HANDLER); MinecraftForge.EVENT_BUS.register(this); diff --git a/src/main/java/net/minecraftforge/common/VillagerTradingManager.java b/src/main/java/net/minecraftforge/common/VillagerTradingManager.java new file mode 100644 index 0000000000..5a8a7faed1 --- /dev/null +++ b/src/main/java/net/minecraftforge/common/VillagerTradingManager.java @@ -0,0 +1,102 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2019. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.common; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.common.collect.Lists; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import net.minecraft.entity.merchant.villager.VillagerProfession; +import net.minecraft.entity.merchant.villager.VillagerTrades; +import net.minecraft.entity.merchant.villager.VillagerTrades.ITrade; +import net.minecraft.util.NonNullList; +import net.minecraftforge.event.village.VillagerTradesEvent; +import net.minecraftforge.event.village.WandererTradesEvent; +import net.minecraftforge.fml.event.server.FMLServerAboutToStartEvent; +import net.minecraftforge.registries.ForgeRegistries; + +public class VillagerTradingManager +{ + + private static final Map> VANILLA_TRADES = new HashMap<>(); + private static final Int2ObjectMap WANDERER_TRADES = new Int2ObjectOpenHashMap<>(); + + static + { + VillagerTrades.field_221239_a.entrySet().forEach(e -> + { + Int2ObjectMap copy = new Int2ObjectOpenHashMap<>(); + e.getValue().int2ObjectEntrySet().forEach(ent -> copy.put(ent.getIntKey(), Arrays.copyOf(ent.getValue(), ent.getValue().length))); + VANILLA_TRADES.put(e.getKey(), copy); + }); + VillagerTrades.field_221240_b.int2ObjectEntrySet().forEach(e -> WANDERER_TRADES.put(e.getIntKey(), Arrays.copyOf(e.getValue(), e.getValue().length))); + } + + static void loadTrades(FMLServerAboutToStartEvent e) + { + postWandererEvent(); + postVillagerEvents(); + } + + /** + * Posts the WandererTradesEvent. + */ + private static void postWandererEvent() + { + List generic = NonNullList.create(); + List rare = NonNullList.create(); + Arrays.stream(WANDERER_TRADES.get(1)).forEach(generic::add); + Arrays.stream(WANDERER_TRADES.get(2)).forEach(rare::add); + MinecraftForge.EVENT_BUS.post(new WandererTradesEvent(generic, rare)); + VillagerTrades.field_221240_b.put(1, generic.toArray(new ITrade[0])); + VillagerTrades.field_221240_b.put(2, rare.toArray(new ITrade[0])); + } + + /** + * Posts a VillagerTradesEvent for each registered profession. + */ + private static void postVillagerEvents() + { + for (VillagerProfession prof : ForgeRegistries.PROFESSIONS) + { + Int2ObjectMap trades = VANILLA_TRADES.getOrDefault(prof, new Int2ObjectOpenHashMap<>()); + Int2ObjectMap> mutableTrades = new Int2ObjectOpenHashMap<>(); + for (int i = 1; i < 6; i++) + { + mutableTrades.put(i, NonNullList.create()); + } + trades.int2ObjectEntrySet().forEach(e -> + { + Arrays.stream(e.getValue()).forEach(mutableTrades.get(e.getIntKey())::add); + }); + MinecraftForge.EVENT_BUS.post(new VillagerTradesEvent(mutableTrades, prof)); + Int2ObjectMap newTrades = new Int2ObjectOpenHashMap<>(); + mutableTrades.int2ObjectEntrySet().forEach(e -> newTrades.put(e.getIntKey(), e.getValue().toArray(new ITrade[0]))); + VillagerTrades.field_221239_a.put(prof, newTrades); + } + } + +} diff --git a/src/main/java/net/minecraftforge/event/village/VillagerTradesEvent.java b/src/main/java/net/minecraftforge/event/village/VillagerTradesEvent.java new file mode 100644 index 0000000000..1ee6e6af1f --- /dev/null +++ b/src/main/java/net/minecraftforge/event/village/VillagerTradesEvent.java @@ -0,0 +1,65 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2019. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.event.village; + +import java.util.List; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import net.minecraft.entity.merchant.villager.VillagerData; +import net.minecraft.entity.merchant.villager.VillagerProfession; +import net.minecraft.entity.merchant.villager.VillagerTrades.ITrade; +import net.minecraftforge.common.BasicTrade; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.fml.event.server.FMLServerAboutToStartEvent; + +/** + * VillagerTradesEvent is fired during the {@link FMLServerAboutToStartEvent}. It is used to gather the trade lists for each profession. + * It is fired on the {@link MinecraftForge#EVENT_BUS}. + * It is fired once for each registered villager profession. + * Villagers pick two trades from their trade map, based on their level. + * Villager level is increased by successful trades. + * The map is populated for levels 1-5 (inclusive), so Map#get will never return null for those keys. + * Levels outside of this range do nothing, as specified by {@link VillagerData#func_221128_d(int)} which is called before attempting to level up. + * To add trades to the merchant, simply add new trades to the list. {@link BasicTrade} provides a default implementation. + */ +public class VillagerTradesEvent extends Event +{ + + protected Int2ObjectMap> trades; + protected VillagerProfession type; + + public VillagerTradesEvent(Int2ObjectMap> trades, VillagerProfession type) + { + this.trades = trades; + this.type = type; + } + + public Int2ObjectMap> getTrades() + { + return trades; + } + + public VillagerProfession getType() + { + return type; + } + +} \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/event/village/WandererTradesEvent.java b/src/main/java/net/minecraftforge/event/village/WandererTradesEvent.java new file mode 100644 index 0000000000..3508cd163e --- /dev/null +++ b/src/main/java/net/minecraftforge/event/village/WandererTradesEvent.java @@ -0,0 +1,57 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2019. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.event.village; + +import java.util.List; + +import net.minecraft.entity.merchant.villager.VillagerTrades.ITrade; +import net.minecraftforge.common.BasicTrade; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.fml.event.server.FMLServerAboutToStartEvent; + +/** + * WandererTradesEvent is fired during the {@link FMLServerAboutToStartEvent}. It is used to gather the trade lists for the wandering merchant. + * It is fired on the {@link MinecraftForge#EVENT_BUS}. + * The wandering merchant picks a few trades from {@link TradeType#GENERIC} and a single trade from {@link TradeType#RARE}. + * To add trades to the merchant, simply add new trades to the list. {@link BasicTrade} provides a default implementation. +*/ +public class WandererTradesEvent extends Event +{ + + protected List generic; + protected List rare; + + public WandererTradesEvent(List generic, List rare) + { + this.generic = generic; + this.rare = rare; + } + + public List getGenericTrades() + { + return generic; + } + + public List getRareTrades() + { + return rare; + } +} \ No newline at end of file