From af6e84822746f6eff5b20b045e08ffa2f4ab0d82 Mon Sep 17 00:00:00 2001 From: LexManos Date: Wed, 20 Sep 2023 15:24:46 -0700 Subject: [PATCH] Global Loot Modifiers --- build.gradle | 3 +- .../advancements/Advancement.java.patch | 13 ++ .../resources/DelegatingOps.java.patch | 36 ++++ .../resources/RegistryDataLoader.java.patch | 24 ++- .../resources/RegistryOps.java.patch | 37 +++- .../ServerGamePacketListenerImpl.java.patch | 2 +- .../world/entity/LivingEntity.java.patch | 4 +- .../PersistentEntitySectionManager.java.patch | 2 +- .../TransientEntitySectionManager.java.patch | 2 +- .../level/storage/loot/LootContext.java.patch | 4 +- .../storage/loot/LootDataType.java.patch | 14 ++ .../level/storage/loot/LootPool.java.patch | 95 ++++++++++ .../level/storage/loot/LootTable.java.patch | 41 ++++- .../loot_modifiers/global_loot_modifiers.json | 9 + .../loot_modifiers/bamboo_silk.json | 13 ++ .../loot_modifiers/dungeon_loot.json | 9 + .../loot_modifiers/smelting.json | 18 ++ .../loot_modifiers/wheat_harvest.json | 20 +++ src/generated_test/resources/pack.mcmeta | 8 + .../net/minecraftforge/common/ForgeHooks.java | 133 +++----------- .../common/ForgeInternalHandler.java | 5 +- .../net/minecraftforge/common/ForgeMod.java | 46 +++-- .../net/minecraftforge/common/ToolAction.java | 22 +-- .../common/crafting/AbstractIngredient.java | 94 ---------- .../common/crafting/CompoundIngredient.java | 88 ++------- .../common/crafting/CraftingHelper.java | 38 +--- .../crafting/IIngredientSerializer.java | 22 --- .../common/crafting/MultiItemValue.java | 57 ------ .../common/crafting/StrictNBTIngredient.java | 72 ++------ .../crafting/VanillaIngredientSerializer.java | 39 ---- .../crafting/conditions/AndCondition.java | 82 ++------- .../crafting/conditions/ConditionCodec.java | 66 +++++++ .../crafting/conditions/ConditionContext.java | 44 ++--- .../crafting/conditions/FalseCondition.java | 43 +---- .../crafting/conditions/ICondition.java | 47 +++-- .../conditions/IConditionBuilder.java | 38 ++-- .../conditions/IConditionSerializer.java | 27 --- .../conditions/ItemExistsCondition.java | 63 ++----- .../conditions/ModLoadedCondition.java | 55 ++---- .../crafting/conditions/NotCondition.java | 55 ++---- .../crafting/conditions/OrCondition.java | 81 ++------- .../conditions/TagEmptyCondition.java | 63 ++----- .../crafting/conditions/TrueCondition.java | 42 +---- .../data/GlobalLootModifierProvider.java | 11 +- .../common/loot/CanToolPerformAction.java | 54 ++---- .../common/loot/IGlobalLootModifier.java | 48 ++--- .../common/loot/LootModifier.java | 26 ++- .../common/loot/LootModifierManager.java | 88 +++++---- .../common/loot/LootTableIdCondition.java | 76 +++----- .../common/util/FakePlayer.java | 4 +- .../common/util/FakePlayerFactory.java | 15 +- .../event/ForgeEventFactory.java | 21 ++- .../ForgeDeferredRegistriesSetup.java | 3 +- .../registries/ForgeRegistries.java | 18 +- .../minecraftforge/registries/GameData.java | 22 ++- .../debug/CreativeModeTabTest.java | 102 +++++------ .../loot/GlobalLootModifiersTest.java | 169 ++++++++++-------- .../java/net/minecraftforge/test/Empty.java | 57 +++++- src/test/resources/META-INF/mods.toml | 16 +- .../debug/DataGeneratorTest.java | 73 +++----- .../debug/fluid/NewFluidTest.java | 60 +++---- .../debug/gameplay/loot/package-info.java | 11 -- src/test_old/resources/META-INF/mods.toml | 10 -- 63 files changed, 1058 insertions(+), 1502 deletions(-) create mode 100644 patches/minecraft/net/minecraft/resources/DelegatingOps.java.patch create mode 100644 patches/minecraft/net/minecraft/world/level/storage/loot/LootDataType.java.patch create mode 100644 patches/minecraft/net/minecraft/world/level/storage/loot/LootPool.java.patch create mode 100644 src/generated_test/resources/data/forge/loot_modifiers/global_loot_modifiers.json create mode 100644 src/generated_test/resources/data/global_loot_test/loot_modifiers/bamboo_silk.json create mode 100644 src/generated_test/resources/data/global_loot_test/loot_modifiers/dungeon_loot.json create mode 100644 src/generated_test/resources/data/global_loot_test/loot_modifiers/smelting.json create mode 100644 src/generated_test/resources/data/global_loot_test/loot_modifiers/wheat_harvest.json create mode 100644 src/generated_test/resources/pack.mcmeta delete mode 100644 src/main/java/net/minecraftforge/common/crafting/AbstractIngredient.java delete mode 100644 src/main/java/net/minecraftforge/common/crafting/IIngredientSerializer.java delete mode 100644 src/main/java/net/minecraftforge/common/crafting/MultiItemValue.java delete mode 100644 src/main/java/net/minecraftforge/common/crafting/VanillaIngredientSerializer.java create mode 100644 src/main/java/net/minecraftforge/common/crafting/conditions/ConditionCodec.java delete mode 100644 src/main/java/net/minecraftforge/common/crafting/conditions/IConditionSerializer.java rename src/{test_old => test}/java/net/minecraftforge/debug/CreativeModeTabTest.java (67%) rename src/{test_old => test}/java/net/minecraftforge/debug/gameplay/loot/GlobalLootModifiersTest.java (63%) delete mode 100644 src/test_old/java/net/minecraftforge/debug/gameplay/loot/package-info.java diff --git a/build.gradle b/build.gradle index 091273d996..7a7ab560e9 100644 --- a/build.gradle +++ b/build.gradle @@ -769,9 +769,10 @@ project(':forge') { } args '--flat', '--all', '--validate', + '--mod', 'empty', //'--mod', 'data_gen_test', //'--mod', 'piston_event_test', - //'--mod', 'global_loot_test', + '--mod', 'global_loot_test', //'--mod', 'scaffolding_test', //'--mod', 'custom_tag_types_test', //'--mod', 'new_model_loader_test', diff --git a/patches/minecraft/net/minecraft/advancements/Advancement.java.patch b/patches/minecraft/net/minecraft/advancements/Advancement.java.patch index 9288588edd..7a25438646 100644 --- a/patches/minecraft/net/minecraft/advancements/Advancement.java.patch +++ b/patches/minecraft/net/minecraft/advancements/Advancement.java.patch @@ -15,3 +15,16 @@ Optional optional = p_300691_.has("parent") ? Optional.of(new ResourceLocation(GsonHelper.getAsString(p_300691_, "parent"))) : Optional.empty(); Optional optional1 = p_300691_.has("display") ? Optional.of(DisplayInfo.fromJson(GsonHelper.getAsJsonObject(p_300691_, "display"))) : Optional.empty(); AdvancementRewards advancementrewards = p_300691_.has("rewards") ? AdvancementRewards.deserialize(GsonHelper.getAsJsonObject(p_300691_, "rewards")) : AdvancementRewards.EMPTY; +@@ -182,7 +_,11 @@ + } + + public AdvancementHolder save(Consumer p_138390_, String p_138391_) { +- AdvancementHolder advancementholder = this.build(new ResourceLocation(p_138391_)); ++ return save(p_138390_, new ResourceLocation(p_138391_)); ++ } ++ ++ public AdvancementHolder save(Consumer p_138390_, ResourceLocation id) { ++ AdvancementHolder advancementholder = this.build(id); + p_138390_.accept(advancementholder); + return advancementholder; + } diff --git a/patches/minecraft/net/minecraft/resources/DelegatingOps.java.patch b/patches/minecraft/net/minecraft/resources/DelegatingOps.java.patch new file mode 100644 index 0000000000..8818b2dae0 --- /dev/null +++ b/patches/minecraft/net/minecraft/resources/DelegatingOps.java.patch @@ -0,0 +1,36 @@ +--- a/net/minecraft/resources/DelegatingOps.java ++++ b/net/minecraft/resources/DelegatingOps.java +@@ -160,4 +_,33 @@ + public RecordBuilder mapBuilder() { + return new RecordBuilder.MapBuilder<>(this); + } ++ ++ java.util.Map ctx; ++ public R getContext(ResourceLocation rl) { ++ return (R)this.ctx.get(rl); ++ } ++ ++ public static > Builder builder(java.util.function.Supplier root) { ++ return new Builder(root); ++ } ++ ++ public static class Builder> { ++ private final java.util.function.Supplier func; ++ private final java.util.Map ctx = new java.util.HashMap<>(); ++ ++ private Builder(java.util.function.Supplier func) { ++ this.func = func; ++ } ++ ++ public Builder with(ResourceLocation key, Object ctx) { ++ this.ctx.put(key, ctx); ++ return this; ++ } ++ ++ public R build() { ++ var ret = this.func.get(); ++ ret.ctx = this.ctx; ++ return ret; ++ } ++ } + } diff --git a/patches/minecraft/net/minecraft/resources/RegistryDataLoader.java.patch b/patches/minecraft/net/minecraft/resources/RegistryDataLoader.java.patch index e4406c5e63..b99e5c0aee 100644 --- a/patches/minecraft/net/minecraft/resources/RegistryDataLoader.java.patch +++ b/patches/minecraft/net/minecraft/resources/RegistryDataLoader.java.patch @@ -1,6 +1,6 @@ --- a/net/minecraft/resources/RegistryDataLoader.java +++ b/net/minecraft/resources/RegistryDataLoader.java -@@ -123,7 +_,7 @@ +@@ -123,13 +_,16 @@ } private static String registryDirPath(ResourceLocation p_252033_) { @@ -9,11 +9,27 @@ } static void loadRegistryContents(RegistryOps.RegistryInfoLookup p_256369_, ResourceManager p_256349_, ResourceKey> p_255792_, WritableRegistry p_256211_, Decoder p_256232_, Map, Exception> p_255884_) { -@@ -139,6 +_,7 @@ + String s = registryDirPath(p_255792_.location()); + FileToIdConverter filetoidconverter = FileToIdConverter.json(s); +- RegistryOps registryops = RegistryOps.create(JsonOps.INSTANCE, p_256369_); ++ RegistryOps registryops = RegistryOps.builder(JsonOps.INSTANCE, p_256369_) ++ .with(net.minecraftforge.common.crafting.conditions.ICondition.IContext.KEY, net.minecraftforge.common.crafting.conditions.ICondition.IContext.TAGS_INVALID) ++ .build(); ++ Decoder> conditional = net.minecraftforge.common.crafting.conditions.ConditionCodec.wrap(p_256232_); + + for(Map.Entry entry : filetoidconverter.listMatchingResources(p_256349_).entrySet()) { + ResourceLocation resourcelocation = entry.getKey(); +@@ -138,7 +_,12 @@ + try (Reader reader = resource.openAsReader()) { JsonElement jsonelement = JsonParser.parseReader(reader); - DataResult dataresult = p_256232_.parse(registryops, jsonelement); -+ if (!net.minecraftforge.common.crafting.conditions.ICondition.shouldRegisterEntry(jsonelement)) continue; +- DataResult dataresult = p_256232_.parse(registryops, jsonelement); ++ var result = conditional.decode(registryops, jsonelement); ++ if (result.result().map(p -> p.getFirst()).isEmpty()) { ++ LOGGER.debug("Skipping {} conditions not met", resourcelocation); ++ continue; ++ } ++ DataResult dataresult = result.map(p -> p.mapFirst(Optional::get)).map(p -> p.getFirst()); E e = dataresult.getOrThrow(false, (p_248715_) -> { }); p_256211_.register(resourcekey, e, resource.isBuiltin() ? Lifecycle.stable() : dataresult.lifecycle()); diff --git a/patches/minecraft/net/minecraft/resources/RegistryOps.java.patch b/patches/minecraft/net/minecraft/resources/RegistryOps.java.patch index 93c5fa962c..222bc00484 100644 --- a/patches/minecraft/net/minecraft/resources/RegistryOps.java.patch +++ b/patches/minecraft/net/minecraft/resources/RegistryOps.java.patch @@ -1,9 +1,33 @@ --- a/net/minecraft/resources/RegistryOps.java +++ b/net/minecraft/resources/RegistryOps.java -@@ -74,6 +_,20 @@ - }); +@@ -41,11 +_,20 @@ + return new RegistryOps<>(p_256278_, p_256479_); } ++ public static DelegatingOps.Builder> builder(DynamicOps parent, RegistryOps.RegistryInfoLookup lookup) { ++ return DelegatingOps.builder(() -> create(parent, lookup)); ++ } ++ + private RegistryOps(DynamicOps p_256313_, RegistryOps.RegistryInfoLookup p_255799_) { + super(p_256313_); + this.lookupProvider = p_255799_; + } + ++ public RegistryOps(RegistryOps parent) { ++ super(parent); ++ this.lookupProvider = parent.lookupProvider; ++ } ++ + public Optional> owner(ResourceKey> p_255757_) { + return this.lookupProvider.lookup(p_255757_).map(RegistryOps.RegistryInfo::owner); + } +@@ -71,6 +_,20 @@ + } + }).forGetter((p_255526_) -> { + return null; ++ }); ++ } ++ + public static com.mojang.serialization.MapCodec> retrieveRegistryLookup(ResourceKey> resourceKey) { + return ExtraCodecs.retrieveContext(ops -> { + if (!(ops instanceof RegistryOps registryOps)) @@ -15,9 +39,6 @@ + + return DataResult.success(registryLookup, registryInfo.elementsLifecycle()); + }).orElseGet(() -> DataResult.error(() -> "Unknown registry: " + resourceKey)); -+ }); -+ } -+ - public static RecordCodecBuilder> retrieveElement(ResourceKey p_256347_) { - ResourceKey> resourcekey = ResourceKey.createRegistryKey(p_256347_.registry()); - return ExtraCodecs.retrieveContext((p_274808_) -> { + }); + } + diff --git a/patches/minecraft/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch b/patches/minecraft/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch index 85a03518a6..8b60027ed8 100644 --- a/patches/minecraft/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch +++ b/patches/minecraft/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch @@ -31,7 +31,7 @@ ItemStack itemstack = this.player.getItemInHand(InteractionHand.OFF_HAND); - this.player.setItemInHand(InteractionHand.OFF_HAND, this.player.getItemInHand(InteractionHand.MAIN_HAND)); - this.player.setItemInHand(InteractionHand.MAIN_HAND, itemstack); -+ var event = net.minecraftforge.common.ForgeHooks.onLivingSwapHandItems(this.player); ++ var event = net.minecraftforge.event.ForgeEventFactory.onLivingSwapHandItems(this.player); + if (event.isCanceled()) return; + this.player.setItemInHand(InteractionHand.OFF_HAND, event.getItemSwappedToOffHand()); + this.player.setItemInHand(InteractionHand.MAIN_HAND, event.getItemSwappedToMainHand()); diff --git a/patches/minecraft/net/minecraft/world/entity/LivingEntity.java.patch b/patches/minecraft/net/minecraft/world/entity/LivingEntity.java.patch index 5179826f84..e73b998e7d 100644 --- a/patches/minecraft/net/minecraft/world/entity/LivingEntity.java.patch +++ b/patches/minecraft/net/minecraft/world/entity/LivingEntity.java.patch @@ -173,7 +173,7 @@ - this.hurtCurrentlyUsedShield(p_21017_); - f1 = p_21017_; - p_21017_ = 0.0F; -+ var ev = net.minecraftforge.common.ForgeHooks.onShieldBlock(this, p_21016_, p_21017_); ++ var ev = net.minecraftforge.event.ForgeEventFactory.onShieldBlock(this, p_21016_, p_21017_); + if(!ev.isCanceled()) { + if(ev.shieldTakesDamage()) this.hurtCurrentlyUsedShield(p_21017_); + f1 = ev.getBlockedDamage(); @@ -391,7 +391,7 @@ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.OFFHAND); - this.setItemSlot(EquipmentSlot.OFFHAND, this.getItemBySlot(EquipmentSlot.MAINHAND)); - this.setItemSlot(EquipmentSlot.MAINHAND, itemstack); -+ var event = net.minecraftforge.common.ForgeHooks.onLivingSwapHandItems(this); ++ var event = net.minecraftforge.event.ForgeEventFactory.onLivingSwapHandItems(this); + if (event.isCanceled()) return; + this.setItemSlot(EquipmentSlot.OFFHAND, event.getItemSwappedToOffHand()); + this.setItemSlot(EquipmentSlot.MAINHAND, event.getItemSwappedToMainHand()); diff --git a/patches/minecraft/net/minecraft/world/level/entity/PersistentEntitySectionManager.java.patch b/patches/minecraft/net/minecraft/world/level/entity/PersistentEntitySectionManager.java.patch index f0c81f8db5..5c0e2bf1f6 100644 --- a/patches/minecraft/net/minecraft/world/level/entity/PersistentEntitySectionManager.java.patch +++ b/patches/minecraft/net/minecraft/world/level/entity/PersistentEntitySectionManager.java.patch @@ -62,7 +62,7 @@ this.currentSection = entitysection; this.currentSectionKey = i; this.updateStatus(visibility, entitysection.getStatus()); -+ if (this.realEntity != null) net.minecraftforge.common.ForgeHooks.onEntityEnterSection(this.realEntity, oldSectionKey, i); ++ if (this.realEntity != null) net.minecraftforge.event.ForgeEventFactory.onEntityEnterSection(this.realEntity, oldSectionKey, i); } } diff --git a/patches/minecraft/net/minecraft/world/level/entity/TransientEntitySectionManager.java.patch b/patches/minecraft/net/minecraft/world/level/entity/TransientEntitySectionManager.java.patch index 39578727b1..c9421c9469 100644 --- a/patches/minecraft/net/minecraft/world/level/entity/TransientEntitySectionManager.java.patch +++ b/patches/minecraft/net/minecraft/world/level/entity/TransientEntitySectionManager.java.patch @@ -26,7 +26,7 @@ TransientEntitySectionManager.this.callbacks.onTickingStart(this.entity); } } -+ if (this.realEntity != null) net.minecraftforge.common.ForgeHooks.onEntityEnterSection(this.realEntity, oldSectionKey, i); ++ if (this.realEntity != null) net.minecraftforge.event.ForgeEventFactory.onEntityEnterSection(this.realEntity, oldSectionKey, i); } } diff --git a/patches/minecraft/net/minecraft/world/level/storage/loot/LootContext.java.patch b/patches/minecraft/net/minecraft/world/level/storage/loot/LootContext.java.patch index 8bef637a74..084a075280 100644 --- a/patches/minecraft/net/minecraft/world/level/storage/loot/LootContext.java.patch +++ b/patches/minecraft/net/minecraft/world/level/storage/loot/LootContext.java.patch @@ -1,6 +1,6 @@ --- a/net/minecraft/world/level/storage/loot/LootContext.java +++ b/net/minecraft/world/level/storage/loot/LootContext.java -@@ -86,15 +_,45 @@ +@@ -86,15 +_,43 @@ return new LootContext.VisitedEntry<>(LootDataType.MODIFIER, p_279163_); } @@ -16,7 +16,6 @@ + this.queriedLootTableId = queriedLootTableId; + } + -+ /* + public void setQueriedLootTableId(ResourceLocation queriedLootTableId) { + if (this.queriedLootTableId == null && queriedLootTableId != null) this.queriedLootTableId = queriedLootTableId; + } @@ -24,7 +23,6 @@ + public ResourceLocation getQueriedLootTableId() { + return this.queriedLootTableId == null ? net.minecraftforge.common.loot.LootTableIdCondition.UNKNOWN_LOOT_TABLE : this.queriedLootTableId; + } -+ */ + // =============================== FORGE END =============================== + public static class Builder { diff --git a/patches/minecraft/net/minecraft/world/level/storage/loot/LootDataType.java.patch b/patches/minecraft/net/minecraft/world/level/storage/loot/LootDataType.java.patch new file mode 100644 index 0000000000..0ee807b4c6 --- /dev/null +++ b/patches/minecraft/net/minecraft/world/level/storage/loot/LootDataType.java.patch @@ -0,0 +1,14 @@ +--- a/net/minecraft/world/level/storage/loot/LootDataType.java ++++ b/net/minecraft/world/level/storage/loot/LootDataType.java +@@ -42,7 +_,10 @@ + dataresult.error().ifPresent((p_297003_) -> { + LOGGER.error("Couldn't parse element {}:{} - {}", this.directory, p_279253_, p_297003_.message()); + }); +- return dataresult.result(); ++ var ret = dataresult.result(); ++ if (this == TABLE && ret.isPresent()) ++ ret = Optional.ofNullable((T)net.minecraftforge.event.ForgeEventFactory.onLoadLootTable(p_279253_, (LootTable)ret.get())); ++ return ret; + } + + public static Stream> values() { diff --git a/patches/minecraft/net/minecraft/world/level/storage/loot/LootPool.java.patch b/patches/minecraft/net/minecraft/world/level/storage/loot/LootPool.java.patch new file mode 100644 index 0000000000..a100d96c48 --- /dev/null +++ b/patches/minecraft/net/minecraft/world/level/storage/loot/LootPool.java.patch @@ -0,0 +1,95 @@ +--- a/net/minecraft/world/level/storage/loot/LootPool.java ++++ b/net/minecraft/world/level/storage/loot/LootPool.java +@@ -38,8 +_,12 @@ + return p_297004_.rolls; + }), NumberProviders.CODEC.fieldOf("bonus_rolls").orElse(ConstantValue.exactly(0.0F)).forGetter((p_297006_) -> { + return p_297006_.bonusRolls; +- })).apply(p_297005_, LootPool::new); ++ }), ++ Codec.STRING.optionalFieldOf("name").forGetter(p -> p.name.filter(n -> !n.startsWith("custom#"))), ++ net.minecraftforge.common.crafting.conditions.ICondition.OPTIONAL_FEILD_CODEC.forGetter(p -> p.forge_condition) ++ ).apply(p_297005_, LootPool::new); + }); ++ public static final Codec CONDITIONAL_CODEC = net.minecraftforge.common.crafting.conditions.ConditionCodec.checkingDecode(CODEC); + private final List entries; + private final List conditions; + private final Predicate compositeCondition; +@@ -47,8 +_,13 @@ + private final BiFunction compositeFunction; + private NumberProvider rolls; + private NumberProvider bonusRolls; ++ private java.util.Optional name; ++ private java.util.Optional forge_condition; + + LootPool(List p_298341_, List p_297697_, List p_299722_, NumberProvider p_165131_, NumberProvider p_165132_) { ++ this(p_298341_, p_297697_, p_299722_, p_165131_, p_165132_, java.util.Optional.empty(), java.util.Optional.empty()); ++ } ++ LootPool(List p_298341_, List p_297697_, List p_299722_, NumberProvider p_165131_, NumberProvider p_165132_, java.util.Optional name, java.util.Optional forge_conditions) { + this.entries = p_298341_; + this.conditions = p_297697_; + this.compositeCondition = LootItemConditions.andConditions(p_297697_); +@@ -56,6 +_,8 @@ + this.compositeFunction = LootItemFunctions.compose(p_299722_); + this.rolls = p_165131_; + this.bonusRolls = p_165132_; ++ this.name = name; ++ this.forge_condition = forge_conditions; + } + + private void addRandomItem(Consumer p_79059_, LootContext p_79060_) { +@@ -126,12 +_,35 @@ + return new LootPool.Builder(); + } + ++ private boolean isFrozen = false; ++ public void freeze() { this.isFrozen = true; } ++ public boolean isFrozen(){ return this.isFrozen; } ++ private void checkFrozen() { ++ if (this.isFrozen()) ++ throw new RuntimeException("Attempted to modify LootPool after being frozen!"); ++ } ++ @org.jetbrains.annotations.Nullable ++ public String getName() { return this.name.orElse(null); } ++ void setName(final String name) { ++ if (this.name.isPresent()) ++ throw new UnsupportedOperationException("Cannot change the name of a pool when it has a name set!"); ++ this.name = java.util.Optional.of(name); ++ } ++ public NumberProvider getRolls() { return this.rolls; } ++ public NumberProvider getBonusRolls() { return this.bonusRolls; } ++ public void setRolls (NumberProvider v){ checkFrozen(); this.rolls = v; } ++ public void setBonusRolls(NumberProvider v){ checkFrozen(); this.bonusRolls = v; } ++ + public static class Builder implements FunctionUserBuilder, ConditionUserBuilder { + private final ImmutableList.Builder entries = ImmutableList.builder(); + private final ImmutableList.Builder conditions = ImmutableList.builder(); + private final ImmutableList.Builder functions = ImmutableList.builder(); + private NumberProvider rolls = ConstantValue.exactly(1.0F); + private NumberProvider bonusRolls = ConstantValue.exactly(0.0F); ++ @org.jetbrains.annotations.Nullable ++ private String name; ++ @org.jetbrains.annotations.Nullable ++ private net.minecraftforge.common.crafting.conditions.ICondition forge_condition; + + public LootPool.Builder setRolls(NumberProvider p_165134_) { + this.rolls = p_165134_; +@@ -162,8 +_,18 @@ + return this; + } + ++ public LootPool.Builder name(String name) { ++ this.name = name; ++ return this; ++ } ++ ++ public LootPool.Builder when(net.minecraftforge.common.crafting.conditions.ICondition value) { ++ this.forge_condition = value; ++ return this; ++ } ++ + public LootPool build() { +- return new LootPool(this.entries.build(), this.conditions.build(), this.functions.build(), this.rolls, this.bonusRolls); ++ return new LootPool(this.entries.build(), this.conditions.build(), this.functions.build(), this.rolls, this.bonusRolls, java.util.Optional.ofNullable(this.name), java.util.Optional.ofNullable(forge_condition)); + } + } + } diff --git a/patches/minecraft/net/minecraft/world/level/storage/loot/LootTable.java.patch b/patches/minecraft/net/minecraft/world/level/storage/loot/LootTable.java.patch index d4e3a37e58..24251e173f 100644 --- a/patches/minecraft/net/minecraft/world/level/storage/loot/LootTable.java.patch +++ b/patches/minecraft/net/minecraft/world/level/storage/loot/LootTable.java.patch @@ -1,5 +1,14 @@ --- a/net/minecraft/world/level/storage/loot/LootTable.java +++ b/net/minecraft/world/level/storage/loot/LootTable.java +@@ -35,7 +_,7 @@ + return p_297013_.paramSet; + }), ExtraCodecs.strictOptionalField(ResourceLocation.CODEC, "random_sequence").forGetter((p_297014_) -> { + return p_297014_.randomSequence; +- }), ExtraCodecs.strictOptionalField(LootPool.CODEC.listOf(), "pools", List.of()).forGetter((p_297012_) -> { ++ }), ExtraCodecs.strictOptionalField(LootPool.CONDITIONAL_CODEC.listOf(), "pools", List.of()).forGetter((p_297012_) -> { + return p_297012_.pools; + }), ExtraCodecs.strictOptionalField(LootItemFunctions.CODEC.listOf(), "functions", List.of()).forGetter((p_297010_) -> { + return p_297010_.functions; @@ -50,7 +_,7 @@ LootTable(LootContextParamSet p_287716_, Optional p_298628_, List p_298771_, List p_301234_) { this.paramSet = p_287716_; @@ -47,11 +56,11 @@ ObjectArrayList objectarraylist = new ObjectArrayList<>(); - this.getRandomItems(p_230923_, objectarraylist::add); + this.getRandomItemsRaw(p_230923_, createStackSplitter(p_230923_.getLevel(), objectarraylist::add)); -+ //objectarraylist = net.minecraftforge.common.ForgeHooks.modifyLoot(this.getLootTableId(), objectarraylist, p_230923_); //TODO: GLM ++ objectarraylist = net.minecraftforge.common.ForgeHooks.modifyLoot(this.getLootTableId(), objectarraylist, p_230923_); return objectarraylist; } -@@ -207,6 +_,23 @@ +@@ -207,6 +_,51 @@ public static LootTable.Builder lootTable() { return new LootTable.Builder(); @@ -68,10 +77,38 @@ + return this.lootTableId; + } + ++ @org.jetbrains.annotations.Nullable ++ public LootPool removePool(String name) { ++ checkFrozen(); ++ for (var pool : this.pools) { ++ if (name.equals(pool.getName())) { ++ this.pools.remove(pool); ++ return pool; ++ } ++ } ++ return null; ++ } ++ + public void addPool(LootPool pool) { ++ checkFrozen(); + if (pools.stream().anyMatch(e -> e == pool)) + throw new RuntimeException("Attempted to add a duplicate pool to loot table: " + pool); + this.pools.add(pool); ++ } ++ ++ private boolean isFrozen = false; ++ public void freeze() { ++ this.isFrozen = true; ++ this.pools.forEach(LootPool::freeze); ++ } ++ ++ public boolean isFrozen() { ++ return this.isFrozen; ++ } ++ ++ private void checkFrozen() { ++ if (this.isFrozen()) ++ throw new RuntimeException("Attempted to modify LootTable after being finalized!"); } public static class Builder implements FunctionUserBuilder { diff --git a/src/generated_test/resources/data/forge/loot_modifiers/global_loot_modifiers.json b/src/generated_test/resources/data/forge/loot_modifiers/global_loot_modifiers.json new file mode 100644 index 0000000000..86a059a62d --- /dev/null +++ b/src/generated_test/resources/data/forge/loot_modifiers/global_loot_modifiers.json @@ -0,0 +1,9 @@ +{ + "entries": [ + "global_loot_test:dungeon_loot", + "global_loot_test:bamboo_silk", + "global_loot_test:wheat_harvest", + "global_loot_test:smelting" + ], + "replace": false +} \ No newline at end of file diff --git a/src/generated_test/resources/data/global_loot_test/loot_modifiers/bamboo_silk.json b/src/generated_test/resources/data/global_loot_test/loot_modifiers/bamboo_silk.json new file mode 100644 index 0000000000..09924fa32e --- /dev/null +++ b/src/generated_test/resources/data/global_loot_test/loot_modifiers/bamboo_silk.json @@ -0,0 +1,13 @@ +{ + "type": "global_loot_test:silk_touch_bamboo", + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "items": [ + "minecraft:bamboo" + ] + } + } + ] +} \ No newline at end of file diff --git a/src/generated_test/resources/data/global_loot_test/loot_modifiers/dungeon_loot.json b/src/generated_test/resources/data/global_loot_test/loot_modifiers/dungeon_loot.json new file mode 100644 index 0000000000..5dba5b78d3 --- /dev/null +++ b/src/generated_test/resources/data/global_loot_test/loot_modifiers/dungeon_loot.json @@ -0,0 +1,9 @@ +{ + "type": "global_loot_test:dungeon_loot", + "conditions": [ + { + "condition": "forge:loot_table_id", + "loot_table_id": "minecraft:chests/simple_dungeon" + } + ] +} \ No newline at end of file diff --git a/src/generated_test/resources/data/global_loot_test/loot_modifiers/smelting.json b/src/generated_test/resources/data/global_loot_test/loot_modifiers/smelting.json new file mode 100644 index 0000000000..09b17fd901 --- /dev/null +++ b/src/generated_test/resources/data/global_loot_test/loot_modifiers/smelting.json @@ -0,0 +1,18 @@ +{ + "type": "global_loot_test:smelting", + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "global_loot_test:smelt", + "levels": { + "min": 1 + } + } + ] + } + } + ] +} \ No newline at end of file diff --git a/src/generated_test/resources/data/global_loot_test/loot_modifiers/wheat_harvest.json b/src/generated_test/resources/data/global_loot_test/loot_modifiers/wheat_harvest.json new file mode 100644 index 0000000000..e2cdba2d4d --- /dev/null +++ b/src/generated_test/resources/data/global_loot_test/loot_modifiers/wheat_harvest.json @@ -0,0 +1,20 @@ +{ + "type": "global_loot_test:wheat_harvest", + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "items": [ + "minecraft:shears" + ] + } + }, + { + "block": "minecraft:wheat", + "condition": "minecraft:block_state_property" + } + ], + "numSeeds": 3, + "replacement": "minecraft:wheat", + "seedItem": "minecraft:wheat_seeds" +} \ No newline at end of file diff --git a/src/generated_test/resources/pack.mcmeta b/src/generated_test/resources/pack.mcmeta new file mode 100644 index 0000000000..ca02aa7f6f --- /dev/null +++ b/src/generated_test/resources/pack.mcmeta @@ -0,0 +1,8 @@ +{ + "pack": { + "description": { + "text": "Forge tests resource pack" + }, + "pack_format": 18 + } +} \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/common/ForgeHooks.java b/src/main/java/net/minecraftforge/common/ForgeHooks.java index f6592705fa..e8ea1ce802 100644 --- a/src/main/java/net/minecraftforge/common/ForgeHooks.java +++ b/src/main/java/net/minecraftforge/common/ForgeHooks.java @@ -22,9 +22,15 @@ import java.util.stream.Stream; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; +import com.mojang.datafixers.util.Pair; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.Decoder; import com.mojang.serialization.Dynamic; +import com.mojang.serialization.DynamicOps; import com.mojang.serialization.Lifecycle; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.commands.SharedSuggestionProvider; @@ -76,6 +82,8 @@ import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.material.Fluids; import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.WorldData; +import net.minecraft.world.level.storage.loot.LootContext; +import net.minecraft.world.level.storage.loot.LootPool; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.entity.item.ItemEntity; @@ -121,7 +129,6 @@ import net.minecraftforge.event.RegisterStructureConversionsEvent; import net.minecraftforge.event.VanillaGameEvent; import net.minecraftforge.event.entity.EntityAttributeCreationEvent; import net.minecraftforge.event.entity.EntityAttributeModificationEvent; -import net.minecraftforge.event.entity.EntityEvent; import net.minecraftforge.event.entity.item.ItemTossEvent; import net.minecraftforge.event.entity.living.EnderManAngerEvent; import net.minecraftforge.event.entity.living.LivingAttackEvent; @@ -139,10 +146,8 @@ import net.minecraftforge.event.entity.living.LivingFallEvent; import net.minecraftforge.event.entity.living.LivingHurtEvent; import net.minecraftforge.event.entity.living.LivingKnockBackEvent; import net.minecraftforge.event.entity.living.LivingMakeBrainEvent; -import net.minecraftforge.event.entity.living.LivingSwapItemsEvent; import net.minecraftforge.event.entity.living.LivingUseTotemEvent; import net.minecraftforge.event.entity.living.LootingLevelEvent; -import net.minecraftforge.event.entity.living.ShieldBlockEvent; import net.minecraftforge.event.entity.player.AnvilRepairEvent; import net.minecraftforge.event.entity.player.AttackEntityEvent; import net.minecraftforge.event.entity.player.CriticalHitEvent; @@ -188,6 +193,8 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +/** FOR INTERNAL USE ONLY, DO NOT CALL DIRECTLY */ +@ApiStatus.Internal public class ForgeHooks { private static final Logger LOGGER = LogManager.getLogger(); @SuppressWarnings("unused") @@ -648,14 +655,6 @@ public class ForgeHooks { return evt.isCanceled() ? evt.getCancellationResult() : null; } - /** - * @deprecated Use {@link #onLeftClickBlock(Player, BlockPos, Direction, ServerboundPlayerActionPacket.Action)} instead - */ - @Deprecated(since = "1.20.1", forRemoval = true) - public static PlayerInteractEvent.LeftClickBlock onLeftClickBlock(Player player, BlockPos pos, Direction face) { - return onLeftClickBlock(player, pos, face, ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK); - } - public static PlayerInteractEvent.LeftClickBlock onLeftClickBlock(Player player, BlockPos pos, Direction face, ServerboundPlayerActionPacket.Action action) { PlayerInteractEvent.LeftClickBlock evt = new PlayerInteractEvent.LeftClickBlock(player, pos, face, PlayerInteractEvent.LeftClickBlock.Action.convert(action)); MinecraftForge.EVENT_BUS.post(evt); @@ -693,85 +692,23 @@ public class ForgeHooks { return evt.getNewGameMode(); } - /* TODO: GLM - private static final ThreadLocal> lootContext = new ThreadLocal<>(); - private static LootTableContext getLootTableContext() { - LootTableContext ctx = lootContext.get().peek(); + public static Codec> createLootTablePoolCodec(Codec vanilla) { + var list = vanilla.listOf(); + Decoder> decoder = new Decoder<>() { + @Override + public DataResult, T>> decode(DynamicOps ops, T input) { + return list.decode(ops, input).map(p -> { + var decoded = p.getFirst(); + for (int x = 0; x < decoded.size(); x++) + decoded.get(x); - if (ctx == null) - throw new JsonParseException("Invalid call stack, could not grab json context!"); // Should I throw this? Do we care about custom deserializers outside the manager? - - return ctx; - } - - public static TriFunction> getLootTableDeserializer(Gson gson, String directory) { - return (location, data, resourceManager) -> { - try { - Resource resource = resourceManager.getResource(location.withPath(directory + "/" + location.getPath() + ".json")).orElse(null); - boolean custom = resource == null || !resource.isBuiltin(); - return Optional.ofNullable(loadLootTable(gson, location, data, custom)); - } catch (Exception exception) { - LOGGER.error("Couldn't parse element {}:{}", directory, location, exception); - return Optional.empty(); + return p; + }); } }; + return Codec.of(list, decoder); } - public static LootTable loadLootTable(Gson gson, ResourceLocation name, JsonElement data, boolean custom) { - Deque que = lootContext.get(); - if (que == null) { - que = Queues.newArrayDeque(); - lootContext.set(que); - } - - LootTable ret; - try { - que.push(new LootTableContext(name, custom)); - ret = gson.fromJson(data, LootTable.class); - ret.setLootTableId(name); - } catch (JsonParseException e) { - throw e; - } finally { - que.pop(); - } - - if (!custom) - ret = ForgeEventFactory.loadLootTable(name, ret); - - if (ret != null) - ret.freeze(); - - return ret; - } - - private static class LootTableContext { - public final ResourceLocation name; - public final boolean vanilla; - public final boolean custom; - public int poolCount = 0; - - private LootTableContext(ResourceLocation name, boolean custom) { - this.name = name; - this.custom = custom; - this.vanilla = "minecraft".equals(this.name.getNamespace()); - } - } - - public static String readPoolName(JsonObject json) { - LootTableContext ctx = getLootTableContext(); - - if (json.has("name")) - return GsonHelper.getAsString(json, "name"); - - if (ctx.custom) - return "custom#" + json.hashCode(); //We don't care about custom ones modders shouldn't be editing them! - - ctx.poolCount++; - - return ctx.poolCount == 1 ? "main" : "pool" + (ctx.poolCount - 1); - } - */ - /** * Returns a vanilla fluid type for the given fluid. * @@ -953,7 +890,6 @@ public class ForgeHooks { FurnaceBlockEntity.getFuel().entrySet().forEach(e -> VANILLA_BURNS.put(ForgeRegistries.ITEMS.getDelegateOrThrow(e.getKey()), e.getValue())); } - // TODO: GLM /** * Handles the modification of loot table drops via the registered Global Loot Modifiers, * so that custom effects can be processed. @@ -967,16 +903,13 @@ public class ForgeHooks { * * @apiNote The given context will be modified by this method to also store the ID of the * loot table being queried. - * / + */ public static ObjectArrayList modifyLoot(ResourceLocation lootTableId, ObjectArrayList generatedLoot, LootContext context) { context.setQueriedLootTableId(lootTableId); // In case the ID was set via copy constructor, this will be ignored: intended - LootModifierManager man = ForgeInternalHandler.getLootModifierManager(); - for (IGlobalLootModifier mod : man.getAllLootMods()) { + for (var mod : ForgeInternalHandler.getLootModifierManager().getAllLootMods()) generatedLoot = mod.apply(generatedLoot, context); - } return generatedLoot; } - */ public static List getModPacks() { List modpacks = ResourcePackLoader.getPackNames(); @@ -992,13 +925,11 @@ public class ForgeHooks { } private static final Map, AttributeSupplier> FORGE_ATTRIBUTES = new HashMap<>(); - /** FOR INTERNAL USE ONLY, DO NOT CALL DIRECTLY */ @Deprecated public static Map, AttributeSupplier> getAttributesView() { return Collections.unmodifiableMap(FORGE_ATTRIBUTES); } - /** FOR INTERNAL USE ONLY, DO NOT CALL DIRECTLY */ @Deprecated public static void modifyAttributes() { ModLoader.get().postEvent(new EntityAttributeCreationEvent(FORGE_ATTRIBUTES)); @@ -1013,22 +944,6 @@ public class ForgeHooks { }); } - public static void onEntityEnterSection(Entity entity, long packedOldPos, long packedNewPos) { - MinecraftForge.EVENT_BUS.post(new EntityEvent.EnteringSection(entity, packedOldPos, packedNewPos)); - } - - public static ShieldBlockEvent onShieldBlock(LivingEntity blocker, DamageSource source, float blocked) { - ShieldBlockEvent e = new ShieldBlockEvent(blocker, source, blocked); - MinecraftForge.EVENT_BUS.post(e); - return e; - } - - public static LivingSwapItemsEvent.Hands onLivingSwapHandItems(LivingEntity livingEntity) { - LivingSwapItemsEvent.Hands event = new LivingSwapItemsEvent.Hands(livingEntity); - MinecraftForge.EVENT_BUS.post(event); - return event; - } - public static void writeAdditionalLevelSaveData(WorldData worldData, CompoundTag levelTag) { CompoundTag fmlData = new CompoundTag(); ListTag modList = new ListTag(); diff --git a/src/main/java/net/minecraftforge/common/ForgeInternalHandler.java b/src/main/java/net/minecraftforge/common/ForgeInternalHandler.java index ad0e5b5fa5..718fab7011 100644 --- a/src/main/java/net/minecraftforge/common/ForgeInternalHandler.java +++ b/src/main/java/net/minecraftforge/common/ForgeInternalHandler.java @@ -12,6 +12,7 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.server.TickTask; import net.minecraft.server.level.ServerLevel; +import net.minecraftforge.common.loot.LootModifierManager; import net.minecraftforge.common.util.FakePlayerFactory; import net.minecraftforge.event.AddReloadListenerEvent; import net.minecraftforge.event.RegisterCommandsEvent; @@ -101,7 +102,6 @@ public class ForgeInternalHandler { ConfigCommand.register(event.getDispatcher()); } - /* private static LootModifierManager INSTANCE; @SubscribeEvent @@ -111,11 +111,10 @@ public class ForgeInternalHandler { } static LootModifierManager getLootModifierManager() { - if(INSTANCE == null) + if (INSTANCE == null) throw new IllegalStateException("Can not retrieve LootModifierManager until resources have loaded once."); return INSTANCE; } - */ @SubscribeEvent public void resourceReloadListeners(AddReloadListenerEvent event) { diff --git a/src/main/java/net/minecraftforge/common/ForgeMod.java b/src/main/java/net/minecraftforge/common/ForgeMod.java index b14373f339..7071f1df09 100644 --- a/src/main/java/net/minecraftforge/common/ForgeMod.java +++ b/src/main/java/net/minecraftforge/common/ForgeMod.java @@ -41,6 +41,7 @@ import net.minecraft.util.ExtraCodecs; import net.minecraft.core.RegistryCodecs; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.pathfinder.BlockPathTypes; +import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType; import net.minecraft.world.phys.Vec3; import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions; import net.minecraftforge.common.data.ExistingFileHelper; @@ -50,6 +51,8 @@ import net.minecraftforge.common.data.ForgeSpriteSourceProvider; import net.minecraftforge.common.data.VanillaSoundDefinitionsProvider; import net.minecraftforge.common.extensions.IForgeEntity; import net.minecraftforge.common.extensions.IForgePlayer; +import net.minecraftforge.common.loot.CanToolPerformAction; +import net.minecraftforge.common.loot.LootTableIdCondition; import net.minecraftforge.common.world.BiomeModifier; import net.minecraftforge.common.world.ForgeBiomeModifiers.AddFeaturesBiomeModifier; import net.minecraftforge.common.world.ForgeBiomeModifiers.AddSpawnsBiomeModifier; @@ -89,9 +92,9 @@ import org.apache.logging.log4j.Logger; import net.minecraft.data.DataGenerator; import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.common.crafting.CraftingHelper; import net.minecraftforge.common.crafting.conditions.AndCondition; import net.minecraftforge.common.crafting.conditions.FalseCondition; +import net.minecraftforge.common.crafting.conditions.ICondition; import net.minecraftforge.common.crafting.conditions.ItemExistsCondition; import net.minecraftforge.common.crafting.conditions.ModLoadedCondition; import net.minecraftforge.common.crafting.conditions.NotCondition; @@ -129,9 +132,10 @@ public class ForgeMod { private static final DeferredRegister> STRUCTURE_MODIFIER_SERIALIZERS = DeferredRegister.create(ForgeRegistries.Keys.STRUCTURE_MODIFIER_SERIALIZERS, "forge"); private static final DeferredRegister HOLDER_SET_TYPES = DeferredRegister.create(ForgeRegistries.Keys.HOLDER_SET_TYPES, "forge"); - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({ "unchecked", "rawtypes", "unused" }) private static final RegistryObject ENUM_COMMAND_ARGUMENT_TYPE = COMMAND_ARGUMENT_TYPES.register("enum", () -> ArgumentTypeInfos.registerByClass(EnumArgument.class, new EnumArgument.Info())); + @SuppressWarnings("unused") private static final RegistryObject> MODID_COMMAND_ARGUMENT_TYPE = COMMAND_ARGUMENT_TYPES.register("modid", () -> ArgumentTypeInfos.registerByClass(ModIdArgument.class, SingletonArgumentInfo.contextFree(ModIdArgument::modIdArgument))); @@ -367,6 +371,25 @@ public class ForgeMod { } }); + private static final DeferredRegister LOOT_CONDITION_TYPES = DeferredRegister.create(Registries.LOOT_CONDITION_TYPE, "forge"); + static { + LOOT_CONDITION_TYPES.register("loot_table_id", () -> LootTableIdCondition.TYPE); + LOOT_CONDITION_TYPES.register("can_tool_perform_action", () -> CanToolPerformAction.TYPE); + } + + private static final DeferredRegister> CONDITION_SERIALIZERS = DeferredRegister.create(ForgeRegistries.Keys.CONDITION_SERIALIZERS, "forge"); + static { + CONDITION_SERIALIZERS.register("and", () -> AndCondition.CODEC); + CONDITION_SERIALIZERS.register("false", () -> FalseCondition.CODEC); + CONDITION_SERIALIZERS.register("item_exists", () -> ItemExistsCondition.CODEC); + CONDITION_SERIALIZERS.register("mod_loaded", () -> ModLoadedCondition.CODEC); + CONDITION_SERIALIZERS.register("not", () -> NotCondition.CODEC); + CONDITION_SERIALIZERS.register("or", () -> OrCondition.CODEC); + CONDITION_SERIALIZERS.register("true", () -> TrueCondition.CODEC); + CONDITION_SERIALIZERS.register("tag_empty", () -> TagEmptyCondition.CODEC); + } + + private static boolean enableMilkFluid = false; public static final RegistryObject BUCKET_EMPTY_MILK = RegistryObject.create(new ResourceLocation("item.bucket.empty_milk"), ForgeRegistries.SOUND_EVENTS); public static final RegistryObject BUCKET_FILL_MILK = RegistryObject.create(new ResourceLocation("item.bucket.fill_milk"), ForgeRegistries.SOUND_EVENTS); @@ -414,7 +437,6 @@ public class ForgeMod { modEventBus.addListener(this::registerFluids); modEventBus.addListener(this::registerVanillaDisplayContexts); modEventBus.addListener(this::registerRecipeSerializers); - modEventBus.addListener(this::registerLootData); modEventBus.register(this); ATTRIBUTES.register(modEventBus); COMMAND_ARGUMENT_TYPES.register(modEventBus); @@ -422,6 +444,8 @@ public class ForgeMod { STRUCTURE_MODIFIER_SERIALIZERS.register(modEventBus); HOLDER_SET_TYPES.register(modEventBus); VANILLA_FLUID_TYPES.register(modEventBus); + LOOT_CONDITION_TYPES.register(modEventBus); + CONDITION_SERIALIZERS.register(modEventBus); MinecraftForge.EVENT_BUS.addListener(this::serverStopping); ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ForgeConfig.clientSpec); ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, ForgeConfig.serverSpec); @@ -546,14 +570,6 @@ public class ForgeMod { public void registerRecipeSerializers(RegisterEvent event) { if (event.getRegistryKey().equals(ForgeRegistries.Keys.RECIPE_SERIALIZERS)) { - CraftingHelper.register(AndCondition.Serializer.INSTANCE); - CraftingHelper.register(FalseCondition.Serializer.INSTANCE); - CraftingHelper.register(ItemExistsCondition.Serializer.INSTANCE); - CraftingHelper.register(ModLoadedCondition.Serializer.INSTANCE); - CraftingHelper.register(NotCondition.Serializer.INSTANCE); - CraftingHelper.register(OrCondition.Serializer.INSTANCE); - CraftingHelper.register(TrueCondition.Serializer.INSTANCE); - CraftingHelper.register(TagEmptyCondition.Serializer.INSTANCE); /* CraftingHelper.register(new ResourceLocation("forge", "compound"), CompoundIngredient.Serializer.INSTANCE); @@ -568,14 +584,6 @@ public class ForgeMod { } } - public void registerLootData(RegisterEvent event) { - if (!event.getRegistryKey().equals(Registries.LOOT_CONDITION_TYPE)) - return; - - //event.register(Registries.LOOT_CONDITION_TYPE, new ResourceLocation("forge:loot_table_id"), () -> LootTableIdCondition.LOOT_TABLE_ID); - //event.register(Registries.LOOT_CONDITION_TYPE, new ResourceLocation("forge:can_tool_perform_action"), () -> CanToolPerformAction.LOOT_CONDITION_TYPE); - } - public static final PermissionNode USE_SELECTORS_PERMISSION = new PermissionNode<>("forge", "use_entity_selectors", PermissionTypes.BOOLEAN, (player, uuid, contexts) -> player != null && player.hasPermissions(Commands.LEVEL_GAMEMASTERS)); diff --git a/src/main/java/net/minecraftforge/common/ToolAction.java b/src/main/java/net/minecraftforge/common/ToolAction.java index 030f3b00ae..96cca64475 100644 --- a/src/main/java/net/minecraftforge/common/ToolAction.java +++ b/src/main/java/net/minecraftforge/common/ToolAction.java @@ -10,9 +10,10 @@ import java.util.Collections; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -@SuppressWarnings("ClassCanBeRecord") -public final class ToolAction -{ +import com.mojang.serialization.Codec; + +public final class ToolAction { + public static final Codec CODEC = Codec.STRING.xmap(ToolAction::get, ToolAction::name).stable(); private static final Map actions = new ConcurrentHashMap<>(); /** @@ -20,30 +21,26 @@ public final class ToolAction * This collection can be kept around, and will update itself in response to changes to the map. * See {@link ConcurrentHashMap#values()} for details. */ - public static Collection getActions() - { + public static Collection getActions() { return Collections.unmodifiableCollection(actions.values()); } /** * Gets or creates a new ToolAction for the given name. */ - public static ToolAction get(String name) - { + public static ToolAction get(String name) { return actions.computeIfAbsent(name, ToolAction::new); } /** * Returns the name of this tool action */ - public String name() - { + public String name() { return name; } @Override - public String toString() - { + public String toString() { return "ToolAction[" + name + "]"; } @@ -52,8 +49,7 @@ public final class ToolAction /** * Use {@link #get(String)} to get or create a ToolAction */ - private ToolAction(String name) - { + private ToolAction(String name) { this.name = name; } } diff --git a/src/main/java/net/minecraftforge/common/crafting/AbstractIngredient.java b/src/main/java/net/minecraftforge/common/crafting/AbstractIngredient.java deleted file mode 100644 index 865713fa47..0000000000 --- a/src/main/java/net/minecraftforge/common/crafting/AbstractIngredient.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.minecraftforge.common.crafting; -/* -import com.google.gson.JsonElement; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.tags.TagKey; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.level.ItemLike; -import org.jetbrains.annotations.Nullable; - -import java.util.stream.Stream; - -/** - * Extension of {@link Ingredient} which makes most methods custom ingredients need to implement abstract, and removes the static constructors - * Mods are encouraged to extend this class for their custom ingredients - * / -public abstract class AbstractIngredient extends Ingredient { - /** Empty constructor, for the sake of dynamic ingredients * / - protected AbstractIngredient() { - super(Stream.of()); - } - - /** Value constructor, for ingredients that have some vanilla representation * / - protected AbstractIngredient(Stream values) { - super(values); - } - - @Override - public abstract boolean isSimple(); - - @Override - public abstract IIngredientSerializer getSerializer(); - - @Override - public abstract JsonElement toJson(boolean allowEmpty); - - - /* Hide vanilla ingredient static constructors to reduce errors with constructing custom ingredients * / - - /** @deprecated use {@link Ingredient#fromValues(Stream)} * / - @Deprecated - public static Ingredient fromValues(Stream values) { - throw new UnsupportedOperationException("Use Ingredient.fromValues()"); - } - - /** @deprecated use {@link Ingredient#of()} * / - @Deprecated - public static Ingredient of() { - throw new UnsupportedOperationException("Use Ingredient.of()"); - } - - /** @deprecated use {@link Ingredient#of(ItemLike...)} (Stream)} * / - @Deprecated - public static Ingredient of(ItemLike... items) { - throw new UnsupportedOperationException("Use Ingredient.of()"); - } - - /** @deprecated use {@link Ingredient#of(ItemStack...)} (Stream)} * / - @Deprecated - public static Ingredient of(ItemStack... stacks) { - throw new UnsupportedOperationException("Use Ingredient.of()"); - } - - /** @deprecated use {@link Ingredient#of(Stream)} (Stream)} * / - @Deprecated - public static Ingredient of(Stream stacks) { - throw new UnsupportedOperationException("Use Ingredient.of()"); - } - - /** @deprecated use {@link Ingredient#of(TagKey)} (Stream)} * / - @Deprecated - public static Ingredient of(TagKey tag) { - throw new UnsupportedOperationException("Use Ingredient.of()"); - } - - /** @deprecated use {@link Ingredient#fromNetwork(FriendlyByteBuf)} * / - @Deprecated - public static Ingredient fromNetwork(FriendlyByteBuf buffer) { - throw new UnsupportedOperationException("Use Ingredient.fromNetwork()"); - } - - /** @deprecated use {@link Ingredient#fromJson(JsonElement)} (Stream)} * / - @Deprecated - public static Ingredient fromJson(@Nullable JsonElement json) { - throw new UnsupportedOperationException("Use Ingredient.fromJson()"); - } -} -*/ diff --git a/src/main/java/net/minecraftforge/common/crafting/CompoundIngredient.java b/src/main/java/net/minecraftforge/common/crafting/CompoundIngredient.java index edff16b5bd..10aa0273f8 100644 --- a/src/main/java/net/minecraftforge/common/crafting/CompoundIngredient.java +++ b/src/main/java/net/minecraftforge/common/crafting/CompoundIngredient.java @@ -27,9 +27,9 @@ import net.minecraft.network.FriendlyByteBuf; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -/** Ingredient that matches if any of the child ingredients match * / -public class CompoundIngredient extends AbstractIngredient -{ +/** Ingredient that matches if any of the child ingredients match */ +/* +public class CompoundIngredient extends Ingredient { private List children; private ItemStack[] stacks; private IntList itemIds; @@ -41,7 +41,8 @@ public class CompoundIngredient extends AbstractIngredient this.isSimple = children.stream().allMatch(Ingredient::isSimple); } - /** Creates a compound ingredient from the given list of ingredients * / + /** Creates a compound ingredient from the given list of ingredients */ +/* public static Ingredient of(Ingredient... children) { // if 0 or 1 ingredient, can save effort @@ -68,10 +69,8 @@ public class CompoundIngredient extends AbstractIngredient @Override @NotNull - public ItemStack[] getItems() - { - if (stacks == null) - { + public ItemStack[] getItems() { + if (stacks == null) { List tmp = Lists.newArrayList(); for (Ingredient child : children) Collections.addAll(tmp, child.getItems()); @@ -83,15 +82,11 @@ public class CompoundIngredient extends AbstractIngredient @Override @NotNull - public IntList getStackingIds() - { + public IntList getStackingIds() { boolean childrenNeedInvalidation = false; for (Ingredient child : children) - { childrenNeedInvalidation |= child.checkInvalidation(); - } - if (childrenNeedInvalidation || this.itemIds == null || checkInvalidation()) - { + if (childrenNeedInvalidation || this.itemIds == null || checkInvalidation()) { this.markValid(); this.itemIds = new IntArrayList(); for (Ingredient child : children) @@ -103,8 +98,7 @@ public class CompoundIngredient extends AbstractIngredient } @Override - public boolean test(@Nullable ItemStack target) - { + public boolean test(@Nullable ItemStack target) { if (target == null) return false; @@ -112,74 +106,18 @@ public class CompoundIngredient extends AbstractIngredient } @Override - protected void invalidate() - { - this.itemIds = null; - this.stacks = null; - } - - @Override - public boolean isSimple() - { + public boolean isSimple() { return isSimple; } - @Override - public IIngredientSerializer getSerializer() - { - return Serializer.INSTANCE; - } - @NotNull - public Collection getChildren() - { + public Collection getChildren() { return this.children; } @Override - public JsonElement toJson() - { - if (this.children.size() == 1) - { - return this.children.get(0).toJson(); - } - else - { - JsonArray json = new JsonArray(); - this.children.stream().forEach(e -> json.add(e.toJson())); - return json; - } - } - - @Override - public boolean isEmpty() - { + public boolean isEmpty() { return children.stream().allMatch(Ingredient::isEmpty); } - - public static class Serializer implements IIngredientSerializer - { - public static final Serializer INSTANCE = new Serializer(); - - @Override - public CompoundIngredient parse(FriendlyByteBuf buffer) - { - return new CompoundIngredient(Stream.generate(() -> Ingredient.fromNetwork(buffer)).limit(buffer.readVarInt()).collect(Collectors.toList())); - } - - @Override - public CompoundIngredient parse(JsonObject json) - { - throw new JsonSyntaxException("CompoundIngredient should not be directly referenced in json, just use an array of ingredients."); - } - - @Override - public void write(FriendlyByteBuf buffer, CompoundIngredient ingredient) - { - buffer.writeVarInt(ingredient.children.size()); - ingredient.children.forEach(c -> c.toNetwork(buffer)); - } - - } } */ diff --git a/src/main/java/net/minecraftforge/common/crafting/CraftingHelper.java b/src/main/java/net/minecraftforge/common/crafting/CraftingHelper.java index 63a88b2976..f2db032539 100644 --- a/src/main/java/net/minecraftforge/common/crafting/CraftingHelper.java +++ b/src/main/java/net/minecraftforge/common/crafting/CraftingHelper.java @@ -16,12 +16,12 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.serialization.Codec; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraftforge.common.crafting.conditions.ICondition; -import net.minecraftforge.common.crafting.conditions.IConditionSerializer; import net.minecraft.nbt.TagParser; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.GsonHelper; @@ -173,13 +173,11 @@ public class CraftingHelper { } // CONDITIONS - private static final Map> conditions = new HashMap<>(); - public static IConditionSerializer register(IConditionSerializer serializer) { - ResourceLocation key = serializer.getID(); + private static final Map> conditions = new HashMap<>(); + public static void register(ResourceLocation key, Codec codec) { if (conditions.containsKey(key)) throw new IllegalStateException("Duplicate recipe condition serializer: " + key); - conditions.put(key, serializer); - return serializer; + conditions.put(key, codec); } public static boolean processConditions(JsonObject json, String memberName, ICondition.IContext context) { @@ -187,38 +185,16 @@ public class CraftingHelper { } public static boolean processConditions(JsonArray conditions, ICondition.IContext context) { - for (int x = 0; x < conditions.size(); x++) - { + for (int x = 0; x < conditions.size(); x++) { if (!conditions.get(x).isJsonObject()) throw new JsonSyntaxException("Conditions must be an array of JsonObjects"); JsonObject json = conditions.get(x).getAsJsonObject(); + /* if (!CraftingHelper.getCondition(json).test(context)) return false; + */ } return true; } - - public static ICondition getCondition(JsonObject json) { - ResourceLocation type = new ResourceLocation(GsonHelper.getAsString(json, "type")); - IConditionSerializer serializer = conditions.get(type); - if (serializer == null) - throw new JsonSyntaxException("Unknown condition type: " + type.toString()); - return serializer.read(json); - } - - public static JsonObject serialize(T condition) { - @SuppressWarnings("unchecked") - IConditionSerializer serializer = (IConditionSerializer)conditions.get(condition.getID()); - if (serializer == null) - throw new JsonSyntaxException("Unknown condition type: " + condition.getID().toString()); - return serializer.getJson(condition); - } - - public static JsonArray serialize(ICondition... conditions) { - JsonArray arr = new JsonArray(); - for(ICondition iCond : conditions) - arr.add(serialize(iCond)); - return arr; - } } diff --git a/src/main/java/net/minecraftforge/common/crafting/IIngredientSerializer.java b/src/main/java/net/minecraftforge/common/crafting/IIngredientSerializer.java deleted file mode 100644 index 5bc1dd5d46..0000000000 --- a/src/main/java/net/minecraftforge/common/crafting/IIngredientSerializer.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.minecraftforge.common.crafting; - -// TODO: Ingredient Serializers -/* -import com.google.gson.JsonObject; - -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.network.FriendlyByteBuf; - -public interface IIngredientSerializer { - T parse(FriendlyByteBuf buffer); - - T parse(JsonObject json); - - void write(FriendlyByteBuf buffer, T ingredient); -} -*/ \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/common/crafting/MultiItemValue.java b/src/main/java/net/minecraftforge/common/crafting/MultiItemValue.java deleted file mode 100644 index db242478e4..0000000000 --- a/src/main/java/net/minecraftforge/common/crafting/MultiItemValue.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.minecraftforge.common.crafting; -/* -import java.util.Collection; -import java.util.Collections; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; - -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.Ingredient.Value; -import net.minecraftforge.registries.ForgeRegistries; - -public class MultiItemValue implements Value -{ - private Collection items; - public MultiItemValue(Collection items) - { - this.items = Collections.unmodifiableCollection(items); - } - - @Override - public Collection getItems() - { - return items; - } - - @Override - public JsonObject serialize() - { - if (items.size() == 1) - return toJson(items.iterator().next()); - - JsonObject ret = new JsonObject(); - JsonArray array = new JsonArray(); - items.forEach(stack -> array.add(toJson(stack))); - ret.add("items", array); - return ret; - } - - private JsonObject toJson(ItemStack stack) - { - JsonObject ret = new JsonObject(); - ret.addProperty("item", ForgeRegistries.ITEMS.getKey(stack.getItem()).toString()); - if (stack.getCount() != 1) - ret.addProperty("count", stack.getCount()); - if (stack.getTag() != null) - ret.addProperty("nbt", stack.getTag().toString()); //TODO: Better serialization? - return ret; - } - -} -*/ diff --git a/src/main/java/net/minecraftforge/common/crafting/StrictNBTIngredient.java b/src/main/java/net/minecraftforge/common/crafting/StrictNBTIngredient.java index f9d836ff4d..7cf7705503 100644 --- a/src/main/java/net/minecraftforge/common/crafting/StrictNBTIngredient.java +++ b/src/main/java/net/minecraftforge/common/crafting/StrictNBTIngredient.java @@ -4,37 +4,35 @@ */ package net.minecraftforge.common.crafting; -/* -import java.util.stream.Stream; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; +import java.util.stream.Stream; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.registries.ForgeRegistries; import org.jetbrains.annotations.Nullable; -/** Ingredient that matches the given stack, performing an exact NBT match. Use {@link PartialNBTIngredient} if you need partial match. * / -public class StrictNBTIngredient extends AbstractIngredient -{ +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +/** Ingredient that matches the given stack, performing an exact NBT match. Use {@link PartialNBTIngredient} if you need partial match. */ +public class StrictNBTIngredient extends Ingredient { + public static final Codec CODEC = RecordCodecBuilder.create(b -> b.group( + ItemStack.CODEC.fieldOf("stack").forGetter(i -> i.stack) + ).apply(b, StrictNBTIngredient::new)); + private final ItemStack stack; - protected StrictNBTIngredient(ItemStack stack) - { + protected StrictNBTIngredient(ItemStack stack) { super(Stream.of(new Ingredient.ItemValue(stack))); this.stack = stack; } - /** Creates a new ingredient matching the given stack and tag * / - public static StrictNBTIngredient of(ItemStack stack) - { + /** Creates a new ingredient matching the given stack and tag */ + public static StrictNBTIngredient of(ItemStack stack) { return new StrictNBTIngredient(stack); } @Override - public boolean test(@Nullable ItemStack input) - { + public boolean test(@Nullable ItemStack input) { if (input == null) return false; //Can't use areItemStacksEqualUsingNBTShareTag because it compares stack size as well @@ -42,47 +40,7 @@ public class StrictNBTIngredient extends AbstractIngredient } @Override - public boolean isSimple() - { + public boolean isSimple() { return false; } - - @Override - public IIngredientSerializer getSerializer() - { - return Serializer.INSTANCE; - } - - @Override - public JsonElement toJson() - { - JsonObject json = new JsonObject(); - json.addProperty("type", CraftingHelper.getID(Serializer.INSTANCE).toString()); - json.addProperty("item", ForgeRegistries.ITEMS.getKey(stack.getItem()).toString()); - json.addProperty("count", stack.getCount()); - if (stack.hasTag()) - json.addProperty("nbt", stack.getTag().toString()); - return json; - } - - public static class Serializer implements IIngredientSerializer - { - public static final Serializer INSTANCE = new Serializer(); - - @Override - public StrictNBTIngredient parse(FriendlyByteBuf buffer) { - return new StrictNBTIngredient(buffer.readItem()); - } - - @Override - public StrictNBTIngredient parse(JsonObject json) { - return new StrictNBTIngredient(CraftingHelper.getItemStack(json, true)); - } - - @Override - public void write(FriendlyByteBuf buffer, StrictNBTIngredient ingredient) { - buffer.writeItem(ingredient.stack); - } - } } -*/ diff --git a/src/main/java/net/minecraftforge/common/crafting/VanillaIngredientSerializer.java b/src/main/java/net/minecraftforge/common/crafting/VanillaIngredientSerializer.java deleted file mode 100644 index 7fe2419111..0000000000 --- a/src/main/java/net/minecraftforge/common/crafting/VanillaIngredientSerializer.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.minecraftforge.common.crafting; -/* -import java.util.stream.Stream; - -import com.google.gson.JsonObject; - -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.network.FriendlyByteBuf; - -public class VanillaIngredientSerializer implements IIngredientSerializer -{ - public static final VanillaIngredientSerializer INSTANCE = new VanillaIngredientSerializer(); - - public Ingredient parse(FriendlyByteBuf buffer) - { - return Ingredient.fromValues(Stream.generate(() -> new Ingredient.ItemValue(buffer.readItem())).limit(buffer.readVarInt())); - } - - public Ingredient parse(JsonObject json) - { - return Ingredient.fromValues(Stream.of(Ingredient.valueFromJson(json))); - } - - public void write(FriendlyByteBuf buffer, Ingredient ingredient) - { - ItemStack[] items = ingredient.getItems(); - buffer.writeVarInt(items.length); - - for (ItemStack stack : items) - buffer.writeItem(stack); - } -} -*/ diff --git a/src/main/java/net/minecraftforge/common/crafting/conditions/AndCondition.java b/src/main/java/net/minecraftforge/common/crafting/conditions/AndCondition.java index adf0ff9400..07fd147898 100644 --- a/src/main/java/net/minecraftforge/common/crafting/conditions/AndCondition.java +++ b/src/main/java/net/minecraftforge/common/crafting/conditions/AndCondition.java @@ -5,49 +5,20 @@ package net.minecraftforge.common.crafting.conditions; -import java.util.ArrayList; import java.util.List; import com.google.common.base.Joiner; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonSyntaxException; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.util.GsonHelper; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.common.crafting.CraftingHelper; - -public class AndCondition implements ICondition -{ - private static final ResourceLocation NAME = new ResourceLocation("forge", "and"); - private final ICondition[] children; - - public AndCondition(ICondition... values) - { - if (values == null || values.length == 0) - throw new IllegalArgumentException("Values must not be empty"); - - for (ICondition child : values) - { - if (child == null) - throw new IllegalArgumentException("Value must not be null"); - } - - this.children = values; - } +public record AndCondition(List children) implements ICondition { + public static final Codec CODEC = RecordCodecBuilder.create(b -> b.group( + ICondition.CODEC.listOf().fieldOf("values").forGetter(AndCondition::children) + ).apply(b, AndCondition::new)); @Override - public ResourceLocation getID() - { - return NAME; - } - - @Override - public boolean test(IContext context) - { - for (ICondition child : children) - { + public boolean test(IContext context) { + for (ICondition child : children) { if (!child.test(context)) return false; } @@ -55,41 +26,12 @@ public class AndCondition implements ICondition } @Override - public String toString() - { + public String toString() { return Joiner.on(" && ").join(children); } - public static class Serializer implements IConditionSerializer - { - public static final Serializer INSTANCE = new Serializer(); - - @Override - public void write(JsonObject json, AndCondition value) - { - JsonArray values = new JsonArray(); - for (ICondition child : value.children) - values.add(CraftingHelper.serialize(child)); - json.add("values", values); - } - - @Override - public AndCondition read(JsonObject json) - { - List children = new ArrayList<>(); - for (JsonElement j : GsonHelper.getAsJsonArray(json, "values")) - { - if (!j.isJsonObject()) - throw new JsonSyntaxException("And condition values must be an array of JsonObjects"); - children.add(CraftingHelper.getCondition(j.getAsJsonObject())); - } - return new AndCondition(children.toArray(new ICondition[children.size()])); - } - - @Override - public ResourceLocation getID() - { - return AndCondition.NAME; - } + @Override + public Codec codec() { + return CODEC; } } diff --git a/src/main/java/net/minecraftforge/common/crafting/conditions/ConditionCodec.java b/src/main/java/net/minecraftforge/common/crafting/conditions/ConditionCodec.java new file mode 100644 index 0000000000..51f311b46d --- /dev/null +++ b/src/main/java/net/minecraftforge/common/crafting/conditions/ConditionCodec.java @@ -0,0 +1,66 @@ +package net.minecraftforge.common.crafting.conditions; + +import java.util.Optional; +import java.util.function.Supplier; + +import com.mojang.datafixers.util.Pair; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.Decoder; +import com.mojang.serialization.DynamicOps; +import net.minecraft.resources.DelegatingOps; +import net.minecraftforge.common.crafting.conditions.ICondition.IContext; + +public class ConditionCodec { + public static Codec checkingDecode(Codec normal, Supplier _default) { + return checkingDecode(normal, _default, ICondition.DEFAULT_FIELD); + } + + public static Codec checkingDecode(Codec normal, Supplier _default, String key) { + return Codec.of(normal, new UnwrapDecoder<>(wrap(normal, key), _default)); + } + + public static Decoder> wrap(Decoder normal) { + return wrap(normal, ICondition.DEFAULT_FIELD); + } + + public static Decoder> wrap(Decoder normal, String key) { + return new OptionalConditionalDecoder<>(normal, key); + } + + public static IContext getContext(DynamicOps ops) { + IContext ret = null; + if (ops instanceof DelegatingOps dele) + ret = dele.getContext(ICondition.IContext.KEY); + return ret == null ? IContext.EMPTY : ret; + } + + private static record UnwrapDecoder(Decoder> normal, Supplier _default) implements Decoder { + @Override + public DataResult> decode(DynamicOps ops, T input) { + var ret = normal.decode(ops, input); + if (!ret.result().isPresent() || !ret.result().get().getFirst().isPresent()) + return ret.map(p -> p.mapFirst(e -> _default.get())); + return ret.map(p -> p.mapFirst(Optional::get)); + } + } + + private static record OptionalConditionalDecoder(Decoder normal, String key) implements Decoder> { + @Override + public DataResult, T>> decode(DynamicOps ops, T input) { + var conditionRaw = ops.get(input, key); + if (conditionRaw.error().isPresent() || !conditionRaw.result().isPresent()) + return normal.decode(ops, input).map(p -> p.mapFirst(Optional::of)); + + var conditionDecoded = ICondition.CODEC.parse(ops, conditionRaw.result().get()); + if (conditionDecoded.error().isPresent()) + return DataResult.error(() -> conditionDecoded.error().get().message()); + + var condition = conditionDecoded.result().get(); + if (condition.test(getContext(ops))) + return DataResult.success(Pair.of(Optional.empty(), null)); + + return normal.decode(ops, input).map(p -> p.mapFirst(Optional::of)); + } + } +} diff --git a/src/main/java/net/minecraftforge/common/crafting/conditions/ConditionContext.java b/src/main/java/net/minecraftforge/common/crafting/conditions/ConditionContext.java index 7cfe212368..7a4310d75e 100644 --- a/src/main/java/net/minecraftforge/common/crafting/conditions/ConditionContext.java +++ b/src/main/java/net/minecraftforge/common/crafting/conditions/ConditionContext.java @@ -6,7 +6,6 @@ package net.minecraftforge.common.crafting.conditions; import net.minecraft.core.Holder; -import net.minecraft.core.HolderSet; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; @@ -17,32 +16,27 @@ import java.util.Collections; import java.util.IdentityHashMap; import java.util.Map; -public class ConditionContext implements ICondition.IContext -{ - private final TagManager tagManager; - private Map, Map>>> loadedTags = null; +public class ConditionContext implements ICondition.IContext { + private final TagManager tagManager; + private Map, Map>>> loadedTags = null; - public ConditionContext(TagManager tagManager) - { - this.tagManager = tagManager; - } + public ConditionContext(TagManager tagManager) { + this.tagManager = tagManager; + } - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({ "unchecked", "rawtypes" }) @Override - public Map>> getAllTags(ResourceKey> registry) - { - if (loadedTags == null) - { - var tags = tagManager.getResult(); - if (tags.isEmpty()) throw new IllegalStateException("Tags have not been loaded yet."); + public Map>> getAllTags(ResourceKey> registry) { + if (loadedTags == null) { + var tags = tagManager.getResult(); + if (tags.isEmpty()) throw new IllegalStateException("Tags have not been loaded yet."); - loadedTags = new IdentityHashMap<>(); - for (var loadResult : tags) - { - Map>> map = Collections.unmodifiableMap(loadResult.tags()); - loadedTags.put(loadResult.key(), (Map) map); - } - } - return (Map) loadedTags.getOrDefault(registry, Collections.emptyMap()); - } + loadedTags = new IdentityHashMap<>(); + for (var loadResult : tags) { + var map = Collections.unmodifiableMap(loadResult.tags()); + loadedTags.put(loadResult.key(), (Map)map); + } + } + return (Map)loadedTags.getOrDefault(registry, Collections.emptyMap()); + } } diff --git a/src/main/java/net/minecraftforge/common/crafting/conditions/FalseCondition.java b/src/main/java/net/minecraftforge/common/crafting/conditions/FalseCondition.java index 2277af5c27..b003d080e3 100644 --- a/src/main/java/net/minecraftforge/common/crafting/conditions/FalseCondition.java +++ b/src/main/java/net/minecraftforge/common/crafting/conditions/FalseCondition.java @@ -5,51 +5,26 @@ package net.minecraftforge.common.crafting.conditions; -import com.google.gson.JsonObject; -import net.minecraft.resources.ResourceLocation; +import com.mojang.serialization.Codec; -public final class FalseCondition implements ICondition -{ +public final class FalseCondition implements ICondition { public static final FalseCondition INSTANCE = new FalseCondition(); - private static final ResourceLocation NAME = new ResourceLocation("forge", "false"); + public static final Codec CODEC = Codec.unit(INSTANCE).stable(); - private FalseCondition() {} + private FalseCondition() { } @Override - public ResourceLocation getID() - { - return NAME; - } - - @Override - public boolean test(IContext condition) - { + public boolean test(IContext condition) { return false; } @Override - public String toString() - { + public String toString() { return "false"; } - public static class Serializer implements IConditionSerializer - { - public static final Serializer INSTANCE = new Serializer(); - - @Override - public void write(JsonObject json, FalseCondition value) { } - - @Override - public FalseCondition read(JsonObject json) - { - return FalseCondition.INSTANCE; - } - - @Override - public ResourceLocation getID() - { - return FalseCondition.NAME; - } + @Override + public Codec codec() { + return CODEC; } } diff --git a/src/main/java/net/minecraftforge/common/crafting/conditions/ICondition.java b/src/main/java/net/minecraftforge/common/crafting/conditions/ICondition.java index 5a6f5e9946..89b8ed67bf 100644 --- a/src/main/java/net/minecraftforge/common/crafting/conditions/ICondition.java +++ b/src/main/java/net/minecraftforge/common/crafting/conditions/ICondition.java @@ -5,50 +5,46 @@ package net.minecraftforge.common.crafting.conditions; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; + import net.minecraft.core.Holder; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; -import net.minecraftforge.common.crafting.CraftingHelper; +import net.minecraft.util.ExtraCodecs; +import net.minecraftforge.registries.ForgeRegistries; import java.util.Collection; import java.util.Collections; import java.util.Map; +import java.util.Optional; import java.util.Set; +import java.util.function.Function; -public interface ICondition -{ - static boolean shouldRegisterEntry(JsonElement json) - { - if (!(json instanceof JsonObject obj) || !obj.has("forge:conditions")) - return true; - - return CraftingHelper.processConditions(obj, "forge:conditions", IContext.TAGS_INVALID); - } - - ResourceLocation getID(); +public interface ICondition { + Codec CODEC = ExtraCodecs.lazyInitializedCodec(() -> ForgeRegistries.CONDITION_SERIALIZERS.get().getCodec().dispatch(ICondition::codec, Function.identity())); + String DEFAULT_FIELD = "forge:condition"; + MapCodec> OPTIONAL_FEILD_CODEC = CODEC.optionalFieldOf(DEFAULT_FIELD); boolean test(IContext context); - interface IContext - { - IContext EMPTY = new IContext() - { + Codec codec(); + + interface IContext { + public static ResourceLocation KEY = new ResourceLocation("forge", "condition_context"); + + IContext EMPTY = new IContext() { @Override - public Map>> getAllTags(ResourceKey> registry) - { + public Map>> getAllTags(ResourceKey> registry) { return Collections.emptyMap(); } }; - IContext TAGS_INVALID = new IContext() - { + IContext TAGS_INVALID = new IContext() { @Override - public Map>> getAllTags(ResourceKey> registry) - { + public Map>> getAllTags(ResourceKey> registry) { throw new UnsupportedOperationException("Usage of tag-based conditions is not permitted in this context!"); } }; @@ -56,8 +52,7 @@ public interface ICondition /** * Return the requested tag if available, or an empty tag otherwise. */ - default Collection> getTag(TagKey key) - { + default Collection> getTag(TagKey key) { return getAllTags(key.registry()).getOrDefault(key.location(), Set.of()); } diff --git a/src/main/java/net/minecraftforge/common/crafting/conditions/IConditionBuilder.java b/src/main/java/net/minecraftforge/common/crafting/conditions/IConditionBuilder.java index 18391e8d5a..5080c8a25c 100644 --- a/src/main/java/net/minecraftforge/common/crafting/conditions/IConditionBuilder.java +++ b/src/main/java/net/minecraftforge/common/crafting/conditions/IConditionBuilder.java @@ -5,48 +5,42 @@ package net.minecraftforge.common.crafting.conditions; +import java.util.List; + +import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; -public interface IConditionBuilder -{ - default ICondition and(ICondition... values) - { - return new AndCondition(values); +public interface IConditionBuilder { + default ICondition and(ICondition... values) { + return new AndCondition(List.of(values)); } - default ICondition FALSE() - { + default ICondition FALSE() { return FalseCondition.INSTANCE; } - default ICondition TRUE() - { + default ICondition TRUE() { return TrueCondition.INSTANCE; } - default ICondition not(ICondition value) - { + default ICondition not(ICondition value) { return new NotCondition(value); } - default ICondition or(ICondition... values) - { - return new OrCondition(values); + default ICondition or(ICondition... values) { + return new OrCondition(List.of(values)); } - default ICondition itemExists(String namespace, String path) - { - return new ItemExistsCondition(namespace, path); + default ICondition itemExists(String namespace, String path) { + return new ItemExistsCondition(new ResourceLocation(namespace, path)); } - default ICondition modLoaded(String modid) - { + default ICondition modLoaded(String modid) { return new ModLoadedCondition(modid); } - default ICondition tagEmpty(TagKey tag) - { - return new TagEmptyCondition(tag.location()); + default ICondition tagEmpty(TagKey tag) { + return new TagEmptyCondition(tag); } } diff --git a/src/main/java/net/minecraftforge/common/crafting/conditions/IConditionSerializer.java b/src/main/java/net/minecraftforge/common/crafting/conditions/IConditionSerializer.java deleted file mode 100644 index 1b95445cb5..0000000000 --- a/src/main/java/net/minecraftforge/common/crafting/conditions/IConditionSerializer.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.minecraftforge.common.crafting.conditions; - -import com.google.gson.JsonObject; - -import net.minecraft.resources.ResourceLocation; - -public interface IConditionSerializer -{ - void write(JsonObject json, T value); - - T read(JsonObject json); - - ResourceLocation getID(); - - default JsonObject getJson(T value) - { - JsonObject json = new JsonObject(); - this.write(json, value); - json.addProperty("type", value.getID().toString()); - return json; - } -} diff --git a/src/main/java/net/minecraftforge/common/crafting/conditions/ItemExistsCondition.java b/src/main/java/net/minecraftforge/common/crafting/conditions/ItemExistsCondition.java index 445a5c5928..841f65724a 100644 --- a/src/main/java/net/minecraftforge/common/crafting/conditions/ItemExistsCondition.java +++ b/src/main/java/net/minecraftforge/common/crafting/conditions/ItemExistsCondition.java @@ -5,70 +5,29 @@ package net.minecraftforge.common.crafting.conditions; -import com.google.gson.JsonObject; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.util.GsonHelper; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.registries.ForgeRegistries; -public class ItemExistsCondition implements ICondition -{ - private static final ResourceLocation NAME = new ResourceLocation("forge", "item_exists"); - private final ResourceLocation item; - - public ItemExistsCondition(String location) - { - this(new ResourceLocation(location)); - } - - public ItemExistsCondition(String namespace, String path) - { - this(new ResourceLocation(namespace, path)); - } - - public ItemExistsCondition(ResourceLocation item) - { - this.item = item; - } +public record ItemExistsCondition(ResourceLocation item) implements ICondition { + public static Codec CODEC = RecordCodecBuilder.create(b -> b.group( + ResourceLocation.CODEC.fieldOf("item").forGetter(ItemExistsCondition::item) + ).apply(b, ItemExistsCondition::new)); @Override - public ResourceLocation getID() - { - return NAME; - } - - @Override - public boolean test(IContext context) - { + public boolean test(IContext context) { return ForgeRegistries.ITEMS.containsKey(item); } @Override - public String toString() - { + public String toString() { return "item_exists(\"" + item + "\")"; } - public static class Serializer implements IConditionSerializer - { - public static final Serializer INSTANCE = new Serializer(); - - @Override - public void write(JsonObject json, ItemExistsCondition value) - { - json.addProperty("item", value.item.toString()); - } - - @Override - public ItemExistsCondition read(JsonObject json) - { - return new ItemExistsCondition(new ResourceLocation(GsonHelper.getAsString(json, "item"))); - } - - @Override - public ResourceLocation getID() - { - return ItemExistsCondition.NAME; - } + @Override + public Codec codec() { + return CODEC; } } diff --git a/src/main/java/net/minecraftforge/common/crafting/conditions/ModLoadedCondition.java b/src/main/java/net/minecraftforge/common/crafting/conditions/ModLoadedCondition.java index a724213eef..c30623b14d 100644 --- a/src/main/java/net/minecraftforge/common/crafting/conditions/ModLoadedCondition.java +++ b/src/main/java/net/minecraftforge/common/crafting/conditions/ModLoadedCondition.java @@ -5,60 +5,29 @@ package net.minecraftforge.common.crafting.conditions; -import com.google.gson.JsonObject; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.util.GsonHelper; -import net.minecraft.resources.ResourceLocation; import net.minecraftforge.fml.ModList; -public class ModLoadedCondition implements ICondition -{ - private static final ResourceLocation NAME = new ResourceLocation("forge", "mod_loaded"); - private final String modid; - - public ModLoadedCondition(String modid) - { - this.modid = modid; - } +public record ModLoadedCondition(String modid) implements ICondition { + public static final Codec CODEC = RecordCodecBuilder.create(b -> b.group( + Codec.STRING.fieldOf("modid").forGetter(ModLoadedCondition::modid) + ).apply(b, ModLoadedCondition::new)); @Override - public ResourceLocation getID() - { - return NAME; - } - - @Override - public boolean test(IContext context) - { + public boolean test(IContext context) { return ModList.get().isLoaded(modid); } @Override - public String toString() - { + public String toString() { return "mod_loaded(\"" + modid + "\")"; } - public static class Serializer implements IConditionSerializer - { - public static final Serializer INSTANCE = new Serializer(); - - @Override - public void write(JsonObject json, ModLoadedCondition value) - { - json.addProperty("modid", value.modid); - } - - @Override - public ModLoadedCondition read(JsonObject json) - { - return new ModLoadedCondition(GsonHelper.getAsString(json, "modid")); - } - - @Override - public ResourceLocation getID() - { - return ModLoadedCondition.NAME; - } + @Override + public Codec codec() { + return CODEC; } + } diff --git a/src/main/java/net/minecraftforge/common/crafting/conditions/NotCondition.java b/src/main/java/net/minecraftforge/common/crafting/conditions/NotCondition.java index 4b6a90198e..a324ef6ce3 100644 --- a/src/main/java/net/minecraftforge/common/crafting/conditions/NotCondition.java +++ b/src/main/java/net/minecraftforge/common/crafting/conditions/NotCondition.java @@ -5,59 +5,26 @@ package net.minecraftforge.common.crafting.conditions; -import com.google.gson.JsonObject; -import net.minecraft.util.GsonHelper; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.common.crafting.CraftingHelper; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; -public class NotCondition implements ICondition -{ - private static final ResourceLocation NAME = new ResourceLocation("forge", "not"); - private final ICondition child; - - public NotCondition(ICondition child) - { - this.child = child; - } +public record NotCondition(ICondition child) implements ICondition { + public static Codec CODEC = RecordCodecBuilder.create(b -> b.group( + ICondition.CODEC.fieldOf("value").forGetter(NotCondition::child) + ).apply(b, NotCondition::new)); @Override - public ResourceLocation getID() - { - return NAME; - } - - @Override - public boolean test(IContext context) - { + public boolean test(IContext context) { return !child.test(context); } @Override - public String toString() - { + public String toString() { return "!" + child; } - public static class Serializer implements IConditionSerializer - { - public static final Serializer INSTANCE = new Serializer(); - - @Override - public void write(JsonObject json, NotCondition value) - { - json.add("value", CraftingHelper.serialize(value.child)); - } - - @Override - public NotCondition read(JsonObject json) - { - return new NotCondition(CraftingHelper.getCondition(GsonHelper.getAsJsonObject(json, "value"))); - } - - @Override - public ResourceLocation getID() - { - return NotCondition.NAME; - } + @Override + public Codec codec() { + return CODEC; } } diff --git a/src/main/java/net/minecraftforge/common/crafting/conditions/OrCondition.java b/src/main/java/net/minecraftforge/common/crafting/conditions/OrCondition.java index 107895f200..86a9dee36d 100644 --- a/src/main/java/net/minecraftforge/common/crafting/conditions/OrCondition.java +++ b/src/main/java/net/minecraftforge/common/crafting/conditions/OrCondition.java @@ -5,49 +5,21 @@ package net.minecraftforge.common.crafting.conditions; -import java.util.ArrayList; import java.util.List; import com.google.common.base.Joiner; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonSyntaxException; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.util.GsonHelper; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.common.crafting.CraftingHelper; +public record OrCondition(List children) implements ICondition { + public static final Codec CODEC = RecordCodecBuilder.create(b -> b.group( + ICondition.CODEC.listOf().fieldOf("values").forGetter(AndCondition::children) + ).apply(b, AndCondition::new)); -public class OrCondition implements ICondition -{ - private static final ResourceLocation NAME = new ResourceLocation("forge", "or"); - private final ICondition[] children; - - public OrCondition(ICondition... values) - { - if (values == null || values.length == 0) - throw new IllegalArgumentException("Values must not be empty"); - - for (ICondition child : values) - { - if (child == null) - throw new IllegalArgumentException("Value must not be null"); - } - - this.children = values; - } @Override - public ResourceLocation getID() - { - return NAME; - } - - @Override - public boolean test(IContext context) - { - for (ICondition child : children) - { + public boolean test(IContext context) { + for (ICondition child : children) { if (child.test(context)) return true; } @@ -56,41 +28,12 @@ public class OrCondition implements ICondition } @Override - public String toString() - { + public String toString() { return Joiner.on(" || ").join(children); } - public static class Serializer implements IConditionSerializer - { - public static final Serializer INSTANCE = new Serializer(); - - @Override - public void write(JsonObject json, OrCondition value) - { - JsonArray values = new JsonArray(); - for (ICondition child : value.children) - values.add(CraftingHelper.serialize(child)); - json.add("values", values); - } - - @Override - public OrCondition read(JsonObject json) - { - List children = new ArrayList<>(); - for (JsonElement j : GsonHelper.getAsJsonArray(json, "values")) - { - if (!j.isJsonObject()) - throw new JsonSyntaxException("Or condition values must be an array of JsonObjects"); - children.add(CraftingHelper.getCondition(j.getAsJsonObject())); - } - return new OrCondition(children.toArray(new ICondition[children.size()])); - } - - @Override - public ResourceLocation getID() - { - return OrCondition.NAME; - } + @Override + public Codec codec() { + return CODEC; } } diff --git a/src/main/java/net/minecraftforge/common/crafting/conditions/TagEmptyCondition.java b/src/main/java/net/minecraftforge/common/crafting/conditions/TagEmptyCondition.java index 1ceb158a89..a6ba226f12 100644 --- a/src/main/java/net/minecraftforge/common/crafting/conditions/TagEmptyCondition.java +++ b/src/main/java/net/minecraftforge/common/crafting/conditions/TagEmptyCondition.java @@ -5,73 +5,32 @@ package net.minecraftforge.common.crafting.conditions; -import com.google.gson.JsonObject; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; -import net.minecraft.util.GsonHelper; import net.minecraft.resources.ResourceLocation; -public class TagEmptyCondition implements ICondition -{ - private static final ResourceLocation NAME = new ResourceLocation("forge", "tag_empty"); - private final TagKey tag; +public record TagEmptyCondition(TagKey tag) implements ICondition { + public static final Codec CODEC = RecordCodecBuilder.create(b -> b.group( + ResourceLocation.CODEC.xmap(loc -> TagKey.create(Registries.ITEM, loc), TagKey::location).fieldOf("tag").forGetter(TagEmptyCondition::tag) + ).apply(b, TagEmptyCondition::new)); - public TagEmptyCondition(String location) - { - this(new ResourceLocation(location)); - } - - public TagEmptyCondition(String namespace, String path) - { - this(new ResourceLocation(namespace, path)); - } - - public TagEmptyCondition(ResourceLocation tag) - { - this.tag = TagKey.create(Registries.ITEM, tag); - } @Override - public ResourceLocation getID() - { - return NAME; - } - - @Override - public boolean test(ICondition.IContext context) - { + public boolean test(ICondition.IContext context) { return context.getTag(tag).isEmpty(); } @Override - public String toString() - { + public String toString() { return "tag_empty(\"" + tag.location() + "\")"; } - public static class Serializer implements IConditionSerializer - { - public static final Serializer INSTANCE = new Serializer(); - - @Override - public void write(JsonObject json, TagEmptyCondition value) - { - json.addProperty("tag", value.tag.location().toString()); - } - - @Override - public TagEmptyCondition read(JsonObject json) - { - return new TagEmptyCondition(new ResourceLocation(GsonHelper.getAsString(json, "tag"))); - } - - @Override - public ResourceLocation getID() - { - return TagEmptyCondition.NAME; - } + @Override + public Codec codec() { + return CODEC; } } diff --git a/src/main/java/net/minecraftforge/common/crafting/conditions/TrueCondition.java b/src/main/java/net/minecraftforge/common/crafting/conditions/TrueCondition.java index 51ae173038..0ae9a7b533 100644 --- a/src/main/java/net/minecraftforge/common/crafting/conditions/TrueCondition.java +++ b/src/main/java/net/minecraftforge/common/crafting/conditions/TrueCondition.java @@ -5,52 +5,26 @@ package net.minecraftforge.common.crafting.conditions; -import com.google.gson.JsonObject; +import com.mojang.serialization.Codec; -import net.minecraft.resources.ResourceLocation; - -public final class TrueCondition implements ICondition -{ +public final class TrueCondition implements ICondition { public static final TrueCondition INSTANCE = new TrueCondition(); - private static final ResourceLocation NAME = new ResourceLocation("forge", "true"); + public static Codec CODEC = Codec.unit(INSTANCE).stable(); private TrueCondition() {} @Override - public ResourceLocation getID() - { - return NAME; - } - - @Override - public boolean test(IContext context) - { + public boolean test(IContext context) { return true; } @Override - public String toString() - { + public String toString() { return "true"; } - public static class Serializer implements IConditionSerializer - { - public static final Serializer INSTANCE = new Serializer(); - - @Override - public void write(JsonObject json, TrueCondition value) { } - - @Override - public TrueCondition read(JsonObject json) - { - return TrueCondition.INSTANCE; - } - - @Override - public ResourceLocation getID() - { - return TrueCondition.NAME; - } + @Override + public Codec codec() { + return CODEC; } } diff --git a/src/main/java/net/minecraftforge/common/data/GlobalLootModifierProvider.java b/src/main/java/net/minecraftforge/common/data/GlobalLootModifierProvider.java index e533e77e3a..bc63f6115c 100644 --- a/src/main/java/net/minecraftforge/common/data/GlobalLootModifierProvider.java +++ b/src/main/java/net/minecraftforge/common/data/GlobalLootModifierProvider.java @@ -4,7 +4,7 @@ */ package net.minecraftforge.common.data; -/* + import com.google.common.collect.ImmutableList; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -31,7 +31,7 @@ import java.util.stream.Collectors; * Provider for forge's GlobalLootModifier system. See {@link LootModifier} * * This provider only requires implementing {@link #start()} and calling {@link #add} from it. - * / + */ public abstract class GlobalLootModifierProvider implements DataProvider { private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); @@ -48,7 +48,7 @@ public abstract class GlobalLootModifierProvider implements DataProvider /** * Sets the "replace" key in global_loot_modifiers to true. - * / + */ protected void replacing() { this.replace = true; @@ -56,7 +56,7 @@ public abstract class GlobalLootModifierProvider implements DataProvider /** * Call {@link #add} here, which will pass in the necessary information to write the jsons. - * / + */ protected abstract void start(); @Override @@ -91,7 +91,7 @@ public abstract class GlobalLootModifierProvider implements DataProvider * * @param modifier The name of the modifier, which will be the file name. * @param instance The instance to serialize - * / + */ public void add(String modifier, T instance) { JsonElement json = IGlobalLootModifier.DIRECT_CODEC.encodeStart(JsonOps.INSTANCE, instance).getOrThrow(false, s -> {}); @@ -104,4 +104,3 @@ public abstract class GlobalLootModifierProvider implements DataProvider return "Global Loot Modifiers : " + modid; } } -*/ diff --git a/src/main/java/net/minecraftforge/common/loot/CanToolPerformAction.java b/src/main/java/net/minecraftforge/common/loot/CanToolPerformAction.java index 3deec52fe6..52a0047438 100644 --- a/src/main/java/net/minecraftforge/common/loot/CanToolPerformAction.java +++ b/src/main/java/net/minecraftforge/common/loot/CanToolPerformAction.java @@ -4,11 +4,11 @@ */ package net.minecraftforge.common.loot; -/* + import com.google.common.collect.ImmutableSet; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonObject; -import com.google.gson.JsonSerializationContext; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.parameters.LootContextParam; @@ -22,46 +22,30 @@ import java.util.Set; /** * This LootItemCondition "forge:can_tool_perform_action" can be used to check if a tool can perform a given ToolAction. - * / -public class CanToolPerformAction implements LootItemCondition { + */ +public record CanToolPerformAction(ToolAction action) implements LootItemCondition { + public static final Codec CODEC = RecordCodecBuilder.create(b -> b.group( + ToolAction.CODEC.fieldOf("action").forGetter(CanToolPerformAction::action) + ).apply(b, CanToolPerformAction::new)); + public static final LootItemConditionType TYPE = new LootItemConditionType(CODEC); - public static final LootItemConditionType LOOT_CONDITION_TYPE = new LootItemConditionType(new CanToolPerformAction.Serializer()); - - final ToolAction action; - - public CanToolPerformAction(ToolAction action) { - this.action = action; + @Override + public @NotNull LootItemConditionType getType() { + return TYPE; } - @NotNull - public LootItemConditionType getType() { - return LOOT_CONDITION_TYPE; - } - - @NotNull - public Set> getReferencedContextParams() { + @Override + public @NotNull Set> getReferencedContextParams() { return ImmutableSet.of(LootContextParams.TOOL); } - public boolean test(LootContext lootContext) { - ItemStack itemstack = lootContext.getParamOrNull(LootContextParams.TOOL); + @Override + public boolean test(LootContext ctx) { + ItemStack itemstack = ctx.getParamOrNull(LootContextParams.TOOL); return itemstack != null && itemstack.canPerformAction(this.action); } public static LootItemCondition.Builder canToolPerformAction(ToolAction action) { return () -> new CanToolPerformAction(action); } - - public static class Serializer implements net.minecraft.world.level.storage.loot.Serializer { - public void serialize(JsonObject json, CanToolPerformAction itemCondition, @NotNull JsonSerializationContext context) { - json.addProperty("action", itemCondition.action.name()); - } - - @NotNull - public CanToolPerformAction deserialize(JsonObject json, @NotNull JsonDeserializationContext context) { - return new CanToolPerformAction(ToolAction.get(json.get("action").getAsString())); - } - } - -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/common/loot/IGlobalLootModifier.java b/src/main/java/net/minecraftforge/common/loot/IGlobalLootModifier.java index 12b12ea6ba..3def7a1d4f 100644 --- a/src/main/java/net/minecraftforge/common/loot/IGlobalLootModifier.java +++ b/src/main/java/net/minecraftforge/common/loot/IGlobalLootModifier.java @@ -4,11 +4,9 @@ */ package net.minecraftforge.common.loot; -/* + import com.google.gson.JsonElement; -import com.google.gson.JsonSyntaxException; import com.mojang.serialization.Codec; -import com.mojang.serialization.DataResult; import com.mojang.serialization.Dynamic; import com.mojang.serialization.JsonOps; import it.unimi.dsi.fastutil.objects.ObjectArrayList; @@ -16,9 +14,11 @@ import net.minecraft.util.ExtraCodecs; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; +import net.minecraft.world.level.storage.loot.predicates.LootItemConditions; import net.minecraftforge.registries.ForgeRegistries; import org.jetbrains.annotations.NotNull; +import java.util.List; import java.util.function.Function; /** @@ -26,46 +26,19 @@ import java.util.function.Function; * {@link LootModifier} Supplies base functionality; most modders should only need to extend that.
* Requires a {@link Codec} to be registered: {@link ForgeRegistries#GLOBAL_LOOT_MODIFIER_SERIALIZERS}, and returned in {@link #codec()} * Individual instances of modifiers must be registered via json, see forge:loot_modifiers/global_loot_modifiers - * / + */ public interface IGlobalLootModifier { Codec DIRECT_CODEC = ExtraCodecs.lazyInitializedCodec(() -> ForgeRegistries.GLOBAL_LOOT_MODIFIER_SERIALIZERS.get().getCodec()) .dispatch(IGlobalLootModifier::codec, Function.identity()); - Codec LOOT_CONDITIONS_CODEC = Codec.PASSTHROUGH.flatXmap( - d -> - { - try - { - LootItemCondition[] conditions = LootModifierManager.GSON_INSTANCE.fromJson(getJson(d), LootItemCondition[].class); - return DataResult.success(conditions); - } - catch (JsonSyntaxException e) - { - LootModifierManager.LOGGER.warn("Unable to decode loot conditions", e); - return DataResult.error(e::getMessage); - } - }, - conditions -> - { - try - { - JsonElement element = LootModifierManager.GSON_INSTANCE.toJsonTree(conditions); - return DataResult.success(new Dynamic<>(JsonOps.INSTANCE, element)); - } - catch (JsonSyntaxException e) - { - LootModifierManager.LOGGER.warn("Unable to encode loot conditions", e); - return DataResult.error(e::getMessage); - } - } - ); + Codec LOOT_CONDITIONS_CODEC = LootItemConditions.CODEC.listOf().xmap(list -> list.toArray(LootItemCondition[]::new), List::of); @SuppressWarnings("unchecked") static JsonElement getJson(Dynamic dynamic) { Dynamic typed = (Dynamic) dynamic; - return typed.getValue() instanceof JsonElement ? - (JsonElement) typed.getValue() : - typed.getOps().convertTo(JsonOps.INSTANCE, typed.getValue()); + return typed.getValue() instanceof JsonElement element ? + element : + typed.getOps().convertTo(JsonOps.INSTANCE, typed.getValue()); } /** @@ -74,13 +47,12 @@ public interface IGlobalLootModifier { * @param generatedLoot the list of ItemStacks that will be dropped, generated by loot tables * @param context the LootContext, identical to what is passed to loot tables * @return modified loot drops - * / + */ @NotNull ObjectArrayList apply(ObjectArrayList generatedLoot, LootContext context); /** * Returns the registered codec for this modifier - * / + */ Codec codec(); } -*/ diff --git a/src/main/java/net/minecraftforge/common/loot/LootModifier.java b/src/main/java/net/minecraftforge/common/loot/LootModifier.java index 3e136973c5..8f3efc79cf 100644 --- a/src/main/java/net/minecraftforge/common/loot/LootModifier.java +++ b/src/main/java/net/minecraftforge/common/loot/LootModifier.java @@ -4,7 +4,8 @@ */ package net.minecraftforge.common.loot; -/* + +import java.util.Arrays; import java.util.function.Predicate; import com.mojang.datafixers.Products; @@ -20,9 +21,8 @@ import org.jetbrains.annotations.NotNull; /** * A base implementation of a Global Loot Modifier for modders to extend. * Takes care of ILootCondition matching and comes with the base codec to extend. - * / -public abstract class LootModifier implements IGlobalLootModifier -{ + */ +public abstract class LootModifier implements IGlobalLootModifier { protected final LootItemCondition[] conditions; private final Predicate combinedConditions; @@ -35,26 +35,23 @@ public abstract class LootModifier implements IGlobalLootModifier *

* Otherwise can follow this with #and() to add more fields. * Examples: Forge Test Subclasses or {@link BendingTrunkPlacer#CODEC} - * / - protected static Products.P1, LootItemCondition[]> codecStart(RecordCodecBuilder.Instance instance) - { + */ + protected static Products.P1, LootItemCondition[]> codecStart(RecordCodecBuilder.Instance instance) { return instance.group(LOOT_CONDITIONS_CODEC.fieldOf("conditions").forGetter(lm -> lm.conditions)); } /** * Constructs a LootModifier. * @param conditionsIn the ILootConditions that need to be matched before the loot is modified. - * / - protected LootModifier(LootItemCondition[] conditionsIn) - { + */ + protected LootModifier(LootItemCondition[] conditionsIn) { this.conditions = conditionsIn; - this.combinedConditions = LootItemConditions.andConditions(conditionsIn); + this.combinedConditions = LootItemConditions.andConditions(Arrays.asList(conditionsIn)); } @NotNull @Override - public final ObjectArrayList apply(ObjectArrayList generatedLoot, LootContext context) - { + public final ObjectArrayList apply(ObjectArrayList generatedLoot, LootContext context) { return this.combinedConditions.test(context) ? this.doApply(generatedLoot, context) : generatedLoot; } @@ -64,8 +61,7 @@ public abstract class LootModifier implements IGlobalLootModifier * @param generatedLoot the list of ItemStacks that will be dropped, generated by loot tables * @param context the LootContext, identical to what is passed to loot tables * @return modified loot drops - * / + */ @NotNull protected abstract ObjectArrayList doApply(ObjectArrayList generatedLoot, LootContext context); } -*/ diff --git a/src/main/java/net/minecraftforge/common/loot/LootModifierManager.java b/src/main/java/net/minecraftforge/common/loot/LootModifierManager.java index e80737a560..edef6697e1 100644 --- a/src/main/java/net/minecraftforge/common/loot/LootModifierManager.java +++ b/src/main/java/net/minecraftforge/common/loot/LootModifierManager.java @@ -4,17 +4,10 @@ */ package net.minecraftforge.common.loot; -/* -import java.io.BufferedReader; + import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.nio.charset.StandardCharsets; import java.util.*; -import com.mojang.datafixers.util.Pair; -import com.mojang.serialization.Codec; import com.mojang.serialization.JsonOps; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -22,74 +15,73 @@ import org.apache.logging.log4j.Logger; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap.Builder; import com.google.gson.Gson; -import com.google.gson.JsonArray; +import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; import net.minecraft.util.profiling.ProfilerFiller; -import net.minecraft.server.packs.resources.Resource; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.util.GsonHelper; import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.registries.ForgeRegistries; public class LootModifierManager extends SimpleJsonResourceReloadListener { - public static final Logger LOGGER = LogManager.getLogger(); - public static final Gson GSON_INSTANCE = Deserializers.createFunctionSerializer().create(); + private static final Logger LOGGER = LogManager.getLogger(); + private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); + private static final String FOLDER = "loot_modifiers"; - private Map registeredLootModifiers = ImmutableMap.of(); - private static final String folder = "loot_modifiers"; + private Map modifiers = ImmutableMap.of(); public LootModifierManager() { - super(GSON_INSTANCE, folder); + super(GSON, FOLDER); } @Override - protected void apply(Map resourceList, ResourceManager resourceManagerIn, ProfilerFiller profilerIn) { - Builder builder = ImmutableMap.builder(); - List finalLocations = new ArrayList<>(); - ResourceLocation resourcelocation = new ResourceLocation("forge","loot_modifiers/global_loot_modifiers.json"); - //read in all data files from forge:loot_modifiers/global_loot_modifiers in order to do layering - for(Resource iresource : resourceManagerIn.getResourceStack(resourcelocation)) { - try ( InputStream inputstream = iresource.open(); - Reader reader = new BufferedReader(new InputStreamReader(inputstream, StandardCharsets.UTF_8)); - ) { - JsonObject jsonobject = GsonHelper.fromJson(GSON_INSTANCE, reader, JsonObject.class); - boolean replace = jsonobject.get("replace").getAsBoolean(); - if (replace) - finalLocations.clear(); - JsonArray entryList = jsonobject.get("entries").getAsJsonArray(); - for(JsonElement entry : entryList) { - ResourceLocation loc = new ResourceLocation(entry.getAsString()); - finalLocations.remove(loc); //remove and re-add if needed, to update the ordering. - finalLocations.add(loc); - } - } + protected Map prepare(ResourceManager resources, ProfilerFiller profilerFiller) { + var path = new ResourceLocation("forge", FOLDER + "/global_loot_modifiers.json"); - catch (RuntimeException | IOException ioexception) { - LOGGER.error("Couldn't read global loot modifier list {} in data pack {}", resourcelocation, iresource.sourcePackId(), ioexception); + List toLoad = new ArrayList<>(); + //read in all data files from forge:loot_modifiers/global_loot_modifiers in order to do layering + for (var resource : resources.getResourceStack(path)) { + try (var reader = resource.openAsReader()) { + var json = GsonHelper.fromJson(GSON, reader, JsonObject.class); + + if (GsonHelper.getAsBoolean(json, "replace", false)) + toLoad.clear(); + + for(var entry : GsonHelper.getAsJsonArray(json, "entries")) { + ResourceLocation loc = new ResourceLocation(entry.getAsString()); + toLoad.remove(loc); //remove and re-add if needed, to update the ordering. + toLoad.add(loc); + } + } catch (RuntimeException | IOException ioexception) { + LOGGER.error("Couldn't read global loot modifier list {} in data pack {}", path, resource.sourcePackId(), ioexception); } } + //use layered config to fetch modifier data files (modifiers missing from config are disabled) - for (ResourceLocation location : finalLocations) - { - JsonElement json = resourceList.get(location); + var ret = super.prepare(resources, profilerFiller); + ret.keySet().removeIf(k -> !toLoad.contains(k)); + return ret; + } + + @Override + protected void apply(Map resources, ResourceManager resourceManagerIn, ProfilerFiller profilerIn) { + Builder builder = ImmutableMap.builder(); + resources.forEach((location, json) -> { IGlobalLootModifier.DIRECT_CODEC.parse(JsonOps.INSTANCE, json) // log error if parse fails .resultOrPartial(errorMsg -> LOGGER.warn("Could not decode GlobalLootModifier with json id {} - error: {}", location, errorMsg)) // add loot modifier if parse succeeds .ifPresent(modifier -> builder.put(location, modifier)); - } - this.registeredLootModifiers = builder.build(); + }); + this.modifiers = builder.build(); } /** * An immutable collection of the registered loot modifiers in layered order. - * / + */ public Collection getAllLootMods() { - return registeredLootModifiers.values(); + return modifiers.values(); } - -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/common/loot/LootTableIdCondition.java b/src/main/java/net/minecraftforge/common/loot/LootTableIdCondition.java index 9d68402911..05802e2230 100644 --- a/src/main/java/net/minecraftforge/common/loot/LootTableIdCondition.java +++ b/src/main/java/net/minecraftforge/common/loot/LootTableIdCondition.java @@ -4,77 +4,51 @@ */ package net.minecraftforge.common.loot; -/* -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonObject; -import com.google.gson.JsonSerializationContext; -import net.minecraft.world.level.storage.loot.Serializer; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; -import net.minecraft.util.GsonHelper; import net.minecraft.resources.ResourceLocation; -public class LootTableIdCondition implements LootItemCondition -{ +public record LootTableIdCondition(ResourceLocation id) implements LootItemCondition { + public static final Codec CODEC = RecordCodecBuilder.create(b -> b.group( + ResourceLocation.CODEC.fieldOf("loot_table_id").forGetter(LootTableIdCondition::id) + ).apply(b, LootTableIdCondition::new)); + + // TODO Forge Registry at some point? - public static final LootItemConditionType LOOT_TABLE_ID = new LootItemConditionType(new LootTableIdCondition.Serializer()); + public static final LootItemConditionType TYPE = new LootItemConditionType(CODEC); public static final ResourceLocation UNKNOWN_LOOT_TABLE = new ResourceLocation("forge", "unknown_loot_table"); - private final ResourceLocation targetLootTableId; - - private LootTableIdCondition(final ResourceLocation targetLootTableId) - { - this.targetLootTableId = targetLootTableId; + @Override + public LootItemConditionType getType() { + return TYPE; } @Override - public LootItemConditionType getType() - { - return LOOT_TABLE_ID; + public boolean test(LootContext ctx) { + return ctx.getQueriedLootTableId().equals(this.id()); } - @Override - public boolean test(LootContext lootContext) - { - return lootContext.getQueriedLootTableId().equals(this.targetLootTableId); - } - - public static Builder builder(final ResourceLocation targetLootTableId) - { + public static Builder builder(final ResourceLocation targetLootTableId) { return new Builder(targetLootTableId); } - public static class Builder implements LootItemCondition.Builder - { - private final ResourceLocation targetLootTableId; + public static class Builder implements LootItemCondition.Builder { + private final ResourceLocation id; - public Builder(ResourceLocation targetLootTableId) - { - if (targetLootTableId == null) throw new IllegalArgumentException("Target loot table must not be null"); - this.targetLootTableId = targetLootTableId; + public Builder(ResourceLocation id) { + if (id == null) + throw new IllegalArgumentException("Target loot table must not be null"); + this.id = id; } @Override - public LootItemCondition build() - { - return new LootTableIdCondition(this.targetLootTableId); - } - } - - public static class Serializer implements net.minecraft.world.level.storage.loot.Serializer - { - @Override - public void serialize(JsonObject object, LootTableIdCondition instance, JsonSerializationContext ctx) - { - object.addProperty("loot_table_id", instance.targetLootTableId.toString()); - } - - @Override - public LootTableIdCondition deserialize(JsonObject object, JsonDeserializationContext ctx) - { - return new LootTableIdCondition(new ResourceLocation(GsonHelper.getAsString(object, "loot_table_id"))); + public LootItemCondition build() { + return new LootTableIdCondition(this.id); } } } -*/ \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/common/util/FakePlayer.java b/src/main/java/net/minecraftforge/common/util/FakePlayer.java index 6bdaf259c9..8c49f47416 100644 --- a/src/main/java/net/minecraftforge/common/util/FakePlayer.java +++ b/src/main/java/net/minecraftforge/common/util/FakePlayer.java @@ -15,8 +15,6 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.chat.PlayerChatMessage; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.PacketFlow; -import net.minecraft.network.protocol.common.ServerboundClientInformationPacket; -import net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket; import net.minecraft.network.protocol.game.ServerboundAcceptTeleportationPacket; import net.minecraft.network.protocol.game.ServerboundBlockEntityTagQuery; import net.minecraft.network.protocol.game.ServerboundChangeDifficultyPacket; @@ -76,7 +74,7 @@ import org.jetbrains.annotations.Nullable; /** * A basic fake server player implementation that can be used to simulate player actions. */ -@Deprecated // TODO: Re-write this whole system to be less hacky. Use until we get a good replacement. +// TODO: Re-write this whole system to be less hacky. Use until we get a good replacement. public class FakePlayer extends ServerPlayer { protected FakePlayer(ServerLevel level, GameProfile name, ClientInformation info) { super(level.getServer(), level, name, info); diff --git a/src/main/java/net/minecraftforge/common/util/FakePlayerFactory.java b/src/main/java/net/minecraftforge/common/util/FakePlayerFactory.java index f2c2bce581..79920043cc 100644 --- a/src/main/java/net/minecraftforge/common/util/FakePlayerFactory.java +++ b/src/main/java/net/minecraftforge/common/util/FakePlayerFactory.java @@ -14,17 +14,14 @@ import com.mojang.authlib.GameProfile; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.network.CommonListenerCookie; - -@Deprecated // TODO: Re-write this whole system to be less hacky. Use until we get a good replacement. -public class FakePlayerFactory -{ +// TODO: Re-write this whole system to be less hacky. Use until we get a good replacement. +public class FakePlayerFactory { private static final GameProfile MINECRAFT = new GameProfile(UUID.fromString("41C82C87-7AfB-4024-BA57-13D2C99CAE77"), "[Minecraft]"); // Map of all active fake player usernames to their entities private static final Map fakePlayers = Maps.newHashMap(); private record FakePlayerKey(ServerLevel level, GameProfile username) { } - public static FakePlayer getMinecraft(ServerLevel level) - { + public static FakePlayer getMinecraft(ServerLevel level) { return get(level, MINECRAFT); } @@ -34,14 +31,12 @@ public class FakePlayerFactory * WorldEvent.Unload and kill all references to prevent worlds staying in memory, * or call this function every time and let Forge take care of the cleanup. */ - public static FakePlayer get(ServerLevel level, GameProfile username) - { + public static FakePlayer get(ServerLevel level, GameProfile username) { FakePlayerKey key = new FakePlayerKey(level, username); return fakePlayers.computeIfAbsent(key, FakePlayerFactory::create); } - public static void unloadLevel(ServerLevel level) - { + public static void unloadLevel(ServerLevel level) { fakePlayers.entrySet().removeIf(entry -> entry.getValue().level() == level); } diff --git a/src/main/java/net/minecraftforge/event/ForgeEventFactory.java b/src/main/java/net/minecraftforge/event/ForgeEventFactory.java index 4a7750d0a2..56095ab20a 100644 --- a/src/main/java/net/minecraftforge/event/ForgeEventFactory.java +++ b/src/main/java/net/minecraftforge/event/ForgeEventFactory.java @@ -63,6 +63,7 @@ import net.minecraft.world.level.storage.loot.LootTable; import net.minecraft.server.packs.resources.PreparableReloadListener; import net.minecraft.world.level.BaseSpawner; import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.InteractionResult; import net.minecraft.core.Direction; import net.minecraft.world.InteractionHand; @@ -110,7 +111,9 @@ import net.minecraftforge.event.entity.living.LivingEntityUseItemEvent; import net.minecraftforge.event.entity.living.LivingExperienceDropEvent; import net.minecraftforge.event.entity.living.LivingHealEvent; import net.minecraftforge.event.entity.living.LivingPackSizeEvent; +import net.minecraftforge.event.entity.living.LivingSwapItemsEvent; import net.minecraftforge.event.entity.living.MobSpawnEvent; +import net.minecraftforge.event.entity.living.ShieldBlockEvent; import net.minecraftforge.event.entity.living.MobSpawnEvent.AllowDespawn; import net.minecraftforge.event.entity.living.MobSpawnEvent.PositionCheck; import net.minecraftforge.event.entity.living.MobSpawnEvent.SpawnPlacementCheck; @@ -572,11 +575,9 @@ public class ForgeEventFactory { return onProjectileImpactResult(projectile, ray) != ProjectileImpactEvent.ImpactResult.DEFAULT; } - public static LootTable loadLootTable(ResourceLocation name, LootTable table) { + public static @Nullable LootTable onLoadLootTable(ResourceLocation name, LootTable table) { var event = new LootTableLoadEvent(name, table); - if (post(event)) - return LootTable.EMPTY; - return event.getTable(); + return post(event) ? null : event.getTable(); } public static boolean canCreateFluidSource(Level level, BlockPos pos, BlockState state, boolean def) { @@ -811,4 +812,16 @@ public class ForgeEventFactory { public static void onChannelRegistrationChange(Connection connection, ChannelRegistrationChangeEvent.Type changeType, HashSet changed) { post(new ChannelRegistrationChangeEvent(connection, changeType, changed)); } + + public static LivingSwapItemsEvent.Hands onLivingSwapHandItems(LivingEntity entity) { + return fire(new LivingSwapItemsEvent.Hands(entity)); + } + + public static ShieldBlockEvent onShieldBlock(LivingEntity blocker, DamageSource source, float blocked) { + return fire(new ShieldBlockEvent(blocker, source, blocked)); + } + + public static void onEntityEnterSection(Entity entity, long packedOldPos, long packedNewPos) { + post(new EntityEvent.EnteringSection(entity, packedOldPos, packedNewPos)); + } } diff --git a/src/main/java/net/minecraftforge/registries/ForgeDeferredRegistriesSetup.java b/src/main/java/net/minecraftforge/registries/ForgeDeferredRegistriesSetup.java index f95f467317..91fdebd658 100644 --- a/src/main/java/net/minecraftforge/registries/ForgeDeferredRegistriesSetup.java +++ b/src/main/java/net/minecraftforge/registries/ForgeDeferredRegistriesSetup.java @@ -25,11 +25,12 @@ public class ForgeDeferredRegistriesSetup } ForgeRegistries.DEFERRED_ENTITY_DATA_SERIALIZERS.register(modEventBus); - //ForgeRegistries.DEFERRED_GLOBAL_LOOT_MODIFIER_SERIALIZERS.register(modEventBus); + ForgeRegistries.DEFERRED_GLOBAL_LOOT_MODIFIER_SERIALIZERS.register(modEventBus); ForgeRegistries.DEFERRED_BIOME_MODIFIER_SERIALIZERS.register(modEventBus); ForgeRegistries.DEFERRED_FLUID_TYPES.register(modEventBus); ForgeRegistries.DEFERRED_STRUCTURE_MODIFIER_SERIALIZERS.register(modEventBus); ForgeRegistries.DEFERRED_HOLDER_SET_TYPES.register(modEventBus); ForgeRegistries.DEFERRED_DISPLAY_CONTEXTS.register(modEventBus); + ForgeRegistries.DEFERRED_CONDITION_CODECS.register(modEventBus); } } diff --git a/src/main/java/net/minecraftforge/registries/ForgeRegistries.java b/src/main/java/net/minecraftforge/registries/ForgeRegistries.java index 66d10b424a..ee87775a51 100644 --- a/src/main/java/net/minecraftforge/registries/ForgeRegistries.java +++ b/src/main/java/net/minecraftforge/registries/ForgeRegistries.java @@ -43,6 +43,8 @@ import net.minecraft.world.level.levelgen.feature.Feature; import net.minecraft.world.level.levelgen.feature.foliageplacers.FoliagePlacerType; import net.minecraft.world.level.levelgen.feature.treedecorators.TreeDecoratorType; import net.minecraftforge.common.Tags; +import net.minecraftforge.common.crafting.conditions.ICondition; +import net.minecraftforge.common.loot.IGlobalLootModifier; import net.minecraftforge.common.world.BiomeModifier; import net.minecraftforge.fluids.FluidType; import net.minecraftforge.registries.holdersets.HolderSetType; @@ -104,12 +106,12 @@ public class ForgeRegistries * Use {@link Keys#ENTITY_DATA_SERIALIZERS} to create a {@link DeferredRegister}. */ public static final Supplier>> ENTITY_DATA_SERIALIZERS = DEFERRED_ENTITY_DATA_SERIALIZERS.makeRegistry(GameData::getDataSerializersRegistryBuilder); - //static final DeferredRegister> DEFERRED_GLOBAL_LOOT_MODIFIER_SERIALIZERS = DeferredRegister.create(Keys.GLOBAL_LOOT_MODIFIER_SERIALIZERS, Keys.GLOBAL_LOOT_MODIFIER_SERIALIZERS.location().getNamespace()); + static final DeferredRegister> DEFERRED_GLOBAL_LOOT_MODIFIER_SERIALIZERS = DeferredRegister.create(Keys.GLOBAL_LOOT_MODIFIER_SERIALIZERS, Keys.GLOBAL_LOOT_MODIFIER_SERIALIZERS.location().getNamespace()); /** * Calling {@link Supplier#get()} before {@link NewRegistryEvent} is fired will result in a null registry returned. * Use {@link Keys#GLOBAL_LOOT_MODIFIER_SERIALIZERS} to create a {@link DeferredRegister}. */ - //public static final Supplier>> GLOBAL_LOOT_MODIFIER_SERIALIZERS = DEFERRED_GLOBAL_LOOT_MODIFIER_SERIALIZERS.makeRegistry(GameData::getGLMSerializersRegistryBuilder); + public static final Supplier>> GLOBAL_LOOT_MODIFIER_SERIALIZERS = DEFERRED_GLOBAL_LOOT_MODIFIER_SERIALIZERS.makeRegistry(GameData::getGLMSerializersRegistryBuilder); static final DeferredRegister> DEFERRED_BIOME_MODIFIER_SERIALIZERS = DeferredRegister.create(Keys.BIOME_MODIFIER_SERIALIZERS, Keys.BIOME_MODIFIER_SERIALIZERS.location().getNamespace()); /** * Calling {@link Supplier#get()} before {@link NewRegistryEvent} is fired will result in a null registry returned. @@ -142,6 +144,13 @@ public class ForgeRegistries */ public static final Supplier> DISPLAY_CONTEXTS = DEFERRED_DISPLAY_CONTEXTS.makeRegistry(GameData::getItemDisplayContextRegistryBuilder); + static final DeferredRegister> DEFERRED_CONDITION_CODECS = DeferredRegister.create(Keys.CONDITION_SERIALIZERS, Keys.CONDITION_SERIALIZERS.location().getNamespace()); + /** + * Calling {@link Supplier#get()} before {@link NewRegistryEvent} is fired will result in a null registry returned. + * Use {@link Keys#CONDITION_SERIALIZERS} to create a {@link DeferredRegister}. + */ + public static final Supplier>> CONDITION_SERIALIZERS = DEFERRED_CONDITION_CODECS.makeRegistry(GameData::getConditionCodecRegistryBuilder); + public static final class Keys { //Vanilla public static final ResourceKey> BLOCKS = key("block"); @@ -179,12 +188,13 @@ public class ForgeRegistries // Forge public static final ResourceKey>> ENTITY_DATA_SERIALIZERS = key("forge:entity_data_serializers"); - //public static final ResourceKey>> GLOBAL_LOOT_MODIFIER_SERIALIZERS = key("forge:global_loot_modifier_serializers"); + public static final ResourceKey>> GLOBAL_LOOT_MODIFIER_SERIALIZERS = key("forge:global_loot_modifier_serializers"); public static final ResourceKey>> BIOME_MODIFIER_SERIALIZERS = key("forge:biome_modifier_serializers"); public static final ResourceKey>> STRUCTURE_MODIFIER_SERIALIZERS = key("forge:structure_modifier_serializers"); public static final ResourceKey> FLUID_TYPES = key("forge:fluid_type"); public static final ResourceKey> HOLDER_SET_TYPES = key("forge:holder_set_type"); public static final ResourceKey> DISPLAY_CONTEXTS = key("forge:display_contexts"); + public static final ResourceKey>> CONDITION_SERIALIZERS = key("forge:condition_codecs"); // Forge Dynamic public static final ResourceKey> BIOME_MODIFIERS = key("forge:biome_modifier"); @@ -207,4 +217,4 @@ public class ForgeRegistries Bootstrap.bootStrap(); Tags.init(); } -} +} \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/registries/GameData.java b/src/main/java/net/minecraftforge/registries/GameData.java index 8c3fddf442..20bdfc7578 100644 --- a/src/main/java/net/minecraftforge/registries/GameData.java +++ b/src/main/java/net/minecraftforge/registries/GameData.java @@ -50,6 +50,8 @@ import net.minecraft.world.level.material.Fluid; import net.minecraftforge.common.CreativeModeTabRegistry; import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.crafting.conditions.ICondition; +import net.minecraftforge.common.loot.IGlobalLootModifier; import net.minecraftforge.common.util.LogMessageAdapter; import net.minecraftforge.common.world.BiomeModifier; import net.minecraftforge.common.world.StructureModifier; @@ -91,6 +93,7 @@ public class GameData init(); } + @SuppressWarnings("deprecation") public static void init() { if (DISABLE_VANILLA_REGISTRIES) @@ -146,12 +149,10 @@ public class GameData return makeRegistry(Keys.ENTITY_DATA_SERIALIZERS, 256 /*vanilla space*/, MAX_VARINT).disableSaving().disableOverrides(); } - /* static RegistryBuilder> getGLMSerializersRegistryBuilder() { return makeRegistry(Keys.GLOBAL_LOOT_MODIFIER_SERIALIZERS).disableSaving().disableSync(); } - */ static RegistryBuilder> getBiomeModifierSerializersRegistryBuilder() { @@ -173,6 +174,11 @@ public class GameData return new RegistryBuilder().disableSaving().disableSync(); } + static RegistryBuilder> getConditionCodecRegistryBuilder() + { + return new RegistryBuilder>().disableSaving().disableSync(); + } + static RegistryBuilder getItemDisplayContextRegistryBuilder() { return new RegistryBuilder() @@ -232,7 +238,6 @@ public class GameData return RegistryManager.ACTIVE.getRegistry(Keys.POI_TYPES).getSlaveMap(BLOCKSTATE_TO_POINT_OF_INTEREST_TYPE, Map.class); } - @SuppressWarnings({ "unchecked", "rawtypes" }) public static void vanillaSnapshot() { LOGGER.debug(REGISTRIES, "Creating vanilla freeze snapshot"); @@ -250,13 +255,13 @@ public class GameData LOGGER.debug(REGISTRIES, "Vanilla freeze snapshot created"); } + @SuppressWarnings("deprecation") public static void unfreezeData() { LOGGER.debug(REGISTRIES, "Unfreezing vanilla registries"); BuiltInRegistries.REGISTRY.stream().filter(r -> r instanceof MappedRegistry).forEach(r -> ((MappedRegistry)r).unfreeze()); } - @SuppressWarnings({ "rawtypes", "unchecked" }) public static void freezeData() { LOGGER.debug(REGISTRIES, "Freezing registries"); @@ -286,7 +291,7 @@ public class GameData public static void revertToFrozen() { revertTo(RegistryManager.FROZEN, true); } - @SuppressWarnings({ "unchecked", "rawtypes" }) + public static void revertTo(final RegistryManager target, boolean fireEvents) { if (target.registries.isEmpty()) @@ -312,7 +317,6 @@ public class GameData LOGGER.debug(REGISTRIES, "{} state restored.", target.getName()); } - @SuppressWarnings({ "rawtypes", "unchecked" }) public static void revert(RegistryManager state, ResourceLocation registry, boolean lock) { LOGGER.debug(REGISTRIES, "Reverting {} to {}", registry, state.getName()); @@ -381,8 +385,10 @@ public class GameData this.nextId = 0; } + @SuppressWarnings("unused") void remove(I key) { + @SuppressWarnings("deprecation") Integer prev = this.tToId.remove(key); if (prev != null) { @@ -437,6 +443,7 @@ public class GameData { final ClearableObjectIntIdentityMap idMap = new ClearableObjectIntIdentityMap() { + @SuppressWarnings("deprecation") @Override public int getId(BlockState key) { @@ -527,6 +534,7 @@ public class GameData @Override public void onAdd(IForgeRegistryInternal owner, RegistryManager stage, int id, ResourceKey key, PoiType obj, @Nullable PoiType oldObj) { + @SuppressWarnings("unchecked") Map map = owner.getSlaveMap(BLOCKSTATE_TO_POINT_OF_INTEREST_TYPE, Map.class); if (oldObj != null) { @@ -595,7 +603,6 @@ public class GameData } - @SuppressWarnings({ "unchecked", "rawtypes" }) public static Multimap injectSnapshot(Map snapshot, boolean injectFrozenData, boolean isLocalWorld) { LOGGER.info(REGISTRIES, "Injecting existing registry data into this {} instance", EffectiveSide.get()); @@ -756,7 +763,6 @@ public class GameData } //Another bouncer for generic reasons - @SuppressWarnings("unchecked") private static void processMissing(ResourceLocation name, RegistryManager STAGING, MissingMappingsEvent e, Map missing, Map remaps, Collection defaulted, Collection failed, boolean injectNetworkDummies) { List> mappings = e.getAllMappings(ResourceKey.createRegistryKey(name)); diff --git a/src/test_old/java/net/minecraftforge/debug/CreativeModeTabTest.java b/src/test/java/net/minecraftforge/debug/CreativeModeTabTest.java similarity index 67% rename from src/test_old/java/net/minecraftforge/debug/CreativeModeTabTest.java rename to src/test/java/net/minecraftforge/debug/CreativeModeTabTest.java index a181ee9998..dd3d4cc821 100644 --- a/src/test_old/java/net/minecraftforge/debug/CreativeModeTabTest.java +++ b/src/test/java/net/minecraftforge/debug/CreativeModeTabTest.java @@ -26,16 +26,14 @@ import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.registries.RegisterEvent; @Mod(CreativeModeTabTest.MOD_ID) -public class CreativeModeTabTest -{ +public class CreativeModeTabTest { public static final String MOD_ID = "creative_mode_tab_test"; private static final boolean ENABLED = true; private static final ResourceKey LOGS = ResourceKey.create(Registries.CREATIVE_MODE_TAB, new ResourceLocation(MOD_ID, "logs")); private static final ResourceKey STONE = ResourceKey.create(Registries.CREATIVE_MODE_TAB, new ResourceLocation(MOD_ID, "stone")); - public CreativeModeTabTest() - { + public CreativeModeTabTest() { if (!ENABLED) return; @@ -45,49 +43,45 @@ public class CreativeModeTabTest modEventBus.addListener(CreativeModeTabTest::onCreativeModeTabBuildContents); } - private static void onCreativeModeTabRegister(RegisterEvent event) - { + private static void onCreativeModeTabRegister(RegisterEvent event) { event.register(Registries.CREATIVE_MODE_TAB, helper -> { helper.register(LOGS, CreativeModeTab.builder().icon(() -> new ItemStack(Blocks.ACACIA_LOG)) - .title(Component.literal("Logs")) - .withLabelColor(0x00FF00) - .displayItems((params, output) -> { - output.accept(new ItemStack(Blocks.ACACIA_LOG)); - output.accept(new ItemStack(Blocks.BIRCH_LOG)); - output.accept(new ItemStack(Blocks.DARK_OAK_LOG)); - output.accept(new ItemStack(Blocks.JUNGLE_LOG)); - output.accept(new ItemStack(Blocks.OAK_LOG)); - output.accept(new ItemStack(Blocks.SPRUCE_LOG)); - }) - .build()); + .title(Component.literal("Logs")) + .withLabelColor(0x00FF00) + .displayItems((params, output) -> { + output.accept(new ItemStack(Blocks.ACACIA_LOG)); + output.accept(new ItemStack(Blocks.BIRCH_LOG)); + output.accept(new ItemStack(Blocks.DARK_OAK_LOG)); + output.accept(new ItemStack(Blocks.JUNGLE_LOG)); + output.accept(new ItemStack(Blocks.OAK_LOG)); + output.accept(new ItemStack(Blocks.SPRUCE_LOG)); + }) + .build()); + helper.register(STONE, CreativeModeTab.builder().icon(() -> new ItemStack(Blocks.STONE)) - .title(Component.literal("Stone")) - .withLabelColor(0x0000FF) - .displayItems((params, output) -> { - output.accept(new ItemStack(Blocks.STONE)); - output.accept(new ItemStack(Blocks.GRANITE)); - output.accept(new ItemStack(Blocks.DIORITE)); - output.accept(new ItemStack(Blocks.ANDESITE)); - }) - .withTabsAfter(CreativeModeTabs.BUILDING_BLOCKS) - .build()); + .title(Component.literal("Stone")) + .withLabelColor(0x0000FF) + .displayItems((params, output) -> { + output.accept(new ItemStack(Blocks.STONE)); + output.accept(new ItemStack(Blocks.GRANITE)); + output.accept(new ItemStack(Blocks.DIORITE)); + output.accept(new ItemStack(Blocks.ANDESITE)); + }) + .withTabsAfter(CreativeModeTabs.BUILDING_BLOCKS) + .build()); helper.register(new ResourceLocation(MOD_ID, "colors"), CreativeModeTab.builder().title(Component.literal("Colors")) - .displayItems((params, output) -> - { - for (DyeColor color : DyeColor.values()) - { - output.accept(DyeItem.byColor(color)); - } - }) - .withTabFactory(CreativeModeColorTab::new) - .withTabsBefore(CreativeModeTabs.COLORED_BLOCKS) - .build() + .displayItems((params, output) -> { + for (DyeColor color : DyeColor.values()) + output.accept(DyeItem.byColor(color)); + }) + .withTabFactory(CreativeModeColorTab::new) + .withTabsBefore(CreativeModeTabs.COLORED_BLOCKS) + .build() ); List blocks = List.of(Blocks.GRANITE, Blocks.DIORITE, Blocks.ANDESITE, Blocks.COBBLESTONE); - for (int i = 0; i < blocks.size(); i++) - { + for (int i = 0; i < blocks.size(); i++) { Block block = blocks.get(i); helper.register(new ResourceLocation(MOD_ID, "dummy" + i), CreativeModeTab.builder() .title(Component.literal("Dummy " + i)) @@ -99,22 +93,20 @@ public class CreativeModeTabTest //final ResourceLocation custom_tabs_image = new ResourceLocation(MOD_ID, "textures/gui/container/creative_inventory/custom_tabs.png"); helper.register(new ResourceLocation(MOD_ID, "with_tabs_image"), CreativeModeTab.builder() - .title(Component.translatable("itemGroup.with_tabs_image")) - .icon(() -> new ItemStack(Blocks.BRICKS)) - .displayItems((params, output) -> output.accept(Blocks.BRICKS)) - //.withTabsImage(custom_tabs_image) - .build()); + .title(Component.translatable("itemGroup.with_tabs_image")) + .icon(() -> new ItemStack(Blocks.BRICKS)) + .displayItems((params, output) -> output.accept(Blocks.BRICKS)) + //.withTabsImage(custom_tabs_image) + .build()); }); } private static ItemStack i(ItemLike item) { return new ItemStack(item); } - private static void onCreativeModeTabBuildContents(BuildCreativeModeTabContentsEvent event) - { + private static void onCreativeModeTabBuildContents(BuildCreativeModeTabContentsEvent event) { var entries = event.getEntries(); var vis = TabVisibility.PARENT_AND_SEARCH_TABS; - if (event.getTabKey() == LOGS) - { + if (event.getTabKey() == LOGS) { entries.putAfter(i(Blocks.ACACIA_LOG), i(Blocks.STRIPPED_ACACIA_LOG), vis); entries.putAfter(i(Blocks.BIRCH_LOG), i(Blocks.STRIPPED_BIRCH_LOG), vis); entries.putAfter(i(Blocks.DARK_OAK_LOG), i(Blocks.STRIPPED_DARK_OAK_LOG), vis); @@ -123,8 +115,7 @@ public class CreativeModeTabTest entries.putAfter(i(Blocks.SPRUCE_LOG), i(Blocks.STRIPPED_SPRUCE_LOG), vis); } - if (event.getTabKey() == STONE) - { + if (event.getTabKey() == STONE) { entries.putBefore(i(Blocks.STONE), i(Blocks.SMOOTH_STONE), vis); entries.putBefore(i(Blocks.GRANITE), i(Blocks.POLISHED_GRANITE), vis); entries.putBefore(i(Blocks.DIORITE), i(Blocks.POLISHED_DIORITE), vis); @@ -132,25 +123,20 @@ public class CreativeModeTabTest } } - private static class CreativeModeColorTab extends CreativeModeTab - { + private static class CreativeModeColorTab extends CreativeModeTab { private final ItemStack[] iconItems; - public CreativeModeColorTab(CreativeModeTab.Builder builder) - { + public CreativeModeColorTab(CreativeModeTab.Builder builder) { super(builder); DyeColor[] colors = DyeColor.values(); iconItems = new ItemStack[colors.length]; for (int i = 0; i < colors.length; i++) - { iconItems[i] = new ItemStack(DyeItem.byColor(colors[i])); - } } @Override - public ItemStack getIconItem() - { + public ItemStack getIconItem() { int idx = (int)(System.currentTimeMillis() / 1200) % iconItems.length; return iconItems[idx]; } diff --git a/src/test_old/java/net/minecraftforge/debug/gameplay/loot/GlobalLootModifiersTest.java b/src/test/java/net/minecraftforge/debug/gameplay/loot/GlobalLootModifiersTest.java similarity index 63% rename from src/test_old/java/net/minecraftforge/debug/gameplay/loot/GlobalLootModifiersTest.java rename to src/test/java/net/minecraftforge/debug/gameplay/loot/GlobalLootModifiersTest.java index e73d325402..c409a712da 100644 --- a/src/test_old/java/net/minecraftforge/debug/gameplay/loot/GlobalLootModifiersTest.java +++ b/src/test/java/net/minecraftforge/debug/gameplay/loot/GlobalLootModifiersTest.java @@ -4,37 +4,34 @@ */ package net.minecraftforge.debug.gameplay.loot; -/* + import com.google.common.base.Suppliers; +import com.google.common.collect.ImmutableMap; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.minecraft.advancements.critereon.EnchantmentPredicate; import net.minecraft.advancements.critereon.ItemPredicate; import net.minecraft.advancements.critereon.MinMaxBounds; -import net.minecraft.core.registries.Registries; import net.minecraft.util.ExtraCodecs; import net.minecraft.world.level.block.Blocks; -import net.minecraft.data.DataGenerator; import net.minecraft.data.PackOutput; import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.world.item.enchantment.Enchantment.Rarity; -import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.EnchantmentCategory; +import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.SimpleContainer; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.SmeltingRecipe; +import net.minecraft.world.item.CreativeModeTab.TabVisibility; import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootParams; -import net.minecraft.world.level.storage.loot.parameters.LootContextParamSet; 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.LootTable; import net.minecraft.world.level.storage.loot.predicates.LootItemBlockStatePropertyCondition; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; import net.minecraft.world.level.storage.loot.predicates.MatchTool; @@ -45,9 +42,10 @@ import net.minecraftforge.common.loot.LootModifier; import net.minecraftforge.common.loot.LootTableIdCondition; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.registries.RegistryObject; +import net.minecraftforge.test.Empty; import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.data.event.GatherDataEvent; +import net.minecraftforge.event.BuildCreativeModeTabContentsEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.registries.DeferredRegister; @@ -62,64 +60,78 @@ public class GlobalLootModifiersTest { public static final String MODID = "global_loot_test"; public static final boolean ENABLE = true; - public GlobalLootModifiersTest() - { - if(ENABLE) - { - GLM.register(FMLJavaModLoadingContext.get().getModEventBus()); - ENCHANTS.register(FMLJavaModLoadingContext.get().getModEventBus()); - } + public GlobalLootModifiersTest() { + if (!ENABLE) + return; + + var modBus = FMLJavaModLoadingContext.get().getModEventBus(); + GLM.register(modBus); + ENCHANTS.register(modBus); + modBus.register(this); + } private static final DeferredRegister> GLM = DeferredRegister.create(ForgeRegistries.Keys.GLOBAL_LOOT_MODIFIER_SERIALIZERS, MODID); private static final DeferredRegister ENCHANTS = DeferredRegister.create(ForgeRegistries.ENCHANTMENTS, MODID); - private static final RegistryObject> DUNGEON_LOOT = GLM.register("dungeon_loot", DungeonLootEnhancerModifier.CODEC); - private static final RegistryObject> SMELTING = GLM.register("smelting", SmeltingEnchantmentModifier.CODEC); - private static final RegistryObject> WHEATSEEDS = GLM.register("wheat_harvest", WheatSeedsConverterModifier.CODEC); - private static final RegistryObject> SILKTOUCH = GLM.register("silk_touch_bamboo", SilkTouchTestModifier.CODEC); - private static final RegistryObject SMELT = ENCHANTS.register("smelt", () -> new SmelterEnchantment(Rarity.UNCOMMON, EnchantmentCategory.DIGGER, EquipmentSlot.MAINHAND)); + public static final RegistryObject> DUNGEON_LOOT = GLM.register("dungeon_loot", DungeonLootEnhancerModifier.CODEC); + public static final RegistryObject> SMELTING = GLM.register("smelting", SmeltingEnchantmentModifier.CODEC); + public static final RegistryObject> WHEATSEEDS = GLM.register("wheat_harvest", WheatSeedsConverterModifier.CODEC); + public static final RegistryObject> SILKTOUCH = GLM.register("silk_touch_bamboo", SilkTouchTestModifier.CODEC); + public static final RegistryObject SMELT = ENCHANTS.register("smelt", () -> new SmelterEnchantment(Rarity.UNCOMMON, EnchantmentCategory.DIGGER, EquipmentSlot.MAINHAND)); - @EventBusSubscriber(modid = MODID, bus = EventBusSubscriber.Bus.MOD) - public static class EventHandlers { - @SubscribeEvent - public static void runData(GatherDataEvent event) - { - if(ENABLE) - event.getGenerator().addProvider(event.includeServer(), new DataProvider(event.getGenerator().getPackOutput(), MODID)); + @SubscribeEvent + public void runData(GatherDataEvent event) { + event.getGenerator().addProvider(event.includeServer(), new DataProvider(event.getGenerator().getPackOutput(), MODID)); + } + + @SubscribeEvent + public void onCreativeModeTabBuildContents(BuildCreativeModeTabContentsEvent event) { + var entries = event.getEntries(); + var vis = TabVisibility.PARENT_AND_SEARCH_TABS; + if (event.getTabKey() == Empty.TAB) { + var smelt = new ItemStack(Items.SHEARS); + EnchantmentHelper.setEnchantments(ImmutableMap.builder().put(SMELT.get(), 1).build(), smelt); + entries.put(smelt, vis); } } - private static class DataProvider extends GlobalLootModifierProvider - { - public DataProvider(PackOutput output, String modid) - { + private static class DataProvider extends GlobalLootModifierProvider { + public DataProvider(PackOutput output, String modid) { super(output, modid); } @Override - protected void start() - { + protected void start() { add("smelting", new SmeltingEnchantmentModifier( - new LootItemCondition[]{ - MatchTool.toolMatches( - ItemPredicate.Builder.item().hasEnchantment( - new EnchantmentPredicate(SMELT.get(), MinMaxBounds.Ints.atLeast(1)))) - .build() - }) + new LootItemCondition[]{ + MatchTool.toolMatches( + ItemPredicate.Builder.item().hasEnchantment( + new EnchantmentPredicate(SMELT.get(), MinMaxBounds.Ints.atLeast(1)) + ) + ).build() + }) ); add("wheat_harvest", new WheatSeedsConverterModifier( - new LootItemCondition[] { - MatchTool.toolMatches(ItemPredicate.Builder.item().of(Items.SHEARS)).build(), - LootItemBlockStatePropertyCondition.hasBlockStateProperties(Blocks.WHEAT).build() - }, - 3, Items.WHEAT_SEEDS, Items.WHEAT) + new LootItemCondition[] { + MatchTool.toolMatches(ItemPredicate.Builder.item().of(Items.SHEARS)).build(), + LootItemBlockStatePropertyCondition.hasBlockStateProperties(Blocks.WHEAT).build() + }, + 3, Items.WHEAT_SEEDS, Items.WHEAT) ); add("dungeon_loot", new DungeonLootEnhancerModifier( - new LootItemCondition[] { LootTableIdCondition.builder(new ResourceLocation("chests/simple_dungeon")).build() }, - 2) + new LootItemCondition[] { + LootTableIdCondition.builder(new ResourceLocation("chests/simple_dungeon")).build() + }, 2) + ); + + // Bamboo silk harvests everything + add("bamboo_silk", new SilkTouchTestModifier( + new LootItemCondition[] { + MatchTool.toolMatches(ItemPredicate.Builder.item().of(Items.BAMBOO)).build() + }) ); } } @@ -132,10 +144,14 @@ public class GlobalLootModifiersTest { /** * The smelting enchantment causes this modifier to be invoked, via the smelting loot_modifier json - * - * / + */ private static class SmeltingEnchantmentModifier extends LootModifier { - public static final Supplier> CODEC = Suppliers.memoize(() -> RecordCodecBuilder.create(inst -> codecStart(inst).apply(inst, SmeltingEnchantmentModifier::new))); + public static final Supplier> CODEC = Suppliers.memoize(() -> + RecordCodecBuilder.create(inst -> + codecStart(inst) + .apply(inst, SmeltingEnchantmentModifier::new) + ) + ); public SmeltingEnchantmentModifier(LootItemCondition[] conditionsIn) { super(conditionsIn); @@ -144,8 +160,8 @@ public class GlobalLootModifiersTest { @NotNull @Override public ObjectArrayList doApply(ObjectArrayList generatedLoot, LootContext context) { - ObjectArrayList ret = new ObjectArrayList(); - generatedLoot.forEach((stack) -> ret.add(smelt(stack, context))); + var ret = new ObjectArrayList(); + generatedLoot.forEach(stack -> ret.add(smelt(stack, context))); return ret; } @@ -170,9 +186,14 @@ public class GlobalLootModifiersTest { /** * When harvesting blocks with bamboo, this modifier is invoked, via the silk_touch_bamboo loot_modifier json * - * / + */ private static class SilkTouchTestModifier extends LootModifier { - public static final Supplier> CODEC = Suppliers.memoize(() -> RecordCodecBuilder.create(inst -> codecStart(inst).apply(inst, SilkTouchTestModifier::new))); + public static final Supplier> CODEC = Suppliers.memoize(() -> + RecordCodecBuilder.create(inst -> + codecStart(inst) + .apply(inst, SilkTouchTestModifier::new) + ) + ); public SilkTouchTestModifier(LootItemCondition[] conditionsIn) { super(conditionsIn); @@ -181,15 +202,18 @@ public class GlobalLootModifiersTest { @NotNull @Override public ObjectArrayList doApply(ObjectArrayList generatedLoot, LootContext context) { - ItemStack ctxTool = context.getParamOrNull(LootContextParams.TOOL); + var ctxTool = context.getParamOrNull(LootContextParams.TOOL); //return early if silk-touch is already applied (otherwise we'll get stuck in an infinite loop). - if(ctxTool == null || EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, ctxTool) > 0) return generatedLoot; - ItemStack fakeTool = ctxTool.copy(); + if (ctxTool == null || ctxTool.getEnchantmentLevel(Enchantments.SILK_TOUCH) > 0) return generatedLoot; + var fakeTool = ctxTool.copy(); fakeTool.enchant(Enchantments.SILK_TOUCH, 1); - LootParams.Builder builder = new LootParams.Builder(context.getLevel()); - builder.withParameter(LootContextParams.TOOL, fakeTool); - LootTable loottable = context.getLevel().getServer().getLootData().getLootTable(context.getParamOrNull(LootContextParams.BLOCK_STATE).getBlock().getLootTable()); - return loottable.getRandomItems(builder.create(LootContextParamSets.EMPTY)); // TODO - porting: we need an AT + var params = new LootParams.Builder(context.getLevel()) + .withParameter(LootContextParams.TOOL, fakeTool) + .create(LootContextParamSets.EMPTY); + + return context.getLevel().getServer().getLootData() + .getLootTable(context.getParamOrNull(LootContextParams.BLOCK_STATE).getBlock().getLootTable()) + .getRandomItems(params); } @Override @@ -202,14 +226,14 @@ public class GlobalLootModifiersTest { * When harvesting wheat with shears, this modifier is invoked via the wheat_harvest loot_modifier json
* This modifier checks how many seeds were harvested and turns X seeds into Y wheat (3:1) * - * / + */ private static class WheatSeedsConverterModifier extends LootModifier { public static final Supplier> CODEC = Suppliers.memoize(() -> RecordCodecBuilder.create(inst -> codecStart(inst).and( - inst.group( - Codec.INT.fieldOf("numSeeds").forGetter(m -> m.numSeedsToConvert), - ForgeRegistries.ITEMS.getCodec().fieldOf("seedItem").forGetter(m -> m.itemToCheck), - ForgeRegistries.ITEMS.getCodec().fieldOf("replacement").forGetter(m -> m.itemReward) - )).apply(inst, WheatSeedsConverterModifier::new) + inst.group( + Codec.INT.fieldOf("numSeeds").forGetter(m -> m.numSeedsToConvert), + ForgeRegistries.ITEMS.getCodec().fieldOf("seedItem").forGetter(m -> m.itemToCheck), + ForgeRegistries.ITEMS.getCodec().fieldOf("replacement").forGetter(m -> m.itemReward) + )).apply(inst, WheatSeedsConverterModifier::new) )); private final int numSeedsToConvert; @@ -252,8 +276,8 @@ public class GlobalLootModifiersTest { private static class DungeonLootEnhancerModifier extends LootModifier { public static final Supplier> CODEC = Suppliers.memoize(() -> RecordCodecBuilder.create(inst -> codecStart(inst) - .and(ExtraCodecs.POSITIVE_INT.optionalFieldOf("multiplication_factor", 2).forGetter(m -> m.multiplicationFactor)) - .apply(inst, DungeonLootEnhancerModifier::new) + .and(ExtraCodecs.POSITIVE_INT.optionalFieldOf("multiplication_factor", 2).forGetter(m -> m.multiplicationFactor)) + .apply(inst, DungeonLootEnhancerModifier::new) )); private final int multiplicationFactor; @@ -266,9 +290,9 @@ public class GlobalLootModifiersTest { @Override protected ObjectArrayList doApply(ObjectArrayList generatedLoot, LootContext context) { return generatedLoot.stream() - .map(ItemStack::copy) - .peek(stack -> stack.setCount(Math.min(stack.getMaxStackSize(), stack.getCount() * this.multiplicationFactor))) - .collect(Collectors.toCollection(ObjectArrayList::new)); + .map(ItemStack::copy) + .peek(stack -> stack.setCount(Math.min(stack.getMaxStackSize(), stack.getCount() * this.multiplicationFactor))) + .collect(Collectors.toCollection(ObjectArrayList::new)); } @Override @@ -276,5 +300,4 @@ public class GlobalLootModifiersTest { return CODEC.get(); } } -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/src/test/java/net/minecraftforge/test/Empty.java b/src/test/java/net/minecraftforge/test/Empty.java index 8e10b08e3d..4aacb2d78f 100644 --- a/src/test/java/net/minecraftforge/test/Empty.java +++ b/src/test/java/net/minecraftforge/test/Empty.java @@ -5,10 +5,59 @@ package net.minecraftforge.test; -import net.minecraftforge.fml.common.Mod; +import java.util.Optional; -/* Empty test mod to make FML happy if there are no others */ -@Mod("empty") +import net.minecraft.DetectedVersion; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.metadata.PackMetadataGenerator; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.PackType; +import net.minecraft.server.packs.metadata.pack.PackMetadataSection; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraftforge.data.event.GatherDataEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.registries.RegisterEvent; + +/* A place where I can put common utility stuff for now. Until I re-write the test codebase. */ +@Mod(Empty.MOD_ID) public class Empty { - + public static final String MOD_ID = "empty"; + public static final ResourceKey TAB = ResourceKey.create(Registries.CREATIVE_MODE_TAB, new ResourceLocation(MOD_ID, "test_items")); + + public Empty() { + var modBus = FMLJavaModLoadingContext.get().getModEventBus(); + modBus.register(this); + } + + @SubscribeEvent + public void onRegister(RegisterEvent event) { + event.register(Registries.CREATIVE_MODE_TAB, h -> { + h.register(TAB, CreativeModeTab.builder() + .icon(() -> new ItemStack(Items.STICK)) + .title(Component.literal("Test Items")) + .build() + ); + }); + } + + @SubscribeEvent + public void onDataGen(GatherDataEvent event) { + var gen = event.getGenerator(); + var packOutput = gen.getPackOutput(); + + gen.addProvider(true, new PackMetadataGenerator(packOutput) + .add(PackMetadataSection.TYPE, new PackMetadataSection( + Component.literal("Forge tests resource pack"), + DetectedVersion.BUILT_IN.getPackVersion(PackType.CLIENT_RESOURCES), + Optional.empty() + //Arrays.stream(PackType.values()).collect(Collectors.toMap(Function.identity(), DetectedVersion.BUILT_IN::getPackVersion)) + )) + ); + } } diff --git a/src/test/resources/META-INF/mods.toml b/src/test/resources/META-INF/mods.toml index e421c88e14..56730474a7 100644 --- a/src/test/resources/META-INF/mods.toml +++ b/src/test/resources/META-INF/mods.toml @@ -3,4 +3,18 @@ loaderVersion="[28,)" license="LGPL v2.1" [[mods]] -modId="empty" \ No newline at end of file +modId="empty" + +[[mods]] +modId="creative_mode_tab_test" + + + +[[mods]] +modId="global_loot_test" +[[dependencies.global_loot_test]] +modId="forge" +mandatory=true +versionRange="[1,)" +ordering="AFTER" +side="BOTH" diff --git a/src/test_old/java/net/minecraftforge/debug/DataGeneratorTest.java b/src/test_old/java/net/minecraftforge/debug/DataGeneratorTest.java index 9d9937e3a6..1e90131105 100644 --- a/src/test_old/java/net/minecraftforge/debug/DataGeneratorTest.java +++ b/src/test_old/java/net/minecraftforge/debug/DataGeneratorTest.java @@ -4,13 +4,12 @@ */ package net.minecraftforge.debug; -/* + import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.math.BigDecimal; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; @@ -22,7 +21,6 @@ import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; -import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; @@ -30,25 +28,23 @@ import java.util.stream.Stream; import com.google.gson.JsonNull; import com.google.gson.JsonPrimitive; import net.minecraft.DetectedVersion; -import net.minecraft.Util; import net.minecraft.advancements.critereon.InventoryChangeTrigger; -import net.minecraft.core.*; +import net.minecraft.core.Direction; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderGetter; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.RegistrySetBuilder; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.registries.Registries; import net.minecraft.data.CachedOutput; import net.minecraft.data.PackOutput; import net.minecraft.data.metadata.PackMetadataGenerator; -import net.minecraft.data.recipes.*; import net.minecraft.data.worldgen.BootstapContext; -import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceKey; import net.minecraft.server.packs.metadata.pack.PackMetadataSection; import net.minecraft.sounds.SoundEvents; -import net.minecraft.tags.ItemTags; import net.minecraft.world.item.ItemDisplayContext; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.TheEndBiomeSource; import net.minecraft.world.level.block.ButtonBlock; @@ -61,11 +57,6 @@ import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; -import net.minecraftforge.common.crafting.CompoundIngredient; -import net.minecraftforge.common.crafting.PartialNBTIngredient; -import net.minecraftforge.common.crafting.DifferenceIngredient; -import net.minecraftforge.common.crafting.IntersectionIngredient; -import net.minecraftforge.common.crafting.StrictNBTIngredient; import net.minecraftforge.common.data.*; import net.minecraftforge.registries.ForgeRegistries; import org.apache.commons.lang3.tuple.Triple; @@ -85,7 +76,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import net.minecraft.advancements.Advancement; -import net.minecraft.advancements.AdvancementRewards; +import net.minecraft.advancements.AdvancementHolder; import net.minecraft.advancements.FrameType; import net.minecraft.client.renderer.block.model.ItemTransforms; import net.minecraft.client.renderer.block.model.ItemTransform; @@ -108,9 +99,6 @@ import net.minecraftforge.client.model.generators.ModelFile; import net.minecraftforge.client.model.generators.ModelFile.UncheckedModelFile; import net.minecraftforge.client.model.generators.MultiPartBlockStateBuilder; import net.minecraftforge.client.model.generators.VariantBlockStateBuilder; -import net.minecraftforge.common.crafting.ConditionalAdvancement; -import net.minecraftforge.common.crafting.ConditionalRecipe; -import net.minecraftforge.common.crafting.conditions.IConditionBuilder; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus; @@ -130,8 +118,7 @@ import net.minecraft.world.level.block.TrapDoorBlock; @SuppressWarnings("deprecation") @Mod(DataGeneratorTest.MODID) @Mod.EventBusSubscriber(bus = Bus.MOD) -public class DataGeneratorTest -{ +public class DataGeneratorTest { static final String MODID = "data_gen_test"; private static Gson GSON = null; @@ -144,24 +131,24 @@ public class DataGeneratorTest .add(Registries.LEVEL_STEM, DataGeneratorTest::levelStem); @SubscribeEvent - public static void gatherData(GatherDataEvent event) - { + public static void gatherData(GatherDataEvent event) { GSON = new GsonBuilder() - .registerTypeAdapter(Variant.class, new Variant.Deserializer()) - .registerTypeAdapter(ItemTransforms.class, new ItemTransforms.Deserializer()) - .registerTypeAdapter(ItemTransform.class, new ItemTransform.Deserializer()) - .create(); + .registerTypeAdapter(Variant.class, new Variant.Deserializer()) + .registerTypeAdapter(ItemTransforms.class, new ItemTransforms.Deserializer()) + .registerTypeAdapter(ItemTransform.class, new ItemTransform.Deserializer()) + .create(); DataGenerator gen = event.getGenerator(); PackOutput packOutput = gen.getPackOutput(); CompletableFuture lookupProvider = event.getLookupProvider(); gen.addProvider(true, new PackMetadataGenerator(packOutput) - .add(PackMetadataSection.TYPE, new PackMetadataSection( - Component.literal("Forge tests resource pack"), - DetectedVersion.BUILT_IN.getPackVersion(PackType.CLIENT_RESOURCES), - Arrays.stream(PackType.values()).collect(Collectors.toMap(Function.identity(), DetectedVersion.BUILT_IN::getPackVersion)) - )) + .add(PackMetadataSection.TYPE, new PackMetadataSection( + Component.literal("Forge tests resource pack"), + DetectedVersion.BUILT_IN.getPackVersion(PackType.CLIENT_RESOURCES), + Optional.empty() + //Arrays.stream(PackType.values()).collect(Collectors.toMap(Function.identity(), DetectedVersion.BUILT_IN::getPackVersion)) + )) ); gen.addProvider(event.includeClient(), new Lang(packOutput)); // Let blockstate provider see generated item models by passing its existing file helper @@ -171,7 +158,7 @@ public class DataGeneratorTest gen.addProvider(event.includeClient(), new SoundDefinitions(packOutput, event.getExistingFileHelper())); gen.addProvider(event.includeClient(), new ParticleDescriptions(packOutput, event.getExistingFileHelper())); - gen.addProvider(event.includeServer(), new Recipes(packOutput)); + //gen.addProvider(event.includeServer(), new Recipes(packOutput)); gen.addProvider(event.includeServer(), new Tags(packOutput, lookupProvider, event.getExistingFileHelper())); gen.addProvider(event.includeServer(), new ForgeAdvancementProvider(packOutput, lookupProvider, event.getExistingFileHelper(), List.of(new Advancements()))); gen.addProvider(event.includeServer(), new DatapackBuiltinEntriesProvider(packOutput, lookupProvider, BUILDER, Set.of(MODID))); @@ -187,6 +174,7 @@ public class DataGeneratorTest context.register(TEST_LEVEL_STEM, levelStem); } + /* public static class Recipes extends RecipeProvider implements IConditionBuilder { public Recipes(PackOutput gen) @@ -367,6 +355,7 @@ public class DataGeneratorTest .save(consumer, new ResourceLocation("data_gen_test", "compound_ingredient_custom_types")); } } + */ public static class SoundDefinitions extends SoundDefinitionsProvider { @@ -1059,12 +1048,9 @@ public class DataGeneratorTest } } - private static class Advancements implements ForgeAdvancementProvider.AdvancementGenerator - { - + private static class Advancements implements ForgeAdvancementProvider.AdvancementGenerator { @Override - public void generate(HolderLookup.Provider registries, Consumer saver, ExistingFileHelper existingFileHelper) - { + public void generate(HolderLookup.Provider registries, Consumer saver, ExistingFileHelper existingFileHelper) { Advancement.Builder.advancement().display(Items.DIRT, Component.translatable(Items.DIRT.getDescriptionId()), Component.translatable("dirt_description"), @@ -1074,7 +1060,7 @@ public class DataGeneratorTest true, false) .addCriterion("has_dirt", InventoryChangeTrigger.TriggerInstance.hasItems(Items.DIRT)) - .save(saver, new ResourceLocation(MODID, "obtain_dirt"), existingFileHelper); + .save(saver, new ResourceLocation(MODID, "obtain_dirt")); Advancement.Builder.advancement().display(Items.DIAMOND_BLOCK, Component.translatable(Items.DIAMOND_BLOCK.getDescriptionId()), @@ -1085,7 +1071,7 @@ public class DataGeneratorTest true, false) .addCriterion("obtained_diamond_block", InventoryChangeTrigger.TriggerInstance.hasItems(Items.DIAMOND_BLOCK)) - .save(saver, new ResourceLocation("obtain_diamond_block"), existingFileHelper); + .save(saver, new ResourceLocation("obtain_diamond_block")); Advancement.Builder.advancement() .display(Blocks.GRASS_BLOCK, @@ -1097,7 +1083,7 @@ public class DataGeneratorTest false, false) .addCriterion("crafting_table", InventoryChangeTrigger.TriggerInstance.hasItems(Blocks.CRAFTING_TABLE)) - .save(saver, new ResourceLocation("story/root"), existingFileHelper); + .save(saver, new ResourceLocation("story/root")); // This should cause an error because of the parent not existing /* Advancement.Builder.advancement().display(Blocks.COBBLESTONE, @@ -1111,7 +1097,7 @@ public class DataGeneratorTest .addCriterion("get_cobbleStone", InventoryChangeTrigger.Instance.hasItems(Items.COBBLESTONE)) .parent(new ResourceLocation("not_there/not_here")) .save(consumer, new ResourceLocation("illegal_parent"), fileHelper); -* / +*/ Advancement.Builder.advancement().display(Blocks.COBBLESTONE, Component.translatable(Items.COBBLESTONE.getDescriptionId()), @@ -1123,7 +1109,7 @@ public class DataGeneratorTest false) .addCriterion("get_cobbleStone", InventoryChangeTrigger.TriggerInstance.hasItems(Items.COBBLESTONE)) .parent(new ResourceLocation("forge", "dummy_parent")) - .save(saver, new ResourceLocation("good_parent"), existingFileHelper); + .save(saver, new ResourceLocation("good_parent")); } } @@ -1266,4 +1252,3 @@ public class DataGeneratorTest return model.replaceAll("^\\w+:", "minecraft:"); } } -*/ diff --git a/src/test_old/java/net/minecraftforge/debug/fluid/NewFluidTest.java b/src/test_old/java/net/minecraftforge/debug/fluid/NewFluidTest.java index aad2b68f6c..c084053b14 100644 --- a/src/test_old/java/net/minecraftforge/debug/fluid/NewFluidTest.java +++ b/src/test_old/java/net/minecraftforge/debug/fluid/NewFluidTest.java @@ -4,7 +4,8 @@ */ package net.minecraftforge.debug.fluid; -/* + +import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.*; import net.minecraft.world.level.material.MapColor; import net.minecraft.world.level.material.FluidState; @@ -59,41 +60,33 @@ public class NewFluidTest { public static final DeferredRegister FLUID_TYPES = DeferredRegister.create(ForgeRegistries.Keys.FLUID_TYPES, MODID); public static final DeferredRegister FLUIDS = DeferredRegister.create(ForgeRegistries.FLUIDS, MODID); - private static ForgeFlowingFluid.Properties makeProperties() - { + private static ForgeFlowingFluid.Properties makeProperties() { return new ForgeFlowingFluid.Properties(test_fluid_type, test_fluid, test_fluid_flowing) .bucket(TEST_FLUID_BUCKET).block(test_fluid_block); } - public static RegistryObject test_fluid_type = FLUID_TYPES.register("test_fluid", () -> new FluidType(FluidType.Properties.create()) - { + public static RegistryObject test_fluid_type = FLUID_TYPES.register("test_fluid", () -> new FluidType(FluidType.Properties.create()) { @Override - public void initializeClient(Consumer consumer) - { - consumer.accept(new IClientFluidTypeExtensions() - { + public void initializeClient(Consumer consumer) { + consumer.accept(new IClientFluidTypeExtensions() { @Override - public ResourceLocation getStillTexture() - { + public ResourceLocation getStillTexture() { return FLUID_STILL; } @Override - public ResourceLocation getFlowingTexture() - { + public ResourceLocation getFlowingTexture() { return FLUID_FLOWING; } @Nullable @Override - public ResourceLocation getOverlayTexture() - { + public ResourceLocation getOverlayTexture() { return FLUID_OVERLAY; } @Override - public int getTintColor() - { + public int getTintColor() { return 0x3F1080FF; } }); @@ -122,10 +115,8 @@ public class NewFluidTest { new BlockItem(fluidloggable_block.get(), new Item.Properties()) ); - public NewFluidTest() - { - if (ENABLE) - { + public NewFluidTest() { + if (ENABLE) { IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); modEventBus.addListener(this::loadComplete); @@ -138,17 +129,14 @@ public class NewFluidTest { } } - private void addCreative(BuildCreativeModeTabContentsEvent event) - { - if (event.getTabKey() == CreativeModeTabs.INGREDIENTS) - { + private void addCreative(BuildCreativeModeTabContentsEvent event) { + if (event.getTabKey() == CreativeModeTabs.INGREDIENTS) { event.accept(FLUID_LOGGABLE_BLOCK_ITEM); event.accept(TEST_FLUID_BUCKET); } } - public void loadComplete(FMLLoadCompleteEvent event) - { + public void loadComplete(FMLLoadCompleteEvent event) { // some sanity checks BlockState state = Fluids.WATER.defaultFluidState().createLegacyBlock(); BlockState state2 = Fluids.WATER.getFluidType().getBlockForFluidState(null,null,Fluids.WATER.defaultFluidState()); @@ -159,30 +147,27 @@ public class NewFluidTest { } // WARNING: this doesn't allow "any fluid", only the fluid from this test mod! - private static class FluidloggableBlock extends Block implements SimpleWaterloggedBlock - { + private static class FluidloggableBlock extends Block implements SimpleWaterloggedBlock { public static final BooleanProperty FLUIDLOGGED = BooleanProperty.create("fluidlogged"); - public FluidloggableBlock(Properties properties) - { + public FluidloggableBlock(Properties properties) { super(properties); registerDefaultState(getStateDefinition().any().setValue(FLUIDLOGGED, false)); } @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) - { + protected void createBlockStateDefinition(StateDefinition.Builder builder) { builder.add(FLUIDLOGGED); } @Override - public boolean canPlaceLiquid(BlockGetter worldIn, BlockPos pos, BlockState state, Fluid fluidIn) { + public boolean canPlaceLiquid(@Nullable Player player, BlockGetter worldIn, BlockPos pos, BlockState state, Fluid fluidIn) { return !state.getValue(FLUIDLOGGED) && fluidIn == test_fluid.get(); } @Override public boolean placeLiquid(LevelAccessor worldIn, BlockPos pos, BlockState state, FluidState fluidStateIn) { - if (canPlaceLiquid(worldIn, pos, state, fluidStateIn.getType())) { + if (canPlaceLiquid(null, worldIn, pos, state, fluidStateIn.getType())) { if (!worldIn.isClientSide()) { worldIn.setBlock(pos, state.setValue(FLUIDLOGGED, true), 3); worldIn.scheduleTick(pos, fluidStateIn.getType(), fluidStateIn.getType().getTickDelay(worldIn)); @@ -195,7 +180,7 @@ public class NewFluidTest { } @Override - public ItemStack pickupBlock(LevelAccessor worldIn, BlockPos pos, BlockState state) { + public ItemStack pickupBlock(@Nullable Player player, LevelAccessor worldIn, BlockPos pos, BlockState state) { if (state.getValue(FLUIDLOGGED)) { worldIn.setBlock(pos, state.setValue(FLUIDLOGGED, false), 3); return new ItemStack(TEST_FLUID_BUCKET.get()); @@ -208,5 +193,4 @@ public class NewFluidTest { return state.getValue(FLUIDLOGGED) ? test_fluid.get().defaultFluidState() : Fluids.EMPTY.defaultFluidState(); } } -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/src/test_old/java/net/minecraftforge/debug/gameplay/loot/package-info.java b/src/test_old/java/net/minecraftforge/debug/gameplay/loot/package-info.java deleted file mode 100644 index 4436a52f7b..0000000000 --- a/src/test_old/java/net/minecraftforge/debug/gameplay/loot/package-info.java +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault -package net.minecraftforge.debug.gameplay.loot; - -import javax.annotation.ParametersAreNonnullByDefault; -import net.minecraft.MethodsReturnNonnullByDefault; diff --git a/src/test_old/resources/META-INF/mods.toml b/src/test_old/resources/META-INF/mods.toml index 387a30d4b2..cab937fdf0 100644 --- a/src/test_old/resources/META-INF/mods.toml +++ b/src/test_old/resources/META-INF/mods.toml @@ -98,14 +98,6 @@ modId="trsr_transformer_test" [[mods]] modId="nameplate_render_test" [[mods]] -modId="global_loot_test" -[[dependencies.global_loot_test]] -modId="forge" -mandatory=true -versionRange="[1,)" -ordering="AFTER" -side="BOTH" -[[mods]] modId="custom_plant_type_test" [[mods]] modId="chunk_data_event_save_null_world_test" @@ -292,8 +284,6 @@ modId="grindstone_event_test" [[mods]] modId="data_pack_registries_test" [[mods]] -modId="creative_mode_tab_test" -[[mods]] modId="render_level_stages_test" [[mods]] modId="trade_with_villager_event_test"