Refactor CharismaTradeEvents: Add GossipType import and resolve merchant using reflection

This commit is contained in:
2026-01-13 20:24:52 +01:00
parent 4e145f0557
commit 1b60e8b6b8
2 changed files with 22 additions and 20 deletions
@@ -10,6 +10,7 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.effect.MobEffectCategory;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.ai.gossip.GossipType;
import net.minecraft.world.entity.npc.Villager;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.LightLayer;
@@ -28,7 +29,6 @@ import net.minecraftforge.event.entity.living.LivingDamageEvent;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.animal.IronGolem;
import net.minecraft.world.entity.animal.SnowGolem;
import net.minecraft.world.entity.npc.GossipType;
import net.minecraftforge.event.entity.living.LivingEvent;
import net.minecraft.world.phys.AABB;
@@ -3,16 +3,19 @@ package net.fretux.ascend.event;
import net.fretux.ascend.AscendMod;
import net.fretux.ascend.player.PlayerStatsProvider;
import net.fretux.ascend.player.StatEffects;
import net.minecraft.world.entity.ai.gossip.GossipType;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.MerchantMenu;
import net.minecraft.world.item.trading.Merchant;
import net.minecraft.world.item.trading.MerchantOffer;
import net.minecraft.world.entity.npc.Villager;
import net.minecraft.world.entity.npc.GossipType;
import net.minecraftforge.event.entity.player.PlayerContainerEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import java.lang.reflect.Field;
@Mod.EventBusSubscriber(modid = AscendMod.MODID)
public class CharismaTradeEvents {
@@ -20,45 +23,29 @@ public class CharismaTradeEvents {
public static void onOpenMerchant(PlayerContainerEvent.Open event) {
Player player = event.getEntity();
if (player.level().isClientSide) return;
AbstractContainerMenu menu = event.getContainer();
if (!(menu instanceof MerchantMenu merchantMenu)) return;
player.getCapability(PlayerStatsProvider.PLAYER_STATS).ifPresent(stats -> {
int cha = stats.getAttributeLevel("charisma");
if (cha <= 0) return;
if (merchantMenu.getTrader() instanceof Villager villager) {
Merchant merchant = resolveMerchant(merchantMenu);
if (merchant instanceof Villager villager) {
int reputationBonus = StatEffects.getCharismaVillagerReputationBonus(cha);
if (reputationBonus > 0) {
villager.getGossips().add(player.getUUID(), GossipType.MINOR_POSITIVE, reputationBonus);
}
}
double discountFraction = StatEffects.getCharismaTradeDiscount(cha);
if (discountFraction <= 0.0d) return;
var offers = merchantMenu.getOffers();
if (offers == null) return;
for (MerchantOffer offer : offers) {
if (offer == null) continue;
// Base cost of first input (emeralds, etc.)
int base = offer.getBaseCostA().getCount();
if (base <= 0) continue;
// Desired discounted cost
int target = (int) Math.max(1, Math.floor(base * (1.0d - discountFraction)));
// Current special price diff already includes:
// popularity, hero-of-village, etc.
int currentSpecial = offer.getSpecialPriceDiff();
// We want: base + newSpecial = target
int newSpecial = target - base;
// Adjust relative to current to avoid stacking each open.
int delta = newSpecial - currentSpecial;
if (delta != 0) {
offer.addToSpecialPriceDiff(delta);
@@ -66,4 +53,19 @@ public class CharismaTradeEvents {
}
});
}
private static Merchant resolveMerchant(MerchantMenu merchantMenu) {
for (Field field : MerchantMenu.class.getDeclaredFields()) {
if (!Merchant.class.isAssignableFrom(field.getType())) {
continue;
}
field.setAccessible(true);
try {
return (Merchant) field.get(merchantMenu);
} catch (IllegalAccessException ignored) {
return null;
}
}
return null;
}
}