Skip to content

Commit

Permalink
Backport to 1.20.1
Browse files Browse the repository at this point in the history
  • Loading branch information
DrexHD committed Jan 18, 2024
1 parent 4a41062 commit 5db626b
Show file tree
Hide file tree
Showing 21 changed files with 509 additions and 415 deletions.
8 changes: 4 additions & 4 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx1G
# Fabric Properties
minecraft_version=1.20.2
minecraft_version=1.20.1
loader_version=0.15.5
# Mod Properties
mod_version=4.1.2
maven_group=me.drex
archives_base_name=villagerconfig
# Dependencies
fabric_version=0.90.7+1.20.2
mod_menu_version=8.0.0
cloth_config_version=12.0.109
fabric_version=0.87.0+1.20.1
mod_menu_version=7.1.0
cloth_config_version=11.0.99
fiber_version=0.23.0-2
config2brigadier_version=1.2.5
3 changes: 2 additions & 1 deletion src/main/java/me/drex/villagerconfig/VillagerConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import me.drex.villagerconfig.commands.VillagerConfigCommand;
import me.drex.villagerconfig.config.ConfigManager;
import me.drex.villagerconfig.json.TradeGsons;
import me.drex.villagerconfig.util.TradeManager;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
Expand All @@ -18,7 +19,7 @@ public class VillagerConfig implements ModInitializer {
public static final Logger LOGGER = LogManager.getLogger("VillagerConfig");
public static final Path DATA_PATH = FabricLoader.getInstance().getConfigDir().resolve("VillagerConfig");
public static final String MOD_ID = "villagerconfig";
public static final TradeManager TRADE_MANAGER = new TradeManager();
public static final TradeManager TRADE_MANAGER = new TradeManager(TradeGsons.GSON);

@Override
public void onInitialize() {
Expand Down
14 changes: 4 additions & 10 deletions src/main/java/me/drex/villagerconfig/commands/GenerateCommand.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package me.drex.villagerconfig.commands;

import com.mojang.brigadier.arguments.BoolArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import me.drex.villagerconfig.VillagerConfig;
import me.drex.villagerconfig.util.TradeProvider;
import net.minecraft.ChatFormatting;
Expand All @@ -20,20 +18,16 @@ public class GenerateCommand {

public static LiteralArgumentBuilder<CommandSourceStack> builder() {
return Commands.literal("generate")
.then(
Commands.argument("experimental", BoolArgumentType.bool())
.executes(ctx -> execute(ctx.getSource(), BoolArgumentType.getBool(ctx, "experimental")))
)
.executes(ctx -> execute(ctx.getSource(), false));
.executes(ctx -> execute(ctx.getSource()));
}

private static int execute(CommandSourceStack src, boolean experimental) {
private static int execute(CommandSourceStack src) {
DataGenerator dataGenerator = new DataGenerator(GENERATED, SharedConstants.getCurrentVersion(), true);
DataGenerator.PackGenerator tradesPack = dataGenerator.getVanillaPack(true);
tradesPack.addProvider(packOutput -> new TradeProvider(packOutput, experimental));
tradesPack.addProvider(TradeProvider::new);
try {
dataGenerator.run();
src.sendSuccess(() -> Component.literal("Successfully generated trade " + (experimental ? "(experimental) " : "") + "data to " + GENERATED).withStyle(ChatFormatting.GREEN), false);
src.sendSuccess(() -> Component.literal("Successfully generated trade data to " + GENERATED).withStyle(ChatFormatting.GREEN), false);
return 1;
} catch (Throwable e) {
src.sendFailure(Component.literal("An error occurred, please look into the console for more information."));
Expand Down
70 changes: 50 additions & 20 deletions src/main/java/me/drex/villagerconfig/data/BehaviorTrade.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package me.drex.villagerconfig.data;

import com.google.common.collect.Lists;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import me.drex.villagerconfig.mixin.MerchantOfferAccessor;
import me.drex.villagerconfig.util.loot.VCLootContextParams;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.GsonHelper;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.npc.VillagerTrades;
Expand All @@ -14,7 +15,6 @@
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.LootParams;
import net.minecraft.world.level.storage.loot.entries.EmptyLootItem;
import net.minecraft.world.level.storage.loot.entries.LootPoolEntries;
import net.minecraft.world.level.storage.loot.entries.LootPoolEntry;
import net.minecraft.world.level.storage.loot.entries.LootPoolEntryContainer;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
Expand All @@ -23,10 +23,10 @@
import net.minecraft.world.level.storage.loot.predicates.LootItemConditions;
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
import net.minecraft.world.level.storage.loot.providers.number.NumberProvider;
import net.minecraft.world.level.storage.loot.providers.number.NumberProviders;
import org.apache.commons.lang3.mutable.MutableInt;
import org.jetbrains.annotations.Nullable;

import java.lang.reflect.Type;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
Expand All @@ -35,18 +35,6 @@

public class BehaviorTrade implements VillagerTrades.ItemListing {

public static final Codec<BehaviorTrade> CODEC = RecordCodecBuilder.create(instance -> instance.group(
LootPoolEntries.CODEC.fieldOf("cost_a").forGetter(behaviorTrade -> behaviorTrade.costA),
LootPoolEntries.CODEC.optionalFieldOf("cost_b").forGetter(behaviorTrade -> behaviorTrade.costB),
LootPoolEntries.CODEC.fieldOf("result").forGetter(behaviorTrade -> behaviorTrade.result),
NumberProviders.CODEC.optionalFieldOf("price_multiplier", ConstantValue.exactly(0.2f)).forGetter(behaviorTrade -> behaviorTrade.priceMultiplier),
NumberProviders.CODEC.optionalFieldOf("trader_experience", ConstantValue.exactly(0)).forGetter(behaviorTrade -> behaviorTrade.traderExperience),
NumberProviders.CODEC.optionalFieldOf("max_uses", ConstantValue.exactly(12)).forGetter(behaviorTrade -> behaviorTrade.maxUses),
LootItemConditions.CODEC.listOf().optionalFieldOf("conditions", List.of()).forGetter(behaviorTrade -> behaviorTrade.conditions),
Codec.unboundedMap(Codec.STRING, NumberProviders.CODEC).optionalFieldOf("reference_providers", Map.of()).forGetter(behaviorTrade -> behaviorTrade.referenceProviders),
Codec.BOOL.optionalFieldOf("reward_experience", true).forGetter(behaviorTrade -> behaviorTrade.rewardExperience)
).apply(instance, BehaviorTrade::new));

private final LootPoolEntryContainer costA;
private final Optional<LootPoolEntryContainer> costB;
private final LootPoolEntryContainer result;
Expand All @@ -66,7 +54,7 @@ public class BehaviorTrade implements VillagerTrades.ItemListing {
this.traderExperience = traderExperience;
this.maxUses = maxUses;
this.conditions = conditions;
this.compositeCondition = LootItemConditions.andConditions(conditions);
this.compositeCondition = LootItemConditions.andConditions(conditions.toArray(new LootItemCondition[]{}));
this.referenceProviders = referenceProviders;
this.rewardExperience = rewardExperience;
}
Expand All @@ -80,7 +68,7 @@ public MerchantOffer getOffer(Entity entity, RandomSource random) {
.withParameter(LootContextParams.THIS_ENTITY, entity)
.withParameter(VCLootContextParams.NUMBER_REFERENCE, generateNumberReferences(entity, random))
.create(VCLootContextParams.VILLAGER_LOOT_CONTEXT);
LootContext lootContext = new LootContext.Builder(lootParams).create(Optional.empty());
LootContext lootContext = new LootContext.Builder(lootParams).create(null);

AtomicReference<ItemStack> costA = new AtomicReference<>(ItemStack.EMPTY);
AtomicReference<ItemStack> costB = new AtomicReference<>(ItemStack.EMPTY);
Expand Down Expand Up @@ -133,7 +121,7 @@ private void addRandomItem(Consumer<ItemStack> consumer, LootContext lootContext
private Map<String, Float> generateNumberReferences(Entity entity, RandomSource random) {
LootParams lootParams = new LootParams.Builder((ServerLevel) entity.level())
.create(LootContextParamSets.EMPTY);
LootContext simpleContext = new LootContext.Builder(lootParams).create(Optional.empty());
LootContext simpleContext = new LootContext.Builder(lootParams).create(null);
return referenceProviders.entrySet().stream().collect(
Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().getFloat(simpleContext))
);
Expand Down Expand Up @@ -205,9 +193,51 @@ public Builder rewardExperience(boolean rewardExp) {
}

public BehaviorTrade build() {
return new BehaviorTrade(costA, costB, result, priceMultiplier, traderExperience, maxUses, this.conditions, referenceProviders, rewardExperience);
return new BehaviorTrade(costA, costB, result, priceMultiplier, traderExperience, maxUses, conditions, referenceProviders, rewardExperience);
}

}

public static class Serializer implements JsonSerializer<BehaviorTrade>, JsonDeserializer<BehaviorTrade> {

private static final Type REFERENCE_PROVIDERS_TYPE = TypeToken.getParameterized(Map.class, String.class, NumberProvider.class).getType();

@Override
public BehaviorTrade deserialize(JsonElement jsonElement, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = GsonHelper.convertToJsonObject(jsonElement, "behaviour trade");
LootPoolEntryContainer costA = GsonHelper.getAsObject(jsonObject, "cost_a", context, LootPoolEntryContainer.class);
Optional<LootPoolEntryContainer> costB = Optional.ofNullable(GsonHelper.getAsObject(jsonObject, "cost_b", null, context, LootPoolEntryContainer.class));
LootPoolEntryContainer result = GsonHelper.getAsObject(jsonObject, "result", context, LootPoolEntryContainer.class);
NumberProvider priceMultiplier = GsonHelper.getAsObject(jsonObject, "price_multiplier", ConstantValue.exactly(0.2f), context, NumberProvider.class);
NumberProvider traderExperience = GsonHelper.getAsObject(jsonObject, "trader_experience", ConstantValue.exactly(0), context, NumberProvider.class);
NumberProvider maxUses = GsonHelper.getAsObject(jsonObject, "max_uses", ConstantValue.exactly(12), context, NumberProvider.class);
LootItemCondition[] conditions = GsonHelper.getAsObject(jsonObject, "conditions", new LootItemCondition[]{}, context, LootItemCondition[].class);
Map<String, NumberProvider> referenceProviders = Collections.emptyMap();
if (jsonObject.has("reference_providers")) {
referenceProviders = context.deserialize(jsonObject.get("reference_providers"), REFERENCE_PROVIDERS_TYPE);
}
boolean rewardExperience = GsonHelper.getAsBoolean(jsonObject, "reward_experience", true);
return new BehaviorTrade(costA, costB, result, priceMultiplier, traderExperience, maxUses, List.of(conditions), referenceProviders, rewardExperience);
}

@Override
public JsonElement serialize(BehaviorTrade behaviorTrade, Type typeOfSrc, JsonSerializationContext context) {
JsonObject jsonObject = new JsonObject();
jsonObject.add("cost_a", context.serialize(behaviorTrade.costA));
behaviorTrade.costB.ifPresent(lootPoolEntryContainer -> jsonObject.add("cost_b", context.serialize(lootPoolEntryContainer)));
jsonObject.add("result", context.serialize(behaviorTrade.result));
jsonObject.add("price_multiplier", context.serialize(behaviorTrade.priceMultiplier));
jsonObject.add("trader_experience", context.serialize(behaviorTrade.traderExperience));
jsonObject.add("max_uses", context.serialize(behaviorTrade.maxUses));
if (!behaviorTrade.conditions.isEmpty()) {
jsonObject.add("conditions", context.serialize(behaviorTrade.conditions));
}
if (!behaviorTrade.referenceProviders.isEmpty()) {
jsonObject.add("reference_providers", context.serialize(behaviorTrade.referenceProviders, REFERENCE_PROVIDERS_TYPE));
}
jsonObject.addProperty("reward_experience", behaviorTrade.rewardExperience);
return jsonObject;
}
}

}
33 changes: 23 additions & 10 deletions src/main/java/me/drex/villagerconfig/data/TradeGroup.java
Original file line number Diff line number Diff line change
@@ -1,28 +1,22 @@
package me.drex.villagerconfig.data;

import com.google.common.collect.Sets;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import com.google.gson.*;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.entity.npc.AbstractVillager;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.LootParams;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.level.storage.loot.providers.number.NumberProvider;
import net.minecraft.world.level.storage.loot.providers.number.NumberProviders;

import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;

public class TradeGroup {

public static final Codec<TradeGroup> CODEC = RecordCodecBuilder.create(instance -> instance.group(
NumberProviders.CODEC.fieldOf("num_to_select").forGetter(tradeGroup -> tradeGroup.numToSelect),
BehaviorTrade.CODEC.listOf().fieldOf("trades").forGetter(tradeGroup -> tradeGroup.trades)
).apply(instance, TradeGroup::new));

final NumberProvider numToSelect;
final List<BehaviorTrade> trades;

Expand All @@ -35,7 +29,7 @@ public List<BehaviorTrade> getTrades(AbstractVillager villager) {
LootParams lootParams = new LootParams.Builder((ServerLevel) villager.level())
.withOptionalParameter(LootContextParams.THIS_ENTITY, villager)
.create(LootContextParamSets.PIGLIN_BARTER);
LootContext lootContext = new LootContext.Builder(lootParams).create(Optional.empty());
LootContext lootContext = new LootContext.Builder(lootParams).create(null);

List<BehaviorTrade> applicableTrades = trades.stream().filter(behaviorTrade -> behaviorTrade.compositeCondition.test(lootContext)).toList();

Expand All @@ -57,4 +51,23 @@ public List<BehaviorTrade> getTrades(AbstractVillager villager) {
return List.of(factories);
}

public static class Serializer implements JsonSerializer<TradeGroup>, JsonDeserializer<TradeGroup> {

@Override
public TradeGroup deserialize(JsonElement jsonElement, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = GsonHelper.convertToJsonObject(jsonElement, "trade group");
BehaviorTrade[] trades = GsonHelper.getAsObject(jsonObject, "trades", context, BehaviorTrade[].class);
NumberProvider numToSelect = GsonHelper.getAsObject(jsonObject, "num_to_select", context, NumberProvider.class);
return new TradeGroup(numToSelect, List.of(trades));
}

@Override
public JsonElement serialize(TradeGroup tradeGroup, Type typeOfSrc, JsonSerializationContext context) {
JsonObject jsonObject = new JsonObject();
jsonObject.add("trades", context.serialize(tradeGroup.trades));
jsonObject.add("num_to_select", context.serialize(tradeGroup.numToSelect));
return jsonObject;
}
}

}
26 changes: 20 additions & 6 deletions src/main/java/me/drex/villagerconfig/data/TradeTable.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
package me.drex.villagerconfig.data;

import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import com.google.gson.*;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.entity.npc.AbstractVillager;
import net.minecraft.world.entity.npc.VillagerTrades;

import java.lang.reflect.Type;
import java.util.List;

public class TradeTable {

public static final Codec<TradeTable> CODEC = RecordCodecBuilder.create(instance -> instance.group(
TradeTier.CODEC.listOf().fieldOf("tiers").forGetter(tradeTable -> tradeTable.tiers)
).apply(instance, TradeTable::new));

final List<TradeTier> tiers;

public TradeTable(List<TradeTier> tiers) {
Expand Down Expand Up @@ -40,4 +37,21 @@ public int maxLevel() {
return tiers.size();
}

public static class Serializer implements JsonSerializer<TradeTable>, JsonDeserializer<TradeTable> {

@Override
public TradeTable deserialize(JsonElement jsonElement, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = GsonHelper.convertToJsonObject(jsonElement, "trade table");
TradeTier[] tiers = GsonHelper.getAsObject(jsonObject, "tiers", context, TradeTier[].class);
return new TradeTable(List.of(tiers));
}

@Override
public JsonElement serialize(TradeTable tradeTable, Type typeOfSrc, JsonSerializationContext context) {
JsonObject jsonObject = new JsonObject();
jsonObject.add("tiers", context.serialize(tradeTable.tiers));
return jsonObject;
}
}

}
29 changes: 22 additions & 7 deletions src/main/java/me/drex/villagerconfig/data/TradeTier.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
package me.drex.villagerconfig.data;

import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import com.google.gson.*;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.entity.npc.AbstractVillager;
import net.minecraft.world.entity.npc.VillagerTrades;

import java.lang.reflect.Type;
import java.util.LinkedList;
import java.util.List;

public class TradeTier {

public static final Codec<TradeTier> CODEC = RecordCodecBuilder.create(instance -> instance.group(
Codec.INT.fieldOf("total_exp_required").forGetter(tradeTier -> tradeTier.totalExpRequired),
TradeGroup.CODEC.listOf().fieldOf("groups").forGetter(tradeTier -> tradeTier.groups)
).apply(instance, TradeTier::new));

final int totalExpRequired;
final List<TradeGroup> groups;

Expand All @@ -39,4 +35,23 @@ protected int requiredExperience() {
return this.totalExpRequired;
}

public static class Serializer implements JsonSerializer<TradeTier>, JsonDeserializer<TradeTier> {

@Override
public TradeTier deserialize(JsonElement jsonElement, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = GsonHelper.convertToJsonObject(jsonElement, "trade tier");
TradeGroup[] groups = GsonHelper.getAsObject(jsonObject, "groups", context, TradeGroup[].class);
int totalExpRequired = GsonHelper.getAsInt(jsonObject, "total_exp_required");
return new TradeTier(totalExpRequired, List.of(groups));
}

@Override
public JsonElement serialize(TradeTier tradeTier, Type typeOfSrc, JsonSerializationContext context) {
JsonObject jsonObject = new JsonObject();
jsonObject.add("groups", context.serialize(tradeTier.groups));
jsonObject.addProperty("total_exp_required", tradeTier.totalExpRequired);
return jsonObject;
}
}

}
21 changes: 21 additions & 0 deletions src/main/java/me/drex/villagerconfig/json/TradeGsons.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package me.drex.villagerconfig.json;

import com.google.gson.Gson;
import me.drex.villagerconfig.data.BehaviorTrade;
import me.drex.villagerconfig.data.TradeGroup;
import me.drex.villagerconfig.data.TradeTable;
import me.drex.villagerconfig.data.TradeTier;
import net.minecraft.world.entity.npc.VillagerTrades;
import net.minecraft.world.level.storage.loot.Deserializers;

public class TradeGsons {

public static final Gson GSON = Deserializers.createLootTableSerializer()
.setPrettyPrinting()
.registerTypeAdapter(TradeTable.class, new TradeTable.Serializer())
.registerTypeAdapter(TradeTier.class, new TradeTier.Serializer())
.registerTypeAdapter(TradeGroup.class, new TradeGroup.Serializer())
.registerTypeHierarchyAdapter(VillagerTrades.ItemListing.class, new BehaviorTrade.Serializer())
.create();

}
Loading

0 comments on commit 5db626b

Please sign in to comment.