Advancements!
This commit is contained in:
parent
6e78972ea1
commit
1a468f9817
@ -30,6 +30,7 @@ import ru.dbotthepony.mc.otm.registry.*
|
||||
import ru.dbotthepony.mc.otm.core.registryName
|
||||
import ru.dbotthepony.mc.otm.datagen.advancements.AdvancementProvider
|
||||
import ru.dbotthepony.mc.otm.datagen.advancements.addAdvancements
|
||||
import ru.dbotthepony.mc.otm.datagen.advancements.addAndroidAdvancements
|
||||
import ru.dbotthepony.mc.otm.datagen.blocks.addBlockStates
|
||||
import ru.dbotthepony.mc.otm.datagen.blocks.addComplexBlockStates
|
||||
import ru.dbotthepony.mc.otm.datagen.items.addItemModels
|
||||
@ -69,6 +70,8 @@ object DataGen {
|
||||
private set
|
||||
var languageProvider: MatteryLanguageProvider by WriteOnce()
|
||||
private set
|
||||
var researchProvider: AndroidResearchDataProvider by WriteOnce()
|
||||
private set
|
||||
|
||||
fun decorativeCubeAll(vararg blocks: Block) {
|
||||
blockModelProvider.decorativeCubeAll(*blocks)
|
||||
@ -300,6 +303,7 @@ object DataGen {
|
||||
val recipeProvider = MatteryRecipeProvider(event.generator)
|
||||
val lootModifier = LootModifiers(event.generator)
|
||||
val languageProvider = MatteryLanguageProvider(event.generator)
|
||||
val researchProvider = AndroidResearchDataProvider(event.generator).also { it.exec { addResearchData(it, languageProvider) } }
|
||||
|
||||
this.blockModelProvider = blockModelProvider
|
||||
this.blockStateProvider = blockStateProvider
|
||||
@ -308,6 +312,7 @@ object DataGen {
|
||||
this.recipeProvider = recipeProvider
|
||||
this.lootModifier = lootModifier
|
||||
this.languageProvider = languageProvider
|
||||
this.researchProvider = researchProvider
|
||||
|
||||
val tagsProvider = TagsProvider(event)
|
||||
val advancementProvider = AdvancementProvider(event)
|
||||
@ -323,7 +328,7 @@ object DataGen {
|
||||
event.generator.addProvider(true, lootTableProvider)
|
||||
event.generator.addProvider(true, lootModifier)
|
||||
event.generator.addProvider(true, SoundDataProvider(event))
|
||||
event.generator.addProvider(true, AndroidResearchDataProvider(event.generator).also { it.exec { addResearchData(it, languageProvider) } })
|
||||
event.generator.addProvider(true, researchProvider)
|
||||
event.generator.addProvider(true, advancementProvider)
|
||||
|
||||
AddEnglishLanguage(languageProvider)
|
||||
@ -348,6 +353,7 @@ object DataGen {
|
||||
|
||||
advancementProvider.exec { it, files ->
|
||||
addAdvancements(it, files, languageProvider)
|
||||
addAndroidAdvancements(it, files, languageProvider)
|
||||
}
|
||||
|
||||
addPlatePressRecipes(recipeProvider)
|
||||
|
@ -458,6 +458,9 @@ fun addResearchData(serializer: Consumer<AndroidResearchType>, lang: MatteryLang
|
||||
add(ENDER_TELEPORTER, "Ender Teleporter")
|
||||
add(ENDER_TELEPORTER, "description", "Allows unit to perform instant, short distance teleports without damage to internal systems")
|
||||
|
||||
add(NIGHT_VISION, "Night Vision")
|
||||
add(NIGHT_VISION, "description", "Allows unit to clearly see in the dark")
|
||||
|
||||
add(attackBoostList[0], "Attack Boost %s")
|
||||
add(attackBoostList[0], "description", "Increases total melee attack strength by %s%%")
|
||||
}
|
||||
|
@ -40,4 +40,50 @@ fun addAdvancements(serializer: Consumer<Advancement>, existingFileHelper: Exist
|
||||
)
|
||||
.addCriterion("pulled_by_black_hole", BlackHoleTrigger.Instance)
|
||||
.save(serializer, modLocation("regular/black_hole"), existingFileHelper)
|
||||
|
||||
val ore = AdvancementBuilder()
|
||||
.parent(root)
|
||||
.requirements(RequirementsStrategy.OR)
|
||||
.display(
|
||||
itemStack = ItemStack(MItems.TRITANIUM_ORE_CLUMP),
|
||||
title = TranslatableComponent(translation.add("ore", "Blue Metal Discovery")),
|
||||
description = TranslatableComponent(translation.add("ore.desc", "Mine some Tritanium")),
|
||||
)
|
||||
.addCriterion("has_tritanium_ore", criterion(MItemTags.TRITANIUM_ORES))
|
||||
.addCriterion("has_tritanium_ore_clump", criterion(MItemTags.TRITANIUM_ORE_CLUMPS))
|
||||
.save(serializer, modLocation("regular/ore"), existingFileHelper)
|
||||
|
||||
val ingot = AdvancementBuilder()
|
||||
.parent(ore)
|
||||
.display(
|
||||
itemStack = ItemStack(MItems.TRITANIUM_INGOT),
|
||||
title = TranslatableComponent(translation.add("ingot", "Acquire Harder-ware")),
|
||||
description = TranslatableComponent(translation.add("ingot.desc", "Smelt a Tritanium ingot")),
|
||||
)
|
||||
.addCriterion("has_tritanium_ingot", criterion(MItemTags.TRITANIUM_INGOTS))
|
||||
.save(serializer, modLocation("regular/ingot"), existingFileHelper)
|
||||
|
||||
AdvancementBuilder()
|
||||
.parent(ingot)
|
||||
.display(
|
||||
itemStack = ItemStack(MItems.TRITANIUM_PICKAXE),
|
||||
title = TranslatableComponent(translation.add("pickaxe", "A Tool for Patient Miners")),
|
||||
description = TranslatableComponent(translation.add("pickaxe.desc", "Craft a Tritanium Pickaxe")),
|
||||
)
|
||||
.addCriterion("has_tritanium_pickaxe", criterion(MItems.TRITANIUM_PICKAXE))
|
||||
.save(serializer, modLocation("regular/pickaxe"), existingFileHelper)
|
||||
|
||||
val pill = AdvancementBuilder()
|
||||
.parent(root)
|
||||
.display(
|
||||
itemStack = ItemStack(MItems.PILL_ANDROID),
|
||||
title = TranslatableComponent(translation.add("pill", "Side Colored Mystery")),
|
||||
description = TranslatableComponent(translation.add("pill.desc", "Find some of those mysterious pills. Consult with Cleric before trying to ingest them.")),
|
||||
)
|
||||
.requirements(RequirementsStrategy.OR)
|
||||
.addCriterion("pill1", criterion(MItems.PILL_ANDROID))
|
||||
.addCriterion("pill2", criterion(MItems.PILL_HEAL))
|
||||
.addCriterion("pill3", criterion(MItems.PILL_HUMANE))
|
||||
.addCriterion("pill4", criterion(MItems.PILL_OBLIVION))
|
||||
.save(serializer, modLocation("regular/pill"), existingFileHelper)
|
||||
}
|
||||
|
@ -0,0 +1,183 @@
|
||||
package ru.dbotthepony.mc.otm.datagen.advancements
|
||||
|
||||
import net.minecraft.advancements.Advancement
|
||||
import net.minecraft.advancements.FrameType
|
||||
import net.minecraft.advancements.RequirementsStrategy
|
||||
import net.minecraft.advancements.critereon.DamagePredicate
|
||||
import net.minecraft.advancements.critereon.DamageSourcePredicate
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
import net.minecraft.advancements.critereon.InventoryChangeTrigger
|
||||
import net.minecraft.advancements.critereon.PlayerHurtEntityTrigger
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.EntityType
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraftforge.common.data.ExistingFileHelper
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
import ru.dbotthepony.mc.otm.datagen.DataGen
|
||||
import ru.dbotthepony.mc.otm.datagen.lang.MatteryLanguageProvider
|
||||
import ru.dbotthepony.mc.otm.datagen.modLocation
|
||||
import ru.dbotthepony.mc.otm.registry.MItemTags
|
||||
import ru.dbotthepony.mc.otm.registry.MItems
|
||||
import ru.dbotthepony.mc.otm.registry.MNames
|
||||
import ru.dbotthepony.mc.otm.triggers.AndroidResearchTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.BecomeAndroidDeathTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.BecomeAndroidSleepTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.BecomeAndroidTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.BecomeHumaneTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.ShockwaveDamageMobTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.ShockwaveTrigger
|
||||
import java.util.function.Consumer
|
||||
|
||||
fun addAndroidAdvancements(serializer: Consumer<Advancement>, existingFileHelper: ExistingFileHelper, lang: MatteryLanguageProvider) {
|
||||
val translation = lang.english.Prepended("otm.advancements.android")
|
||||
|
||||
val root = AdvancementBuilder()
|
||||
.display(
|
||||
itemStack = ItemStack(MItems.PILL_ANDROID),
|
||||
title = TranslatableComponent(translation.add("root", "Androids and Humans")),
|
||||
description = TranslatableComponent(translation.add("root.desc", "Can you make out who is cruel machine and who can make love?")),
|
||||
showToast = false,
|
||||
announceChat = false,
|
||||
background = modLocation("textures/block/decorative/metal_beam_top.png")
|
||||
)
|
||||
.addCriterion("became_android", BecomeAndroidTrigger.Instance)
|
||||
.save(serializer, modLocation("android/root"), existingFileHelper)
|
||||
|
||||
AdvancementBuilder()
|
||||
.parent(root)
|
||||
.display(
|
||||
itemStack = ItemStack(MItems.PILL_ANDROID),
|
||||
title = TranslatableComponent(translation.add("normal", "Last Sweet Dreams")),
|
||||
description = TranslatableComponent(translation.add("normal.desc", "Become an Android in your dreams, a soulless machine... Or is it?")),
|
||||
hidden = true,
|
||||
)
|
||||
.addCriterion("became_android", BecomeAndroidSleepTrigger.Instance)
|
||||
.save(serializer, modLocation("android/become_thru_sleep"), existingFileHelper)
|
||||
|
||||
AdvancementBuilder()
|
||||
.parent(root)
|
||||
.display(
|
||||
itemStack = ItemStack(MItems.PILL_ANDROID),
|
||||
title = TranslatableComponent(translation.add("death", "The Old Way")),
|
||||
description = TranslatableComponent(translation.add("death.desc", "Become an Android in event of death, veteran's favorite")),
|
||||
hidden = true,
|
||||
)
|
||||
.addCriterion("became_android", BecomeAndroidDeathTrigger.Instance)
|
||||
.save(serializer, modLocation("android/become_thru_death"), existingFileHelper)
|
||||
|
||||
AdvancementBuilder()
|
||||
.parent(root)
|
||||
.display(
|
||||
itemStack = ItemStack(MItems.PILL_HUMANE),
|
||||
title = TranslatableComponent(translation.add("unandroid", "Feel Humane Again")),
|
||||
description = TranslatableComponent(translation.add("unandroid.desc", "Become fleshy after being a machine, yet something is still missing that you had before...")),
|
||||
hidden = true,
|
||||
frameType = FrameType.GOAL
|
||||
)
|
||||
.addCriterion("become_humane", BecomeHumaneTrigger.Instance)
|
||||
.save(serializer, modLocation("android/become_humane"), existingFileHelper)
|
||||
|
||||
val researchAnything = AdvancementBuilder()
|
||||
.parent(root)
|
||||
.display(
|
||||
itemStack = ItemStack(MItems.ANDROID_STATION),
|
||||
title = TranslatableComponent(translation.add("research_anything", "New Trick")),
|
||||
description = TranslatableComponent(translation.add("research_anything.desc", "Research anything as Android")),
|
||||
)
|
||||
.addCriterion("research_anything", AndroidResearchTrigger.Instance(null))
|
||||
.save(serializer, modLocation("android/research_anything"), existingFileHelper)
|
||||
|
||||
AdvancementBuilder()
|
||||
.parent(researchAnything)
|
||||
.display(
|
||||
itemStack = ItemStack(Items.WATER_BUCKET),
|
||||
title = TranslatableComponent(translation.add("air_bags", "Patching Up Wooden Vessel")),
|
||||
description = TranslatableComponent(translation.add("air_bags.desc", "Research Air Bags as Android, to float in water")),
|
||||
)
|
||||
.addCriterion("air_bags", AndroidResearchTrigger.Instance(modLocation(MNames.AIR_BAGS)))
|
||||
.save(serializer, modLocation("android/research_air_bags"), existingFileHelper)
|
||||
|
||||
AdvancementBuilder()
|
||||
.parent(researchAnything)
|
||||
.display(
|
||||
itemStack = ItemStack(Items.ENDER_EYE),
|
||||
title = TranslatableComponent(translation.add("night_vision", "Second Pair of Eyes")),
|
||||
description = TranslatableComponent(translation.add("night_vision.desc", "Research Night Vision as Android, to see in the dark")),
|
||||
)
|
||||
.addCriterion("night_vision", AndroidResearchTrigger.Instance(modLocation(MNames.NIGHT_VISION)))
|
||||
.save(serializer, modLocation("android/research_night_vision"), existingFileHelper)
|
||||
|
||||
val nanobots = AdvancementBuilder()
|
||||
.parent(researchAnything)
|
||||
.display(
|
||||
itemStack = ItemStack(MItems.MATTER_TRANSFORM_MATRIX),
|
||||
title = TranslatableComponent(translation.add("nanobots", "Nanomachines, Son!")),
|
||||
description = TranslatableComponent(translation.add("nanobots.desc", "Research Nanobots as Android, to unlock potent research that come after it")),
|
||||
hidden = true
|
||||
)
|
||||
.addCriterion("nanobots", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS)))
|
||||
.save(serializer, modLocation("android/research_nanobots"), existingFileHelper)
|
||||
|
||||
val regen = AdvancementBuilder()
|
||||
.parent(nanobots)
|
||||
.display(
|
||||
itemStack = ItemStack(Items.GOLDEN_APPLE),
|
||||
title = TranslatableComponent(translation.add("regen", "Field Repair Done Easy")),
|
||||
description = TranslatableComponent(translation.add("regen.desc", "Research Nanobots Regeneration as Android")),
|
||||
)
|
||||
.addCriterion("regen0", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_1)))
|
||||
.save(serializer, modLocation("android/regen"), existingFileHelper)
|
||||
|
||||
AdvancementBuilder()
|
||||
.parent(regen)
|
||||
.display(
|
||||
itemStack = ItemStack(Items.ENCHANTED_GOLDEN_APPLE),
|
||||
title = TranslatableComponent(translation.add("regen_all", "Field Repair Done Effortless")),
|
||||
description = TranslatableComponent(translation.add("regen_all.desc", "Max out Nanobots Regeneration research")),
|
||||
frameType = FrameType.GOAL,
|
||||
)
|
||||
.addCriterion("regen0", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_1)))
|
||||
.addCriterion("regen1", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_2)))
|
||||
.addCriterion("regen2", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_3)))
|
||||
.addCriterion("regen3", AndroidResearchTrigger.Instance(modLocation(MNames.NANOBOTS_REGENERATION_4)))
|
||||
.save(serializer, modLocation("android/regen_all"), existingFileHelper)
|
||||
|
||||
AdvancementBuilder()
|
||||
.parent(researchAnything)
|
||||
.display(
|
||||
itemStack = ItemStack(MItems.ANDROID_STATION),
|
||||
title = TranslatableComponent(translation.add("research_all", "Mecha-agnomination")),
|
||||
description = TranslatableComponent(translation.add("research_all.desc", "Research everything (that don't block any other research)")),
|
||||
frameType = FrameType.CHALLENGE
|
||||
)
|
||||
.also { advancement ->
|
||||
DataGen.researchProvider.generatedView.stream()
|
||||
.filter { it.allBlockedBy.isEmpty() && it.allBlocking.isEmpty() }
|
||||
.forEach {
|
||||
advancement.addCriterion(it.id.toString(), AndroidResearchTrigger.Instance(it))
|
||||
}
|
||||
}
|
||||
.save(serializer, modLocation("android/research_everything"), existingFileHelper)
|
||||
|
||||
val shockwave = AdvancementBuilder()
|
||||
.parent(researchAnything)
|
||||
.display(
|
||||
itemStack = ItemStack(Items.PISTON),
|
||||
title = TranslatableComponent(translation.add("shockwave", "Supersonic Landing")),
|
||||
description = TranslatableComponent(translation.add("shockwave.desc", "Perform a Shockwave upon landing")),
|
||||
)
|
||||
.addCriterion("shockwave", ShockwaveTrigger.Instance)
|
||||
.save(serializer, modLocation("android/shockwave"), existingFileHelper)
|
||||
|
||||
AdvancementBuilder()
|
||||
.parent(shockwave)
|
||||
.display(
|
||||
itemStack = ItemStack(Items.WARDEN_SPAWN_EGG),
|
||||
title = TranslatableComponent(translation.add("shockwave_warden", "Music To Their Ears")),
|
||||
description = TranslatableComponent(translation.add("shockwave_warden.desc", "Hurt Warden using Shockwave ability")),
|
||||
frameType = FrameType.GOAL
|
||||
)
|
||||
.addCriterion("shockwave_warden", ShockwaveDamageMobTrigger.Instance(EntityPredicate.Builder.entity().of(EntityType.WARDEN).build().wrap()))
|
||||
.save(serializer, modLocation("android/shockwave_warden"), existingFileHelper)
|
||||
}
|
@ -4,6 +4,7 @@ import net.minecraft.advancements.Advancement
|
||||
import net.minecraft.advancements.CriterionTriggerInstance
|
||||
import net.minecraft.advancements.DisplayInfo
|
||||
import net.minecraft.advancements.FrameType
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
import net.minecraft.advancements.critereon.InventoryChangeTrigger
|
||||
import net.minecraft.advancements.critereon.ItemPredicate
|
||||
import net.minecraft.network.chat.Component
|
||||
@ -11,6 +12,7 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.tags.TagKey
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.ItemLike
|
||||
import ru.dbotthepony.mc.otm.core.TextComponent
|
||||
|
||||
fun AdvancementBuilder(): Advancement.Builder = Advancement.Builder.advancement()
|
||||
@ -57,3 +59,13 @@ fun predicate(tag: TagKey<Item>): ItemPredicate {
|
||||
fun criterion(tag: TagKey<Item>): CriterionTriggerInstance {
|
||||
return InventoryChangeTrigger.TriggerInstance.hasItems(predicate(tag))
|
||||
}
|
||||
|
||||
fun predicate(item: ItemLike): ItemPredicate {
|
||||
return ItemPredicate.Builder.item().of(item).build()
|
||||
}
|
||||
|
||||
fun criterion(item: ItemLike): CriterionTriggerInstance {
|
||||
return InventoryChangeTrigger.TriggerInstance.hasItems(predicate(item))
|
||||
}
|
||||
|
||||
fun EntityPredicate.wrap(): EntityPredicate.Composite = EntityPredicate.Composite.wrap(this)
|
||||
|
@ -200,8 +200,13 @@ object ServerConfig {
|
||||
val COOLDOWN: Int by specBuilder.comment("In ticks").defineInRange("cooldown", 30, 1)
|
||||
val RADIUS_HORIZONTAL: Double by specBuilder.comment("In meters").defineInRange("radiusHorizontal", 4.0, 0.0)
|
||||
val RADIUS_VERTICAL: Double by specBuilder.comment("In meters").defineInRange("radiusVertical", 1.0, 0.0)
|
||||
|
||||
val RADIUS_HORIZONTAL_WARDEN: Double by specBuilder.comment("In meters, when searching for Warden").defineInRange("radiusHorizontalWarden", 16.0, 0.0)
|
||||
val RADIUS_VERTICAL_WARDEN: Double by specBuilder.comment("In meters, when searching for Warden").defineInRange("radiusVerticalWarden", 6.0, 0.0)
|
||||
|
||||
val BREAK_BLOCKS: Boolean by specBuilder.comment("Break blocks without any blast resistance").define("breakBlocks", true)
|
||||
val DAMAGE: Double by specBuilder.comment("Max potential damage done by shockwave").defineInRange("damage", 12.0, 0.0, Float.MAX_VALUE.toDouble())
|
||||
val WARDEN_DAMAGE_MULT: Double by specBuilder.defineInRange("wardenDamageMultiplier", 4.0, 0.0, Float.MAX_VALUE.toDouble())
|
||||
val ENERGY_COST by specBuilder.defineImpreciseFraction("energyCost", ImpreciseFraction(2048), ImpreciseFraction.ZERO)
|
||||
|
||||
init {
|
||||
|
@ -7,6 +7,7 @@ import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraftforge.common.util.INBTSerializable
|
||||
@ -25,6 +26,7 @@ import ru.dbotthepony.mc.otm.core.registryName
|
||||
import ru.dbotthepony.mc.otm.core.set
|
||||
import ru.dbotthepony.mc.otm.network.FieldSynchronizer
|
||||
import ru.dbotthepony.mc.otm.registry.MRegistry
|
||||
import ru.dbotthepony.mc.otm.triggers.AndroidResearchTrigger
|
||||
import java.io.DataInputStream
|
||||
import java.io.InputStream
|
||||
import kotlin.math.absoluteValue
|
||||
@ -273,6 +275,11 @@ class AndroidResearch(val type: AndroidResearchType, val capability: MatteryPlay
|
||||
if (force || canResearch && consumeResearchCost(false)) {
|
||||
onResearched()
|
||||
isResearched = true
|
||||
|
||||
if (ply is ServerPlayer) {
|
||||
AndroidResearchTrigger.trigger(ply as ServerPlayer, this.type)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import net.minecraft.data.CachedOutput
|
||||
import net.minecraft.data.DataGenerator
|
||||
import net.minecraft.data.DataProvider
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import java.util.Collections
|
||||
import java.util.LinkedList
|
||||
import java.util.function.Consumer
|
||||
|
||||
@ -14,6 +15,9 @@ open class AndroidResearchDataProvider(protected val dataGenerator: DataGenerato
|
||||
|
||||
protected val callbacks = LinkedList<(Consumer<AndroidResearchType>) -> Unit>()
|
||||
|
||||
private val generated = LinkedList<AndroidResearchType>()
|
||||
val generatedView: List<AndroidResearchType> = Collections.unmodifiableList(generated)
|
||||
|
||||
/**
|
||||
* override this
|
||||
*/
|
||||
@ -49,6 +53,7 @@ open class AndroidResearchDataProvider(protected val dataGenerator: DataGenerato
|
||||
|
||||
for (value in added) {
|
||||
value.validate()
|
||||
generated.add(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,10 +2,14 @@ package ru.dbotthepony.mc.otm.android.feature
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import it.unimi.dsi.fastutil.objects.ReferenceArraySet
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.monster.warden.Warden
|
||||
import net.minecraftforge.network.NetworkEvent
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.ServerConfig
|
||||
@ -33,6 +37,8 @@ import ru.dbotthepony.mc.otm.network.sender
|
||||
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
|
||||
import ru.dbotthepony.mc.otm.registry.MNames
|
||||
import ru.dbotthepony.mc.otm.registry.ShockwaveDamageSource
|
||||
import ru.dbotthepony.mc.otm.triggers.ShockwaveDamageMobTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.ShockwaveTrigger
|
||||
import java.util.function.Supplier
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.roundToInt
|
||||
@ -77,6 +83,10 @@ class ShockwaveFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF
|
||||
|
||||
cooldown = ServerConfig.Shockwave.COOLDOWN
|
||||
|
||||
if (ply is ServerPlayer) {
|
||||
ShockwaveTrigger.trigger(ply as ServerPlayer)
|
||||
}
|
||||
|
||||
// TODO: raycasting
|
||||
val entities = ply.level.getEntitiesInEllipsoid(
|
||||
ply.position,
|
||||
@ -84,17 +94,47 @@ class ShockwaveFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF
|
||||
except = ply,
|
||||
) { (it !is LivingEntity || !it.isSpectator && it.isAlive) }
|
||||
|
||||
val wardens = ply.level.getEntitiesInEllipsoid(
|
||||
Warden::class.java,
|
||||
ply.position,
|
||||
Vector(ServerConfig.Shockwave.RADIUS_HORIZONTAL_WARDEN, ServerConfig.Shockwave.RADIUS_VERTICAL_WARDEN, ServerConfig.Shockwave.RADIUS_HORIZONTAL_WARDEN),
|
||||
) { true }
|
||||
|
||||
val seen = ReferenceArraySet<Entity>()
|
||||
|
||||
for ((entity, distanceMultiplier) in wardens) {
|
||||
seen.add(entity)
|
||||
val multiplier = (1.0 - distanceMultiplier).pow(0.5)
|
||||
|
||||
val source = ShockwaveDamageSource(ply)
|
||||
val damage = multiplier.toFloat() * ServerConfig.Shockwave.DAMAGE.toFloat() * ServerConfig.Shockwave.WARDEN_DAMAGE_MULT.toFloat()
|
||||
entity.hurt(source, damage)
|
||||
entity.deltaMovement += (entity.position - ply.position).normalize() * (multiplier * 3.0)
|
||||
|
||||
if (ply is ServerPlayer) {
|
||||
ShockwaveDamageMobTrigger.trigger(ply as ServerPlayer, entity, source, damage)
|
||||
}
|
||||
}
|
||||
|
||||
for ((entity, distanceMultiplier) in entities) {
|
||||
if (seen.add(entity)) {
|
||||
val multiplier = (1.0 - distanceMultiplier).pow(1.25)
|
||||
|
||||
// don't hurt items, arrows, etc etc
|
||||
if (entity is LivingEntity) {
|
||||
entity.hurt(ShockwaveDamageSource(ply), multiplier.toFloat() * ServerConfig.Shockwave.DAMAGE.toFloat())
|
||||
val source = ShockwaveDamageSource(ply)
|
||||
val damage = multiplier.toFloat() * ServerConfig.Shockwave.DAMAGE.toFloat()
|
||||
entity.hurt(source, damage)
|
||||
entity.deltaMovement += (entity.position - ply.position).normalize() * (multiplier * 3.0)
|
||||
|
||||
if (ply is ServerPlayer) {
|
||||
ShockwaveDamageMobTrigger.trigger(ply as ServerPlayer, entity, source, damage)
|
||||
}
|
||||
} else {
|
||||
entity.deltaMovement += (entity.position - ply.position).normalize() * (multiplier * 6.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ServerConfig.Shockwave.BREAK_BLOCKS) {
|
||||
val rounded = ply.position.roundToIntVector()
|
||||
|
@ -32,11 +32,9 @@ import net.minecraftforge.event.entity.living.LivingDropsEvent
|
||||
import net.minecraftforge.event.entity.living.LivingHurtEvent
|
||||
import net.minecraftforge.event.entity.living.LivingSpawnEvent
|
||||
import net.minecraftforge.event.entity.living.MobEffectEvent
|
||||
import net.minecraftforge.event.entity.player.EntityItemPickupEvent
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent
|
||||
import net.minecraftforge.eventbus.api.Event
|
||||
import net.minecraftforge.registries.ForgeRegistries
|
||||
import org.apache.commons.lang3.mutable.MutableInt
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.mc.otm.*
|
||||
import ru.dbotthepony.mc.otm.android.AndroidFeature
|
||||
@ -51,6 +49,11 @@ import ru.dbotthepony.mc.otm.menu.ExoSuitInventoryMenu
|
||||
import ru.dbotthepony.mc.otm.network.*
|
||||
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
|
||||
import ru.dbotthepony.mc.otm.registry.MRegistry
|
||||
import ru.dbotthepony.mc.otm.triggers.AndroidResearchTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.BecomeAndroidDeathTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.BecomeAndroidSleepTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.BecomeAndroidTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.BecomeHumaneTrigger
|
||||
import java.util.*
|
||||
import java.util.stream.Stream
|
||||
import kotlin.collections.ArrayDeque
|
||||
@ -245,6 +248,10 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
deathLog.clear()
|
||||
androidEnergy.batteryLevel = ServerConfig.ANDROID_MAX_ENERGY
|
||||
androidEnergy.maxBatteryLevel = ServerConfig.ANDROID_MAX_ENERGY
|
||||
|
||||
if (ply is ServerPlayer) {
|
||||
BecomeAndroidTrigger.trigger(ply)
|
||||
}
|
||||
}
|
||||
|
||||
fun becomeAndroidAndKill() {
|
||||
@ -265,6 +272,10 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
androidEnergy.batteryLevel = ImpreciseFraction.ZERO
|
||||
androidEnergy.maxBatteryLevel = ServerConfig.ANDROID_MAX_ENERGY
|
||||
dropBattery()
|
||||
|
||||
if (ply is ServerPlayer) {
|
||||
BecomeHumaneTrigger.trigger(ply)
|
||||
}
|
||||
}
|
||||
|
||||
fun becomeHumaneAndKill() {
|
||||
@ -524,6 +535,20 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
val instance = AndroidResearch(research, this)
|
||||
instance.deserializeNBT(researchTag)
|
||||
this.research[research] = instance
|
||||
|
||||
if (instance.isResearched && ply is ServerPlayer) {
|
||||
onceServer(20) {
|
||||
if (!ply.hasDisconnected())
|
||||
AndroidResearchTrigger.trigger(ply, instance.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isAndroid && ply is ServerPlayer) {
|
||||
onceServer(20) {
|
||||
if (!ply.hasDisconnected())
|
||||
BecomeAndroidTrigger.trigger(ply)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -590,7 +615,11 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
if (ply.isSleeping && ply.sleepTimer > SLEEP_TICKS_LIMIT) {
|
||||
becomeAndroid()
|
||||
shouldPlaySound = true
|
||||
(ply as? ServerPlayer)?.displayClientMessage(TranslatableComponent("otm.pill.message_finish").withStyle(ChatFormatting.DARK_RED), false)
|
||||
|
||||
if (ply is ServerPlayer) {
|
||||
ply.displayClientMessage(TranslatableComponent("otm.pill.message_finish").withStyle(ChatFormatting.DARK_RED), false)
|
||||
BecomeAndroidSleepTrigger.trigger(ply)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -839,7 +868,13 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
|
||||
if (original.willBecomeAndroid && event.isWasDeath) {
|
||||
original.becomeAndroid()
|
||||
(event.entity as? ServerPlayer)?.displayClientMessage(TranslatableComponent("otm.pill.message_finish").withStyle(ChatFormatting.DARK_RED), false)
|
||||
|
||||
val ply = event.entity
|
||||
|
||||
if (ply is ServerPlayer) {
|
||||
ply.displayClientMessage(TranslatableComponent("otm.pill.message_finish").withStyle(ChatFormatting.DARK_RED), false)
|
||||
BecomeAndroidDeathTrigger.trigger(ply)
|
||||
}
|
||||
}
|
||||
|
||||
it.deserializeNBT(original.serializeNBT())
|
||||
|
@ -3,6 +3,7 @@ package ru.dbotthepony.mc.otm.core
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.phys.AABB
|
||||
import java.util.LinkedList
|
||||
import java.util.function.Predicate
|
||||
import kotlin.math.pow
|
||||
|
||||
@ -20,7 +21,46 @@ fun Level.getEntitiesInEllipsoid(pos: Vector, dimensions: Vector, except: Entity
|
||||
pos.z + dimensions.z,
|
||||
), predicate)
|
||||
|
||||
val result = ArrayList<Pair<Entity, Double>>()
|
||||
val result = LinkedList<Pair<Entity, Double>>()
|
||||
|
||||
for (it in entities) {
|
||||
val a = (it.position - pos).let { vec ->
|
||||
vec.x.pow(2.0) / dimensions.x.pow(2.0) +
|
||||
vec.y.pow(2.0) / dimensions.y.pow(2.0) +
|
||||
vec.z.pow(2.0) / dimensions.z.pow(2.0)
|
||||
}
|
||||
|
||||
val b = it.boundingBox.center.let { vec ->
|
||||
(vec.x - pos.x).pow(2.0) / dimensions.x.pow(2.0) +
|
||||
(vec.y - pos.y).pow(2.0) / dimensions.y.pow(2.0) +
|
||||
(vec.z - pos.z).pow(2.0) / dimensions.z.pow(2.0)
|
||||
}
|
||||
|
||||
val min = a.coerceAtMost(b)
|
||||
|
||||
if (min <= 1.0) {
|
||||
result.add(it to min)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Pair of entity and distance fraction to center of ellipsoid
|
||||
*/
|
||||
fun <T : Entity> Level.getEntitiesInEllipsoid(type: Class<out T>, pos: Vector, dimensions: Vector, predicate: Predicate<in Entity>): List<Pair<T, Double>> {
|
||||
val entities = getEntitiesOfClass(type, AABB(
|
||||
pos.x - dimensions.x,
|
||||
pos.y - dimensions.y,
|
||||
pos.z - dimensions.z,
|
||||
|
||||
pos.x + dimensions.x,
|
||||
pos.y + dimensions.y,
|
||||
pos.z + dimensions.z,
|
||||
), predicate)
|
||||
|
||||
val result = LinkedList<Pair<T, Double>>()
|
||||
|
||||
for (it in entities) {
|
||||
val a = (it.position - pos).let { vec ->
|
||||
@ -65,3 +105,10 @@ fun Level.getEntitiesInSphere(pos: Vector, radius: Double, except: Entity?, pred
|
||||
fun Level.getEntitiesInSphere(pos: Vector, radius: Double, predicate: Predicate<in Entity>): List<Pair<Entity, Double>> {
|
||||
return getEntitiesInEllipsoid(pos, Vector(radius, radius, radius), null, predicate)
|
||||
}
|
||||
|
||||
/**
|
||||
* Pair of entity and distance fraction to center of ellipsoid
|
||||
*/
|
||||
fun Level.getEntitiesInSphere(type: Class<out Entity>, pos: Vector, radius: Double, predicate: Predicate<in Entity>): List<Pair<Entity, Double>> {
|
||||
return getEntitiesInEllipsoid(type, pos, Vector(radius, radius, radius), predicate)
|
||||
}
|
||||
|
@ -44,7 +44,14 @@ import ru.dbotthepony.mc.otm.registry.objects.ColoredDecorativeBlock
|
||||
import ru.dbotthepony.mc.otm.registry.objects.CrateProperties
|
||||
import ru.dbotthepony.mc.otm.registry.objects.DecorativeBlock
|
||||
import ru.dbotthepony.mc.otm.registry.objects.StripedColoredDecorativeBlock
|
||||
import ru.dbotthepony.mc.otm.triggers.AndroidResearchTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.BecomeAndroidDeathTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.BecomeAndroidSleepTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.BecomeAndroidTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.BecomeHumaneTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.BlackHoleTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.ShockwaveDamageMobTrigger
|
||||
import ru.dbotthepony.mc.otm.triggers.ShockwaveTrigger
|
||||
import java.util.function.Supplier
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
@ -261,6 +268,13 @@ object MRegistry {
|
||||
private fun initializeCommon(event: FMLCommonSetupEvent) {
|
||||
event.enqueueWork {
|
||||
CriteriaTriggers.register(BlackHoleTrigger)
|
||||
CriteriaTriggers.register(BecomeAndroidTrigger)
|
||||
CriteriaTriggers.register(BecomeAndroidDeathTrigger)
|
||||
CriteriaTriggers.register(BecomeAndroidSleepTrigger)
|
||||
CriteriaTriggers.register(BecomeHumaneTrigger)
|
||||
CriteriaTriggers.register(AndroidResearchTrigger)
|
||||
CriteriaTriggers.register(ShockwaveDamageMobTrigger)
|
||||
CriteriaTriggers.register(ShockwaveTrigger)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,54 @@
|
||||
package ru.dbotthepony.mc.otm.triggers
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonPrimitive
|
||||
import net.minecraft.advancements.critereon.AbstractCriterionTriggerInstance
|
||||
import net.minecraft.advancements.critereon.DeserializationContext
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
import net.minecraft.advancements.critereon.SerializationContext
|
||||
import net.minecraft.advancements.critereon.SimpleCriterionTrigger
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.android.AndroidResearchType
|
||||
import ru.dbotthepony.mc.otm.core.set
|
||||
import java.util.function.Predicate
|
||||
|
||||
object AndroidResearchTrigger : SimpleCriterionTrigger<AndroidResearchTrigger.Instance>() {
|
||||
val ID = ResourceLocation(OverdriveThatMatters.MOD_ID, "android_research")
|
||||
|
||||
override fun getId(): ResourceLocation {
|
||||
return ID
|
||||
}
|
||||
|
||||
override fun createInstance(
|
||||
p_66248_: JsonObject,
|
||||
p_66249_: EntityPredicate.Composite,
|
||||
p_66250_: DeserializationContext
|
||||
): Instance {
|
||||
return Instance(
|
||||
p_66248_["research"]?.asString?.let(::ResourceLocation)
|
||||
)
|
||||
}
|
||||
|
||||
fun trigger(player: ServerPlayer, research: AndroidResearchType) {
|
||||
trigger(player) {
|
||||
it.test(research)
|
||||
}
|
||||
}
|
||||
|
||||
class Instance(val research: ResourceLocation?) : AbstractCriterionTriggerInstance(ID, EntityPredicate.Composite.ANY), Predicate<AndroidResearchType> {
|
||||
constructor(research: AndroidResearchType) : this(research.id)
|
||||
|
||||
override fun test(t: AndroidResearchType): Boolean {
|
||||
return research == null || t.id == research
|
||||
}
|
||||
|
||||
override fun serializeToJson(p_16979_: SerializationContext): JsonObject {
|
||||
return super.serializeToJson(p_16979_).also {
|
||||
if (research != null)
|
||||
it["research"] = JsonPrimitive(research.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
package ru.dbotthepony.mc.otm.triggers
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import net.minecraft.advancements.critereon.AbstractCriterionTriggerInstance
|
||||
import net.minecraft.advancements.critereon.DeserializationContext
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
import net.minecraft.advancements.critereon.SimpleCriterionTrigger
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
|
||||
object BecomeAndroidTrigger : SimpleCriterionTrigger<BecomeAndroidTrigger.Instance>() {
|
||||
val ID = ResourceLocation(OverdriveThatMatters.MOD_ID, "become_android")
|
||||
|
||||
override fun getId(): ResourceLocation {
|
||||
return ID
|
||||
}
|
||||
|
||||
override fun createInstance(
|
||||
p_66248_: JsonObject,
|
||||
p_66249_: EntityPredicate.Composite,
|
||||
p_66250_: DeserializationContext
|
||||
): Instance {
|
||||
return Instance
|
||||
}
|
||||
|
||||
fun trigger(player: ServerPlayer) {
|
||||
trigger(player) { true }
|
||||
}
|
||||
|
||||
object Instance : AbstractCriterionTriggerInstance(ID, EntityPredicate.Composite.ANY)
|
||||
}
|
||||
|
||||
object BecomeAndroidSleepTrigger : SimpleCriterionTrigger<BecomeAndroidSleepTrigger.Instance>() {
|
||||
val ID = ResourceLocation(OverdriveThatMatters.MOD_ID, "become_android_sleep")
|
||||
|
||||
override fun getId(): ResourceLocation {
|
||||
return ID
|
||||
}
|
||||
|
||||
override fun createInstance(
|
||||
p_66248_: JsonObject,
|
||||
p_66249_: EntityPredicate.Composite,
|
||||
p_66250_: DeserializationContext
|
||||
): Instance {
|
||||
return Instance
|
||||
}
|
||||
|
||||
fun trigger(player: ServerPlayer) {
|
||||
trigger(player) { true }
|
||||
}
|
||||
|
||||
object Instance : AbstractCriterionTriggerInstance(ID, EntityPredicate.Composite.ANY)
|
||||
}
|
||||
|
||||
object BecomeAndroidDeathTrigger : SimpleCriterionTrigger<BecomeAndroidDeathTrigger.Instance>() {
|
||||
val ID = ResourceLocation(OverdriveThatMatters.MOD_ID, "become_android_death")
|
||||
|
||||
override fun getId(): ResourceLocation {
|
||||
return ID
|
||||
}
|
||||
|
||||
override fun createInstance(
|
||||
p_66248_: JsonObject,
|
||||
p_66249_: EntityPredicate.Composite,
|
||||
p_66250_: DeserializationContext
|
||||
): Instance {
|
||||
return Instance
|
||||
}
|
||||
|
||||
fun trigger(player: ServerPlayer) {
|
||||
trigger(player) { true }
|
||||
}
|
||||
|
||||
object Instance : AbstractCriterionTriggerInstance(ID, EntityPredicate.Composite.ANY)
|
||||
}
|
||||
|
||||
object BecomeHumaneTrigger : SimpleCriterionTrigger<BecomeHumaneTrigger.Instance>() {
|
||||
val ID = ResourceLocation(OverdriveThatMatters.MOD_ID, "become_humane")
|
||||
|
||||
override fun getId(): ResourceLocation {
|
||||
return ID
|
||||
}
|
||||
|
||||
override fun createInstance(
|
||||
p_66248_: JsonObject,
|
||||
p_66249_: EntityPredicate.Composite,
|
||||
p_66250_: DeserializationContext
|
||||
): Instance {
|
||||
return Instance
|
||||
}
|
||||
|
||||
fun trigger(player: ServerPlayer) {
|
||||
trigger(player) { true }
|
||||
}
|
||||
|
||||
object Instance : AbstractCriterionTriggerInstance(ID, EntityPredicate.Composite.ANY)
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package ru.dbotthepony.mc.otm.triggers
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonSyntaxException
|
||||
import net.minecraft.advancements.critereon.AbstractCriterionTriggerInstance
|
||||
import net.minecraft.advancements.critereon.DamagePredicate
|
||||
import net.minecraft.advancements.critereon.DamageSourcePredicate
|
||||
import net.minecraft.advancements.critereon.DeserializationContext
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
import net.minecraft.advancements.critereon.MinMaxBounds
|
||||
import net.minecraft.advancements.critereon.SerializationContext
|
||||
import net.minecraft.advancements.critereon.SimpleCriterionTrigger
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.damagesource.DamageSource
|
||||
import net.minecraft.world.entity.Entity
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.core.set
|
||||
|
||||
object ShockwaveDamageMobTrigger: SimpleCriterionTrigger<ShockwaveDamageMobTrigger.Instance>() {
|
||||
val ID = ResourceLocation(OverdriveThatMatters.MOD_ID, "shockwave_damage_mob")
|
||||
|
||||
override fun getId(): ResourceLocation {
|
||||
return ID
|
||||
}
|
||||
|
||||
override fun createInstance(
|
||||
p_66248_: JsonObject,
|
||||
p_66249_: EntityPredicate.Composite,
|
||||
p_66250_: DeserializationContext
|
||||
): Instance {
|
||||
return Instance(
|
||||
EntityPredicate.Composite.fromJson(p_66248_, "entity_predicate", p_66250_),
|
||||
(p_66248_["damage"] as? JsonObject)?.let(DamagePredicate::fromJson) ?: DamagePredicate.ANY
|
||||
)
|
||||
}
|
||||
|
||||
fun trigger(player: ServerPlayer, entity: Entity, damageSource: DamageSource, damage: Float) {
|
||||
val context = EntityPredicate.createContext(player, entity)
|
||||
|
||||
trigger(player) {
|
||||
it.predicate.matches(context) && it.damagePredicate.matches(player, damageSource, damage, damage, false)
|
||||
}
|
||||
}
|
||||
|
||||
class Instance(
|
||||
val predicate: EntityPredicate.Composite = EntityPredicate.Composite.ANY,
|
||||
val damagePredicate: DamagePredicate = DamagePredicate(
|
||||
MinMaxBounds.Doubles.atLeast(1.0),
|
||||
MinMaxBounds.Doubles.atLeast(1.0),
|
||||
EntityPredicate.ANY,
|
||||
null,
|
||||
DamageSourcePredicate.ANY
|
||||
)
|
||||
) : AbstractCriterionTriggerInstance(ID, EntityPredicate.Composite.ANY) {
|
||||
override fun serializeToJson(p_16979_: SerializationContext): JsonObject {
|
||||
return super.serializeToJson(p_16979_).also {
|
||||
it["entity_predicate"] = predicate.toJson(p_16979_)
|
||||
it["damage"] = damagePredicate.serializeToJson()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package ru.dbotthepony.mc.otm.triggers
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import net.minecraft.advancements.critereon.AbstractCriterionTriggerInstance
|
||||
import net.minecraft.advancements.critereon.DeserializationContext
|
||||
import net.minecraft.advancements.critereon.EntityPredicate.Composite
|
||||
import net.minecraft.advancements.critereon.SimpleCriterionTrigger
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
|
||||
object ShockwaveTrigger : SimpleCriterionTrigger<ShockwaveTrigger.Instance>() {
|
||||
val ID = ResourceLocation(OverdriveThatMatters.MOD_ID, "shockwave")
|
||||
|
||||
override fun getId(): ResourceLocation {
|
||||
return ID
|
||||
}
|
||||
|
||||
override fun createInstance(
|
||||
p_66248_: JsonObject,
|
||||
p_66249_: Composite,
|
||||
p_66250_: DeserializationContext
|
||||
): Instance {
|
||||
return Instance
|
||||
}
|
||||
|
||||
fun trigger(player: ServerPlayer) {
|
||||
trigger(player) { true }
|
||||
}
|
||||
|
||||
object Instance : AbstractCriterionTriggerInstance(ID, Composite.ANY)
|
||||
}
|
Loading…
Reference in New Issue
Block a user