Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
3e291ff340
114
src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/DSL.kt
Normal file
114
src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/DSL.kt
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.datagen.loot
|
||||||
|
|
||||||
|
import net.minecraft.advancements.critereon.StatePropertiesPredicate
|
||||||
|
import net.minecraft.util.StringRepresentable
|
||||||
|
import net.minecraft.world.item.Rarity
|
||||||
|
import net.minecraft.world.level.ItemLike
|
||||||
|
import net.minecraft.world.level.block.Block
|
||||||
|
import net.minecraft.world.level.block.state.properties.Property
|
||||||
|
import net.minecraft.world.level.storage.loot.LootPool
|
||||||
|
import net.minecraft.world.level.storage.loot.LootTable
|
||||||
|
import net.minecraft.world.level.storage.loot.entries.LootItem
|
||||||
|
import net.minecraft.world.level.storage.loot.entries.LootPoolSingletonContainer
|
||||||
|
import net.minecraft.world.level.storage.loot.functions.LootItemConditionalFunction
|
||||||
|
import net.minecraft.world.level.storage.loot.functions.SetItemCountFunction
|
||||||
|
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.providers.number.ConstantValue
|
||||||
|
import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator
|
||||||
|
import ru.dbotthepony.mc.otm.data.condition.ChanceCondition
|
||||||
|
import ru.dbotthepony.mc.otm.data.loot.RandomizerFunction
|
||||||
|
|
||||||
|
inline fun LootTable.Builder.lootPool(configurator: LootPool.Builder.() -> Unit): LootTable.Builder = withPool(LootPool.lootPool().also(configurator))
|
||||||
|
inline fun LootTable.Builder.singleItem(item: ItemLike, configurator: LootPoolSingletonContainer.Builder<*>.() -> Unit): LootTable.Builder {
|
||||||
|
return withPool(LootPool.lootPool().also {
|
||||||
|
it.item(item, configurator)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun lootPool(configurator: LootPool.Builder.() -> Unit): LootPool = LootPool.lootPool().also(configurator).build()
|
||||||
|
inline fun singleItem(item: ItemLike, configurator: LootPoolSingletonContainer.Builder<*>.() -> Unit): LootPool = lootPool { item(item, configurator) }
|
||||||
|
fun singleRandomizedItem(item: ItemLike, rarity: Rarity = Rarity.COMMON, chance: Double? = null): LootPool {
|
||||||
|
return lootPool {
|
||||||
|
item(item) {
|
||||||
|
apply(RandomizerFunction.valueOf(rarity))
|
||||||
|
|
||||||
|
if (chance != null) {
|
||||||
|
chanceCondition(chance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun LootPool.Builder.item(item: ItemLike, configurator: LootPoolSingletonContainer.Builder<*>.() -> Unit) {
|
||||||
|
add(LootItem.lootTableItem(item).also(configurator))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun LootPool.Builder.setRolls(count: Int): LootPool.Builder = setRolls(ConstantValue.exactly(count.toFloat()))
|
||||||
|
fun LootPool.Builder.setRolls(count: Float): LootPool.Builder = setRolls(ConstantValue.exactly(count))
|
||||||
|
fun LootPool.Builder.setRolls(min: Int, max: Int): LootPool.Builder = setRolls(UniformGenerator.between(min.toFloat(), max.toFloat()))
|
||||||
|
fun LootPool.Builder.setRolls(min: Float, max: Float): LootPool.Builder = setRolls(UniformGenerator.between(min, max))
|
||||||
|
|
||||||
|
fun LootPool.Builder.condition(value: LootItemCondition.Builder): LootPool.Builder = `when`(value)
|
||||||
|
fun LootPool.Builder.chanceCondition(chance: Double): LootPool.Builder = condition(ChanceCondition(chance))
|
||||||
|
|
||||||
|
fun <T : LootPoolSingletonContainer.Builder<*>> T.setCount(count: Int, configurator: LootItemConditionalFunction.Builder<*>.() -> Unit = {}): T {
|
||||||
|
apply(SetItemCountFunction.setCount(ConstantValue.exactly(count.toFloat())).also(configurator))
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : LootPoolSingletonContainer.Builder<*>> T.setCount(minimal: Int, maximal: Int, configurator: LootItemConditionalFunction.Builder<*>.() -> Unit = {}): T {
|
||||||
|
apply(SetItemCountFunction.setCount(UniformGenerator.between(minimal.toFloat(), maximal.toFloat())).also(configurator))
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : LootPoolSingletonContainer.Builder<*>> T.chanceCondition(chance: Double): T {
|
||||||
|
condition(ChanceCondition(chance))
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : LootPoolSingletonContainer.Builder<*>> T.setCount(minimal: Float, maximal: Float, configurator: LootItemConditionalFunction.Builder<*>.() -> Unit = {}): T {
|
||||||
|
apply(SetItemCountFunction.setCount(UniformGenerator.between(minimal, maximal)).also(configurator))
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : LootPoolSingletonContainer.Builder<*>> T.condition(condition: LootItemCondition.Builder): T {
|
||||||
|
`when`(condition)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : LootItemConditionalFunction.Builder<*>> T.condition(condition: LootItemCondition.Builder): T {
|
||||||
|
`when`(condition)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <T : LootPoolSingletonContainer.Builder<*>> T.blockStateCondition(block: Block, configurator: StatePropertiesPredicate.Builder.() -> Unit): T {
|
||||||
|
condition(
|
||||||
|
LootItemBlockStatePropertyCondition.hasBlockStateProperties(block)
|
||||||
|
.setProperties(StatePropertiesPredicate.Builder.properties().also(configurator)))
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <T : LootItemConditionalFunction.Builder<*>> T.blockStateCondition(block: Block, configurator: StatePropertiesPredicate.Builder.() -> Unit): T {
|
||||||
|
condition(
|
||||||
|
LootItemBlockStatePropertyCondition.hasBlockStateProperties(block)
|
||||||
|
.setProperties(StatePropertiesPredicate.Builder.properties().also(configurator)))
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : LootItemConditionalFunction.Builder<*>> T.chanceCondition(chance: Double): T {
|
||||||
|
condition(ChanceCondition(chance))
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun StatePropertiesPredicate.Builder.set(property: Property<*>, value: String): StatePropertiesPredicate.Builder = hasProperty(property, value)
|
||||||
|
operator fun StatePropertiesPredicate.Builder.set(property: Property<Int>, value: Int): StatePropertiesPredicate.Builder = hasProperty(property, value)
|
||||||
|
operator fun StatePropertiesPredicate.Builder.set(property: Property<Boolean>, value: Boolean): StatePropertiesPredicate.Builder = hasProperty(property, value)
|
||||||
|
|
||||||
|
operator fun <T : Comparable<T>> StatePropertiesPredicate.Builder.set(property: Property<T>, value: T): StatePropertiesPredicate.Builder {
|
||||||
|
if (value !is StringRepresentable) {
|
||||||
|
throw ClassCastException("Provided type ${value::class.qualifiedName} is not a subtype of ${StringRepresentable::class.qualifiedName}")
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasProperty(property, value.serializedName)
|
||||||
|
}
|
@ -1,8 +1,55 @@
|
|||||||
package ru.dbotthepony.mc.otm.datagen.loot
|
package ru.dbotthepony.mc.otm.datagen.loot
|
||||||
|
|
||||||
import net.minecraft.data.DataGenerator
|
import net.minecraft.data.DataGenerator
|
||||||
|
import net.minecraft.world.item.ItemStack
|
||||||
|
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
|
||||||
import net.minecraftforge.common.data.GlobalLootModifierProvider
|
import net.minecraftforge.common.data.GlobalLootModifierProvider
|
||||||
|
import ru.dbotthepony.mc.otm.data.loot.LootPoolAppender
|
||||||
import ru.dbotthepony.mc.otm.datagen.DataGen
|
import ru.dbotthepony.mc.otm.datagen.DataGen
|
||||||
|
import java.util.Arrays
|
||||||
|
import java.util.stream.Stream
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
fun BasicLootAppender(
|
||||||
|
conditions: Array<out LootItemCondition>,
|
||||||
|
items: Stream<ItemStack>
|
||||||
|
): LootPoolAppender {
|
||||||
|
return LootPoolAppender(conditions, items.map {
|
||||||
|
lootPool {
|
||||||
|
item(it.item) {
|
||||||
|
setCount(it.count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
fun BasicLootAppender(
|
||||||
|
conditions: Array<out LootItemCondition>,
|
||||||
|
vararg items: ItemStack
|
||||||
|
) = BasicLootAppender(conditions, Arrays.stream(items))
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
fun PlainLootAppender(
|
||||||
|
conditions: Array<out LootItemCondition>,
|
||||||
|
items: Stream<Pair<ItemStack, Double>>
|
||||||
|
): LootPoolAppender {
|
||||||
|
return LootPoolAppender(conditions, items.map {
|
||||||
|
lootPool {
|
||||||
|
item(it.first.item) {
|
||||||
|
setCount(it.first.count)
|
||||||
|
}
|
||||||
|
|
||||||
|
chanceCondition(it.second)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
fun PlainLootAppender(
|
||||||
|
conditions: Array<out LootItemCondition>,
|
||||||
|
vararg items: Pair<ItemStack, Double>
|
||||||
|
) = PlainLootAppender(conditions, Arrays.stream(items))
|
||||||
|
|
||||||
class LootModifiers(generator: DataGenerator) : GlobalLootModifierProvider(generator, DataGen.MOD_ID) {
|
class LootModifiers(generator: DataGenerator) : GlobalLootModifierProvider(generator, DataGen.MOD_ID) {
|
||||||
private val lambdas = ArrayList<(LootModifiers) -> Unit>()
|
private val lambdas = ArrayList<(LootModifiers) -> Unit>()
|
||||||
|
@ -6,27 +6,70 @@ import net.minecraft.world.item.ItemStack
|
|||||||
import net.minecraft.world.item.Rarity
|
import net.minecraft.world.item.Rarity
|
||||||
import net.minecraft.world.level.storage.loot.BuiltInLootTables
|
import net.minecraft.world.level.storage.loot.BuiltInLootTables
|
||||||
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
|
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
|
||||||
|
import net.minecraftforge.common.loot.LootModifier
|
||||||
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.condition.ChanceWithPlaytimeCondition
|
||||||
import ru.dbotthepony.mc.otm.data.HasExosuitCondition
|
import ru.dbotthepony.mc.otm.data.condition.HasExosuitCondition
|
||||||
import ru.dbotthepony.mc.otm.data.IRandomizableItem
|
import ru.dbotthepony.mc.otm.data.condition.ItemInInventoryCondition
|
||||||
import ru.dbotthepony.mc.otm.data.ItemInInventoryCondition
|
import ru.dbotthepony.mc.otm.data.condition.KilledByRealPlayerOrIndirectly
|
||||||
import ru.dbotthepony.mc.otm.data.KilledByRealPlayer
|
import ru.dbotthepony.mc.otm.data.loot.LootPoolAppender
|
||||||
import ru.dbotthepony.mc.otm.data.BasicLootAppender
|
import ru.dbotthepony.mc.otm.data.loot.RandomizerFunction
|
||||||
import ru.dbotthepony.mc.otm.data.KilledByRealPlayerOrIndirectly
|
|
||||||
import ru.dbotthepony.mc.otm.data.PlainLootAppender
|
|
||||||
import ru.dbotthepony.mc.otm.data.RandomizableItemLootAppender
|
|
||||||
import ru.dbotthepony.mc.otm.registry.MItems
|
import ru.dbotthepony.mc.otm.registry.MItems
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
fun LootTableIdCondition(location: String): LootItemCondition {
|
fun LootTableIdCondition(location: String): LootItemCondition {
|
||||||
return LootTableIdCondition.Builder(ResourceLocation("minecraft", location)).build()
|
return LootTableIdCondition.Builder(ResourceLocation("minecraft", location)).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
fun LootTableIdCondition(location: ResourceLocation): LootItemCondition {
|
fun LootTableIdCondition(location: ResourceLocation): LootItemCondition {
|
||||||
return LootTableIdCondition.Builder(location).build()
|
return LootTableIdCondition.Builder(location).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun exosuitModifiers(it: LootModifiers) {
|
||||||
|
it.add("dungeon_exosuit", LootPoolAppender(
|
||||||
|
arrayOf(LootTableIdCondition(BuiltInLootTables.SIMPLE_DUNGEON)),
|
||||||
|
|
||||||
|
singleItem(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL) {
|
||||||
|
chanceCondition(0.2)
|
||||||
|
apply(RandomizerFunction.COMMON)
|
||||||
|
},
|
||||||
|
|
||||||
|
singleItem(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL) {
|
||||||
|
chanceCondition(0.05)
|
||||||
|
apply(RandomizerFunction.UNCOMMON)
|
||||||
|
},
|
||||||
|
))
|
||||||
|
|
||||||
|
it.add("mineshaft_exosuit", LootPoolAppender(
|
||||||
|
arrayOf(LootTableIdCondition(BuiltInLootTables.ABANDONED_MINESHAFT)),
|
||||||
|
singleRandomizedItem(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.1),
|
||||||
|
singleRandomizedItem(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.1, rarity = Rarity.UNCOMMON)
|
||||||
|
))
|
||||||
|
|
||||||
|
it.add("desert_pyramid_exosuit", LootPoolAppender(
|
||||||
|
arrayOf(LootTableIdCondition(BuiltInLootTables.DESERT_PYRAMID)),
|
||||||
|
singleRandomizedItem(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.15, rarity = Rarity.UNCOMMON),
|
||||||
|
singleRandomizedItem(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.25, rarity = Rarity.COMMON)
|
||||||
|
))
|
||||||
|
|
||||||
|
it.add("jungle_temple_exosuit", LootPoolAppender(
|
||||||
|
arrayOf(LootTableIdCondition(BuiltInLootTables.JUNGLE_TEMPLE)),
|
||||||
|
singleRandomizedItem(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.15, rarity = Rarity.UNCOMMON),
|
||||||
|
singleRandomizedItem(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.35, rarity = Rarity.RARE)
|
||||||
|
))
|
||||||
|
|
||||||
|
it.add("end_city_exosuit", LootPoolAppender(
|
||||||
|
arrayOf(LootTableIdCondition(BuiltInLootTables.END_CITY_TREASURE)),
|
||||||
|
singleRandomizedItem(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.4, rarity = Rarity.UNCOMMON),
|
||||||
|
singleRandomizedItem(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.2, rarity = Rarity.RARE),
|
||||||
|
singleRandomizedItem(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.15, rarity = Rarity.EPIC),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
fun addLootModifiers(it: LootModifiers) {
|
fun addLootModifiers(it: LootModifiers) {
|
||||||
|
exosuitModifiers(it)
|
||||||
|
|
||||||
it.add("dungeon_pill", PlainLootAppender(
|
it.add("dungeon_pill", PlainLootAppender(
|
||||||
arrayOf(LootTableIdCondition(BuiltInLootTables.SIMPLE_DUNGEON)),
|
arrayOf(LootTableIdCondition(BuiltInLootTables.SIMPLE_DUNGEON)),
|
||||||
ItemStack(MItems.PILL_ANDROID, 1) to 0.4,
|
ItemStack(MItems.PILL_ANDROID, 1) to 0.4,
|
||||||
@ -34,14 +77,6 @@ fun addLootModifiers(it: LootModifiers) {
|
|||||||
ItemStack(MItems.PILL_HEAL, 1) to 0.75,
|
ItemStack(MItems.PILL_HEAL, 1) to 0.75,
|
||||||
))
|
))
|
||||||
|
|
||||||
it.add("dungeon_exosuit", RandomizableItemLootAppender(
|
|
||||||
arrayOf(LootTableIdCondition(BuiltInLootTables.SIMPLE_DUNGEON)),
|
|
||||||
listOf(
|
|
||||||
RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.2),
|
|
||||||
RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.05, rarity = Rarity.UNCOMMON)
|
|
||||||
)
|
|
||||||
))
|
|
||||||
|
|
||||||
it.add("mineshaft_pill", PlainLootAppender(
|
it.add("mineshaft_pill", PlainLootAppender(
|
||||||
arrayOf(LootTableIdCondition(BuiltInLootTables.ABANDONED_MINESHAFT)),
|
arrayOf(LootTableIdCondition(BuiltInLootTables.ABANDONED_MINESHAFT)),
|
||||||
ItemStack(MItems.PILL_ANDROID, 1) to 0.075,
|
ItemStack(MItems.PILL_ANDROID, 1) to 0.075,
|
||||||
@ -49,14 +84,6 @@ fun addLootModifiers(it: LootModifiers) {
|
|||||||
ItemStack(MItems.PILL_HEAL, 1) to 0.4,
|
ItemStack(MItems.PILL_HEAL, 1) to 0.4,
|
||||||
))
|
))
|
||||||
|
|
||||||
it.add("mineshaft_exosuit", RandomizableItemLootAppender(
|
|
||||||
arrayOf(LootTableIdCondition(BuiltInLootTables.ABANDONED_MINESHAFT)),
|
|
||||||
listOf(
|
|
||||||
RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.1),
|
|
||||||
RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.01, rarity = Rarity.UNCOMMON)
|
|
||||||
)
|
|
||||||
))
|
|
||||||
|
|
||||||
it.add("mineshaft_nutrient_paste", PlainLootAppender(
|
it.add("mineshaft_nutrient_paste", PlainLootAppender(
|
||||||
arrayOf(LootTableIdCondition(BuiltInLootTables.ABANDONED_MINESHAFT)),
|
arrayOf(LootTableIdCondition(BuiltInLootTables.ABANDONED_MINESHAFT)),
|
||||||
ItemStack(MItems.NUTRIENT_PASTE, 6) to 0.5,
|
ItemStack(MItems.NUTRIENT_PASTE, 6) to 0.5,
|
||||||
@ -70,27 +97,11 @@ fun addLootModifiers(it: LootModifiers) {
|
|||||||
ItemStack(MItems.PILL_HEAL, 1) to 0.3,
|
ItemStack(MItems.PILL_HEAL, 1) to 0.3,
|
||||||
))
|
))
|
||||||
|
|
||||||
it.add("desert_pyramid_exosuit", RandomizableItemLootAppender(
|
|
||||||
arrayOf(LootTableIdCondition(BuiltInLootTables.DESERT_PYRAMID)),
|
|
||||||
listOf(
|
|
||||||
RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.15, rarity = Rarity.UNCOMMON),
|
|
||||||
RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.25, rarity = Rarity.COMMON),
|
|
||||||
)
|
|
||||||
))
|
|
||||||
|
|
||||||
it.add("jungle_temple_pill", PlainLootAppender(
|
it.add("jungle_temple_pill", PlainLootAppender(
|
||||||
arrayOf(LootTableIdCondition(BuiltInLootTables.JUNGLE_TEMPLE)),
|
arrayOf(LootTableIdCondition(BuiltInLootTables.JUNGLE_TEMPLE)),
|
||||||
ItemStack(MItems.PILL_ANDROID, 1) to 0.5
|
ItemStack(MItems.PILL_ANDROID, 1) to 0.5
|
||||||
))
|
))
|
||||||
|
|
||||||
it.add("jungle_temple_exosuit", RandomizableItemLootAppender(
|
|
||||||
arrayOf(LootTableIdCondition(BuiltInLootTables.JUNGLE_TEMPLE)),
|
|
||||||
listOf(
|
|
||||||
RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.15, rarity = Rarity.UNCOMMON),
|
|
||||||
RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.35, rarity = Rarity.RARE)
|
|
||||||
)
|
|
||||||
))
|
|
||||||
|
|
||||||
it.add("end_city_modifications", PlainLootAppender(
|
it.add("end_city_modifications", PlainLootAppender(
|
||||||
arrayOf(LootTableIdCondition(BuiltInLootTables.END_CITY_TREASURE)),
|
arrayOf(LootTableIdCondition(BuiltInLootTables.END_CITY_TREASURE)),
|
||||||
ItemStack(MItems.PILL_ANDROID, 1) to 0.1,
|
ItemStack(MItems.PILL_ANDROID, 1) to 0.1,
|
||||||
@ -99,15 +110,6 @@ fun addLootModifiers(it: LootModifiers) {
|
|||||||
ItemStack(MItems.ZPM_BATTERY, 1) to 0.005,
|
ItemStack(MItems.ZPM_BATTERY, 1) to 0.005,
|
||||||
))
|
))
|
||||||
|
|
||||||
it.add("end_city_exosuit", RandomizableItemLootAppender(
|
|
||||||
arrayOf(LootTableIdCondition(BuiltInLootTables.END_CITY_TREASURE)),
|
|
||||||
listOf(
|
|
||||||
RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.4, rarity = Rarity.UNCOMMON),
|
|
||||||
RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.2, rarity = Rarity.RARE),
|
|
||||||
RandomizableItemLootAppender.Entry(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_PROCEDURAL as IRandomizableItem, chance = 0.15, rarity = Rarity.EPIC),
|
|
||||||
)
|
|
||||||
))
|
|
||||||
|
|
||||||
it.add("shipwreck_supply_pill", PlainLootAppender(
|
it.add("shipwreck_supply_pill", PlainLootAppender(
|
||||||
arrayOf(LootTableIdCondition(BuiltInLootTables.SHIPWRECK_SUPPLY)),
|
arrayOf(LootTableIdCondition(BuiltInLootTables.SHIPWRECK_SUPPLY)),
|
||||||
ItemStack(MItems.PILL_HUMANE, 1) to 0.4,
|
ItemStack(MItems.PILL_HUMANE, 1) to 0.4,
|
||||||
@ -143,12 +145,18 @@ fun addLootModifiers(it: LootModifiers) {
|
|||||||
))
|
))
|
||||||
|
|
||||||
it.add("wither_exosuit_upgrades", BasicLootAppender(
|
it.add("wither_exosuit_upgrades", BasicLootAppender(
|
||||||
arrayOf(LootTableIdCondition(EntityType.WITHER.defaultLootTable)),
|
arrayOf(
|
||||||
|
LootTableIdCondition(EntityType.WITHER.defaultLootTable),
|
||||||
|
KilledByRealPlayerOrIndirectly,
|
||||||
|
),
|
||||||
ItemStack(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_WITHER),
|
ItemStack(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_WITHER),
|
||||||
))
|
))
|
||||||
|
|
||||||
it.add("ender_dragon_exosuit_upgrades", BasicLootAppender(
|
it.add("ender_dragon_exosuit_upgrades", BasicLootAppender(
|
||||||
arrayOf(LootTableIdCondition(EntityType.ENDER_DRAGON.defaultLootTable)),
|
arrayOf(
|
||||||
|
LootTableIdCondition(EntityType.ENDER_DRAGON.defaultLootTable),
|
||||||
|
KilledByRealPlayerOrIndirectly,
|
||||||
|
),
|
||||||
ItemStack(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_ENDER_DRAGON),
|
ItemStack(MItems.ExosuitUpgrades.INVENTORY_UPGRADE_ENDER_DRAGON),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,9 @@ import net.minecraft.advancements.critereon.StatePropertiesPredicate
|
|||||||
import net.minecraft.data.DataGenerator
|
import net.minecraft.data.DataGenerator
|
||||||
import net.minecraft.data.loot.LootTableProvider
|
import net.minecraft.data.loot.LootTableProvider
|
||||||
import net.minecraft.resources.ResourceLocation
|
import net.minecraft.resources.ResourceLocation
|
||||||
import net.minecraft.util.StringRepresentable
|
|
||||||
import net.minecraft.world.level.ItemLike
|
import net.minecraft.world.level.ItemLike
|
||||||
import net.minecraft.world.level.block.Block
|
import net.minecraft.world.level.block.Block
|
||||||
import net.minecraft.world.level.block.SlabBlock
|
import net.minecraft.world.level.block.SlabBlock
|
||||||
import net.minecraft.world.level.block.state.properties.Property
|
|
||||||
import net.minecraft.world.level.block.state.properties.SlabType
|
import net.minecraft.world.level.block.state.properties.SlabType
|
||||||
import net.minecraft.world.level.storage.loot.LootPool
|
import net.minecraft.world.level.storage.loot.LootPool
|
||||||
import net.minecraft.world.level.storage.loot.LootTable
|
import net.minecraft.world.level.storage.loot.LootTable
|
||||||
@ -22,85 +20,23 @@ import net.minecraft.world.level.storage.loot.ValidationContext
|
|||||||
import net.minecraft.world.level.storage.loot.entries.LootItem
|
import net.minecraft.world.level.storage.loot.entries.LootItem
|
||||||
import net.minecraft.world.level.storage.loot.entries.LootPoolSingletonContainer
|
import net.minecraft.world.level.storage.loot.entries.LootPoolSingletonContainer
|
||||||
import net.minecraft.world.level.storage.loot.functions.CopyNbtFunction
|
import net.minecraft.world.level.storage.loot.functions.CopyNbtFunction
|
||||||
import net.minecraft.world.level.storage.loot.functions.LootItemConditionalFunction
|
|
||||||
import net.minecraft.world.level.storage.loot.functions.SetItemCountFunction
|
import net.minecraft.world.level.storage.loot.functions.SetItemCountFunction
|
||||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSet
|
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.LootContextParamSets
|
||||||
import net.minecraft.world.level.storage.loot.predicates.LootItemBlockStatePropertyCondition
|
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.providers.nbt.ContextNbtProvider
|
import net.minecraft.world.level.storage.loot.providers.nbt.ContextNbtProvider
|
||||||
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue
|
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue
|
||||||
import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator
|
|
||||||
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.core.registryName
|
|
||||||
import java.util.function.BiConsumer
|
import java.util.function.BiConsumer
|
||||||
import java.util.function.Consumer
|
import java.util.function.Consumer
|
||||||
import java.util.function.Supplier
|
import java.util.function.Supplier
|
||||||
import kotlin.reflect.full.isSubclassOf
|
|
||||||
|
|
||||||
private typealias LootTableSaver = BiConsumer<ResourceLocation, LootTable.Builder>
|
private typealias LootTableSaver = BiConsumer<ResourceLocation, LootTable.Builder>
|
||||||
private typealias LootTableCallback = Consumer<LootTableSaver>
|
private typealias LootTableCallback = Consumer<LootTableSaver>
|
||||||
private typealias LootTableCallbackProvider = Supplier<LootTableCallback>
|
private typealias LootTableCallbackProvider = Supplier<LootTableCallback>
|
||||||
private typealias LootTuple = Pair<LootTableCallbackProvider, LootContextParamSet>
|
private typealias LootTuple = Pair<LootTableCallbackProvider, LootContextParamSet>
|
||||||
|
|
||||||
inline fun LootTable.Builder.lootPool(configurator: LootPool.Builder.() -> Unit): LootTable.Builder = withPool(LootPool.lootPool().also(configurator))
|
|
||||||
inline fun LootPool.Builder.item(item: ItemLike, configurator: LootPoolSingletonContainer.Builder<*>.() -> Unit) {
|
|
||||||
add(LootItem.lootTableItem(item).also(configurator))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun LootPool.Builder.setRolls(count: Int): LootPool.Builder = setRolls(ConstantValue.exactly(count.toFloat()))
|
|
||||||
fun LootPool.Builder.setRolls(count: Float): LootPool.Builder = setRolls(ConstantValue.exactly(count))
|
|
||||||
|
|
||||||
fun LootPool.Builder.setRolls(min: Int, max: Int): LootPool.Builder = setRolls(UniformGenerator.between(min.toFloat(), max.toFloat()))
|
|
||||||
fun LootPool.Builder.setRolls(min: Float, max: Float): LootPool.Builder = setRolls(UniformGenerator.between(min, max))
|
|
||||||
|
|
||||||
fun <T : LootPoolSingletonContainer.Builder<*>> T.setCount(count: Int, configurator: LootItemConditionalFunction.Builder<*>.() -> Unit = {}): T {
|
|
||||||
apply(SetItemCountFunction.setCount(ConstantValue.exactly(count.toFloat())).also(configurator))
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T : LootPoolSingletonContainer.Builder<*>> T.setCount(minimal: Int, maximal: Int, configurator: LootItemConditionalFunction.Builder<*>.() -> Unit = {}): T {
|
|
||||||
apply(SetItemCountFunction.setCount(UniformGenerator.between(minimal.toFloat(), maximal.toFloat())).also(configurator))
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T : LootPoolSingletonContainer.Builder<*>> T.setCount(minimal: Float, maximal: Float, configurator: LootItemConditionalFunction.Builder<*>.() -> Unit = {}): T {
|
|
||||||
apply(SetItemCountFunction.setCount(UniformGenerator.between(minimal, maximal)).also(configurator))
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T : LootPoolSingletonContainer.Builder<*>> T.condition(condition: LootItemCondition.Builder): T {
|
|
||||||
`when`(condition)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T : LootItemConditionalFunction.Builder<*>> T.condition(condition: LootItemCondition.Builder): T {
|
|
||||||
`when`(condition)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <T : LootPoolSingletonContainer.Builder<*>> T.blockStateCondition(block: Block, configurator: StatePropertiesPredicate.Builder.() -> Unit): T {
|
|
||||||
condition(LootItemBlockStatePropertyCondition.hasBlockStateProperties(block).setProperties(StatePropertiesPredicate.Builder.properties().also(configurator)))
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <T : LootItemConditionalFunction.Builder<*>> T.blockStateCondition(block: Block, configurator: StatePropertiesPredicate.Builder.() -> Unit): T {
|
|
||||||
condition(LootItemBlockStatePropertyCondition.hasBlockStateProperties(block).setProperties(StatePropertiesPredicate.Builder.properties().also(configurator)))
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun StatePropertiesPredicate.Builder.set(property: Property<*>, value: String): StatePropertiesPredicate.Builder = hasProperty(property, value)
|
|
||||||
operator fun StatePropertiesPredicate.Builder.set(property: Property<Int>, value: Int): StatePropertiesPredicate.Builder = hasProperty(property, value)
|
|
||||||
operator fun StatePropertiesPredicate.Builder.set(property: Property<Boolean>, value: Boolean): StatePropertiesPredicate.Builder = hasProperty(property, value)
|
|
||||||
operator fun <T : Comparable<T>> StatePropertiesPredicate.Builder.set(property: Property<T>, value: T): StatePropertiesPredicate.Builder {
|
|
||||||
if (value !is StringRepresentable) {
|
|
||||||
throw ClassCastException("Provided type ${value::class.qualifiedName} is not a subtype of ${StringRepresentable::class.qualifiedName}")
|
|
||||||
}
|
|
||||||
|
|
||||||
return hasProperty(property, value.serializedName)
|
|
||||||
}
|
|
||||||
|
|
||||||
data class NbtCopy(val source: String, val destination: String, val strategy: CopyNbtFunction.MergeStrategy = CopyNbtFunction.MergeStrategy.REPLACE)
|
data class NbtCopy(val source: String, val destination: String, val strategy: CopyNbtFunction.MergeStrategy = CopyNbtFunction.MergeStrategy.REPLACE)
|
||||||
|
|
||||||
fun TileNbtCopy(source: String, strategy: CopyNbtFunction.MergeStrategy = CopyNbtFunction.MergeStrategy.REPLACE): NbtCopy {
|
fun TileNbtCopy(source: String, strategy: CopyNbtFunction.MergeStrategy = CopyNbtFunction.MergeStrategy.REPLACE): NbtCopy {
|
||||||
@ -158,7 +94,7 @@ class LootTables(generator: DataGenerator) : LootTableProvider(generator) {
|
|||||||
|
|
||||||
override fun validate(map: MutableMap<ResourceLocation, LootTable>, validationtracker: ValidationContext) {}
|
override fun validate(map: MutableMap<ResourceLocation, LootTable>, validationtracker: ValidationContext) {}
|
||||||
|
|
||||||
fun createSlabItemTable(block: Block) {
|
fun createSlabItemTable(block: Block, configurator: LootPoolSingletonContainer.Builder<*>.() -> Unit = {}) {
|
||||||
builder(LootContextParamSets.BLOCK, block.lootTable) {
|
builder(LootContextParamSets.BLOCK, block.lootTable) {
|
||||||
withPool(
|
withPool(
|
||||||
LootPool.lootPool().setRolls(ConstantValue.exactly(1.0f)).add(
|
LootPool.lootPool().setRolls(ConstantValue.exactly(1.0f)).add(
|
||||||
@ -171,14 +107,16 @@ class LootTables(generator: DataGenerator) : LootTableProvider(generator) {
|
|||||||
.hasProperty(SlabBlock.TYPE, SlabType.DOUBLE)
|
.hasProperty(SlabBlock.TYPE, SlabType.DOUBLE)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
).also(configurator)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createSlabItemTable(block: Collection<Block>) {
|
fun createSlabItemTable(blocks: Collection<Block>, configurator: LootPoolSingletonContainer.Builder<*>.() -> Unit = {}) {
|
||||||
block.forEach(this::createSlabItemTable)
|
for (block in blocks) {
|
||||||
|
createSlabItemTable(block, configurator)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun blockProvider(block: Block, provider: () -> LootTable.Builder) {
|
fun blockProvider(block: Block, provider: () -> LootTable.Builder) {
|
||||||
@ -206,13 +144,23 @@ class LootTables(generator: DataGenerator) : LootTableProvider(generator) {
|
|||||||
fun dropsSelf(vararg blocks: Block) {
|
fun dropsSelf(vararg blocks: Block) {
|
||||||
for (block in blocks) {
|
for (block in blocks) {
|
||||||
singleLootPool(LootContextParamSets.BLOCK, block.lootTable) {
|
singleLootPool(LootContextParamSets.BLOCK, block.lootTable) {
|
||||||
add(LootItem.lootTableItem(block))
|
item(block) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun dropsSelf(blocks: Collection<Block>) {
|
fun dropsSelf(block: Block, configurator: LootPoolSingletonContainer.Builder<*>.() -> Unit = {}) {
|
||||||
blocks.forEach(this::dropsSelf)
|
singleLootPool(LootContextParamSets.BLOCK, block.lootTable) {
|
||||||
|
item(block, configurator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dropsSelf(blocks: Collection<Block>, configurator: LootPoolSingletonContainer.Builder<*>.() -> Unit = {}) {
|
||||||
|
for (block in blocks) {
|
||||||
|
singleLootPool(LootContextParamSets.BLOCK, block.lootTable) {
|
||||||
|
item(block, configurator)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun tile(block: Block, f: (CopyNbtFunction.Builder) -> Unit = {}) {
|
fun tile(block: Block, f: (CopyNbtFunction.Builder) -> Unit = {}) {
|
||||||
|
@ -7,6 +7,7 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties
|
|||||||
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf
|
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf
|
||||||
import net.minecraft.world.level.storage.loot.entries.LootItem
|
import net.minecraft.world.level.storage.loot.entries.LootItem
|
||||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets
|
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets
|
||||||
|
import net.minecraft.world.level.storage.loot.predicates.ExplosionCondition
|
||||||
import ru.dbotthepony.mc.otm.block.entity.ChemicalGeneratorBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.ChemicalGeneratorBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.block.entity.EnergyCounterBlockEntity
|
import ru.dbotthepony.mc.otm.block.entity.EnergyCounterBlockEntity
|
||||||
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity.Companion.ENERGY_KEY
|
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity.Companion.ENERGY_KEY
|
||||||
@ -22,45 +23,45 @@ import ru.dbotthepony.mc.otm.registry.MItems
|
|||||||
import ru.dbotthepony.mc.otm.registry.MRegistry
|
import ru.dbotthepony.mc.otm.registry.MRegistry
|
||||||
|
|
||||||
fun addLootTables(lootTables: LootTables) {
|
fun addLootTables(lootTables: LootTables) {
|
||||||
lootTables.dropsSelf(MRegistry.DECORATIVE_CRATE.allBlocks.values)
|
lootTables.dropsSelf(MRegistry.DECORATIVE_CRATE.allBlocks.values) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
|
|
||||||
lootTables.dropsSelf(MRegistry.CARGO_CRATES.allBlocks.values)
|
lootTables.dropsSelf(MRegistry.CARGO_CRATES.allBlocks.values) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MRegistry.INDUSTRIAL_GLASS.allBlocks.values)
|
lootTables.dropsSelf(MRegistry.INDUSTRIAL_GLASS.allBlocks.values) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MRegistry.INDUSTRIAL_GLASS_PANE.allBlocks.values)
|
lootTables.dropsSelf(MRegistry.INDUSTRIAL_GLASS_PANE.allBlocks.values) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MRegistry.TRITANIUM_BLOCK.allBlocks.values)
|
lootTables.dropsSelf(MRegistry.TRITANIUM_BLOCK.allBlocks.values) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MRegistry.TRITANIUM_WALL.allBlocks.values)
|
lootTables.dropsSelf(MRegistry.TRITANIUM_WALL.allBlocks.values) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MRegistry.TRITANIUM_STAIRS.allBlocks.values)
|
lootTables.dropsSelf(MRegistry.TRITANIUM_STAIRS.allBlocks.values) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.createSlabItemTable(MRegistry.TRITANIUM_SLAB.allBlocks.values)
|
lootTables.createSlabItemTable(MRegistry.TRITANIUM_SLAB.allBlocks.values)
|
||||||
lootTables.dropsSelf(MRegistry.VENT.allBlocks.values)
|
lootTables.dropsSelf(MRegistry.VENT.allBlocks.values) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MRegistry.VENT_ALTERNATIVE.allBlocks.values)
|
lootTables.dropsSelf(MRegistry.VENT_ALTERNATIVE.allBlocks.values) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MRegistry.FLOOR_TILES.blocks.values)
|
lootTables.dropsSelf(MRegistry.FLOOR_TILES.blocks.values) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MRegistry.UNREFINED_FLOOR_TILES.blocks.values)
|
lootTables.dropsSelf(MRegistry.UNREFINED_FLOOR_TILES.blocks.values) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MRegistry.TRITANIUM_STRIPED_BLOCK.flatBlocks)
|
lootTables.dropsSelf(MRegistry.TRITANIUM_STRIPED_BLOCK.flatBlocks) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MRegistry.TRITANIUM_STRIPED_STAIRS.flatBlocks)
|
lootTables.dropsSelf(MRegistry.TRITANIUM_STRIPED_STAIRS.flatBlocks) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MRegistry.TRITANIUM_STRIPED_WALL.flatBlocks)
|
lootTables.dropsSelf(MRegistry.TRITANIUM_STRIPED_WALL.flatBlocks) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.createSlabItemTable(MRegistry.TRITANIUM_STRIPED_SLAB.flatBlocks)
|
lootTables.createSlabItemTable(MRegistry.TRITANIUM_STRIPED_SLAB.flatBlocks) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
|
|
||||||
lootTables.dropsSelf(MRegistry.FLOOR_TILES_STAIRS.blocks.values)
|
lootTables.dropsSelf(MRegistry.FLOOR_TILES_STAIRS.blocks.values) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.createSlabItemTable(MRegistry.FLOOR_TILES_SLAB.blocks.values)
|
lootTables.createSlabItemTable(MRegistry.FLOOR_TILES_SLAB.blocks.values) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
|
|
||||||
lootTables.dropsSelf(MBlocks.CARBON_FIBRE_BLOCK)
|
lootTables.dropsSelf(MBlocks.CARBON_FIBRE_BLOCK) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MBlocks.TRITANIUM_RAW_BLOCK)
|
lootTables.dropsSelf(MBlocks.TRITANIUM_RAW_BLOCK) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MBlocks.TRITANIUM_STRIPED_BLOCK)
|
lootTables.dropsSelf(MBlocks.TRITANIUM_STRIPED_BLOCK) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MBlocks.TRITANIUM_STRIPED_WALL)
|
lootTables.dropsSelf(MBlocks.TRITANIUM_STRIPED_WALL) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MBlocks.TRITANIUM_STRIPED_STAIRS)
|
lootTables.dropsSelf(MBlocks.TRITANIUM_STRIPED_STAIRS) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.createSlabItemTable(MBlocks.TRITANIUM_STRIPED_SLAB)
|
lootTables.createSlabItemTable(MBlocks.TRITANIUM_STRIPED_SLAB) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MBlocks.MATTER_CABLE)
|
lootTables.dropsSelf(MBlocks.MATTER_CABLE) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MBlocks.GRAVITATION_STABILIZER)
|
lootTables.dropsSelf(MBlocks.GRAVITATION_STABILIZER)
|
||||||
lootTables.dropsOther(MBlocks.GRAVITATION_STABILIZER_LENS, MBlocks.GRAVITATION_STABILIZER)
|
lootTables.dropsOther(MBlocks.GRAVITATION_STABILIZER_LENS, MBlocks.GRAVITATION_STABILIZER)
|
||||||
|
|
||||||
lootTables.dropsSelf(MBlocks.LABORATORY_LAMP)
|
lootTables.dropsSelf(MBlocks.LABORATORY_LAMP) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MBlocks.LABORATORY_LAMP_INVERTED)
|
lootTables.dropsSelf(MBlocks.LABORATORY_LAMP_INVERTED) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MBlocks.DANGER_STRIPE_BLOCK)
|
lootTables.dropsSelf(MBlocks.DANGER_STRIPE_BLOCK) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MBlocks.METAL_BEAM)
|
lootTables.dropsSelf(MBlocks.METAL_BEAM) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MBlocks.TRITANIUM_INGOT_BLOCK)
|
lootTables.dropsSelf(MBlocks.TRITANIUM_INGOT_BLOCK) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
|
|
||||||
lootTables.dropsSelf(MBlocks.TRITANIUM_TRAPDOOR)
|
lootTables.dropsSelf(MBlocks.TRITANIUM_TRAPDOOR) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
lootTables.dropsSelf(MRegistry.TRITANIUM_PRESSURE_PLATE.allBlocks.values)
|
lootTables.dropsSelf(MRegistry.TRITANIUM_PRESSURE_PLATE.allBlocks.values) { condition(ExplosionCondition.survivesExplosion()) }
|
||||||
|
|
||||||
lootTables.block(MBlocks.PHANTOM_ATTRACTOR) {
|
lootTables.block(MBlocks.PHANTOM_ATTRACTOR) {
|
||||||
item(MBlocks.PHANTOM_ATTRACTOR) {
|
item(MBlocks.PHANTOM_ATTRACTOR) {
|
||||||
@ -68,6 +69,8 @@ fun addLootTables(lootTables: LootTables) {
|
|||||||
this[BlockStateProperties.DOUBLE_BLOCK_HALF] = DoubleBlockHalf.LOWER
|
this[BlockStateProperties.DOUBLE_BLOCK_HALF] = DoubleBlockHalf.LOWER
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
condition(ExplosionCondition.survivesExplosion())
|
||||||
}
|
}
|
||||||
|
|
||||||
lootTables.block(MBlocks.TRITANIUM_DOOR) {
|
lootTables.block(MBlocks.TRITANIUM_DOOR) {
|
||||||
@ -76,6 +79,8 @@ fun addLootTables(lootTables: LootTables) {
|
|||||||
this[BlockStateProperties.DOUBLE_BLOCK_HALF] = DoubleBlockHalf.LOWER
|
this[BlockStateProperties.DOUBLE_BLOCK_HALF] = DoubleBlockHalf.LOWER
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
condition(ExplosionCondition.survivesExplosion())
|
||||||
}
|
}
|
||||||
|
|
||||||
lootTables.builder(LootContextParamSets.ADVANCEMENT_ENTITY, modLocation("research_all_android")) {
|
lootTables.builder(LootContextParamSets.ADVANCEMENT_ENTITY, modLocation("research_all_android")) {
|
||||||
|
@ -43,6 +43,11 @@ fun addCraftingTableRecipes(consumer: Consumer<FinishedRecipe>) {
|
|||||||
.unlockedBy(MItemTags.TRITANIUM_INGOTS_STORAGE)
|
.unlockedBy(MItemTags.TRITANIUM_INGOTS_STORAGE)
|
||||||
.save(consumer, modLocation("tritanium_ingot_from_storage"))
|
.save(consumer, modLocation("tritanium_ingot_from_storage"))
|
||||||
|
|
||||||
|
ShapelessRecipeBuilder(MItems.ENERGY_COUNTER, 1)
|
||||||
|
.requires(MItems.ENERGY_COUNTER)
|
||||||
|
.unlockedBy(MItems.ENERGY_COUNTER)
|
||||||
|
.save(consumer, modLocation("energy_counter_reset"))
|
||||||
|
|
||||||
MatteryRecipe(MBlocks.PLATE_PRESS)
|
MatteryRecipe(MBlocks.PLATE_PRESS)
|
||||||
.row(MItems.ELECTRIC_PARTS, MItems.ENERGY_BUS, MItems.ELECTRIC_PARTS)
|
.row(MItems.ELECTRIC_PARTS, MItems.ENERGY_BUS, MItems.ELECTRIC_PARTS)
|
||||||
.row(MItemTags.TRITANIUM_INGOTS, Items.BLAST_FURNACE, MItemTags.TRITANIUM_INGOTS)
|
.row(MItemTags.TRITANIUM_INGOTS, Items.BLAST_FURNACE, MItemTags.TRITANIUM_INGOTS)
|
||||||
@ -52,8 +57,7 @@ fun addCraftingTableRecipes(consumer: Consumer<FinishedRecipe>) {
|
|||||||
.build(consumer)
|
.build(consumer)
|
||||||
|
|
||||||
MatteryRecipe(MBlocks.PLATE_PRESS)
|
MatteryRecipe(MBlocks.PLATE_PRESS)
|
||||||
.rowB(MItemTags.BASIC_CIRCUIT)
|
.rowB(MItems.MACHINE_FRAME)
|
||||||
.row(MItemTags.TRITANIUM_PLATES, MItems.MACHINE_FRAME, MItemTags.TRITANIUM_PLATES)
|
|
||||||
.rowAC(MItemTags.PISTONS, MItemTags.PISTONS)
|
.rowAC(MItemTags.PISTONS, MItemTags.PISTONS)
|
||||||
.unlockedBy(MItemTags.TRITANIUM_INGOTS)
|
.unlockedBy(MItemTags.TRITANIUM_INGOTS)
|
||||||
.unlockedBy(MItems.ELECTRIC_PARTS)
|
.unlockedBy(MItems.ELECTRIC_PARTS)
|
||||||
|
@ -208,5 +208,6 @@ fun addTags(tagsProvider: TagsProvider) {
|
|||||||
MobEffects.ABSORPTION,
|
MobEffects.ABSORPTION,
|
||||||
MobEffects.SATURATION,
|
MobEffects.SATURATION,
|
||||||
MobEffects.DOLPHINS_GRACE,
|
MobEffects.DOLPHINS_GRACE,
|
||||||
|
MobEffects.CONFUSION,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -148,6 +148,26 @@ object ServerConfig {
|
|||||||
.comment("If this is disabled, any (technically) excess hunger will be nullified, unless playing on peaceful difficulty.")
|
.comment("If this is disabled, any (technically) excess hunger will be nullified, unless playing on peaceful difficulty.")
|
||||||
.define("regenerateEnergy", true)
|
.define("regenerateEnergy", true)
|
||||||
|
|
||||||
|
object NanobotsRegeneration {
|
||||||
|
val COOLDOWN: List<Int> by specBuilder
|
||||||
|
.comment("In ticks, time between heal ticks")
|
||||||
|
.comment("One heal tick restores 1 heart (2 health points) at most")
|
||||||
|
.comment("If not getting hurt in specified period of ticks, heal tick takes place, tick timer resets to zero and THIS array' index advances by 1")
|
||||||
|
.comment("Index inside this array can not exceed of one of ability's")
|
||||||
|
.comment("")
|
||||||
|
.comment("Wording in pseudocode:")
|
||||||
|
.comment("if (ticksSinceTakingDamage >= cooldownConfigOption[healTicks /* or config's biggest index, whichever is smaller */]) {")
|
||||||
|
.comment(" healTicks = min(healTicks + 1, this.level /* ability level */)")
|
||||||
|
.comment(" ticksSinceTakingDamage = 0")
|
||||||
|
.comment(" this.ply.heal(...)")
|
||||||
|
.comment("}")
|
||||||
|
.defineList("cooldown", { mutableListOf(80, 60, 40, 20) }) { it is Int }
|
||||||
|
|
||||||
|
val ENERGY_PER_HITPOINT by specBuilder
|
||||||
|
.comment("Energy required to regenerate 1 health point (half a heart)")
|
||||||
|
.defineImpreciseFraction("energyPerHitpoint", ImpreciseFraction(800))
|
||||||
|
}
|
||||||
|
|
||||||
val ANDROID_ENERGY_PER_HUNGER_POINT by specBuilder.defineImpreciseFraction("energyPerHunger", ImpreciseFraction(2000), ImpreciseFraction.ZERO)
|
val ANDROID_ENERGY_PER_HUNGER_POINT by specBuilder.defineImpreciseFraction("energyPerHunger", ImpreciseFraction(2000), ImpreciseFraction.ZERO)
|
||||||
val ANDROID_MAX_ENERGY by specBuilder.comment("Internal battery of every android has this much storage").defineImpreciseFraction("capacity", ImpreciseFraction(80_000), ImpreciseFraction.ZERO)
|
val ANDROID_MAX_ENERGY by specBuilder.comment("Internal battery of every android has this much storage").defineImpreciseFraction("capacity", ImpreciseFraction(80_000), ImpreciseFraction.ZERO)
|
||||||
val NIGHT_VISION_POWER_DRAW by specBuilder.defineImpreciseFraction("nightVisionPowerDraw", ImpreciseFraction(8), ImpreciseFraction.ZERO)
|
val NIGHT_VISION_POWER_DRAW by specBuilder.defineImpreciseFraction("nightVisionPowerDraw", ImpreciseFraction(8), ImpreciseFraction.ZERO)
|
||||||
@ -223,6 +243,7 @@ object ServerConfig {
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
// access instances so spec is built
|
// access instances so spec is built
|
||||||
|
NanobotsRegeneration
|
||||||
EnderTeleporter
|
EnderTeleporter
|
||||||
AndroidJumpBoost
|
AndroidJumpBoost
|
||||||
AndroidItemMagnet
|
AndroidItemMagnet
|
||||||
|
@ -3,6 +3,7 @@ package ru.dbotthepony.mc.otm.android.feature
|
|||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.server.level.ServerPlayer
|
import net.minecraft.server.level.ServerPlayer
|
||||||
import net.minecraftforge.event.entity.living.LivingHurtEvent
|
import net.minecraftforge.event.entity.living.LivingHurtEvent
|
||||||
|
import ru.dbotthepony.mc.otm.ServerConfig
|
||||||
import ru.dbotthepony.mc.otm.android.AndroidFeature
|
import ru.dbotthepony.mc.otm.android.AndroidFeature
|
||||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||||
@ -19,16 +20,16 @@ class NanobotsRegenerationFeature(android: MatteryPlayerCapability) : AndroidFea
|
|||||||
if (ply.health > 0f && ply.health < ply.maxHealth) {
|
if (ply.health > 0f && ply.health < ply.maxHealth) {
|
||||||
ticksPassed++
|
ticksPassed++
|
||||||
|
|
||||||
val waitTime = TICKS_BETWEEN_HEAL.getOrElse(healTicks) { TICKS_BETWEEN_HEAL.last() }
|
val waitTime = ServerConfig.NanobotsRegeneration.COOLDOWN.getOrElse(healTicks) { ServerConfig.NanobotsRegeneration.COOLDOWN.last() }
|
||||||
|
|
||||||
if (ticksPassed > waitTime) {
|
if (ticksPassed > waitTime) {
|
||||||
val missingHealth = (ply.maxHealth - ply.health).coerceAtMost(2f)
|
val missingHealth = (ply.maxHealth - ply.health).coerceAtMost(2f)
|
||||||
val power = ENERGY_PER_HITPOINT * missingHealth
|
val power = ServerConfig.NanobotsRegeneration.ENERGY_PER_HITPOINT * missingHealth
|
||||||
val extracted = android.androidEnergy.extractEnergyInner(power, false)
|
val extracted = android.androidEnergy.extractEnergyInner(power, false)
|
||||||
|
|
||||||
if (extracted.isPositive) {
|
if (extracted.isPositive) {
|
||||||
healTicks = (healTicks + 1).coerceAtMost(level)
|
healTicks = (healTicks + 1).coerceAtMost(level)
|
||||||
val healed = (extracted / ENERGY_PER_HITPOINT).toFloat()
|
val healed = (extracted / ServerConfig.NanobotsRegeneration.ENERGY_PER_HITPOINT).toFloat()
|
||||||
ply.heal(healed)
|
ply.heal(healed)
|
||||||
(ply as ServerPlayer?)?.awardStat(StatNames.HEALTH_REGENERATED, (healed * 10f).roundToInt())
|
(ply as ServerPlayer?)?.awardStat(StatNames.HEALTH_REGENERATED, (healed * 10f).roundToInt())
|
||||||
ticksPassed = 0
|
ticksPassed = 0
|
||||||
@ -59,15 +60,4 @@ class NanobotsRegenerationFeature(android: MatteryPlayerCapability) : AndroidFea
|
|||||||
ticksPassed = nbt.getInt("ticksPassed")
|
ticksPassed = nbt.getInt("ticksPassed")
|
||||||
healTicks = nbt.getInt("healTicks")
|
healTicks = nbt.getInt("healTicks")
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val ENERGY_PER_HITPOINT = ImpreciseFraction(800)
|
|
||||||
|
|
||||||
private val TICKS_BETWEEN_HEAL = listOf(
|
|
||||||
100, // 5 seconds
|
|
||||||
80, // 4 seconds
|
|
||||||
60, // 3 seconds
|
|
||||||
40, // 2 seconds
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@ import net.minecraftforge.common.capabilities.Capability
|
|||||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||||
import net.minecraftforge.common.util.LazyOptional
|
import net.minecraftforge.common.util.LazyOptional
|
||||||
import net.minecraftforge.energy.IEnergyStorage
|
import net.minecraftforge.energy.IEnergyStorage
|
||||||
import net.minecraftforge.network.PacketDistributor
|
|
||||||
import ru.dbotthepony.mc.otm.*
|
import ru.dbotthepony.mc.otm.*
|
||||||
import ru.dbotthepony.mc.otm.block.EnergyCounterBlock
|
import ru.dbotthepony.mc.otm.block.EnergyCounterBlock
|
||||||
import ru.dbotthepony.mc.otm.capability.*
|
import ru.dbotthepony.mc.otm.capability.*
|
||||||
@ -126,13 +125,13 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
|||||||
tickOnceServer(this::checkSurroundings)
|
tickOnceServer(this::checkSurroundings)
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class EnergyCounterCap(val is_input: Boolean) : IMatteryEnergyStorage {
|
private inner class EnergyCounterCap(val isInput: Boolean) : IMatteryEnergyStorage {
|
||||||
override fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
|
override fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
|
||||||
return extractEnergyInner(howMuch, simulate)
|
return extractEnergyInner(howMuch, simulate)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
|
override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
|
||||||
if (is_input)
|
if (isInput)
|
||||||
return ImpreciseFraction.ZERO
|
return ImpreciseFraction.ZERO
|
||||||
|
|
||||||
if (inputCapability.isPresent) {
|
if (inputCapability.isPresent) {
|
||||||
@ -164,7 +163,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
|
override fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
|
||||||
if (!is_input)
|
if (!isInput)
|
||||||
return ImpreciseFraction.ZERO
|
return ImpreciseFraction.ZERO
|
||||||
|
|
||||||
if (outputCapability.isPresent) {
|
if (outputCapability.isPresent) {
|
||||||
@ -193,7 +192,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
|||||||
|
|
||||||
override val batteryLevel: ImpreciseFraction
|
override val batteryLevel: ImpreciseFraction
|
||||||
get() {
|
get() {
|
||||||
if (is_input) {
|
if (isInput) {
|
||||||
if (outputCapability.isPresent) {
|
if (outputCapability.isPresent) {
|
||||||
val it = outputCapability.resolve().get()
|
val it = outputCapability.resolve().get()
|
||||||
|
|
||||||
@ -220,7 +219,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
|||||||
|
|
||||||
override val maxBatteryLevel: ImpreciseFraction
|
override val maxBatteryLevel: ImpreciseFraction
|
||||||
get() {
|
get() {
|
||||||
if (is_input) {
|
if (isInput) {
|
||||||
if (outputCapability.isPresent) {
|
if (outputCapability.isPresent) {
|
||||||
val it = outputCapability.resolve().get()
|
val it = outputCapability.resolve().get()
|
||||||
|
|
||||||
@ -247,7 +246,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
|||||||
|
|
||||||
override val missingPower: ImpreciseFraction
|
override val missingPower: ImpreciseFraction
|
||||||
get() {
|
get() {
|
||||||
if (is_input) {
|
if (isInput) {
|
||||||
if (outputCapability.isPresent) {
|
if (outputCapability.isPresent) {
|
||||||
val it = outputCapability.resolve().get()
|
val it = outputCapability.resolve().get()
|
||||||
|
|
||||||
@ -272,15 +271,15 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
|||||||
return ImpreciseFraction.ZERO
|
return ImpreciseFraction.ZERO
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun canExtract() = !is_input
|
override fun canExtract() = !isInput
|
||||||
override fun canReceive() = is_input
|
override fun canReceive() = isInput
|
||||||
}
|
}
|
||||||
|
|
||||||
private var resolverInput = LazyOptional.of<IMatteryEnergyStorage> { energyInput }
|
private var resolverInput = LazyOptional.of<IMatteryEnergyStorage> { energyInput }
|
||||||
private var resolverOutput = LazyOptional.of<IMatteryEnergyStorage> { energyOutput }
|
private var resolverOutput = LazyOptional.of<IMatteryEnergyStorage> { energyOutput }
|
||||||
|
|
||||||
private var resolverInputMekanism = if (isMekanismLoaded) LazyOptional.of { Mattery2MekanismEnergyWrapper(energyInput) } else null
|
private var resolverInputMekanism = if (isMekanismLoaded) LazyOptional.of { Mattery2MekanismEnergyWrapper(energyInput) } else null
|
||||||
private var resolverOutputMekanism = if (isMekanismLoaded) LazyOptional.of { Mattery2MekanismEnergyWrapper(energyInput) } else null
|
private var resolverOutputMekanism = if (isMekanismLoaded) LazyOptional.of { Mattery2MekanismEnergyWrapper(energyOutput) } else null
|
||||||
|
|
||||||
private var valid = true
|
private var valid = true
|
||||||
|
|
||||||
@ -301,7 +300,7 @@ class EnergyCounterBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Mat
|
|||||||
|
|
||||||
if (isMekanismLoaded) {
|
if (isMekanismLoaded) {
|
||||||
resolverInputMekanism = LazyOptional.of { Mattery2MekanismEnergyWrapper(energyInput) }
|
resolverInputMekanism = LazyOptional.of { Mattery2MekanismEnergyWrapper(energyInput) }
|
||||||
resolverOutputMekanism = LazyOptional.of { Mattery2MekanismEnergyWrapper(energyInput) }
|
resolverOutputMekanism = LazyOptional.of { Mattery2MekanismEnergyWrapper(energyOutput) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import net.minecraft.client.renderer.FogRenderer
|
|||||||
import net.minecraft.client.renderer.GameRenderer
|
import net.minecraft.client.renderer.GameRenderer
|
||||||
import net.minecraft.core.Vec3i
|
import net.minecraft.core.Vec3i
|
||||||
import net.minecraft.world.level.levelgen.XoroshiroRandomSource
|
import net.minecraft.world.level.levelgen.XoroshiroRandomSource
|
||||||
|
import net.minecraft.world.level.material.FogType
|
||||||
import org.lwjgl.opengl.GL14
|
import org.lwjgl.opengl.GL14
|
||||||
import ru.dbotthepony.mc.otm.ClientConfig
|
import ru.dbotthepony.mc.otm.ClientConfig
|
||||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||||
@ -465,7 +466,7 @@ object GlitchRenderer {
|
|||||||
makeColorGlitch()
|
makeColorGlitch()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Minecraft.useShaderTransparency()) {
|
if (!Minecraft.useShaderTransparency() && minecraft.gameRenderer.mainCamera.fluidInCamera == FogType.NONE) {
|
||||||
glitchBuffer.bindWrite(true)
|
glitchBuffer.bindWrite(true)
|
||||||
RenderSystem.clearColor(FogRenderer.fogRed, FogRenderer.fogGreen, FogRenderer.fogBlue, 1f)
|
RenderSystem.clearColor(FogRenderer.fogRed, FogRenderer.fogGreen, FogRenderer.fogBlue, 1f)
|
||||||
RenderSystem.clear(GlConst.GL_COLOR_BUFFER_BIT, Minecraft.ON_OSX)
|
RenderSystem.clear(GlConst.GL_COLOR_BUFFER_BIT, Minecraft.ON_OSX)
|
||||||
|
@ -216,6 +216,7 @@ class MatterPanelScreen(
|
|||||||
val input = object : EditBoxPanel<MatterPanelScreen>(this@MatterPanelScreen, rowInput) {
|
val input = object : EditBoxPanel<MatterPanelScreen>(this@MatterPanelScreen, rowInput) {
|
||||||
init {
|
init {
|
||||||
dock = Dock.FILL
|
dock = Dock.FILL
|
||||||
|
requestFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun configureNew(widget: EditBox, recreation: Boolean) {
|
override fun configureNew(widget: EditBox, recreation: Boolean) {
|
||||||
|
@ -1576,7 +1576,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
|
|||||||
open fun tick() {
|
open fun tick() {
|
||||||
tick++
|
tick++
|
||||||
|
|
||||||
for (child in Array(childrenInternal.size) { childrenInternal[it] }) {
|
for (child in Array(visibleChildrenInternal.size) { visibleChildrenInternal[it] }) {
|
||||||
child.tick()
|
child.tick()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,28 @@ import java.util.function.Predicate
|
|||||||
import kotlin.NoSuchElementException
|
import kotlin.NoSuchElementException
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents value which can be encoded onto or decoded from stream.
|
||||||
|
*
|
||||||
|
* Also provides [copy] and [compare] methods
|
||||||
|
*/
|
||||||
interface IStreamCodec<V> {
|
interface IStreamCodec<V> {
|
||||||
fun read(stream: DataInputStream): V
|
fun read(stream: DataInputStream): V
|
||||||
fun write(stream: DataOutputStream, value: V)
|
fun write(stream: DataOutputStream, value: V)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if value is immutable, return it right away
|
||||||
|
*/
|
||||||
fun copy(value: V): V
|
fun copy(value: V): V
|
||||||
fun compare(a: V, b: V): Boolean
|
|
||||||
|
/**
|
||||||
|
* Optional equality check override. Utilized to determine whenever e.g. network value is different from new value
|
||||||
|
*
|
||||||
|
* By default uses [Any.equals]
|
||||||
|
*/
|
||||||
|
fun compare(a: V, b: V): Boolean {
|
||||||
|
return a == b
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class StreamCodec<V>(
|
class StreamCodec<V>(
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
package ru.dbotthepony.mc.otm.data
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList
|
|
||||||
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 java.util.Arrays
|
|
||||||
import java.util.stream.Stream
|
|
||||||
|
|
||||||
class BasicLootAppender(
|
|
||||||
conditions: Array<out LootItemCondition>,
|
|
||||||
items: Stream<ItemStack>
|
|
||||||
) : LootModifier(conditions) {
|
|
||||||
constructor(
|
|
||||||
conditions: Array<out LootItemCondition>,
|
|
||||||
items: Collection<ItemStack>
|
|
||||||
) : this(conditions, items.stream())
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
conditions: Array<out LootItemCondition>,
|
|
||||||
vararg items: ItemStack
|
|
||||||
) : this(conditions, Arrays.stream(items))
|
|
||||||
|
|
||||||
private val items = items.map { it.copy() }.collect(ImmutableList.toImmutableList())
|
|
||||||
|
|
||||||
override fun codec(): Codec<out IGlobalLootModifier> {
|
|
||||||
return CODEC
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun doApply(
|
|
||||||
generatedLoot: ObjectArrayList<ItemStack>,
|
|
||||||
context: LootContext
|
|
||||||
): ObjectArrayList<ItemStack> {
|
|
||||||
for (item in items)
|
|
||||||
generatedLoot.add(item.copy())
|
|
||||||
|
|
||||||
return generatedLoot
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val CODEC: Codec<BasicLootAppender> by lazy {
|
|
||||||
RecordCodecBuilder.create {
|
|
||||||
codecStart(it)
|
|
||||||
.and(ItemStackCodec.LIST.fieldOf("items").forGetter(BasicLootAppender::items))
|
|
||||||
.apply(it, ::BasicLootAppender)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
package ru.dbotthepony.mc.otm.data
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList
|
|
||||||
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 java.util.*
|
|
||||||
import java.util.stream.Stream
|
|
||||||
|
|
||||||
class PlainLootAppender(conditions: Array<out LootItemCondition>, entries: Stream<Pair<ItemStack, Double>>) : LootModifier(conditions) {
|
|
||||||
constructor(conditions: Array<out LootItemCondition>, vararg entries: Pair<ItemStack, Double>) : this(conditions, Arrays.stream(entries))
|
|
||||||
constructor(conditions: Array<out LootItemCondition>, entries: Collection<Pair<ItemStack, Double>>) : this(conditions, entries.stream())
|
|
||||||
|
|
||||||
private val entries = entries.map { it.first.copy() to it.second }.collect(ImmutableList.toImmutableList())
|
|
||||||
|
|
||||||
override fun doApply(generatedLoot: ObjectArrayList<ItemStack>, context: LootContext): ObjectArrayList<ItemStack> {
|
|
||||||
for ((item, chance) in entries) {
|
|
||||||
if (context.random.nextDouble() <= chance) {
|
|
||||||
generatedLoot.add(item.copy())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return generatedLoot
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun codec(): Codec<out IGlobalLootModifier> {
|
|
||||||
return CODEC
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val paircodec: Codec<Pair<ItemStack, Double>> = RecordCodecBuilder.create {
|
|
||||||
it.group(
|
|
||||||
ItemStackCodec.fieldOf("item").forGetter { it.first },
|
|
||||||
Codec.DOUBLE.fieldOf("chance").forGetter { it.second }
|
|
||||||
).apply(it, ::Pair)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val pairlistcodec = Codec.list(paircodec)
|
|
||||||
|
|
||||||
val CODEC: Codec<PlainLootAppender> =
|
|
||||||
RecordCodecBuilder.create {
|
|
||||||
codecStart(it).and(
|
|
||||||
pairlistcodec.fieldOf("entries").forGetter(PlainLootAppender::entries)
|
|
||||||
).apply(it, ::PlainLootAppender)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,195 +0,0 @@
|
|||||||
package ru.dbotthepony.mc.otm.data
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList
|
|
||||||
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.RecordCodecBuilder
|
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList
|
|
||||||
import net.minecraft.util.RandomSource
|
|
||||||
import net.minecraft.util.valueproviders.ConstantInt
|
|
||||||
import net.minecraft.util.valueproviders.IntProvider
|
|
||||||
import net.minecraft.util.valueproviders.UniformInt
|
|
||||||
import net.minecraft.world.entity.player.Player
|
|
||||||
import net.minecraft.world.item.Item
|
|
||||||
import net.minecraft.world.item.ItemStack
|
|
||||||
import net.minecraft.world.item.Rarity
|
|
||||||
import net.minecraft.world.level.ItemLike
|
|
||||||
import net.minecraft.world.level.storage.loot.LootContext
|
|
||||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
|
|
||||||
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
|
|
||||||
import net.minecraftforge.common.loot.LootModifier
|
|
||||||
import net.minecraftforge.registries.ForgeRegistries
|
|
||||||
|
|
||||||
interface IRandomizableItem : ItemLike {
|
|
||||||
fun randomize(itemStack: ItemStack, random: RandomSource, ply: Player?, rarity: Rarity = Rarity.COMMON)
|
|
||||||
}
|
|
||||||
|
|
||||||
class RandomizableItemLootAppender(
|
|
||||||
conditions: Array<out LootItemCondition>,
|
|
||||||
entries: Collection<Entry>
|
|
||||||
) : LootModifier(conditions) {
|
|
||||||
data class Entry(
|
|
||||||
val item: IRandomizableItem,
|
|
||||||
val chance: Double,
|
|
||||||
val count: IntProvider = ConstantInt.of(1),
|
|
||||||
val rarity: Rarity = Rarity.COMMON,
|
|
||||||
val distinct: Boolean = true,
|
|
||||||
) {
|
|
||||||
constructor(
|
|
||||||
item: IRandomizableItem,
|
|
||||||
chance: Double,
|
|
||||||
count: Int,
|
|
||||||
rarity: Rarity = Rarity.COMMON,
|
|
||||||
distinct: Boolean = true,
|
|
||||||
) : this(item, chance, ConstantInt.of(count), rarity, distinct)
|
|
||||||
|
|
||||||
private constructor(
|
|
||||||
item: Item,
|
|
||||||
chance: Double,
|
|
||||||
count: IntProvider,
|
|
||||||
rarity: Rarity = Rarity.COMMON,
|
|
||||||
distinct: Boolean = true,
|
|
||||||
) : this(item as? IRandomizableItem ?: throw ClassCastException("$item is not a subtype of IRandomizableItem"), chance, count, rarity, distinct)
|
|
||||||
|
|
||||||
init {
|
|
||||||
require(count.minValue >= 0) { "Invalid min value ${count.minValue}" }
|
|
||||||
require(count.maxValue >= 0) { "Invalid max value ${count.maxValue}" }
|
|
||||||
require(count.maxValue >= count.minValue) { "Invalid bounds, they must be ${count.maxValue} >= ${count.minValue}!" }
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val CODEC: Codec<Entry> by lazy {
|
|
||||||
RecordCodecBuilder.create {
|
|
||||||
it.group(
|
|
||||||
ForgeRegistries.ITEMS.codec.fieldOf("item").forGetter { it.item.asItem() },
|
|
||||||
Codec.DOUBLE.fieldOf("chance").forGetter(Entry::chance),
|
|
||||||
IntProvider.CODEC.fieldOf("count").forGetter(Entry::count),
|
|
||||||
Rarity::class.codec().fieldOf("rarity").forGetter(Entry::rarity),
|
|
||||||
Codec.BOOL.fieldOf("distinct").forGetter(Entry::distinct),
|
|
||||||
).apply(it, ::Entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val entries: List<Entry> = ImmutableList.copyOf(entries)
|
|
||||||
|
|
||||||
override fun codec(): Codec<RandomizableItemLootAppender> {
|
|
||||||
return Companion
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun doApply(
|
|
||||||
generatedLoot: ObjectArrayList<ItemStack>,
|
|
||||||
context: LootContext
|
|
||||||
): ObjectArrayList<ItemStack> {
|
|
||||||
val random = context.random
|
|
||||||
|
|
||||||
val player =
|
|
||||||
context.getParamOrNull(LootContextParams.DIRECT_KILLER_ENTITY).let {
|
|
||||||
if (it != null)
|
|
||||||
it as? Player
|
|
||||||
else
|
|
||||||
context.getParamOrNull(LootContextParams.KILLER_ENTITY).let {
|
|
||||||
if (it != null)
|
|
||||||
it as? Player
|
|
||||||
else
|
|
||||||
context.getParamOrNull(LootContextParams.THIS_ENTITY) as? Player
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for ((item, chance, count, rarity, distinct) in entries) {
|
|
||||||
if (random.nextDouble() <= chance) {
|
|
||||||
if (distinct) {
|
|
||||||
val items = ArrayList<ItemStack>()
|
|
||||||
|
|
||||||
for (i in 0 until count.sample(random)) {
|
|
||||||
val stack = ItemStack(item.asItem(), 1)
|
|
||||||
item.randomize(stack, random, player, rarity)
|
|
||||||
|
|
||||||
for (existing in items) {
|
|
||||||
if (ItemStack.isSameItemSameTags(existing, stack)) {
|
|
||||||
existing.count += stack.count
|
|
||||||
stack.count = 0
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stack.count > 0) {
|
|
||||||
items.add(stack)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (stack in items) {
|
|
||||||
while (stack.count > stack.maxStackSize && stack.maxStackSize > 0) {
|
|
||||||
val split = stack.split(stack.maxStackSize)
|
|
||||||
generatedLoot.add(split)
|
|
||||||
}
|
|
||||||
|
|
||||||
generatedLoot.add(stack)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val stack = ItemStack(item.asItem(), count.sample(random))
|
|
||||||
item.randomize(stack, random, player, rarity)
|
|
||||||
|
|
||||||
while (stack.count > stack.maxStackSize && stack.maxStackSize > 0) {
|
|
||||||
val split = stack.split(stack.maxStackSize)
|
|
||||||
generatedLoot.add(split)
|
|
||||||
}
|
|
||||||
|
|
||||||
generatedLoot.add(stack)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return generatedLoot
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object : Codec<RandomizableItemLootAppender> {
|
|
||||||
override fun <T : Any> encode(
|
|
||||||
input: RandomizableItemLootAppender,
|
|
||||||
ops: DynamicOps<T>,
|
|
||||||
prefix: T
|
|
||||||
): DataResult<T> {
|
|
||||||
require(prefix == ops.empty()) { "Non-empty prefix: $prefix" }
|
|
||||||
|
|
||||||
return LOOT_CONDITIONS_CODEC.encode(input.conditions, ops, prefix).flatMap map@{
|
|
||||||
val encodedEntries = input.entries.map { Entry.CODEC.encode(it, ops, prefix) }
|
|
||||||
val firstError = encodedEntries.firstOrNull { !it.result().isPresent }
|
|
||||||
|
|
||||||
if (firstError != null) {
|
|
||||||
return@map firstError
|
|
||||||
}
|
|
||||||
|
|
||||||
return@map DataResult.success(ops.createMap(linkedMapOf(
|
|
||||||
ops.createString("conditions") to it,
|
|
||||||
ops.createString("entries") to ops.createList(encodedEntries.stream().map { it.result().get() })
|
|
||||||
)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun <T : Any> decode(
|
|
||||||
ops: DynamicOps<T>,
|
|
||||||
input: T
|
|
||||||
): DataResult<Pair<RandomizableItemLootAppender, T>> {
|
|
||||||
return ops.getMap(input).flatMap { map ->
|
|
||||||
LOOT_CONDITIONS_CODEC.decode(ops, map["conditions"]).flatMap {
|
|
||||||
val conditions = it.first
|
|
||||||
|
|
||||||
ops.getStream(map["entries"]).flatMap {
|
|
||||||
val collected = it.map { Entry.CODEC.decode(ops, it) }.toList()
|
|
||||||
|
|
||||||
for ((i, element) in collected.withIndex()) {
|
|
||||||
if (element.result().isEmpty) {
|
|
||||||
return@flatMap DataResult.error("Invalid entry at $i: ${element.error().get().message()}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return@flatMap DataResult.success(Pair.of(RandomizableItemLootAppender(conditions, collected.map { it.result().get().first }), ops.empty()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,44 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.data.condition
|
||||||
|
|
||||||
|
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.world.level.storage.loot.LootContext
|
||||||
|
import net.minecraft.world.level.storage.loot.Serializer
|
||||||
|
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
|
||||||
|
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
|
||||||
|
import ru.dbotthepony.mc.otm.core.set
|
||||||
|
import ru.dbotthepony.mc.otm.registry.MLootItemConditions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* u serious?
|
||||||
|
*/
|
||||||
|
data class ChanceCondition(val chance: Double) : LootItemCondition, LootItemCondition.Builder {
|
||||||
|
init {
|
||||||
|
require(chance in 0.0 .. 1.0) { "Invalid chance: $chance" }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun test(t: LootContext): Boolean {
|
||||||
|
return t.random.nextDouble() < chance
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getType(): LootItemConditionType {
|
||||||
|
return MLootItemConditions.CHANCE
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun build(): LootItemCondition {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object : Serializer<ChanceCondition> {
|
||||||
|
override fun serialize(p_79325_: JsonObject, p_79326_: ChanceCondition, p_79327_: JsonSerializationContext) {
|
||||||
|
p_79325_["chance"] = JsonPrimitive(p_79326_.chance)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deserialize(p_79323_: JsonObject, p_79324_: JsonDeserializationContext): ChanceCondition {
|
||||||
|
return ChanceCondition(p_79323_["chance"]?.asDouble ?: throw JsonSyntaxException("Invalid chance json element"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package ru.dbotthepony.mc.otm.data
|
package ru.dbotthepony.mc.otm.data.condition
|
||||||
|
|
||||||
import com.google.gson.JsonDeserializationContext
|
import com.google.gson.JsonDeserializationContext
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
@ -11,9 +11,10 @@ import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
|
|||||||
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
|
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
|
||||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||||
import ru.dbotthepony.mc.otm.core.set
|
import ru.dbotthepony.mc.otm.core.set
|
||||||
|
import ru.dbotthepony.mc.otm.data.get
|
||||||
import ru.dbotthepony.mc.otm.registry.MLootItemConditions
|
import ru.dbotthepony.mc.otm.registry.MLootItemConditions
|
||||||
|
|
||||||
class ChanceWithPlaytimeCondition(
|
data class ChanceWithPlaytimeCondition(
|
||||||
val minPlaytime: Int = 0,
|
val minPlaytime: Int = 0,
|
||||||
val maxPlaytime: Int,
|
val maxPlaytime: Int,
|
||||||
val minProbability: Double,
|
val minProbability: Double,
|
@ -1,4 +1,4 @@
|
|||||||
package ru.dbotthepony.mc.otm.data
|
package ru.dbotthepony.mc.otm.data.condition
|
||||||
|
|
||||||
import com.google.gson.JsonDeserializationContext
|
import com.google.gson.JsonDeserializationContext
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
@ -10,6 +10,7 @@ import net.minecraft.world.level.storage.loot.predicates.InvertedLootItemConditi
|
|||||||
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
|
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
|
||||||
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
|
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
|
||||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||||
|
import ru.dbotthepony.mc.otm.data.get
|
||||||
import ru.dbotthepony.mc.otm.registry.MLootItemConditions
|
import ru.dbotthepony.mc.otm.registry.MLootItemConditions
|
||||||
|
|
||||||
object HasExosuitCondition : LootItemCondition, Serializer<HasExosuitCondition>, LootItemCondition.Builder {
|
object HasExosuitCondition : LootItemCondition, Serializer<HasExosuitCondition>, LootItemCondition.Builder {
|
@ -1,4 +1,4 @@
|
|||||||
package ru.dbotthepony.mc.otm.data
|
package ru.dbotthepony.mc.otm.data.condition
|
||||||
|
|
||||||
import com.google.gson.JsonDeserializationContext
|
import com.google.gson.JsonDeserializationContext
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
@ -17,9 +17,10 @@ import net.minecraftforge.registries.ForgeRegistries
|
|||||||
import ru.dbotthepony.mc.otm.capability.itemsStream
|
import ru.dbotthepony.mc.otm.capability.itemsStream
|
||||||
import ru.dbotthepony.mc.otm.core.registryName
|
import ru.dbotthepony.mc.otm.core.registryName
|
||||||
import ru.dbotthepony.mc.otm.core.set
|
import ru.dbotthepony.mc.otm.core.set
|
||||||
|
import ru.dbotthepony.mc.otm.data.get
|
||||||
import ru.dbotthepony.mc.otm.registry.MLootItemConditions
|
import ru.dbotthepony.mc.otm.registry.MLootItemConditions
|
||||||
|
|
||||||
class ItemInInventoryCondition(
|
data class ItemInInventoryCondition(
|
||||||
val item: ItemStack,
|
val item: ItemStack,
|
||||||
val matchDamage: Boolean = false,
|
val matchDamage: Boolean = false,
|
||||||
val matchNBT: Boolean = false,
|
val matchNBT: Boolean = false,
|
@ -1,4 +1,4 @@
|
|||||||
package ru.dbotthepony.mc.otm.data
|
package ru.dbotthepony.mc.otm.data.condition
|
||||||
|
|
||||||
import com.google.gson.JsonDeserializationContext
|
import com.google.gson.JsonDeserializationContext
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
@ -10,7 +10,7 @@ import net.minecraft.world.level.storage.loot.predicates.InvertedLootItemConditi
|
|||||||
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
|
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
|
||||||
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
|
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
|
||||||
import net.minecraftforge.common.util.FakePlayer
|
import net.minecraftforge.common.util.FakePlayer
|
||||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
import ru.dbotthepony.mc.otm.data.get
|
||||||
import ru.dbotthepony.mc.otm.registry.MLootItemConditions
|
import ru.dbotthepony.mc.otm.registry.MLootItemConditions
|
||||||
|
|
||||||
object KilledByRealPlayer : LootItemCondition, Serializer<KilledByRealPlayer>, LootItemCondition.Builder {
|
object KilledByRealPlayer : LootItemCondition, Serializer<KilledByRealPlayer>, LootItemCondition.Builder {
|
@ -1,4 +1,4 @@
|
|||||||
package ru.dbotthepony.mc.otm.data
|
package ru.dbotthepony.mc.otm.data.condition
|
||||||
|
|
||||||
import com.google.gson.JsonDeserializationContext
|
import com.google.gson.JsonDeserializationContext
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
@ -12,6 +12,7 @@ import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
|
|||||||
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
|
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
|
||||||
import net.minecraftforge.common.util.FakePlayer
|
import net.minecraftforge.common.util.FakePlayer
|
||||||
import ru.dbotthepony.mc.otm.NULLABLE_MINECRAFT_SERVER
|
import ru.dbotthepony.mc.otm.NULLABLE_MINECRAFT_SERVER
|
||||||
|
import ru.dbotthepony.mc.otm.data.get
|
||||||
import ru.dbotthepony.mc.otm.registry.MLootItemConditions
|
import ru.dbotthepony.mc.otm.registry.MLootItemConditions
|
||||||
|
|
||||||
object KilledByRealPlayerOrIndirectly : LootItemCondition, Serializer<KilledByRealPlayerOrIndirectly>, LootItemCondition.Builder {
|
object KilledByRealPlayerOrIndirectly : LootItemCondition, Serializer<KilledByRealPlayerOrIndirectly>, LootItemCondition.Builder {
|
@ -0,0 +1,11 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.data.loot
|
||||||
|
|
||||||
|
import net.minecraft.util.RandomSource
|
||||||
|
import net.minecraft.world.entity.player.Player
|
||||||
|
import net.minecraft.world.item.ItemStack
|
||||||
|
import net.minecraft.world.item.Rarity
|
||||||
|
import net.minecraft.world.level.ItemLike
|
||||||
|
|
||||||
|
interface IRandomizableItem {
|
||||||
|
fun randomize(itemStack: ItemStack, random: RandomSource, ply: Player?, rarity: Rarity = Rarity.COMMON)
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package ru.dbotthepony.mc.otm.data
|
package ru.dbotthepony.mc.otm.data.loot
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
import com.google.gson.*
|
import com.google.gson.*
|
||||||
@ -8,14 +8,17 @@ import com.mojang.serialization.Dynamic
|
|||||||
import com.mojang.serialization.JsonOps
|
import com.mojang.serialization.JsonOps
|
||||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList
|
||||||
|
import net.minecraft.resources.ResourceLocation
|
||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import net.minecraft.world.level.storage.loot.Deserializers
|
import net.minecraft.world.level.storage.loot.Deserializers
|
||||||
import net.minecraft.world.level.storage.loot.LootContext
|
import net.minecraft.world.level.storage.loot.LootContext
|
||||||
import net.minecraft.world.level.storage.loot.LootPool
|
import net.minecraft.world.level.storage.loot.LootPool
|
||||||
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
|
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
|
||||||
|
import net.minecraftforge.common.ForgeHooks
|
||||||
import net.minecraftforge.common.loot.IGlobalLootModifier
|
import net.minecraftforge.common.loot.IGlobalLootModifier
|
||||||
import net.minecraftforge.common.loot.LootModifier
|
import net.minecraftforge.common.loot.LootModifier
|
||||||
import java.util.Arrays
|
import java.util.Arrays
|
||||||
|
import java.util.Deque
|
||||||
import java.util.stream.Stream
|
import java.util.stream.Stream
|
||||||
|
|
||||||
class LootPoolAppender(conditions: Array<out LootItemCondition>, pools: Stream<LootPool>) : LootModifier(conditions) {
|
class LootPoolAppender(conditions: Array<out LootItemCondition>, pools: Stream<LootPool>) : LootModifier(conditions) {
|
||||||
@ -25,7 +28,10 @@ class LootPoolAppender(conditions: Array<out LootItemCondition>, pools: Stream<L
|
|||||||
constructor(conditions: Array<out LootItemCondition>, vararg pools: LootPool) : this(conditions, Arrays.stream(pools))
|
constructor(conditions: Array<out LootItemCondition>, vararg pools: LootPool) : this(conditions, Arrays.stream(pools))
|
||||||
|
|
||||||
override fun doApply(generatedLoot: ObjectArrayList<ItemStack>, context: LootContext): ObjectArrayList<ItemStack> {
|
override fun doApply(generatedLoot: ObjectArrayList<ItemStack>, context: LootContext): ObjectArrayList<ItemStack> {
|
||||||
pools.forEach { it.addRandomItems(generatedLoot::add, context) }
|
for (pool in pools) {
|
||||||
|
pool.addRandomItems(generatedLoot::add, context)
|
||||||
|
}
|
||||||
|
|
||||||
return generatedLoot
|
return generatedLoot
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,23 +39,39 @@ class LootPoolAppender(conditions: Array<out LootItemCondition>, pools: Stream<L
|
|||||||
return CODEC
|
return CODEC
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: remove reflection once Forge implement a way to provide lootpool deserialization context in non-reflective way
|
||||||
companion object {
|
companion object {
|
||||||
// same bro
|
private val lootPoolCodec: Codec<List<LootPool>>
|
||||||
private fun getJson(it: Dynamic<Any?>): JsonElement {
|
|
||||||
val value = it.value ?: throw NullPointerException("value was null")
|
private val forgeHooksLootContext by lazy {
|
||||||
return value as? JsonElement ?: it.ops.convertTo(JsonOps.INSTANCE, it)
|
val field = ForgeHooks::class.java.getDeclaredField("lootContext")
|
||||||
|
field.isAccessible = true
|
||||||
|
field
|
||||||
}
|
}
|
||||||
|
|
||||||
private val lootPoolCodec: Codec<List<LootPool>>
|
private val lootTableContextConstructor by lazy {
|
||||||
|
val clazz = ForgeHooks::class.java.declaredClasses.firstOrNull { it.name.contains("LootTableContext") } ?: throw NoSuchElementException("Unable to find ForgeHooks\$LootTableContext!")
|
||||||
|
val constructor = clazz.getDeclaredConstructor(ResourceLocation::class.java, Boolean::class.java)
|
||||||
|
constructor.isAccessible = true
|
||||||
|
constructor
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val serializer = Deserializers.createLootTableSerializer().create()
|
val serializer = Deserializers.createLootTableSerializer().create()
|
||||||
|
val notExistingLocation = ResourceLocation("null", "null")
|
||||||
|
|
||||||
lootPoolCodec = Codec.list(Codec.PASSTHROUGH.flatXmap({
|
lootPoolCodec = Codec.list(Codec.PASSTHROUGH.flatXmap({
|
||||||
|
val dequeueHolder = forgeHooksLootContext.get(null) as ThreadLocal<Deque<Any>>
|
||||||
|
val deque = dequeueHolder.get() ?: java.util.ArrayDeque()
|
||||||
|
dequeueHolder.set(deque)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
DataResult.success(serializer.fromJson(getJson(it as Dynamic<Any?>), LootPool::class.java))
|
deque.push(lootTableContextConstructor.newInstance(notExistingLocation, true))
|
||||||
|
DataResult.success(serializer.fromJson(it.convert(JsonOps.INSTANCE).value, LootPool::class.java))
|
||||||
} catch(err: JsonSyntaxException) {
|
} catch(err: JsonSyntaxException) {
|
||||||
DataResult.error(err.message)
|
DataResult.error(err.message)
|
||||||
|
} finally {
|
||||||
|
deque.pop()
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
try {
|
try {
|
@ -0,0 +1,81 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.data.loot
|
||||||
|
|
||||||
|
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.world.entity.player.Player
|
||||||
|
import net.minecraft.world.item.ItemStack
|
||||||
|
import net.minecraft.world.item.Rarity
|
||||||
|
import net.minecraft.world.level.storage.loot.LootContext
|
||||||
|
import net.minecraft.world.level.storage.loot.Serializer
|
||||||
|
import net.minecraft.world.level.storage.loot.functions.LootItemFunction
|
||||||
|
import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType
|
||||||
|
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
|
||||||
|
import org.apache.logging.log4j.LogManager
|
||||||
|
import ru.dbotthepony.mc.otm.core.set
|
||||||
|
import ru.dbotthepony.mc.otm.registry.MItemFunctionTypes
|
||||||
|
|
||||||
|
enum class RandomizerFunction(val rarity: Rarity) : LootItemFunction, LootItemFunction.Builder {
|
||||||
|
COMMON(Rarity.COMMON),
|
||||||
|
UNCOMMON(Rarity.UNCOMMON),
|
||||||
|
RARE(Rarity.RARE),
|
||||||
|
EPIC(Rarity.EPIC);
|
||||||
|
|
||||||
|
override fun apply(itemStack: ItemStack, context: LootContext): ItemStack {
|
||||||
|
val randomizer = itemStack.item as? IRandomizableItem
|
||||||
|
|
||||||
|
if (randomizer == null) {
|
||||||
|
LOGGER.error("${itemStack.item} does not implement ${IRandomizableItem::class.qualifiedName}! Can not randomize $itemStack!")
|
||||||
|
return itemStack
|
||||||
|
}
|
||||||
|
|
||||||
|
val random = context.random
|
||||||
|
|
||||||
|
val player =
|
||||||
|
context.getParamOrNull(LootContextParams.DIRECT_KILLER_ENTITY).let {
|
||||||
|
if (it != null)
|
||||||
|
it as? Player
|
||||||
|
else
|
||||||
|
context.getParamOrNull(LootContextParams.KILLER_ENTITY).let {
|
||||||
|
if (it != null)
|
||||||
|
it as? Player
|
||||||
|
else
|
||||||
|
context.getParamOrNull(LootContextParams.THIS_ENTITY) as? Player
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
randomizer.randomize(itemStack, random, player, rarity)
|
||||||
|
return itemStack
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getType(): LootItemFunctionType {
|
||||||
|
return MItemFunctionTypes.RANDOMIZER
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun build(): LootItemFunction {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object : Serializer<RandomizerFunction> {
|
||||||
|
fun valueOf(rarity: Rarity): RandomizerFunction {
|
||||||
|
return when(rarity) {
|
||||||
|
Rarity.COMMON -> COMMON
|
||||||
|
Rarity.UNCOMMON -> UNCOMMON
|
||||||
|
Rarity.RARE -> RARE
|
||||||
|
Rarity.EPIC -> EPIC
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(p_79325_: JsonObject, p_79326_: RandomizerFunction, p_79327_: JsonSerializationContext) {
|
||||||
|
p_79325_["rarity"] = JsonPrimitive(p_79326_.rarity.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deserialize(p_79323_: JsonObject, p_79324_: JsonDeserializationContext): RandomizerFunction {
|
||||||
|
return valueOf(Rarity.valueOf(p_79323_["rarity"]?.asString ?: throw JsonSyntaxException("Invalid rarity json element")))
|
||||||
|
}
|
||||||
|
|
||||||
|
private val LOGGER = LogManager.getLogger()
|
||||||
|
}
|
||||||
|
}
|
@ -11,11 +11,12 @@ import net.minecraft.world.level.Level
|
|||||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||||
import ru.dbotthepony.mc.otm.core.set
|
import ru.dbotthepony.mc.otm.core.set
|
||||||
import ru.dbotthepony.mc.otm.core.tagNotNull
|
import ru.dbotthepony.mc.otm.core.tagNotNull
|
||||||
import ru.dbotthepony.mc.otm.data.IRandomizableItem
|
import ru.dbotthepony.mc.otm.data.loot.IRandomizableItem
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") // .tab(null) is a legal statement because tab field itself is nullable
|
@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") // .tab(null) is a legal statement because tab field itself is nullable
|
||||||
class ProceduralExoSuitSlotUpgradeItem : AbstractExoSuitSlotUpgradeItem(defaultProperties().tab(null)), IRandomizableItem {
|
class ProceduralExoSuitSlotUpgradeItem : AbstractExoSuitSlotUpgradeItem(defaultProperties().tab(null)),
|
||||||
|
IRandomizableItem {
|
||||||
override fun getRarity(itemStack: ItemStack): Rarity {
|
override fun getRarity(itemStack: ItemStack): Rarity {
|
||||||
return when (slotCount(itemStack)) {
|
return when (slotCount(itemStack)) {
|
||||||
in 0 .. 9 -> Rarity.COMMON
|
in 0 .. 9 -> Rarity.COMMON
|
||||||
|
@ -34,10 +34,10 @@ private object TritaniumArmorMaterial : ArmorMaterial {
|
|||||||
|
|
||||||
override fun getDefenseForSlot(p_40411_: EquipmentSlot): Int {
|
override fun getDefenseForSlot(p_40411_: EquipmentSlot): Int {
|
||||||
return when (p_40411_) {
|
return when (p_40411_) {
|
||||||
EquipmentSlot.FEET -> 4
|
EquipmentSlot.FEET -> 3
|
||||||
EquipmentSlot.LEGS -> 7
|
EquipmentSlot.LEGS -> 6
|
||||||
EquipmentSlot.CHEST -> 12
|
EquipmentSlot.CHEST -> 8
|
||||||
EquipmentSlot.HEAD -> 5
|
EquipmentSlot.HEAD -> 3
|
||||||
else -> throw IllegalArgumentException("yo dude what the fuck")
|
else -> throw IllegalArgumentException("yo dude what the fuck")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,12 @@ class ExoSuitInventoryMenu(val capability: MatteryPlayerCapability) : MatteryMen
|
|||||||
init {
|
init {
|
||||||
for ((a, b) in curiosSlots) {
|
for ((a, b) in curiosSlots) {
|
||||||
addSlot(a)
|
addSlot(a)
|
||||||
if (b != null) addSlot(b)
|
storage2Inventory(a)
|
||||||
|
|
||||||
|
if (b != null) {
|
||||||
|
addSlot(b)
|
||||||
|
storage2Inventory(b)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,6 +94,24 @@ enum class MapAction {
|
|||||||
CLEAR, ADD, REMOVE
|
CLEAR, ADD, REMOVE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Universal one-to-many value synchronizer
|
||||||
|
*
|
||||||
|
* This class represent collection of synchronizable values (similar to entitydata or menu's dataslots)
|
||||||
|
*
|
||||||
|
* Advantages of this class are:
|
||||||
|
* * It can be freely pooled. You can call [collectNetworkPayload] and [FieldSynchronizer.Endpoint.collectNetworkPayload] as much as you like,
|
||||||
|
* because they use dirty lists to track which fields need networking. **Warning**: If you attach one or more "observed" values (more on them below),
|
||||||
|
* each call to above methods will cause scan on observed fields.
|
||||||
|
* * It is universal. No, seriously, you can use it anywhere, all it needs is you encode [FastByteArrayOutputStream], send it over your
|
||||||
|
* networking channel, and create [InputStream] to feed to [FieldSynchronizer.Endpoint]
|
||||||
|
* * Its capabilities at networking are only limited by codecs you provide, see [FieldSynchronizer.Field], [IStreamCodec]
|
||||||
|
* * Provides not only single values, but also smart [FieldSynchronizer.Map] map synchronization
|
||||||
|
* * Has network version "conflict" resolver. If source FieldSynchronizer and target FieldSynchronizer have different set of fields, they can figure out how to synchronize
|
||||||
|
* only known fields. **Keep in mind this only works if you manually specify names on ALL created fields**
|
||||||
|
* * Directly bytestream embeddable. [FieldSynchronizer.Endpoint] always knows how much bytes to read from incoming stream, you can directly embed it into your data flow
|
||||||
|
* on network channel.
|
||||||
|
*/
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCallback: Boolean) {
|
class FieldSynchronizer(private val callback: Runnable, private val alwaysCallCallback: Boolean) {
|
||||||
constructor() : this(Runnable {}, false)
|
constructor() : this(Runnable {}, false)
|
||||||
|
@ -4,19 +4,13 @@ import net.minecraftforge.eventbus.api.IEventBus
|
|||||||
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.LootPoolAppender
|
import ru.dbotthepony.mc.otm.data.loot.LootPoolAppender
|
||||||
import ru.dbotthepony.mc.otm.data.BasicLootAppender
|
|
||||||
import ru.dbotthepony.mc.otm.data.PlainLootAppender
|
|
||||||
import ru.dbotthepony.mc.otm.data.RandomizableItemLootAppender
|
|
||||||
|
|
||||||
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") { LootPoolAppender.CODEC }
|
registry.register("loot_appender") { LootPoolAppender.CODEC }
|
||||||
registry.register("loot_appender_separated") { PlainLootAppender.CODEC }
|
|
||||||
registry.register("loot_appender_basic") { BasicLootAppender.CODEC }
|
|
||||||
registry.register("randomizable_item_loot_appender") { RandomizableItemLootAppender.Companion }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun register(bus: IEventBus) {
|
internal fun register(bus: IEventBus) {
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.registry
|
||||||
|
|
||||||
|
import net.minecraft.core.Registry
|
||||||
|
import net.minecraft.resources.ResourceLocation
|
||||||
|
import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType
|
||||||
|
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
|
||||||
|
import net.minecraftforge.registries.RegisterEvent
|
||||||
|
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||||
|
import ru.dbotthepony.mc.otm.data.loot.RandomizerFunction
|
||||||
|
|
||||||
|
object MItemFunctionTypes {
|
||||||
|
val RANDOMIZER = LootItemFunctionType(RandomizerFunction.Companion)
|
||||||
|
|
||||||
|
internal fun register(event: RegisterEvent) {
|
||||||
|
if (event.getVanillaRegistry<LootItemConditionType>() == Registry.LOOT_FUNCTION_TYPE) {
|
||||||
|
Registry.LOOT_FUNCTION_TYPE.register(ResourceLocation(OverdriveThatMatters.MOD_ID, "randomizer"), RANDOMIZER)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,14 +3,14 @@ package ru.dbotthepony.mc.otm.registry
|
|||||||
import net.minecraft.core.Registry
|
import net.minecraft.core.Registry
|
||||||
import net.minecraft.resources.ResourceLocation
|
import net.minecraft.resources.ResourceLocation
|
||||||
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
|
import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
|
||||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent
|
|
||||||
import net.minecraftforge.registries.RegisterEvent
|
import net.minecraftforge.registries.RegisterEvent
|
||||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||||
import ru.dbotthepony.mc.otm.data.ChanceWithPlaytimeCondition
|
import ru.dbotthepony.mc.otm.data.condition.ChanceWithPlaytimeCondition
|
||||||
import ru.dbotthepony.mc.otm.data.HasExosuitCondition
|
import ru.dbotthepony.mc.otm.data.condition.HasExosuitCondition
|
||||||
import ru.dbotthepony.mc.otm.data.ItemInInventoryCondition
|
import ru.dbotthepony.mc.otm.data.condition.ItemInInventoryCondition
|
||||||
import ru.dbotthepony.mc.otm.data.KilledByRealPlayer
|
import ru.dbotthepony.mc.otm.data.condition.KilledByRealPlayer
|
||||||
import ru.dbotthepony.mc.otm.data.KilledByRealPlayerOrIndirectly
|
import ru.dbotthepony.mc.otm.data.condition.KilledByRealPlayerOrIndirectly
|
||||||
|
import ru.dbotthepony.mc.otm.data.condition.ChanceCondition
|
||||||
|
|
||||||
object MLootItemConditions {
|
object MLootItemConditions {
|
||||||
val HAS_EXOSUIT = LootItemConditionType(HasExosuitCondition)
|
val HAS_EXOSUIT = LootItemConditionType(HasExosuitCondition)
|
||||||
@ -18,6 +18,7 @@ object MLootItemConditions {
|
|||||||
val KILLED_BY_REAL_PLAYER_OR_INDIRECTLY = LootItemConditionType(KilledByRealPlayerOrIndirectly)
|
val KILLED_BY_REAL_PLAYER_OR_INDIRECTLY = LootItemConditionType(KilledByRealPlayerOrIndirectly)
|
||||||
val CHANCE_WITH_PLAYTIME = LootItemConditionType(ChanceWithPlaytimeCondition)
|
val CHANCE_WITH_PLAYTIME = LootItemConditionType(ChanceWithPlaytimeCondition)
|
||||||
val ITEM_IN_INVENTORY = LootItemConditionType(ItemInInventoryCondition)
|
val ITEM_IN_INVENTORY = LootItemConditionType(ItemInInventoryCondition)
|
||||||
|
val CHANCE = LootItemConditionType(ChanceCondition.Companion)
|
||||||
|
|
||||||
internal fun register(event: RegisterEvent) {
|
internal fun register(event: RegisterEvent) {
|
||||||
if (event.getVanillaRegistry<LootItemConditionType>() == Registry.LOOT_CONDITION_TYPE) {
|
if (event.getVanillaRegistry<LootItemConditionType>() == Registry.LOOT_CONDITION_TYPE) {
|
||||||
@ -26,6 +27,7 @@ object MLootItemConditions {
|
|||||||
Registry.LOOT_CONDITION_TYPE.register(ResourceLocation(OverdriveThatMatters.MOD_ID, "item_in_inventory"), ITEM_IN_INVENTORY)
|
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)
|
Registry.LOOT_CONDITION_TYPE.register(ResourceLocation(OverdriveThatMatters.MOD_ID, "killed_by_real_player"), KILLED_BY_REAL_PLAYER)
|
||||||
Registry.LOOT_CONDITION_TYPE.register(ResourceLocation(OverdriveThatMatters.MOD_ID, "killed_by_real_player_or_indirectly"), KILLED_BY_REAL_PLAYER_OR_INDIRECTLY)
|
Registry.LOOT_CONDITION_TYPE.register(ResourceLocation(OverdriveThatMatters.MOD_ID, "killed_by_real_player_or_indirectly"), KILLED_BY_REAL_PLAYER_OR_INDIRECTLY)
|
||||||
|
Registry.LOOT_CONDITION_TYPE.register(ResourceLocation(OverdriveThatMatters.MOD_ID, "chance"), CHANCE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,6 +262,7 @@ object MRegistry {
|
|||||||
bus.addListener(this::initializeCommon)
|
bus.addListener(this::initializeCommon)
|
||||||
bus.addListener(MStats::registerVanilla)
|
bus.addListener(MStats::registerVanilla)
|
||||||
bus.addListener(MLootItemConditions::register)
|
bus.addListener(MLootItemConditions::register)
|
||||||
|
bus.addListener(MItemFunctionTypes::register)
|
||||||
|
|
||||||
MBlocks.register(bus)
|
MBlocks.register(bus)
|
||||||
MBlockEntities.register(bus)
|
MBlockEntities.register(bus)
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
|
|
||||||
"pattern": [
|
"pattern": [
|
||||||
"GBG",
|
"BGB",
|
||||||
"PEP",
|
"PEP",
|
||||||
"TET"
|
"TET"
|
||||||
],
|
],
|
||||||
@ -31,6 +31,6 @@
|
|||||||
|
|
||||||
"result": {
|
"result": {
|
||||||
"item": "overdrive_that_matters:machine_frame",
|
"item": "overdrive_that_matters:machine_frame",
|
||||||
"count": 1
|
"count": 2
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user