Switch away from Forge's loot modifiers

We switched to Forge's loot modifier system in the 1.20 update, as
LootTable.addPool had been removed. Turns out this was by accident, and
so we switch back to the previous implementation, as it's much simpler
and efficient.
This commit is contained in:
Jonathan Coates 2023-07-07 10:18:16 +01:00
parent a98f3b2a4c
commit 915b6f9d81
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
11 changed files with 24 additions and 143 deletions

View File

@ -9,7 +9,7 @@
# Remember to update corresponding versions in fabric.mod.json/mods.toml
fabric-api = "0.83.1+1.20.1"
fabric-loader = "0.14.21"
forge = "47.0.1"
forge = "47.1.0"
forgeSpi = "6.0.0"
mixin = "0.8.5"
parchment = "2023.03.12"

View File

@ -23,7 +23,11 @@
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.storage.loot.BuiltInLootTables;
import net.minecraft.world.level.storage.loot.LootPool;
import net.minecraft.world.level.storage.loot.entries.LootTableReference;
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
import javax.annotation.Nullable;
import java.util.Set;
import java.util.function.BiConsumer;
@ -71,7 +75,7 @@ public static void onChunkWatch(LevelChunk chunk, ServerPlayer player) {
public static final ResourceLocation TREASURE_DISK_LOOT = new ResourceLocation(ComputerCraftAPI.MOD_ID, "treasure_disk");
public static final Set<ResourceLocation> TREASURE_DISK_LOOT_TABLES = Set.of(
private static final Set<ResourceLocation> TREASURE_DISK_LOOT_TABLES = Set.of(
BuiltInLootTables.SIMPLE_DUNGEON,
BuiltInLootTables.ABANDONED_MINESHAFT,
BuiltInLootTables.STRONGHOLD_CORRIDOR,
@ -84,6 +88,16 @@ public static void onChunkWatch(LevelChunk chunk, ServerPlayer player) {
BuiltInLootTables.VILLAGE_CARTOGRAPHER
);
public static @Nullable LootPool.Builder getExtraLootPool(ResourceLocation lootTable) {
if (!lootTable.getNamespace().equals("minecraft") || !TREASURE_DISK_LOOT_TABLES.contains(lootTable)) {
return null;
}
return LootPool.lootPool()
.add(LootTableReference.lootTableReference(TREASURE_DISK_LOOT))
.setRolls(ConstantValue.exactly(1));
}
public static void onDatapackReload(BiConsumer<String, PreparableReloadListener> addReload) {
addReload.accept("mounts", ResourceMount.RELOAD_LISTENER);
addReload.accept("turtle_upgrades", TurtleUpgrades.instance());

View File

@ -37,9 +37,6 @@
import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.storage.LevelResource;
import net.minecraft.world.level.storage.loot.LootPool;
import net.minecraft.world.level.storage.loot.entries.LootTableReference;
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
@ -95,10 +92,8 @@ public static void init() {
UseBlockCallback.EVENT.register(FabricCommonHooks::useOnBlock);
LootTableEvents.MODIFY.register((resourceManager, lootManager, id, tableBuilder, source) -> {
if (!id.getNamespace().equals("minecraft") || !CommonHooks.TREASURE_DISK_LOOT_TABLES.contains(id)) return;
tableBuilder.withPool(LootPool.lootPool()
.add(LootTableReference.lootTableReference(CommonHooks.TREASURE_DISK_LOOT))
.setRolls(ConstantValue.exactly(1)));
var pool = CommonHooks.getExtraLootPool(id);
if (pool != null) tableBuilder.withPool(pool);
});
CommonHooks.onDatapackReload((name, listener) -> ResourceManagerHelper.get(PackType.SERVER_DATA).registerReloadListener(new ReloadListener(name, listener)));

View File

@ -1,21 +0,0 @@
{
"type": "computercraft:inject_loot_table",
"conditions": [
{
"condition": "minecraft:any_of",
"terms": [
{"condition": "forge:loot_table_id", "loot_table_id": "minecraft:chests/stronghold_library"},
{"condition": "forge:loot_table_id", "loot_table_id": "minecraft:chests/woodland_mansion"},
{"condition": "forge:loot_table_id", "loot_table_id": "minecraft:chests/stronghold_corridor"},
{"condition": "forge:loot_table_id", "loot_table_id": "minecraft:chests/abandoned_mineshaft"},
{"condition": "forge:loot_table_id", "loot_table_id": "minecraft:chests/simple_dungeon"},
{"condition": "forge:loot_table_id", "loot_table_id": "minecraft:chests/village/village_cartographer"},
{"condition": "forge:loot_table_id", "loot_table_id": "minecraft:chests/igloo_chest"},
{"condition": "forge:loot_table_id", "loot_table_id": "minecraft:chests/jungle_temple"},
{"condition": "forge:loot_table_id", "loot_table_id": "minecraft:chests/desert_pyramid"},
{"condition": "forge:loot_table_id", "loot_table_id": "minecraft:chests/stronghold_crossing"}
]
}
],
"loot_table": "computercraft:treasure_disk"
}

View File

@ -1 +0,0 @@
{"entries": ["computercraft:treasure_disk"], "replace": false}

View File

@ -12,7 +12,6 @@
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.pocket.PocketUpgradeSerialiser;
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
import dan200.computercraft.shared.ForgeModRegistry;
import dan200.computercraft.shared.ModRegistry;
import dan200.computercraft.shared.config.ConfigSpec;
import dan200.computercraft.shared.details.FluidData;
@ -37,7 +36,6 @@
public final class ComputerCraft {
public ComputerCraft() {
ModRegistry.register();
ForgeModRegistry.register();
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, ((ForgeConfigFile) ConfigSpec.serverSpec).spec());
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ((ForgeConfigFile) ConfigSpec.clientSpec).spec());

View File

@ -42,8 +42,6 @@ public class Generators {
public static void gather(GatherDataEvent event) {
var generator = event.getGenerator();
DataProviders.add(new GeneratorFactoryImpl(generator.getVanillaPack(true), event.getExistingFileHelper(), event.getLookupProvider()));
generator.<LootModifierProvider>addProvider(event.includeServer(), LootModifierProvider::new);
}
private record GeneratorFactoryImpl(

View File

@ -1,32 +0,0 @@
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.data;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.shared.CommonHooks;
import dan200.computercraft.shared.loot.InjectLootTableModifier;
import net.minecraft.data.PackOutput;
import net.minecraft.world.level.storage.loot.predicates.AnyOfCondition;
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition;
import net.minecraftforge.common.data.GlobalLootModifierProvider;
import net.minecraftforge.common.loot.LootTableIdCondition;
final class LootModifierProvider extends GlobalLootModifierProvider {
LootModifierProvider(PackOutput output) {
super(output, ComputerCraftAPI.MOD_ID);
}
@Override
protected void start() {
add("treasure_disk", new InjectLootTableModifier(
new LootItemCondition[]{
AnyOfCondition.anyOf(
CommonHooks.TREASURE_DISK_LOOT_TABLES.stream().map(LootTableIdCondition::builder).toArray(LootItemCondition.Builder[]::new)
).build(),
},
CommonHooks.TREASURE_DISK_LOOT
));
}
}

View File

@ -138,6 +138,12 @@ public static void onCapability(AttachCapabilitiesEvent<BlockEntity> event) {
}
}
@SubscribeEvent
public static void lootLoad(LootTableLoadEvent event) {
var pool = CommonHooks.getExtraLootPool(event.getName());
if (pool != null) event.getTable().addPool(pool.build());
}
@SubscribeEvent(priority = EventPriority.HIGHEST)
public static void onEntitySpawn(EntityJoinLevelEvent event) {
if (CommonHooks.onEntitySpawn(event.getEntity())) event.setCanceled(true);

View File

@ -1,31 +0,0 @@
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.shared;
import com.mojang.serialization.Codec;
import dan200.computercraft.shared.loot.InjectLootTableModifier;
import dan200.computercraft.shared.platform.PlatformHelper;
import dan200.computercraft.shared.platform.RegistrationHelper;
import dan200.computercraft.shared.platform.RegistryEntry;
import net.minecraftforge.common.loot.IGlobalLootModifier;
import net.minecraftforge.registries.ForgeRegistries;
/**
* {@link ModRegistry} equivalent for Forge-specific content.
*/
public final class ForgeModRegistry {
private ForgeModRegistry() {
}
public static final class Codecs {
static final RegistrationHelper<Codec<? extends IGlobalLootModifier>> REGISTRY = PlatformHelper.get().createRegistrationHelper(ForgeRegistries.Keys.GLOBAL_LOOT_MODIFIER_SERIALIZERS);
public static final RegistryEntry<Codec<InjectLootTableModifier>> INJECT_LOOT_TABLE = REGISTRY.register("inject_loot_table", InjectLootTableModifier::createCodec);
}
public static void register() {
Codecs.REGISTRY.register();
}
}

View File

@ -1,45 +0,0 @@
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.shared.loot;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import dan200.computercraft.shared.ForgeModRegistry;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.minecraft.resources.ResourceLocation;
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.minecraftforge.common.loot.LootModifier;
/**
* A {@link LootModifier} which adds a new loot pool to a piece of loot.
*/
public final class InjectLootTableModifier extends LootModifier {
private final ResourceLocation location;
public InjectLootTableModifier(LootItemCondition[] conditionsIn, ResourceLocation location) {
super(conditionsIn);
this.location = location;
}
public static Codec<InjectLootTableModifier> createCodec() {
return RecordCodecBuilder.create(inst -> LootModifier.codecStart(inst).and(
ResourceLocation.CODEC.fieldOf("loot_table").forGetter(m -> m.location)
).apply(inst, InjectLootTableModifier::new)
);
}
@Override
protected ObjectArrayList<ItemStack> doApply(ObjectArrayList<ItemStack> generatedLoot, LootContext context) {
context.getResolver().getLootTable(location).getRandomItemsRaw(context, generatedLoot::add);
return generatedLoot;
}
@Override
public Codec<InjectLootTableModifier> codec() {
return ForgeModRegistry.Codecs.INJECT_LOOT_TABLE.get();
}
}