Exosuit Probe drops!

This commit is contained in:
DBotThePony 2022-09-15 20:29:51 +07:00
parent 47e9840365
commit 38334ec9e7
Signed by: DBot
GPG Key ID: DCC23B5715498507
13 changed files with 426 additions and 12 deletions

View File

@ -1,45 +1,61 @@
package ru.dbotthepony.mc.otm.datagen.loot package ru.dbotthepony.mc.otm.datagen.loot
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.world.entity.EntityType
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
import net.minecraft.world.level.storage.loot.predicates.LootItemKilledByPlayerCondition
import net.minecraftforge.common.loot.LootTableIdCondition import net.minecraftforge.common.loot.LootTableIdCondition
import ru.dbotthepony.mc.otm.data.ChanceWithPlaytimeCondition
import ru.dbotthepony.mc.otm.data.HasExosuitCondition
import ru.dbotthepony.mc.otm.data.ItemInInventoryCondition
import ru.dbotthepony.mc.otm.data.KilledByRealPlayer
import ru.dbotthepony.mc.otm.data.LootTableBasicAppender import ru.dbotthepony.mc.otm.data.LootTableBasicAppender
import ru.dbotthepony.mc.otm.data.LootTableSeparatedAppender
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems
fun LootTableIdCondition(location: String): LootItemCondition {
return LootTableIdCondition.Builder(ResourceLocation("minecraft", location)).build()
}
fun LootTableIdCondition(location: ResourceLocation): LootItemCondition {
return LootTableIdCondition.Builder(location).build()
}
fun addLootModifiers(it: LootModifiers) { fun addLootModifiers(it: LootModifiers) {
it.add("dungeon_pill", LootTableBasicAppender( it.add("dungeon_pill", LootTableSeparatedAppender(
arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/simple_dungeon")).build()), arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/simple_dungeon")).build()),
ItemStack(MItems.PILL_ANDROID, 1) to 0.4, ItemStack(MItems.PILL_ANDROID, 1) to 0.4,
ItemStack(MItems.PILL_HEAL, 2) to 0.5, ItemStack(MItems.PILL_HEAL, 2) to 0.5,
ItemStack(MItems.PILL_HEAL, 1) to 0.75, ItemStack(MItems.PILL_HEAL, 1) to 0.75,
)) ))
it.add("mineshaft_pill", LootTableBasicAppender( it.add("mineshaft_pill", LootTableSeparatedAppender(
arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/abandoned_mineshaft")).build()), arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/abandoned_mineshaft")).build()),
ItemStack(MItems.PILL_ANDROID, 1) to 0.075, ItemStack(MItems.PILL_ANDROID, 1) to 0.075,
ItemStack(MItems.PILL_HEAL, 2) to 0.1, ItemStack(MItems.PILL_HEAL, 2) to 0.1,
ItemStack(MItems.PILL_HEAL, 1) to 0.4, ItemStack(MItems.PILL_HEAL, 1) to 0.4,
)) ))
it.add("mineshaft_nutrient_paste", LootTableBasicAppender( it.add("mineshaft_nutrient_paste", LootTableSeparatedAppender(
arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/abandoned_mineshaft")).build()), arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/abandoned_mineshaft")).build()),
ItemStack(MItems.NUTRIENT_PASTE, 6) to 0.5, ItemStack(MItems.NUTRIENT_PASTE, 6) to 0.5,
ItemStack(MItems.NUTRIENT_PASTE, 8) to 0.35, ItemStack(MItems.NUTRIENT_PASTE, 8) to 0.35,
ItemStack(MItems.NUTRIENT_PASTE, 12) to 0.15, ItemStack(MItems.NUTRIENT_PASTE, 12) to 0.15,
)) ))
it.add("desert_pyramid_pill", LootTableBasicAppender( it.add("desert_pyramid_pill", LootTableSeparatedAppender(
arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/abandoned_mineshaft")).build()), arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/abandoned_mineshaft")).build()),
ItemStack(MItems.PILL_ANDROID, 1) to 0.05, ItemStack(MItems.PILL_ANDROID, 1) to 0.05,
ItemStack(MItems.PILL_HEAL, 1) to 0.3, ItemStack(MItems.PILL_HEAL, 1) to 0.3,
)) ))
it.add("jungle_temple_pill", LootTableBasicAppender( it.add("jungle_temple_pill", LootTableSeparatedAppender(
arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/jungle_temple")).build()), arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/jungle_temple")).build()),
ItemStack(MItems.PILL_ANDROID, 1) to 0.5 ItemStack(MItems.PILL_ANDROID, 1) to 0.5
)) ))
it.add("end_city_modifications", LootTableBasicAppender( it.add("end_city_modifications", LootTableSeparatedAppender(
arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/end_city_treasure")).build()), arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/end_city_treasure")).build()),
ItemStack(MItems.PILL_ANDROID, 1) to 0.1, ItemStack(MItems.PILL_ANDROID, 1) to 0.1,
ItemStack(MItems.PILL_HUMANE, 1) to 0.3, ItemStack(MItems.PILL_HUMANE, 1) to 0.3,
@ -47,16 +63,36 @@ fun addLootModifiers(it: LootModifiers) {
ItemStack(MItems.ZPM_BATTERY, 1) to 0.005, ItemStack(MItems.ZPM_BATTERY, 1) to 0.005,
)) ))
it.add("shipwreck_supply_pill", LootTableBasicAppender( it.add("shipwreck_supply_pill", LootTableSeparatedAppender(
arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/shipwreck_supply")).build()), arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/shipwreck_supply")).build()),
ItemStack(MItems.PILL_HUMANE, 1) to 0.4, ItemStack(MItems.PILL_HUMANE, 1) to 0.4,
ItemStack(MItems.PILL_HEAL, 1) to 0.6, ItemStack(MItems.PILL_HEAL, 1) to 0.6,
)) ))
it.add("shipwreck_supply_nutrient_paste", LootTableBasicAppender( it.add("shipwreck_supply_nutrient_paste", LootTableSeparatedAppender(
arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/shipwreck_supply")).build()), arrayOf(LootTableIdCondition.Builder(ResourceLocation("chests/shipwreck_supply")).build()),
ItemStack(MItems.NUTRIENT_PASTE, 12) to 0.85, ItemStack(MItems.NUTRIENT_PASTE, 12) to 0.85,
ItemStack(MItems.NUTRIENT_PASTE, 24) to 0.35, ItemStack(MItems.NUTRIENT_PASTE, 24) to 0.35,
ItemStack(MItems.NUTRIENT_PASTE, 38) to 0.1, ItemStack(MItems.NUTRIENT_PASTE, 38) to 0.1,
)) ))
it.add("exosuit_probe_enderman_drop", LootTableBasicAppender(
arrayOf(
LootTableIdCondition(EntityType.ENDERMAN.defaultLootTable),
HasExosuitCondition.INVERTED,
KilledByRealPlayer,
ChanceWithPlaytimeCondition(
minPlaytime = 20 * 60 * 10,
maxPlaytime = 20 * 60 * 120,
minProbability = 0.1,
maxProbability = 0.5,
),
ItemInInventoryCondition(
ItemStack(MItems.EXOSUIT_PROBE)
).invert().build()
),
listOf(
ItemStack(MItems.EXOSUIT_PROBE)
)
))
} }

View File

@ -1,5 +1,6 @@
package ru.dbotthepony.mc.otm.capability package ru.dbotthepony.mc.otm.capability
import com.google.common.collect.Streams
import net.minecraft.core.Direction import net.minecraft.core.Direction
import net.minecraft.world.entity.player.Player import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
@ -11,9 +12,11 @@ import net.minecraftforge.fml.ModList
import ru.dbotthepony.mc.otm.compat.mekanism.getMekanismEnergySided import ru.dbotthepony.mc.otm.compat.mekanism.getMekanismEnergySided
import ru.dbotthepony.mc.otm.compat.mekanism.mekanismEnergy import ru.dbotthepony.mc.otm.compat.mekanism.mekanismEnergy
import ru.dbotthepony.mc.otm.container.iterator import ru.dbotthepony.mc.otm.container.iterator
import ru.dbotthepony.mc.otm.container.stream
import ru.dbotthepony.mc.otm.core.iterator import ru.dbotthepony.mc.otm.core.iterator
import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.core.orNull import ru.dbotthepony.mc.otm.core.orNull
import java.util.stream.Stream
val ICapabilityProvider.matteryPlayer: MatteryPlayerCapability? get() = getCapability(MatteryCapability.MATTERY_PLAYER).orNull() val ICapabilityProvider.matteryPlayer: MatteryPlayerCapability? get() = getCapability(MatteryCapability.MATTERY_PLAYER).orNull()
@ -145,6 +148,16 @@ fun ICapabilityProvider.getMatteryEnergySided(side: Direction? = null): LazyOpti
return LazyOptional.empty() return LazyOptional.empty()
} }
fun Player.itemStream(): Stream<out ItemStack> {
matteryPlayer?.let {
if (it.hasExoSuit) {
return Streams.concat(inventory.stream(), it.exoSuitContainer.stream())
}
}
return inventory.stream()
}
fun Player.extendedItemIterator(): MutableIterator<ItemStack> { fun Player.extendedItemIterator(): MutableIterator<ItemStack> {
return object : MutableIterator<ItemStack> { return object : MutableIterator<ItemStack> {
private val regular = this@extendedItemIterator.inventory.iterator() private val regular = this@extendedItemIterator.inventory.iterator()

View File

@ -0,0 +1,77 @@
package ru.dbotthepony.mc.otm.data
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import com.google.gson.JsonSerializationContext
import net.minecraft.world.level.storage.loot.LootContext
import net.minecraft.world.level.storage.loot.Serializer
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.registry.MLootItemConditions
class ChanceWithPlaytimeCondition(
val minPlaytime: Int = 0,
val maxPlaytime: Int,
val minProbability: Double,
val maxProbability: Double
) : LootItemCondition, LootItemCondition.Builder {
init {
require(minPlaytime <= maxPlaytime) { "Invalid playtime range: min $minPlaytime, max $maxPlaytime" }
require(minProbability <= maxProbability) { "Invalid probability range: min $minProbability, max $maxProbability" }
require(maxProbability <= 1.0) { "Excessive max probability: $maxProbability" }
}
override fun test(t: LootContext): Boolean {
return t[LootContextParams.LAST_DAMAGE_PLAYER]?.matteryPlayer?.let {
val chance: Double
if (it.ticksIExist < minPlaytime) {
chance = minProbability
} else if (it.ticksIExist >= maxPlaytime) {
chance = maxProbability
} else {
chance = minProbability + (maxProbability - minProbability) * (it.ticksIExist - minPlaytime).toDouble() / (maxPlaytime - minPlaytime).toDouble()
}
return t.random.nextDouble() <= chance
} ?: (t.random.nextDouble() <= minProbability)
}
override fun getType(): LootItemConditionType {
return MLootItemConditions.CHANCE_WITH_PLAYTIME
}
override fun build(): LootItemCondition {
return this
}
companion object : Serializer<ChanceWithPlaytimeCondition> {
override fun serialize(
p_79325_: JsonObject,
p_79326_: ChanceWithPlaytimeCondition,
p_79327_: JsonSerializationContext
) {
p_79325_["minPlaytime"] = JsonPrimitive(p_79326_.minPlaytime)
p_79325_["maxPlaytime"] = JsonPrimitive(p_79326_.maxPlaytime)
p_79325_["minProbability"] = JsonPrimitive(p_79326_.minProbability)
p_79325_["maxProbability"] = JsonPrimitive(p_79326_.maxProbability)
}
override fun deserialize(
p_79323_: JsonObject,
p_79324_: JsonDeserializationContext
): ChanceWithPlaytimeCondition {
return ChanceWithPlaytimeCondition(
minPlaytime = p_79323_["minPlaytime"].asInt,
maxPlaytime = p_79323_["maxPlaytime"].asInt,
minProbability = p_79323_["minProbability"].asDouble,
maxProbability = p_79323_["maxProbability"].asDouble,
)
}
}
}

View File

@ -0,0 +1,13 @@
package ru.dbotthepony.mc.otm.data
import com.mojang.serialization.DataResult
import net.minecraft.world.level.storage.loot.LootContext
import net.minecraft.world.level.storage.loot.parameters.LootContextParam
operator fun <T> LootContext.get(param: LootContextParam<T>): T? {
return getParamOrNull(param)
}
fun <T> DataResult<T>.getOrNull(): T? {
return get().left().orElse(null)
}

View File

@ -0,0 +1,40 @@
package ru.dbotthepony.mc.otm.data
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonObject
import com.google.gson.JsonSerializationContext
import net.minecraft.world.level.storage.loot.LootContext
import net.minecraft.world.level.storage.loot.Serializer
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
import net.minecraft.world.level.storage.loot.predicates.InvertedLootItemCondition
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.registry.MLootItemConditions
object HasExosuitCondition : LootItemCondition, Serializer<HasExosuitCondition>, LootItemCondition.Builder {
override fun test(t: LootContext): Boolean {
t[LootContextParams.LAST_DAMAGE_PLAYER]?.matteryPlayer?.let {
return it.hasExoSuit
}
return false
}
override fun getType(): LootItemConditionType {
return MLootItemConditions.HAS_EXOSUIT
}
override fun serialize(p_79325_: JsonObject, p_79326_: HasExosuitCondition, p_79327_: JsonSerializationContext) {
}
override fun deserialize(p_79323_: JsonObject, p_79324_: JsonDeserializationContext): HasExosuitCondition {
return this
}
override fun build(): LootItemCondition {
return this
}
val INVERTED: LootItemCondition = InvertedLootItemCondition.invert(this).build()
}

View File

@ -0,0 +1,91 @@
package ru.dbotthepony.mc.otm.data
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import com.google.gson.JsonSerializationContext
import com.google.gson.JsonSyntaxException
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraft.world.level.storage.loot.LootContext
import net.minecraft.world.level.storage.loot.Serializer
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
import net.minecraftforge.registries.ForgeRegistries
import ru.dbotthepony.mc.otm.capability.itemStream
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.registry.MLootItemConditions
class ItemInInventoryCondition(
val item: ItemStack,
val matchDamage: Boolean = false,
val matchNBT: Boolean = false
) : LootItemCondition, LootItemCondition.Builder {
override fun test(t: LootContext): Boolean {
val matches = t[LootContextParams.LAST_DAMAGE_PLAYER]?.itemStream()?.filter {
if (matchDamage && matchNBT) {
it.item == item.item && it.tag == item.tag && it.damageValue == item.damageValue
} else if (matchDamage) {
it.item == item.item && it.damageValue == item.damageValue
} else if (matchNBT) {
it.item == item.item && it.tag == item.tag
} else {
it.item == item.item
}
} ?: return false
var count = 0
for (match in matches) {
count += match.count
if (count >= item.count) {
return true
}
}
return false
}
override fun getType(): LootItemConditionType {
return MLootItemConditions.ITEM_IN_INVENTORY
}
override fun build(): LootItemCondition {
return this
}
companion object : Serializer<ItemInInventoryCondition> {
override fun serialize(
p_79325_: JsonObject,
p_79326_: ItemInInventoryCondition,
p_79327_: JsonSerializationContext
) {
p_79325_["item"] = JsonPrimitive(p_79326_.item.item.registryName!!.toString())
p_79325_["itemCount"] = JsonPrimitive(p_79326_.item.count)
p_79325_["matchDamage"] = JsonPrimitive(p_79326_.matchDamage)
p_79325_["matchNBT"] = JsonPrimitive(p_79326_.matchNBT)
}
override fun deserialize(p_79323_: JsonObject, p_79324_: JsonDeserializationContext): ItemInInventoryCondition {
val item = p_79323_["item"]?.asString ?: throw JsonSyntaxException("Missing item")
val itemCount = p_79323_["itemCount"]?.asInt ?: throw JsonSyntaxException("Missing itemCount")
val matchDamage = p_79323_["matchDamage"]?.asBoolean ?: throw JsonSyntaxException("Missing matchDamage")
val matchNBT = p_79323_["matchNBT"]?.asBoolean ?: throw JsonSyntaxException("Missing matchNBT")
val getItem = ForgeRegistries.ITEMS.getValue(ResourceLocation(item))
if (getItem == null || getItem == Items.AIR) {
throw JsonSyntaxException("Invalid item $item")
}
return ItemInInventoryCondition(
ItemStack(getItem, itemCount),
matchDamage, matchNBT
)
}
}
}

View File

@ -0,0 +1,39 @@
package ru.dbotthepony.mc.otm.data
import com.mojang.datafixers.util.Pair
import com.mojang.serialization.Codec
import com.mojang.serialization.DataResult
import com.mojang.serialization.DynamicOps
import com.mojang.serialization.codecs.ListCodec
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraftforge.registries.ForgeRegistries
object ItemStackCodec : Codec<ItemStack> {
override fun <T : Any?> encode(input: ItemStack, ops: DynamicOps<T>, prefix: T): DataResult<T> {
require(prefix == ops.empty()) { "Non-empty prefix: $prefix" }
return ForgeRegistries.ITEMS.codec.encode(input.item, ops, ops.empty()).map {
ops.createMap(mapOf(
ops.createString("id") to it,
ops.createString("count") to ops.createInt(input.count)
))
}
}
override fun <T : Any?> decode(ops: DynamicOps<T>, input: T): DataResult<Pair<ItemStack, T>> {
return ops.getMap(input).flatMap {
val item = it["id"]?.let { ForgeRegistries.ITEMS.codec.decode(ops, it) }?.result()?.orElse(null)?.first
val count = it["count"]?.let(ops::getNumberValue)?.result()?.orElse(null)?.toInt() ?: return@flatMap DataResult.error("Invalid item count")
if (item == null || item == Items.AIR) {
return@flatMap DataResult.error("Unknown item type $item")
}
DataResult.success(ItemStack(item, count))
}.map { Pair.of(it, ops.empty()) }
}
val LIST = ListCodec(this)
}

View File

@ -0,0 +1,37 @@
package ru.dbotthepony.mc.otm.data
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonObject
import com.google.gson.JsonSerializationContext
import net.minecraft.world.level.storage.loot.LootContext
import net.minecraft.world.level.storage.loot.Serializer
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
import net.minecraft.world.level.storage.loot.predicates.InvertedLootItemCondition
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
import net.minecraftforge.common.util.FakePlayer
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.registry.MLootItemConditions
object KilledByRealPlayer : LootItemCondition, Serializer<KilledByRealPlayer>, LootItemCondition.Builder {
override fun test(t: LootContext): Boolean {
return t.hasParam(LootContextParams.LAST_DAMAGE_PLAYER) && t[LootContextParams.LAST_DAMAGE_PLAYER] !is FakePlayer
}
override fun getType(): LootItemConditionType {
return MLootItemConditions.HAS_EXOSUIT
}
override fun serialize(p_79325_: JsonObject, p_79326_: KilledByRealPlayer, p_79327_: JsonSerializationContext) {
}
override fun deserialize(p_79323_: JsonObject, p_79324_: JsonDeserializationContext): KilledByRealPlayer {
return this
}
override fun build(): LootItemCondition {
return this
}
val INVERTED: LootItemCondition = InvertedLootItemCondition.invert(this).build()
}

View File

@ -64,7 +64,7 @@ class LootTableAppender(conditions: Array<out LootItemCondition>, private vararg
} }
} }
class LootTableBasicAppender(conditions: Array<out LootItemCondition>, entries: List<Pair<ItemStack, Double>>) : LootModifier(conditions) { class LootTableSeparatedAppender(conditions: Array<out LootItemCondition>, entries: List<Pair<ItemStack, Double>>) : LootModifier(conditions) {
constructor(conditions: Array<out LootItemCondition>, vararg entries: Pair<ItemStack, Double>) : this(conditions, entries.toList()) constructor(conditions: Array<out LootItemCondition>, vararg entries: Pair<ItemStack, Double>) : this(conditions, entries.toList())
private val entries = ImmutableList.copyOf(entries) private val entries = ImmutableList.copyOf(entries)
@ -135,11 +135,11 @@ class LootTableBasicAppender(conditions: Array<out LootItemCondition>, entries:
}) })
} }
val CODEC: Codec<LootTableBasicAppender> by lazy { val CODEC: Codec<LootTableSeparatedAppender> by lazy {
RecordCodecBuilder.create { RecordCodecBuilder.create {
codecStart(it).and( codecStart(it).and(
ItemPairListCodec.fieldOf("entries").forGetter { appender -> appender.entries } ItemPairListCodec.fieldOf("entries").forGetter { appender -> appender.entries }
).apply(it, ::LootTableBasicAppender) ).apply(it, ::LootTableSeparatedAppender)
} }
} }
} }

View File

@ -0,0 +1,38 @@
package ru.dbotthepony.mc.otm.data
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import it.unimi.dsi.fastutil.objects.ObjectArrayList
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.IGlobalLootModifier
import net.minecraftforge.common.loot.LootModifier
import ru.dbotthepony.mc.otm.core.ImmutableList
class LootTableBasicAppender(
conditions: Array<out LootItemCondition>,
items: List<ItemStack>
) : LootModifier(conditions) {
private val items = ImmutableList(items.size) { items[it].copy() }
override fun codec(): Codec<out IGlobalLootModifier> {
return CODEC
}
override fun doApply(
generatedLoot: ObjectArrayList<ItemStack>,
context: LootContext
): ObjectArrayList<ItemStack> {
generatedLoot.addAll(items)
return generatedLoot
}
companion object {
val CODEC: Codec<LootTableBasicAppender> by lazy {
RecordCodecBuilder.create {
codecStart(it).and(ItemStackCodec.LIST.fieldOf("items").forGetter { it.items }).apply(it, ::LootTableBasicAppender)
}
}
}
}

View File

@ -1,18 +1,19 @@
package ru.dbotthepony.mc.otm.registry package ru.dbotthepony.mc.otm.registry
import net.minecraftforge.eventbus.api.IEventBus import net.minecraftforge.eventbus.api.IEventBus
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext
import net.minecraftforge.registries.DeferredRegister import net.minecraftforge.registries.DeferredRegister
import net.minecraftforge.registries.ForgeRegistries import net.minecraftforge.registries.ForgeRegistries
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.data.LootTableAppender import ru.dbotthepony.mc.otm.data.LootTableAppender
import ru.dbotthepony.mc.otm.data.LootTableBasicAppender import ru.dbotthepony.mc.otm.data.LootTableBasicAppender
import ru.dbotthepony.mc.otm.data.LootTableSeparatedAppender
object LootModifiers { object LootModifiers {
private val registry = DeferredRegister.create(ForgeRegistries.Keys.GLOBAL_LOOT_MODIFIER_SERIALIZERS, OverdriveThatMatters.MOD_ID) private val registry = DeferredRegister.create(ForgeRegistries.Keys.GLOBAL_LOOT_MODIFIER_SERIALIZERS, OverdriveThatMatters.MOD_ID)
init { init {
registry.register("loot_appender") { LootTableAppender.CODEC } registry.register("loot_appender") { LootTableAppender.CODEC }
registry.register("loot_appender_separated") { LootTableSeparatedAppender.CODEC }
registry.register("loot_appender_basic") { LootTableBasicAppender.CODEC } registry.register("loot_appender_basic") { LootTableBasicAppender.CODEC }
} }

View File

@ -0,0 +1,28 @@
package ru.dbotthepony.mc.otm.registry
import net.minecraft.core.Registry
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent
import net.minecraftforge.registries.RegisterEvent
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.data.ChanceWithPlaytimeCondition
import ru.dbotthepony.mc.otm.data.HasExosuitCondition
import ru.dbotthepony.mc.otm.data.ItemInInventoryCondition
import ru.dbotthepony.mc.otm.data.KilledByRealPlayer
object MLootItemConditions {
val HAS_EXOSUIT = LootItemConditionType(HasExosuitCondition)
val KILLED_BY_REAL_PLAYER = LootItemConditionType(KilledByRealPlayer)
val CHANCE_WITH_PLAYTIME = LootItemConditionType(ChanceWithPlaytimeCondition)
val ITEM_IN_INVENTORY = LootItemConditionType(ItemInInventoryCondition)
internal fun register(event: RegisterEvent) {
if (event.getVanillaRegistry<LootItemConditionType>() == Registry.LOOT_CONDITION_TYPE) {
Registry.LOOT_CONDITION_TYPE.register(ResourceLocation(OverdriveThatMatters.MOD_ID, "has_exosuit"), HAS_EXOSUIT)
Registry.LOOT_CONDITION_TYPE.register(ResourceLocation(OverdriveThatMatters.MOD_ID, "chance_with_playtime"), CHANCE_WITH_PLAYTIME)
Registry.LOOT_CONDITION_TYPE.register(ResourceLocation(OverdriveThatMatters.MOD_ID, "item_in_inventory"), ITEM_IN_INVENTORY)
Registry.LOOT_CONDITION_TYPE.register(ResourceLocation(OverdriveThatMatters.MOD_ID, "killed_by_real_player"), KILLED_BY_REAL_PLAYER)
}
}
}

View File

@ -223,6 +223,7 @@ object MRegistry {
fun initialize(bus: IEventBus) { fun initialize(bus: IEventBus) {
bus.addListener(this::register) bus.addListener(this::register)
bus.addListener(MStats::registerVanilla) bus.addListener(MStats::registerVanilla)
bus.addListener(MLootItemConditions::register)
MBlocks.register(bus) MBlocks.register(bus)
MBlockEntities.register(bus) MBlockEntities.register(bus)