Compare commits

...

81 Commits
1.21 ... 1.20.1

Author SHA1 Message Date
066418d7b2
https://i.dbotthepony.ru/2024/07/18/attachment-133_1.gif 2024-07-18 20:16:50 +07:00
c83476225d
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-06-01 20:16:05 +07:00
f8277e55c3
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-05-31 16:49:35 +07:00
49dd781a82
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-05-31 16:37:18 +07:00
65dbeeeb4f
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-05-31 11:22:02 +07:00
f6138671d2
How does CAR is for 1.20.2 on 1.20.1 branch 2024-05-31 11:19:15 +07:00
34b60be434
Post merge fixes for 1.20.1 2024-05-31 11:13:53 +07:00
6153c2e972
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-05-31 11:10:20 +07:00
376e548cec
Revert "what"
This reverts commit 87e64a102a.
2024-01-22 14:28:21 +07:00
653ecedafb
Proper backport "allow vanilla servers on otm modded clients" 2024-01-22 14:02:21 +07:00
87e64a102a
what 2024-01-22 11:45:56 +07:00
0b7e54b4ef
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-22 11:45:00 +07:00
f0dba4ccc3
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-22 11:39:06 +07:00
b35dfaeacd
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-14 00:29:02 +07:00
6a2eb3dec2
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-13 12:17:56 +07:00
ce94d22212
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-13 12:04:52 +07:00
21b84651a8
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-13 12:02:26 +07:00
80917f7d12
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-13 11:50:42 +07:00
12b10ee6fe
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-13 11:42:52 +07:00
a88549f17f
Post merge fixes for 1.20.1 2024-01-12 21:21:07 +07:00
5552be70d5
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-12 21:17:44 +07:00
cb386d39f5
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-09 18:25:48 +07:00
22c3c22081
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-09 17:54:17 +07:00
0da77bc453
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-09 13:53:32 +07:00
f2aade3a8e
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-09 13:42:01 +07:00
46820a311f
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-09 13:41:17 +07:00
3743a3402d
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-08 21:51:08 +07:00
055b9cc489
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-08 21:41:51 +07:00
640f62d63b
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-08 14:16:23 +07:00
d3423a6160
Post merge fixes for 1.20.1 2024-01-08 14:13:43 +07:00
55c0be74d3
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-08 14:13:04 +07:00
9d9b19da9d
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-07 12:07:19 +07:00
652acf3ce1
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-07 11:49:20 +07:00
101e57756a
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-06 16:45:21 +07:00
67dbcde6dc
Post merge fixes for 1.20.1 2024-01-06 11:41:44 +07:00
b4c994f02f
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-06 11:37:34 +07:00
8007c1757e
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-05 23:52:11 +07:00
8aafa38c27
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-05 23:07:36 +07:00
e51ba7015a
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-05 22:59:33 +07:00
1d0e24095a
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-05 22:20:09 +07:00
a7d405b5ea
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-05 22:13:36 +07:00
8ee5e94a78
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-05 21:42:09 +07:00
f9dcf43cc4
Fix compilation error 2024-01-04 20:12:29 +07:00
42fe77e6b4
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-04 20:10:11 +07:00
b28e180704
Downgrade worldedit 2024-01-02 20:33:42 +07:00
2deaef94aa
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-02 20:33:11 +07:00
78ac178526
Merge branch '1.20.2' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into 1.20.1 2024-01-02 18:08:11 +07:00
92f2680feb
Use appropriate texture for status effect background 2024-01-02 15:16:28 +07:00
077e82064b
Merge branch '1.20.2' into 1.20.1 2024-01-02 15:05:25 +07:00
c821fa76a6
Merge branch '1.20.2' into 1.20.1 2024-01-02 14:19:25 +07:00
6e4bf4e7ec
Merge branch '1.20.2' into 1.20.1 2024-01-02 12:26:47 +07:00
5b45cf7d0a
Merge branch '1.20.2' into 1.20.1 2024-01-02 12:22:08 +07:00
edea36a8a6
Merge branch '1.20.2' into 1.20.1 2024-01-02 12:00:12 +07:00
34ef50f6ee
Merge branch '1.20.2' into 1.20.1 2024-01-01 17:31:29 +07:00
4c5c2362ce
Merge branch '1.20.2' into 1.20.1 2024-01-01 17:29:28 +07:00
54fa8a252e
Merge branch '1.20.2' into 1.20.1 2024-01-01 16:51:04 +07:00
a9cb2db3b4
Merge branch '1.20.2' into 1.20.1 2024-01-01 16:38:01 +07:00
748a232569
Merge branch 'master' into 1.20.1 2024-01-01 15:45:06 +07:00
86c426a504
Merge branch 'master' into 1.20.1 2024-01-01 11:45:14 +07:00
108b49bedb
Merge branch 'master' into 1.20.1 2024-01-01 02:55:55 +07:00
71850b38e5
Merge branch 'master' into 1.20.1 2024-01-01 00:58:18 +07:00
796f29127f
Merge branch 'master' into 1.20.1 2024-01-01 00:13:22 +07:00
8c43a3ec6d
Merge branch 'master' into 1.20.1 2023-12-31 23:18:46 +07:00
477e782c7c
*french disappointment* 2023-12-31 22:44:28 +07:00
65cf8bf9df
Fixes to data loading 2023-12-31 22:43:02 +07:00
e5a982ae13
Caused by: java.lang.invoke.LambdaConversionException: Invalid receiver type int; not a subtype of implementation type class java.lang.Integer 2023-12-31 22:25:55 +07:00
f942093e4f
Don't embed condition json by default 2023-12-31 22:23:16 +07:00
5d15611f84
Update mods.toml 2023-12-31 22:20:48 +07:00
1803d687ab
Make mod compile against 1.20.1 2023-12-31 22:18:43 +07:00
347be35184
Make main source set compile 2023-12-31 22:08:15 +07:00
aa0a283e06
More backporting 2023-12-31 21:40:54 +07:00
98fcacc9a8
More backporting 2023-12-31 21:14:32 +07:00
422ae92303
More backporting 2023-12-31 21:02:52 +07:00
7683cacc29
More backporting 2023-12-31 20:42:20 +07:00
520112df77
Backport MCriterionTrigger to 1.20.1 2023-12-31 20:29:57 +07:00
5453c8c793
Merge branch 'master' into 1.20.1 2023-12-31 20:25:03 +07:00
3c5ea937a5
More backporting 2023-12-31 18:23:07 +07:00
f16483d7c0
Some recipe backporting 2023-12-31 17:46:56 +07:00
8072a7b135
Don't check for "chunk send" status because it is already sent during event fire 2023-12-31 17:08:45 +07:00
44c6d0c0cf
Merge branch 'master' into 1.20.1 2023-12-31 17:02:21 +07:00
27dce0bd31
Downgrade dependencies 2023-12-31 12:54:59 +07:00
78 changed files with 603 additions and 352 deletions

View File

@ -10,28 +10,28 @@ mod_version=1.4
use_commit_hash_in_version=true use_commit_hash_in_version=true
mc_version=1.20.2 mc_version=1.20.1
jei_mc_version=1.20.2 jei_mc_version=1.20.1
curios_mc_version=1.20.2 curios_mc_version=1.20.1
forge_gradle_version=[6.0.14,6.2) forge_gradle_version=[6.0.14,6.2)
forge_version=48.1.0 forge_version=47.2.19
mixingradle_version=0.7.33 mixingradle_version=0.7.33
mixin_version=0.8.5 mixin_version=0.8.5
kommons_version=3.0.2 kommons_version=3.0.2
jei_version=16.0.0.28 jei_version=15.2.0.27
jupiter_version=5.9.2 jupiter_version=5.9.2
curios_version=6.0.2 curios_version=5.4.7
cosmetic_armor_reworked_id=4764779 cosmetic_armor_reworked_id=4600191
ad_astra_id=4594155 ad_astra_id=4594155
botarium_id=4594094 botarium_id=4594094
resourceful_lib_id=4598948 resourceful_lib_id=4598948
resourceful_config_id=4576455 resourceful_config_id=4576455
jade_id=4818518 jade_id=4986594
configured_id=4462894 configured_id=4462894
worldedit_id=4807512 worldedit_id=4586218
kotlin_for_forge_version=4.7.0 kotlin_for_forge_version=4.7.0
kotlin_version=1.9.0 kotlin_version=1.9.0

View File

@ -1,9 +1,8 @@
package ru.dbotthepony.mc.otm.datagen.advancements package ru.dbotthepony.mc.otm.datagen.advancements
import net.minecraft.advancements.AdvancementHolder
import net.minecraft.advancements.AdvancementRewards import net.minecraft.advancements.AdvancementRewards
import net.minecraft.advancements.FrameType 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.advancements.critereon.InventoryChangeTrigger
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.ItemStack 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 ru.dbotthepony.mc.otm.triggers.NailedEntityTrigger
import java.util.function.Consumer import java.util.function.Consumer
typealias Strategy = RequirementsStrategy
fun addAdvancements(serializer: Consumer<AdvancementHolder>, lang: MatteryLanguageProvider) { fun addAdvancements(serializer: Consumer<AdvancementHolder>, lang: MatteryLanguageProvider) {
val translation = lang.MultiBuilder("otm.advancements.regular") val translation = lang.MultiBuilder("otm.advancements.regular")

View File

@ -1,7 +1,5 @@
package ru.dbotthepony.mc.otm.datagen.advancements 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.AdvancementRewards
import net.minecraft.advancements.FrameType import net.minecraft.advancements.FrameType
import net.minecraft.advancements.critereon.EntityPredicate import net.minecraft.advancements.critereon.EntityPredicate

View File

@ -1,12 +1,9 @@
package ru.dbotthepony.mc.otm.datagen.advancements 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.FrameType
import net.minecraft.advancements.critereon.ItemPredicate import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items 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.lang.MatteryLanguageProvider
import ru.dbotthepony.mc.otm.datagen.modLocation import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems

View File

@ -16,6 +16,7 @@ import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.ItemLike import net.minecraft.world.level.ItemLike
import ru.dbotthepony.mc.otm.core.TextComponent import ru.dbotthepony.mc.otm.core.TextComponent
import java.util.function.Consumer
fun AdvancementBuilder(): Advancement.Builder = Advancement.Builder.advancement() fun AdvancementBuilder(): Advancement.Builder = Advancement.Builder.advancement()
@ -58,7 +59,7 @@ fun predicate(tag: TagKey<Item>): ItemPredicate {
return ItemPredicate.Builder.item().of(tag).build() 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)) return InventoryChangeTrigger.TriggerInstance.hasItems(predicate(tag))
} }
@ -66,8 +67,10 @@ fun predicate(item: ItemLike): ItemPredicate {
return ItemPredicate.Builder.item().of(item).build() return ItemPredicate.Builder.item().of(item).build()
} }
fun criterion(item: ItemLike): Criterion<*> { fun criterion(item: ItemLike): CriterionTriggerInstance {
return InventoryChangeTrigger.TriggerInstance.hasItems(predicate(item)) return InventoryChangeTrigger.TriggerInstance.hasItems(predicate(item))
} }
fun EntityPredicate.wrap(): ContextAwarePredicate = EntityPredicate.wrap(this) fun EntityPredicate.wrap(): ContextAwarePredicate = EntityPredicate.wrap(this)
fun Advancement.Builder.save(advancement: Consumer<Advancement>, name: ResourceLocation) = save(advancement, name.toString())

View File

@ -1,8 +1,8 @@
package ru.dbotthepony.mc.otm.datagen.advancements package ru.dbotthepony.mc.otm.datagen.advancements
import net.minecraft.advancements.AdvancementHolder import net.minecraft.advancements.Advancement
import net.minecraft.advancements.AdvancementRequirements
import net.minecraft.advancements.FrameType import net.minecraft.advancements.FrameType
import net.minecraft.advancements.RequirementsStrategy
import net.minecraft.advancements.critereon.ItemPredicate import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.world.item.Item import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack 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 ru.dbotthepony.mc.otm.triggers.TakeItemOutOfReplicatorTrigger
import java.util.function.Consumer import java.util.function.Consumer
typealias AdvancementHolder = Advancement
data class CraftEntry( data class CraftEntry(
val item: Collection<Item>, val item: Collection<Item>,
val englishName: String, val englishName: String,
@ -59,7 +61,7 @@ data class CraftEntry(
it.addCriterion(i.toString(), criterion(item)) it.addCriterion(i.toString(), criterion(item))
} }
} }
.requirements(AdvancementRequirements.Strategy.OR) .requirements(RequirementsStrategy.OR)
.save(serializer, modLocation("machines/$path")) .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()) for ((i, v) in MItems.CHEMICAL_GENERATOR.values.withIndex())
it.addCriterion("has_machine_$i", criterion(v)) it.addCriterion("has_machine_$i", criterion(v))
} }
.requirements(AdvancementRequirements.Strategy.OR) .requirements(RequirementsStrategy.OR)
.save(serializer, modLocation("machines/chemical_generator")) .save(serializer, modLocation("machines/chemical_generator"))
val press = AdvancementBuilder() val press = AdvancementBuilder()
@ -100,7 +102,7 @@ fun addMachineAdvancements(serializer: Consumer<AdvancementHolder>, lang: Matter
for ((i, m) in MItems.TWIN_PLATE_PRESS.values.withIndex()) for ((i, m) in MItems.TWIN_PLATE_PRESS.values.withIndex())
it.addCriterion(i.toString(), criterion(m)) it.addCriterion(i.toString(), criterion(m))
} }
.requirements(AdvancementRequirements.Strategy.OR) .requirements(RequirementsStrategy.OR)
.save(serializer, modLocation("machines/plate_press")) .save(serializer, modLocation("machines/plate_press"))
CraftEntry(MItems.ENERGY_SERVO.values, "Power Goes In, Powered Things Go Out", CraftEntry(MItems.ENERGY_SERVO.values, "Power Goes In, Powered Things Go Out",

View File

@ -1,7 +1,6 @@
package ru.dbotthepony.mc.otm.datagen.recipes package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.data.recipes.RecipeCategory import net.minecraft.data.recipes.RecipeCategory
import net.minecraft.data.recipes.RecipeOutput
import net.minecraft.tags.ItemTags import net.minecraft.tags.ItemTags
import net.minecraftforge.common.Tags import net.minecraftforge.common.Tags
import ru.dbotthepony.mc.otm.registry.MItemTags import ru.dbotthepony.mc.otm.registry.MItemTags

View File

@ -1,14 +1,12 @@
package ru.dbotthepony.mc.otm.datagen.recipes package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.data.recipes.RecipeCategory import net.minecraft.data.recipes.RecipeCategory
import net.minecraft.data.recipes.RecipeOutput
import net.minecraft.data.recipes.SimpleCookingRecipeBuilder import net.minecraft.data.recipes.SimpleCookingRecipeBuilder
import net.minecraft.util.valueproviders.ConstantFloat import net.minecraft.util.valueproviders.ConstantFloat
import net.minecraft.world.item.Item import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.level.ItemLike 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.datagen.modLocation
import ru.dbotthepony.mc.otm.registry.MItemTags import ru.dbotthepony.mc.otm.registry.MItemTags
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems

View File

@ -1,8 +1,6 @@
package ru.dbotthepony.mc.otm.datagen.recipes package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.data.recipes.FinishedRecipe
import net.minecraft.data.recipes.RecipeCategory import net.minecraft.data.recipes.RecipeCategory
import net.minecraft.data.recipes.RecipeOutput
import net.minecraft.data.recipes.ShapelessRecipeBuilder import net.minecraft.data.recipes.ShapelessRecipeBuilder
import net.minecraft.tags.ItemTags import net.minecraft.tags.ItemTags
import net.minecraft.world.item.ItemStack 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.core.registryName
import ru.dbotthepony.mc.otm.datagen.modLocation import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.recipe.UpgradeRecipe import ru.dbotthepony.mc.otm.recipe.UpgradeRecipe
import java.util.function.Consumer
fun addCraftingTableRecipes(consumer: RecipeOutput) { fun addCraftingTableRecipes(consumer: RecipeOutput) {
val machinesCategory = RecipeCategory.DECORATIONS val machinesCategory = RecipeCategory.DECORATIONS

View File

@ -1,6 +1,5 @@
package ru.dbotthepony.mc.otm.datagen.recipes package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.data.recipes.RecipeOutput
import net.minecraft.world.item.Items import net.minecraft.world.item.Items
import net.minecraftforge.common.Tags import net.minecraftforge.common.Tags
import ru.dbotthepony.mc.otm.registry.MItemTags import ru.dbotthepony.mc.otm.registry.MItemTags

View File

@ -1,6 +1,5 @@
package ru.dbotthepony.mc.otm.datagen.recipes package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.data.recipes.RecipeOutput
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.item.crafting.Ingredient
import net.minecraftforge.common.Tags import net.minecraftforge.common.Tags
@ -14,6 +13,7 @@ import ru.dbotthepony.mc.otm.registry.MItems
fun addMatterEntanglerRecipes(consumer: RecipeOutput) { fun addMatterEntanglerRecipes(consumer: RecipeOutput) {
consumer.accept( consumer.accept(
MatterEntanglerRecipe( MatterEntanglerRecipe(
modLocation("quantum_capacitor"),
IngredientMatrix.of( IngredientMatrix.of(
listOf(Ingredient.of(MItems.ELECTRIC_PARTS), Ingredient.of(MItemTags.GOLD_WIRES), Ingredient.of(MItems.ELECTRIC_PARTS)), 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)), 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, 400.0,
ItemStack(MItems.QUANTUM_CAPACITOR, 2), ItemStack(MItems.QUANTUM_CAPACITOR, 2),
experience = 15f experience = 15f
).energetic().toFinished(modLocation("quantum_capacitor")) ).energetic().toFinished()
) )
consumer.accept( consumer.accept(
MatterEntanglerRecipe( MatterEntanglerRecipe(
modLocation("quantum_battery"),
IngredientMatrix.of( 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(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)), 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, 600.0,
ItemStack(MItems.QUANTUM_BATTERY, 2), ItemStack(MItems.QUANTUM_BATTERY, 2),
experience = 20f experience = 20f
).energetic().toFinished(modLocation("quantum_battery")) ).energetic().toFinished()
) )
} }

View File

@ -7,7 +7,6 @@ import net.minecraft.advancements.Criterion
import net.minecraft.advancements.CriterionTriggerInstance import net.minecraft.advancements.CriterionTriggerInstance
import net.minecraft.data.recipes.FinishedRecipe import net.minecraft.data.recipes.FinishedRecipe
import net.minecraft.data.recipes.RecipeCategory import net.minecraft.data.recipes.RecipeCategory
import net.minecraft.data.recipes.RecipeOutput
import net.minecraft.data.recipes.ShapedRecipeBuilder import net.minecraft.data.recipes.ShapedRecipeBuilder
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.tags.TagKey import net.minecraft.tags.TagKey
@ -62,10 +61,6 @@ private fun RecipeOutput.map(mapper: (FinishedRecipe) -> FinishedRecipe): Recipe
override fun accept(recipe: FinishedRecipe) { override fun accept(recipe: FinishedRecipe) {
this@map.accept(mapper(recipe)) 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 val rows = arrayOfNulls<RecipeRow>(3)
private var index = 0 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)) 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) unlockedBy.add(name to trigger)
return this return this
} }
@ -195,7 +190,7 @@ class MatteryRecipe(val result: ItemLike, val count: Int = 1, val category: Reci
pJson["source"] = upgradeSource!!.toString() pJson["source"] = upgradeSource!!.toString()
} }
override fun type(): RecipeSerializer<*> { override fun getType(): RecipeSerializer<*> {
return UpgradeRecipe.CODEC 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) { fun buildEnergetic(consumer: RecipeOutput, name: String? = null) {
build(consumer.map { build(consumer.map {
object : FinishedRecipe by it { object : FinishedRecipe by it {
override fun type(): RecipeSerializer<*> { override fun getType(): RecipeSerializer<*> {
return EnergyContainerRecipe.Companion return EnergyContainerRecipe.Companion
} }
} }

View File

@ -1,17 +1,13 @@
package ru.dbotthepony.mc.otm.datagen.recipes 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.Criterion
import net.minecraft.advancements.CriterionTriggerInstance
import net.minecraft.advancements.critereon.ContextAwarePredicate import net.minecraft.advancements.critereon.ContextAwarePredicate
import net.minecraft.advancements.critereon.EntityPredicate
import net.minecraft.advancements.critereon.InventoryChangeTrigger import net.minecraft.advancements.critereon.InventoryChangeTrigger
import net.minecraft.advancements.critereon.ItemPredicate import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.advancements.critereon.MinMaxBounds import net.minecraft.advancements.critereon.MinMaxBounds
import net.minecraft.data.DataGenerator import net.minecraft.data.DataGenerator
import net.minecraft.data.recipes.FinishedRecipe
import net.minecraft.data.recipes.RecipeBuilder import net.minecraft.data.recipes.RecipeBuilder
import net.minecraft.data.recipes.RecipeOutput
import net.minecraft.data.recipes.RecipeProvider import net.minecraft.data.recipes.RecipeProvider
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.tags.ItemTags 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.MicrowaveRecipe
import ru.dbotthepony.mc.otm.recipe.PlatePressRecipe import ru.dbotthepony.mc.otm.recipe.PlatePressRecipe
import java.util.* import java.util.*
import java.util.function.Consumer
import java.util.stream.Stream import java.util.stream.Stream
private typealias RecipeBuilderCallback = (MatteryRecipeProvider, consumer: RecipeOutput) -> Unit 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()) 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()) 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()) return inventoryTrigger(ItemPredicate.Builder.item().of(p_125976_).build())
} }
fun inventoryTrigger(vararg p_126012_: ItemPredicate): Criterion<InventoryChangeTrigger.TriggerInstance> { fun inventoryTrigger(vararg p_126012_: ItemPredicate): CriterionTriggerInstance {
return CriteriaTriggers.INVENTORY_CHANGED.createCriterion(InventoryChangeTrigger.TriggerInstance( return InventoryChangeTrigger.TriggerInstance(
Optional.empty(), ContextAwarePredicate.ANY,
MinMaxBounds.Ints.ANY, MinMaxBounds.Ints.ANY,
MinMaxBounds.Ints.ANY, MinMaxBounds.Ints.ANY,
MinMaxBounds.Ints.ANY, MinMaxBounds.Ints.ANY,
ImmutableList.copyOf(p_126012_) p_126012_
)) )
} }
fun multiIngredient(vararg items: Any) : Ingredient { 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) { fun plate(id: String, count: Int = 1, workTicks: Int = 200, experience: FloatProvider = ConstantFloat.ZERO) {
exec { _, consumer -> exec { _, consumer ->
consumer.accept(PlatePressRecipe( consumer.accept(PlatePressRecipe(
modLocation("plates/$id"),
Ingredient.of(ItemTags.create(ResourceLocation("forge", "ingots/$id"))), Ingredient.of(ItemTags.create(ResourceLocation("forge", "ingots/$id"))),
Ingredient.of(ItemTags.create(ResourceLocation("forge", "plates/$id"))), Ingredient.of(ItemTags.create(ResourceLocation("forge", "plates/$id"))),
count, count,
workTicks, workTicks,
experience = experience 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) { fun plate(id: String, ingredient: Ingredient, result: Ingredient, count: Int = 1, workTicks: Int = 200, experience: FloatProvider = ConstantFloat.ZERO) {
exec { it, callback -> 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) { fun microwave(id: String, ingredient: Ingredient, result: Ingredient, count: Int = 1, workTicks: Int = 200, experience: FloatProvider = ConstantFloat.ZERO) {
exec { it, callback -> 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())
} }
} }
} }

View File

@ -1,20 +1,16 @@
package ru.dbotthepony.mc.otm.datagen.recipes 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.DyeColor
import net.minecraft.world.item.Item import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items import net.minecraft.world.item.Items
import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.item.crafting.Ingredient
import ru.dbotthepony.mc.otm.core.registryName 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.datagen.modLocation
import ru.dbotthepony.mc.otm.recipe.PainterArmorDyeRecipe import ru.dbotthepony.mc.otm.recipe.PainterArmorDyeRecipe
import ru.dbotthepony.mc.otm.recipe.PainterRecipe import ru.dbotthepony.mc.otm.recipe.PainterRecipe
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MRegistry import ru.dbotthepony.mc.otm.registry.MRegistry
import java.util.function.Consumer
private val Item.recipeName get() = registryName!!.namespace + "/" + registryName!!.path 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 if (targetColor == null) continue
consumer.accept(PainterRecipe( consumer.accept(PainterRecipe(
modLocation("painter/" + targetItem.recipeName),
Ingredient.of(items.entries.stream().filter { it.key != null && it.key != targetColor }.map { ItemStack(it.value) }), Ingredient.of(items.entries.stream().filter { it.key != null && it.key != targetColor }.map { ItemStack(it.value) }),
ItemStack(targetItem), ItemStack(targetItem),
mapOf(targetColor to amount) 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 if (k1 == null) continue
consumer.accept(PainterRecipe( consumer.accept(PainterRecipe(
modLocation("painter/" + default.recipeName + "/" + v1.recipeName),
Ingredient.of(default), Ingredient.of(default),
ItemStack(v1), ItemStack(v1),
mapOf(k1 to amount) mapOf(k1 to amount)
).toFinished(modLocation("painter/" + default.recipeName + "/" + v1.recipeName))) ).toFinished())
} }
} }
private fun cleaning(consumer: RecipeOutput, to: Item, from: Map<out DyeColor?, Item>) { private fun cleaning(consumer: RecipeOutput, to: Item, from: Map<out DyeColor?, Item>) {
consumer.accept(PainterRecipe( consumer.accept(PainterRecipe(
modLocation("painter/cleaning/" + to.recipeName),
Ingredient.of(from.entries.stream().filter { it.key != null }.map { ItemStack(it.value) }), Ingredient.of(from.entries.stream().filter { it.key != null }.map { ItemStack(it.value) }),
ItemStack(to), ItemStack(to),
mapOf(null to 15) 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>) { 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 val (baseColor, stripe) = colors
consumer.accept(PainterRecipe( consumer.accept(PainterRecipe(
modLocation("painter/stripes_$name/${baseColor.getName()}/${stripe.getName()}"),
Ingredient.of(base[baseColor]), Ingredient.of(base[baseColor]),
ItemStack(stripeItem), ItemStack(stripeItem),
setOf(stripe) 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) striped(consumer, "slabs", MRegistry.TRITANIUM_STRIPED_SLAB.itemsWithColor, MRegistry.TRITANIUM_SLAB.items)
for (color in DyeColor.entries) { 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( consumer.accept(PainterRecipe(
modLocation("painter/tritanium_yellow_stripe"),
Ingredient.of(MRegistry.TRITANIUM_BLOCK.item), Ingredient.of(MRegistry.TRITANIUM_BLOCK.item),
ItemStack(MItems.TRITANIUM_STRIPED_BLOCK), ItemStack(MItems.TRITANIUM_STRIPED_BLOCK),
mapOf(DyeColor.YELLOW to 1) mapOf(DyeColor.YELLOW to 1)
).toFinished(modLocation("painter/tritanium_yellow_stripe"))) ).toFinished())
consumer.accept(PainterRecipe( consumer.accept(PainterRecipe(
modLocation("painter/tritanium_yellow_stripe_stairs"),
Ingredient.of(MRegistry.TRITANIUM_STAIRS.item), Ingredient.of(MRegistry.TRITANIUM_STAIRS.item),
ItemStack(MItems.TRITANIUM_STRIPED_STAIRS), ItemStack(MItems.TRITANIUM_STRIPED_STAIRS),
mapOf(DyeColor.YELLOW to 1) mapOf(DyeColor.YELLOW to 1)
).toFinished(modLocation("painter/tritanium_yellow_stripe_stairs"))) ).toFinished())
consumer.accept(PainterRecipe( consumer.accept(PainterRecipe(
modLocation("painter/tritanium_yellow_stripe_slab"),
Ingredient.of(MRegistry.TRITANIUM_SLAB.item), Ingredient.of(MRegistry.TRITANIUM_SLAB.item),
ItemStack(MItems.TRITANIUM_STRIPED_SLAB), ItemStack(MItems.TRITANIUM_STRIPED_SLAB),
mapOf(DyeColor.YELLOW to 1) mapOf(DyeColor.YELLOW to 1)
).toFinished(modLocation("painter/tritanium_yellow_stripe_slab"))) ).toFinished())
consumer.accept(PainterRecipe( consumer.accept(PainterRecipe(
modLocation("painter/tritanium_yellow_stripe_wall"),
Ingredient.of(MRegistry.TRITANIUM_WALL.item), Ingredient.of(MRegistry.TRITANIUM_WALL.item),
ItemStack(MItems.TRITANIUM_STRIPED_WALL), ItemStack(MItems.TRITANIUM_STRIPED_WALL),
mapOf(DyeColor.YELLOW to 1) mapOf(DyeColor.YELLOW to 1)
).toFinished(modLocation("painter/tritanium_yellow_stripe_wall"))) ).toFinished())
} }

View File

@ -1,7 +1,7 @@
package ru.dbotthepony.mc.otm.datagen.recipes package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.data.recipes.FinishedRecipe
import net.minecraft.data.recipes.RecipeCategory import net.minecraft.data.recipes.RecipeCategory
import net.minecraft.data.recipes.RecipeOutput
import net.minecraft.data.recipes.ShapelessRecipeBuilder import net.minecraft.data.recipes.ShapelessRecipeBuilder
import net.minecraft.tags.TagKey import net.minecraft.tags.TagKey
import net.minecraft.world.item.DyeColor 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.MItemTags
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MRegistry import ru.dbotthepony.mc.otm.registry.MRegistry
import java.util.function.Consumer
typealias RecipeOutput = Consumer<FinishedRecipe>
fun hammerRecipe(output: ItemLike, input: ItemLike, consumer: RecipeOutput) { fun hammerRecipe(output: ItemLike, input: ItemLike, consumer: RecipeOutput) {
ShapelessRecipeBuilder(RecipeCategory.MISC, output, 1) ShapelessRecipeBuilder(RecipeCategory.MISC, output, 1)

View File

@ -1,7 +1,6 @@
package ru.dbotthepony.mc.otm.datagen.recipes package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.data.recipes.RecipeCategory import net.minecraft.data.recipes.RecipeCategory
import net.minecraft.data.recipes.RecipeOutput
import net.minecraftforge.common.Tags import net.minecraftforge.common.Tags
import ru.dbotthepony.mc.otm.recipe.UpgradeRecipe import ru.dbotthepony.mc.otm.recipe.UpgradeRecipe
import ru.dbotthepony.mc.otm.registry.MItemTags import ru.dbotthepony.mc.otm.registry.MItemTags

View File

@ -1,7 +1,6 @@
package ru.dbotthepony.mc.otm.datagen.recipes package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.data.recipes.RecipeCategory import net.minecraft.data.recipes.RecipeCategory
import net.minecraft.data.recipes.RecipeOutput
import net.minecraftforge.common.Tags import net.minecraftforge.common.Tags
import ru.dbotthepony.mc.otm.registry.MItemTags import ru.dbotthepony.mc.otm.registry.MItemTags
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems

View File

@ -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.TranslatableComponent
import ru.dbotthepony.mc.otm.core.isActuallyEmpty import ru.dbotthepony.mc.otm.core.isActuallyEmpty
import ru.dbotthepony.mc.otm.data.ComponentCodec 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.data.JsonElementCodec
import ru.dbotthepony.mc.otm.isClient import ru.dbotthepony.mc.otm.isClient
import java.util.Optional import java.util.Optional
@ -392,7 +393,7 @@ class AndroidResearchType(
ListCodec( ListCodec(
RecordCodecBuilder.create<Pair<Ingredient, Int>> { RecordCodecBuilder.create<Pair<Ingredient, Int>> {
it.group( 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 } Codec.intRange(1, Int.MAX_VALUE).optionalFieldOf("count", 1).forGetter { it.second }
).apply(it, ::Pair) ).apply(it, ::Pair)
} }

View File

@ -594,14 +594,11 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
private fun recheckPlayer(player: ServerPlayer) { private fun recheckPlayer(player: ServerPlayer) {
sometimeServer { sometimeServer {
if (player in players && !player.hasDisconnected()) { if (player in players && !player.hasDisconnected()) {
if (player.connection.chunkSender.isPending(chunkPos)) { veto.remove(player)
recheckPlayer(player)
} else {
veto.remove(player)
blockEntities.forEach { blockEntities.forEach {
it.synchers[player] = it.syncher.Remote() it.synchers[player] =
} it.syncher.Remote()
} }
} else if (player in players && player.hasDisconnected()) { } else if (player in players && player.hasDisconnected()) {
unsubscribe(player) unsubscribe(player)

View File

@ -668,11 +668,11 @@ class ExplosionQueue(private val level: ServerLevel) : SavedData() {
@JvmStatic @JvmStatic
fun queueForLevel(level: ServerLevel): ExplosionQueue { fun queueForLevel(level: ServerLevel): ExplosionQueue {
return level.dataStorage.computeIfAbsent( return level.dataStorage.computeIfAbsent(
Factory({ ExplosionQueue(level) }, { {
val factory = ExplosionQueue(level) val factory = ExplosionQueue(level)
factory.load(it) factory.load(it)
factory factory
}, DataFixTypes.LEVEL), }, { ExplosionQueue(level) },
"otm_blackhole_explosion_queue" "otm_blackhole_explosion_queue"
) )
} }

View File

@ -29,6 +29,7 @@ import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.ShadowCraftingContainer import ru.dbotthepony.mc.otm.container.ShadowCraftingContainer
import ru.dbotthepony.mc.otm.container.UpgradeContainer import ru.dbotthepony.mc.otm.container.UpgradeContainer
import ru.dbotthepony.mc.otm.core.math.Decimal 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.DecimalCodec
import ru.dbotthepony.mc.otm.data.minRange import ru.dbotthepony.mc.otm.data.minRange
import ru.dbotthepony.mc.otm.graph.matter.MatterNode import ru.dbotthepony.mc.otm.graph.matter.MatterNode

View File

@ -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.collect.toList
import ru.dbotthepony.mc.otm.core.isNotEmpty import ru.dbotthepony.mc.otm.core.isNotEmpty
import ru.dbotthepony.mc.otm.core.util.ItemStorageStackSorter import ru.dbotthepony.mc.otm.core.util.ItemStorageStackSorter
import ru.dbotthepony.mc.otm.core.value
interface IItemMonitorPlayerSettings { interface IItemMonitorPlayerSettings {
var ingredientPriority: ItemMonitorPlayerSettings.IngredientPriority var ingredientPriority: ItemMonitorPlayerSettings.IngredientPriority

View File

@ -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.collect.maybe
import ru.dbotthepony.mc.otm.core.getValue import ru.dbotthepony.mc.otm.core.getValue
import ru.dbotthepony.mc.otm.core.immutableList 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.core.util.item
import ru.dbotthepony.mc.otm.menu.tech.PoweredFurnaceMenu import ru.dbotthepony.mc.otm.menu.tech.PoweredFurnaceMenu
import ru.dbotthepony.mc.otm.recipe.MatteryCookingRecipe import ru.dbotthepony.mc.otm.recipe.MatteryCookingRecipe

View File

@ -22,6 +22,7 @@ import ru.dbotthepony.mc.otm.container.UpgradeContainer
import ru.dbotthepony.mc.otm.container.balance import ru.dbotthepony.mc.otm.container.balance
import ru.dbotthepony.mc.otm.core.collect.filter import ru.dbotthepony.mc.otm.core.collect.filter
import ru.dbotthepony.mc.otm.core.collect.maybe 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.menu.tech.PlatePressMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MRecipes import ru.dbotthepony.mc.otm.registry.MRecipes

View File

@ -556,7 +556,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
super.onJobTick(status) super.onJobTick(status)
if (isExopackVisible && ply.level().random.nextFloat() <= 0.05f) { 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))
} }
} }

View File

@ -224,7 +224,7 @@ fun onMouseScrolled(event: MouseScrolled.Pre) {
for (widget in screen.renderables) { for (widget in screen.renderables) {
if (widget is Panel2Widget<*, *>) { 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 event.isCanceled = true
return return
} }
@ -233,7 +233,7 @@ fun onMouseScrolled(event: MouseScrolled.Pre) {
val slot = screen.slotUnderMouse val slot = screen.slotUnderMouse
if (slot != null && (slot.container == minecraft.player?.inventory && slot.containerSlot in 9 .. 35 || slot.container == minecraft.player?.matteryPlayer?.exopackContainer)) { 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 event.isCanceled = true
return return
} }

View File

@ -569,7 +569,7 @@ abstract class MatteryScreen<T : MatteryMenu>(menu: T, inventory: Inventory, tit
return super.mouseReleased(p_97812_, p_97813_, p_97814_) 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) { for (panel in panels) {
if (panel.mouseScrolledChecked(mouseX, mouseY, scrollY)) { if (panel.mouseScrolledChecked(mouseX, mouseY, scrollY)) {
return true return true
@ -653,7 +653,7 @@ abstract class MatteryScreen<T : MatteryMenu>(menu: T, inventory: Inventory, tit
val mouseYf = mouseY.toFloat() val mouseYf = mouseY.toFloat()
// dark background // dark background
this.renderBackground(graphics, mouseX, mouseY, partialTick) this.renderBackground(graphics)
super.hoveredSlot = null super.hoveredSlot = null
var hovered = false var hovered = false

View File

@ -30,6 +30,7 @@ import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.map import ru.dbotthepony.mc.otm.core.map
import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.core.util.CreativeMenuItemComparator import ru.dbotthepony.mc.otm.core.util.CreativeMenuItemComparator
import ru.dbotthepony.mc.otm.core.value
import ru.dbotthepony.mc.otm.menu.decorative.PainterMenu import ru.dbotthepony.mc.otm.menu.decorative.PainterMenu
class PainterScreen(menu: PainterMenu, inventory: Inventory, title: Component) : MatteryScreen<PainterMenu>(menu, inventory, title) { class PainterScreen(menu: PainterMenu, inventory: Inventory, title: Component) : MatteryScreen<PainterMenu>(menu, inventory, title) {

View File

@ -100,7 +100,7 @@ open class EditablePanel<out S : Screen>(
return this@EditablePanel.mouseDragged(p_94740_, p_94741_, p_94742_, p_94743_, p_94744_) 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) return this@EditablePanel.mouseScrolled(mouseX, mouseY, scrollY)
} }

View File

@ -4,7 +4,7 @@ import com.mojang.blaze3d.systems.RenderSystem
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
import net.minecraft.client.gui.screens.Screen 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.MobEffect
import net.minecraft.world.effect.MobEffectInstance import net.minecraft.world.effect.MobEffectInstance
import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.LivingEntity
@ -264,7 +264,7 @@ open class EffectListPanel<out S : Screen> @JvmOverloads constructor(
} }
companion object { companion object {
val BAR = ResourceLocation("textures/gui/sprites/container/inventory/effect_background_large.png").sprite(0f, 0f, 120f, 32f, 120f, 32f) val BAR = AbstractContainerScreen.INVENTORY_LOCATION.sprite(0f, 166f, 120f, 32f)
val SQUARE_THIN = ResourceLocation("textures/gui/sprites/hud/effect_background.png").sprite(0f, 0f, 24f, 24f, 24f, 24f) val SQUARE_THIN = AbstractContainerScreen.INVENTORY_LOCATION.sprite(141f, 166f, 24f, 24f)
} }
} }

View File

@ -170,14 +170,16 @@ class EntityRendererPanel<out S : Screen> @JvmOverloads constructor(
return return
} }
val renderX = width.toInt() / 2
val renderY = (height * 0.9f).toInt()
InventoryScreen.renderEntityInInventoryFollowsMouse( InventoryScreen.renderEntityInInventoryFollowsMouse(
graphics.parent, graphics.parent,
0, 0, renderX,
this.width.toInt(), this.height.toInt(), renderY,
renderScale, renderScale,
0f, absoluteX.toInt() + renderX - mouseX,
mouseX - absoluteX.toInt(), absoluteY + height * 0.15f - mouseY,
mouseY - absoluteY + height * 0.15f,
entity entity
) )
} }

View File

@ -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_) 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) return panel.mouseScrolledChecked(mouseX, mouseY, scrollY)
} }

View File

@ -35,7 +35,7 @@ fun onCuriosSlotModifiersUpdated(event: SlotModifiersUpdatedEvent) {
} }
fun openCuriosScreen(carriedStack: ItemStack = ItemStack.EMPTY) { 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>> { private fun Player.getCuriosSlotsImpl(): List<PlayerSlot<Slot, Slot>> {

View File

@ -56,7 +56,7 @@ object MatterBottlerProvider : IBlockComponentProvider, IServerDataProvider<Bloc
data.getFloat("workProgress"), data.getFloat("workProgress"),
null, null,
elementHelper.progressStyle().color(RGBAColor.WHITE.toBGRA()), elementHelper.progressStyle().color(RGBAColor.WHITE.toBGRA()),
BoxStyle.getNestedBox(), BoxStyle.DEFAULT,
true true
) )
) )

View File

@ -57,7 +57,7 @@ object MatterReconstructorProvider : IBlockComponentProvider, IServerDataProvide
maxDamage maxDamage
), ),
elementHelper.progressStyle().color(RGBAColor.DARK_GREEN.toBGRA()).textColor(RGBAColor.WHITE.toBGRA()), elementHelper.progressStyle().color(RGBAColor.DARK_GREEN.toBGRA()).textColor(RGBAColor.WHITE.toBGRA()),
BoxStyle.getNestedBox(), BoxStyle.DEFAULT,
true true
) )
) )

View File

@ -69,7 +69,7 @@ object MatterStorageProvider : IBlockComponentProvider, IServerDataProvider<Bloc
maxStoredMatter.formatMatter() maxStoredMatter.formatMatter()
), ),
elementHelper.progressStyle().color(JadeColors.MATTER_COLOR.toBGRA()).textColor(RGBAColor.WHITE.toBGRA()), elementHelper.progressStyle().color(JadeColors.MATTER_COLOR.toBGRA()).textColor(RGBAColor.WHITE.toBGRA()),
BoxStyle.getNestedBox(), BoxStyle.DEFAULT,
true true
) )
) )

View File

@ -67,7 +67,7 @@ object MatteryEnergyProvider : IBlockComponentProvider, IServerDataProvider<Bloc
maxBatteryLevel.formatPower() maxBatteryLevel.formatPower()
), ),
elementHelper.progressStyle().color(JadeColors.ENERGY_COLOR.toBGRA(), JadeColors.ENERGY_COLOR2.toBGRA()).textColor(RGBAColor.WHITE.toBGRA()), elementHelper.progressStyle().color(JadeColors.ENERGY_COLOR.toBGRA(), JadeColors.ENERGY_COLOR2.toBGRA()).textColor(RGBAColor.WHITE.toBGRA()),
BoxStyle.getNestedBox(), BoxStyle.DEFAULT,
true true
) )
) )

View File

@ -75,7 +75,7 @@ object MatteryWorkerProvider : IBlockComponentProvider, IServerDataProvider<Bloc
progress, progress,
null, null,
if (isUnableToProcess) styleError else style, if (isUnableToProcess) styleError else style,
BoxStyle.getNestedBox(), BoxStyle.DEFAULT,
true true
) )
) )

View File

@ -14,15 +14,14 @@ import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.MenuType import net.minecraft.world.inventory.MenuType
import net.minecraft.world.inventory.Slot import net.minecraft.world.inventory.Slot
import net.minecraft.world.item.crafting.CraftingRecipe 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.TranslatableComponent
import ru.dbotthepony.mc.otm.core.toImmutableList import ru.dbotthepony.mc.otm.core.toImmutableList
import ru.dbotthepony.mc.otm.menu.ExopackInventoryMenu import ru.dbotthepony.mc.otm.menu.ExopackInventoryMenu
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
class ExopackInventoryTransferHandler(private val helper: IRecipeTransferHandlerHelper) : IRecipeTransferHandler<ExopackInventoryMenu, RecipeHolder<CraftingRecipe>> { class ExopackInventoryTransferHandler(private val helper: IRecipeTransferHandlerHelper) : IRecipeTransferHandler<ExopackInventoryMenu, CraftingRecipe> {
private val transfer = helper.createUnregisteredRecipeTransferHandler(object : IRecipeTransferInfo<ExopackInventoryMenu, RecipeHolder<CraftingRecipe>> { private val transfer = helper.createUnregisteredRecipeTransferHandler(object : IRecipeTransferInfo<ExopackInventoryMenu, CraftingRecipe> {
override fun getContainerClass(): Class<out ExopackInventoryMenu> { override fun getContainerClass(): Class<out ExopackInventoryMenu> {
return ExopackInventoryMenu::class.java return ExopackInventoryMenu::class.java
} }
@ -31,24 +30,24 @@ class ExopackInventoryTransferHandler(private val helper: IRecipeTransferHandler
return Optional.empty() 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 return RecipeTypes.CRAFTING
} }
override fun canHandle(container: ExopackInventoryMenu, recipe: RecipeHolder<CraftingRecipe>): Boolean { override fun canHandle(container: ExopackInventoryMenu, recipe: CraftingRecipe): Boolean {
return true return true
} }
override fun getRecipeSlots( override fun getRecipeSlots(
container: ExopackInventoryMenu, container: ExopackInventoryMenu,
recipe: RecipeHolder<CraftingRecipe> recipe: CraftingRecipe
): List<Slot> { ): List<Slot> {
return container.craftingSlots return container.craftingSlots
} }
override fun getInventorySlots( override fun getInventorySlots(
container: ExopackInventoryMenu, container: ExopackInventoryMenu,
recipe: RecipeHolder<CraftingRecipe> recipe: CraftingRecipe
): List<Slot> { ): List<Slot> {
return container.playerInventorySlots return container.playerInventorySlots
} }
@ -62,7 +61,7 @@ class ExopackInventoryTransferHandler(private val helper: IRecipeTransferHandler
return Optional.empty() 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 return RecipeTypes.CRAFTING
} }
@ -89,7 +88,7 @@ class ExopackInventoryTransferHandler(private val helper: IRecipeTransferHandler
override fun transferRecipe( override fun transferRecipe(
container: ExopackInventoryMenu, container: ExopackInventoryMenu,
recipe: RecipeHolder<CraftingRecipe>, recipe: CraftingRecipe,
recipeSlots: IRecipeSlotsView, recipeSlots: IRecipeSlotsView,
player: Player, player: Player,
maxTransfer: Boolean, maxTransfer: Boolean,

View File

@ -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.filterIsInstance
import ru.dbotthepony.mc.otm.core.collect.map import ru.dbotthepony.mc.otm.core.collect.map
import ru.dbotthepony.mc.otm.core.collect.toList 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.decorative.PainterMenu
import ru.dbotthepony.mc.otm.menu.matter.MatterEntanglerMenu import ru.dbotthepony.mc.otm.menu.matter.MatterEntanglerMenu
import ru.dbotthepony.mc.otm.menu.tech.PlatePressMenu import ru.dbotthepony.mc.otm.menu.tech.PlatePressMenu

View File

@ -20,11 +20,13 @@ import net.minecraft.network.FriendlyByteBuf
import net.minecraft.network.chat.ComponentContents import net.minecraft.network.chat.ComponentContents
import net.minecraft.network.chat.contents.TranslatableContents import net.minecraft.network.chat.contents.TranslatableContents
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.world.Container
import net.minecraft.world.entity.Entity import net.minecraft.world.entity.Entity
import net.minecraft.world.item.Item import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items import net.minecraft.world.item.Items
import net.minecraft.world.item.crafting.Ingredient 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.BlockGetter
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import net.minecraft.world.level.LevelAccessor 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.BlockState
import net.minecraft.world.level.block.state.StateHolder import net.minecraft.world.level.block.state.StateHolder
import net.minecraft.world.level.block.state.properties.Property 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.minecraft.world.phys.Vec3
import net.minecraftforge.common.ForgeHooks import net.minecraftforge.common.ForgeHooks
import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.common.util.LazyOptional
@ -67,6 +71,7 @@ import java.util.UUID
import java.util.concurrent.Callable import java.util.concurrent.Callable
import java.util.concurrent.Future import java.util.concurrent.Future
import java.util.function.Consumer import java.util.function.Consumer
import java.util.function.Function
import java.util.function.Supplier import java.util.function.Supplier
import java.util.stream.Stream import java.util.stream.Stream
import java.util.stream.StreamSupport 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) } return Supplier { b.invoke(first.value) }
} }
inline val <R : Recipe<T>, T : Container> R.value get() = this

View File

@ -117,7 +117,7 @@ fun CompoundTag.putJson(key: String, json: JsonElement) {
putByteArray(key, bytes.array.copyOfRange(0, bytes.length)) 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) val bytes = getByteArray(key)
if (bytes.isEmpty()) if (bytes.isEmpty())

View File

@ -8,9 +8,7 @@ import com.mojang.serialization.Codec
import com.mojang.serialization.DataResult import com.mojang.serialization.DataResult
import com.mojang.serialization.DynamicOps import com.mojang.serialization.DynamicOps
import com.mojang.serialization.JsonOps import com.mojang.serialization.JsonOps
import io.netty.buffer.ByteBuf
import io.netty.buffer.Unpooled import io.netty.buffer.Unpooled
import net.minecraft.advancements.AdvancementHolder
import net.minecraft.data.recipes.FinishedRecipe import net.minecraft.data.recipes.FinishedRecipe
import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation 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 ru.dbotthepony.mc.otm.core.util.writeBinaryJsonWithCodec
import kotlin.collections.ArrayDeque import kotlin.collections.ArrayDeque
import kotlin.concurrent.getOrSet 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<*>>( class Codec2RecipeSerializer<S : Recipe<*>>(
val empty: S?, val empty: S?,
codec: (Codec2RecipeSerializer<S>.Context) -> Codec<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) constructor(supplier: (Codec2RecipeSerializer<S>.Context) -> Codec<S>) : this(null, supplier)
private class CurrentContext { private class CurrentContext {
val idStack = ArrayDeque<ResourceLocation>()
var isNetwork = 0 var isNetwork = 0
} }
inner class Context { inner class Context {
val id: ResourceLocation
get() = checkNotNull(context.idStack.lastOrNull()) { "Not currently deserializing recipe" }
val ingredients: Codec<Ingredient> get() = ActualIngredientCodec val ingredients: Codec<Ingredient> get() = ActualIngredientCodec
fun <P : Recipe<*>> wrap(serializer: RecipeSerializer<P>): Codec<P> { val isNetwork: Boolean
return object : Codec<P> { get() = context.isNetwork > 0
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)
}
}
}
}
} }
private val codec = codec.invoke(Context()) private val codec = codec.invoke(Context())
@ -97,30 +60,45 @@ class Codec2RecipeSerializer<S : Recipe<*>>(
} }
} }
override fun codec(): Codec<S> { override fun fromJson(id: ResourceLocation, data: JsonObject): S {
return this 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 { try {
context.idStack.addLast(id)
context.isNetwork++ context.isNetwork++
return data.readBinaryJsonWithCodecIndirect(this) 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 { } finally {
context.isNetwork-- context.isNetwork--
context.idStack.removeLast()
} }
} }
override fun toNetwork(data: FriendlyByteBuf, recipe: S) { override fun toNetwork(data: FriendlyByteBuf, recipe: S) {
try { try {
context.idStack.addLast(recipe.id)
context.isNetwork++ context.isNetwork++
data.writeBinaryJsonWithCodec(this, recipe) data.writeBinaryJsonWithCodec(this, recipe)
} finally { } finally {
context.isNetwork-- context.isNetwork--
context.idStack.removeLast()
} }
} }
fun toFinished(recipe: S, id: ResourceLocation): FinishedRecipe { fun toFinished(recipe: S): FinishedRecipe {
return object : FinishedRecipe { return object : FinishedRecipe {
override fun serializeRecipeData(p_125967_: JsonObject) { override fun serializeRecipeData(p_125967_: JsonObject) {
encode(recipe, JsonOps.INSTANCE, p_125967_).get().map( encode(recipe, JsonOps.INSTANCE, p_125967_).get().map(
@ -137,15 +115,19 @@ class Codec2RecipeSerializer<S : Recipe<*>>(
) )
} }
override fun id(): ResourceLocation { override fun getId(): ResourceLocation {
return id return recipe.id
} }
override fun type(): RecipeSerializer<*> { override fun getType(): RecipeSerializer<*> {
return this@Codec2RecipeSerializer return this@Codec2RecipeSerializer
} }
override fun advancement(): AdvancementHolder? { override fun serializeAdvancement(): JsonObject? {
return null
}
override fun getAdvancementId(): ResourceLocation? {
return null return null
} }
} }
@ -156,7 +138,7 @@ class Codec2RecipeSerializer<S : Recipe<*>>(
return if (context.isNetwork > 0) { return if (context.isNetwork > 0) {
networkIngredientCodec.encode(input, ops, prefix) networkIngredientCodec.encode(input, ops, prefix)
} else { } 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) { return if (context.isNetwork > 0) {
networkIngredientCodec.decode(ops, input) networkIngredientCodec.decode(ops, input)
} else { } 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). * since RecipeSerializers are expected to be stateless. [Codec2RecipeSerializer], however, is stateful (threading PoV).
* To make it stateless, [ThreadLocal] is used. * To make it stateless, [ThreadLocal] is used.
*/ */
private val context by object : ThreadLocal<CurrentContext>() { private val contextHolder = ThreadLocal<CurrentContext>()
override fun initialValue(): CurrentContext { private val context: CurrentContext
return CurrentContext() get() = contextHolder.getOrSet { CurrentContext() }
}
}
} }
} }
private operator fun <T> ThreadLocal<T>.getValue(companion: Codec2RecipeSerializer.Companion, property: KProperty<*>): T {
return get()
}

View File

@ -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)
}
}
}

View File

@ -1,29 +1,48 @@
package ru.dbotthepony.mc.otm.data package ru.dbotthepony.mc.otm.data
import com.mojang.serialization.Codec import com.mojang.serialization.Codec
import com.mojang.serialization.DataResult
import com.mojang.serialization.Dynamic import com.mojang.serialization.Dynamic
import com.mojang.serialization.DynamicOps
import com.mojang.serialization.JsonOps import com.mojang.serialization.JsonOps
import com.mojang.serialization.codecs.RecordCodecBuilder import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.advancements.critereon.DamagePredicate import net.minecraft.advancements.critereon.DamagePredicate
import net.minecraft.advancements.critereon.DamageSourcePredicate import net.minecraft.advancements.critereon.DamageSourcePredicate
import net.minecraft.advancements.critereon.EntityPredicate import net.minecraft.advancements.critereon.EntityPredicate
import net.minecraft.advancements.critereon.MinMaxBounds import net.minecraft.advancements.critereon.MinMaxBounds
import java.util.Optional
import kotlin.reflect.KProperty1 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 { private val dealtReceived: Codec<Pair<MinMaxBounds.Doubles, MinMaxBounds.Doubles>> = RecordCodecBuilder.create {
it.group( it.group(
MinMaxBounds.Doubles.CODEC.fieldOf("dealt").forGetter { it.first }, DoublesCodec.fieldOf("dealt").forGetter { it.first },
MinMaxBounds.Doubles.CODEC.fieldOf("taken").forGetter { it.second }, DoublesCodec.fieldOf("taken").forGetter { it.second },
).apply(it, ::Pair) ).apply(it, ::Pair)
} }
val DamagePredicateCodec: Codec<DamagePredicate> = RecordCodecBuilder.create { val DamagePredicateCodec: Codec<DamagePredicate> = RecordCodecBuilder.create {
it.group( it.group(
dealtReceived.fieldOf("damage").forGetter { it.dealtDamage to it.takenDamage }, dealtReceived.fieldOf("damage").forGetter { it.dealtDamage to it.takenDamage },
Codec.BOOL.optionalFieldOf("blocked").forGetter { it.blocked }, Codec.BOOL.optionalFieldOf("blocked").forGetter { Optional.ofNullable(it.blocked) },
EntityPredicate.CODEC.optionalFieldOf("source_entity").forGetter { it.sourceEntity }, Codec.PASSTHROUGH.xmap({ EntityPredicate.fromJson(it.cast(JsonOps.INSTANCE)) }, { Dynamic(JsonOps.INSTANCE, it.serializeToJson()) }).fieldOf("source_entity").forGetter { it.sourceEntity },
DamageSourcePredicate.CODEC.optionalFieldOf("type").forGetter { it.type }, 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, 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> { fun <V, T1> simpleCodec(factory: (T1) -> V, field1: KProperty1<V, T1>, codec1: Codec<T1>): Codec<V> {

View File

@ -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}" }
}
}
}

View File

@ -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}" }
}
}
}

View File

@ -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()))
}
}
}
}

View File

@ -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.nbt.set
import ru.dbotthepony.mc.otm.core.stream import ru.dbotthepony.mc.otm.core.stream
import ru.dbotthepony.mc.otm.core.tagNotNull import ru.dbotthepony.mc.otm.core.tagNotNull
import ru.dbotthepony.mc.otm.data.Codec2Serializer
import ru.dbotthepony.mc.otm.registry.MItemFunctionTypes import ru.dbotthepony.mc.otm.registry.MItemFunctionTypes
import java.util.Optional import java.util.Optional
import java.util.stream.Stream import java.util.stream.Stream
@ -73,15 +74,17 @@ class CopyTileNbtFunction(filter: Stream<out String> = Stream.empty()) : LootIte
} }
companion object { companion object {
val CODEC: Codec<CopyTileNbtFunction> by lazy { val CODEC by lazy {
RecordCodecBuilder.create { Codec2Serializer<CopyTileNbtFunction>(
it.group( RecordCodecBuilder.create {
Codec.STRING.listOf() it.group(
.optionalFieldOf("filter") Codec.STRING.listOf()
.xmap({ it.orElseGet { listOf() } }, { if (it.isEmpty()) Optional.empty() else Optional.of(it) }) .optionalFieldOf("filter")
.forGetter(CopyTileNbtFunction::filter), .xmap({ it.orElseGet { listOf() } }, { if (it.isEmpty()) Optional.empty() else Optional.of(it) })
).apply(it, ::CopyTileNbtFunction) .forGetter(CopyTileNbtFunction::filter),
} ).apply(it, ::CopyTileNbtFunction)
}
)
} }
} }
} }

View File

@ -1,13 +1,20 @@
package ru.dbotthepony.mc.otm.data.loot package ru.dbotthepony.mc.otm.data.loot
import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableList
import com.google.gson.JsonSyntaxException
import com.mojang.serialization.Codec 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 com.mojang.serialization.codecs.RecordCodecBuilder
import it.unimi.dsi.fastutil.objects.ObjectArrayList import it.unimi.dsi.fastutil.objects.ObjectArrayList
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.storage.loot.Deserializers
import net.minecraft.world.level.storage.loot.LootContext import net.minecraft.world.level.storage.loot.LootContext
import net.minecraft.world.level.storage.loot.LootPool import net.minecraft.world.level.storage.loot.LootPool
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
import net.minecraftforge.common.ForgeHooks
import net.minecraftforge.common.loot.IGlobalLootModifier import net.minecraftforge.common.loot.IGlobalLootModifier
import net.minecraftforge.common.loot.LootModifier import net.minecraftforge.common.loot.LootModifier
import java.util.* import java.util.*
@ -32,10 +39,51 @@ class LootPoolAppender(conditions: Array<out LootItemCondition>, pools: Stream<L
} }
companion object { 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> = val CODEC: Codec<LootPoolAppender> =
RecordCodecBuilder.create { RecordCodecBuilder.create {
codecStart(it).and( codecStart(it).and(
LootPool.CODEC.listOf().fieldOf("pools").forGetter(LootPoolAppender::pools) lootPoolCodec.fieldOf("pools").forGetter(LootPoolAppender::pools)
).apply(it, ::LootPoolAppender) ).apply(it, ::LootPoolAppender)
} }
} }

View File

@ -102,7 +102,7 @@ class FluidCapsuleItem(val capacity: IntSupplier) : MatteryItem(Properties().sta
actionResult.result actionResult.result
} else { } else {
val state = level.getBlockState(hitPos) 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) val actionResult = FluidUtil.tryPlaceFluid(player, level, hand, placePos, targetItem, fluid)
if (!actionResult.isSuccess) return InteractionResultHolder.pass(item) if (!actionResult.isSuccess) return InteractionResultHolder.pass(item)

View File

@ -1,7 +1,7 @@
package ru.dbotthepony.mc.otm.item package ru.dbotthepony.mc.otm.item
import net.minecraft.core.BlockSource
import net.minecraft.core.Direction import net.minecraft.core.Direction
import net.minecraft.core.dispenser.BlockSource
import net.minecraft.core.dispenser.DefaultDispenseItemBehavior import net.minecraft.core.dispenser.DefaultDispenseItemBehavior
import net.minecraft.core.dispenser.DispenseItemBehavior import net.minecraft.core.dispenser.DispenseItemBehavior
import net.minecraft.tags.BlockTags 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.DyeColor
import net.minecraft.world.item.Item import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.MinecartItem
import net.minecraft.world.item.context.UseOnContext import net.minecraft.world.item.context.UseOnContext
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import net.minecraft.world.level.block.BaseRailBlock import net.minecraft.world.level.block.BaseRailBlock
import net.minecraft.world.level.block.DispenserBlock import net.minecraft.world.level.block.DispenserBlock
import net.minecraft.world.level.block.state.properties.RailShape import net.minecraft.world.level.block.state.properties.RailShape
import net.minecraft.world.level.gameevent.GameEvent 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.entity.MinecartCargoCrate
import ru.dbotthepony.mc.otm.registry.MEntityTypes import ru.dbotthepony.mc.otm.registry.MEntityTypes
import kotlin.math.floor
class MinecartCargoCrateItem(val color: DyeColor?) : MatteryItem(Properties().stacksTo(16)) { class MinecartCargoCrateItem(val color: DyeColor?) : MatteryItem(Properties().stacksTo(16)) {
init { init {
@ -68,7 +65,7 @@ class MinecartCargoCrateItem(val color: DyeColor?) : MatteryItem(Properties().st
private val default = DefaultDispenseItemBehavior() private val default = DefaultDispenseItemBehavior()
override fun dispense(blockSource: BlockSource, itemStack: ItemStack): ItemStack { 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 level: Level = blockSource.level
val x = blockSource.pos.x + direction.stepX.toDouble() * 1.125 val x = blockSource.pos.x + direction.stepX.toDouble() * 1.125
val y = blockSource.pos.y + direction.stepY.toDouble() val y = blockSource.pos.y + direction.stepY.toDouble()

View File

@ -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.math.set
import ru.dbotthepony.mc.otm.core.nbt.mapPresent import ru.dbotthepony.mc.otm.core.nbt.mapPresent
import ru.dbotthepony.mc.otm.core.tagNotNull 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.data.DecimalProvider
import ru.dbotthepony.mc.otm.registry.MItemFunctionTypes import ru.dbotthepony.mc.otm.registry.MItemFunctionTypes
import java.util.Optional import java.util.Optional
@ -119,15 +120,17 @@ class ProceduralBatteryItem : MatteryItem(Properties().stacksTo(1)) {
} }
companion object { companion object {
val CODEC: Codec<Randomizer> by lazy { val CODEC by lazy {
RecordCodecBuilder.create { Codec2Serializer<Randomizer>(
it.group( RecordCodecBuilder.create {
DecimalProvider.CODEC.fieldOf("maxBatteryLevel").forGetter(Randomizer::maxBatteryLevel), it.group(
DecimalProvider.CODEC.optionalFieldOf("batteryLevel").forGetter(Randomizer::batteryLevel), DecimalProvider.CODEC.fieldOf("maxBatteryLevel").forGetter(Randomizer::maxBatteryLevel),
DecimalProvider.CODEC.fieldOf("maxInput").forGetter(Randomizer::maxInput), DecimalProvider.CODEC.optionalFieldOf("batteryLevel").forGetter(Randomizer::batteryLevel),
DecimalProvider.CODEC.optionalFieldOf("maxOutput").forGetter(Randomizer::maxOutput), DecimalProvider.CODEC.fieldOf("maxInput").forGetter(Randomizer::maxInput),
).apply(it, ::Randomizer) DecimalProvider.CODEC.optionalFieldOf("maxOutput").forGetter(Randomizer::maxOutput),
} ).apply(it, ::Randomizer)
}
)
} }
} }
} }

View File

@ -153,7 +153,7 @@ class QuantumBatteryItem(val savedataID: String, val balanceValues: EnergyBalanc
val clientData = Object2ObjectOpenHashMap<UUID, IValues>() val clientData = Object2ObjectOpenHashMap<UUID, IValues>()
val serverData: Data by lazyPerServer { 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 { private inner class Power(private val stack: ItemStack) : IMatteryEnergyStorage, ICapabilityProvider {

View File

@ -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.TranslatableComponent
import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.tagNotNull import ru.dbotthepony.mc.otm.core.tagNotNull
import ru.dbotthepony.mc.otm.data.Codec2Serializer
import ru.dbotthepony.mc.otm.registry.MItemFunctionTypes import ru.dbotthepony.mc.otm.registry.MItemFunctionTypes
import java.util.* import java.util.*
@ -34,11 +35,15 @@ class ProceduralExopackSlotUpgradeItem : AbstractExopackSlotUpgradeItem(defaultP
} }
companion object { companion object {
val CODEC: Codec<Randomizer> = RecordCodecBuilder.create { val CODEC by lazy {
it.group( Codec2Serializer<Randomizer>(
IntProvider.CODEC.fieldOf("slots").forGetter(Randomizer::slots), RecordCodecBuilder.create {
IntProvider.CODEC.optionalFieldOf("luck_bias", ConstantInt.ZERO).forGetter(Randomizer::luckBias), it.group(
).apply(it, ::Randomizer) IntProvider.CODEC.fieldOf("slots").forGetter(Randomizer::slots),
IntProvider.CODEC.optionalFieldOf("luck_bias", ConstantInt.ZERO).forGetter(Randomizer::luckBias),
).apply(it, ::Randomizer)
}
)
} }
} }
} }

View File

@ -53,7 +53,6 @@ import net.minecraftforge.event.AddReloadListenerEvent
import net.minecraftforge.event.OnDatapackSyncEvent import net.minecraftforge.event.OnDatapackSyncEvent
import net.minecraftforge.event.RegisterCommandsEvent import net.minecraftforge.event.RegisterCommandsEvent
import net.minecraftforge.event.entity.player.ItemTooltipEvent import net.minecraftforge.event.entity.player.ItemTooltipEvent
import net.minecraftforge.event.network.CustomPayloadEvent
import net.minecraftforge.event.server.ServerStartedEvent import net.minecraftforge.event.server.ServerStartedEvent
import net.minecraftforge.eventbus.api.IEventBus import net.minecraftforge.eventbus.api.IEventBus
import net.minecraftforge.fml.ModList 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.readCollection
import ru.dbotthepony.mc.otm.core.util.writeBinaryComponent import ru.dbotthepony.mc.otm.core.util.writeBinaryComponent
import ru.dbotthepony.mc.otm.core.util.writeCollection 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.core.writeItemType
import ru.dbotthepony.mc.otm.milliTime import ru.dbotthepony.mc.otm.milliTime
import ru.dbotthepony.mc.otm.network.GenericNetworkChannel import ru.dbotthepony.mc.otm.network.GenericNetworkChannel
@ -1717,7 +1717,7 @@ object MatterManager {
if (event.player == null) { if (event.player == null) {
syncRegistry(PacketDistributor.ALL.noArg()) syncRegistry(PacketDistributor.ALL.noArg())
} else { } else {
syncRegistry(PacketDistributor.PLAYER.with(event.player!!)) syncRegistry(PacketDistributor.PLAYER.with { event.player!! })
} }
} }

View File

@ -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) { 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) 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) inventory.player.onEquipItem(type, oldItem, newItem)
super.setByPlayer(newItem, oldItem) super.setByPlayer(newItem)
} }
override fun mayPlace(itemStack: ItemStack): Boolean { override fun mayPlace(itemStack: ItemStack): Boolean {
@ -333,9 +334,10 @@ abstract class MatteryMenu(
autoCreateInventoryFrame = autoFrame autoCreateInventoryFrame = autoFrame
offhandSlot = object : InventorySlot(inventory, 40) { 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) inventory.player.onEquipItem(net.minecraft.world.entity.EquipmentSlot.OFFHAND, oldItem, newItem)
super.setByPlayer(newItem, oldItem) super.setByPlayer(newItem)
} }
override fun getNoItemIcon(): Pair<ResourceLocation, ResourceLocation> { override fun getNoItemIcon(): Pair<ResourceLocation, ResourceLocation> {

View File

@ -242,7 +242,7 @@ class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val isRemote: Bo
fun network() { fun network() {
check(!isRemote) { "Not a server" } 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) { for (packet in networkBacklog) {
MenuNetworkChannel.send(consumer, packet) MenuNetworkChannel.send(consumer, packet)

View File

@ -4,7 +4,6 @@ import net.minecraft.world.SimpleContainer
import net.minecraft.world.entity.player.Inventory import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.* import net.minecraft.world.item.*
import net.minecraft.world.item.crafting.RecipeHolder
import net.minecraft.world.level.material.Fluids import net.minecraft.world.level.material.Fluids
import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.fluids.FluidStack 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.collect.maybe
import ru.dbotthepony.mc.otm.core.isNotEmpty import ru.dbotthepony.mc.otm.core.isNotEmpty
import ru.dbotthepony.mc.otm.core.util.ResourceLocationValueCodec 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.MatteryMenu
import ru.dbotthepony.mc.otm.menu.MatterySlot import ru.dbotthepony.mc.otm.menu.MatterySlot
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
@ -46,7 +46,7 @@ class PainterMenu(
val inputContainer = MatteryContainer(::rescan, 1) val inputContainer = MatteryContainer(::rescan, 1)
val outputContainer = MatteryContainer(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() }) } var selectedRecipe by mSynchronizer.Slot(ListenableDelegate.Box(null), ResourceLocationValueCodec.nullable()).also { it.addListener(Runnable { rescan() }) }
val isBulk = BooleanInputWithFeedback(this, tile?.let { it::isBulk }) val isBulk = BooleanInputWithFeedback(this, tile?.let { it::isBulk })
@ -128,7 +128,7 @@ class PainterMenu(
} }
val listeners = Listenable.Void() val listeners = Listenable.Void()
val possibleRecipes = ArrayList<RecipeHolder<out AbstractPainterRecipe>>() val possibleRecipes = ArrayList<AbstractPainterRecipe>()
private fun rescan() { private fun rescan() {
possibleRecipes.clear() possibleRecipes.clear()
@ -140,7 +140,7 @@ class PainterMenu(
if (inputContainer.isEmpty || selectedRecipe == null) { if (inputContainer.isEmpty || selectedRecipe == null) {
outputContainer.clearContent() outputContainer.clearContent()
} else { } 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())) { if (recipe == null || !recipe.value.canCraft(dyeStoredDirect) || !recipe.value.matches(inputContainer, inventory.player.level())) {
outputContainer.clearContent() outputContainer.clearContent()

View File

@ -13,6 +13,7 @@ import ru.dbotthepony.mc.otm.container.ShadowCraftingContainer
import ru.dbotthepony.mc.otm.container.get import ru.dbotthepony.mc.otm.container.get
import ru.dbotthepony.mc.otm.container.set import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.isNotEmpty 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.item.IQuantumLinked
import ru.dbotthepony.mc.otm.menu.OutputSlot import ru.dbotthepony.mc.otm.menu.OutputSlot
import ru.dbotthepony.mc.otm.menu.MatteryMenu import ru.dbotthepony.mc.otm.menu.MatteryMenu

View File

@ -140,11 +140,11 @@ object GenericNetworkChannel : MatteryNetworkChannel(
name = "generic" name = "generic"
) { ) {
fun makeSmoke(x: Double, y: Double, z: Double, level: Level) { 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) { 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() { fun register() {

View File

@ -5,12 +5,11 @@ import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.Entity import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.player.Player 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.NetworkDirection
import net.minecraftforge.network.NetworkEvent
import net.minecraftforge.network.NetworkRegistry
import net.minecraftforge.network.PacketDistributor import net.minecraftforge.network.PacketDistributor
import net.minecraftforge.network.SimpleChannel import net.minecraftforge.network.simple.SimpleChannel
import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.LogManager
import ru.dbotthepony.kommons.util.Delegate import ru.dbotthepony.kommons.util.Delegate
import ru.dbotthepony.kommons.util.getValue import ru.dbotthepony.kommons.util.getValue
@ -22,6 +21,7 @@ import java.util.concurrent.ConcurrentLinkedQueue
import java.util.concurrent.locks.LockSupport import java.util.concurrent.locks.LockSupport
import java.util.function.BiConsumer import java.util.function.BiConsumer
import java.util.function.Function import java.util.function.Function
import java.util.function.Supplier
import kotlin.reflect.KClass import kotlin.reflect.KClass
class MNetworkContext(val sender: ServerPlayer?, packetHandled: Delegate<Boolean>, private val enqueuer: (Runnable) -> CompletableFuture<*>) { 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) { abstract class MatteryNetworkChannel(val version: Int, val name: String) {
val channel: SimpleChannel = ChannelBuilder val channel: SimpleChannel = NetworkRegistry
.named(ResourceLocation(OverdriveThatMatters.MOD_ID, name)) .newSimpleChannel(ResourceLocation(OverdriveThatMatters.MOD_ID, name), { version.toString() }, { it == NetworkRegistry.ACCEPTVANILLA || it == NetworkRegistry.ABSENT.version || it == version.toString() }, { it == version.toString() })
.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()
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) { fun send(ply: Player, packet: Any) {
if (ply is ServerPlayer) { 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 return
} }
channel.send(packet, PacketDistributor.TRACKING_ENTITY.with(entity)) channel.send(PacketDistributor.TRACKING_ENTITY.with { entity }, packet)
} }
fun sendTrackingAndSelf(entity: Entity, packet: Any) { fun sendTrackingAndSelf(entity: Entity, packet: Any) {
@ -66,11 +62,11 @@ abstract class MatteryNetworkChannel(val version: Int, val name: String) {
return 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) { fun send(distributor: PacketDistributor.PacketTarget, packet: Any) {
channel.send(packet, distributor) channel.send(distributor, packet)
} }
private var nextNetworkPacketID = 0 private var nextNetworkPacketID = 0
@ -87,8 +83,8 @@ abstract class MatteryNetworkChannel(val version: Int, val name: String) {
throw IndexOutOfBoundsException("Network message ID overflow!") throw IndexOutOfBoundsException("Network message ID overflow!")
} }
val builder = channel.messageBuilder(packetClass, direction) val builder = channel.messageBuilder(packetClass, nextNetworkPacketID++)
val bridgeHandler = BiConsumer<T, CustomPayloadEvent.Context> { a, b -> handler(a, MNetworkContext(b.sender, Delegate.Of({ b.packetHandled }, { b.packetHandled = it }), b::enqueueWork)) } 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) { if (handleOnMainThread) {
builder.consumerMainThread(bridgeHandler) builder.consumerMainThread(bridgeHandler)

View File

@ -1,9 +1,11 @@
package ru.dbotthepony.mc.otm.recipe package ru.dbotthepony.mc.otm.recipe
import com.google.gson.JsonObject
import com.mojang.serialization.Codec import com.mojang.serialization.Codec
import net.minecraft.core.NonNullList import net.minecraft.core.NonNullList
import net.minecraft.core.RegistryAccess import net.minecraft.core.RegistryAccess
import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.inventory.CraftingContainer import net.minecraft.world.inventory.CraftingContainer
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.crafting.CraftingBookCategory import net.minecraft.world.item.crafting.CraftingBookCategory
@ -99,16 +101,12 @@ class EnergyContainerRecipe(val parent: ShapedRecipe) : CraftingRecipe, IShapedR
} }
companion object : RecipeSerializer<EnergyContainerRecipe> { companion object : RecipeSerializer<EnergyContainerRecipe> {
private val codec by lazy { override fun fromNetwork(id: ResourceLocation, data: FriendlyByteBuf): EnergyContainerRecipe? {
RecipeSerializer.SHAPED_RECIPE.codec().xmap(::EnergyContainerRecipe, EnergyContainerRecipe::parent) return ShapedRecipe.Serializer.SHAPED_RECIPE.fromNetwork(id, data)?.let(::EnergyContainerRecipe)
} }
override fun codec(): Codec<EnergyContainerRecipe> { override fun fromJson(p_44103_: ResourceLocation, p_44104_: JsonObject): EnergyContainerRecipe {
return codec return EnergyContainerRecipe(ShapedRecipe.Serializer.SHAPED_RECIPE.fromJson(p_44103_, p_44104_))
}
override fun fromNetwork(data: FriendlyByteBuf): EnergyContainerRecipe? {
return ShapedRecipe.Serializer.SHAPED_RECIPE.fromNetwork(data)?.let(::EnergyContainerRecipe)
} }
override fun toNetwork(buff: FriendlyByteBuf, value: EnergyContainerRecipe) { override fun toNetwork(buff: FriendlyByteBuf, value: EnergyContainerRecipe) {

View File

@ -42,6 +42,7 @@ interface IMatterEntanglerRecipe : IMatteryRecipe<CraftingContainer> {
} }
open class MatterEntanglerRecipe( open class MatterEntanglerRecipe(
private val id: ResourceLocation,
override val ingredients: IIngredientMatrix, override val ingredients: IIngredientMatrix,
override val matter: Decimal, override val matter: Decimal,
override val ticks: Double, override val ticks: Double,
@ -50,6 +51,10 @@ open class MatterEntanglerRecipe(
val uuidKey: String = "uuid", val uuidKey: String = "uuid",
val fixedUuid: Optional<UUID> = Optional.empty() val fixedUuid: Optional<UUID> = Optional.empty()
) : IMatterEntanglerRecipe { ) : IMatterEntanglerRecipe {
override fun getId(): ResourceLocation {
return id
}
override fun matches(container: CraftingContainer, level: Level): Boolean { override fun matches(container: CraftingContainer, level: Level): Boolean {
if (isIncomplete) return false if (isIncomplete) return false
return ingredients.test(container) return ingredients.test(container)
@ -98,8 +103,8 @@ open class MatterEntanglerRecipe(
return ItemStack(MItems.MATTER_ENTANGLER) return ItemStack(MItems.MATTER_ENTANGLER)
} }
fun toFinished(id: ResourceLocation): FinishedRecipe { fun toFinished(): FinishedRecipe {
return SERIALIZER.toFinished(this, id) return SERIALIZER.toFinished(this)
} }
fun energetic() = Energy(this) fun energetic() = Energy(this)
@ -114,8 +119,8 @@ open class MatterEntanglerRecipe(
} }
} }
fun toFinished(id: ResourceLocation): FinishedRecipe { fun toFinished(): FinishedRecipe {
return ENERGY_SERIALIZER.toFinished(this, id) return ENERGY_SERIALIZER.toFinished(this)
} }
override fun getSerializer(): RecipeSerializer<*> { override fun getSerializer(): RecipeSerializer<*> {
@ -132,8 +137,8 @@ open class MatterEntanglerRecipe(
} }
} }
fun toFinished(id: ResourceLocation): FinishedRecipe { fun toFinished(): FinishedRecipe {
return MATTER_SERIALIZER.toFinished(this, id) return MATTER_SERIALIZER.toFinished(this)
} }
override fun getSerializer(): RecipeSerializer<*> { override fun getSerializer(): RecipeSerializer<*> {
@ -152,7 +157,7 @@ open class MatterEntanglerRecipe(
Codec.FLOAT.minRange(0f).optionalFieldOf("experience", 0f).forGetter(MatterEntanglerRecipe::experience), Codec.FLOAT.minRange(0f).optionalFieldOf("experience", 0f).forGetter(MatterEntanglerRecipe::experience),
Codec.STRING.optionalFieldOf("uuidKey", "uuid").forGetter(MatterEntanglerRecipe::uuidKey), Codec.STRING.optionalFieldOf("uuidKey", "uuid").forGetter(MatterEntanglerRecipe::uuidKey),
UUIDUtil.STRING_CODEC.optionalFieldOf("fixedUuid").forGetter(MatterEntanglerRecipe::fixedUuid) 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) }
} }
} }

View File

@ -24,12 +24,17 @@ import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MRecipes import ru.dbotthepony.mc.otm.registry.MRecipes
abstract class MatteryCookingRecipe( abstract class MatteryCookingRecipe(
private val id: ResourceLocation,
val input: Ingredient, val input: Ingredient,
val output: Ingredient, val output: Ingredient,
val count: Int = 1, val count: Int = 1,
val workTime: Int = 200, val workTime: Int = 200,
val experience: FloatProvider = ConstantFloat.ZERO val experience: FloatProvider = ConstantFloat.ZERO
) : Recipe<Container> { ) : Recipe<Container> {
override fun getId(): ResourceLocation {
return id
}
override fun matches(container: Container, level: Level): Boolean { override fun matches(container: Container, level: Level): Boolean {
if (isIncomplete) if (isIncomplete)
return false return false
@ -69,20 +74,21 @@ abstract class MatteryCookingRecipe(
override fun getResultItem(registry: RegistryAccess): ItemStack = outputStack override fun getResultItem(registry: RegistryAccess): ItemStack = outputStack
abstract fun toFinished(id: ResourceLocation): FinishedRecipe abstract fun toFinished(): FinishedRecipe
} }
class MicrowaveRecipe( class MicrowaveRecipe(
id: ResourceLocation,
input: Ingredient, input: Ingredient,
output: Ingredient, output: Ingredient,
count: Int = 1, count: Int = 1,
workTime: Int = 200, workTime: Int = 200,
experience: FloatProvider = ConstantFloat.ZERO 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 getType(): RecipeType<*> = MRecipes.MICROWAVE
override fun getToastSymbol(): ItemStack = ItemStack(MItems.POWERED_SMOKER[null]!!) override fun getToastSymbol(): ItemStack = ItemStack(MItems.POWERED_SMOKER[null]!!)
override fun getSerializer(): RecipeSerializer<*> = SERIALIZER override fun getSerializer(): RecipeSerializer<*> = SERIALIZER
override fun toFinished(id: ResourceLocation): FinishedRecipe = SERIALIZER.toFinished(this, id) override fun toFinished(): FinishedRecipe = SERIALIZER.toFinished(this)
companion object { companion object {
val SERIALIZER = Codec2RecipeSerializer<MicrowaveRecipe> { context -> val SERIALIZER = Codec2RecipeSerializer<MicrowaveRecipe> { context ->
@ -93,7 +99,7 @@ class MicrowaveRecipe(
Codec.INT.minRange(1).optionalFieldOf("count", 1).forGetter(MicrowaveRecipe::count), Codec.INT.minRange(1).optionalFieldOf("count", 1).forGetter(MicrowaveRecipe::count),
Codec.INT.minRange(0).optionalFieldOf("workTime", 200).forGetter(MicrowaveRecipe::workTime), Codec.INT.minRange(0).optionalFieldOf("workTime", 200).forGetter(MicrowaveRecipe::workTime),
FloatProvider.CODEC.optionalFieldOf("experience", ConstantFloat.ZERO).forGetter(MicrowaveRecipe::experience) 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) }
} }
} }
} }

View File

@ -31,8 +31,13 @@ import ru.dbotthepony.mc.otm.registry.MRecipes
import java.util.function.Predicate import java.util.function.Predicate
abstract class AbstractPainterRecipe( abstract class AbstractPainterRecipe(
private val id: ResourceLocation,
dyes: Map<out DyeColor?, Int> dyes: Map<out DyeColor?, Int>
) : IMatteryRecipe<Container> { ) : IMatteryRecipe<Container> {
override fun getId(): ResourceLocation {
return id
}
val dyes: Object2IntMap<DyeColor?> = Object2IntMaps.unmodifiable(Object2IntArrayMap(dyes)) val dyes: Object2IntMap<DyeColor?> = Object2IntMaps.unmodifiable(Object2IntArrayMap(dyes))
abstract fun matches(value: ItemStack): Boolean abstract fun matches(value: ItemStack): Boolean
@ -106,15 +111,17 @@ abstract class AbstractPainterRecipe(
} }
class PainterRecipe( class PainterRecipe(
id: ResourceLocation,
val input: Ingredient, val input: Ingredient,
val output: ItemStack, val output: ItemStack,
dyes: Map<out DyeColor?, Int> dyes: Map<out DyeColor?, Int>
) : AbstractPainterRecipe(dyes) { ) : AbstractPainterRecipe(id, dyes) {
constructor( constructor(
id: ResourceLocation,
input: Ingredient, input: Ingredient,
output: ItemStack, output: ItemStack,
dyes: Set<DyeColor?> 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 { override fun matches(value: ItemStack): Boolean {
return !isIncomplete && input.test(value) return !isIncomplete && input.test(value)
@ -154,8 +161,8 @@ class PainterRecipe(
return MRecipes.PAINTER return MRecipes.PAINTER
} }
fun toFinished(id: ResourceLocation): FinishedRecipe { fun toFinished(): FinishedRecipe {
return SERIALIZER.toFinished(this, id) return SERIALIZER.toFinished(this)
} }
override fun getOutput(container: Container): ItemStack { override fun getOutput(container: Container): ItemStack {
@ -169,17 +176,19 @@ class PainterRecipe(
context.ingredients.fieldOf("input").forGetter(PainterRecipe::input), context.ingredients.fieldOf("input").forGetter(PainterRecipe::input),
ItemStack.CODEC.fieldOf("output").forGetter(PainterRecipe::output), ItemStack.CODEC.fieldOf("output").forGetter(PainterRecipe::output),
dyesFieldCodec.forGetter(AbstractPainterRecipe::dyes), dyesFieldCodec.forGetter(AbstractPainterRecipe::dyes),
).apply(it, ::PainterRecipe) ).apply(it) { a, b, c -> PainterRecipe(context.id, a, b, c) }
} }
} }
} }
} }
class PainterArmorDyeRecipe( class PainterArmorDyeRecipe(
id: ResourceLocation,
dyes: Map<out DyeColor?, Int> dyes: Map<out DyeColor?, Int>
) : AbstractPainterRecipe(dyes) { ) : AbstractPainterRecipe(id, dyes) {
constructor( constructor(
id: ResourceLocation,
dyes: Set<DyeColor?> 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 { override fun matches(value: ItemStack): Boolean {
return !isIncomplete && value.item is DyeableArmorItem return !isIncomplete && value.item is DyeableArmorItem
@ -207,8 +216,8 @@ class PainterArmorDyeRecipe(
override fun isIncomplete(): Boolean = dyes.isEmpty() override fun isIncomplete(): Boolean = dyes.isEmpty()
fun toFinished(id: ResourceLocation): FinishedRecipe { fun toFinished(): FinishedRecipe {
return SERIALIZER.toFinished(this, id) return SERIALIZER.toFinished(this)
} }
override fun getOutput(container: Container): ItemStack { override fun getOutput(container: Container): ItemStack {
@ -228,11 +237,11 @@ class PainterArmorDyeRecipe(
} }
companion object { companion object {
val SERIALIZER = Codec2RecipeSerializer<PainterArmorDyeRecipe> { _ -> val SERIALIZER = Codec2RecipeSerializer<PainterArmorDyeRecipe> { context ->
RecordCodecBuilder.create { RecordCodecBuilder.create {
it.group( it.group(
dyesFieldCodec.forGetter(AbstractPainterRecipe::dyes), dyesFieldCodec.forGetter(AbstractPainterRecipe::dyes),
).apply(it, ::PainterArmorDyeRecipe) ).apply(it) { a -> PainterArmorDyeRecipe(context.id, a) }
} }
} }
} }

View File

@ -24,12 +24,17 @@ import ru.dbotthepony.mc.otm.data.minRange
import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MItems
class PlatePressRecipe( class PlatePressRecipe(
private val id: ResourceLocation,
val input: Ingredient, val input: Ingredient,
val output: Ingredient, val output: Ingredient,
val count: Int = 1, val count: Int = 1,
val workTime: Int = 200, val workTime: Int = 200,
val experience: FloatProvider = ConstantFloat.ZERO val experience: FloatProvider = ConstantFloat.ZERO
) : Recipe<Container> { ) : Recipe<Container> {
override fun getId(): ResourceLocation {
return id
}
override fun matches(container: Container, p_44003_: Level): Boolean { override fun matches(container: Container, p_44003_: Level): Boolean {
if (isIncomplete) if (isIncomplete)
return false return false
@ -79,7 +84,7 @@ class PlatePressRecipe(
return ItemStack(MItems.TWIN_PLATE_PRESS[null]!!) return ItemStack(MItems.TWIN_PLATE_PRESS[null]!!)
} }
fun toFinished(id: ResourceLocation) = SERIALIZER.toFinished(this, id) fun toFinished() = SERIALIZER.toFinished(this)
companion object { companion object {
val SERIALIZER = Codec2RecipeSerializer<PlatePressRecipe> { context -> val SERIALIZER = Codec2RecipeSerializer<PlatePressRecipe> { context ->
@ -90,7 +95,7 @@ class PlatePressRecipe(
Codec.INT.minRange(1).optionalFieldOf("count", 1).forGetter(PlatePressRecipe::count), Codec.INT.minRange(1).optionalFieldOf("count", 1).forGetter(PlatePressRecipe::count),
Codec.INT.minRange(0).optionalFieldOf("workTime", 200).forGetter(PlatePressRecipe::workTime), Codec.INT.minRange(0).optionalFieldOf("workTime", 200).forGetter(PlatePressRecipe::workTime),
FloatProvider.CODEC.optionalFieldOf("experience", ConstantFloat.ZERO).forGetter(PlatePressRecipe::experience) 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) }
} }
} }
} }

View File

@ -1,16 +1,12 @@
package ru.dbotthepony.mc.otm.recipe package ru.dbotthepony.mc.otm.recipe
import com.google.common.collect.ImmutableList 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.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.core.NonNullList import net.minecraft.core.NonNullList
import net.minecraft.core.RegistryAccess import net.minecraft.core.RegistryAccess
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.util.GsonHelper
import net.minecraft.util.StringRepresentable import net.minecraft.util.StringRepresentable
import net.minecraft.world.inventory.CraftingContainer import net.minecraft.world.inventory.CraftingContainer
import net.minecraft.world.item.ItemStack 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.container.util.stream
import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.core.tagNotNull 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.Codec2RecipeSerializer
import ru.dbotthepony.mc.otm.data.RecipePair
import ru.dbotthepony.mc.otm.data.codec
import ru.dbotthepony.mc.otm.data.SingletonCodec import ru.dbotthepony.mc.otm.data.SingletonCodec
import java.util.stream.Stream import java.util.stream.Stream
class UpgradeRecipe( class UpgradeRecipe(
val parent: ShapedRecipe, val parent: RecipePair<ShapedRecipe>,
copyPaths: Stream<Op>, copyPaths: Stream<Op>,
val source: ResourceLocation, val source: ResourceLocation,
) : CraftingRecipe, IShapedRecipe<CraftingContainer> by parent { ) : CraftingRecipe, IShapedRecipe<CraftingContainer> by parent.recipe {
constructor(parent: ShapedRecipe, copyPaths: Collection<Op>, source: ResourceLocation) : this(parent, copyPaths.stream(), source) constructor(parent: RecipePair<ShapedRecipe>, copyPaths: Collection<Op>, source: ResourceLocation) : this(parent, copyPaths.stream(), source)
override fun matches(p_44002_: CraftingContainer, p_44003_: Level): Boolean { 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 { 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 { 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> { override fun getRemainingItems(p_44004_: CraftingContainer): NonNullList<ItemStack> {
return parent.getRemainingItems(p_44004_) return parent.recipe.getRemainingItems(p_44004_)
} }
override fun getIngredients(): NonNullList<Ingredient> { override fun getIngredients(): NonNullList<Ingredient> {
return parent.ingredients return parent.recipe.ingredients
} }
override fun isSpecial(): Boolean { override fun isSpecial(): Boolean {
return parent.isSpecial return parent.recipe.isSpecial
} }
override fun showNotification(): Boolean { override fun showNotification(): Boolean {
return parent.showNotification() return parent.recipe.showNotification()
} }
override fun getGroup(): String { override fun getGroup(): String {
return parent.group return parent.recipe.group
} }
override fun getToastSymbol(): ItemStack { override fun getToastSymbol(): ItemStack {
return parent.toastSymbol return parent.recipe.toastSymbol
} }
override fun isIncomplete(): Boolean { override fun isIncomplete(): Boolean {
return parent.isIncomplete return parent.recipe.isIncomplete
} }
override fun getType(): RecipeType<*> { override fun getType(): RecipeType<*> {
return parent.type return parent.recipe.type
} }
override fun category(): CraftingBookCategory { override fun category(): CraftingBookCategory {
return parent.category() return parent.recipe.category()
} }
enum class OpType : StringRepresentable { enum class OpType : StringRepresentable {
@ -208,7 +202,7 @@ class UpgradeRecipe(
val copyPaths: ImmutableList<Op> = copyPaths.collect(ImmutableList.toImmutableList()) val copyPaths: ImmutableList<Op> = copyPaths.collect(ImmutableList.toImmutableList())
override fun assemble(pInv: CraftingContainer, registryAccess: RegistryAccess): ItemStack { override fun assemble(pInv: CraftingContainer, registryAccess: RegistryAccess): ItemStack {
val result = parent.assemble(pInv, registryAccess) val result = parent.recipe.assemble(pInv, registryAccess)
if (result.isEmpty) { if (result.isEmpty) {
return result return result
@ -242,7 +236,7 @@ class UpgradeRecipe(
val CODEC = Codec2RecipeSerializer<UpgradeRecipe> { p -> val CODEC = Codec2RecipeSerializer<UpgradeRecipe> { p ->
RecordCodecBuilder.create { RecordCodecBuilder.create {
it.group( 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), COPY_PATHS_CODEC.fieldOf("copyPaths").forGetter(UpgradeRecipe::copyPaths),
ResourceLocation.CODEC.fieldOf("source").forGetter(UpgradeRecipe::source) ResourceLocation.CODEC.fieldOf("source").forGetter(UpgradeRecipe::source)
).apply(it, ::UpgradeRecipe) ).apply(it, ::UpgradeRecipe)

View File

@ -6,6 +6,7 @@ import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType
import net.minecraftforge.eventbus.api.IEventBus import net.minecraftforge.eventbus.api.IEventBus
import net.minecraftforge.registries.DeferredRegister import net.minecraftforge.registries.DeferredRegister
import ru.dbotthepony.mc.otm.OverdriveThatMatters 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.SingletonCodec
import ru.dbotthepony.mc.otm.data.condition.ChanceWithPlaytimeCondition import ru.dbotthepony.mc.otm.data.condition.ChanceWithPlaytimeCondition
import ru.dbotthepony.mc.otm.data.condition.HasExoPackCondition import ru.dbotthepony.mc.otm.data.condition.HasExoPackCondition
@ -17,12 +18,12 @@ import ru.dbotthepony.mc.otm.data.condition.ChanceCondition
object MLootItemConditions { object MLootItemConditions {
private val registry = MDeferredRegister(Registries.LOOT_CONDITION_TYPE, OverdriveThatMatters.MOD_ID) private val registry = MDeferredRegister(Registries.LOOT_CONDITION_TYPE, OverdriveThatMatters.MOD_ID)
val HAS_EXOPACK: LootItemConditionType by registry.register("has_exopack") { LootItemConditionType(SingletonCodec(HasExoPackCondition)) } 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(ChanceWithPlaytimeCondition.CODEC) } 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(ItemInInventoryCondition.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(SingletonCodec(KilledByRealPlayer)) } 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(SingletonCodec(KilledByRealPlayerOrIndirectly)) } 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(ChanceCondition.CODEC) } val CHANCE: LootItemConditionType by registry.register("chance") { LootItemConditionType(Codec2Serializer(ChanceCondition.CODEC)) }
internal fun register(bus: IEventBus) { internal fun register(bus: IEventBus) {
registry.register(bus) registry.register(bus)

View File

@ -334,28 +334,28 @@ object MRegistry : IBlockItemRegistryAcceptor {
NanobotsArmorFeature.Companion NanobotsArmorFeature.Companion
EnderTeleporterFeature.Companion EnderTeleporterFeature.Companion
CriteriaTriggers.register(BlackHoleTrigger.id.toString(), BlackHoleTrigger) CriteriaTriggers.register(BlackHoleTrigger)
CriteriaTriggers.register(BecomeAndroidTrigger.id.toString(), BecomeAndroidTrigger) CriteriaTriggers.register(BecomeAndroidTrigger)
CriteriaTriggers.register(BecomeAndroidDeathTrigger.id.toString(), BecomeAndroidDeathTrigger) CriteriaTriggers.register(BecomeAndroidDeathTrigger)
CriteriaTriggers.register(BecomeAndroidSleepTrigger.id.toString(), BecomeAndroidSleepTrigger) CriteriaTriggers.register(BecomeAndroidSleepTrigger)
CriteriaTriggers.register(BecomeHumaneTrigger.id.toString(), BecomeHumaneTrigger) CriteriaTriggers.register(BecomeHumaneTrigger)
CriteriaTriggers.register(AndroidResearchTrigger.id.toString(), AndroidResearchTrigger) CriteriaTriggers.register(AndroidResearchTrigger)
CriteriaTriggers.register(ShockwaveDamageMobTrigger.id.toString(), ShockwaveDamageMobTrigger) CriteriaTriggers.register(ShockwaveDamageMobTrigger)
CriteriaTriggers.register(ShockwaveTrigger.id.toString(), ShockwaveTrigger) CriteriaTriggers.register(ShockwaveTrigger)
CriteriaTriggers.register(AndroidBatteryTrigger.id.toString(), AndroidBatteryTrigger) CriteriaTriggers.register(AndroidBatteryTrigger)
CriteriaTriggers.register(NanobotsArmorTrigger.id.toString(), NanobotsArmorTrigger) CriteriaTriggers.register(NanobotsArmorTrigger)
CriteriaTriggers.register(FallDampenersSaveTrigger.id.toString(), FallDampenersSaveTrigger) CriteriaTriggers.register(FallDampenersSaveTrigger)
CriteriaTriggers.register(EnderTeleporterFallDeathTrigger.id.toString(), EnderTeleporterFallDeathTrigger) CriteriaTriggers.register(EnderTeleporterFallDeathTrigger)
CriteriaTriggers.register(KillAsAndroidTrigger.id.toString(), KillAsAndroidTrigger) CriteriaTriggers.register(KillAsAndroidTrigger)
CriteriaTriggers.register(AndroidTravelUnderwater.id.toString(), AndroidTravelUnderwater) CriteriaTriggers.register(AndroidTravelUnderwater)
CriteriaTriggers.register(NailedEntityTrigger.id.toString(), NailedEntityTrigger) CriteriaTriggers.register(NailedEntityTrigger)
CriteriaTriggers.register(ExopackObtainedTrigger.id.toString(), ExopackObtainedTrigger) CriteriaTriggers.register(ExopackObtainedTrigger)
CriteriaTriggers.register(ExopackGainedSmeltingTrigger.id.toString(), ExopackGainedSmeltingTrigger) CriteriaTriggers.register(ExopackGainedSmeltingTrigger)
CriteriaTriggers.register(ExopackGainedCraftingTrigger.id.toString(), ExopackGainedCraftingTrigger) CriteriaTriggers.register(ExopackGainedCraftingTrigger)
CriteriaTriggers.register(ExopackGainedEnderAccessTrigger.id.toString(), ExopackGainedEnderAccessTrigger) CriteriaTriggers.register(ExopackGainedEnderAccessTrigger)
CriteriaTriggers.register(ExopackSlotsExpandedTrigger.id.toString(), ExopackSlotsExpandedTrigger) CriteriaTriggers.register(ExopackSlotsExpandedTrigger)
CriteriaTriggers.register(ExopackBatterySlotTrigger.id.toString(), ExopackBatterySlotTrigger) CriteriaTriggers.register(ExopackBatterySlotTrigger)
CriteriaTriggers.register(TakeItemOutOfReplicatorTrigger.id.toString(), TakeItemOutOfReplicatorTrigger) CriteriaTriggers.register(TakeItemOutOfReplicatorTrigger)
} }
private fun initializeCommon(event: FMLCommonSetupEvent) { private fun initializeCommon(event: FMLCommonSetupEvent) {

View File

@ -4,6 +4,7 @@ import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.advancements.critereon.ContextAwarePredicate import net.minecraft.advancements.critereon.ContextAwarePredicate
import net.minecraft.advancements.critereon.DamagePredicate import net.minecraft.advancements.critereon.DamagePredicate
import net.minecraft.advancements.critereon.DamageSourcePredicate
import net.minecraft.advancements.critereon.EntityPredicate import net.minecraft.advancements.critereon.EntityPredicate
import net.minecraft.advancements.critereon.MinMaxBounds import net.minecraft.advancements.critereon.MinMaxBounds
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
@ -35,9 +36,9 @@ class HurtTrigger(id: ResourceLocation) : MCriterionTrigger<HurtTrigger.Instance
val damagePredicate: Optional<DamagePredicate> = Optional.of(DamagePredicate( val damagePredicate: Optional<DamagePredicate> = Optional.of(DamagePredicate(
MinMaxBounds.Doubles.atLeast(1.0), MinMaxBounds.Doubles.atLeast(1.0),
MinMaxBounds.Doubles.atLeast(1.0), MinMaxBounds.Doubles.atLeast(1.0),
Optional.empty(), EntityPredicate.ANY,
Optional.empty(), null,
Optional.empty() DamageSourcePredicate.ANY
)), )),
player: Optional<ContextAwarePredicate> = Optional.empty() player: Optional<ContextAwarePredicate> = Optional.empty()
) : AbstractInstance(player) ) : AbstractInstance(player)

View File

@ -7,6 +7,7 @@ import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.data.ItemPredicateCodec
import java.util.* import java.util.*
class ItemTrigger(id: ResourceLocation) : MCriterionTrigger<ItemTrigger.Instance>(id) { 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 { override val codec: Codec<Instance> = RecordCodecBuilder.create {
it.group( it.group(
ItemPredicate.CODEC.fieldOf("predicate").forGetter(Instance::predicate), ItemPredicateCodec.fieldOf("predicate").forGetter(Instance::predicate),
Codec.BOOL.optionalFieldOf("invert", false).forGetter(Instance::invert), Codec.BOOL.optionalFieldOf("invert", false).forGetter(Instance::invert),
playerPredicateCodec.forGetter(Instance::playerPredicate) playerPredicateCodec.forGetter(Instance::playerPredicate)
).apply(it, ::Instance) ).apply(it, ::Instance)

View File

@ -17,6 +17,7 @@ import net.minecraft.advancements.CriterionTriggerInstance
import net.minecraft.advancements.critereon.ContextAwarePredicate import net.minecraft.advancements.critereon.ContextAwarePredicate
import net.minecraft.advancements.critereon.DeserializationContext import net.minecraft.advancements.critereon.DeserializationContext
import net.minecraft.advancements.critereon.EntityPredicate import net.minecraft.advancements.critereon.EntityPredicate
import net.minecraft.advancements.critereon.SerializationContext
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.server.PlayerAdvancements import net.minecraft.server.PlayerAdvancements
import net.minecraft.server.level.ServerPlayer 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 // allows to support both 1.20.1 and 1.20.2 with ease
// and has slightly less memory footprint than vanilla SimpleCriterionTrigger // 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>>>() private val listeners = Reference2ObjectOpenHashMap<PlayerAdvancements, ObjectOpenHashSet<CriterionTrigger.Listener<T>>>()
override fun addPlayerListener(advancements: PlayerAdvancements, listener: 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) val context = EntityPredicate.createContext(player, player)
listeners.iterator() 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() .toImmutableList()
.forEach { it.run(advancements) } .forEach { it.run(advancements) }
} }
abstract inner class AbstractInstance(val playerPredicate: Optional<ContextAwarePredicate>) : CriterionTriggerInstance { 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 { override fun getCriterion(): ResourceLocation {
return codec.toJsonStrict(this as T) as JsonObject 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 @JvmStatic
protected val predicateCodec: Codec<ContextAwarePredicate> = object : Codec<ContextAwarePredicate> { protected val predicateCodec: Codec<ContextAwarePredicate> = object : Codec<ContextAwarePredicate> {
override fun <T : Any?> encode(input: ContextAwarePredicate, ops: DynamicOps<T>, prefix: T): DataResult<T> { 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>> { 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" } val context = deserializationContext.get().lastOrNull() ?: return DataResult.error { "Not current deserializing trigger instance" }
return try { 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) { } catch (err: Exception) {
DataResult.error { "Failed to deserialize ContextAwarePredicate: " + err.message } DataResult.error { "Failed to deserialize ContextAwarePredicate: " + err.message }
} }

View File

@ -14,6 +14,7 @@ import net.minecraft.advancements.CriterionTrigger
import net.minecraft.advancements.critereon.DeserializationContext import net.minecraft.advancements.critereon.DeserializationContext
import net.minecraft.advancements.critereon.InventoryChangeTrigger import net.minecraft.advancements.critereon.InventoryChangeTrigger
import net.minecraft.advancements.critereon.MinMaxBounds import net.minecraft.advancements.critereon.MinMaxBounds
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.PlayerAdvancements import net.minecraft.server.PlayerAdvancements
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.Container import net.minecraft.world.Container
@ -83,13 +84,13 @@ object MatteryInventoryChangeTrigger : CriterionTrigger<InventoryChangeTrigger.T
nodes.add(Node( nodes.add(Node(
DefaultStrategy, 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 }, { 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) })) { inventory: Container, item: ItemStack, slotsFull: Int, slotsEmpty: Int, slotsOccupied: Int -> mutableListOf(item.item) }))
nodes.add(Node( nodes.add(Node(
DefaultStrategy, 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) }, { 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)) })) { 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>) { fun add(listener: CriterionTrigger.Listener<InventoryChangeTrigger.TriggerInstance>) {
if (set.add(listener)) { 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>) { fun remove(listener: CriterionTrigger.Listener<InventoryChangeTrigger.TriggerInstance>) {
if (set.remove(listener)) { 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) { if (nodeId + 1 == nodes.size) {
for (l in v as Set<CriterionTrigger.Listener<InventoryChangeTrigger.TriggerInstance>>) { for (l in v as Set<CriterionTrigger.Listener<InventoryChangeTrigger.TriggerInstance>>) {
// переделываем matches у InventoryTriggerInstance // переделываем matches у InventoryTriggerInstance
with (l.trigger) { with (l.triggerInstance) {
if ( if (
this.slotsFull.matches(slotsFull) && this.slotsFull.matches(slotsFull) &&
this.slotsEmpty.matches(slotsEmpty) && this.slotsEmpty.matches(slotsEmpty) &&
@ -217,6 +218,10 @@ object MatteryInventoryChangeTrigger : CriterionTrigger<InventoryChangeTrigger.T
listeners[advancements]?.remove(instance) listeners[advancements]?.remove(instance)
} }
override fun getId(): ResourceLocation {
return CriteriaTriggers.INVENTORY_CHANGED.id
}
override fun removePlayerListeners(advancements: PlayerAdvancements) { override fun removePlayerListeners(advancements: PlayerAdvancements) {
listeners.remove(advancements) listeners.remove(advancements)
} }

View File

@ -7,12 +7,13 @@ import net.minecraft.advancements.critereon.MinMaxBounds.Doubles
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.data.DoublesCodec
import java.util.* import java.util.*
object NanobotsArmorTrigger : MCriterionTrigger<NanobotsArmorTrigger.Instance>(ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_armor")) { object NanobotsArmorTrigger : MCriterionTrigger<NanobotsArmorTrigger.Instance>(ResourceLocation(OverdriveThatMatters.MOD_ID, "nanobots_armor")) {
override val codec: Codec<Instance> = RecordCodecBuilder.create { override val codec: Codec<Instance> = RecordCodecBuilder.create {
it.group( it.group(
Doubles.CODEC.fieldOf("predicate").forGetter(Instance::predicate), DoublesCodec.fieldOf("predicate").forGetter(Instance::predicate),
playerPredicateCodec.forGetter(Instance::playerPredicate), playerPredicateCodec.forGetter(Instance::playerPredicate),
).apply(it, ::Instance) ).apply(it, ::Instance)
} }

View File

@ -13,7 +13,7 @@ class SingletonTrigger(id: ResourceLocation) : MCriterionTrigger<SingletonTrigge
} }
val empty = Instance() val empty = Instance()
val criterion = Criterion(this@SingletonTrigger, empty) val criterion = Criterion(empty)
inner class Instance(player: Optional<ContextAwarePredicate> = Optional.empty()) : AbstractInstance(player) inner class Instance(player: Optional<ContextAwarePredicate> = Optional.empty()) : AbstractInstance(player)
} }

View File

@ -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_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_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-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

View File

@ -41,7 +41,7 @@ Matter. Energy. Combined.
# Does this dependency have to exist - if not, ordering below must be specified # Does this dependency have to exist - if not, ordering below must be specified
mandatory=true #mandatory mandatory=true #mandatory
# The version range of the dependency # 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 # An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory
ordering="NONE" ordering="NONE"
# Side this dependency is applied on - BOTH, CLIENT or SERVER # Side this dependency is applied on - BOTH, CLIENT or SERVER
@ -51,6 +51,6 @@ Matter. Energy. Combined.
modId="minecraft" modId="minecraft"
mandatory=true mandatory=true
# This version range declares a minimum of the current minecraft version up to but not including the next major version # 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" ordering="NONE"
side="BOTH" side="BOTH"