Compare commits
81 Commits
Author | SHA1 | Date | |
---|---|---|---|
066418d7b2 | |||
c83476225d | |||
f8277e55c3 | |||
49dd781a82 | |||
65dbeeeb4f | |||
f6138671d2 | |||
34b60be434 | |||
6153c2e972 | |||
376e548cec | |||
653ecedafb | |||
87e64a102a | |||
0b7e54b4ef | |||
f0dba4ccc3 | |||
b35dfaeacd | |||
6a2eb3dec2 | |||
ce94d22212 | |||
21b84651a8 | |||
80917f7d12 | |||
12b10ee6fe | |||
a88549f17f | |||
5552be70d5 | |||
cb386d39f5 | |||
22c3c22081 | |||
0da77bc453 | |||
f2aade3a8e | |||
46820a311f | |||
3743a3402d | |||
055b9cc489 | |||
640f62d63b | |||
d3423a6160 | |||
55c0be74d3 | |||
9d9b19da9d | |||
652acf3ce1 | |||
101e57756a | |||
67dbcde6dc | |||
b4c994f02f | |||
8007c1757e | |||
8aafa38c27 | |||
e51ba7015a | |||
1d0e24095a | |||
a7d405b5ea | |||
8ee5e94a78 | |||
f9dcf43cc4 | |||
42fe77e6b4 | |||
b28e180704 | |||
2deaef94aa | |||
78ac178526 | |||
92f2680feb | |||
077e82064b | |||
c821fa76a6 | |||
6e4bf4e7ec | |||
5b45cf7d0a | |||
edea36a8a6 | |||
34ef50f6ee | |||
4c5c2362ce | |||
54fa8a252e | |||
a9cb2db3b4 | |||
748a232569 | |||
86c426a504 | |||
108b49bedb | |||
71850b38e5 | |||
796f29127f | |||
8c43a3ec6d | |||
477e782c7c | |||
65cf8bf9df | |||
e5a982ae13 | |||
f942093e4f | |||
5d15611f84 | |||
1803d687ab | |||
347be35184 | |||
aa0a283e06 | |||
98fcacc9a8 | |||
422ae92303 | |||
7683cacc29 | |||
520112df77 | |||
5453c8c793 | |||
3c5ea937a5 | |||
f16483d7c0 | |||
8072a7b135 | |||
44c6d0c0cf | |||
27dce0bd31 |
@ -10,28 +10,28 @@ mod_version=1.4
|
||||
|
||||
use_commit_hash_in_version=true
|
||||
|
||||
mc_version=1.20.2
|
||||
jei_mc_version=1.20.2
|
||||
curios_mc_version=1.20.2
|
||||
mc_version=1.20.1
|
||||
jei_mc_version=1.20.1
|
||||
curios_mc_version=1.20.1
|
||||
|
||||
forge_gradle_version=[6.0.14,6.2)
|
||||
forge_version=48.1.0
|
||||
forge_version=47.2.19
|
||||
mixingradle_version=0.7.33
|
||||
mixin_version=0.8.5
|
||||
|
||||
kommons_version=3.0.2
|
||||
|
||||
jei_version=16.0.0.28
|
||||
jei_version=15.2.0.27
|
||||
jupiter_version=5.9.2
|
||||
curios_version=6.0.2
|
||||
cosmetic_armor_reworked_id=4764779
|
||||
curios_version=5.4.7
|
||||
cosmetic_armor_reworked_id=4600191
|
||||
ad_astra_id=4594155
|
||||
botarium_id=4594094
|
||||
resourceful_lib_id=4598948
|
||||
resourceful_config_id=4576455
|
||||
jade_id=4818518
|
||||
jade_id=4986594
|
||||
configured_id=4462894
|
||||
worldedit_id=4807512
|
||||
worldedit_id=4586218
|
||||
|
||||
kotlin_for_forge_version=4.7.0
|
||||
kotlin_version=1.9.0
|
||||
|
@ -1,9 +1,8 @@
|
||||
package ru.dbotthepony.mc.otm.datagen.advancements
|
||||
|
||||
import net.minecraft.advancements.AdvancementHolder
|
||||
import net.minecraft.advancements.AdvancementRewards
|
||||
import net.minecraft.advancements.FrameType
|
||||
import net.minecraft.advancements.AdvancementRequirements.Strategy
|
||||
import net.minecraft.advancements.RequirementsStrategy
|
||||
import net.minecraft.advancements.critereon.InventoryChangeTrigger
|
||||
import net.minecraft.world.item.DyeColor
|
||||
import net.minecraft.world.item.ItemStack
|
||||
@ -17,6 +16,8 @@ import ru.dbotthepony.mc.otm.triggers.BlackHoleTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.NailedEntityTrigger
|
||||
import java.util.function.Consumer
|
||||
|
||||
typealias Strategy = RequirementsStrategy
|
||||
|
||||
fun addAdvancements(serializer: Consumer<AdvancementHolder>, lang: MatteryLanguageProvider) {
|
||||
val translation = lang.MultiBuilder("otm.advancements.regular")
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
package ru.dbotthepony.mc.otm.datagen.advancements
|
||||
|
||||
import net.minecraft.advancements.AdvancementHolder
|
||||
import net.minecraft.advancements.AdvancementRequirements.Strategy
|
||||
import net.minecraft.advancements.AdvancementRewards
|
||||
import net.minecraft.advancements.FrameType
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
|
@ -1,12 +1,9 @@
|
||||
package ru.dbotthepony.mc.otm.datagen.advancements
|
||||
|
||||
import net.minecraft.advancements.Advancement
|
||||
import net.minecraft.advancements.AdvancementHolder
|
||||
import net.minecraft.advancements.FrameType
|
||||
import net.minecraft.advancements.critereon.ItemPredicate
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraftforge.common.data.ExistingFileHelper
|
||||
import ru.dbotthepony.mc.otm.datagen.lang.MatteryLanguageProvider
|
||||
import ru.dbotthepony.mc.otm.datagen.modLocation
|
||||
import ru.dbotthepony.mc.otm.registry.MItems
|
||||
|
@ -16,6 +16,7 @@ import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.ItemLike
|
||||
import ru.dbotthepony.mc.otm.core.TextComponent
|
||||
import java.util.function.Consumer
|
||||
|
||||
fun AdvancementBuilder(): Advancement.Builder = Advancement.Builder.advancement()
|
||||
|
||||
@ -58,7 +59,7 @@ fun predicate(tag: TagKey<Item>): ItemPredicate {
|
||||
return ItemPredicate.Builder.item().of(tag).build()
|
||||
}
|
||||
|
||||
fun criterion(tag: TagKey<Item>): Criterion<*> {
|
||||
fun criterion(tag: TagKey<Item>): CriterionTriggerInstance {
|
||||
return InventoryChangeTrigger.TriggerInstance.hasItems(predicate(tag))
|
||||
}
|
||||
|
||||
@ -66,8 +67,10 @@ fun predicate(item: ItemLike): ItemPredicate {
|
||||
return ItemPredicate.Builder.item().of(item).build()
|
||||
}
|
||||
|
||||
fun criterion(item: ItemLike): Criterion<*> {
|
||||
fun criterion(item: ItemLike): CriterionTriggerInstance {
|
||||
return InventoryChangeTrigger.TriggerInstance.hasItems(predicate(item))
|
||||
}
|
||||
|
||||
fun EntityPredicate.wrap(): ContextAwarePredicate = EntityPredicate.wrap(this)
|
||||
|
||||
fun Advancement.Builder.save(advancement: Consumer<Advancement>, name: ResourceLocation) = save(advancement, name.toString())
|
||||
|
@ -1,8 +1,8 @@
|
||||
package ru.dbotthepony.mc.otm.datagen.advancements
|
||||
|
||||
import net.minecraft.advancements.AdvancementHolder
|
||||
import net.minecraft.advancements.AdvancementRequirements
|
||||
import net.minecraft.advancements.Advancement
|
||||
import net.minecraft.advancements.FrameType
|
||||
import net.minecraft.advancements.RequirementsStrategy
|
||||
import net.minecraft.advancements.critereon.ItemPredicate
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
@ -16,6 +16,8 @@ import ru.dbotthepony.mc.otm.registry.MItems
|
||||
import ru.dbotthepony.mc.otm.triggers.TakeItemOutOfReplicatorTrigger
|
||||
import java.util.function.Consumer
|
||||
|
||||
typealias AdvancementHolder = Advancement
|
||||
|
||||
data class CraftEntry(
|
||||
val item: Collection<Item>,
|
||||
val englishName: String,
|
||||
@ -59,7 +61,7 @@ data class CraftEntry(
|
||||
it.addCriterion(i.toString(), criterion(item))
|
||||
}
|
||||
}
|
||||
.requirements(AdvancementRequirements.Strategy.OR)
|
||||
.requirements(RequirementsStrategy.OR)
|
||||
.save(serializer, modLocation("machines/$path"))
|
||||
}
|
||||
}
|
||||
@ -82,7 +84,7 @@ fun addMachineAdvancements(serializer: Consumer<AdvancementHolder>, lang: Matter
|
||||
for ((i, v) in MItems.CHEMICAL_GENERATOR.values.withIndex())
|
||||
it.addCriterion("has_machine_$i", criterion(v))
|
||||
}
|
||||
.requirements(AdvancementRequirements.Strategy.OR)
|
||||
.requirements(RequirementsStrategy.OR)
|
||||
.save(serializer, modLocation("machines/chemical_generator"))
|
||||
|
||||
val press = AdvancementBuilder()
|
||||
@ -100,7 +102,7 @@ fun addMachineAdvancements(serializer: Consumer<AdvancementHolder>, lang: Matter
|
||||
for ((i, m) in MItems.TWIN_PLATE_PRESS.values.withIndex())
|
||||
it.addCriterion(i.toString(), criterion(m))
|
||||
}
|
||||
.requirements(AdvancementRequirements.Strategy.OR)
|
||||
.requirements(RequirementsStrategy.OR)
|
||||
.save(serializer, modLocation("machines/plate_press"))
|
||||
|
||||
CraftEntry(MItems.ENERGY_SERVO.values, "Power Goes In, Powered Things Go Out",
|
||||
|
@ -1,7 +1,6 @@
|
||||
package ru.dbotthepony.mc.otm.datagen.recipes
|
||||
|
||||
import net.minecraft.data.recipes.RecipeCategory
|
||||
import net.minecraft.data.recipes.RecipeOutput
|
||||
import net.minecraft.tags.ItemTags
|
||||
import net.minecraftforge.common.Tags
|
||||
import ru.dbotthepony.mc.otm.registry.MItemTags
|
||||
|
@ -1,14 +1,12 @@
|
||||
package ru.dbotthepony.mc.otm.datagen.recipes
|
||||
|
||||
import net.minecraft.data.recipes.RecipeCategory
|
||||
import net.minecraft.data.recipes.RecipeOutput
|
||||
import net.minecraft.data.recipes.SimpleCookingRecipeBuilder
|
||||
import net.minecraft.util.valueproviders.ConstantFloat
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.crafting.Ingredient
|
||||
import net.minecraft.world.level.ItemLike
|
||||
import ru.dbotthepony.mc.otm.core.registryName
|
||||
import ru.dbotthepony.mc.otm.datagen.modLocation
|
||||
import ru.dbotthepony.mc.otm.registry.MItemTags
|
||||
import ru.dbotthepony.mc.otm.registry.MItems
|
||||
|
@ -1,8 +1,6 @@
|
||||
package ru.dbotthepony.mc.otm.datagen.recipes
|
||||
|
||||
import net.minecraft.data.recipes.FinishedRecipe
|
||||
import net.minecraft.data.recipes.RecipeCategory
|
||||
import net.minecraft.data.recipes.RecipeOutput
|
||||
import net.minecraft.data.recipes.ShapelessRecipeBuilder
|
||||
import net.minecraft.tags.ItemTags
|
||||
import net.minecraft.world.item.ItemStack
|
||||
@ -17,7 +15,6 @@ import ru.dbotthepony.mc.otm.registry.MRegistry
|
||||
import ru.dbotthepony.mc.otm.core.registryName
|
||||
import ru.dbotthepony.mc.otm.datagen.modLocation
|
||||
import ru.dbotthepony.mc.otm.recipe.UpgradeRecipe
|
||||
import java.util.function.Consumer
|
||||
|
||||
fun addCraftingTableRecipes(consumer: RecipeOutput) {
|
||||
val machinesCategory = RecipeCategory.DECORATIONS
|
||||
|
@ -1,6 +1,5 @@
|
||||
package ru.dbotthepony.mc.otm.datagen.recipes
|
||||
|
||||
import net.minecraft.data.recipes.RecipeOutput
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraftforge.common.Tags
|
||||
import ru.dbotthepony.mc.otm.registry.MItemTags
|
||||
|
@ -1,6 +1,5 @@
|
||||
package ru.dbotthepony.mc.otm.datagen.recipes
|
||||
|
||||
import net.minecraft.data.recipes.RecipeOutput
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.crafting.Ingredient
|
||||
import net.minecraftforge.common.Tags
|
||||
@ -14,6 +13,7 @@ import ru.dbotthepony.mc.otm.registry.MItems
|
||||
fun addMatterEntanglerRecipes(consumer: RecipeOutput) {
|
||||
consumer.accept(
|
||||
MatterEntanglerRecipe(
|
||||
modLocation("quantum_capacitor"),
|
||||
IngredientMatrix.of(
|
||||
listOf(Ingredient.of(MItems.ELECTRIC_PARTS), Ingredient.of(MItemTags.GOLD_WIRES), Ingredient.of(MItems.ELECTRIC_PARTS)),
|
||||
listOf(Ingredient.of(MItems.BATTERY_CAPACITOR), Ingredient.of(MItems.QUANTUM_TRANSCEIVER), Ingredient.of(MItems.BATTERY_CAPACITOR)),
|
||||
@ -23,11 +23,12 @@ fun addMatterEntanglerRecipes(consumer: RecipeOutput) {
|
||||
400.0,
|
||||
ItemStack(MItems.QUANTUM_CAPACITOR, 2),
|
||||
experience = 15f
|
||||
).energetic().toFinished(modLocation("quantum_capacitor"))
|
||||
).energetic().toFinished()
|
||||
)
|
||||
|
||||
consumer.accept(
|
||||
MatterEntanglerRecipe(
|
||||
modLocation("quantum_battery"),
|
||||
IngredientMatrix.of(
|
||||
listOf(Ingredient.of(Tags.Items.STORAGE_BLOCKS_REDSTONE), Ingredient.of(MItemTags.GOLD_WIRES), Ingredient.of(Tags.Items.STORAGE_BLOCKS_REDSTONE)),
|
||||
listOf(Ingredient.of(MItems.BATTERY_DENSE), Ingredient.of(MItems.QUANTUM_TRANSCEIVER), Ingredient.of(MItems.BATTERY_DENSE)),
|
||||
@ -37,6 +38,6 @@ fun addMatterEntanglerRecipes(consumer: RecipeOutput) {
|
||||
600.0,
|
||||
ItemStack(MItems.QUANTUM_BATTERY, 2),
|
||||
experience = 20f
|
||||
).energetic().toFinished(modLocation("quantum_battery"))
|
||||
).energetic().toFinished()
|
||||
)
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import net.minecraft.advancements.Criterion
|
||||
import net.minecraft.advancements.CriterionTriggerInstance
|
||||
import net.minecraft.data.recipes.FinishedRecipe
|
||||
import net.minecraft.data.recipes.RecipeCategory
|
||||
import net.minecraft.data.recipes.RecipeOutput
|
||||
import net.minecraft.data.recipes.ShapedRecipeBuilder
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.tags.TagKey
|
||||
@ -62,10 +61,6 @@ private fun RecipeOutput.map(mapper: (FinishedRecipe) -> FinishedRecipe): Recipe
|
||||
override fun accept(recipe: FinishedRecipe) {
|
||||
this@map.accept(mapper(recipe))
|
||||
}
|
||||
|
||||
override fun advancement(): Advancement.Builder {
|
||||
return this@map.advancement()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,11 +72,11 @@ class MatteryRecipe(val result: ItemLike, val count: Int = 1, val category: Reci
|
||||
private val rows = arrayOfNulls<RecipeRow>(3)
|
||||
private var index = 0
|
||||
|
||||
private val unlockedBy = ArrayList<Pair<String, Criterion<*>>>().also {
|
||||
private val unlockedBy = ArrayList<Pair<String, CriterionTriggerInstance>>().also {
|
||||
it.add("has_result" to has(result))
|
||||
}
|
||||
|
||||
fun unlockedBy(name: String, trigger: Criterion<*>): MatteryRecipe {
|
||||
fun unlockedBy(name: String, trigger: CriterionTriggerInstance): MatteryRecipe {
|
||||
unlockedBy.add(name to trigger)
|
||||
return this
|
||||
}
|
||||
@ -195,7 +190,7 @@ class MatteryRecipe(val result: ItemLike, val count: Int = 1, val category: Reci
|
||||
pJson["source"] = upgradeSource!!.toString()
|
||||
}
|
||||
|
||||
override fun type(): RecipeSerializer<*> {
|
||||
override fun getType(): RecipeSerializer<*> {
|
||||
return UpgradeRecipe.CODEC
|
||||
}
|
||||
}
|
||||
@ -227,7 +222,7 @@ class MatteryRecipe(val result: ItemLike, val count: Int = 1, val category: Reci
|
||||
fun buildEnergetic(consumer: RecipeOutput, name: String? = null) {
|
||||
build(consumer.map {
|
||||
object : FinishedRecipe by it {
|
||||
override fun type(): RecipeSerializer<*> {
|
||||
override fun getType(): RecipeSerializer<*> {
|
||||
return EnergyContainerRecipe.Companion
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,13 @@
|
||||
package ru.dbotthepony.mc.otm.datagen.recipes
|
||||
|
||||
import com.google.common.collect.ImmutableList
|
||||
import net.minecraft.advancements.CriteriaTriggers
|
||||
import net.minecraft.advancements.Criterion
|
||||
import net.minecraft.advancements.CriterionTriggerInstance
|
||||
import net.minecraft.advancements.critereon.ContextAwarePredicate
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
import net.minecraft.advancements.critereon.InventoryChangeTrigger
|
||||
import net.minecraft.advancements.critereon.ItemPredicate
|
||||
import net.minecraft.advancements.critereon.MinMaxBounds
|
||||
import net.minecraft.data.DataGenerator
|
||||
import net.minecraft.data.recipes.FinishedRecipe
|
||||
import net.minecraft.data.recipes.RecipeBuilder
|
||||
import net.minecraft.data.recipes.RecipeOutput
|
||||
import net.minecraft.data.recipes.RecipeProvider
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.tags.ItemTags
|
||||
@ -27,31 +23,30 @@ import ru.dbotthepony.mc.otm.datagen.modLocation
|
||||
import ru.dbotthepony.mc.otm.recipe.MicrowaveRecipe
|
||||
import ru.dbotthepony.mc.otm.recipe.PlatePressRecipe
|
||||
import java.util.*
|
||||
import java.util.function.Consumer
|
||||
import java.util.stream.Stream
|
||||
|
||||
private typealias RecipeBuilderCallback = (MatteryRecipeProvider, consumer: RecipeOutput) -> Unit
|
||||
|
||||
fun has(p_176521_: MinMaxBounds.Ints, p_176522_: ItemLike): Criterion<InventoryChangeTrigger.TriggerInstance> {
|
||||
fun has(p_176521_: MinMaxBounds.Ints, p_176522_: ItemLike): CriterionTriggerInstance {
|
||||
return inventoryTrigger(ItemPredicate.Builder.item().of(p_176522_).withCount(p_176521_).build())
|
||||
}
|
||||
|
||||
fun has(p_125978_: ItemLike): Criterion<InventoryChangeTrigger.TriggerInstance> {
|
||||
fun has(p_125978_: ItemLike): CriterionTriggerInstance {
|
||||
return inventoryTrigger(ItemPredicate.Builder.item().of(p_125978_).build())
|
||||
}
|
||||
|
||||
fun has(p_125976_: TagKey<Item>): Criterion<InventoryChangeTrigger.TriggerInstance> {
|
||||
fun has(p_125976_: TagKey<Item>): CriterionTriggerInstance {
|
||||
return inventoryTrigger(ItemPredicate.Builder.item().of(p_125976_).build())
|
||||
}
|
||||
|
||||
fun inventoryTrigger(vararg p_126012_: ItemPredicate): Criterion<InventoryChangeTrigger.TriggerInstance> {
|
||||
return CriteriaTriggers.INVENTORY_CHANGED.createCriterion(InventoryChangeTrigger.TriggerInstance(
|
||||
Optional.empty(),
|
||||
fun inventoryTrigger(vararg p_126012_: ItemPredicate): CriterionTriggerInstance {
|
||||
return InventoryChangeTrigger.TriggerInstance(
|
||||
ContextAwarePredicate.ANY,
|
||||
MinMaxBounds.Ints.ANY,
|
||||
MinMaxBounds.Ints.ANY,
|
||||
MinMaxBounds.Ints.ANY,
|
||||
ImmutableList.copyOf(p_126012_)
|
||||
))
|
||||
p_126012_
|
||||
)
|
||||
}
|
||||
|
||||
fun multiIngredient(vararg items: Any) : Ingredient {
|
||||
@ -104,24 +99,25 @@ class MatteryRecipeProvider(generatorIn: DataGenerator) : RecipeProvider(generat
|
||||
fun plate(id: String, count: Int = 1, workTicks: Int = 200, experience: FloatProvider = ConstantFloat.ZERO) {
|
||||
exec { _, consumer ->
|
||||
consumer.accept(PlatePressRecipe(
|
||||
modLocation("plates/$id"),
|
||||
Ingredient.of(ItemTags.create(ResourceLocation("forge", "ingots/$id"))),
|
||||
Ingredient.of(ItemTags.create(ResourceLocation("forge", "plates/$id"))),
|
||||
count,
|
||||
workTicks,
|
||||
experience = experience
|
||||
).toFinished(modLocation("plates/$id")))
|
||||
).toFinished())
|
||||
}
|
||||
}
|
||||
|
||||
fun plate(id: String, ingredient: Ingredient, result: Ingredient, count: Int = 1, workTicks: Int = 200, experience: FloatProvider = ConstantFloat.ZERO) {
|
||||
exec { it, callback ->
|
||||
callback.accept(PlatePressRecipe(ingredient, result, count, workTicks, experience = experience).toFinished(modLocation("plate_$id")))
|
||||
callback.accept(PlatePressRecipe(modLocation("plates/$id"), ingredient, result, count, workTicks, experience = experience).toFinished())
|
||||
}
|
||||
}
|
||||
|
||||
fun microwave(id: String, ingredient: Ingredient, result: Ingredient, count: Int = 1, workTicks: Int = 200, experience: FloatProvider = ConstantFloat.ZERO) {
|
||||
exec { it, callback ->
|
||||
callback.accept(MicrowaveRecipe(ingredient, result, count, workTicks, experience = experience).toFinished(modLocation("microwave/$id")))
|
||||
callback.accept(MicrowaveRecipe(modLocation("microwave/$id"), ingredient, result, count, workTicks, experience = experience).toFinished())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,16 @@
|
||||
package ru.dbotthepony.mc.otm.datagen.recipes
|
||||
|
||||
import net.minecraft.data.recipes.FinishedRecipe
|
||||
import net.minecraft.data.recipes.RecipeOutput
|
||||
import net.minecraft.world.item.DyeColor
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.item.crafting.Ingredient
|
||||
import ru.dbotthepony.mc.otm.core.registryName
|
||||
import ru.dbotthepony.mc.otm.core.stream
|
||||
import ru.dbotthepony.mc.otm.datagen.modLocation
|
||||
import ru.dbotthepony.mc.otm.recipe.PainterArmorDyeRecipe
|
||||
import ru.dbotthepony.mc.otm.recipe.PainterRecipe
|
||||
import ru.dbotthepony.mc.otm.registry.MItems
|
||||
import ru.dbotthepony.mc.otm.registry.MRegistry
|
||||
import java.util.function.Consumer
|
||||
|
||||
private val Item.recipeName get() = registryName!!.namespace + "/" + registryName!!.path
|
||||
|
||||
@ -23,10 +19,11 @@ private fun generate(consumer: RecipeOutput, items: Map<out DyeColor?, Item>, am
|
||||
if (targetColor == null) continue
|
||||
|
||||
consumer.accept(PainterRecipe(
|
||||
modLocation("painter/" + targetItem.recipeName),
|
||||
Ingredient.of(items.entries.stream().filter { it.key != null && it.key != targetColor }.map { ItemStack(it.value) }),
|
||||
ItemStack(targetItem),
|
||||
mapOf(targetColor to amount)
|
||||
).toFinished(modLocation("painter/" + targetItem.recipeName)))
|
||||
).toFinished())
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,19 +37,21 @@ private fun generate(consumer: RecipeOutput, default: Item, items: Map<out DyeCo
|
||||
if (k1 == null) continue
|
||||
|
||||
consumer.accept(PainterRecipe(
|
||||
modLocation("painter/" + default.recipeName + "/" + v1.recipeName),
|
||||
Ingredient.of(default),
|
||||
ItemStack(v1),
|
||||
mapOf(k1 to amount)
|
||||
).toFinished(modLocation("painter/" + default.recipeName + "/" + v1.recipeName)))
|
||||
).toFinished())
|
||||
}
|
||||
}
|
||||
|
||||
private fun cleaning(consumer: RecipeOutput, to: Item, from: Map<out DyeColor?, Item>) {
|
||||
consumer.accept(PainterRecipe(
|
||||
modLocation("painter/cleaning/" + to.recipeName),
|
||||
Ingredient.of(from.entries.stream().filter { it.key != null }.map { ItemStack(it.value) }),
|
||||
ItemStack(to),
|
||||
mapOf(null to 15)
|
||||
).toFinished(modLocation("painter/cleaning/" + to.recipeName)))
|
||||
).toFinished())
|
||||
}
|
||||
|
||||
private fun striped(consumer: RecipeOutput, name: String, items: List<Pair<Item, Pair<DyeColor, DyeColor>>>, base: Map<DyeColor, Item>) {
|
||||
@ -60,10 +59,11 @@ private fun striped(consumer: RecipeOutput, name: String, items: List<Pair<Item,
|
||||
val (baseColor, stripe) = colors
|
||||
|
||||
consumer.accept(PainterRecipe(
|
||||
modLocation("painter/stripes_$name/${baseColor.getName()}/${stripe.getName()}"),
|
||||
Ingredient.of(base[baseColor]),
|
||||
ItemStack(stripeItem),
|
||||
setOf(stripe)
|
||||
).toFinished(modLocation("painter/stripes_$name/${baseColor.getName()}/${stripe.getName()}")))
|
||||
).toFinished())
|
||||
}
|
||||
}
|
||||
|
||||
@ -318,32 +318,36 @@ fun addPainterRecipes(consumer: RecipeOutput) {
|
||||
striped(consumer, "slabs", MRegistry.TRITANIUM_STRIPED_SLAB.itemsWithColor, MRegistry.TRITANIUM_SLAB.items)
|
||||
|
||||
for (color in DyeColor.entries) {
|
||||
consumer.accept(PainterArmorDyeRecipe(mapOf(color to 1)).toFinished(modLocation("painter/armor_dye_" + color.getName().lowercase())))
|
||||
consumer.accept(PainterArmorDyeRecipe(modLocation("painter/armor_dye_" + color.getName().lowercase()), mapOf(color to 1)).toFinished())
|
||||
}
|
||||
|
||||
consumer.accept(PainterArmorDyeRecipe(mapOf(null to 15)).toFinished(modLocation("painter/armor_clear_dye")))
|
||||
consumer.accept(PainterArmorDyeRecipe(modLocation("painter/armor_clear_dye"), mapOf(null to 15)).toFinished())
|
||||
|
||||
consumer.accept(PainterRecipe(
|
||||
modLocation("painter/tritanium_yellow_stripe"),
|
||||
Ingredient.of(MRegistry.TRITANIUM_BLOCK.item),
|
||||
ItemStack(MItems.TRITANIUM_STRIPED_BLOCK),
|
||||
mapOf(DyeColor.YELLOW to 1)
|
||||
).toFinished(modLocation("painter/tritanium_yellow_stripe")))
|
||||
).toFinished())
|
||||
|
||||
consumer.accept(PainterRecipe(
|
||||
modLocation("painter/tritanium_yellow_stripe_stairs"),
|
||||
Ingredient.of(MRegistry.TRITANIUM_STAIRS.item),
|
||||
ItemStack(MItems.TRITANIUM_STRIPED_STAIRS),
|
||||
mapOf(DyeColor.YELLOW to 1)
|
||||
).toFinished(modLocation("painter/tritanium_yellow_stripe_stairs")))
|
||||
).toFinished())
|
||||
|
||||
consumer.accept(PainterRecipe(
|
||||
modLocation("painter/tritanium_yellow_stripe_slab"),
|
||||
Ingredient.of(MRegistry.TRITANIUM_SLAB.item),
|
||||
ItemStack(MItems.TRITANIUM_STRIPED_SLAB),
|
||||
mapOf(DyeColor.YELLOW to 1)
|
||||
).toFinished(modLocation("painter/tritanium_yellow_stripe_slab")))
|
||||
).toFinished())
|
||||
|
||||
consumer.accept(PainterRecipe(
|
||||
modLocation("painter/tritanium_yellow_stripe_wall"),
|
||||
Ingredient.of(MRegistry.TRITANIUM_WALL.item),
|
||||
ItemStack(MItems.TRITANIUM_STRIPED_WALL),
|
||||
mapOf(DyeColor.YELLOW to 1)
|
||||
).toFinished(modLocation("painter/tritanium_yellow_stripe_wall")))
|
||||
).toFinished())
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package ru.dbotthepony.mc.otm.datagen.recipes
|
||||
|
||||
import net.minecraft.data.recipes.FinishedRecipe
|
||||
import net.minecraft.data.recipes.RecipeCategory
|
||||
import net.minecraft.data.recipes.RecipeOutput
|
||||
import net.minecraft.data.recipes.ShapelessRecipeBuilder
|
||||
import net.minecraft.tags.TagKey
|
||||
import net.minecraft.world.item.DyeColor
|
||||
@ -16,6 +16,9 @@ import ru.dbotthepony.mc.otm.datagen.modLocation
|
||||
import ru.dbotthepony.mc.otm.registry.MItemTags
|
||||
import ru.dbotthepony.mc.otm.registry.MItems
|
||||
import ru.dbotthepony.mc.otm.registry.MRegistry
|
||||
import java.util.function.Consumer
|
||||
|
||||
typealias RecipeOutput = Consumer<FinishedRecipe>
|
||||
|
||||
fun hammerRecipe(output: ItemLike, input: ItemLike, consumer: RecipeOutput) {
|
||||
ShapelessRecipeBuilder(RecipeCategory.MISC, output, 1)
|
||||
|
@ -1,7 +1,6 @@
|
||||
package ru.dbotthepony.mc.otm.datagen.recipes
|
||||
|
||||
import net.minecraft.data.recipes.RecipeCategory
|
||||
import net.minecraft.data.recipes.RecipeOutput
|
||||
import net.minecraftforge.common.Tags
|
||||
import ru.dbotthepony.mc.otm.recipe.UpgradeRecipe
|
||||
import ru.dbotthepony.mc.otm.registry.MItemTags
|
||||
|
@ -1,7 +1,6 @@
|
||||
package ru.dbotthepony.mc.otm.datagen.recipes
|
||||
|
||||
import net.minecraft.data.recipes.RecipeCategory
|
||||
import net.minecraft.data.recipes.RecipeOutput
|
||||
import net.minecraftforge.common.Tags
|
||||
import ru.dbotthepony.mc.otm.registry.MItemTags
|
||||
import ru.dbotthepony.mc.otm.registry.MItems
|
||||
|
@ -25,6 +25,7 @@ import ru.dbotthepony.mc.otm.core.collect.ListSet
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.isActuallyEmpty
|
||||
import ru.dbotthepony.mc.otm.data.ComponentCodec
|
||||
import ru.dbotthepony.mc.otm.data.IngredientCodec
|
||||
import ru.dbotthepony.mc.otm.data.JsonElementCodec
|
||||
import ru.dbotthepony.mc.otm.isClient
|
||||
import java.util.Optional
|
||||
@ -392,7 +393,7 @@ class AndroidResearchType(
|
||||
ListCodec(
|
||||
RecordCodecBuilder.create<Pair<Ingredient, Int>> {
|
||||
it.group(
|
||||
Ingredient.CODEC.fieldOf("item").forGetter { it.first },
|
||||
IngredientCodec.fieldOf("item").forGetter { it.first },
|
||||
Codec.intRange(1, Int.MAX_VALUE).optionalFieldOf("count", 1).forGetter { it.second }
|
||||
).apply(it, ::Pair)
|
||||
}
|
||||
|
@ -594,14 +594,11 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
|
||||
private fun recheckPlayer(player: ServerPlayer) {
|
||||
sometimeServer {
|
||||
if (player in players && !player.hasDisconnected()) {
|
||||
if (player.connection.chunkSender.isPending(chunkPos)) {
|
||||
recheckPlayer(player)
|
||||
} else {
|
||||
veto.remove(player)
|
||||
veto.remove(player)
|
||||
|
||||
blockEntities.forEach {
|
||||
it.synchers[player] = it.syncher.Remote()
|
||||
}
|
||||
blockEntities.forEach {
|
||||
it.synchers[player] =
|
||||
it.syncher.Remote()
|
||||
}
|
||||
} else if (player in players && player.hasDisconnected()) {
|
||||
unsubscribe(player)
|
||||
|
@ -668,11 +668,11 @@ class ExplosionQueue(private val level: ServerLevel) : SavedData() {
|
||||
@JvmStatic
|
||||
fun queueForLevel(level: ServerLevel): ExplosionQueue {
|
||||
return level.dataStorage.computeIfAbsent(
|
||||
Factory({ ExplosionQueue(level) }, {
|
||||
{
|
||||
val factory = ExplosionQueue(level)
|
||||
factory.load(it)
|
||||
factory
|
||||
}, DataFixTypes.LEVEL),
|
||||
}, { ExplosionQueue(level) },
|
||||
"otm_blackhole_explosion_queue"
|
||||
)
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.container.ShadowCraftingContainer
|
||||
import ru.dbotthepony.mc.otm.container.UpgradeContainer
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.value
|
||||
import ru.dbotthepony.mc.otm.data.DecimalCodec
|
||||
import ru.dbotthepony.mc.otm.data.minRange
|
||||
import ru.dbotthepony.mc.otm.graph.matter.MatterNode
|
||||
|
@ -49,6 +49,7 @@ import ru.dbotthepony.mc.otm.core.collect.map
|
||||
import ru.dbotthepony.mc.otm.core.collect.toList
|
||||
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||
import ru.dbotthepony.mc.otm.core.util.ItemStorageStackSorter
|
||||
import ru.dbotthepony.mc.otm.core.value
|
||||
|
||||
interface IItemMonitorPlayerSettings {
|
||||
var ingredientPriority: ItemMonitorPlayerSettings.IngredientPriority
|
||||
|
@ -36,6 +36,7 @@ import ru.dbotthepony.mc.otm.core.collect.filter
|
||||
import ru.dbotthepony.mc.otm.core.collect.maybe
|
||||
import ru.dbotthepony.mc.otm.core.getValue
|
||||
import ru.dbotthepony.mc.otm.core.immutableList
|
||||
import ru.dbotthepony.mc.otm.core.value
|
||||
import ru.dbotthepony.mc.otm.core.util.item
|
||||
import ru.dbotthepony.mc.otm.menu.tech.PoweredFurnaceMenu
|
||||
import ru.dbotthepony.mc.otm.recipe.MatteryCookingRecipe
|
||||
|
@ -22,6 +22,7 @@ import ru.dbotthepony.mc.otm.container.UpgradeContainer
|
||||
import ru.dbotthepony.mc.otm.container.balance
|
||||
import ru.dbotthepony.mc.otm.core.collect.filter
|
||||
import ru.dbotthepony.mc.otm.core.collect.maybe
|
||||
import ru.dbotthepony.mc.otm.core.value
|
||||
import ru.dbotthepony.mc.otm.menu.tech.PlatePressMenu
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
import ru.dbotthepony.mc.otm.registry.MRecipes
|
||||
|
@ -556,7 +556,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
super.onJobTick(status)
|
||||
|
||||
if (isExopackVisible && ply.level().random.nextFloat() <= 0.05f) {
|
||||
MatteryPlayerNetworkChannel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(ply as ServerPlayer), ExopackSmokePacket(ply.uuid))
|
||||
MatteryPlayerNetworkChannel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with { ply as ServerPlayer }, ExopackSmokePacket(ply.uuid))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -224,7 +224,7 @@ fun onMouseScrolled(event: MouseScrolled.Pre) {
|
||||
|
||||
for (widget in screen.renderables) {
|
||||
if (widget is Panel2Widget<*, *>) {
|
||||
if (widget.panel.mouseScrolledChecked(event.mouseX, event.mouseY, event.deltaX)) {
|
||||
if (widget.panel.mouseScrolledChecked(event.mouseX, event.mouseY, event.scrollDelta)) {
|
||||
event.isCanceled = true
|
||||
return
|
||||
}
|
||||
@ -233,7 +233,7 @@ fun onMouseScrolled(event: MouseScrolled.Pre) {
|
||||
val slot = screen.slotUnderMouse
|
||||
|
||||
if (slot != null && (slot.container == minecraft.player?.inventory && slot.containerSlot in 9 .. 35 || slot.container == minecraft.player?.matteryPlayer?.exopackContainer)) {
|
||||
widget.panel.mouseScrolledInner(event.mouseX, event.mouseY, event.deltaX)
|
||||
widget.panel.mouseScrolledInner(event.mouseX, event.mouseY, event.scrollDelta)
|
||||
event.isCanceled = true
|
||||
return
|
||||
}
|
||||
|
@ -569,7 +569,7 @@ abstract class MatteryScreen<T : MatteryMenu>(menu: T, inventory: Inventory, tit
|
||||
return super.mouseReleased(p_97812_, p_97813_, p_97814_)
|
||||
}
|
||||
|
||||
override fun mouseScrolled(mouseX: Double, mouseY: Double, scrollX: Double, scrollY: Double): Boolean {
|
||||
override fun mouseScrolled(mouseX: Double, mouseY: Double, scrollY: Double): Boolean {
|
||||
for (panel in panels) {
|
||||
if (panel.mouseScrolledChecked(mouseX, mouseY, scrollY)) {
|
||||
return true
|
||||
@ -653,7 +653,7 @@ abstract class MatteryScreen<T : MatteryMenu>(menu: T, inventory: Inventory, tit
|
||||
val mouseYf = mouseY.toFloat()
|
||||
|
||||
// dark background
|
||||
this.renderBackground(graphics, mouseX, mouseY, partialTick)
|
||||
this.renderBackground(graphics)
|
||||
|
||||
super.hoveredSlot = null
|
||||
var hovered = false
|
||||
|
@ -30,6 +30,7 @@ import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.map
|
||||
import ru.dbotthepony.kommons.math.RGBAColor
|
||||
import ru.dbotthepony.mc.otm.core.util.CreativeMenuItemComparator
|
||||
import ru.dbotthepony.mc.otm.core.value
|
||||
import ru.dbotthepony.mc.otm.menu.decorative.PainterMenu
|
||||
|
||||
class PainterScreen(menu: PainterMenu, inventory: Inventory, title: Component) : MatteryScreen<PainterMenu>(menu, inventory, title) {
|
||||
|
@ -100,7 +100,7 @@ open class EditablePanel<out S : Screen>(
|
||||
return this@EditablePanel.mouseDragged(p_94740_, p_94741_, p_94742_, p_94743_, p_94744_)
|
||||
}
|
||||
|
||||
override fun mouseScrolled(mouseX: Double, mouseY: Double, scrollX: Double, scrollY: Double): Boolean {
|
||||
override fun mouseScrolled(mouseX: Double, mouseY: Double, scrollY: Double): Boolean {
|
||||
return this@EditablePanel.mouseScrolled(mouseX, mouseY, scrollY)
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ import com.mojang.blaze3d.systems.RenderSystem
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
import net.minecraft.world.effect.MobEffectInstance
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@ -264,7 +264,7 @@ open class EffectListPanel<out S : Screen> @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
companion object {
|
||||
val BAR = ResourceLocation("textures/gui/sprites/container/inventory/effect_background_large.png").sprite(0f, 0f, 120f, 32f, 120f, 32f)
|
||||
val SQUARE_THIN = ResourceLocation("textures/gui/sprites/hud/effect_background.png").sprite(0f, 0f, 24f, 24f, 24f, 24f)
|
||||
val BAR = AbstractContainerScreen.INVENTORY_LOCATION.sprite(0f, 166f, 120f, 32f)
|
||||
val SQUARE_THIN = AbstractContainerScreen.INVENTORY_LOCATION.sprite(141f, 166f, 24f, 24f)
|
||||
}
|
||||
}
|
||||
|
@ -170,14 +170,16 @@ class EntityRendererPanel<out S : Screen> @JvmOverloads constructor(
|
||||
return
|
||||
}
|
||||
|
||||
val renderX = width.toInt() / 2
|
||||
val renderY = (height * 0.9f).toInt()
|
||||
|
||||
InventoryScreen.renderEntityInInventoryFollowsMouse(
|
||||
graphics.parent,
|
||||
0, 0,
|
||||
this.width.toInt(), this.height.toInt(),
|
||||
renderX,
|
||||
renderY,
|
||||
renderScale,
|
||||
0f,
|
||||
mouseX - absoluteX.toInt(),
|
||||
mouseY - absoluteY + height * 0.15f,
|
||||
absoluteX.toInt() + renderX - mouseX,
|
||||
absoluteY + height * 0.15f - mouseY,
|
||||
entity
|
||||
)
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ class Panel2Widget<out S: Screen, out P : EditablePanel<S>>(
|
||||
return panel.mouseDraggedChecked(p_94740_, p_94741_, p_94742_, p_94743_, p_94744_)
|
||||
}
|
||||
|
||||
override fun mouseScrolled(mouseX: Double, mouseY: Double, scrollX: Double, scrollY: Double): Boolean {
|
||||
override fun mouseScrolled(mouseX: Double, mouseY: Double, scrollY: Double): Boolean {
|
||||
return panel.mouseScrolledChecked(mouseX, mouseY, scrollY)
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ fun onCuriosSlotModifiersUpdated(event: SlotModifiersUpdatedEvent) {
|
||||
}
|
||||
|
||||
fun openCuriosScreen(carriedStack: ItemStack = ItemStack.EMPTY) {
|
||||
if (FMLEnvironment.dist.isClient) NetworkHandler.INSTANCE.send(CPacketOpenCurios(carriedStack), PacketDistributor.SERVER.noArg())
|
||||
if (FMLEnvironment.dist.isClient) NetworkHandler.INSTANCE.send(PacketDistributor.SERVER.noArg(), CPacketOpenCurios(carriedStack))
|
||||
}
|
||||
|
||||
private fun Player.getCuriosSlotsImpl(): List<PlayerSlot<Slot, Slot>> {
|
||||
|
@ -56,7 +56,7 @@ object MatterBottlerProvider : IBlockComponentProvider, IServerDataProvider<Bloc
|
||||
data.getFloat("workProgress"),
|
||||
null,
|
||||
elementHelper.progressStyle().color(RGBAColor.WHITE.toBGRA()),
|
||||
BoxStyle.getNestedBox(),
|
||||
BoxStyle.DEFAULT,
|
||||
true
|
||||
)
|
||||
)
|
||||
|
@ -57,7 +57,7 @@ object MatterReconstructorProvider : IBlockComponentProvider, IServerDataProvide
|
||||
maxDamage
|
||||
),
|
||||
elementHelper.progressStyle().color(RGBAColor.DARK_GREEN.toBGRA()).textColor(RGBAColor.WHITE.toBGRA()),
|
||||
BoxStyle.getNestedBox(),
|
||||
BoxStyle.DEFAULT,
|
||||
true
|
||||
)
|
||||
)
|
||||
|
@ -69,7 +69,7 @@ object MatterStorageProvider : IBlockComponentProvider, IServerDataProvider<Bloc
|
||||
maxStoredMatter.formatMatter()
|
||||
),
|
||||
elementHelper.progressStyle().color(JadeColors.MATTER_COLOR.toBGRA()).textColor(RGBAColor.WHITE.toBGRA()),
|
||||
BoxStyle.getNestedBox(),
|
||||
BoxStyle.DEFAULT,
|
||||
true
|
||||
)
|
||||
)
|
||||
|
@ -67,7 +67,7 @@ object MatteryEnergyProvider : IBlockComponentProvider, IServerDataProvider<Bloc
|
||||
maxBatteryLevel.formatPower()
|
||||
),
|
||||
elementHelper.progressStyle().color(JadeColors.ENERGY_COLOR.toBGRA(), JadeColors.ENERGY_COLOR2.toBGRA()).textColor(RGBAColor.WHITE.toBGRA()),
|
||||
BoxStyle.getNestedBox(),
|
||||
BoxStyle.DEFAULT,
|
||||
true
|
||||
)
|
||||
)
|
||||
|
@ -75,7 +75,7 @@ object MatteryWorkerProvider : IBlockComponentProvider, IServerDataProvider<Bloc
|
||||
progress,
|
||||
null,
|
||||
if (isUnableToProcess) styleError else style,
|
||||
BoxStyle.getNestedBox(),
|
||||
BoxStyle.DEFAULT,
|
||||
true
|
||||
)
|
||||
)
|
||||
|
@ -14,15 +14,14 @@ import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.MenuType
|
||||
import net.minecraft.world.inventory.Slot
|
||||
import net.minecraft.world.item.crafting.CraftingRecipe
|
||||
import net.minecraft.world.item.crafting.RecipeHolder
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.toImmutableList
|
||||
import ru.dbotthepony.mc.otm.menu.ExopackInventoryMenu
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class ExopackInventoryTransferHandler(private val helper: IRecipeTransferHandlerHelper) : IRecipeTransferHandler<ExopackInventoryMenu, RecipeHolder<CraftingRecipe>> {
|
||||
private val transfer = helper.createUnregisteredRecipeTransferHandler(object : IRecipeTransferInfo<ExopackInventoryMenu, RecipeHolder<CraftingRecipe>> {
|
||||
class ExopackInventoryTransferHandler(private val helper: IRecipeTransferHandlerHelper) : IRecipeTransferHandler<ExopackInventoryMenu, CraftingRecipe> {
|
||||
private val transfer = helper.createUnregisteredRecipeTransferHandler(object : IRecipeTransferInfo<ExopackInventoryMenu, CraftingRecipe> {
|
||||
override fun getContainerClass(): Class<out ExopackInventoryMenu> {
|
||||
return ExopackInventoryMenu::class.java
|
||||
}
|
||||
@ -31,24 +30,24 @@ class ExopackInventoryTransferHandler(private val helper: IRecipeTransferHandler
|
||||
return Optional.empty()
|
||||
}
|
||||
|
||||
override fun getRecipeType(): mezz.jei.api.recipe.RecipeType<RecipeHolder<CraftingRecipe>> {
|
||||
override fun getRecipeType(): mezz.jei.api.recipe.RecipeType<CraftingRecipe> {
|
||||
return RecipeTypes.CRAFTING
|
||||
}
|
||||
|
||||
override fun canHandle(container: ExopackInventoryMenu, recipe: RecipeHolder<CraftingRecipe>): Boolean {
|
||||
override fun canHandle(container: ExopackInventoryMenu, recipe: CraftingRecipe): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getRecipeSlots(
|
||||
container: ExopackInventoryMenu,
|
||||
recipe: RecipeHolder<CraftingRecipe>
|
||||
recipe: CraftingRecipe
|
||||
): List<Slot> {
|
||||
return container.craftingSlots
|
||||
}
|
||||
|
||||
override fun getInventorySlots(
|
||||
container: ExopackInventoryMenu,
|
||||
recipe: RecipeHolder<CraftingRecipe>
|
||||
recipe: CraftingRecipe
|
||||
): List<Slot> {
|
||||
return container.playerInventorySlots
|
||||
}
|
||||
@ -62,7 +61,7 @@ class ExopackInventoryTransferHandler(private val helper: IRecipeTransferHandler
|
||||
return Optional.empty()
|
||||
}
|
||||
|
||||
override fun getRecipeType(): mezz.jei.api.recipe.RecipeType<RecipeHolder<CraftingRecipe>> {
|
||||
override fun getRecipeType(): mezz.jei.api.recipe.RecipeType<CraftingRecipe> {
|
||||
return RecipeTypes.CRAFTING
|
||||
}
|
||||
|
||||
@ -89,7 +88,7 @@ class ExopackInventoryTransferHandler(private val helper: IRecipeTransferHandler
|
||||
|
||||
override fun transferRecipe(
|
||||
container: ExopackInventoryMenu,
|
||||
recipe: RecipeHolder<CraftingRecipe>,
|
||||
recipe: CraftingRecipe,
|
||||
recipeSlots: IRecipeSlotsView,
|
||||
player: Player,
|
||||
maxTransfer: Boolean,
|
||||
|
@ -26,6 +26,8 @@ import ru.dbotthepony.mc.otm.core.collect.filter
|
||||
import ru.dbotthepony.mc.otm.core.collect.filterIsInstance
|
||||
import ru.dbotthepony.mc.otm.core.collect.map
|
||||
import ru.dbotthepony.mc.otm.core.collect.toList
|
||||
import ru.dbotthepony.mc.otm.core.filterNotNull
|
||||
import ru.dbotthepony.mc.otm.core.value
|
||||
import ru.dbotthepony.mc.otm.menu.decorative.PainterMenu
|
||||
import ru.dbotthepony.mc.otm.menu.matter.MatterEntanglerMenu
|
||||
import ru.dbotthepony.mc.otm.menu.tech.PlatePressMenu
|
||||
|
@ -20,11 +20,13 @@ import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.chat.ComponentContents
|
||||
import net.minecraft.network.chat.contents.TranslatableContents
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.Container
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.item.crafting.Ingredient
|
||||
import net.minecraft.world.item.crafting.Recipe
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.LevelAccessor
|
||||
@ -33,6 +35,8 @@ import net.minecraft.world.level.block.Blocks
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateHolder
|
||||
import net.minecraft.world.level.block.state.properties.Property
|
||||
import net.minecraft.world.level.saveddata.SavedData
|
||||
import net.minecraft.world.level.storage.DimensionDataStorage
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraftforge.common.ForgeHooks
|
||||
import net.minecraftforge.common.util.LazyOptional
|
||||
@ -67,6 +71,7 @@ import java.util.UUID
|
||||
import java.util.concurrent.Callable
|
||||
import java.util.concurrent.Future
|
||||
import java.util.function.Consumer
|
||||
import java.util.function.Function
|
||||
import java.util.function.Supplier
|
||||
import java.util.stream.Stream
|
||||
import java.util.stream.StreamSupport
|
||||
@ -516,3 +521,4 @@ fun <A, B> lazy2(a: () -> A, b: A.() -> B): Supplier<B> {
|
||||
return Supplier { b.invoke(first.value) }
|
||||
}
|
||||
|
||||
inline val <R : Recipe<T>, T : Container> R.value get() = this
|
||||
|
@ -117,7 +117,7 @@ fun CompoundTag.putJson(key: String, json: JsonElement) {
|
||||
putByteArray(key, bytes.array.copyOfRange(0, bytes.length))
|
||||
}
|
||||
|
||||
fun CompoundTag.getJson(key: String, sizeLimit: NbtAccounter = NbtAccounter(1 shl 18, 512)): JsonElement? {
|
||||
fun CompoundTag.getJson(key: String, sizeLimit: NbtAccounter = NbtAccounter(1 shl 18)): JsonElement? {
|
||||
val bytes = getByteArray(key)
|
||||
|
||||
if (bytes.isEmpty())
|
||||
|
@ -8,9 +8,7 @@ import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.DataResult
|
||||
import com.mojang.serialization.DynamicOps
|
||||
import com.mojang.serialization.JsonOps
|
||||
import io.netty.buffer.ByteBuf
|
||||
import io.netty.buffer.Unpooled
|
||||
import net.minecraft.advancements.AdvancementHolder
|
||||
import net.minecraft.data.recipes.FinishedRecipe
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
@ -24,15 +22,7 @@ import ru.dbotthepony.mc.otm.core.util.readBinaryJsonWithCodecIndirect
|
||||
import ru.dbotthepony.mc.otm.core.util.writeBinaryJsonWithCodec
|
||||
import kotlin.collections.ArrayDeque
|
||||
import kotlin.concurrent.getOrSet
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
/**
|
||||
* 1.20.2: Mojang FINALLY moved json IO of recipes to codecs
|
||||
*
|
||||
* ...but they forgot to do the same for Networking them, Ingredient does not have codec for network.
|
||||
*
|
||||
* Mojang.... Mojang never changes.
|
||||
*/
|
||||
class Codec2RecipeSerializer<S : Recipe<*>>(
|
||||
val empty: S?,
|
||||
codec: (Codec2RecipeSerializer<S>.Context) -> Codec<S>,
|
||||
@ -40,45 +30,18 @@ class Codec2RecipeSerializer<S : Recipe<*>>(
|
||||
constructor(supplier: (Codec2RecipeSerializer<S>.Context) -> Codec<S>) : this(null, supplier)
|
||||
|
||||
private class CurrentContext {
|
||||
val idStack = ArrayDeque<ResourceLocation>()
|
||||
var isNetwork = 0
|
||||
}
|
||||
|
||||
inner class Context {
|
||||
val id: ResourceLocation
|
||||
get() = checkNotNull(context.idStack.lastOrNull()) { "Not currently deserializing recipe" }
|
||||
|
||||
val ingredients: Codec<Ingredient> get() = ActualIngredientCodec
|
||||
|
||||
fun <P : Recipe<*>> wrap(serializer: RecipeSerializer<P>): Codec<P> {
|
||||
return object : Codec<P> {
|
||||
override fun <T : Any?> encode(input: P, ops: DynamicOps<T>, prefix: T): DataResult<T> {
|
||||
if (context.isNetwork > 0) {
|
||||
val parent = Unpooled.buffer()
|
||||
val buff = FriendlyByteBuf(parent)
|
||||
serializer.toNetwork(buff, input)
|
||||
return DataResult.success(ops.createByteList(parent.nioBuffer()))
|
||||
} else {
|
||||
return serializer.codec().encode(input, ops, prefix)
|
||||
}
|
||||
}
|
||||
|
||||
override fun <T : Any?> decode(ops: DynamicOps<T>, input: T): DataResult<Pair<P, T>> {
|
||||
if (context.isNetwork > 0) {
|
||||
return ops.getByteBuffer(input).flatMap {
|
||||
val parent = Unpooled.buffer()
|
||||
val buff = FriendlyByteBuf(parent)
|
||||
parent.writeBytes(it)
|
||||
parent.setIndex(0, 0)
|
||||
val read = serializer.fromNetwork(buff)
|
||||
|
||||
if (read == null)
|
||||
DataResult.error { "Unable to read parent recipe from network" }
|
||||
else
|
||||
DataResult.success(Pair(read, ops.empty()))
|
||||
}
|
||||
} else {
|
||||
return serializer.codec().decode(ops, input)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val isNetwork: Boolean
|
||||
get() = context.isNetwork > 0
|
||||
}
|
||||
|
||||
private val codec = codec.invoke(Context())
|
||||
@ -97,30 +60,45 @@ class Codec2RecipeSerializer<S : Recipe<*>>(
|
||||
}
|
||||
}
|
||||
|
||||
override fun codec(): Codec<S> {
|
||||
return this
|
||||
override fun fromJson(id: ResourceLocation, data: JsonObject): S {
|
||||
try {
|
||||
context.idStack.addLast(id)
|
||||
|
||||
return decode(JsonOps.INSTANCE, data).get().map(
|
||||
{ it.first },
|
||||
{ empty ?: throw JsonSyntaxException("Failed to deserialize recipe from JSON: ${it.message()}") }
|
||||
)
|
||||
} finally {
|
||||
context.idStack.removeLast()
|
||||
}
|
||||
}
|
||||
|
||||
override fun fromNetwork(data: FriendlyByteBuf): S? {
|
||||
override fun fromNetwork(id: ResourceLocation, data: FriendlyByteBuf): S? {
|
||||
try {
|
||||
context.idStack.addLast(id)
|
||||
context.isNetwork++
|
||||
|
||||
return data.readBinaryJsonWithCodecIndirect(this)
|
||||
.resultOrPartial { LOGGER.error("Failed to read recipe from network: $it") }.orElse(null)
|
||||
.resultOrPartial { LOGGER.error("Failed to read recipe $id from network: $it") }.orElse(null)
|
||||
} finally {
|
||||
context.isNetwork--
|
||||
context.idStack.removeLast()
|
||||
}
|
||||
}
|
||||
|
||||
override fun toNetwork(data: FriendlyByteBuf, recipe: S) {
|
||||
try {
|
||||
context.idStack.addLast(recipe.id)
|
||||
context.isNetwork++
|
||||
|
||||
data.writeBinaryJsonWithCodec(this, recipe)
|
||||
} finally {
|
||||
context.isNetwork--
|
||||
context.idStack.removeLast()
|
||||
}
|
||||
}
|
||||
|
||||
fun toFinished(recipe: S, id: ResourceLocation): FinishedRecipe {
|
||||
fun toFinished(recipe: S): FinishedRecipe {
|
||||
return object : FinishedRecipe {
|
||||
override fun serializeRecipeData(p_125967_: JsonObject) {
|
||||
encode(recipe, JsonOps.INSTANCE, p_125967_).get().map(
|
||||
@ -137,15 +115,19 @@ class Codec2RecipeSerializer<S : Recipe<*>>(
|
||||
)
|
||||
}
|
||||
|
||||
override fun id(): ResourceLocation {
|
||||
return id
|
||||
override fun getId(): ResourceLocation {
|
||||
return recipe.id
|
||||
}
|
||||
|
||||
override fun type(): RecipeSerializer<*> {
|
||||
override fun getType(): RecipeSerializer<*> {
|
||||
return this@Codec2RecipeSerializer
|
||||
}
|
||||
|
||||
override fun advancement(): AdvancementHolder? {
|
||||
override fun serializeAdvancement(): JsonObject? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getAdvancementId(): ResourceLocation? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
@ -156,7 +138,7 @@ class Codec2RecipeSerializer<S : Recipe<*>>(
|
||||
return if (context.isNetwork > 0) {
|
||||
networkIngredientCodec.encode(input, ops, prefix)
|
||||
} else {
|
||||
Ingredient.CODEC.encode(input, ops, prefix)
|
||||
IngredientCodec.encode(input, ops, prefix)
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,7 +146,7 @@ class Codec2RecipeSerializer<S : Recipe<*>>(
|
||||
return if (context.isNetwork > 0) {
|
||||
networkIngredientCodec.decode(ops, input)
|
||||
} else {
|
||||
Ingredient.CODEC.decode(ops, input)
|
||||
IngredientCodec.decode(ops, input)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -178,14 +160,8 @@ class Codec2RecipeSerializer<S : Recipe<*>>(
|
||||
* since RecipeSerializers are expected to be stateless. [Codec2RecipeSerializer], however, is stateful (threading PoV).
|
||||
* To make it stateless, [ThreadLocal] is used.
|
||||
*/
|
||||
private val context by object : ThreadLocal<CurrentContext>() {
|
||||
override fun initialValue(): CurrentContext {
|
||||
return CurrentContext()
|
||||
}
|
||||
}
|
||||
private val contextHolder = ThreadLocal<CurrentContext>()
|
||||
private val context: CurrentContext
|
||||
get() = contextHolder.getOrSet { CurrentContext() }
|
||||
}
|
||||
}
|
||||
|
||||
private operator fun <T> ThreadLocal<T>.getValue(companion: Codec2RecipeSerializer.Companion, property: KProperty<*>): T {
|
||||
return get()
|
||||
}
|
||||
|
@ -0,0 +1,38 @@
|
||||
package ru.dbotthepony.mc.otm.data
|
||||
|
||||
import com.google.gson.JsonDeserializationContext
|
||||
import com.google.gson.JsonNull
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonSerializationContext
|
||||
import com.google.gson.JsonSyntaxException
|
||||
import com.mojang.serialization.Codec
|
||||
import net.minecraft.world.level.storage.loot.Serializer
|
||||
import ru.dbotthepony.mc.otm.core.fromJsonStrict
|
||||
import ru.dbotthepony.mc.otm.core.set
|
||||
import ru.dbotthepony.mc.otm.core.toJsonStrict
|
||||
|
||||
class Codec2Serializer<T : Any>(val codec: Codec<T>, val embed: Boolean = false) : Serializer<T> {
|
||||
override fun serialize(data: JsonObject, value: T, context: JsonSerializationContext) {
|
||||
if (embed) {
|
||||
val result = codec.toJsonStrict(value, data)
|
||||
|
||||
if (result !is JsonObject) {
|
||||
throw RuntimeException("Expected JsonObject from codec, got ${result::class.qualifiedName}")
|
||||
}
|
||||
|
||||
val keys = ArrayList(data.keySet())
|
||||
for (k in keys) data.remove(k)
|
||||
for ((k, v) in result.entrySet()) data[k] = v
|
||||
} else {
|
||||
data["value"] = codec.toJsonStrict(value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun deserialize(data: JsonObject, context: JsonDeserializationContext): T {
|
||||
if (embed) {
|
||||
return codec.fromJsonStrict(data)
|
||||
} else {
|
||||
return codec.fromJsonStrict(data["value"] ?: JsonNull.INSTANCE)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +1,48 @@
|
||||
package ru.dbotthepony.mc.otm.data
|
||||
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.DataResult
|
||||
import com.mojang.serialization.Dynamic
|
||||
import com.mojang.serialization.DynamicOps
|
||||
import com.mojang.serialization.JsonOps
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.advancements.critereon.DamagePredicate
|
||||
import net.minecraft.advancements.critereon.DamageSourcePredicate
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
import net.minecraft.advancements.critereon.MinMaxBounds
|
||||
import java.util.Optional
|
||||
import kotlin.reflect.KProperty1
|
||||
|
||||
val DoublesCodec: Codec<MinMaxBounds.Doubles> = RecordCodecBuilder.create {
|
||||
it.group(
|
||||
Codec.DOUBLE.optionalFieldOf("min").forGetter { Optional.ofNullable(it.min) },
|
||||
Codec.DOUBLE.optionalFieldOf("max").forGetter { Optional.ofNullable(it.max) },
|
||||
).apply(it) { min, max ->
|
||||
if (min.isEmpty && max.isEmpty)
|
||||
MinMaxBounds.Doubles.ANY
|
||||
else if (min.isEmpty)
|
||||
MinMaxBounds.Doubles.atMost(max.get())
|
||||
else if (max.isEmpty)
|
||||
MinMaxBounds.Doubles.atLeast(min.get())
|
||||
else
|
||||
MinMaxBounds.Doubles.between(min.get(), max.get())
|
||||
}
|
||||
}
|
||||
|
||||
private val dealtReceived: Codec<Pair<MinMaxBounds.Doubles, MinMaxBounds.Doubles>> = RecordCodecBuilder.create {
|
||||
it.group(
|
||||
MinMaxBounds.Doubles.CODEC.fieldOf("dealt").forGetter { it.first },
|
||||
MinMaxBounds.Doubles.CODEC.fieldOf("taken").forGetter { it.second },
|
||||
DoublesCodec.fieldOf("dealt").forGetter { it.first },
|
||||
DoublesCodec.fieldOf("taken").forGetter { it.second },
|
||||
).apply(it, ::Pair)
|
||||
}
|
||||
|
||||
val DamagePredicateCodec: Codec<DamagePredicate> = RecordCodecBuilder.create {
|
||||
it.group(
|
||||
dealtReceived.fieldOf("damage").forGetter { it.dealtDamage to it.takenDamage },
|
||||
Codec.BOOL.optionalFieldOf("blocked").forGetter { it.blocked },
|
||||
EntityPredicate.CODEC.optionalFieldOf("source_entity").forGetter { it.sourceEntity },
|
||||
DamageSourcePredicate.CODEC.optionalFieldOf("type").forGetter { it.type },
|
||||
).apply(it) { damage, blocked, source, type -> DamagePredicate(damage.first, damage.second, source, blocked, type) }
|
||||
Codec.BOOL.optionalFieldOf("blocked").forGetter { Optional.ofNullable(it.blocked) },
|
||||
Codec.PASSTHROUGH.xmap({ EntityPredicate.fromJson(it.cast(JsonOps.INSTANCE)) }, { Dynamic(JsonOps.INSTANCE, it.serializeToJson()) }).fieldOf("source_entity").forGetter { it.sourceEntity },
|
||||
Codec.PASSTHROUGH.xmap({ DamageSourcePredicate.fromJson(it.cast(JsonOps.INSTANCE)) }, { Dynamic(JsonOps.INSTANCE, it.serializeToJson()) }).fieldOf("type").forGetter { it.type },
|
||||
).apply(it) { damage, blocked, source, type -> DamagePredicate(damage.first, damage.second, source, blocked.orElse(null), type) }
|
||||
}
|
||||
|
||||
fun <V, T1> simpleCodec(factory: (T1) -> V, field1: KProperty1<V, T1>, codec1: Codec<T1>): Codec<V> {
|
||||
|
@ -0,0 +1,23 @@
|
||||
package ru.dbotthepony.mc.otm.data
|
||||
|
||||
import com.google.gson.JsonSyntaxException
|
||||
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.JsonOps
|
||||
import net.minecraft.world.item.crafting.Ingredient
|
||||
|
||||
object IngredientCodec : Codec<Ingredient> {
|
||||
override fun <T : Any> encode(input: Ingredient, ops: DynamicOps<T>, prefix: T): DataResult<T> {
|
||||
return DataResult.success(JsonOps.INSTANCE.convertTo(ops, input.toJson()))
|
||||
}
|
||||
|
||||
override fun <T : Any> decode(ops: DynamicOps<T>, input: T): DataResult<Pair<Ingredient, T>> {
|
||||
try {
|
||||
return DataResult.success(Pair(Ingredient.fromJson(ops.convertTo(JsonOps.INSTANCE, input)), ops.empty()))
|
||||
} catch (err: JsonSyntaxException) {
|
||||
return DataResult.error { "Error decoding Ingredient: ${err.message}" }
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package ru.dbotthepony.mc.otm.data
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParseException
|
||||
import com.google.gson.JsonSyntaxException
|
||||
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.JsonOps
|
||||
import net.minecraft.advancements.critereon.ItemPredicate
|
||||
|
||||
object ItemPredicateCodec : Codec<ItemPredicate> {
|
||||
override fun <T : Any> encode(input: ItemPredicate, ops: DynamicOps<T>, prefix: T): DataResult<T> {
|
||||
return DataResult.success(JsonOps.INSTANCE.convertTo(ops, input.serializeToJson().let { if (it is JsonObject) it.getRidOfNulls() else it }))
|
||||
}
|
||||
|
||||
override fun <T : Any> decode(ops: DynamicOps<T>, input: T): DataResult<Pair<ItemPredicate, T>> {
|
||||
return try {
|
||||
DataResult.success(Pair(ItemPredicate.fromJson(ops.convertTo(JsonOps.INSTANCE, input)), ops.empty()))
|
||||
} catch (err: JsonSyntaxException) {
|
||||
DataResult.error { "Failed to deserialize ItemPredicate: ${err.message}" }
|
||||
} catch (err: JsonParseException) {
|
||||
DataResult.error { "Failed to deserialize ItemPredicate: ${err.message}" }
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package ru.dbotthepony.mc.otm.data
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
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.JsonOps
|
||||
import io.netty.buffer.UnpooledByteBufAllocator
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.world.item.crafting.Recipe
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
data class RecipePair<R : Recipe<*>>(val recipe: R, val data: JsonObject)
|
||||
|
||||
fun <R : Recipe<*>> RecipeSerializer<R>.codec(context: Codec2RecipeSerializer<*>.Context): Codec<RecipePair<R>> {
|
||||
return object : Codec<RecipePair<R>> {
|
||||
override fun <T : Any> encode(input: RecipePair<R>, ops: DynamicOps<T>, prefix: T): DataResult<T> {
|
||||
if (context.isNetwork) {
|
||||
val buffer = FriendlyByteBuf(UnpooledByteBufAllocator.DEFAULT.heapBuffer())
|
||||
buffer.writeResourceLocation(input.recipe.id)
|
||||
toNetwork(buffer, input.recipe)
|
||||
buffer.readerIndex(0)
|
||||
val array = ByteBuffer.allocate(buffer.readableBytes())
|
||||
buffer.readBytes(array)
|
||||
array.position(0)
|
||||
return DataResult.success(ops.createByteList(array))
|
||||
} else {
|
||||
return DataResult.success(JsonOps.INSTANCE.convertTo(ops, input.data))
|
||||
}
|
||||
}
|
||||
|
||||
override fun <T : Any> decode(ops: DynamicOps<T>, input: T): DataResult<Pair<RecipePair<R>, T>> {
|
||||
if (context.isNetwork) {
|
||||
return ops.getByteBuffer(input).map {
|
||||
it.position(0)
|
||||
val buffer = FriendlyByteBuf(UnpooledByteBufAllocator.DEFAULT.heapBuffer())
|
||||
buffer.writeBytes(it)
|
||||
buffer.readerIndex(0)
|
||||
Pair(RecipePair(fromNetwork(buffer.readResourceLocation(), buffer)!!, JsonObject()), ops.empty())
|
||||
}
|
||||
} else {
|
||||
val getJson = ops.convertTo(JsonOps.INSTANCE, input) as JsonObject
|
||||
return DataResult.success(Pair(RecipePair(fromJson(context.id, getJson), getJson), ops.empty()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@ import ru.dbotthepony.mc.otm.core.nbt.getJson
|
||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||
import ru.dbotthepony.mc.otm.core.stream
|
||||
import ru.dbotthepony.mc.otm.core.tagNotNull
|
||||
import ru.dbotthepony.mc.otm.data.Codec2Serializer
|
||||
import ru.dbotthepony.mc.otm.registry.MItemFunctionTypes
|
||||
import java.util.Optional
|
||||
import java.util.stream.Stream
|
||||
@ -73,15 +74,17 @@ class CopyTileNbtFunction(filter: Stream<out String> = Stream.empty()) : LootIte
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CODEC: Codec<CopyTileNbtFunction> by lazy {
|
||||
RecordCodecBuilder.create {
|
||||
it.group(
|
||||
Codec.STRING.listOf()
|
||||
.optionalFieldOf("filter")
|
||||
.xmap({ it.orElseGet { listOf() } }, { if (it.isEmpty()) Optional.empty() else Optional.of(it) })
|
||||
.forGetter(CopyTileNbtFunction::filter),
|
||||
).apply(it, ::CopyTileNbtFunction)
|
||||
}
|
||||
val CODEC by lazy {
|
||||
Codec2Serializer<CopyTileNbtFunction>(
|
||||
RecordCodecBuilder.create {
|
||||
it.group(
|
||||
Codec.STRING.listOf()
|
||||
.optionalFieldOf("filter")
|
||||
.xmap({ it.orElseGet { listOf() } }, { if (it.isEmpty()) Optional.empty() else Optional.of(it) })
|
||||
.forGetter(CopyTileNbtFunction::filter),
|
||||
).apply(it, ::CopyTileNbtFunction)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,20 @@
|
||||
package ru.dbotthepony.mc.otm.data.loot
|
||||
|
||||
import com.google.common.collect.ImmutableList
|
||||
import com.google.gson.JsonSyntaxException
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.DataResult
|
||||
import com.mojang.serialization.Dynamic
|
||||
import com.mojang.serialization.JsonOps
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.storage.loot.Deserializers
|
||||
import net.minecraft.world.level.storage.loot.LootContext
|
||||
import net.minecraft.world.level.storage.loot.LootPool
|
||||
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.LootModifier
|
||||
import java.util.*
|
||||
@ -32,10 +39,51 @@ class LootPoolAppender(conditions: Array<out LootItemCondition>, pools: Stream<L
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val lootPoolCodec: Codec<List<LootPool>>
|
||||
|
||||
private val forgeHooksLootContext by lazy {
|
||||
val field = ForgeHooks::class.java.getDeclaredField("lootContext")
|
||||
field.isAccessible = true
|
||||
field
|
||||
}
|
||||
|
||||
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 {
|
||||
val serializer = Deserializers.createLootTableSerializer().create()
|
||||
val notExistingLocation = ResourceLocation("null", "null")
|
||||
|
||||
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 {
|
||||
deque.push(lootTableContextConstructor.newInstance(notExistingLocation, true))
|
||||
DataResult.success(serializer.fromJson(it.convert(JsonOps.INSTANCE).value, LootPool::class.java))
|
||||
} catch(err: JsonSyntaxException) {
|
||||
DataResult.error { err.message }
|
||||
} finally {
|
||||
deque.pop()
|
||||
}
|
||||
}, {
|
||||
try {
|
||||
DataResult.success(Dynamic(JsonOps.INSTANCE, serializer.toJsonTree(it)))
|
||||
} catch(err: JsonSyntaxException) {
|
||||
DataResult.error { err.message }
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
val CODEC: Codec<LootPoolAppender> =
|
||||
RecordCodecBuilder.create {
|
||||
codecStart(it).and(
|
||||
LootPool.CODEC.listOf().fieldOf("pools").forGetter(LootPoolAppender::pools)
|
||||
lootPoolCodec.fieldOf("pools").forGetter(LootPoolAppender::pools)
|
||||
).apply(it, ::LootPoolAppender)
|
||||
}
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ class FluidCapsuleItem(val capacity: IntSupplier) : MatteryItem(Properties().sta
|
||||
actionResult.result
|
||||
} else {
|
||||
val state = level.getBlockState(hitPos)
|
||||
val placePos = if (state.block is LiquidBlockContainer && (state.block as LiquidBlockContainer).canPlaceLiquid(player, level, hitPos, state, fluid.fluid)) hitPos else nextPos
|
||||
val placePos = if (state.block is LiquidBlockContainer && (state.block as LiquidBlockContainer).canPlaceLiquid(level, hitPos, state, fluid.fluid)) hitPos else nextPos
|
||||
|
||||
val actionResult = FluidUtil.tryPlaceFluid(player, level, hand, placePos, targetItem, fluid)
|
||||
if (!actionResult.isSuccess) return InteractionResultHolder.pass(item)
|
||||
|
@ -1,7 +1,7 @@
|
||||
package ru.dbotthepony.mc.otm.item
|
||||
|
||||
import net.minecraft.core.BlockSource
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.core.dispenser.BlockSource
|
||||
import net.minecraft.core.dispenser.DefaultDispenseItemBehavior
|
||||
import net.minecraft.core.dispenser.DispenseItemBehavior
|
||||
import net.minecraft.tags.BlockTags
|
||||
@ -9,17 +9,14 @@ import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.item.DyeColor
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.MinecartItem
|
||||
import net.minecraft.world.item.context.UseOnContext
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.BaseRailBlock
|
||||
import net.minecraft.world.level.block.DispenserBlock
|
||||
import net.minecraft.world.level.block.state.properties.RailShape
|
||||
import net.minecraft.world.level.gameevent.GameEvent
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.entity.MinecartCargoCrate
|
||||
import ru.dbotthepony.mc.otm.registry.MEntityTypes
|
||||
import kotlin.math.floor
|
||||
|
||||
class MinecartCargoCrateItem(val color: DyeColor?) : MatteryItem(Properties().stacksTo(16)) {
|
||||
init {
|
||||
@ -68,7 +65,7 @@ class MinecartCargoCrateItem(val color: DyeColor?) : MatteryItem(Properties().st
|
||||
private val default = DefaultDispenseItemBehavior()
|
||||
|
||||
override fun dispense(blockSource: BlockSource, itemStack: ItemStack): ItemStack {
|
||||
val direction = blockSource.state.getValue(DispenserBlock.FACING)
|
||||
val direction = blockSource.blockState.getValue(DispenserBlock.FACING)
|
||||
val level: Level = blockSource.level
|
||||
val x = blockSource.pos.x + direction.stepX.toDouble() * 1.125
|
||||
val y = blockSource.pos.y + direction.stepY.toDouble()
|
||||
|
@ -24,6 +24,7 @@ import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.core.math.set
|
||||
import ru.dbotthepony.mc.otm.core.nbt.mapPresent
|
||||
import ru.dbotthepony.mc.otm.core.tagNotNull
|
||||
import ru.dbotthepony.mc.otm.data.Codec2Serializer
|
||||
import ru.dbotthepony.mc.otm.data.DecimalProvider
|
||||
import ru.dbotthepony.mc.otm.registry.MItemFunctionTypes
|
||||
import java.util.Optional
|
||||
@ -119,15 +120,17 @@ class ProceduralBatteryItem : MatteryItem(Properties().stacksTo(1)) {
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CODEC: Codec<Randomizer> by lazy {
|
||||
RecordCodecBuilder.create {
|
||||
it.group(
|
||||
DecimalProvider.CODEC.fieldOf("maxBatteryLevel").forGetter(Randomizer::maxBatteryLevel),
|
||||
DecimalProvider.CODEC.optionalFieldOf("batteryLevel").forGetter(Randomizer::batteryLevel),
|
||||
DecimalProvider.CODEC.fieldOf("maxInput").forGetter(Randomizer::maxInput),
|
||||
DecimalProvider.CODEC.optionalFieldOf("maxOutput").forGetter(Randomizer::maxOutput),
|
||||
).apply(it, ::Randomizer)
|
||||
}
|
||||
val CODEC by lazy {
|
||||
Codec2Serializer<Randomizer>(
|
||||
RecordCodecBuilder.create {
|
||||
it.group(
|
||||
DecimalProvider.CODEC.fieldOf("maxBatteryLevel").forGetter(Randomizer::maxBatteryLevel),
|
||||
DecimalProvider.CODEC.optionalFieldOf("batteryLevel").forGetter(Randomizer::batteryLevel),
|
||||
DecimalProvider.CODEC.fieldOf("maxInput").forGetter(Randomizer::maxInput),
|
||||
DecimalProvider.CODEC.optionalFieldOf("maxOutput").forGetter(Randomizer::maxOutput),
|
||||
).apply(it, ::Randomizer)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ class QuantumBatteryItem(val savedataID: String, val balanceValues: EnergyBalanc
|
||||
val clientData = Object2ObjectOpenHashMap<UUID, IValues>()
|
||||
|
||||
val serverData: Data by lazyPerServer {
|
||||
it.overworld().dataStorage.computeIfAbsent(SavedData.Factory(::Data, ::Data, DataFixTypes.SAVED_DATA_MAP_DATA), "otm_$savedataID")
|
||||
it.overworld().dataStorage.computeIfAbsent(::Data, ::Data, "otm_$savedataID")
|
||||
}
|
||||
|
||||
private inner class Power(private val stack: ItemStack) : IMatteryEnergyStorage, ICapabilityProvider {
|
||||
|
@ -15,6 +15,7 @@ import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||
import ru.dbotthepony.mc.otm.core.tagNotNull
|
||||
import ru.dbotthepony.mc.otm.data.Codec2Serializer
|
||||
import ru.dbotthepony.mc.otm.registry.MItemFunctionTypes
|
||||
import java.util.*
|
||||
|
||||
@ -34,11 +35,15 @@ class ProceduralExopackSlotUpgradeItem : AbstractExopackSlotUpgradeItem(defaultP
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CODEC: Codec<Randomizer> = RecordCodecBuilder.create {
|
||||
it.group(
|
||||
IntProvider.CODEC.fieldOf("slots").forGetter(Randomizer::slots),
|
||||
IntProvider.CODEC.optionalFieldOf("luck_bias", ConstantInt.ZERO).forGetter(Randomizer::luckBias),
|
||||
).apply(it, ::Randomizer)
|
||||
val CODEC by lazy {
|
||||
Codec2Serializer<Randomizer>(
|
||||
RecordCodecBuilder.create {
|
||||
it.group(
|
||||
IntProvider.CODEC.fieldOf("slots").forGetter(Randomizer::slots),
|
||||
IntProvider.CODEC.optionalFieldOf("luck_bias", ConstantInt.ZERO).forGetter(Randomizer::luckBias),
|
||||
).apply(it, ::Randomizer)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,6 @@ import net.minecraftforge.event.AddReloadListenerEvent
|
||||
import net.minecraftforge.event.OnDatapackSyncEvent
|
||||
import net.minecraftforge.event.RegisterCommandsEvent
|
||||
import net.minecraftforge.event.entity.player.ItemTooltipEvent
|
||||
import net.minecraftforge.event.network.CustomPayloadEvent
|
||||
import net.minecraftforge.event.server.ServerStartedEvent
|
||||
import net.minecraftforge.eventbus.api.IEventBus
|
||||
import net.minecraftforge.fml.ModList
|
||||
@ -94,6 +93,7 @@ import ru.dbotthepony.mc.otm.core.util.readBinaryComponent
|
||||
import ru.dbotthepony.mc.otm.core.util.readCollection
|
||||
import ru.dbotthepony.mc.otm.core.util.writeBinaryComponent
|
||||
import ru.dbotthepony.mc.otm.core.util.writeCollection
|
||||
import ru.dbotthepony.mc.otm.core.value
|
||||
import ru.dbotthepony.mc.otm.core.writeItemType
|
||||
import ru.dbotthepony.mc.otm.milliTime
|
||||
import ru.dbotthepony.mc.otm.network.GenericNetworkChannel
|
||||
@ -1717,7 +1717,7 @@ object MatterManager {
|
||||
if (event.player == null) {
|
||||
syncRegistry(PacketDistributor.ALL.noArg())
|
||||
} else {
|
||||
syncRegistry(PacketDistributor.PLAYER.with(event.player!!))
|
||||
syncRegistry(PacketDistributor.PLAYER.with { event.player!! })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,9 +304,10 @@ abstract class MatteryMenu(
|
||||
open inner class EquipmentSlot(container: Container, index: Int, val type: net.minecraft.world.entity.EquipmentSlot) : InventorySlot(container, index) {
|
||||
constructor(type: net.minecraft.world.entity.EquipmentSlot) : this(inventory, 34 + type.ordinal, type)
|
||||
|
||||
override fun setByPlayer(newItem: ItemStack, oldItem: ItemStack) {
|
||||
override fun setByPlayer(newItem: ItemStack) {
|
||||
val oldItem = item
|
||||
inventory.player.onEquipItem(type, oldItem, newItem)
|
||||
super.setByPlayer(newItem, oldItem)
|
||||
super.setByPlayer(newItem)
|
||||
}
|
||||
|
||||
override fun mayPlace(itemStack: ItemStack): Boolean {
|
||||
@ -333,9 +334,10 @@ abstract class MatteryMenu(
|
||||
autoCreateInventoryFrame = autoFrame
|
||||
|
||||
offhandSlot = object : InventorySlot(inventory, 40) {
|
||||
override fun setByPlayer(newItem: ItemStack, oldItem: ItemStack) {
|
||||
override fun setByPlayer(newItem: ItemStack) {
|
||||
val oldItem = this.item
|
||||
inventory.player.onEquipItem(net.minecraft.world.entity.EquipmentSlot.OFFHAND, oldItem, newItem)
|
||||
super.setByPlayer(newItem, oldItem)
|
||||
super.setByPlayer(newItem)
|
||||
}
|
||||
|
||||
override fun getNoItemIcon(): Pair<ResourceLocation, ResourceLocation> {
|
||||
|
@ -242,7 +242,7 @@ class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val isRemote: Bo
|
||||
|
||||
fun network() {
|
||||
check(!isRemote) { "Not a server" }
|
||||
val consumer = PacketDistributor.PLAYER.with(ply as ServerPlayer)
|
||||
val consumer = PacketDistributor.PLAYER.with { ply as ServerPlayer }
|
||||
|
||||
for (packet in networkBacklog) {
|
||||
MenuNetworkChannel.send(consumer, packet)
|
||||
|
@ -4,7 +4,6 @@ import net.minecraft.world.SimpleContainer
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.*
|
||||
import net.minecraft.world.item.crafting.RecipeHolder
|
||||
import net.minecraft.world.level.material.Fluids
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
import net.minecraftforge.fluids.FluidStack
|
||||
@ -23,6 +22,7 @@ import ru.dbotthepony.mc.otm.core.collect.filter
|
||||
import ru.dbotthepony.mc.otm.core.collect.maybe
|
||||
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||
import ru.dbotthepony.mc.otm.core.util.ResourceLocationValueCodec
|
||||
import ru.dbotthepony.mc.otm.core.value
|
||||
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||
import ru.dbotthepony.mc.otm.menu.MatterySlot
|
||||
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
|
||||
@ -46,7 +46,7 @@ class PainterMenu(
|
||||
|
||||
val inputContainer = MatteryContainer(::rescan, 1)
|
||||
val outputContainer = MatteryContainer(1)
|
||||
private var lastRecipe: RecipeHolder<out AbstractPainterRecipe>? = null
|
||||
private var lastRecipe: AbstractPainterRecipe? = null
|
||||
var selectedRecipe by mSynchronizer.Slot(ListenableDelegate.Box(null), ResourceLocationValueCodec.nullable()).also { it.addListener(Runnable { rescan() }) }
|
||||
|
||||
val isBulk = BooleanInputWithFeedback(this, tile?.let { it::isBulk })
|
||||
@ -128,7 +128,7 @@ class PainterMenu(
|
||||
}
|
||||
|
||||
val listeners = Listenable.Void()
|
||||
val possibleRecipes = ArrayList<RecipeHolder<out AbstractPainterRecipe>>()
|
||||
val possibleRecipes = ArrayList<AbstractPainterRecipe>()
|
||||
|
||||
private fun rescan() {
|
||||
possibleRecipes.clear()
|
||||
@ -140,7 +140,7 @@ class PainterMenu(
|
||||
if (inputContainer.isEmpty || selectedRecipe == null) {
|
||||
outputContainer.clearContent()
|
||||
} else {
|
||||
val recipe = inventory.player.level().recipeManager.byKey(selectedRecipe!!).get() as RecipeHolder<AbstractPainterRecipe>?
|
||||
val recipe = inventory.player.level().recipeManager.byKey(selectedRecipe!!).get() as AbstractPainterRecipe?
|
||||
|
||||
if (recipe == null || !recipe.value.canCraft(dyeStoredDirect) || !recipe.value.matches(inputContainer, inventory.player.level())) {
|
||||
outputContainer.clearContent()
|
||||
|
@ -13,6 +13,7 @@ import ru.dbotthepony.mc.otm.container.ShadowCraftingContainer
|
||||
import ru.dbotthepony.mc.otm.container.get
|
||||
import ru.dbotthepony.mc.otm.container.set
|
||||
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||
import ru.dbotthepony.mc.otm.core.value
|
||||
import ru.dbotthepony.mc.otm.item.IQuantumLinked
|
||||
import ru.dbotthepony.mc.otm.menu.OutputSlot
|
||||
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||
|
@ -140,11 +140,11 @@ object GenericNetworkChannel : MatteryNetworkChannel(
|
||||
name = "generic"
|
||||
) {
|
||||
fun makeSmoke(x: Double, y: Double, z: Double, level: Level) {
|
||||
send(PacketDistributor.NEAR.with(PacketDistributor.TargetPoint(x, y, z, 64.0, level.dimension())), SmokeParticlesPacket(x, y, z))
|
||||
send(PacketDistributor.NEAR.with { PacketDistributor.TargetPoint(x, y, z, 64.0, level.dimension()) }, SmokeParticlesPacket(x, y, z))
|
||||
}
|
||||
|
||||
fun makeSmoke(excluded: ServerPlayer, x: Double, y: Double, z: Double) {
|
||||
send(PacketDistributor.NEAR.with(PacketDistributor.TargetPoint(excluded, x, y, z, 64.0, excluded.level().dimension())), SmokeParticlesPacket(x, y, z))
|
||||
send(PacketDistributor.NEAR.with { PacketDistributor.TargetPoint(excluded, x, y, z, 64.0, excluded.level().dimension()) }, SmokeParticlesPacket(x, y, z))
|
||||
}
|
||||
|
||||
fun register() {
|
||||
|
@ -5,12 +5,11 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraftforge.event.network.CustomPayloadEvent
|
||||
import net.minecraftforge.network.Channel
|
||||
import net.minecraftforge.network.ChannelBuilder
|
||||
import net.minecraftforge.network.NetworkDirection
|
||||
import net.minecraftforge.network.NetworkEvent
|
||||
import net.minecraftforge.network.NetworkRegistry
|
||||
import net.minecraftforge.network.PacketDistributor
|
||||
import net.minecraftforge.network.SimpleChannel
|
||||
import net.minecraftforge.network.simple.SimpleChannel
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.kommons.util.Delegate
|
||||
import ru.dbotthepony.kommons.util.getValue
|
||||
@ -22,6 +21,7 @@ import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import java.util.concurrent.locks.LockSupport
|
||||
import java.util.function.BiConsumer
|
||||
import java.util.function.Function
|
||||
import java.util.function.Supplier
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
class MNetworkContext(val sender: ServerPlayer?, packetHandled: Delegate<Boolean>, private val enqueuer: (Runnable) -> CompletableFuture<*>) {
|
||||
@ -38,18 +38,14 @@ interface MatteryPacket {
|
||||
}
|
||||
|
||||
abstract class MatteryNetworkChannel(val version: Int, val name: String) {
|
||||
val channel: SimpleChannel = ChannelBuilder
|
||||
.named(ResourceLocation(OverdriveThatMatters.MOD_ID, name))
|
||||
.clientAcceptedVersions { status, version -> (status == Channel.VersionTest.Status.MISSING || status == Channel.VersionTest.Status.VANILLA) || version == this.version }
|
||||
.serverAcceptedVersions { status, version -> status == Channel.VersionTest.Status.PRESENT || version == this.version }
|
||||
.networkProtocolVersion(version)
|
||||
.simpleChannel()
|
||||
val channel: SimpleChannel = NetworkRegistry
|
||||
.newSimpleChannel(ResourceLocation(OverdriveThatMatters.MOD_ID, name), { version.toString() }, { it == NetworkRegistry.ACCEPTVANILLA || it == NetworkRegistry.ABSENT.version || it == version.toString() }, { it == version.toString() })
|
||||
|
||||
fun sendToServer(packet: Any) = channel.send(packet, PacketDistributor.SERVER.noArg())
|
||||
fun sendToServer(packet: Any) = channel.send(PacketDistributor.SERVER.noArg(), packet)
|
||||
|
||||
fun send(ply: Player, packet: Any) {
|
||||
if (ply is ServerPlayer) {
|
||||
channel.send(packet, PacketDistributor.PLAYER.with(ply))
|
||||
channel.send(PacketDistributor.PLAYER.with { ply }, packet)
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,7 +54,7 @@ abstract class MatteryNetworkChannel(val version: Int, val name: String) {
|
||||
return
|
||||
}
|
||||
|
||||
channel.send(packet, PacketDistributor.TRACKING_ENTITY.with(entity))
|
||||
channel.send(PacketDistributor.TRACKING_ENTITY.with { entity }, packet)
|
||||
}
|
||||
|
||||
fun sendTrackingAndSelf(entity: Entity, packet: Any) {
|
||||
@ -66,11 +62,11 @@ abstract class MatteryNetworkChannel(val version: Int, val name: String) {
|
||||
return
|
||||
}
|
||||
|
||||
channel.send(packet, PacketDistributor.TRACKING_ENTITY_AND_SELF.with(entity))
|
||||
channel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with { entity }, packet)
|
||||
}
|
||||
|
||||
fun send(distributor: PacketDistributor.PacketTarget, packet: Any) {
|
||||
channel.send(packet, distributor)
|
||||
channel.send(distributor, packet)
|
||||
}
|
||||
|
||||
private var nextNetworkPacketID = 0
|
||||
@ -87,8 +83,8 @@ abstract class MatteryNetworkChannel(val version: Int, val name: String) {
|
||||
throw IndexOutOfBoundsException("Network message ID overflow!")
|
||||
}
|
||||
|
||||
val builder = channel.messageBuilder(packetClass, direction)
|
||||
val bridgeHandler = BiConsumer<T, CustomPayloadEvent.Context> { a, b -> handler(a, MNetworkContext(b.sender, Delegate.Of({ b.packetHandled }, { b.packetHandled = it }), b::enqueueWork)) }
|
||||
val builder = channel.messageBuilder(packetClass, nextNetworkPacketID++)
|
||||
val bridgeHandler = BiConsumer<T, Supplier<NetworkEvent.Context>> { a, b -> handler(a, MNetworkContext(b.get().sender, Delegate.Of({ b.get().packetHandled }, { b.get().packetHandled = it }), b.get()::enqueueWork)) }
|
||||
|
||||
if (handleOnMainThread) {
|
||||
builder.consumerMainThread(bridgeHandler)
|
||||
|
@ -1,9 +1,11 @@
|
||||
package ru.dbotthepony.mc.otm.recipe
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import com.mojang.serialization.Codec
|
||||
import net.minecraft.core.NonNullList
|
||||
import net.minecraft.core.RegistryAccess
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.inventory.CraftingContainer
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.crafting.CraftingBookCategory
|
||||
@ -99,16 +101,12 @@ class EnergyContainerRecipe(val parent: ShapedRecipe) : CraftingRecipe, IShapedR
|
||||
}
|
||||
|
||||
companion object : RecipeSerializer<EnergyContainerRecipe> {
|
||||
private val codec by lazy {
|
||||
RecipeSerializer.SHAPED_RECIPE.codec().xmap(::EnergyContainerRecipe, EnergyContainerRecipe::parent)
|
||||
override fun fromNetwork(id: ResourceLocation, data: FriendlyByteBuf): EnergyContainerRecipe? {
|
||||
return ShapedRecipe.Serializer.SHAPED_RECIPE.fromNetwork(id, data)?.let(::EnergyContainerRecipe)
|
||||
}
|
||||
|
||||
override fun codec(): Codec<EnergyContainerRecipe> {
|
||||
return codec
|
||||
}
|
||||
|
||||
override fun fromNetwork(data: FriendlyByteBuf): EnergyContainerRecipe? {
|
||||
return ShapedRecipe.Serializer.SHAPED_RECIPE.fromNetwork(data)?.let(::EnergyContainerRecipe)
|
||||
override fun fromJson(p_44103_: ResourceLocation, p_44104_: JsonObject): EnergyContainerRecipe {
|
||||
return EnergyContainerRecipe(ShapedRecipe.Serializer.SHAPED_RECIPE.fromJson(p_44103_, p_44104_))
|
||||
}
|
||||
|
||||
override fun toNetwork(buff: FriendlyByteBuf, value: EnergyContainerRecipe) {
|
||||
|
@ -42,6 +42,7 @@ interface IMatterEntanglerRecipe : IMatteryRecipe<CraftingContainer> {
|
||||
}
|
||||
|
||||
open class MatterEntanglerRecipe(
|
||||
private val id: ResourceLocation,
|
||||
override val ingredients: IIngredientMatrix,
|
||||
override val matter: Decimal,
|
||||
override val ticks: Double,
|
||||
@ -50,6 +51,10 @@ open class MatterEntanglerRecipe(
|
||||
val uuidKey: String = "uuid",
|
||||
val fixedUuid: Optional<UUID> = Optional.empty()
|
||||
) : IMatterEntanglerRecipe {
|
||||
override fun getId(): ResourceLocation {
|
||||
return id
|
||||
}
|
||||
|
||||
override fun matches(container: CraftingContainer, level: Level): Boolean {
|
||||
if (isIncomplete) return false
|
||||
return ingredients.test(container)
|
||||
@ -98,8 +103,8 @@ open class MatterEntanglerRecipe(
|
||||
return ItemStack(MItems.MATTER_ENTANGLER)
|
||||
}
|
||||
|
||||
fun toFinished(id: ResourceLocation): FinishedRecipe {
|
||||
return SERIALIZER.toFinished(this, id)
|
||||
fun toFinished(): FinishedRecipe {
|
||||
return SERIALIZER.toFinished(this)
|
||||
}
|
||||
|
||||
fun energetic() = Energy(this)
|
||||
@ -114,8 +119,8 @@ open class MatterEntanglerRecipe(
|
||||
}
|
||||
}
|
||||
|
||||
fun toFinished(id: ResourceLocation): FinishedRecipe {
|
||||
return ENERGY_SERIALIZER.toFinished(this, id)
|
||||
fun toFinished(): FinishedRecipe {
|
||||
return ENERGY_SERIALIZER.toFinished(this)
|
||||
}
|
||||
|
||||
override fun getSerializer(): RecipeSerializer<*> {
|
||||
@ -132,8 +137,8 @@ open class MatterEntanglerRecipe(
|
||||
}
|
||||
}
|
||||
|
||||
fun toFinished(id: ResourceLocation): FinishedRecipe {
|
||||
return MATTER_SERIALIZER.toFinished(this, id)
|
||||
fun toFinished(): FinishedRecipe {
|
||||
return MATTER_SERIALIZER.toFinished(this)
|
||||
}
|
||||
|
||||
override fun getSerializer(): RecipeSerializer<*> {
|
||||
@ -152,7 +157,7 @@ open class MatterEntanglerRecipe(
|
||||
Codec.FLOAT.minRange(0f).optionalFieldOf("experience", 0f).forGetter(MatterEntanglerRecipe::experience),
|
||||
Codec.STRING.optionalFieldOf("uuidKey", "uuid").forGetter(MatterEntanglerRecipe::uuidKey),
|
||||
UUIDUtil.STRING_CODEC.optionalFieldOf("fixedUuid").forGetter(MatterEntanglerRecipe::fixedUuid)
|
||||
).apply(it, ::MatterEntanglerRecipe)
|
||||
).apply(it) { a, b, c, d, e, f, g -> MatterEntanglerRecipe(context.id, a, b, c, d, e, f, g) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,12 +24,17 @@ import ru.dbotthepony.mc.otm.registry.MItems
|
||||
import ru.dbotthepony.mc.otm.registry.MRecipes
|
||||
|
||||
abstract class MatteryCookingRecipe(
|
||||
private val id: ResourceLocation,
|
||||
val input: Ingredient,
|
||||
val output: Ingredient,
|
||||
val count: Int = 1,
|
||||
val workTime: Int = 200,
|
||||
val experience: FloatProvider = ConstantFloat.ZERO
|
||||
) : Recipe<Container> {
|
||||
override fun getId(): ResourceLocation {
|
||||
return id
|
||||
}
|
||||
|
||||
override fun matches(container: Container, level: Level): Boolean {
|
||||
if (isIncomplete)
|
||||
return false
|
||||
@ -69,20 +74,21 @@ abstract class MatteryCookingRecipe(
|
||||
|
||||
override fun getResultItem(registry: RegistryAccess): ItemStack = outputStack
|
||||
|
||||
abstract fun toFinished(id: ResourceLocation): FinishedRecipe
|
||||
abstract fun toFinished(): FinishedRecipe
|
||||
}
|
||||
|
||||
class MicrowaveRecipe(
|
||||
id: ResourceLocation,
|
||||
input: Ingredient,
|
||||
output: Ingredient,
|
||||
count: Int = 1,
|
||||
workTime: Int = 200,
|
||||
experience: FloatProvider = ConstantFloat.ZERO
|
||||
) : MatteryCookingRecipe(input, output, count, workTime, experience) {
|
||||
) : MatteryCookingRecipe(id, input, output, count, workTime, experience) {
|
||||
override fun getType(): RecipeType<*> = MRecipes.MICROWAVE
|
||||
override fun getToastSymbol(): ItemStack = ItemStack(MItems.POWERED_SMOKER[null]!!)
|
||||
override fun getSerializer(): RecipeSerializer<*> = SERIALIZER
|
||||
override fun toFinished(id: ResourceLocation): FinishedRecipe = SERIALIZER.toFinished(this, id)
|
||||
override fun toFinished(): FinishedRecipe = SERIALIZER.toFinished(this)
|
||||
|
||||
companion object {
|
||||
val SERIALIZER = Codec2RecipeSerializer<MicrowaveRecipe> { context ->
|
||||
@ -93,7 +99,7 @@ class MicrowaveRecipe(
|
||||
Codec.INT.minRange(1).optionalFieldOf("count", 1).forGetter(MicrowaveRecipe::count),
|
||||
Codec.INT.minRange(0).optionalFieldOf("workTime", 200).forGetter(MicrowaveRecipe::workTime),
|
||||
FloatProvider.CODEC.optionalFieldOf("experience", ConstantFloat.ZERO).forGetter(MicrowaveRecipe::experience)
|
||||
).apply(it, ::MicrowaveRecipe)
|
||||
).apply(it) { a, b, c, d, e -> MicrowaveRecipe(context.id, a, b, c, d, e) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,8 +31,13 @@ import ru.dbotthepony.mc.otm.registry.MRecipes
|
||||
import java.util.function.Predicate
|
||||
|
||||
abstract class AbstractPainterRecipe(
|
||||
private val id: ResourceLocation,
|
||||
dyes: Map<out DyeColor?, Int>
|
||||
) : IMatteryRecipe<Container> {
|
||||
override fun getId(): ResourceLocation {
|
||||
return id
|
||||
}
|
||||
|
||||
val dyes: Object2IntMap<DyeColor?> = Object2IntMaps.unmodifiable(Object2IntArrayMap(dyes))
|
||||
|
||||
abstract fun matches(value: ItemStack): Boolean
|
||||
@ -106,15 +111,17 @@ abstract class AbstractPainterRecipe(
|
||||
}
|
||||
|
||||
class PainterRecipe(
|
||||
id: ResourceLocation,
|
||||
val input: Ingredient,
|
||||
val output: ItemStack,
|
||||
dyes: Map<out DyeColor?, Int>
|
||||
) : AbstractPainterRecipe(dyes) {
|
||||
) : AbstractPainterRecipe(id, dyes) {
|
||||
constructor(
|
||||
id: ResourceLocation,
|
||||
input: Ingredient,
|
||||
output: ItemStack,
|
||||
dyes: Set<DyeColor?>
|
||||
) : this(input, output, Object2IntArrayMap<DyeColor?>().also { map -> dyes.forEach { map[it] = 1 } })
|
||||
) : this(id, input, output, Object2IntArrayMap<DyeColor?>().also { map -> dyes.forEach { map[it] = 1 } })
|
||||
|
||||
override fun matches(value: ItemStack): Boolean {
|
||||
return !isIncomplete && input.test(value)
|
||||
@ -154,8 +161,8 @@ class PainterRecipe(
|
||||
return MRecipes.PAINTER
|
||||
}
|
||||
|
||||
fun toFinished(id: ResourceLocation): FinishedRecipe {
|
||||
return SERIALIZER.toFinished(this, id)
|
||||
fun toFinished(): FinishedRecipe {
|
||||
return SERIALIZER.toFinished(this)
|
||||
}
|
||||
|
||||
override fun getOutput(container: Container): ItemStack {
|
||||
@ -169,17 +176,19 @@ class PainterRecipe(
|
||||
context.ingredients.fieldOf("input").forGetter(PainterRecipe::input),
|
||||
ItemStack.CODEC.fieldOf("output").forGetter(PainterRecipe::output),
|
||||
dyesFieldCodec.forGetter(AbstractPainterRecipe::dyes),
|
||||
).apply(it, ::PainterRecipe)
|
||||
).apply(it) { a, b, c -> PainterRecipe(context.id, a, b, c) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
class PainterArmorDyeRecipe(
|
||||
id: ResourceLocation,
|
||||
dyes: Map<out DyeColor?, Int>
|
||||
) : AbstractPainterRecipe(dyes) {
|
||||
) : AbstractPainterRecipe(id, dyes) {
|
||||
constructor(
|
||||
id: ResourceLocation,
|
||||
dyes: Set<DyeColor?>
|
||||
) : this(Object2IntArrayMap<DyeColor?>().also { map -> dyes.forEach { map[it] = 1 } })
|
||||
) : this(id, Object2IntArrayMap<DyeColor?>().also { map -> dyes.forEach { map[it] = 1 } })
|
||||
|
||||
override fun matches(value: ItemStack): Boolean {
|
||||
return !isIncomplete && value.item is DyeableArmorItem
|
||||
@ -207,8 +216,8 @@ class PainterArmorDyeRecipe(
|
||||
|
||||
override fun isIncomplete(): Boolean = dyes.isEmpty()
|
||||
|
||||
fun toFinished(id: ResourceLocation): FinishedRecipe {
|
||||
return SERIALIZER.toFinished(this, id)
|
||||
fun toFinished(): FinishedRecipe {
|
||||
return SERIALIZER.toFinished(this)
|
||||
}
|
||||
|
||||
override fun getOutput(container: Container): ItemStack {
|
||||
@ -228,11 +237,11 @@ class PainterArmorDyeRecipe(
|
||||
}
|
||||
|
||||
companion object {
|
||||
val SERIALIZER = Codec2RecipeSerializer<PainterArmorDyeRecipe> { _ ->
|
||||
val SERIALIZER = Codec2RecipeSerializer<PainterArmorDyeRecipe> { context ->
|
||||
RecordCodecBuilder.create {
|
||||
it.group(
|
||||
dyesFieldCodec.forGetter(AbstractPainterRecipe::dyes),
|
||||
).apply(it, ::PainterArmorDyeRecipe)
|
||||
).apply(it) { a -> PainterArmorDyeRecipe(context.id, a) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,12 +24,17 @@ import ru.dbotthepony.mc.otm.data.minRange
|
||||
import ru.dbotthepony.mc.otm.registry.MItems
|
||||
|
||||
class PlatePressRecipe(
|
||||
private val id: ResourceLocation,
|
||||
val input: Ingredient,
|
||||
val output: Ingredient,
|
||||
val count: Int = 1,
|
||||
val workTime: Int = 200,
|
||||
val experience: FloatProvider = ConstantFloat.ZERO
|
||||
) : Recipe<Container> {
|
||||
override fun getId(): ResourceLocation {
|
||||
return id
|
||||
}
|
||||
|
||||
override fun matches(container: Container, p_44003_: Level): Boolean {
|
||||
if (isIncomplete)
|
||||
return false
|
||||
@ -79,7 +84,7 @@ class PlatePressRecipe(
|
||||
return ItemStack(MItems.TWIN_PLATE_PRESS[null]!!)
|
||||
}
|
||||
|
||||
fun toFinished(id: ResourceLocation) = SERIALIZER.toFinished(this, id)
|
||||
fun toFinished() = SERIALIZER.toFinished(this)
|
||||
|
||||
companion object {
|
||||
val SERIALIZER = Codec2RecipeSerializer<PlatePressRecipe> { context ->
|
||||
@ -90,7 +95,7 @@ class PlatePressRecipe(
|
||||
Codec.INT.minRange(1).optionalFieldOf("count", 1).forGetter(PlatePressRecipe::count),
|
||||
Codec.INT.minRange(0).optionalFieldOf("workTime", 200).forGetter(PlatePressRecipe::workTime),
|
||||
FloatProvider.CODEC.optionalFieldOf("experience", ConstantFloat.ZERO).forGetter(PlatePressRecipe::experience)
|
||||
).apply(it, ::PlatePressRecipe)
|
||||
).apply(it) { a, b, c, d, e -> PlatePressRecipe(context.id, a, b, c, d, e) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,12 @@
|
||||
package ru.dbotthepony.mc.otm.recipe
|
||||
|
||||
import com.google.common.collect.ImmutableList
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonPrimitive
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.core.NonNullList
|
||||
import net.minecraft.core.RegistryAccess
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.GsonHelper
|
||||
import net.minecraft.util.StringRepresentable
|
||||
import net.minecraft.world.inventory.CraftingContainer
|
||||
import net.minecraft.world.item.ItemStack
|
||||
@ -25,68 +21,66 @@ import net.minecraftforge.common.crafting.IShapedRecipe
|
||||
import ru.dbotthepony.mc.otm.container.util.stream
|
||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||
import ru.dbotthepony.mc.otm.core.registryName
|
||||
import ru.dbotthepony.mc.otm.core.set
|
||||
import ru.dbotthepony.mc.otm.core.tagNotNull
|
||||
import ru.dbotthepony.mc.otm.core.util.readBinaryJson
|
||||
import ru.dbotthepony.mc.otm.core.util.writeBinaryJson
|
||||
import ru.dbotthepony.mc.otm.core.collect.stream
|
||||
import ru.dbotthepony.mc.otm.data.Codec2RecipeSerializer
|
||||
import ru.dbotthepony.mc.otm.data.RecipePair
|
||||
import ru.dbotthepony.mc.otm.data.codec
|
||||
import ru.dbotthepony.mc.otm.data.SingletonCodec
|
||||
import java.util.stream.Stream
|
||||
|
||||
class UpgradeRecipe(
|
||||
val parent: ShapedRecipe,
|
||||
val parent: RecipePair<ShapedRecipe>,
|
||||
copyPaths: Stream<Op>,
|
||||
val source: ResourceLocation,
|
||||
) : CraftingRecipe, IShapedRecipe<CraftingContainer> by parent {
|
||||
constructor(parent: ShapedRecipe, copyPaths: Collection<Op>, source: ResourceLocation) : this(parent, copyPaths.stream(), source)
|
||||
) : CraftingRecipe, IShapedRecipe<CraftingContainer> by parent.recipe {
|
||||
constructor(parent: RecipePair<ShapedRecipe>, copyPaths: Collection<Op>, source: ResourceLocation) : this(parent, copyPaths.stream(), source)
|
||||
|
||||
override fun matches(p_44002_: CraftingContainer, p_44003_: Level): Boolean {
|
||||
return parent.matches(p_44002_, p_44003_)
|
||||
return parent.recipe.matches(p_44002_, p_44003_)
|
||||
}
|
||||
|
||||
override fun canCraftInDimensions(p_43999_: Int, p_44000_: Int): Boolean {
|
||||
return parent.canCraftInDimensions(p_43999_, p_44000_)
|
||||
return parent.recipe.canCraftInDimensions(p_43999_, p_44000_)
|
||||
}
|
||||
|
||||
override fun getResultItem(p_267052_: RegistryAccess): ItemStack {
|
||||
return parent.getResultItem(p_267052_)
|
||||
return parent.recipe.getResultItem(p_267052_)
|
||||
}
|
||||
|
||||
override fun getRemainingItems(p_44004_: CraftingContainer): NonNullList<ItemStack> {
|
||||
return parent.getRemainingItems(p_44004_)
|
||||
return parent.recipe.getRemainingItems(p_44004_)
|
||||
}
|
||||
|
||||
override fun getIngredients(): NonNullList<Ingredient> {
|
||||
return parent.ingredients
|
||||
return parent.recipe.ingredients
|
||||
}
|
||||
|
||||
override fun isSpecial(): Boolean {
|
||||
return parent.isSpecial
|
||||
return parent.recipe.isSpecial
|
||||
}
|
||||
|
||||
override fun showNotification(): Boolean {
|
||||
return parent.showNotification()
|
||||
return parent.recipe.showNotification()
|
||||
}
|
||||
|
||||
override fun getGroup(): String {
|
||||
return parent.group
|
||||
return parent.recipe.group
|
||||
}
|
||||
|
||||
override fun getToastSymbol(): ItemStack {
|
||||
return parent.toastSymbol
|
||||
return parent.recipe.toastSymbol
|
||||
}
|
||||
|
||||
override fun isIncomplete(): Boolean {
|
||||
return parent.isIncomplete
|
||||
return parent.recipe.isIncomplete
|
||||
}
|
||||
|
||||
override fun getType(): RecipeType<*> {
|
||||
return parent.type
|
||||
return parent.recipe.type
|
||||
}
|
||||
|
||||
override fun category(): CraftingBookCategory {
|
||||
return parent.category()
|
||||
return parent.recipe.category()
|
||||
}
|
||||
|
||||
enum class OpType : StringRepresentable {
|
||||
@ -208,7 +202,7 @@ class UpgradeRecipe(
|
||||
val copyPaths: ImmutableList<Op> = copyPaths.collect(ImmutableList.toImmutableList())
|
||||
|
||||
override fun assemble(pInv: CraftingContainer, registryAccess: RegistryAccess): ItemStack {
|
||||
val result = parent.assemble(pInv, registryAccess)
|
||||
val result = parent.recipe.assemble(pInv, registryAccess)
|
||||
|
||||
if (result.isEmpty) {
|
||||
return result
|
||||
@ -242,7 +236,7 @@ class UpgradeRecipe(
|
||||
val CODEC = Codec2RecipeSerializer<UpgradeRecipe> { p ->
|
||||
RecordCodecBuilder.create {
|
||||
it.group(
|
||||
p.wrap(ShapedRecipe.Serializer.SHAPED_RECIPE).fieldOf("parent").forGetter(UpgradeRecipe::parent),
|
||||
ShapedRecipe.Serializer.SHAPED_RECIPE.codec(p).fieldOf("parent").forGetter(UpgradeRecipe::parent),
|
||||
COPY_PATHS_CODEC.fieldOf("copyPaths").forGetter(UpgradeRecipe::copyPaths),
|
||||
ResourceLocation.CODEC.fieldOf("source").forGetter(UpgradeRecipe::source)
|
||||
).apply(it, ::UpgradeRecipe)
|
||||
|
@ -6,6 +6,7 @@ import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
|
||||
import net.minecraftforge.eventbus.api.IEventBus
|
||||
import net.minecraftforge.registries.DeferredRegister
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.data.Codec2Serializer
|
||||
import ru.dbotthepony.mc.otm.data.SingletonCodec
|
||||
import ru.dbotthepony.mc.otm.data.condition.ChanceWithPlaytimeCondition
|
||||
import ru.dbotthepony.mc.otm.data.condition.HasExoPackCondition
|
||||
@ -17,12 +18,12 @@ import ru.dbotthepony.mc.otm.data.condition.ChanceCondition
|
||||
object MLootItemConditions {
|
||||
private val registry = MDeferredRegister(Registries.LOOT_CONDITION_TYPE, OverdriveThatMatters.MOD_ID)
|
||||
|
||||
val HAS_EXOPACK: LootItemConditionType by registry.register("has_exopack") { LootItemConditionType(SingletonCodec(HasExoPackCondition)) }
|
||||
val CHANCE_WITH_PLAYTIME: LootItemConditionType by registry.register("chance_with_playtime") { LootItemConditionType(ChanceWithPlaytimeCondition.CODEC) }
|
||||
val ITEM_IN_INVENTORY: LootItemConditionType by registry.register("item_in_inventory") { LootItemConditionType(ItemInInventoryCondition.CODEC) }
|
||||
val KILLED_BY_REAL_PLAYER: LootItemConditionType by registry.register("killed_by_real_player") { LootItemConditionType(SingletonCodec(KilledByRealPlayer)) }
|
||||
val KILLED_BY_REAL_PLAYER_OR_INDIRECTLY: LootItemConditionType by registry.register("killed_by_real_player_or_indirectly") { LootItemConditionType(SingletonCodec(KilledByRealPlayerOrIndirectly)) }
|
||||
val CHANCE: LootItemConditionType by registry.register("chance") { LootItemConditionType(ChanceCondition.CODEC) }
|
||||
val HAS_EXOPACK: LootItemConditionType by registry.register("has_exopack") { LootItemConditionType(Codec2Serializer(SingletonCodec(HasExoPackCondition))) }
|
||||
val CHANCE_WITH_PLAYTIME: LootItemConditionType by registry.register("chance_with_playtime") { LootItemConditionType(Codec2Serializer(ChanceWithPlaytimeCondition.CODEC)) }
|
||||
val ITEM_IN_INVENTORY: LootItemConditionType by registry.register("item_in_inventory") { LootItemConditionType(Codec2Serializer(ItemInInventoryCondition.CODEC)) }
|
||||
val KILLED_BY_REAL_PLAYER: LootItemConditionType by registry.register("killed_by_real_player") { LootItemConditionType(Codec2Serializer(SingletonCodec(KilledByRealPlayer))) }
|
||||
val KILLED_BY_REAL_PLAYER_OR_INDIRECTLY: LootItemConditionType by registry.register("killed_by_real_player_or_indirectly") { LootItemConditionType(Codec2Serializer(SingletonCodec(KilledByRealPlayerOrIndirectly))) }
|
||||
val CHANCE: LootItemConditionType by registry.register("chance") { LootItemConditionType(Codec2Serializer(ChanceCondition.CODEC)) }
|
||||
|
||||
internal fun register(bus: IEventBus) {
|
||||
registry.register(bus)
|
||||
|
@ -334,28 +334,28 @@ object MRegistry : IBlockItemRegistryAcceptor {
|
||||
NanobotsArmorFeature.Companion
|
||||
EnderTeleporterFeature.Companion
|
||||
|
||||
CriteriaTriggers.register(BlackHoleTrigger.id.toString(), BlackHoleTrigger)
|
||||
CriteriaTriggers.register(BecomeAndroidTrigger.id.toString(), BecomeAndroidTrigger)
|
||||
CriteriaTriggers.register(BecomeAndroidDeathTrigger.id.toString(), BecomeAndroidDeathTrigger)
|
||||
CriteriaTriggers.register(BecomeAndroidSleepTrigger.id.toString(), BecomeAndroidSleepTrigger)
|
||||
CriteriaTriggers.register(BecomeHumaneTrigger.id.toString(), BecomeHumaneTrigger)
|
||||
CriteriaTriggers.register(AndroidResearchTrigger.id.toString(), AndroidResearchTrigger)
|
||||
CriteriaTriggers.register(ShockwaveDamageMobTrigger.id.toString(), ShockwaveDamageMobTrigger)
|
||||
CriteriaTriggers.register(ShockwaveTrigger.id.toString(), ShockwaveTrigger)
|
||||
CriteriaTriggers.register(AndroidBatteryTrigger.id.toString(), AndroidBatteryTrigger)
|
||||
CriteriaTriggers.register(NanobotsArmorTrigger.id.toString(), NanobotsArmorTrigger)
|
||||
CriteriaTriggers.register(FallDampenersSaveTrigger.id.toString(), FallDampenersSaveTrigger)
|
||||
CriteriaTriggers.register(EnderTeleporterFallDeathTrigger.id.toString(), EnderTeleporterFallDeathTrigger)
|
||||
CriteriaTriggers.register(KillAsAndroidTrigger.id.toString(), KillAsAndroidTrigger)
|
||||
CriteriaTriggers.register(AndroidTravelUnderwater.id.toString(), AndroidTravelUnderwater)
|
||||
CriteriaTriggers.register(NailedEntityTrigger.id.toString(), NailedEntityTrigger)
|
||||
CriteriaTriggers.register(ExopackObtainedTrigger.id.toString(), ExopackObtainedTrigger)
|
||||
CriteriaTriggers.register(ExopackGainedSmeltingTrigger.id.toString(), ExopackGainedSmeltingTrigger)
|
||||
CriteriaTriggers.register(ExopackGainedCraftingTrigger.id.toString(), ExopackGainedCraftingTrigger)
|
||||
CriteriaTriggers.register(ExopackGainedEnderAccessTrigger.id.toString(), ExopackGainedEnderAccessTrigger)
|
||||
CriteriaTriggers.register(ExopackSlotsExpandedTrigger.id.toString(), ExopackSlotsExpandedTrigger)
|
||||
CriteriaTriggers.register(ExopackBatterySlotTrigger.id.toString(), ExopackBatterySlotTrigger)
|
||||
CriteriaTriggers.register(TakeItemOutOfReplicatorTrigger.id.toString(), TakeItemOutOfReplicatorTrigger)
|
||||
CriteriaTriggers.register(BlackHoleTrigger)
|
||||
CriteriaTriggers.register(BecomeAndroidTrigger)
|
||||
CriteriaTriggers.register(BecomeAndroidDeathTrigger)
|
||||
CriteriaTriggers.register(BecomeAndroidSleepTrigger)
|
||||
CriteriaTriggers.register(BecomeHumaneTrigger)
|
||||
CriteriaTriggers.register(AndroidResearchTrigger)
|
||||
CriteriaTriggers.register(ShockwaveDamageMobTrigger)
|
||||
CriteriaTriggers.register(ShockwaveTrigger)
|
||||
CriteriaTriggers.register(AndroidBatteryTrigger)
|
||||
CriteriaTriggers.register(NanobotsArmorTrigger)
|
||||
CriteriaTriggers.register(FallDampenersSaveTrigger)
|
||||
CriteriaTriggers.register(EnderTeleporterFallDeathTrigger)
|
||||
CriteriaTriggers.register(KillAsAndroidTrigger)
|
||||
CriteriaTriggers.register(AndroidTravelUnderwater)
|
||||
CriteriaTriggers.register(NailedEntityTrigger)
|
||||
CriteriaTriggers.register(ExopackObtainedTrigger)
|
||||
CriteriaTriggers.register(ExopackGainedSmeltingTrigger)
|
||||
CriteriaTriggers.register(ExopackGainedCraftingTrigger)
|
||||
CriteriaTriggers.register(ExopackGainedEnderAccessTrigger)
|
||||
CriteriaTriggers.register(ExopackSlotsExpandedTrigger)
|
||||
CriteriaTriggers.register(ExopackBatterySlotTrigger)
|
||||
CriteriaTriggers.register(TakeItemOutOfReplicatorTrigger)
|
||||
}
|
||||
|
||||
private fun initializeCommon(event: FMLCommonSetupEvent) {
|
||||
|
@ -4,6 +4,7 @@ import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.advancements.critereon.ContextAwarePredicate
|
||||
import net.minecraft.advancements.critereon.DamagePredicate
|
||||
import net.minecraft.advancements.critereon.DamageSourcePredicate
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
import net.minecraft.advancements.critereon.MinMaxBounds
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
@ -35,9 +36,9 @@ class HurtTrigger(id: ResourceLocation) : MCriterionTrigger<HurtTrigger.Instance
|
||||
val damagePredicate: Optional<DamagePredicate> = Optional.of(DamagePredicate(
|
||||
MinMaxBounds.Doubles.atLeast(1.0),
|
||||
MinMaxBounds.Doubles.atLeast(1.0),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
Optional.empty()
|
||||
EntityPredicate.ANY,
|
||||
null,
|
||||
DamageSourcePredicate.ANY
|
||||
)),
|
||||
player: Optional<ContextAwarePredicate> = Optional.empty()
|
||||
) : AbstractInstance(player)
|
||||
|
@ -7,6 +7,7 @@ import net.minecraft.advancements.critereon.ItemPredicate
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import ru.dbotthepony.mc.otm.data.ItemPredicateCodec
|
||||
import java.util.*
|
||||
|
||||
class ItemTrigger(id: ResourceLocation) : MCriterionTrigger<ItemTrigger.Instance>(id) {
|
||||
@ -16,7 +17,7 @@ class ItemTrigger(id: ResourceLocation) : MCriterionTrigger<ItemTrigger.Instance
|
||||
|
||||
override val codec: Codec<Instance> = RecordCodecBuilder.create {
|
||||
it.group(
|
||||
ItemPredicate.CODEC.fieldOf("predicate").forGetter(Instance::predicate),
|
||||
ItemPredicateCodec.fieldOf("predicate").forGetter(Instance::predicate),
|
||||
Codec.BOOL.optionalFieldOf("invert", false).forGetter(Instance::invert),
|
||||
playerPredicateCodec.forGetter(Instance::playerPredicate)
|
||||
).apply(it, ::Instance)
|
||||
|
@ -17,6 +17,7 @@ import net.minecraft.advancements.CriterionTriggerInstance
|
||||
import net.minecraft.advancements.critereon.ContextAwarePredicate
|
||||
import net.minecraft.advancements.critereon.DeserializationContext
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
import net.minecraft.advancements.critereon.SerializationContext
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.PlayerAdvancements
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
@ -29,7 +30,11 @@ import java.util.function.Predicate
|
||||
|
||||
// allows to support both 1.20.1 and 1.20.2 with ease
|
||||
// and has slightly less memory footprint than vanilla SimpleCriterionTrigger
|
||||
abstract class MCriterionTrigger<T : MCriterionTrigger<T>.AbstractInstance>(val id: ResourceLocation) : CriterionTrigger<T> {
|
||||
abstract class MCriterionTrigger<T : MCriterionTrigger<T>.AbstractInstance>(private val id: ResourceLocation) : CriterionTrigger<T> {
|
||||
override fun getId(): ResourceLocation {
|
||||
return id
|
||||
}
|
||||
|
||||
private val listeners = Reference2ObjectOpenHashMap<PlayerAdvancements, ObjectOpenHashSet<CriterionTrigger.Listener<T>>>()
|
||||
|
||||
override fun addPlayerListener(advancements: PlayerAdvancements, listener: CriterionTrigger.Listener<T>) {
|
||||
@ -62,16 +67,25 @@ abstract class MCriterionTrigger<T : MCriterionTrigger<T>.AbstractInstance>(val
|
||||
val context = EntityPredicate.createContext(player, player)
|
||||
|
||||
listeners.iterator()
|
||||
.filter { predicate.test(it.trigger) && it.trigger.playerPredicate.map { it.matches(context) }.orElse(true) }
|
||||
.filter { predicate.test(it.triggerInstance) && it.triggerInstance.playerPredicate.map { it.matches(context) }.orElse(true) }
|
||||
.toImmutableList()
|
||||
.forEach { it.run(advancements) }
|
||||
}
|
||||
|
||||
abstract inner class AbstractInstance(val playerPredicate: Optional<ContextAwarePredicate>) : CriterionTriggerInstance {
|
||||
fun criterion() = Criterion(this@MCriterionTrigger, this as T)
|
||||
fun criterion() = Criterion(this as T)
|
||||
|
||||
final override fun serializeToJson(): JsonObject {
|
||||
return codec.toJsonStrict(this as T) as JsonObject
|
||||
override fun getCriterion(): ResourceLocation {
|
||||
return id
|
||||
}
|
||||
|
||||
final override fun serializeToJson(context: SerializationContext): JsonObject {
|
||||
return try {
|
||||
serializationContext.get().addLast(context)
|
||||
codec.toJsonStrict(this as T) as JsonObject
|
||||
} finally {
|
||||
serializationContext.get().removeLast()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,17 +96,23 @@ abstract class MCriterionTrigger<T : MCriterionTrigger<T>.AbstractInstance>(val
|
||||
}
|
||||
}
|
||||
|
||||
protected val serializationContext = object : ThreadLocal<ArrayDeque<SerializationContext>>() {
|
||||
override fun initialValue(): ArrayDeque<SerializationContext> {
|
||||
return ArrayDeque()
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
protected val predicateCodec: Codec<ContextAwarePredicate> = object : Codec<ContextAwarePredicate> {
|
||||
override fun <T : Any?> encode(input: ContextAwarePredicate, ops: DynamicOps<T>, prefix: T): DataResult<T> {
|
||||
return DataResult.success(JsonOps.INSTANCE.convertTo(ops, input.toJson()))
|
||||
return DataResult.success(JsonOps.INSTANCE.convertTo(ops, input.toJson(serializationContext.get().lastOrNull() ?: return DataResult.error { "Not serializing trigger instance" })))
|
||||
}
|
||||
|
||||
override fun <T : Any?> decode(ops: DynamicOps<T>, input: T): DataResult<Pair<ContextAwarePredicate, T>> {
|
||||
val context = deserializationContext.get().lastOrNull() ?: return DataResult.error { "Not current deserializing trigger instance" }
|
||||
|
||||
return try {
|
||||
DataResult.success(Pair.of(EntityPredicate.fromJson(JsonObject().also { it["a"] = ops.convertTo(JsonOps.INSTANCE, input) }, "a", context).get(), ops.empty()))
|
||||
DataResult.success(Pair.of(EntityPredicate.fromJson(JsonObject().also { it["a"] = ops.convertTo(JsonOps.INSTANCE, input) }, "a", context), ops.empty()))
|
||||
} catch (err: Exception) {
|
||||
DataResult.error { "Failed to deserialize ContextAwarePredicate: " + err.message }
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import net.minecraft.advancements.CriterionTrigger
|
||||
import net.minecraft.advancements.critereon.DeserializationContext
|
||||
import net.minecraft.advancements.critereon.InventoryChangeTrigger
|
||||
import net.minecraft.advancements.critereon.MinMaxBounds
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.PlayerAdvancements
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.Container
|
||||
@ -83,13 +84,13 @@ object MatteryInventoryChangeTrigger : CriterionTrigger<InventoryChangeTrigger.T
|
||||
|
||||
nodes.add(Node(
|
||||
DefaultStrategy,
|
||||
{ predicates.iterator().flatMap { (it.items.map { it.map { it.value() } }.orElse(listOf(null))).iterator() }.toList() },
|
||||
{ predicates.iterator().flatMap { (it.items ?: listOf(null)).iterator() }.toList() },
|
||||
{ v, inventory: Container, item: ItemStack, slotsFull: Int, slotsEmpty: Int, slotsOccupied: Int -> v == null || item.item == v },
|
||||
{ inventory: Container, item: ItemStack, slotsFull: Int, slotsEmpty: Int, slotsOccupied: Int -> mutableListOf(item.item) }))
|
||||
|
||||
nodes.add(Node(
|
||||
DefaultStrategy,
|
||||
{ predicates.map { it.tag.orElse(null) } },
|
||||
{ predicates.map { it.tag } },
|
||||
{ v, inventory: Container, item: ItemStack, slotsFull: Int, slotsEmpty: Int, slotsOccupied: Int -> v == null || item.`is`(v) },
|
||||
{ inventory: Container, item: ItemStack, slotsFull: Int, slotsEmpty: Int, slotsOccupied: Int -> item.tags.collect(Collectors.toCollection(::ArrayList)) }))
|
||||
|
||||
@ -133,13 +134,13 @@ object MatteryInventoryChangeTrigger : CriterionTrigger<InventoryChangeTrigger.T
|
||||
|
||||
fun add(listener: CriterionTrigger.Listener<InventoryChangeTrigger.TriggerInstance>) {
|
||||
if (set.add(listener)) {
|
||||
search(listener.trigger, tree, 0).forEach { it.add(listener) }
|
||||
search(listener.triggerInstance, tree, 0).forEach { it.add(listener) }
|
||||
}
|
||||
}
|
||||
|
||||
fun remove(listener: CriterionTrigger.Listener<InventoryChangeTrigger.TriggerInstance>) {
|
||||
if (set.remove(listener)) {
|
||||
search(listener.trigger, tree, 0).forEach { it.remove(listener) }
|
||||
search(listener.triggerInstance, tree, 0).forEach { it.remove(listener) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,7 +166,7 @@ object MatteryInventoryChangeTrigger : CriterionTrigger<InventoryChangeTrigger.T
|
||||
if (nodeId + 1 == nodes.size) {
|
||||
for (l in v as Set<CriterionTrigger.Listener<InventoryChangeTrigger.TriggerInstance>>) {
|
||||
// переделываем matches у InventoryTriggerInstance
|
||||
with (l.trigger) {
|
||||
with (l.triggerInstance) {
|
||||
if (
|
||||
this.slotsFull.matches(slotsFull) &&
|
||||
this.slotsEmpty.matches(slotsEmpty) &&
|
||||
@ -217,6 +218,10 @@ object MatteryInventoryChangeTrigger : CriterionTrigger<InventoryChangeTrigger.T
|
||||
listeners[advancements]?.remove(instance)
|
||||
}
|
||||
|
||||
override fun getId(): ResourceLocation {
|
||||
return CriteriaTriggers.INVENTORY_CHANGED.id
|
||||
}
|
||||
|
||||
override fun removePlayerListeners(advancements: PlayerAdvancements) {
|
||||
listeners.remove(advancements)
|
||||
}
|
||||
|
@ -7,12 +7,13 @@ import net.minecraft.advancements.critereon.MinMaxBounds.Doubles
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.data.DoublesCodec
|
||||
import java.util.*
|
||||
|
||||
object NanobotsArmorTrigger : MCriterionTrigger<NanobotsArmorTrigger.Instance>(ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_armor")) {
|
||||
override val codec: Codec<Instance> = RecordCodecBuilder.create {
|
||||
it.group(
|
||||
Doubles.CODEC.fieldOf("predicate").forGetter(Instance::predicate),
|
||||
DoublesCodec.fieldOf("predicate").forGetter(Instance::predicate),
|
||||
playerPredicateCodec.forGetter(Instance::playerPredicate),
|
||||
).apply(it, ::Instance)
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ class SingletonTrigger(id: ResourceLocation) : MCriterionTrigger<SingletonTrigge
|
||||
}
|
||||
|
||||
val empty = Instance()
|
||||
val criterion = Criterion(this@SingletonTrigger, empty)
|
||||
val criterion = Criterion(empty)
|
||||
|
||||
inner class Instance(player: Optional<ContextAwarePredicate> = Optional.empty()) : AbstractInstance(player)
|
||||
}
|
||||
|
@ -172,3 +172,18 @@ public net.minecraft.advancements.critereon.InventoryChangeTrigger$TriggerInstan
|
||||
#public-f net.minecraft.advancements.critereon.SimpleCriterionTrigger m_6467_(Lnet/minecraft/server/PlayerAdvancements;Lnet/minecraft/advancements/CriterionTrigger$Listener;)V # addPlayerListener
|
||||
#public-f net.minecraft.advancements.critereon.SimpleCriterionTrigger m_6468_(Lnet/minecraft/server/PlayerAdvancements;Lnet/minecraft/advancements/CriterionTrigger$Listener;)V # removePlayerListener
|
||||
#public-f net.minecraft.advancements.critereon.SimpleCriterionTrigger m_5656_(Lnet/minecraft/server/PlayerAdvancements;)V # removePlayerListeners
|
||||
|
||||
public net.minecraft.advancements.critereon.ItemPredicate f_45031_
|
||||
public net.minecraft.advancements.critereon.ItemPredicate f_45032_
|
||||
public net.minecraft.advancements.critereon.ItemPredicate f_45033_
|
||||
public net.minecraft.advancements.critereon.ItemPredicate f_151427_
|
||||
public net.minecraft.advancements.critereon.ItemPredicate f_45036_
|
||||
public net.minecraft.advancements.critereon.ItemPredicate f_45035_
|
||||
public net.minecraft.advancements.critereon.ItemPredicate f_45034_
|
||||
public net.minecraft.advancements.critereon.ItemPredicate f_45029_
|
||||
|
||||
public net.minecraft.advancements.critereon.DamagePredicate f_24906_ # blocked
|
||||
public net.minecraft.advancements.critereon.DamagePredicate f_24903_ # dealtDamage
|
||||
public net.minecraft.advancements.critereon.DamagePredicate f_24905_ # sourceEntity
|
||||
public net.minecraft.advancements.critereon.DamagePredicate f_24904_ # takenDamage
|
||||
public net.minecraft.advancements.critereon.DamagePredicate f_24907_ # type
|
||||
|
@ -41,7 +41,7 @@ Matter. Energy. Combined.
|
||||
# Does this dependency have to exist - if not, ordering below must be specified
|
||||
mandatory=true #mandatory
|
||||
# The version range of the dependency
|
||||
versionRange="[48.0.0,)" #mandatory
|
||||
versionRange="[47.0.0,)" #mandatory
|
||||
# An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory
|
||||
ordering="NONE"
|
||||
# Side this dependency is applied on - BOTH, CLIENT or SERVER
|
||||
@ -51,6 +51,6 @@ Matter. Energy. Combined.
|
||||
modId="minecraft"
|
||||
mandatory=true
|
||||
# This version range declares a minimum of the current minecraft version up to but not including the next major version
|
||||
versionRange="[1.20.2,1.21)"
|
||||
versionRange="[1.20.1,1.20.2)"
|
||||
ordering="NONE"
|
||||
side="BOTH"
|
||||
|
Loading…
Reference in New Issue
Block a user