package net.minecraft.world; import net.minecraft.advancements.triggers.CriteriaTriggers; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.storage.ValueInput; import net.minecraft.world.level.storage.ValueOutput; import net.minecraft.world.level.storage.loot.LootParams; import net.minecraft.world.level.storage.loot.LootTable; import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.phys.Vec3; import org.jspecify.annotations.Nullable; public interface RandomizableContainer extends Container { String LOOT_TABLE_TAG = "LootTable"; String LOOT_TABLE_SEED_TAG = "LootTableSeed"; @Nullable ResourceKey getLootTable(); void setLootTable(@Nullable final ResourceKey lootTable); default void setLootTable(final ResourceKey lootTable, final long seed) { this.setLootTable(lootTable); this.setLootTableSeed(seed); } long getLootTableSeed(); void setLootTableSeed(final long lootTableSeed); BlockPos getBlockPos(); @Nullable Level getLevel(); static void setBlockEntityLootTable(final BlockGetter level, final RandomSource random, final BlockPos blockEntityPos, final ResourceKey lootTable) { if (level.getBlockEntity(blockEntityPos) instanceof RandomizableContainer randomizableContainer) { randomizableContainer.setLootTable(lootTable, random.nextLong()); } } default boolean tryLoadLootTable(final ValueInput base) { ResourceKey lootTable = (ResourceKey)base.read("LootTable", LootTable.KEY_CODEC).orElse(null); this.setLootTable(lootTable); this.setLootTableSeed(base.getLongOr("LootTableSeed", 0L)); return lootTable != null; } default boolean trySaveLootTable(final ValueOutput base) { ResourceKey lootTable = this.getLootTable(); if (lootTable == null) { return false; } else { base.store("LootTable", LootTable.KEY_CODEC, lootTable); long lootTableSeed = this.getLootTableSeed(); if (lootTableSeed != 0L) { base.putLong("LootTableSeed", lootTableSeed); } return true; } } default void unpackLootTable(@Nullable final Player player) { Level level = this.getLevel(); BlockPos worldPosition = this.getBlockPos(); ResourceKey lootTableKey = this.getLootTable(); if (lootTableKey != null && level != null && level.getServer() != null) { LootTable lootTable = level.getServer().reloadableRegistries().getLootTable(lootTableKey); if (player instanceof ServerPlayer serverPlayer) { CriteriaTriggers.GENERATE_LOOT.trigger(serverPlayer, lootTableKey); } this.setLootTable(null); LootParams.Builder params = new LootParams.Builder((ServerLevel)level).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(worldPosition)); if (player != null) { params.withLuck(player.getLuck()).withParameter(LootContextParams.THIS_ENTITY, player); } lootTable.fill(this, params.create(LootContextParamSets.CHEST), this.getLootTableSeed()); } } }