forked from mirrors/cobblemon
Compare commits
68
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9da67aa05 | ||
|
|
5e6091c782 | ||
|
|
5a2e5479e0 | ||
|
|
4e1b82917b | ||
|
|
3b1d257241 | ||
|
|
0b8f916648 | ||
|
|
5ad7d5406a | ||
|
|
6ec008ee83 | ||
|
|
f4d2226ec2 | ||
|
|
0fc5d5e9d7 | ||
|
|
972c0f6430 | ||
|
|
86db95a7dc | ||
|
|
be95b79e4d | ||
|
|
5753443ab2 | ||
|
|
c6b7186032 | ||
|
|
32f3be2687 | ||
|
|
9012d78806 | ||
|
|
fffdfb7654 | ||
|
|
b314733f0b | ||
|
|
d5aa07fe91 | ||
|
|
27bedc2d2c | ||
|
|
86744c23a5 | ||
|
|
8d1a64136f | ||
|
|
bc550dd32c | ||
|
|
3009af8c42 | ||
|
|
bfd34eb621 | ||
|
|
2dc2c96176 | ||
|
|
df4db17cfd | ||
|
|
45bec488f1 | ||
|
|
9287374504 | ||
|
|
90c5180712 | ||
|
|
f2a36cd74a | ||
|
|
158aa05f24 | ||
|
|
8924d0fe0f | ||
|
|
d510eaa462 | ||
|
|
8b63057d9d | ||
|
|
d572b3c505 | ||
|
|
8edc60224a | ||
|
|
a634c4f046 | ||
|
|
7139d4708b | ||
|
|
50e99736a3 | ||
|
|
68c4acf0eb | ||
|
|
5b5e7109f5 | ||
|
|
37596523db | ||
|
|
eb80c20dbf | ||
|
|
7ab3951613 | ||
|
|
e6d51c4d56 | ||
|
|
3813ec3c92 | ||
|
|
b9364304ca | ||
|
|
9be212d2b8 | ||
|
|
2559257b3a | ||
|
|
8236c6fb11 | ||
|
|
2041d43db4 | ||
|
|
a1687e8304 | ||
|
|
94d92b6fc0 | ||
|
|
3aa95b9339 | ||
|
|
4e97f70801 | ||
|
|
404ca565f5 | ||
|
|
93db0e1cda | ||
|
|
4a4d292228 | ||
|
|
0fef9eec3d | ||
|
|
5f3dc395ec | ||
|
|
1bf9d36dbd | ||
|
|
b19c5ed125 | ||
|
|
e3cca0d9cf | ||
|
|
1aa55f8199 | ||
|
|
4c16b2ce2e | ||
|
|
a0b263e392 |
@@ -36,6 +36,7 @@ common/src/main/resources/assets/cobblemon/showdown
|
||||
*/generated/resources/*
|
||||
/fabric/src/generated/resources/cobblemon-common.accesswidener
|
||||
/.ignored/
|
||||
common/.fabric
|
||||
|
||||
# MacOS
|
||||
.DS_Store
|
||||
+38
-3
@@ -2,10 +2,45 @@
|
||||
|
||||
## [1.5.1](#1-5-1)
|
||||
|
||||
### Fixes
|
||||
-Fixed a bug in which adding organic material to the fossil tank via right click was adding the full count of the stack currently in hand
|
||||
### Additions
|
||||
- Added unique send out particles for Cherish, Dream, Beast, and Ancient Origin balls.
|
||||
- Made Wooloo and Dubwool dye-able like sheep
|
||||
|
||||
## [1.5.0 - The Ruins and Revival Update (May Xth, 2024)](#1-5-0)
|
||||
### Changes
|
||||
- Sounds for Relic Coin Sacks have been correctly renamed. Relic Coin Pouches received new sounds for breaking and placing.
|
||||
- Readjusted Petilil portraits
|
||||
- Changed "dimensions" spawn condition to check with dimension IDs instead of effects, so custom dimension IDs can be used.
|
||||
|
||||
### Fixes
|
||||
- Fixed a bug in which adding organic material to the fossil tank via right click was adding the full count of the stack currently in hand
|
||||
- Fixed a niche issue where some properties of entities were not initialized correctly, causing Pokémon that appeared to be level 1 until you battle them.
|
||||
- Fixed Fossilized Drake being missing from the Fossils item tag.
|
||||
- Fixed Gilded Chest block entity not being cleared on block break
|
||||
- Fixed sherd brokenness on Forge/Supplementaries incompat
|
||||
- Fixed Fossil Compartment crash with Jade / WAILA forks
|
||||
- Fixed PCStore#resize not allowing PC boxes size reduction.
|
||||
- Fixed pasture block PC lookups when the player is offline.
|
||||
- Fixed an untranslated battle message that occurs when using a move that just ran out of PP (e.g. Fire Blast that just got spited mid-turn).
|
||||
- Fixed held items being eaten even when the held item evolutions are already unlocked.
|
||||
- Fixed Hisuian Decidueye not being Grass/Fighting
|
||||
- Fixed both Decidueye forms learning both Triple Arrows and Spirit Shackle
|
||||
- Fixed Pineco being unable to evolve into Shulker Forretress
|
||||
- Fixed Kabutops T-posing when underwater. It still does not have proper swimming animations yet though.
|
||||
- Fixed Pidgey's missing walk animation.
|
||||
- Fixed recoil evo condition.
|
||||
- Fixed issue where poser debug tools didnt work on JSON posers
|
||||
- Fixed issue where gilded chests dont close when going far away
|
||||
|
||||
|
||||
### Developer
|
||||
- Changed SpawnAction#complete to return a nullable generic R (the spawn action result) instead of a boolean. More information this way.
|
||||
- Added an event when a fossil is revived, with or without a player.
|
||||
|
||||
### Data Pack & Resource Pack Creators
|
||||
- Added support for MoLang conditions for quirks and poses.
|
||||
- Changed the AttackDefenceRatio requirement to StatCompare and StatEqual.
|
||||
|
||||
## [1.5.0 - The Ruins and Revival Update (May 12th, 2024)](#1-5-0)
|
||||
#### "You're telling me that Mojang has added archaeology to the game? Hmm... that gives me an idea."
|
||||
|
||||
### Additions
|
||||
|
||||
@@ -43,7 +43,6 @@ dependencies {
|
||||
modCompileOnly(libs.bundles.fabric.integrations.compileOnly) {
|
||||
isTransitive = false
|
||||
}
|
||||
modImplementation(libs.sbl.fabric)
|
||||
// Flywheel has no common dep so just pick one and don't use any platform specific code in common
|
||||
// modCompileOnly(libs.flywheelFabric)
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common;
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import net.minecraft.entity.ai.brain.Brain;
|
||||
import net.minecraft.entity.ai.brain.MemoryModuleType;
|
||||
import net.minecraft.entity.ai.brain.sensor.Sensor;
|
||||
import net.minecraft.entity.ai.brain.sensor.SensorType;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class GenericsCheatClass {
|
||||
// For some reason, doing this in the PokemonEntity class in Kotlin gives confusing generic errors I could not resolve.
|
||||
public static Brain.Profile<PokemonEntity> createPokemonBrain(Collection<MemoryModuleType<?>> memories, Collection<SensorType<? extends Sensor<? super PokemonEntity>>> sensors) {
|
||||
return Brain.createProfile(memories, sensors);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,6 @@ import com.cobblemon.mod.common.pokemon.properties.HiddenAbilityPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.tags.PokemonFlagProperty
|
||||
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
|
||||
import com.cobblemon.mod.common.sherds.CobblemonSherds
|
||||
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
|
||||
import com.cobblemon.mod.common.trade.TradeManager
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
@@ -235,7 +234,7 @@ object Cobblemon {
|
||||
val player = event.player
|
||||
val block = player.world.getBlockState(event.pos).block
|
||||
player.party().forEach { pokemon ->
|
||||
pokemon.evolutions
|
||||
pokemon.lockedEvolutions
|
||||
.filterIsInstance<BlockClickEvolution>()
|
||||
.forEach { evolution ->
|
||||
evolution.attemptEvolution(pokemon, BlockClickEvolution.BlockInteractionContext(block, player.world))
|
||||
@@ -416,7 +415,6 @@ object Cobblemon {
|
||||
).ifSuccessful { it.mute = true }
|
||||
}
|
||||
|
||||
CobblemonSherds.registerSherds()
|
||||
}
|
||||
|
||||
fun getLevel(dimension: RegistryKey<World>): World? {
|
||||
|
||||
@@ -12,9 +12,7 @@ import net.minecraft.entity.ai.brain.Activity
|
||||
|
||||
object CobblemonActivities {
|
||||
val activities = mutableListOf<Activity>()
|
||||
val BATTLING_ACTIVITY = Activity("pokemon_battle")
|
||||
val POKEMON_SLEEPING_ACTIVITY = Activity("pokemon_sleeping")
|
||||
val POKEMON_COMBAT_ACTIVITY = Activity("pokemon_combat")
|
||||
val BATTLING_ACTIVITY = Activity("pokemon_battling")
|
||||
|
||||
fun register(activity: Activity): Activity {
|
||||
activities.add(activity)
|
||||
|
||||
@@ -8,16 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.block.entity.BerryBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.HealingMachineBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.PCBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.PokemonPastureBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.FossilAnalyzerBlockEntity
|
||||
import com.cobblemon.mod.common.block.entity.FossilMultiblockEntity
|
||||
import com.cobblemon.mod.common.block.entity.RestorationTankBlockEntity
|
||||
import com.cobblemon.mod.common.block.multiblock.FossilMultiblockBuilder
|
||||
import com.cobblemon.mod.common.block.entity.*
|
||||
import com.cobblemon.mod.common.block.entity.DisplayCaseBlockEntity
|
||||
import com.cobblemon.mod.common.block.multiblock.FossilMultiblockBuilder
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import net.minecraft.block.entity.BlockEntityType
|
||||
import net.minecraft.registry.Registries
|
||||
@@ -36,6 +28,9 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
|
||||
@JvmField
|
||||
val PC: BlockEntityType<PCBlockEntity> = this.create("pc", BlockEntityType.Builder.create(::PCBlockEntity, CobblemonBlocks.PC).build(null))
|
||||
|
||||
@JvmField
|
||||
val STADIUM: BlockEntityType<StadiumBlockEntity> = this.create("stadium_terminal", BlockEntityType.Builder.create(::StadiumBlockEntity, CobblemonBlocks.STADIUM).build(null))
|
||||
|
||||
@JvmField
|
||||
val BERRY = this.create("berry", BlockEntityType.Builder.create(::BerryBlockEntity, *CobblemonBlocks.berries().values.toTypedArray()).build(null))
|
||||
|
||||
|
||||
@@ -11,22 +11,14 @@ package com.cobblemon.mod.common
|
||||
import com.cobblemon.mod.common.api.apricorn.Apricorn
|
||||
import com.cobblemon.mod.common.block.*
|
||||
import com.cobblemon.mod.common.block.MintBlock.MintType
|
||||
import com.cobblemon.mod.common.block.FossilAnalyzerBlock
|
||||
import com.cobblemon.mod.common.block.MonitorBlock
|
||||
import com.cobblemon.mod.common.block.RestorationTankBlock
|
||||
import com.cobblemon.mod.common.mixin.invoker.DoorBlockInvoker
|
||||
import com.cobblemon.mod.common.mixin.invoker.PressurePlateBlockInvoker
|
||||
import com.cobblemon.mod.common.mixin.invoker.StairsBlockInvoker
|
||||
import com.cobblemon.mod.common.mixin.invoker.TrapdoorBlockInvoker
|
||||
import com.cobblemon.mod.common.mixin.invoker.*
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.block.BerryBlock
|
||||
import com.cobblemon.mod.common.block.chest.GildedChestBlock
|
||||
import com.cobblemon.mod.common.block.sign.CobblemonHangingSignBlock
|
||||
import com.cobblemon.mod.common.block.sign.CobblemonSignBlock
|
||||
import com.cobblemon.mod.common.block.sign.CobblemonWallHangingSignBlock
|
||||
import com.cobblemon.mod.common.block.sign.CobblemonWallSignBlock
|
||||
import com.cobblemon.mod.common.mixin.invoker.*
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.block.*
|
||||
import net.minecraft.block.enums.Instrument
|
||||
import net.minecraft.block.piston.PistonBehavior
|
||||
@@ -234,7 +226,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
"relic_coin_pouch",
|
||||
CoinPouchBlock(
|
||||
AbstractBlock.Settings.create()
|
||||
.sounds(CobblemonSounds.COIN_POUCH_SOUNDS)
|
||||
.sounds(CobblemonSounds.RELIC_COIN_POUCH_SOUNDS)
|
||||
.pistonBehavior(PistonBehavior.DESTROY)
|
||||
.strength(0.4f)
|
||||
.nonOpaque(), true
|
||||
@@ -245,7 +237,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
"relic_coin_sack",
|
||||
CoinPouchBlock(
|
||||
AbstractBlock.Settings.create()
|
||||
.sounds(CobblemonSounds.COIN_POUCH_SOUNDS)
|
||||
.sounds(CobblemonSounds.RELIC_COIN_SACK_SOUNDS)
|
||||
.pistonBehavior(PistonBehavior.DESTROY)
|
||||
.strength(0.4f), false
|
||||
))
|
||||
@@ -388,6 +380,19 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val STADIUM = create(
|
||||
"stadium_terminal",
|
||||
StadiumBlock(
|
||||
AbstractBlock.Settings.create()
|
||||
.mapColor(MapColor.IRON_GRAY)
|
||||
.sounds(BlockSoundGroup.METAL)
|
||||
.pistonBehavior(PistonBehavior.BLOCK)
|
||||
.strength(2F)
|
||||
.nonOpaque()
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val DISPLAY_CASE = create(
|
||||
"display_case",
|
||||
|
||||
@@ -23,12 +23,7 @@ import com.cobblemon.mod.common.item.armor.CobblemonArmorTrims
|
||||
import com.cobblemon.mod.common.item.battle.DireHitItem
|
||||
import com.cobblemon.mod.common.item.battle.GuardSpecItem
|
||||
import com.cobblemon.mod.common.item.battle.XStatItem
|
||||
import com.cobblemon.mod.common.item.berry.FriendshipRaisingBerryItem
|
||||
import com.cobblemon.mod.common.item.berry.HealingBerryItem
|
||||
import com.cobblemon.mod.common.item.berry.PPRestoringBerryItem
|
||||
import com.cobblemon.mod.common.item.berry.PortionHealingBerryItem
|
||||
import com.cobblemon.mod.common.item.berry.StatusCuringBerryItem
|
||||
import com.cobblemon.mod.common.item.berry.VolatileCuringBerryItem
|
||||
import com.cobblemon.mod.common.item.berry.*
|
||||
import com.cobblemon.mod.common.item.interactive.*
|
||||
import com.cobblemon.mod.common.item.interactive.PotionItem
|
||||
import com.cobblemon.mod.common.item.interactive.ability.AbilityChangeItem
|
||||
@@ -253,6 +248,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
|
||||
@JvmField
|
||||
val PC = blockItem("pc", CobblemonBlocks.PC)
|
||||
@JvmField
|
||||
val STADIUM = blockItem("stadium_terminal", CobblemonBlocks.STADIUM)
|
||||
@JvmField
|
||||
val PASTURE = blockItem("pasture", CobblemonBlocks.PASTURE)
|
||||
@JvmField
|
||||
val DISPLAY_CASE = blockItem("display_case", CobblemonBlocks.DISPLAY_CASE)
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.PrimitiveCodec
|
||||
import java.util.Optional
|
||||
import java.util.UUID
|
||||
import net.minecraft.entity.ai.brain.MemoryModuleType
|
||||
import net.minecraft.util.Uuids
|
||||
|
||||
object CobblemonMemories {
|
||||
val memories = mutableMapOf<String, MemoryModuleType<*>>()
|
||||
|
||||
val POKEMON_FLYING = register("pokemon_flying", PrimitiveCodec.BOOL)
|
||||
val POKEMON_DROWSY = register("pokemon_drowsy", PrimitiveCodec.BOOL)
|
||||
val POKEMON_BATTLE = register<UUID>("pokemon_battle") // No codec because it shouldn't survive relogs
|
||||
val REST_PATH_COOLDOWN = register("rest_path_cooldown", PrimitiveCodec.BOOL)
|
||||
val TARGETED_BATTLE_POKEMON = register<UUID>("targeted_battle_pokemon")
|
||||
|
||||
fun <U> register(id: String, codec: Codec<U>): MemoryModuleType<U> {
|
||||
val memoryModule = MemoryModuleType(Optional.of(codec))
|
||||
memories[id] = memoryModule
|
||||
return memoryModule
|
||||
}
|
||||
|
||||
fun <U> register(id: String): MemoryModuleType<U> {
|
||||
val memoryModule = MemoryModuleType<U>(Optional.empty())
|
||||
memories[id] = memoryModule
|
||||
return memoryModule
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.sensors.DrowsySensor
|
||||
import java.util.function.Supplier
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.entity.ai.brain.sensor.Sensor
|
||||
import net.minecraft.entity.ai.brain.sensor.SensorType
|
||||
|
||||
object CobblemonSensors {
|
||||
val sensors = mutableMapOf<String, SensorType<*>>()
|
||||
|
||||
// val NPC_BATTLING = register("npc_battling", ::NPCBattlingSensor)
|
||||
val POKEMON_DROWSY = register("pokemon_drowsy", ::DrowsySensor)
|
||||
|
||||
fun <E : Entity, U : Sensor<E>> register(id: String, supplier: Supplier<U>): SensorType<U> {
|
||||
val sensor = SensorType(supplier)
|
||||
sensors[id] = sensor
|
||||
return sensor
|
||||
}
|
||||
}
|
||||
@@ -122,13 +122,18 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
|
||||
val FOSSIL_MACHINE_UNPROTECTED = this.create("fossil_machine.unprotected")
|
||||
|
||||
@JvmField
|
||||
val COIN_POUCH_BREAK = this.create("coin_pouch.break")
|
||||
val RELIC_COIN_SACK_BREAK = this.create("relic_coin_sack.break")
|
||||
@JvmField
|
||||
val COIN_POUCH_HIT = this.create("coin_pouch.hit")
|
||||
val RELIC_COIN_SACK_HIT = this.create("relic_coin_sack.hit")
|
||||
@JvmField
|
||||
val COIN_POUCH_STEP = this.create("coin_pouch.step")
|
||||
val RELIC_COIN_SACK_STEP = this.create("relic_coin_sack.step")
|
||||
@JvmField
|
||||
val COIN_POUCH_PLACE = this.create("coin_pouch.place")
|
||||
val RELIC_COIN_SACK_PLACE = this.create("relic_coin_sack.place")
|
||||
@JvmField
|
||||
val RELIC_COIN_POUCH_BREAK = this.create("relic_coin_pouch.break")
|
||||
@JvmField
|
||||
val RELIC_COIN_POUCH_PLACE = this.create("relic_coin_pouch.place")
|
||||
|
||||
@JvmField
|
||||
val TUMBLESTONE_BREAK = this.create("tumblestone.break")
|
||||
@JvmField
|
||||
@@ -189,13 +194,22 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
|
||||
val GILDED_CHEST_PLACE = this.create("gilded_chest.place")
|
||||
|
||||
@JvmField
|
||||
val COIN_POUCH_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
COIN_POUCH_BREAK,
|
||||
COIN_POUCH_STEP,
|
||||
COIN_POUCH_PLACE,
|
||||
COIN_POUCH_HIT,
|
||||
COIN_POUCH_STEP
|
||||
val RELIC_COIN_SACK_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
RELIC_COIN_SACK_BREAK,
|
||||
RELIC_COIN_SACK_STEP,
|
||||
RELIC_COIN_SACK_PLACE,
|
||||
RELIC_COIN_SACK_HIT,
|
||||
RELIC_COIN_SACK_STEP
|
||||
)
|
||||
@JvmField
|
||||
val RELIC_COIN_POUCH_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
RELIC_COIN_POUCH_BREAK,
|
||||
RELIC_COIN_SACK_STEP,
|
||||
RELIC_COIN_POUCH_PLACE,
|
||||
RELIC_COIN_SACK_HIT,
|
||||
RELIC_COIN_SACK_STEP
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val IMPACT_NORMAL = this.create("impact.normal")
|
||||
@JvmField
|
||||
|
||||
@@ -226,7 +226,7 @@ open class PokemonBattle(
|
||||
val facedFainted = opponentPokemon.facedOpponents.contains(faintedPokemon)
|
||||
val pokemon = opponentPokemon.effectedPokemon
|
||||
if (facedFainted) {
|
||||
pokemon.evolutions.forEach { evolution ->
|
||||
pokemon.lockedEvolutions.forEach { evolution ->
|
||||
evolution.requirements.filterIsInstance<DefeatRequirement>().forEach { defeatRequirement ->
|
||||
if (defeatRequirement.target.matches(faintedPokemon.effectedPokemon)) {
|
||||
val progress = pokemon.evolutionProxy.current().progressFirstOrCreate({ it is DefeatEvolutionProgress && it.currentProgress().target == defeatRequirement.target }) { DefeatEvolutionProgress() }
|
||||
|
||||
@@ -78,6 +78,8 @@ object CobblemonEvents {
|
||||
val POKE_BALL_CAPTURE_CALCULATED = EventObservable<PokeBallCaptureCalculatedEvent>()
|
||||
@JvmField
|
||||
val POKEMON_CAPTURED = EventObservable<PokemonCapturedEvent>()
|
||||
@JvmField
|
||||
val FOSSIL_REVIVED = EventObservable<FossilRevivedEvent>()
|
||||
// @JvmField
|
||||
// val EGG_HATCH = EventObservable<HatchEggEvent>()
|
||||
@JvmField
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
|
||||
data class FossilRevivedEvent (
|
||||
val pokemon: Pokemon,
|
||||
val player: ServerPlayerEntity?
|
||||
)
|
||||
@@ -52,21 +52,24 @@ abstract class MultiblockBlock(properties: Settings) : BlockWithEntity(propertie
|
||||
if(hand == Hand.OFF_HAND) {
|
||||
return ActionResult.SUCCESS
|
||||
}
|
||||
val entity = world.getBlockEntity(pos) as MultiblockEntity?
|
||||
if (entity?.multiblockStructure != null) {
|
||||
return entity.multiblockStructure!!.onUse(state, world, pos, player, hand, hit)
|
||||
if (!world.isClient) {
|
||||
val entity = world.getBlockEntity(pos) as MultiblockEntity?
|
||||
if (entity?.multiblockStructure != null) {
|
||||
return entity.multiblockStructure!!.onUse(state, world, pos, player, hand, hit)
|
||||
}
|
||||
}
|
||||
return super.onUse(state, world, pos, player, hand, hit)
|
||||
}
|
||||
|
||||
override fun onBreak(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity?) {
|
||||
super.onBreak(world, pos, state, player)
|
||||
if (!world.isClient) {
|
||||
val entity = world.getBlockEntity(pos)
|
||||
if (entity is MultiblockEntity && entity.multiblockStructure != null) {
|
||||
entity.multiblockStructure!!.onBreak(world, pos, state, player)
|
||||
}
|
||||
entity?.markRemoved()
|
||||
}
|
||||
super.onBreak(world, pos, state, player)
|
||||
}
|
||||
|
||||
override fun createBlockEntity(pos: BlockPos, state: BlockState): BlockEntity? {
|
||||
@@ -78,6 +81,7 @@ abstract class MultiblockBlock(properties: Settings) : BlockWithEntity(propertie
|
||||
return BlockRenderType.MODEL
|
||||
}
|
||||
|
||||
//This is done so a block picked with NBT doesnt absolutely DESTROY multiblocks
|
||||
override fun getPickStack(world: BlockView, pos: BlockPos, state: BlockState): ItemStack {
|
||||
val blockEntity = world.getBlockEntity(pos) as? MultiblockEntity ?: return ItemStack.EMPTY
|
||||
return if (blockEntity.multiblockStructure == null) super.getPickStack(world, pos, state) else ItemStack.EMPTY
|
||||
|
||||
@@ -153,7 +153,7 @@ interface Evolution : EvolutionLike {
|
||||
pokemon.getOwnerPlayer()?.sendMessage(lang("experience.learned_move", pokemon.getDisplayName(), move.displayName))
|
||||
}
|
||||
// we want to instantly tick for example you might only evolve your Bulbasaur at level 34 so Venusaur should be immediately available
|
||||
pokemon.evolutions.filterIsInstance<PassiveEvolution>().forEach { evolution -> evolution.attemptEvolution(pokemon) }
|
||||
pokemon.lockedEvolutions.filterIsInstance<PassiveEvolution>().forEach { evolution -> evolution.attemptEvolution(pokemon) }
|
||||
pokemon.getOwnerPlayer()?.playSound(CobblemonSounds.EVOLVING, SoundCategory.NEUTRAL, 1F, 1F)
|
||||
CobblemonEvents.EVOLUTION_COMPLETE.post(EvolutionCompleteEvent(pokemon, this))
|
||||
}
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ abstract class SpawningCondition<T : SpawningContext> {
|
||||
return false
|
||||
} else if (ctx.position.z < minZ.orMin() || ctx.position.z > maxZ.orMax()) {
|
||||
return false
|
||||
} else if (dimensions != null && dimensions!!.isNotEmpty() && ctx.world.dimension.effects !in dimensions!!) {
|
||||
} else if (dimensions != null && dimensions!!.isNotEmpty() && ctx.world.dimensionKey.value !in dimensions!!) {
|
||||
return false
|
||||
} else if (moonPhase != null && ctx.moonPhase !in moonPhase!!) {
|
||||
return false
|
||||
|
||||
@@ -34,15 +34,19 @@ abstract class SpawnAction<R>(
|
||||
/**
|
||||
* Runs the spawn action and processes any non-null result.
|
||||
*/
|
||||
open fun complete(): Boolean {
|
||||
open fun complete(): R? {
|
||||
if (future.isDone) {
|
||||
return null
|
||||
}
|
||||
|
||||
ctx.influences.forEach { it.affectAction(this) }
|
||||
val result = run()
|
||||
return if (result != null) {
|
||||
if (result != null) {
|
||||
future.complete(result)
|
||||
true
|
||||
} else {
|
||||
future.completeExceptionally(Exception("Nothing was spawned."))
|
||||
false
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ open class PlayerPartyStore(
|
||||
}
|
||||
|
||||
// Passive evolutions
|
||||
pokemon.evolutions.filterIsInstance<PassiveEvolution>().forEach { it.attemptEvolution(pokemon) }
|
||||
pokemon.lockedEvolutions.filterIsInstance<PassiveEvolution>().forEach { it.attemptEvolution(pokemon) }
|
||||
val removeList = mutableListOf<Evolution>()
|
||||
pokemon.evolutionProxy.server().forEach {
|
||||
if (!it.test(pokemon) && it is LevelUpEvolution && !it.permanent)
|
||||
|
||||
@@ -99,7 +99,7 @@ open class PCStore(
|
||||
this.lockedSize = lockNewSize
|
||||
if (boxes.size > newSize) {
|
||||
// reduce
|
||||
val slicedBoxes = boxes.slice(boxes.size until newSize)
|
||||
val slicedBoxes = boxes.slice(newSize until boxes.size)
|
||||
boxes.removeAll(slicedBoxes)
|
||||
slicedBoxes.flatMap { it.asIterable() }.forEach(overflowHandler)
|
||||
} else {
|
||||
|
||||
@@ -15,21 +15,5 @@ package com.cobblemon.mod.common.battles.dispatch
|
||||
* @since July 31st, 2022
|
||||
*/
|
||||
class UntilDispatch(val condition: () -> Boolean) : DispatchResult {
|
||||
var afterAction: (() -> Unit) = {}
|
||||
override fun canProceed(): Boolean {
|
||||
val shouldContinue = condition()
|
||||
if (shouldContinue) {
|
||||
afterAction()
|
||||
}
|
||||
return shouldContinue
|
||||
}
|
||||
|
||||
fun andThen(action: () -> Unit): UntilDispatch {
|
||||
val old = afterAction
|
||||
afterAction = {
|
||||
old()
|
||||
action()
|
||||
}
|
||||
return this
|
||||
}
|
||||
override fun canProceed() = condition()
|
||||
}
|
||||
+2
-2
@@ -54,8 +54,8 @@ class DamageInstruction(
|
||||
if (recoiling) {
|
||||
battlePokemon.effectedPokemon.let { pokemon ->
|
||||
if (RecoilEvolutionProgress.supports(pokemon)) {
|
||||
val newPercentage = privateMessage.argumentAt(1)?.split("/")?.getOrNull(0)?.toIntOrNull() ?: 0
|
||||
val newHealth = (pokemon.hp * (newPercentage / 100.0)).roundToInt()
|
||||
val healthStr = privateMessage.argumentAt(1) ?: throw UnsupportedOperationException("Cant get recoil string")
|
||||
val newHealth = "([0-9]+).*".toRegex().find(healthStr)?.groups?.get(1)?.value?.toIntOrNull() ?: throw UnsupportedOperationException("Cant get recoil string")
|
||||
val difference = pokemon.currentHealth - newHealth
|
||||
if (difference > 0) {
|
||||
val progress = pokemon.evolutionProxy.current().progressFirstOrCreate({ it is RecoilEvolutionProgress }) { RecoilEvolutionProgress() }
|
||||
|
||||
+2
-11
@@ -10,10 +10,10 @@ package com.cobblemon.mod.common.battles.interpreter.instructions
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleMessage
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.Effect
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunction
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addStandardFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.getQueryStruct
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
@@ -66,11 +66,6 @@ class MoveInstruction(
|
||||
val pokemonName = userPokemon.getName()
|
||||
ShowdownInterpreter.lastCauser[battle.battleId] = message
|
||||
|
||||
val targetPokemonEntity = targetPokemon?.entity
|
||||
if (targetPokemonEntity != null) {
|
||||
userPokemon.entity?.brain?.remember(CobblemonMemories.TARGETED_BATTLE_POKEMON, targetPokemonEntity.uuid)
|
||||
}
|
||||
|
||||
userPokemon.effectedPokemon.let { pokemon ->
|
||||
if (UseMoveEvolutionProgress.supports(pokemon, move)) {
|
||||
val progress = pokemon.evolutionProxy.current().progressFirstOrCreate({ it is UseMoveEvolutionProgress && it.currentProgress().move == move }) { UseMoveEvolutionProgress() }
|
||||
@@ -130,11 +125,7 @@ class MoveInstruction(
|
||||
this.future = actionEffect.run(context)
|
||||
holds = context.holds // Reference so future things can check on this action effect's holds
|
||||
future.thenApply { holds.clear() }
|
||||
return@dispatch UntilDispatch { "effects" !in holds }.andThen {
|
||||
val userPokemonId = userPokemon.entity?.uuid ?: return@andThen
|
||||
val targets = hurtTargets.mapNotNull { it.entity }
|
||||
userPokemonId.let { id -> targets.forEach { it.brain.remember(CobblemonMemories.TARGETED_BATTLE_POKEMON, id) } }
|
||||
}
|
||||
return@dispatch UntilDispatch { "effects" !in holds }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,7 @@ import net.minecraft.util.shape.VoxelShapes
|
||||
import net.minecraft.world.BlockView
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.world.WorldAccess
|
||||
import net.minecraft.world.WorldEvents
|
||||
import net.minecraft.world.WorldView
|
||||
|
||||
|
||||
@@ -72,10 +73,12 @@ class RestorationTankBlock(properties: Settings) : MultiblockBlock(properties),
|
||||
|
||||
override fun onBreak(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity?) {
|
||||
super.onBreak(world, pos, state, player)
|
||||
val otherPart = world.getBlockState(getPositionOfOtherPart(state, pos))
|
||||
if (otherPart.block is RestorationTankBlock) {
|
||||
world.setBlockState(getPositionOfOtherPart(state, pos), Blocks.AIR.defaultState, 35)
|
||||
world.syncWorldEvent(player, 2001, getPositionOfOtherPart(state, pos), getRawIdFromState(otherPart))
|
||||
if (!world.isClient) {
|
||||
val otherPart = world.getBlockState(getPositionOfOtherPart(state, pos))
|
||||
if (otherPart.block is RestorationTankBlock) {
|
||||
world.setBlockState(getPositionOfOtherPart(state, pos), Blocks.AIR.defaultState, Block.NOTIFY_ALL)
|
||||
world.syncWorldEvent(player, WorldEvents.BLOCK_BROKEN, getPositionOfOtherPart(state, pos), getRawIdFromState(otherPart))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,9 +90,9 @@ class RestorationTankBlock(properties: Settings) : MultiblockBlock(properties),
|
||||
itemStack: ItemStack?
|
||||
) {
|
||||
//Place the full block before we call to super to validate the multiblock
|
||||
world.setBlockState(pos.up(), state.with(PART, TankPart.TOP) as BlockState, 3)
|
||||
world.setBlockState(pos.up(), state.with(PART, TankPart.TOP) as BlockState, Block.NOTIFY_ALL)
|
||||
world.updateNeighbors(pos, Blocks.AIR)
|
||||
state.updateNeighbors(world, pos, 3)
|
||||
state.updateNeighbors(world, pos, Block.NOTIFY_ALL)
|
||||
super.onPlaced(world, pos, state, placer, itemStack)
|
||||
}
|
||||
|
||||
@@ -100,7 +103,7 @@ class RestorationTankBlock(properties: Settings) : MultiblockBlock(properties),
|
||||
val tankBottomPos = pos.down()
|
||||
val tankBottomState = world.getBlockState(tankBottomPos)
|
||||
if(tankBottomState.block.equals(CobblemonBlocks.RESTORATION_TANK.asBlock()) && tankBottomState.get(PART) == TankPart.BOTTOM) {
|
||||
return super.onUse(tankBottomState, world, tankBottomPos, player, hand, hit)
|
||||
return onUse(tankBottomState, world, tankBottomPos, player, hand, hit)
|
||||
}
|
||||
}
|
||||
return super.onUse(state, world, pos, player, hand, hit)
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.block
|
||||
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.block.entity.StadiumBlockEntity
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.BlockWithEntity
|
||||
import net.minecraft.block.entity.BlockEntity
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.ActionResult
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.hit.BlockHitResult
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.World
|
||||
|
||||
class StadiumBlock(properties: Settings): BlockWithEntity(properties) {
|
||||
override fun createBlockEntity(blockPos: BlockPos?, blockState: BlockState?): BlockEntity = StadiumBlockEntity(blockPos, blockState)
|
||||
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun onUse(
|
||||
blockState: BlockState,
|
||||
world: World,
|
||||
blockPos: BlockPos,
|
||||
player: PlayerEntity,
|
||||
interactionHand: Hand,
|
||||
blockHitResult: BlockHitResult
|
||||
): ActionResult {
|
||||
if (player !is ServerPlayerEntity) return ActionResult.SUCCESS
|
||||
|
||||
val blockEntity = world.getBlockEntity(blockPos)
|
||||
if (blockEntity !is StadiumBlockEntity) return ActionResult.SUCCESS
|
||||
|
||||
val message = "Stadium Pos: " + blockEntity.pos +
|
||||
"\nPlayer 1 Pos: " + blockEntity.getPlayer1Pos() +
|
||||
"\nPoke 1 Pos: " + blockEntity.getPoke1Pos() +
|
||||
"\nPlayer 2 Pos: " + blockEntity.getPlayer2Pos() +
|
||||
"\nPoke 2 Pos: " + blockEntity.getPoke2Pos()
|
||||
player.sendMessage(text(message).red())
|
||||
return ActionResult.SUCCESS
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import net.minecraft.item.ItemPlacementContext
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.screen.ScreenHandler
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.server.world.ServerWorld
|
||||
import net.minecraft.sound.SoundCategory
|
||||
import net.minecraft.state.StateManager
|
||||
import net.minecraft.state.property.BooleanProperty
|
||||
@@ -37,6 +38,7 @@ import net.minecraft.util.*
|
||||
import net.minecraft.util.hit.BlockHitResult
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.util.math.random.Random
|
||||
import net.minecraft.util.shape.VoxelShape
|
||||
import net.minecraft.util.shape.VoxelShapes
|
||||
import net.minecraft.world.BlockView
|
||||
@@ -125,11 +127,13 @@ class GildedChestBlock(settings: Settings, val type: Type = Type.RED) : BlockWit
|
||||
fun isFake() = (type == Type.FAKE)
|
||||
|
||||
override fun onBreak(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity) {
|
||||
if (isFake()) {
|
||||
if (player is ServerPlayerEntity) {
|
||||
if (!world.isClient) {
|
||||
if (isFake() && (player is ServerPlayerEntity)) {
|
||||
spawnPokemon(world, pos, state, player)
|
||||
}
|
||||
world.setBlockState(pos, if (state.fluidState.isOf(Fluids.WATER)) Blocks.WATER.defaultState else Blocks.AIR.defaultState)
|
||||
val bEntity = world.getBlockEntity(pos) as? GildedChestBlockEntity
|
||||
bEntity?.markRemoved()
|
||||
} else super.onBreak(world, pos, state, player)
|
||||
}
|
||||
|
||||
@@ -197,9 +201,11 @@ class GildedChestBlock(settings: Settings, val type: Type = Type.RED) : BlockWit
|
||||
newState: BlockState,
|
||||
moved: Boolean
|
||||
) {
|
||||
if (!state.isOf(newState.block)) {
|
||||
val chest = world.getBlockEntity(pos) as GildedChestBlockEntity
|
||||
ItemScatterer.spawn(world, pos, chest.inventoryContents)
|
||||
if (!state.isOf(newState.block) && !world.isClient) {
|
||||
val chest = world.getBlockEntity(pos) as? GildedChestBlockEntity
|
||||
chest?.let {
|
||||
ItemScatterer.spawn(world, pos, chest.inventoryContents)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,4 +267,14 @@ class GildedChestBlock(settings: Settings, val type: Type = Type.RED) : BlockWit
|
||||
}
|
||||
}
|
||||
|
||||
override fun scheduledTick(
|
||||
state: BlockState?,
|
||||
world: ServerWorld?,
|
||||
pos: BlockPos?,
|
||||
random: Random?
|
||||
) {
|
||||
val blockEntity = world?.getBlockEntity(pos) as? GildedChestBlockEntity ?: return
|
||||
blockEntity.onScheduledTick()
|
||||
}
|
||||
|
||||
}
|
||||
+30
-6
@@ -29,11 +29,17 @@ class FossilAnalyzerBlockEntity(
|
||||
|
||||
class FossilAnalyzerInventory(val analyzerEntity: FossilAnalyzerBlockEntity) : SidedInventory {
|
||||
override fun clear() {
|
||||
TODO("Not yet implemented")
|
||||
if(analyzerEntity.multiblockStructure != null && analyzerEntity.multiblockStructure is FossilMultiblockStructure) {
|
||||
val fossilMultiblockStructure = analyzerEntity.multiblockStructure as FossilMultiblockStructure
|
||||
fossilMultiblockStructure.fossilInventory.clear()
|
||||
}
|
||||
}
|
||||
|
||||
override fun size(): Int {
|
||||
TODO("Not yet implemented")
|
||||
if (analyzerEntity.multiblockStructure != null) {
|
||||
return 3
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun isEmpty(): Boolean {
|
||||
@@ -41,19 +47,34 @@ class FossilAnalyzerBlockEntity(
|
||||
}
|
||||
|
||||
override fun getStack(slot: Int): ItemStack {
|
||||
if (analyzerEntity.multiblockStructure != null && analyzerEntity.multiblockStructure is FossilMultiblockStructure) {
|
||||
val fossilMultiblockStructure = analyzerEntity.multiblockStructure as FossilMultiblockStructure
|
||||
if (fossilMultiblockStructure.fossilInventory.size > slot) {
|
||||
return fossilMultiblockStructure.fossilInventory[slot]
|
||||
}
|
||||
}
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
|
||||
//Unimplemented since no extract
|
||||
override fun removeStack(slot: Int, amount: Int): ItemStack {
|
||||
return ItemStack.EMPTY
|
||||
return removeStack(slot)
|
||||
}
|
||||
|
||||
override fun removeStack(slot: Int): ItemStack {
|
||||
// if(analyzerEntity.multiblockStructure is FossilMultiblockStructure) {
|
||||
// val fossilMultiblockStructure = analyzerEntity.multiblockStructure as FossilMultiblockStructure
|
||||
// if (fossilMultiblockStructure.fossilInventory.size > slot) {
|
||||
// val itemStack = fossilMultiblockStructure.fossilInventory.removeAt(slot)
|
||||
// markDirty()
|
||||
// return itemStack
|
||||
// }
|
||||
// }
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
|
||||
override fun setStack(slot: Int, stack: ItemStack) {
|
||||
if (analyzerEntity.multiblockStructure != null) {
|
||||
if (analyzerEntity.multiblockStructure != null && analyzerEntity.multiblockStructure is FossilMultiblockStructure) {
|
||||
val struct = analyzerEntity.multiblockStructure as FossilMultiblockStructure
|
||||
analyzerEntity.world?.let {
|
||||
struct.insertFossil(stack, it)
|
||||
@@ -72,7 +93,10 @@ class FossilAnalyzerBlockEntity(
|
||||
}
|
||||
|
||||
override fun getAvailableSlots(side: Direction?): IntArray {
|
||||
return IntArray(1)
|
||||
if(analyzerEntity.multiblockStructure != null && analyzerEntity.multiblockStructure is FossilMultiblockStructure) {
|
||||
return intArrayOf(0,1,2)
|
||||
}
|
||||
return IntArray(0)
|
||||
}
|
||||
|
||||
override fun canInsert(slot: Int, stack: ItemStack?, dir: Direction?): Boolean {
|
||||
@@ -87,8 +111,8 @@ class FossilAnalyzerBlockEntity(
|
||||
}
|
||||
|
||||
override fun canExtract(slot: Int, stack: ItemStack?, dir: Direction?): Boolean {
|
||||
// return analyzerEntity.multiblockStructure != null && analyzerEntity.multiblockStructure is FossilMultiblockStructure && dir == Direction.DOWN
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+8
-5
@@ -20,6 +20,7 @@ import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.entity.player.PlayerInventory
|
||||
import net.minecraft.inventory.DoubleInventory
|
||||
import net.minecraft.inventory.Inventories
|
||||
import net.minecraft.inventory.Inventory
|
||||
import net.minecraft.inventory.SidedInventory
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NbtCompound
|
||||
@@ -58,9 +59,7 @@ class GildedChestBlockEntity(pos: BlockPos, state: BlockState, val type: Type =
|
||||
override fun isPlayerViewing(player: PlayerEntity): Boolean {
|
||||
if (player.currentScreenHandler is GenericContainerScreenHandler) {
|
||||
val inventory = (player.currentScreenHandler as GenericContainerScreenHandler).inventory
|
||||
return inventory === this@GildedChestBlockEntity || inventory is DoubleInventory && inventory.isPart(
|
||||
this@GildedChestBlockEntity
|
||||
)
|
||||
return inventory === this@GildedChestBlockEntity
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -99,8 +98,6 @@ class GildedChestBlockEntity(pos: BlockPos, state: BlockState, val type: Type =
|
||||
return dir == Direction.DOWN
|
||||
}
|
||||
|
||||
override fun canPlayerUse(player: PlayerEntity) = !player.isSpectator
|
||||
|
||||
override fun getInvStackList(): DefaultedList<ItemStack> = inventoryContents
|
||||
|
||||
override fun setInvStackList(list: DefaultedList<ItemStack>) {
|
||||
@@ -164,4 +161,10 @@ class GildedChestBlockEntity(pos: BlockPos, state: BlockState, val type: Type =
|
||||
Inventories.readNbt(nbt, inventoryContents)
|
||||
}
|
||||
}
|
||||
|
||||
fun onScheduledTick() {
|
||||
if (!this.removed) {
|
||||
stateManager.updateViewerCount(this.getWorld(), this.getPos(), this.cachedState)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.cobblemon.mod.common.block.entity
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.entity.BlockEntity
|
||||
import net.minecraft.util.math.BlockPos
|
||||
|
||||
class StadiumBlockEntity(blockPos: BlockPos?, blockState: BlockState?): BlockEntity(CobblemonBlockEntities.STADIUM, blockPos, blockState) {
|
||||
fun getPlayer1Pos(): BlockPos? {
|
||||
return pos.add(5, 0, 10)
|
||||
}
|
||||
|
||||
fun getPlayer2Pos(): BlockPos? {
|
||||
return pos.add(5, 0, -10)
|
||||
}
|
||||
|
||||
fun getPoke1Pos(): BlockPos? {
|
||||
return pos.add(5, 0, 5)
|
||||
}
|
||||
|
||||
fun getPoke2Pos(): BlockPos? {
|
||||
return pos.add(5, 0, -5)
|
||||
}
|
||||
|
||||
}
|
||||
+4
-2
@@ -11,6 +11,8 @@ package com.cobblemon.mod.common.block.multiblock
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.advancement.CobblemonCriteria
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.pokemon.FossilRevivedEvent
|
||||
import com.cobblemon.mod.common.api.fossil.Fossil
|
||||
import com.cobblemon.mod.common.api.fossil.Fossils
|
||||
import com.cobblemon.mod.common.api.fossil.NaturalMaterials
|
||||
@@ -113,8 +115,6 @@ class FossilMultiblockStructure (
|
||||
return ActionResult.FAIL
|
||||
}
|
||||
|
||||
|
||||
|
||||
val ballType = (stack.item as PokeBallItem).pokeBall
|
||||
if (!player.isCreative) {
|
||||
stack?.decrement(1)
|
||||
@@ -125,6 +125,7 @@ class FossilMultiblockStructure (
|
||||
this.fossilState.growthState = "Taken"
|
||||
player.playSound(CobblemonSounds.FOSSIL_MACHINE_RETRIEVE_POKEMON, SoundCategory.BLOCKS, 1.0F, 1.0F)
|
||||
CobblemonCriteria.RESURRECT_POKEMON.trigger(player, createdPokemon!!)
|
||||
CobblemonEvents.FOSSIL_REVIVED.post(FossilRevivedEvent(createdPokemon!!, player))
|
||||
|
||||
// Turn the monitor off
|
||||
val monitorState = world.getBlockState(monitorPos)
|
||||
@@ -220,6 +221,7 @@ class FossilMultiblockStructure (
|
||||
entity.setPosition(fixedPosition.toCenterPos().subtract(0.0, 0.5, 0.0))
|
||||
// TODO: Find a correct way to set the new entity's Yaw rotation. (Face away from the machine)
|
||||
if (world.spawnEntity(entity)) {
|
||||
CobblemonEvents.FOSSIL_REVIVED.post(FossilRevivedEvent(pokemon, null))
|
||||
return true
|
||||
} else {
|
||||
Cobblemon.LOGGER.warn("Couldn't spawn resurrected Pokémon for some reason")
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.getQueryStruct
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.client.sound.PositionedSoundInstance
|
||||
@@ -31,6 +32,13 @@ object ClientMoLangFunctions {
|
||||
MinecraftClient.getInstance().soundManager.play(PositionedSoundInstance.master(soundEvent, pitch))
|
||||
}
|
||||
},
|
||||
"is_time" to java.util.function.Function { params ->
|
||||
val time = (MinecraftClient.getInstance().world?.timeOfDay ?: 0) % 24000
|
||||
val min = params.getInt(0)
|
||||
val max = params.getInt(1)
|
||||
time in min..max
|
||||
},
|
||||
"say" to java.util.function.Function { params -> MinecraftClient.getInstance().player?.sendMessage(params.getString(0).text()) ?: Unit },
|
||||
)
|
||||
|
||||
fun MoLangRuntime.setupClient(): MoLangRuntime {
|
||||
|
||||
@@ -8,25 +8,15 @@
|
||||
|
||||
package com.cobblemon.mod.common.client
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.*
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.api.berry.Berries
|
||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||
import com.cobblemon.mod.common.CobblemonBlocks
|
||||
import com.cobblemon.mod.common.CobblemonClientImplementation
|
||||
import com.cobblemon.mod.common.CobblemonEntities
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.scheduling.ClientTaskTracker
|
||||
import com.cobblemon.mod.common.api.text.gray
|
||||
import com.cobblemon.mod.common.client.battle.ClientBattle
|
||||
import com.cobblemon.mod.common.client.gui.PartyOverlay
|
||||
import com.cobblemon.mod.common.client.gui.battle.BattleOverlay
|
||||
import com.cobblemon.mod.common.client.particle.BedrockParticleEffectRepository
|
||||
import com.cobblemon.mod.common.client.render.block.BerryBlockRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.FossilAnalyzerRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.RestorationTankRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.GildedChestBlockRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.HealingMachineRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.*
|
||||
import com.cobblemon.mod.common.client.render.boat.CobblemonBoatRenderer
|
||||
import com.cobblemon.mod.common.client.render.generic.GenericBedrockRenderer
|
||||
@@ -34,10 +24,7 @@ import com.cobblemon.mod.common.client.render.item.CobblemonBuiltinItemRendererR
|
||||
import com.cobblemon.mod.common.client.render.item.PokemonItemRenderer
|
||||
import com.cobblemon.mod.common.client.render.layer.PokemonOnShoulderRenderer
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.bedrock.animation.BedrockAnimationRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.BerryModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.BlockEntityModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokeBallModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.*
|
||||
import com.cobblemon.mod.common.client.render.pokeball.PokeBallRenderer
|
||||
import com.cobblemon.mod.common.client.render.pokemon.PokemonRenderer
|
||||
import com.cobblemon.mod.common.client.sound.battle.BattleMusicController
|
||||
@@ -47,9 +34,6 @@ import com.cobblemon.mod.common.client.trade.ClientTrade
|
||||
import com.cobblemon.mod.common.data.CobblemonDataProvider
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
|
||||
import com.cobblemon.mod.common.item.PokeBallItem
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.FossilModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.GenericBedrockEntityModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.MiscModelRepository
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
@@ -221,7 +205,8 @@ object CobblemonClient {
|
||||
CobblemonBlocks.LARGE_BUDDING_SKY_TUMBLESTONE,
|
||||
CobblemonBlocks.SKY_TUMBLESTONE_CLUSTER,
|
||||
CobblemonBlocks.GIMMIGHOUL_CHEST,
|
||||
CobblemonBlocks.DISPLAY_CASE
|
||||
CobblemonBlocks.DISPLAY_CASE,
|
||||
CobblemonBlocks.STADIUM
|
||||
)
|
||||
|
||||
this.createBoatModelLayers()
|
||||
|
||||
@@ -272,6 +272,9 @@ class PokemonClientDelegate : PoseableEntityState<PokemonEntity>(), PokemonSideD
|
||||
},
|
||||
"weight" to java.util.function.Function {
|
||||
return@Function DoubleValue(currentEntity.pokemon.species.weight.toDouble())
|
||||
},
|
||||
"friendship" to java.util.function.Function {
|
||||
return@Function DoubleValue(currentEntity.pokemon.friendship.toDouble())
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
+9
-2
@@ -20,7 +20,10 @@ import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFram
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.quirk.SimpleQuirk
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.normalizeToArray
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.resolveObject
|
||||
import com.cobblemon.mod.common.util.singularToPluralList
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonPrimitive
|
||||
@@ -34,6 +37,8 @@ class JsonPose<T : Entity>(model: PoseableEntityModel<T>, json: JsonObject) {
|
||||
it.environment.getQueryStruct().addFunctions(model.functions.functions)
|
||||
}
|
||||
|
||||
val condition: ExpressionLike = json.singularToPluralList("condition").get("condition")?.normalizeToArray()?.map { it.asString }?.asExpressionLike() ?: "true".asExpressionLike()
|
||||
|
||||
val poseName = json.get("poseName")?.asString ?: "pose"
|
||||
val poseTypes = (json.get("poseTypes")?.asJsonArray?.map { name ->
|
||||
PoseType.values().find { it.name.lowercase() == name.asString.lowercase() }
|
||||
@@ -81,8 +86,9 @@ class JsonPose<T : Entity>(model: PoseableEntityModel<T>, json: JsonObject) {
|
||||
}
|
||||
|
||||
json as JsonObject
|
||||
json.singularToPluralList("animation")
|
||||
val animations: (state: PoseableEntityState<T>) -> List<StatefulAnimation<T, *>> = { _ ->
|
||||
(json.get("animations")?.asJsonArray ?: JsonArray()).map { animJson ->
|
||||
(json.get("animations")?.normalizeToArray()?.asJsonArray ?: JsonArray()).map { animJson ->
|
||||
try {
|
||||
val expr = animJson.asString.asExpressionLike()
|
||||
runtime.resolveObject(expr).obj as StatefulAnimation<T, *>
|
||||
@@ -97,10 +103,11 @@ class JsonPose<T : Entity>(model: PoseableEntityModel<T>, json: JsonObject) {
|
||||
val loopTimes = json.get("loopTimes")?.asInt ?: 1
|
||||
val minSeconds = json.get("minSecondsBetweenOccurrences")?.asFloat ?: 8F
|
||||
val maxSeconds = json.get("maxSecondsBetweenOccurrences")?.asFloat ?: 30F
|
||||
val condition = json.get("condition")?.asString?.asExpressionLike() ?: "true".asExpressionLike()
|
||||
|
||||
model.quirkMultiple(
|
||||
secondsBetweenOccurrences = minSeconds to maxSeconds,
|
||||
condition = { true },
|
||||
condition = { it.runtime.resolveBoolean(condition) },
|
||||
loopTimes = 1..loopTimes,
|
||||
animations = animations
|
||||
)
|
||||
|
||||
+13
@@ -46,6 +46,7 @@ import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.getDoubleOrNull
|
||||
import com.cobblemon.mod.common.util.getStringOrNull
|
||||
import com.cobblemon.mod.common.util.plus
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.client.render.OverlayTexture
|
||||
import net.minecraft.client.render.RenderLayer
|
||||
@@ -878,6 +879,18 @@ abstract class PoseableEntityModel<T : Entity>(
|
||||
animations = { listOf(animation(it)) }
|
||||
)
|
||||
|
||||
fun quirkMoLangCondition(
|
||||
secondsBetweenOccurrences: Pair<Float, Float> = 8F to 30F,
|
||||
loopTimes: IntRange = 1..1,
|
||||
conditionExpression: ExpressionLike = "true".asExpressionLike(),
|
||||
animation: (state: PoseableEntityState<T>) -> StatefulAnimation<T, *>
|
||||
) = SimpleQuirk<T>(
|
||||
secondsBetweenOccurrences = secondsBetweenOccurrences,
|
||||
loopTimes = loopTimes,
|
||||
condition = { it.runtime.resolveBoolean(conditionExpression) },
|
||||
animations = { listOf(animation(it)) }
|
||||
)
|
||||
|
||||
fun quirkMultiple(
|
||||
secondsBetweenOccurrences: Pair<Float, Float> = 8F to 30F,
|
||||
loopTimes: IntRange = 1..1,
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ abstract class PoseableEntityState<T : Entity> : Schedulable {
|
||||
"anim_time" to java.util.function.Function { return@Function reusableAnimTime.also { it.value = animationSeconds.toDouble() } },
|
||||
"pose_type" to java.util.function.Function { return@Function StringValue((getEntity() as Poseable).getCurrentPoseType().name) },
|
||||
"pose" to java.util.function.Function { _ -> return@Function StringValue(currentPose ?: "") },
|
||||
"say" to java.util.function.Function { params -> MinecraftClient.getInstance().player?.sendMessage(params.getString(0).text()) ?: Unit },
|
||||
"has_entity" to java.util.function.Function { _ -> return@Function DoubleValue(getEntity() != null) },
|
||||
"sound" to java.util.function.Function { params ->
|
||||
val entity = getEntity() ?: return@Function Unit
|
||||
if (params.get<MoValue>(0) !is StringValue) {
|
||||
|
||||
+5
-19
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.JsonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.JsonPoseableEntityModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
|
||||
@@ -24,6 +25,7 @@ import com.cobblemon.mod.common.util.isDusk
|
||||
import com.cobblemon.mod.common.util.isStandingOnRedSand
|
||||
import com.cobblemon.mod.common.util.isStandingOnSand
|
||||
import com.cobblemon.mod.common.util.isStandingOnSandOrRedSand
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.google.gson.ExclusionStrategy
|
||||
import com.google.gson.FieldAttributes
|
||||
import com.google.gson.GsonBuilder
|
||||
@@ -84,30 +86,12 @@ class JsonPokemonPoseableModel(override val rootPart: Bone) : PokemonPoseableMod
|
||||
|
||||
override val head: Bone by lazy { headJoint?.let { getPart(it) } ?: rootPart }
|
||||
|
||||
|
||||
@SerializedName("portraitScale")
|
||||
private val _portraitScale: Float? = null
|
||||
@SerializedName("portraitTranslation")
|
||||
private val _portraitTranslation: Vec3d? = null
|
||||
|
||||
@SerializedName("profileScale")
|
||||
private val _profileScale: Float? = null
|
||||
@SerializedName("profileTranslation")
|
||||
private val _profileTranslation: Vec3d? = null
|
||||
|
||||
//Some weirdness going on here, vars have to be initialized, gson doesn't like multiple fields with the same name
|
||||
@Transient
|
||||
//Idk, works fine with Blastoise
|
||||
override var portraitScale = 1F
|
||||
get() = _portraitScale ?: 1F
|
||||
@Transient
|
||||
override var portraitTranslation = Vec3d.ZERO
|
||||
get() = _portraitTranslation ?: Vec3d(0.0, 0.0, 0.0)
|
||||
@Transient
|
||||
override var profileScale = 1F
|
||||
get() = _profileScale ?: 1F
|
||||
@Transient
|
||||
override var profileTranslation = Vec3d.ZERO
|
||||
get() = _profileTranslation ?: Vec3d(0.0, 0.0, 0.0)
|
||||
|
||||
|
||||
val faint: Supplier<StatefulAnimation<PokemonEntity, ModelFrame>>? = null
|
||||
@@ -192,6 +176,8 @@ class JsonPokemonPoseableModel(override val rootPart: Bone) : PokemonPoseableMod
|
||||
conditionsList.add { mustBeDusk == it.isDusk() }
|
||||
}
|
||||
|
||||
conditionsList.add { (it.delegate as PokemonClientDelegate).runtime.resolveBoolean(pose.condition) }
|
||||
|
||||
val poseCondition: ((PokemonEntity) -> Boolean)? = if (conditionsList.isEmpty()) null else conditionsList.reduce { acc, function -> { acc(it) && function(it) } }
|
||||
|
||||
return Pose(
|
||||
|
||||
+4
-3
@@ -8,13 +8,14 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen1
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BipedWalkAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
@@ -56,7 +57,7 @@ class KabutopsModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bipe
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = UI_POSES + PoseType.STAND,
|
||||
poseTypes = UI_POSES + STATIONARY_POSES,
|
||||
condition = { !it.isBattling },
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
@@ -67,7 +68,7 @@ class KabutopsModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bipe
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseType = PoseType.WALK,
|
||||
poseTypes = MOVING_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
|
||||
+1
-8
@@ -8,21 +8,14 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen1
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.WingFlapIdleAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.createTransformation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BiWingedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.ModelPartTransformation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.parabolaFunction
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.sineFunction
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.SHOULDER_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
@@ -66,7 +59,7 @@ class PidgeyModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
|
||||
stand = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = SHOULDER_POSES + UI_POSES + PoseType.STANDING_POSES,
|
||||
poseTypes = SHOULDER_POSES + UI_POSES + PoseType.STATIONARY_POSES - PoseType.HOVER,
|
||||
transformTicks = 10,
|
||||
transformedParts = arrayOf(
|
||||
wingClosedLeft.createTransformation().withVisibility(visibility = true),
|
||||
|
||||
+2
-2
@@ -25,8 +25,8 @@ class PetililHisuiBiasModel (root: ModelPart) : PokemonPoseableModel(), HeadedFr
|
||||
val leaf_left = getPart("leaf_left_rotation")
|
||||
val leaf_right = getPart("leaf_right_rotation")
|
||||
|
||||
override var portraitScale = 1.75F
|
||||
override var portraitTranslation = Vec3d(0.01, -0.39, 0.0)
|
||||
override var portraitScale = 1.52F
|
||||
override var portraitTranslation = Vec3d(0.1, -0.25, 0.0)
|
||||
|
||||
override var profileScale = 0.8F
|
||||
override var profileTranslation = Vec3d(0.0, 0.5, 0.0)
|
||||
|
||||
+2
-2
@@ -22,8 +22,8 @@ class PetililModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("petilil")
|
||||
override val head = getPart("head")
|
||||
|
||||
override var portraitScale = 2.0F
|
||||
override var portraitTranslation = Vec3d(-0.3, -1.2, 0.0)
|
||||
override var portraitScale = 1.52F
|
||||
override var portraitTranslation = Vec3d(0.1, -0.25, 0.0)
|
||||
|
||||
override var profileScale = 0.8F
|
||||
override var profileTranslation = Vec3d(0.0, 0.5, 0.0)
|
||||
|
||||
+2
-2
@@ -28,8 +28,8 @@ class DubwoolModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Quadr
|
||||
override val foreRightLeg = getPart("leg_front_right")
|
||||
override val hindLeftLeg = getPart("leg_back_left")
|
||||
override val hindRightLeg = getPart("leg_back_right")
|
||||
val wool = getPart("wool")
|
||||
val neckWool = getPart("neck_wool")
|
||||
val wool = getPart("wool_shearable")
|
||||
val neckWool = getPart("neck_wool_shearable")
|
||||
|
||||
override var portraitScale = 3.1F
|
||||
override var portraitTranslation = Vec3d(-1.2, -0.7, 0.0)
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ class WoolooModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Quadru
|
||||
override val foreRightLeg = getPart("leg_front_right")
|
||||
override val hindLeftLeg = getPart("leg_back_left")
|
||||
override val hindRightLeg = getPart("leg_back_right")
|
||||
val wool = getPart("wool")
|
||||
val wool = getPart("wool_shearable")
|
||||
|
||||
override var portraitScale = 3.1F
|
||||
override var portraitTranslation = Vec3d(-0.85, -1.8, 0.0)
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.entity.ai
|
||||
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.entity.ai.brain.MemoryModuleType
|
||||
import net.minecraft.entity.ai.brain.task.SingleTickTask
|
||||
import net.minecraft.entity.ai.brain.task.TaskRunnable
|
||||
import net.minecraft.entity.ai.brain.task.TaskTriggerer
|
||||
|
||||
object AttackAngryAtTask {
|
||||
fun create(): SingleTickTask<LivingEntity> = TaskTriggerer.task {
|
||||
it.group(
|
||||
it.queryMemoryValue(MemoryModuleType.ANGRY_AT),
|
||||
it.queryMemoryAbsent(MemoryModuleType.ATTACK_TARGET)
|
||||
).apply(it) { angryAt, attackTarget ->
|
||||
TaskRunnable { world, entity, _ ->
|
||||
val angryAt = it.getValue(angryAt)
|
||||
val livingEntity = world.getEntity(angryAt) as? LivingEntity
|
||||
if (livingEntity != null) {
|
||||
entity.brain.remember(MemoryModuleType.ATTACK_TARGET, livingEntity)
|
||||
} else {
|
||||
entity.brain.forget(MemoryModuleType.ANGRY_AT)
|
||||
}
|
||||
return@TaskRunnable true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.entity.ai
|
||||
|
||||
import net.minecraft.entity.ai.FuzzyTargeting
|
||||
import net.minecraft.entity.ai.brain.BlockPosLookTarget
|
||||
import net.minecraft.entity.ai.brain.MemoryModuleType
|
||||
import net.minecraft.entity.ai.brain.WalkTarget
|
||||
import net.minecraft.entity.ai.brain.task.SingleTickTask
|
||||
import net.minecraft.entity.ai.brain.task.TaskRunnable
|
||||
import net.minecraft.entity.ai.brain.task.TaskTriggerer
|
||||
import net.minecraft.entity.mob.PathAwareEntity
|
||||
|
||||
object ChooseLandWanderTargetTask {
|
||||
fun create(chance: Int, horizontalRange: Int, verticalRange: Int, walkSpeed: Float, completionRange: Int): SingleTickTask<PathAwareEntity> {
|
||||
return TaskTriggerer.task {
|
||||
it.group(
|
||||
it.queryMemoryAbsent(MemoryModuleType.WALK_TARGET),
|
||||
it.queryMemoryOptional(MemoryModuleType.LOOK_TARGET)
|
||||
).apply(it) { walkTarget, lookTarget ->
|
||||
TaskRunnable { world, entity, time ->
|
||||
if (world.random.nextInt(chance) != 0) return@TaskRunnable false
|
||||
val targetVec = FuzzyTargeting.find(entity, horizontalRange, verticalRange) ?: return@TaskRunnable false
|
||||
walkTarget.remember(WalkTarget(targetVec, walkSpeed, completionRange))
|
||||
lookTarget.remember(BlockPosLookTarget(targetVec.add(0.0, 1.5, 0.0)))
|
||||
return@TaskRunnable true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.entity.ai
|
||||
|
||||
import net.minecraft.entity.ai.NoPenaltyTargeting
|
||||
import net.minecraft.entity.ai.brain.EntityLookTarget
|
||||
import net.minecraft.entity.ai.brain.MemoryModuleState
|
||||
import net.minecraft.entity.ai.brain.MemoryModuleType
|
||||
import net.minecraft.entity.ai.brain.WalkTarget
|
||||
import net.minecraft.entity.ai.brain.task.MultiTickTask
|
||||
import net.minecraft.entity.ai.pathing.Path
|
||||
import net.minecraft.entity.mob.PathAwareEntity
|
||||
import net.minecraft.server.world.ServerWorld
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class FollowWalkTargetTask(
|
||||
minRunTime: Int = 150,
|
||||
maxRunTime: Int = 250
|
||||
) : MultiTickTask<PathAwareEntity>(
|
||||
mapOf(
|
||||
MemoryModuleType.WALK_TARGET to MemoryModuleState.VALUE_PRESENT,
|
||||
MemoryModuleType.PATH to MemoryModuleState.VALUE_ABSENT,
|
||||
MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE to MemoryModuleState.REGISTERED
|
||||
), minRunTime, maxRunTime
|
||||
) {
|
||||
private var pathUpdateCountdownTicks = 0
|
||||
private var path: Path? = null
|
||||
private var lookTargetPos: BlockPos? = null
|
||||
private var speed = 0f
|
||||
|
||||
override fun shouldRun(arg: ServerWorld, arg2: PathAwareEntity): Boolean {
|
||||
if (this.pathUpdateCountdownTicks > 0) {
|
||||
--this.pathUpdateCountdownTicks
|
||||
return false
|
||||
} else {
|
||||
val brain = arg2.brain
|
||||
val walkTarget = brain.getOptionalRegisteredMemory(MemoryModuleType.WALK_TARGET).get()
|
||||
val hasReached = this.hasReached(arg2, walkTarget)
|
||||
if (!hasReached && this.hasFinishedPath(arg2, walkTarget, arg.time)) {
|
||||
this.lookTargetPos = walkTarget.lookTarget.blockPos
|
||||
return true
|
||||
} else {
|
||||
brain.forget(MemoryModuleType.WALK_TARGET)
|
||||
if (hasReached) {
|
||||
brain.forget(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun shouldKeepRunning(arg: ServerWorld, arg2: PathAwareEntity, l: Long): Boolean {
|
||||
if (this.path != null && this.lookTargetPos != null) {
|
||||
val optional = arg2.brain.getOptionalRegisteredMemory(MemoryModuleType.WALK_TARGET)
|
||||
val isTargetSpectator = optional.map(::isTargetSpectator).orElse(false)
|
||||
val entityNavigation = arg2.navigation
|
||||
return !entityNavigation.isIdle && optional.isPresent && !this.hasReached(arg2, optional.get()) && !isTargetSpectator
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
override fun finishRunning(world: ServerWorld, entity: PathAwareEntity, l: Long) {
|
||||
val walkTarget = entity.brain.getOptionalRegisteredMemory(MemoryModuleType.WALK_TARGET).orElse(null)
|
||||
if (walkTarget != null && !this.hasReached(entity, walkTarget) && entity.navigation.isNearPathStartPos) {
|
||||
this.pathUpdateCountdownTicks = world.getRandom().nextInt(40)
|
||||
}
|
||||
|
||||
entity.navigation.stop()
|
||||
entity.brain.forget(MemoryModuleType.WALK_TARGET)
|
||||
entity.brain.forget(MemoryModuleType.PATH)
|
||||
this.path = null
|
||||
}
|
||||
|
||||
override fun run(arg: ServerWorld, entity: PathAwareEntity, time: Long) {
|
||||
entity.brain.remember(MemoryModuleType.PATH, this.path)
|
||||
entity.navigation.startMovingAlong(this.path, speed.toDouble())
|
||||
}
|
||||
|
||||
override fun keepRunning(world: ServerWorld, entity: PathAwareEntity, l: Long) {
|
||||
val path = entity.navigation.currentPath
|
||||
val brain = entity.brain
|
||||
if (this.path !== path) {
|
||||
this.path = path
|
||||
brain.remember(MemoryModuleType.PATH, path)
|
||||
}
|
||||
|
||||
if (path != null && lookTargetPos != null) {
|
||||
val walkTarget = brain.getOptionalRegisteredMemory(MemoryModuleType.WALK_TARGET).get()
|
||||
if (walkTarget.lookTarget.blockPos.getSquaredDistance(lookTargetPos) > 4.0 && hasFinishedPath(entity, walkTarget, world.time)) {
|
||||
lookTargetPos = walkTarget.lookTarget.blockPos
|
||||
run(world, entity, l)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun hasFinishedPath(entity: PathAwareEntity, walkTarget: WalkTarget, time: Long): Boolean {
|
||||
val blockPos = walkTarget.lookTarget.blockPos
|
||||
this.path = entity.navigation.findPathTo(blockPos, 0)
|
||||
this.speed = walkTarget.speed
|
||||
val brain = entity.brain
|
||||
if (hasReached(entity, walkTarget)) {
|
||||
brain.forget(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)
|
||||
} else {
|
||||
val bl = this.path != null && path!!.reachesTarget()
|
||||
if (bl) {
|
||||
brain.forget(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)
|
||||
} else if (!brain.hasMemoryModule(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)) {
|
||||
brain.remember(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, time)
|
||||
}
|
||||
|
||||
if (this.path != null) {
|
||||
return true
|
||||
}
|
||||
|
||||
val vec3d = NoPenaltyTargeting.findTo(
|
||||
entity,
|
||||
10,
|
||||
7,
|
||||
Vec3d.ofBottomCenter(blockPos),
|
||||
1.5707963705062866
|
||||
)
|
||||
if (vec3d != null) {
|
||||
this.path = entity.navigation.findPathTo(vec3d.x, vec3d.y, vec3d.z, 0)
|
||||
return this.path != null
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun hasReached(entity: PathAwareEntity, walkTarget: WalkTarget): Boolean {
|
||||
return walkTarget.lookTarget.blockPos.getManhattanDistance(entity.blockPos) <= walkTarget.completionRange
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun isTargetSpectator(target: WalkTarget): Boolean {
|
||||
val lookTarget = target.lookTarget
|
||||
return if (lookTarget is EntityLookTarget) {
|
||||
lookTarget.entity.isSpectator
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.entity.ai
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.toDF
|
||||
import com.mojang.datafixers.util.Pair
|
||||
import net.minecraft.entity.ai.brain.MemoryModuleState
|
||||
import net.minecraft.entity.ai.brain.MemoryModuleType
|
||||
import net.tslat.smartbrainlib.api.core.behaviour.ExtendedBehaviour
|
||||
import net.tslat.smartbrainlib.util.BrainUtils
|
||||
|
||||
//todo: make sure it's the same behaviour
|
||||
class GetAngryAtAttackerTask : ExtendedBehaviour<PokemonEntity>() {
|
||||
init {
|
||||
whenStarting { entity ->
|
||||
val hurtByEntity = requireNotNull(
|
||||
BrainUtils.getMemory(entity, MemoryModuleType.HURT_BY_ENTITY)
|
||||
)
|
||||
|
||||
val angryAt = BrainUtils.getMemory(entity, MemoryModuleType.ANGRY_AT)
|
||||
if (angryAt != null && angryAt == hurtByEntity.uuid) {
|
||||
return@whenStarting
|
||||
}
|
||||
|
||||
entity.brain.remember(MemoryModuleType.ANGRY_AT, hurtByEntity.uuid)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMemoryRequirements(): List<Pair<MemoryModuleType<*>, MemoryModuleState>> {
|
||||
//todo: not sure what state these should be
|
||||
return listOf(
|
||||
MemoryModuleType.HURT_BY_ENTITY toDF MemoryModuleState.REGISTERED,
|
||||
MemoryModuleType.ANGRY_AT toDF MemoryModuleState.REGISTERED,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.entity.ai
|
||||
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.entity.ai.brain.MemoryModuleType
|
||||
import net.minecraft.entity.ai.brain.WalkTarget
|
||||
import net.minecraft.entity.ai.brain.task.SingleTickTask
|
||||
import net.minecraft.entity.ai.brain.task.TaskRunnable
|
||||
import net.minecraft.entity.ai.brain.task.TaskTriggerer
|
||||
|
||||
object MoveToAttackTargetTask {
|
||||
fun create(): SingleTickTask<LivingEntity> = TaskTriggerer.task {
|
||||
it.group(
|
||||
it.queryMemoryValue(MemoryModuleType.ATTACK_TARGET),
|
||||
it.queryMemoryOptional(MemoryModuleType.WALK_TARGET)
|
||||
).apply(it) { attackTarget, walkTarget ->
|
||||
TaskRunnable { world, entity, _ ->
|
||||
val attackTarget = it.getValue(attackTarget)
|
||||
val position = attackTarget.pos
|
||||
val walkTarget = it.getOptionalValue(walkTarget).orElse(null)
|
||||
if (walkTarget == null || walkTarget.lookTarget.pos.squaredDistanceTo(position) > 2.0) {
|
||||
entity.brain.remember(MemoryModuleType.WALK_TARGET, WalkTarget(attackTarget, 0.5F, 1))
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.entity.ai
|
||||
|
||||
import net.minecraft.entity.ai.brain.task.MultiTickTask
|
||||
import net.minecraft.entity.mob.PathAwareEntity
|
||||
import net.minecraft.registry.tag.FluidTags
|
||||
import net.minecraft.server.world.ServerWorld
|
||||
|
||||
class StayAfloatTask(private val chance: Float = 0F) : MultiTickTask<PathAwareEntity>(emptyMap()) {
|
||||
override fun shouldRun(world: ServerWorld, entity: PathAwareEntity): Boolean {
|
||||
return entity.isTouchingWater && entity.getFluidHeight(FluidTags.WATER) > entity.swimHeight || entity.isInLava
|
||||
}
|
||||
|
||||
override fun shouldKeepRunning(world: ServerWorld, entity: PathAwareEntity, l: Long): Boolean {
|
||||
return this.shouldRun(world, entity)
|
||||
}
|
||||
|
||||
override fun keepRunning(world: ServerWorld, entity: PathAwareEntity, l: Long) {
|
||||
if (entity.random.nextFloat() < this.chance) {
|
||||
entity.jumpControl.setActive()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.entity.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.*
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.drop.DropTable
|
||||
import com.cobblemon.mod.common.api.entity.Despawner
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
@@ -21,7 +20,11 @@ import com.cobblemon.mod.common.api.events.pokemon.ShoulderMountEvent
|
||||
import com.cobblemon.mod.common.api.interaction.PokemonEntityInteraction
|
||||
import com.cobblemon.mod.common.api.net.serializers.PoseTypeDataSerializer
|
||||
import com.cobblemon.mod.common.api.net.serializers.StringSetDataSerializer
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.ChoiceSpeciesFeatureProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.FlagSpeciesFeature
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.StringSpeciesFeature
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
import com.cobblemon.mod.common.api.reactive.ObservableSubscription
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.scheduling.Schedulable
|
||||
@@ -35,14 +38,11 @@ import com.cobblemon.mod.common.block.entity.PokemonPastureBlockEntity
|
||||
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.Poseable
|
||||
import com.cobblemon.mod.common.entity.ai.*
|
||||
import com.cobblemon.mod.common.entity.generic.GenericBedrockEntity
|
||||
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.PokemonMoveControl
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.PokemonNavigation
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.goals.*
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.sensors.DrowsySensor
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.*
|
||||
import com.cobblemon.mod.common.entity.pokemon.effects.EffectTracker
|
||||
import com.cobblemon.mod.common.entity.pokemon.effects.IllusionEffect
|
||||
import com.cobblemon.mod.common.net.messages.client.animation.PlayPoseableAnimationPacket
|
||||
@@ -61,22 +61,14 @@ import com.cobblemon.mod.common.pokemon.evolution.variants.ItemInteractionEvolut
|
||||
import com.cobblemon.mod.common.pokemon.misc.GimmighoulStashHandler
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
import com.google.common.collect.ImmutableList
|
||||
import com.mojang.serialization.Dynamic
|
||||
import java.util.EnumSet
|
||||
import java.util.Optional
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import net.minecraft.entity.*
|
||||
import net.minecraft.entity.ai.brain.Activity
|
||||
import net.minecraft.entity.ai.brain.Brain
|
||||
import net.minecraft.entity.ai.brain.MemoryModuleType
|
||||
import net.minecraft.entity.ai.brain.sensor.NearestLivingEntitiesSensor
|
||||
import net.minecraft.entity.ai.brain.sensor.NearestPlayersSensor
|
||||
import net.minecraft.entity.ai.brain.sensor.Sensor
|
||||
import net.minecraft.entity.ai.brain.sensor.SensorType
|
||||
import net.minecraft.entity.ai.brain.task.ForgetAngryAtTargetTask
|
||||
import net.minecraft.entity.ai.brain.task.LookAroundTask
|
||||
import net.minecraft.entity.ai.brain.task.LookAtMobTask
|
||||
import net.minecraft.entity.ai.brain.task.MultiTickTask
|
||||
import net.minecraft.entity.ai.brain.task.Task
|
||||
import net.minecraft.entity.ai.control.MoveControl
|
||||
import net.minecraft.entity.ai.goal.EatGrassGoal
|
||||
import net.minecraft.entity.ai.goal.Goal
|
||||
import net.minecraft.entity.ai.pathing.PathNodeType
|
||||
import net.minecraft.entity.attribute.DefaultAttributeContainer
|
||||
import net.minecraft.entity.attribute.EntityAttributes
|
||||
@@ -91,6 +83,7 @@ import net.minecraft.entity.passive.PassiveEntity
|
||||
import net.minecraft.entity.passive.TameableShoulderEntity
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.fluid.FluidState
|
||||
import net.minecraft.item.DyeItem
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.item.ItemUsage
|
||||
import net.minecraft.item.Items
|
||||
@@ -111,33 +104,25 @@ import net.minecraft.sound.SoundEvents
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.text.TextContent
|
||||
import net.minecraft.util.ActionResult
|
||||
import net.minecraft.util.Colors
|
||||
import net.minecraft.util.DyeColor
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.Util
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Box
|
||||
import net.minecraft.util.math.Vec3d
|
||||
import net.minecraft.world.EntityView
|
||||
import net.minecraft.world.LightType
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.world.event.GameEvent
|
||||
import net.tslat.smartbrainlib.api.SmartBrainOwner
|
||||
import net.tslat.smartbrainlib.api.core.BrainActivityGroup
|
||||
import net.tslat.smartbrainlib.api.core.SmartBrainProvider
|
||||
import net.tslat.smartbrainlib.api.core.sensor.ExtendedSensor
|
||||
import net.tslat.smartbrainlib.api.core.sensor.vanilla.HurtBySensor
|
||||
import net.tslat.smartbrainlib.api.core.sensor.vanilla.NearbyLivingEntitySensor
|
||||
import net.tslat.smartbrainlib.api.core.sensor.vanilla.NearbyPlayersSensor
|
||||
import java.util.*
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import kotlin.math.ceil
|
||||
|
||||
|
||||
@Suppress("unused")
|
||||
open class PokemonEntity(
|
||||
world: World,
|
||||
pokemon: Pokemon = Pokemon(),
|
||||
type: EntityType<out PokemonEntity> = CobblemonEntities.POKEMON,
|
||||
) : TameableShoulderEntity(type, world), Poseable, Shearable, Schedulable, SmartBrainOwner<PokemonEntity> {
|
||||
) : TameableShoulderEntity(type, world), Poseable, Shearable, Schedulable {
|
||||
companion object {
|
||||
@JvmStatic val SPECIES = DataTracker.registerData(PokemonEntity::class.java, TrackedDataHandlerRegistry.STRING)
|
||||
@JvmStatic val NICKNAME = DataTracker.registerData(PokemonEntity::class.java, TrackedDataHandlerRegistry.TEXT_COMPONENT)
|
||||
@@ -156,45 +141,13 @@ open class PokemonEntity(
|
||||
@JvmStatic val UNBATTLEABLE = DataTracker.registerData(PokemonEntity::class.java, TrackedDataHandlerRegistry.BOOLEAN)
|
||||
@JvmStatic val COUNTS_TOWARDS_SPAWN_CAP = DataTracker.registerData(PokemonEntity::class.java, TrackedDataHandlerRegistry.BOOLEAN)
|
||||
@JvmStatic val SPAWN_DIRECTION = DataTracker.registerData(PokemonEntity::class.java, TrackedDataHandlerRegistry.FLOAT)
|
||||
@JvmStatic val FRIENDSHIP = DataTracker.registerData(PokemonEntity::class.java, TrackedDataHandlerRegistry.INTEGER)
|
||||
|
||||
const val BATTLE_LOCK = "battle"
|
||||
|
||||
fun createAttributes(): DefaultAttributeContainer.Builder = LivingEntity.createLivingAttributes()
|
||||
.add(EntityAttributes.GENERIC_FOLLOW_RANGE)
|
||||
.add(EntityAttributes.GENERIC_ATTACK_KNOCKBACK)
|
||||
|
||||
|
||||
val SENSORS: Collection<SensorType<out Sensor<in PokemonEntity>>> = listOf(
|
||||
SensorType.NEAREST_LIVING_ENTITIES,
|
||||
SensorType.HURT_BY,
|
||||
SensorType.NEAREST_PLAYERS,
|
||||
CobblemonSensors.POKEMON_DROWSY
|
||||
// CobblemonSensors.BATTLING_POKEMON,
|
||||
// CobblemonSensors.NPC_BATTLING
|
||||
)
|
||||
|
||||
val MEMORY_MODULES: List<MemoryModuleType<*>> = ImmutableList.of(
|
||||
MemoryModuleType.LOOK_TARGET,
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
MemoryModuleType.ATTACK_TARGET,
|
||||
MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE,
|
||||
MemoryModuleType.PATH,
|
||||
MemoryModuleType.IS_PANICKING,
|
||||
MemoryModuleType.VISIBLE_MOBS,
|
||||
CobblemonMemories.POKEMON_FLYING,
|
||||
// CobblemonMemories.NPC_BATTLING,
|
||||
// CobblemonMemories.BATTLING_POKEMON,
|
||||
MemoryModuleType.HURT_BY,
|
||||
MemoryModuleType.HURT_BY_ENTITY,
|
||||
MemoryModuleType.NEAREST_VISIBLE_PLAYER,
|
||||
MemoryModuleType.ANGRY_AT,
|
||||
MemoryModuleType.ATTACK_COOLING_DOWN,
|
||||
CobblemonMemories.POKEMON_DROWSY,
|
||||
CobblemonMemories.POKEMON_BATTLE,
|
||||
MemoryModuleType.HOME,
|
||||
CobblemonMemories.REST_PATH_COOLDOWN,
|
||||
CobblemonMemories.TARGETED_BATTLE_POKEMON
|
||||
)
|
||||
}
|
||||
val removalObservable = SimpleObservable<RemovalReason?>()
|
||||
/** A list of observable subscriptions related to this entity that need to be cleaned up when the entity is removed. */
|
||||
@@ -214,7 +167,6 @@ open class PokemonEntity(
|
||||
stepHeight = behaviour.moving.stepHeight
|
||||
// We need to update this value every time the Pokémon changes, other eye height related things will be dynamic.
|
||||
this.updateEyeHeight()
|
||||
setupTasks()
|
||||
}
|
||||
|
||||
var despawner: Despawner<PokemonEntity> = Cobblemon.bestSpawner.defaultPokemonDespawner
|
||||
@@ -233,10 +185,10 @@ open class PokemonEntity(
|
||||
var battleId: UUID?
|
||||
get() = dataTracker.get(BATTLE_ID).orElse(null)
|
||||
set(value) = dataTracker.set(BATTLE_ID, Optional.ofNullable(value))
|
||||
val battle: PokemonBattle?
|
||||
get() = battleId?.let { BattleRegistry.getBattle(it) }
|
||||
val isBattling: Boolean
|
||||
get() = dataTracker.get(BATTLE_ID).isPresent
|
||||
val friendship: Int
|
||||
get() = dataTracker.get(FRIENDSHIP)
|
||||
|
||||
var drops: DropTable? = null
|
||||
|
||||
@@ -283,7 +235,6 @@ open class PokemonEntity(
|
||||
delegate.initialize(this)
|
||||
delegate.changePokemon(pokemon)
|
||||
calculateDimensions()
|
||||
setupTasks()
|
||||
}
|
||||
|
||||
override fun initDataTracker() {
|
||||
@@ -303,7 +254,9 @@ open class PokemonEntity(
|
||||
dataTracker.startTracking(LABEL_LEVEL, 1)
|
||||
dataTracker.startTracking(HIDE_LABEL, false)
|
||||
dataTracker.startTracking(UNBATTLEABLE, false)
|
||||
dataTracker.startTracking(COUNTS_TOWARDS_SPAWN_CAP, true)
|
||||
dataTracker.startTracking(SPAWN_DIRECTION, world.random.nextFloat() * 360F)
|
||||
dataTracker.startTracking(FRIENDSHIP, 0)
|
||||
}
|
||||
|
||||
override fun onTrackedDataSet(data: TrackedData<*>) {
|
||||
@@ -327,10 +280,8 @@ open class PokemonEntity(
|
||||
if (battleId != null) {
|
||||
busyLocks.remove(BATTLE_LOCK) // Remove in case it's hopped across to another battle, don't want extra battle locks
|
||||
busyLocks.add(BATTLE_LOCK)
|
||||
brain.remember(CobblemonMemories.POKEMON_BATTLE, battleId)
|
||||
} else {
|
||||
busyLocks.remove(BATTLE_LOCK)
|
||||
brain.forget(CobblemonMemories.POKEMON_BATTLE)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -385,15 +336,25 @@ open class PokemonEntity(
|
||||
this.tethering = null
|
||||
this.pokemon.recall()
|
||||
}
|
||||
//This is so that pokemon in the pasture block are ALWAYS in sync with the pokemon box
|
||||
//Before, pokemon entities in pastures would hold an old ref to a pokemon obj and changes to that would not appear to the underlying file
|
||||
if (this.tethering != null) {
|
||||
//Only for online players
|
||||
if (world.getPlayerByUuid(ownerUuid) != null){
|
||||
this.ownerUuid?.let {
|
||||
val actualPokemon = Cobblemon.storage.getPC(it)[this.pokemon.uuid]
|
||||
actualPokemon?.let {
|
||||
if (it !== pokemon) {
|
||||
pokemon = it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
schedulingTracker.update(1/20F)
|
||||
}
|
||||
|
||||
override fun mobTick() {
|
||||
super.mobTick()
|
||||
tickBrain(this)
|
||||
}
|
||||
|
||||
fun setMoveControl(moveControl: MoveControl) {
|
||||
this.moveControl = moveControl
|
||||
}
|
||||
@@ -591,131 +552,46 @@ open class PokemonEntity(
|
||||
override fun getNavigation() = navigation as PokemonNavigation
|
||||
override fun createNavigation(world: World) = PokemonNavigation(world, this)
|
||||
|
||||
@Suppress("KotlinConstantConditions")
|
||||
// Brain.Profile is final and Kotlin error's, but this cast is safe.
|
||||
override fun createBrainProfile() = SmartBrainProvider(this) as Brain.Profile<*>
|
||||
|
||||
override fun getSensors(): List<ExtendedSensor<PokemonEntity>> {
|
||||
return listOf(
|
||||
NearbyLivingEntitySensor(),
|
||||
HurtBySensor(),
|
||||
NearbyPlayersSensor(),
|
||||
DrowsySensor()
|
||||
)
|
||||
}
|
||||
|
||||
override fun initGoals() {
|
||||
super.initGoals()
|
||||
@Suppress("SENSELESS_COMPARISON")
|
||||
public override fun initGoals() {
|
||||
// DO NOT REMOVE
|
||||
// LivingEntity#getActiveEyeHeight is called in the constructor of Entity
|
||||
// Pokémon param is not available yet
|
||||
if (this.pokemon == null) {
|
||||
return
|
||||
}
|
||||
moveControl = PokemonMoveControl(this)
|
||||
}
|
||||
|
||||
override fun onFinishPathfinding() {
|
||||
super.onFinishPathfinding()
|
||||
(moveControl as PokemonMoveControl).stop()
|
||||
}
|
||||
|
||||
override fun getCoreTasks(): BrainActivityGroup<PokemonEntity> {
|
||||
val tasks: MutableList<MultiTickTask<in PokemonEntity>> = mutableListOf()
|
||||
if (!pokemon.form.behaviour.moving.swim.canBreatheUnderwater) {
|
||||
tasks.add(StayAfloatTask(0.8F))
|
||||
}
|
||||
tasks.add(GetAngryAtAttackerTask())
|
||||
tasks.add(ForgetAngryAtTargetTask.create())
|
||||
tasks.add(HandleBattleActivityGoal.create())
|
||||
tasks.add(FollowWalkTargetTask())
|
||||
|
||||
return BrainActivityGroup.coreTasks(
|
||||
tasks
|
||||
)
|
||||
}
|
||||
|
||||
fun getIdleTasks(): List<com.mojang.datafixers.util.Pair<Int, Task<in PokemonEntity>>> {
|
||||
val tasks: MutableList<com.mojang.datafixers.util.Pair<Int, Task<in PokemonEntity>>> = mutableListOf()
|
||||
if (pokemon.form.behaviour.moving.canLook) {
|
||||
if (pokemon.form.behaviour.moving.looksAtEntities) {
|
||||
tasks.add(0 toDF LookAtMobTask.create(15F))
|
||||
goalSelector.clear { true }
|
||||
goalSelector.add(0, PokemonInBattleMovementGoal(this, 10))
|
||||
goalSelector.add(0, object : Goal() {
|
||||
override fun canStart() = this@PokemonEntity.dataTracker.get(PHASING_TARGET_ID) != -1 || pokemon.status?.status == Statuses.SLEEP || dataTracker.get(DYING_EFFECTS_STARTED) || evolutionEntity != null
|
||||
override fun shouldContinue(): Boolean {
|
||||
if (pokemon.status?.status == Statuses.SLEEP && !canSleep() && !isBusy) {
|
||||
return false
|
||||
} else if (pokemon.status?.status == Statuses.SLEEP || isBusy) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
tasks.add(0 toDF LookAroundTask(45, 90))
|
||||
override fun getControls() = EnumSet.allOf(Control::class.java)
|
||||
})
|
||||
|
||||
goalSelector.add(1, PokemonBreatheAirGoal(this))
|
||||
goalSelector.add(2, PokemonFloatToSurfaceGoal(this))
|
||||
goalSelector.add(3, PokemonFollowOwnerGoal(this, 1.0, 8F, 2F, false))
|
||||
goalSelector.add(4, PokemonMoveIntoFluidGoal(this))
|
||||
goalSelector.add(5, SleepOnTrainerGoal(this))
|
||||
goalSelector.add(5, WildRestGoal(this))
|
||||
|
||||
if (pokemon.getFeature<FlagSpeciesFeature>(DataKeys.HAS_BEEN_SHEARED) != null) {
|
||||
goalSelector.add(5, EatGrassGoal(this))
|
||||
}
|
||||
tasks.add(0 toDF ChooseLandWanderTargetTask.create(pokemon.form.behaviour.moving.wanderChance, horizontalRange = 10, verticalRange = 5, walkSpeed = 0.33F, completionRange = 1))
|
||||
tasks.add(0 toDF GoToSleepTask.create())
|
||||
tasks.add(0 toDF FindRestingPlaceTask.create(16, 8))
|
||||
tasks.add(0 toDF EatGrassTask())
|
||||
tasks.add(0 toDF AttackAngryAtTask.create())
|
||||
tasks.add(0 toDF MoveToAttackTargetTask.create())
|
||||
tasks.add(0 toDF MoveToOwnerTask.create(completionRange = 4, maxDistance = 14F, teleportDistance = 24F))
|
||||
return tasks
|
||||
|
||||
goalSelector.add(6, PokemonWanderAroundGoal(this))
|
||||
goalSelector.add(7, PokemonLookAtEntityGoal(this, ServerPlayerEntity::class.java, 5F))
|
||||
goalSelector.add(8, PokemonPointAtSpawnGoal(this))
|
||||
}
|
||||
|
||||
fun getBattlingTasks(): List<com.mojang.datafixers.util.Pair<Int, Task<in PokemonEntity>>> {
|
||||
val tasks: MutableList<com.mojang.datafixers.util.Pair<Int, Task<in PokemonEntity>>> = mutableListOf()
|
||||
|
||||
tasks.add(0 toDF LookAtTargetedBattlePokemonTask.create())
|
||||
tasks.add(0 toDF LookAroundTask(Int.MAX_VALUE - 1, Int.MAX_VALUE - 1))
|
||||
|
||||
return tasks
|
||||
}
|
||||
|
||||
fun getSleepingTasks(): List<com.mojang.datafixers.util.Pair<Int, Task<in PokemonEntity>>> {
|
||||
val tasks: MutableList<com.mojang.datafixers.util.Pair<Int, Task<in PokemonEntity>>> = mutableListOf()
|
||||
tasks.add(1 toDF WakeUpTask.create())
|
||||
return tasks
|
||||
}
|
||||
|
||||
fun setupTasks() {
|
||||
val brain = this.getBrain()
|
||||
|
||||
brain.setTaskList(Activity.CORE, ImmutableList.copyOf(getCoreTasks()))
|
||||
brain.setTaskList(Activity.IDLE, ImmutableList.copyOf(getIdleTasks()))
|
||||
brain.setTaskList(CobblemonActivities.BATTLING_ACTIVITY, ImmutableList.copyOf(getBattlingTasks()))
|
||||
brain.setTaskList(CobblemonActivities.POKEMON_SLEEPING_ACTIVITY, ImmutableList.copyOf(getSleepingTasks()))
|
||||
|
||||
brain.setCoreActivities(setOf(Activity.CORE))
|
||||
brain.setDefaultActivity(Activity.IDLE)
|
||||
brain.resetPossibleActivities()
|
||||
}
|
||||
|
||||
//
|
||||
// @Suppress("SENSELESS_COMPARISON")
|
||||
// public override fun initGoals() {
|
||||
// // DO NOT REMOVE
|
||||
// // LivingEntity#getActiveEyeHeight is called in the constructor of Entity
|
||||
// // Pokémon param is not available yet
|
||||
// if (this.pokemon == null) {
|
||||
// return
|
||||
// }
|
||||
// moveControl = PokemonMoveControl(this)
|
||||
// goalSelector.clear { true }
|
||||
// goalSelector.add(0, PokemonInBattleMovementGoal(this, 10))
|
||||
// goalSelector.add(0, object : Goal() {
|
||||
// override fun canStart() = this@PokemonEntity.dataTracker.get(PHASING_TARGET_ID) != -1 || pokemon.status?.status == Statuses.SLEEP || dataTracker.get(DYING_EFFECTS_STARTED) || evolutionEntity != null
|
||||
// override fun shouldContinue(): Boolean {
|
||||
// if (pokemon.status?.status == Statuses.SLEEP && !canSleep() && !isBusy) {
|
||||
// return false
|
||||
// } else if (pokemon.status?.status == Statuses.SLEEP || isBusy) {
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
// override fun getControls() = EnumSet.allOf(Control::class.java)
|
||||
// })
|
||||
//
|
||||
// goalSelector.add(1, PokemonBreatheAirGoal(this))
|
||||
// goalSelector.add(2, PokemonFloatToSurfaceGoal(this))
|
||||
// goalSelector.add(3, PokemonFollowOwnerGoal(this, 1.0, 8F, 2F, false))
|
||||
// goalSelector.add(4, PokemonMoveIntoFluidGoal(this))
|
||||
// goalSelector.add(5, SleepOnTrainerGoal(this))
|
||||
// goalSelector.add(5, WildRestGoal(this))
|
||||
//
|
||||
// if (pokemon.getFeature<FlagSpeciesFeature>(DataKeys.HAS_BEEN_SHEARED) != null) {
|
||||
// goalSelector.add(5, EatGrassGoal(this))
|
||||
// }
|
||||
//
|
||||
// goalSelector.add(6, PokemonWanderAroundGoal(this))
|
||||
// goalSelector.add(7, PokemonLookAtEntityGoal(this, ServerPlayerEntity::class.java, 5F))
|
||||
// goalSelector.add(8, PokemonPointAtSpawnGoal(this))
|
||||
// }
|
||||
|
||||
fun canSleep(): Boolean {
|
||||
val rest = behaviour.resting
|
||||
val worldTime = (world.timeOfDay % 24000).toInt()
|
||||
@@ -731,25 +607,6 @@ open class PokemonEntity(
|
||||
(rest.biomes.isEmpty() || rest.biomes.any { it.fits(biome, this.world.registryManager.get(RegistryKeys.BIOME)) })
|
||||
}
|
||||
|
||||
fun canSleepAt(pos: BlockPos): Boolean {
|
||||
val rest = behaviour.resting
|
||||
val light = world.getLightLevel(pos)
|
||||
val blockState = world.getBlockState(pos)
|
||||
val block = blockState.block
|
||||
val biome = world.getBiome(pos).value()
|
||||
val seesSky = world.isSkyVisible(pos.up())
|
||||
val fits = true
|
||||
val canStayAt = world.canEntityStayAt(pos, ceil(width).toInt(), ceil(height).toInt(), PositionType.LAND)
|
||||
|
||||
return light in rest.light &&
|
||||
(rest.skyLight == null || world.lightingProvider.get(LightType.SKY).getLightLevel(pos) in rest.skyLight) &&
|
||||
(rest.blocks.isEmpty() || rest.blocks.any { it.fits(block, this.world.registryManager.get(RegistryKeys.BLOCK)) }) &&
|
||||
(rest.biomes.isEmpty() || rest.biomes.any { it.fits(biome, this.world.registryManager.get(RegistryKeys.BIOME)) }) &&
|
||||
(rest.canSeeSky == null || rest.canSeeSky == seesSky) &&
|
||||
fits &&
|
||||
canStayAt
|
||||
}
|
||||
|
||||
override fun createChild(level: ServerWorld, partner: PassiveEntity) = null
|
||||
|
||||
override fun isReadyToSitOnPlayer(): Boolean {
|
||||
@@ -758,6 +615,7 @@ open class PokemonEntity(
|
||||
|
||||
override fun interactMob(player: PlayerEntity, hand: Hand) : ActionResult {
|
||||
val itemStack = player.getStackInHand(hand)
|
||||
val colorFeature = pokemon.getFeature<StringSpeciesFeature>(DataKeys.CAN_BE_COLORED)
|
||||
|
||||
if (itemStack.isOf(Items.SHEARS) && this.isShearable) {
|
||||
this.sheared(SoundCategory.PLAYERS)
|
||||
@@ -801,10 +659,7 @@ open class PokemonEntity(
|
||||
} else if (pokemon.lastFlowerFed.isOf(Items.POPPY) || pokemon.lastFlowerFed.isOf(Items.TORCHFLOWER)) {
|
||||
effect = StatusEffect.byRawId(16) // Night Vision
|
||||
duration = 100 // 5 seconds
|
||||
} else if (pokemon.lastFlowerFed.isOf(Items.PINK_TULIP) || pokemon.lastFlowerFed.isOf(Items.RED_TULIP) || pokemon.lastFlowerFed.isOf(
|
||||
Items.WHITE_TULIP
|
||||
) || pokemon.lastFlowerFed.isOf(Items.ORANGE_TULIP)
|
||||
) {
|
||||
} else if (pokemon.lastFlowerFed.isOf(Items.PINK_TULIP) || pokemon.lastFlowerFed.isOf(Items.RED_TULIP) || pokemon.lastFlowerFed.isOf(Items.WHITE_TULIP) || pokemon.lastFlowerFed.isOf(Items.ORANGE_TULIP)) {
|
||||
effect = StatusEffect.byRawId(18) // Weakness
|
||||
duration = 180 // 9 seconds
|
||||
} else if (pokemon.lastFlowerFed.isOf(Items.WITHER_ROSE)) {
|
||||
@@ -825,7 +680,8 @@ open class PokemonEntity(
|
||||
// reset the flower fed state
|
||||
pokemon.lastFlowerFed = ItemStack.EMPTY
|
||||
return ActionResult.success(world.isClient)
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
val mushroomStew = ItemUsage.exchangeStack(itemStack, player, Items.MUSHROOM_STEW.defaultStack)
|
||||
player.setStackInHand(hand, mushroomStew)
|
||||
return ActionResult.success(world.isClient)
|
||||
@@ -865,6 +721,22 @@ open class PokemonEntity(
|
||||
return ActionResult.SUCCESS
|
||||
}
|
||||
}
|
||||
else if (itemStack.item is DyeItem && colorFeature != null) {
|
||||
val item = itemStack.item as DyeItem
|
||||
if (item.color.name.lowercase() != colorFeature.value.lowercase()) {
|
||||
itemStack.decrement(1)
|
||||
colorFeature.value = item.color.name.lowercase()
|
||||
this.pokemon.markFeatureDirty(colorFeature)
|
||||
this.pokemon.updateAspects()
|
||||
}
|
||||
}
|
||||
else if (itemStack.item.equals(Items.WATER_BUCKET) && colorFeature != null) {
|
||||
itemStack.decrement(1)
|
||||
player.giveOrDropItemStack(Items.BUCKET.defaultStack)
|
||||
colorFeature.value = ""
|
||||
this.pokemon.markFeatureDirty(colorFeature)
|
||||
this.pokemon.updateAspects()
|
||||
}
|
||||
|
||||
|
||||
if (hand == Hand.MAIN_HAND && player is ServerPlayerEntity && pokemon.getOwnerPlayer() == player) {
|
||||
@@ -993,7 +865,7 @@ open class PokemonEntity(
|
||||
// Check evolution item interaction
|
||||
if (pokemon.getOwnerPlayer() == player) {
|
||||
val context = ItemInteractionEvolution.ItemInteractionContext(stack, player.world)
|
||||
pokemon.evolutions
|
||||
pokemon.lockedEvolutions
|
||||
.filterIsInstance<ItemInteractionEvolution>()
|
||||
.forEach { evolution ->
|
||||
if (evolution.attemptEvolution(pokemon, context)) {
|
||||
@@ -1291,8 +1163,26 @@ open class PokemonEntity(
|
||||
this.pokemon.markFeatureDirty(feature)
|
||||
this.pokemon.updateAspects()
|
||||
val i = this.random.nextInt(3) + 1
|
||||
for (j in 0 until i) {
|
||||
val itemEntity = this.dropItem(Items.WHITE_WOOL, 1) ?: return
|
||||
for (j in 0 .. i) {
|
||||
val color = this.pokemon.getFeature<StringSpeciesFeature>(DataKeys.CAN_BE_COLORED)?.value ?: "white"
|
||||
val woolItem = when (color) {
|
||||
"black" -> Items.BLACK_WOOL
|
||||
"blue" -> Items.BLUE_WOOL
|
||||
"brown" -> Items.BROWN_WOOL
|
||||
"cyan" -> Items.CYAN_WOOL
|
||||
"gray" -> Items.GRAY_WOOL
|
||||
"green" -> Items.GREEN_WOOL
|
||||
"light-blue" -> Items.LIGHT_BLUE_WOOL
|
||||
"light-gray" -> Items.LIGHT_GRAY_WOOL
|
||||
"lime" -> Items.LIME_WOOL
|
||||
"magenta" -> Items.MAGENTA_WOOL
|
||||
"orange" -> Items.ORANGE_WOOL
|
||||
"purple" -> Items.PURPLE_WOOL
|
||||
"red" -> Items.RED_WOOL
|
||||
"yellow" -> Items.YELLOW_WOOL
|
||||
else -> Items.WHITE_WOOL
|
||||
}
|
||||
val itemEntity = this.dropItem(woolItem, 1) ?: return
|
||||
itemEntity.velocity = itemEntity.velocity.add(
|
||||
((this.random.nextFloat() - this.random.nextFloat()) * 0.1f).toDouble(),
|
||||
(this.random.nextFloat() * 0.05f).toDouble(),
|
||||
@@ -1306,6 +1196,8 @@ open class PokemonEntity(
|
||||
return !this.isBusy && !this.pokemon.isFainted() && !feature.enabled
|
||||
}
|
||||
|
||||
|
||||
|
||||
override fun canUsePortals() = false
|
||||
|
||||
override fun setAir(air: Int) {
|
||||
|
||||
+20
-14
@@ -43,7 +43,7 @@ class PokemonServerDelegate : PokemonSideDelegate {
|
||||
|
||||
override fun changePokemon(pokemon: Pokemon) {
|
||||
updatePathfindingPenalties(pokemon)
|
||||
// entity.initGoals()
|
||||
entity.initGoals()
|
||||
updateMaxHealth()
|
||||
}
|
||||
|
||||
@@ -92,10 +92,28 @@ class PokemonServerDelegate : PokemonSideDelegate {
|
||||
speed = 0.1F
|
||||
entity.despawner.beginTracking(this)
|
||||
}
|
||||
updateTrackedValues()
|
||||
}
|
||||
|
||||
fun getBattle() = entity.battleId?.let(BattleRegistry::getBattle)
|
||||
|
||||
fun updateTrackedValues() {
|
||||
val trackedSpecies = mock?.species ?: entity.pokemon.species.resourceIdentifier.toString()
|
||||
val trackedNickname = mock?.nickname ?: entity.pokemon.nickname ?: Text.empty()
|
||||
val trackedAspects = mock?.aspects ?: entity.pokemon.aspects
|
||||
|
||||
entity.dataTracker.set(PokemonEntity.SPECIES, trackedSpecies)
|
||||
if (entity.dataTracker.get(PokemonEntity.NICKNAME) != trackedNickname) {
|
||||
entity.dataTracker.set(PokemonEntity.NICKNAME, trackedNickname)
|
||||
}
|
||||
entity.dataTracker.set(PokemonEntity.ASPECTS, trackedAspects)
|
||||
entity.dataTracker.set(PokemonEntity.LABEL_LEVEL, entity.pokemon.level)
|
||||
entity.dataTracker.set(PokemonEntity.MOVING, entity.velocity.multiply(1.0, if (entity.isOnGround) 0.0 else 1.0, 1.0).length() > 0.005F)
|
||||
entity.dataTracker.set(PokemonEntity.FRIENDSHIP, entity.pokemon.friendship)
|
||||
|
||||
updatePoseType()
|
||||
}
|
||||
|
||||
override fun onTrackedDataSet(data: TrackedData<*>) {
|
||||
super.onTrackedDataSet(data)
|
||||
if (this::entity.isInitialized) {
|
||||
@@ -162,19 +180,7 @@ class PokemonServerDelegate : PokemonSideDelegate {
|
||||
entity.remove(Entity.RemovalReason.DISCARDED)
|
||||
}
|
||||
|
||||
val trackedSpecies = mock?.species ?: entity.pokemon.species.resourceIdentifier.toString()
|
||||
val trackedNickname = mock?.nickname ?: entity.pokemon.nickname ?: Text.empty()
|
||||
val trackedAspects = mock?.aspects ?: entity.pokemon.aspects
|
||||
|
||||
entity.dataTracker.set(PokemonEntity.SPECIES, trackedSpecies)
|
||||
if (entity.dataTracker.get(PokemonEntity.NICKNAME) != trackedNickname) {
|
||||
entity.dataTracker.set(PokemonEntity.NICKNAME, trackedNickname)
|
||||
}
|
||||
entity.dataTracker.set(PokemonEntity.ASPECTS, trackedAspects)
|
||||
entity.dataTracker.set(PokemonEntity.LABEL_LEVEL, entity.pokemon.level)
|
||||
entity.dataTracker.set(PokemonEntity.MOVING, entity.velocity.multiply(1.0, if (entity.isOnGround) 0.0 else 1.0, 1.0).length() > 0.005F)
|
||||
|
||||
updatePoseType()
|
||||
updateTrackedValues()
|
||||
}
|
||||
|
||||
fun updatePoseType() {
|
||||
|
||||
+2
-8
@@ -34,7 +34,7 @@ class PokemonMoveControl(val pokemonEntity: PokemonEntity) : MoveControl(pokemon
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
if (pokemonEntity.isDead) {
|
||||
if (pokemonEntity.pokemon.status?.status == Statuses.SLEEP || pokemonEntity.isDead) {
|
||||
pokemonEntity.movementSpeed = 0F
|
||||
pokemonEntity.upwardSpeed = 0F
|
||||
return
|
||||
@@ -47,7 +47,7 @@ class PokemonMoveControl(val pokemonEntity: PokemonEntity) : MoveControl(pokemon
|
||||
behaviour.moving.swim.swimSpeed
|
||||
} else {
|
||||
behaviour.moving.walk.walkSpeed
|
||||
} * 2.5F
|
||||
}
|
||||
|
||||
val baseSpeed = entity.getAttributeValue(EntityAttributes.GENERIC_MOVEMENT_SPEED).toFloat() * this.speed.toFloat()
|
||||
val adjustedSpeed = baseSpeed * mediumSpeed
|
||||
@@ -203,10 +203,4 @@ class PokemonMoveControl(val pokemonEntity: PokemonEntity) : MoveControl(pokemon
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
state = State.WAIT
|
||||
forwardMovement = 0.0f
|
||||
sidewaysMovement = 0.0f
|
||||
}
|
||||
}
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.entity.pokemon.ai.sensors
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.CobblemonSensors
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.entity.ai.brain.MemoryModuleType
|
||||
import net.minecraft.entity.ai.brain.sensor.SensorType
|
||||
import net.minecraft.server.world.ServerWorld
|
||||
import net.tslat.smartbrainlib.api.core.sensor.ExtendedSensor
|
||||
|
||||
/**
|
||||
* Senses when the Pokémon is in a situation that would make it ready to sleep.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since March 23rd, 2024
|
||||
*/
|
||||
class DrowsySensor : ExtendedSensor<PokemonEntity>() {
|
||||
override fun memoriesUsed(): List<MemoryModuleType<*>> {
|
||||
return listOf(
|
||||
CobblemonMemories.POKEMON_DROWSY
|
||||
)
|
||||
}
|
||||
|
||||
override fun type(): SensorType<out ExtendedSensor<*>> {
|
||||
return CobblemonSensors.POKEMON_DROWSY
|
||||
}
|
||||
|
||||
override fun sense(world: ServerWorld, entity: PokemonEntity) {
|
||||
val rest = entity.behaviour.resting
|
||||
val isDrowsy = entity.brain.getOptionalRegisteredMemory(CobblemonMemories.POKEMON_DROWSY).orElse(false)
|
||||
val shouldBeDrowsy = rest.canSleep && world.timeOfDay.toInt() in rest.times
|
||||
if (!isDrowsy && shouldBeDrowsy) {
|
||||
entity.brain.remember(CobblemonMemories.POKEMON_DROWSY, true)
|
||||
} else if (isDrowsy && !shouldBeDrowsy) {
|
||||
entity.brain.forget(CobblemonMemories.POKEMON_DROWSY)
|
||||
}
|
||||
}
|
||||
}
|
||||
-88
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.entity.pokemon.ai.tasks
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.FlagSpeciesFeature
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.google.common.collect.ImmutableMap
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.Blocks
|
||||
import net.minecraft.entity.ai.brain.MemoryModuleState
|
||||
import net.minecraft.entity.ai.brain.MemoryModuleType
|
||||
import net.minecraft.entity.ai.brain.task.MultiTickTask
|
||||
import net.minecraft.predicate.block.BlockStatePredicate
|
||||
import net.minecraft.server.world.ServerWorld
|
||||
import net.minecraft.world.GameRules
|
||||
|
||||
/**
|
||||
* The baa's eat the graa's
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since April 6th, 2024
|
||||
*/
|
||||
class EatGrassTask : MultiTickTask<PokemonEntity>(
|
||||
ImmutableMap.of(
|
||||
MemoryModuleType.ANGRY_AT, MemoryModuleState.VALUE_ABSENT,
|
||||
MemoryModuleType.ATTACK_TARGET, MemoryModuleState.VALUE_ABSENT,
|
||||
MemoryModuleType.WALK_TARGET, MemoryModuleState.VALUE_ABSENT,
|
||||
CobblemonMemories.POKEMON_BATTLE, MemoryModuleState.VALUE_ABSENT
|
||||
)
|
||||
) {
|
||||
val grassPredicate = BlockStatePredicate.forBlock(Blocks.GRASS)
|
||||
var timer = -1
|
||||
|
||||
override fun shouldRun(world: ServerWorld, entity: PokemonEntity): Boolean {
|
||||
if (entity.random.nextInt(500) != 0) {
|
||||
return false
|
||||
} else {
|
||||
entity.pokemon.getFeature<FlagSpeciesFeature>(DataKeys.HAS_BEEN_SHEARED)?.enabled?.takeIf { it } ?: run {
|
||||
return false
|
||||
}
|
||||
val blockPos = entity.blockPos
|
||||
if (grassPredicate.test(world.getBlockState(blockPos)) ) {
|
||||
return true
|
||||
} else if (world.getBlockState(blockPos.down()).isOf(Blocks.GRASS_BLOCK)) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
override fun run(world: ServerWorld, entity: PokemonEntity, time: Long) {
|
||||
timer = 40
|
||||
world.sendEntityStatus(entity, 10.toByte())
|
||||
}
|
||||
|
||||
override fun shouldKeepRunning(world: ServerWorld, entity: PokemonEntity, time: Long): Boolean {
|
||||
timer--
|
||||
if (timer < 0) {
|
||||
val blockPos = entity.blockPos
|
||||
if (grassPredicate.test(world.getBlockState(blockPos)) ) {
|
||||
if (world.gameRules.getBoolean(GameRules.DO_MOB_GRIEFING)) {
|
||||
world.breakBlock(blockPos, false)
|
||||
}
|
||||
entity.onEatingGrass()
|
||||
} else if (world.getBlockState(blockPos.down()).isOf(Blocks.GRASS_BLOCK)) {
|
||||
val blockPos2 = blockPos.down()
|
||||
if (world.getBlockState(blockPos2).isOf(Blocks.GRASS_BLOCK)) {
|
||||
if (world.gameRules.getBoolean(GameRules.DO_MOB_GRIEFING)) {
|
||||
world.syncWorldEvent(2001, blockPos2, Block.getRawIdFromState(Blocks.GRASS_BLOCK.defaultState))
|
||||
world.setBlockState(blockPos2, Blocks.DIRT.defaultState, 2)
|
||||
}
|
||||
|
||||
entity.onEatingGrass()
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.entity.pokemon.ai.tasks
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.getBlockPositions
|
||||
import net.minecraft.entity.ai.brain.MemoryModuleType
|
||||
import net.minecraft.entity.ai.brain.WalkTarget
|
||||
import net.minecraft.entity.ai.brain.task.SingleTickTask
|
||||
import net.minecraft.entity.ai.brain.task.TaskRunnable
|
||||
import net.minecraft.entity.ai.brain.task.TaskTriggerer
|
||||
import net.minecraft.util.math.Box
|
||||
|
||||
object FindRestingPlaceTask {
|
||||
fun create(horizontalSearchDistance: Int, verticalSearchDistance: Int): SingleTickTask<PokemonEntity> {
|
||||
return TaskTriggerer.task {
|
||||
it.group(
|
||||
it.queryMemoryAbsent(MemoryModuleType.ANGRY_AT),
|
||||
it.queryMemoryAbsent(MemoryModuleType.ATTACK_TARGET),
|
||||
it.queryMemoryAbsent(MemoryModuleType.WALK_TARGET),
|
||||
it.queryMemoryAbsent(CobblemonMemories.POKEMON_BATTLE),
|
||||
it.queryMemoryValue(CobblemonMemories.POKEMON_DROWSY),
|
||||
it.queryMemoryAbsent(CobblemonMemories.REST_PATH_COOLDOWN)
|
||||
).apply(it) { _, _, walkTarget, _, pokemonDrowsy, restPathCooldown ->
|
||||
TaskRunnable { world, entity, _ ->
|
||||
return@TaskRunnable if (it.getValue(pokemonDrowsy) && entity.pokemon.status?.status != Statuses.SLEEP && entity.pokemon.storeCoordinates.get()?.store !is PartyStore) {
|
||||
entity.brain.remember(CobblemonMemories.REST_PATH_COOLDOWN, true, 40)
|
||||
val position = entity.world
|
||||
.getBlockPositions(Box.of(entity.pos, horizontalSearchDistance.toDouble(), verticalSearchDistance.toDouble(), horizontalSearchDistance.toDouble()))
|
||||
.filter(entity::canSleepAt)
|
||||
// .randomOrNull()
|
||||
.minByOrNull { it.getSquaredDistance(entity.pos) }
|
||||
if (position != null) {
|
||||
walkTarget.remember(WalkTarget(position.down(), 0.3F, 1))
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.entity.pokemon.ai.tasks
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonActivities
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.status.PersistentStatusContainer
|
||||
import net.minecraft.entity.ai.brain.MemoryModuleType
|
||||
import net.minecraft.entity.ai.brain.task.SingleTickTask
|
||||
import net.minecraft.entity.ai.brain.task.TaskRunnable
|
||||
import net.minecraft.entity.ai.brain.task.TaskTriggerer
|
||||
|
||||
object GoToSleepTask {
|
||||
fun create(): SingleTickTask<PokemonEntity> {
|
||||
return TaskTriggerer.task {
|
||||
it.group(
|
||||
it.queryMemoryAbsent(MemoryModuleType.ANGRY_AT),
|
||||
it.queryMemoryAbsent(MemoryModuleType.ATTACK_TARGET),
|
||||
it.queryMemoryAbsent(MemoryModuleType.WALK_TARGET),
|
||||
it.queryMemoryAbsent(CobblemonMemories.POKEMON_BATTLE),
|
||||
it.queryMemoryOptional(CobblemonMemories.POKEMON_DROWSY)
|
||||
).apply(it) { _, _, _, _, pokemonDrowsy ->
|
||||
TaskRunnable { world, entity, _ ->
|
||||
val hasSleepStatus = entity.pokemon.status?.status === Statuses.SLEEP
|
||||
if (entity.behaviour.resting.canSleep && ((it.getOptionalValue(pokemonDrowsy).orElse(false) && entity.canSleepAt(entity.blockPos.down())) || hasSleepStatus) && entity.pokemon.storeCoordinates.get()?.store !is PartyStore) {
|
||||
if (!hasSleepStatus) {
|
||||
entity.pokemon.status = PersistentStatusContainer(Statuses.SLEEP)
|
||||
}
|
||||
entity.brain.resetPossibleActivities(listOf(CobblemonActivities.POKEMON_SLEEPING_ACTIVITY))
|
||||
return@TaskRunnable true
|
||||
} else {
|
||||
return@TaskRunnable false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.entity.pokemon.ai.tasks
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonActivities
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.entity.ai.brain.Activity
|
||||
import net.minecraft.entity.ai.brain.MemoryModuleType
|
||||
import net.minecraft.entity.ai.brain.task.SingleTickTask
|
||||
import net.minecraft.entity.ai.brain.task.TaskRunnable
|
||||
import net.minecraft.entity.ai.brain.task.TaskTriggerer
|
||||
|
||||
/**
|
||||
* Moves Pokémon in and out of the battling activity.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since April 8th, 2024
|
||||
*/
|
||||
object HandleBattleActivityGoal {
|
||||
fun create(): SingleTickTask<PokemonEntity> {
|
||||
return TaskTriggerer.task {
|
||||
it.group(
|
||||
it.queryMemoryOptional(CobblemonMemories.POKEMON_BATTLE),
|
||||
it.queryMemoryOptional(MemoryModuleType.WALK_TARGET),
|
||||
it.queryMemoryOptional(MemoryModuleType.LOOK_TARGET),
|
||||
).apply(it) { battle, walkTarget, lookTarget ->
|
||||
TaskRunnable { world, entity, _ ->
|
||||
val battleUUID = it.getOptionalValue(battle).orElse(null)
|
||||
if (battleUUID != null && !entity.brain.hasActivity(CobblemonActivities.BATTLING_ACTIVITY)) {
|
||||
entity.brain.resetPossibleActivities(listOf(CobblemonActivities.BATTLING_ACTIVITY))
|
||||
entity.brain.forget(MemoryModuleType.WALK_TARGET)
|
||||
entity.brain.forget(MemoryModuleType.LOOK_TARGET)
|
||||
entity.navigation.stop()
|
||||
return@TaskRunnable true
|
||||
} else if (battleUUID == null && entity.brain.hasActivity(CobblemonActivities.BATTLING_ACTIVITY)) {
|
||||
entity.brain.resetPossibleActivities(listOf(Activity.IDLE))
|
||||
entity.brain.forget(MemoryModuleType.WALK_TARGET)
|
||||
entity.brain.forget(MemoryModuleType.LOOK_TARGET)
|
||||
return@TaskRunnable true
|
||||
}
|
||||
return@TaskRunnable false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.entity.pokemon.ai.tasks
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.entity.ai.brain.EntityLookTarget
|
||||
import net.minecraft.entity.ai.brain.MemoryModuleType
|
||||
import net.minecraft.entity.ai.brain.task.SingleTickTask
|
||||
import net.minecraft.entity.ai.brain.task.TaskRunnable
|
||||
import net.minecraft.entity.ai.brain.task.TaskTriggerer
|
||||
|
||||
/**
|
||||
* Manages the look target of a Pokémon in battle.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since April 8th, 2024
|
||||
*/
|
||||
object LookAtTargetedBattlePokemonTask {
|
||||
fun create(): SingleTickTask<PokemonEntity> {
|
||||
return TaskTriggerer.task {
|
||||
it.group(
|
||||
it.queryMemoryValue(CobblemonMemories.POKEMON_BATTLE),
|
||||
it.queryMemoryOptional(CobblemonMemories.TARGETED_BATTLE_POKEMON),
|
||||
it.queryMemoryOptional(MemoryModuleType.LOOK_TARGET),
|
||||
).apply(it) { _, targetedBattlePokemon, lookTarget ->
|
||||
TaskRunnable { world, entity, _ ->
|
||||
val targeted = it.getOptionalValue(targetedBattlePokemon).orElse(null)
|
||||
val targetedEntity = targeted?.let { world.getEntity(it) as? PokemonEntity }
|
||||
val look = it.getOptionalValue(lookTarget).orElse(null) as? EntityLookTarget
|
||||
if (targeted != null && targetedEntity == null) {
|
||||
entity.brain.forget(CobblemonMemories.TARGETED_BATTLE_POKEMON)
|
||||
return@TaskRunnable false
|
||||
} else if (targetedEntity != null && look?.entity != targetedEntity) {
|
||||
entity.brain.remember(MemoryModuleType.LOOK_TARGET, EntityLookTarget(targetedEntity, true))
|
||||
return@TaskRunnable true
|
||||
} else if (targetedEntity == null) {
|
||||
val battle = entity.battle ?: return@TaskRunnable false
|
||||
val nearestOpposingPokemon = battle.sides
|
||||
.find { entity in it.actors.flatMap { it.pokemonList.map { it.entity } } }
|
||||
?.getOppositeSide()?.actors
|
||||
?.flatMap { it.pokemonList.mapNotNull { it.entity } }
|
||||
?.minByOrNull { it.distanceTo(entity) }
|
||||
if (nearestOpposingPokemon != null) {
|
||||
entity.brain.remember(MemoryModuleType.LOOK_TARGET, EntityLookTarget(nearestOpposingPokemon, true))
|
||||
return@TaskRunnable true
|
||||
}
|
||||
}
|
||||
return@TaskRunnable false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-96
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.entity.pokemon.ai.tasks
|
||||
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import kotlin.math.abs
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.entity.ai.brain.EntityLookTarget
|
||||
import net.minecraft.entity.ai.brain.MemoryModuleType
|
||||
import net.minecraft.entity.ai.brain.WalkTarget
|
||||
import net.minecraft.entity.ai.brain.task.SingleTickTask
|
||||
import net.minecraft.entity.ai.brain.task.TaskRunnable
|
||||
import net.minecraft.entity.ai.brain.task.TaskTriggerer
|
||||
import net.minecraft.entity.ai.pathing.LandPathNodeMaker
|
||||
import net.minecraft.entity.ai.pathing.PathNodeType
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.random.Random
|
||||
|
||||
object MoveToOwnerTask {
|
||||
fun create(completionRange: Int, maxDistance: Float, teleportDistance: Float): SingleTickTask<PokemonEntity> = TaskTriggerer.task {
|
||||
it.group(
|
||||
it.queryMemoryOptional(MemoryModuleType.WALK_TARGET),
|
||||
it.queryMemoryAbsent(MemoryModuleType.ANGRY_AT)
|
||||
).apply(it) { walkTarget, _ ->
|
||||
TaskRunnable { _, entity, _ ->
|
||||
val owner = entity.owner ?: return@TaskRunnable false
|
||||
if (entity.pokemon.storeCoordinates.get()?.store !is PartyStore) {
|
||||
return@TaskRunnable false
|
||||
}
|
||||
if (entity.distanceTo(owner) > teleportDistance) {
|
||||
if (tryTeleport(entity, owner)) {
|
||||
entity.brain.forget(MemoryModuleType.LOOK_TARGET)
|
||||
entity.brain.forget(MemoryModuleType.WALK_TARGET)
|
||||
}
|
||||
return@TaskRunnable true
|
||||
} else if (entity.distanceTo(owner) > maxDistance && it.getOptionalValue(walkTarget).isEmpty) {
|
||||
entity.brain.remember(MemoryModuleType.LOOK_TARGET, EntityLookTarget(owner, true))
|
||||
entity.brain.remember(MemoryModuleType.WALK_TARGET, WalkTarget(owner, 0.4F, completionRange))
|
||||
return@TaskRunnable true
|
||||
}
|
||||
return@TaskRunnable false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryTeleport(entity: PokemonEntity, owner: Entity): Boolean {
|
||||
val blockPos = owner.blockPos
|
||||
for (i in 0..9) {
|
||||
val j = this.getRandomInt(entity.random, -3, 3)
|
||||
val k = this.getRandomInt(entity.random, -1, 1)
|
||||
val l = this.getRandomInt(entity.random, -3, 3)
|
||||
val succeeded = this.tryTeleportTo(entity, owner, blockPos.x + j, blockPos.y + k, blockPos.z + l)
|
||||
if (succeeded) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun tryTeleportTo(entity: PokemonEntity, owner: Entity, x: Int, y: Int, z: Int): Boolean {
|
||||
if (abs(x.toDouble() - owner.x) < 2.0 && abs(z - owner.z) < 2.0) {
|
||||
return false
|
||||
} else if (!this.canTeleportTo(entity, BlockPos(x, y, z))) {
|
||||
return false
|
||||
} else {
|
||||
entity.refreshPositionAndAngles(
|
||||
x.toDouble() + 0.5, y.toDouble(), z.toDouble() + 0.5,
|
||||
entity.yaw,
|
||||
entity.pitch
|
||||
)
|
||||
entity.navigation.stop()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
private fun canTeleportTo(entity: PokemonEntity, pos: BlockPos): Boolean {
|
||||
val pathNodeType = LandPathNodeMaker.getLandNodeType(entity.world, pos.mutableCopy())
|
||||
if (pathNodeType != PathNodeType.WALKABLE) {
|
||||
return false
|
||||
} else {
|
||||
val blockPos = pos.subtract(entity.blockPos)
|
||||
return entity.world.isSpaceEmpty(entity, entity.boundingBox.offset(blockPos))
|
||||
}
|
||||
}
|
||||
|
||||
private fun getRandomInt(random: Random, min: Int, max: Int): Int {
|
||||
return random.nextInt(max - min + 1) + min
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.entity.pokemon.ai.tasks
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.entity.ai.brain.task.SingleTickTask
|
||||
import net.minecraft.entity.ai.brain.task.TaskRunnable
|
||||
import net.minecraft.entity.ai.brain.task.TaskTriggerer
|
||||
|
||||
object WakeUpTask {
|
||||
fun create(): SingleTickTask<PokemonEntity> {
|
||||
return TaskTriggerer.task {
|
||||
it.group(
|
||||
it.queryMemoryAbsent(CobblemonMemories.POKEMON_BATTLE),
|
||||
it.queryMemoryAbsent(CobblemonMemories.POKEMON_DROWSY)
|
||||
).apply(it) { _, _ ->
|
||||
TaskRunnable { world, entity, _ ->
|
||||
if (entity.pokemon.status?.status == Statuses.SLEEP && entity.pokemon.storeCoordinates.get()?.store !is PartyStore) {
|
||||
entity.pokemon.status = null
|
||||
entity.brain.resetPossibleActivities()
|
||||
return@TaskRunnable true
|
||||
} else {
|
||||
return@TaskRunnable false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,9 +87,7 @@ object AdvancementHandler {
|
||||
event.battle.actors.forEach { battleActor ->
|
||||
if (!event.winners.contains(battleActor) && battleActor.type == ActorType.WILD) {
|
||||
battleActor.pokemonList.forEach { battlePokemon ->
|
||||
battlePokemon.entity?.pokemon?.let {
|
||||
advancementData.updateTotalDefeatedCount(it)
|
||||
}
|
||||
advancementData.updateTotalDefeatedCount(battlePokemon.originalPokemon)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,6 +218,7 @@ object CobblemonItemGroups {
|
||||
entries.add(CobblemonItems.MONITOR)
|
||||
entries.add(CobblemonItems.PC)
|
||||
entries.add(CobblemonItems.HEALING_MACHINE)
|
||||
entries.add(CobblemonItems.STADIUM)
|
||||
entries.add(CobblemonItems.PASTURE)
|
||||
|
||||
entries.add(CobblemonItems.GILDED_CHEST)
|
||||
|
||||
@@ -19,7 +19,7 @@ class LinkCableItem : CobblemonItem(Settings()), PokemonEntityInteraction {
|
||||
override val accepted = setOf(PokemonEntityInteraction.Ownership.OWNER)
|
||||
override fun processInteraction(player: ServerPlayerEntity, entity: PokemonEntity, stack: ItemStack): Boolean {
|
||||
val pokemon = entity.pokemon
|
||||
pokemon.evolutions.filterIsInstance<TradeEvolution>().forEach { evolution ->
|
||||
pokemon.lockedEvolutions.filterIsInstance<TradeEvolution>().forEach { evolution ->
|
||||
// If an evolution is possible non-optional or has been successfully queued we will consume the item and stop
|
||||
// validate requirements to respect required held items and such.
|
||||
if (evolution.requirements.all { it.check(pokemon) } && evolution.evolve(pokemon)) {
|
||||
|
||||
+6
-1
@@ -39,6 +39,7 @@ class SpawnPokemonPacket(
|
||||
private val hideLabel: Boolean,
|
||||
private val caughtBall: Identifier,
|
||||
private val spawnYaw: Float,
|
||||
private val friendship: Int,
|
||||
vanillaSpawnPacket: EntitySpawnS2CPacket
|
||||
) : SpawnExtraDataEntityPacket<SpawnPokemonPacket, PokemonEntity>(vanillaSpawnPacket) {
|
||||
|
||||
@@ -60,6 +61,7 @@ class SpawnPokemonPacket(
|
||||
entity.dataTracker.get(PokemonEntity.HIDE_LABEL),
|
||||
entity.pokemon.caughtBall.name,
|
||||
entity.dataTracker.get(PokemonEntity.SPAWN_DIRECTION),
|
||||
entity.dataTracker.get(PokemonEntity.FRIENDSHIP),
|
||||
vanillaSpawnPacket
|
||||
)
|
||||
|
||||
@@ -79,6 +81,7 @@ class SpawnPokemonPacket(
|
||||
buffer.writeBoolean(this.hideLabel)
|
||||
buffer.writeIdentifier(this.caughtBall)
|
||||
buffer.writeFloat(this.spawnYaw)
|
||||
buffer.writeInt(this.friendship)
|
||||
}
|
||||
|
||||
override fun applyData(entity: PokemonEntity) {
|
||||
@@ -101,6 +104,7 @@ class SpawnPokemonPacket(
|
||||
entity.dataTracker.set(PokemonEntity.UNBATTLEABLE, unbattlable)
|
||||
entity.dataTracker.set(PokemonEntity.HIDE_LABEL, hideLabel)
|
||||
entity.dataTracker.set(PokemonEntity.SPAWN_DIRECTION, spawnYaw)
|
||||
entity.dataTracker.set(PokemonEntity.FRIENDSHIP, friendship)
|
||||
}
|
||||
|
||||
override fun checkType(entity: Entity): Boolean = entity is PokemonEntity
|
||||
@@ -124,9 +128,10 @@ class SpawnPokemonPacket(
|
||||
val hideLabel = buffer.readBoolean()
|
||||
val caughtBall = buffer.readIdentifier()
|
||||
val spawnAngle = buffer.readFloat()
|
||||
val friendship = buffer.readInt()
|
||||
val vanillaPacket = decodeVanillaPacket(buffer)
|
||||
|
||||
return SpawnPokemonPacket(ownerId, scaleModifier, species, form, aspects, battleId, phasingTargetId, beamModeEmitter, nickname, labelLevel, poseType, unbattlable, hideLabel, caughtBall, spawnAngle, vanillaPacket)
|
||||
return SpawnPokemonPacket(ownerId, scaleModifier, species, form, aspects, battleId, phasingTargetId, beamModeEmitter, nickname, labelLevel, poseType, unbattlable, hideLabel, caughtBall, spawnAngle, friendship, vanillaPacket)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -426,6 +426,8 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
|
||||
// We want non-optional evolutions to trigger first to avoid unnecessary packets and any cost associate with an optional one that would just be lost
|
||||
val evolutions: Iterable<Evolution> get() = this.form.evolutions.sortedBy { evolution -> evolution.optional }
|
||||
val lockedEvolutions: Iterable<Evolution>
|
||||
get() = evolutions.filter { it !in evolutionProxy.current() }
|
||||
|
||||
val preEvolution: PreEvolution? get() = this.form.preEvolution
|
||||
|
||||
|
||||
@@ -28,8 +28,6 @@ class RestBehaviour {
|
||||
val biomes = mutableListOf<RegistryLikeCondition<Biome>>()
|
||||
val light = IntRange(0, 15)
|
||||
val depth = SleepDepth.normal
|
||||
val canSeeSky: Boolean? = null
|
||||
val skyLight: IntRange? = null
|
||||
|
||||
val willSleepOnBed = false
|
||||
}
|
||||
+2
-1
@@ -43,7 +43,8 @@ object CobblemonRequirementAdapter : RequirementAdapter {
|
||||
this.registerType(TimeRangeRequirement.ADAPTER_VARIANT, TimeRangeRequirement::class)
|
||||
this.registerType(LevelRequirement.ADAPTER_VARIANT, LevelRequirement::class)
|
||||
this.registerType(WeatherRequirement.ADAPTER_VARIANT, WeatherRequirement::class)
|
||||
this.registerType(AttackDefenceRatioRequirement.ADAPTER_VARIANT, AttackDefenceRatioRequirement::class)
|
||||
this.registerType(StatCompareRequirement.ADAPTER_VARIANT, StatCompareRequirement::class)
|
||||
this.registerType(StatEqualRequirement.ADAPTER_VARIANT, StatEqualRequirement::class)
|
||||
this.registerType(BattleCriticalHitsRequirement.ADAPTER_VARIANT, BattleCriticalHitsRequirement::class)
|
||||
this.registerType(DamageTakenRequirement.ADAPTER_VARIANT, DamageTakenRequirement::class)
|
||||
this.registerType(UseMoveRequirement.ADAPTER_VARIANT, UseMoveRequirement::class)
|
||||
|
||||
+7
-13
@@ -9,24 +9,18 @@
|
||||
package com.cobblemon.mod.common.pokemon.evolution.requirements
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.requirement.EvolutionRequirement
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
class AttackDefenceRatioRequirement : EvolutionRequirement {
|
||||
|
||||
class StatCompareRequirement : EvolutionRequirement {
|
||||
companion object {
|
||||
const val ADAPTER_VARIANT = "attack_defence_ratio"
|
||||
}
|
||||
enum class AttackDefenceRatio {
|
||||
ATTACK_HIGHER,
|
||||
DEFENCE_HIGHER,
|
||||
EQUAL
|
||||
const val ADAPTER_VARIANT = "stat_compare"
|
||||
}
|
||||
|
||||
val ratio = AttackDefenceRatio.ATTACK_HIGHER
|
||||
val highStat = Stats.ATTACK.name
|
||||
val lowStat = Stats.DEFENCE.name
|
||||
|
||||
override fun check(pokemon: Pokemon): Boolean {
|
||||
return when (ratio) {
|
||||
AttackDefenceRatio.ATTACK_HIGHER -> pokemon.attack > pokemon.defence
|
||||
AttackDefenceRatio.DEFENCE_HIGHER -> pokemon.defence > pokemon.attack
|
||||
AttackDefenceRatio.EQUAL -> pokemon.attack == pokemon.defence
|
||||
}
|
||||
return pokemon.getStat(Stats.getStat(highStat)) > pokemon.getStat(Stats.getStat(lowStat))
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.evolution.requirements
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.requirement.EvolutionRequirement
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
class StatEqualRequirement : EvolutionRequirement {
|
||||
companion object {
|
||||
const val ADAPTER_VARIANT = "stat_equal"
|
||||
}
|
||||
|
||||
val statOne = Stats.ATTACK.name
|
||||
val statTwo = Stats.DEFENCE.name
|
||||
|
||||
override fun check(pokemon: Pokemon): Boolean {
|
||||
return pokemon.getStat(Stats.getStat(statOne)) == pokemon.getStat(Stats.getStat(statTwo))
|
||||
}
|
||||
}
|
||||
@@ -98,11 +98,11 @@ object TradeManager {
|
||||
party2.add(pokemon1)
|
||||
party1.add(pokemon2)
|
||||
|
||||
pokemon1.evolutions.filterIsInstance<TradeEvolution>().firstOrNull {
|
||||
pokemon1.lockedEvolutions.filterIsInstance<TradeEvolution>().firstOrNull {
|
||||
it.attemptEvolution(pokemon1, pokemon2)
|
||||
}
|
||||
|
||||
pokemon2.evolutions.filterIsInstance<TradeEvolution>().firstOrNull {
|
||||
pokemon2.lockedEvolutions.filterIsInstance<TradeEvolution>().firstOrNull {
|
||||
it.attemptEvolution(pokemon2, pokemon1)
|
||||
}
|
||||
CobblemonEvents.TRADE_COMPLETED.post(TradeCompletedEvent(player1, pokemon2, player2, pokemon1))
|
||||
|
||||
@@ -134,6 +134,7 @@ object DataKeys {
|
||||
// Features
|
||||
const val CAN_BE_MILKED = "milkable"
|
||||
const val HAS_BEEN_SHEARED = "sheared"
|
||||
const val CAN_BE_COLORED = "color"
|
||||
|
||||
// Variants
|
||||
const val IS_MOOSHTANK = "mooshtank"
|
||||
|
||||
@@ -24,7 +24,7 @@ inline fun <reified T> Gson.fromJson(string: String) = fromJson(string, T::class
|
||||
* the list value identified by the plural name. During runtime only the plural exists, but when
|
||||
* configuring the JSON the user can use the singular form for a cleaner document.
|
||||
*/
|
||||
fun JsonObject.singularToPluralList(rootName: String, pluralName: String = "${rootName}s") {
|
||||
fun JsonObject.singularToPluralList(rootName: String, pluralName: String = "${rootName}s"): JsonObject {
|
||||
if (has(rootName)) {
|
||||
if (!has(pluralName)) {
|
||||
add(pluralName, JsonArray())
|
||||
@@ -32,6 +32,7 @@ fun JsonObject.singularToPluralList(rootName: String, pluralName: String = "${ro
|
||||
get(pluralName).asJsonArray.add(get(rootName))
|
||||
remove(rootName)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
fun JsonElement.normalizeToArray(): JsonArray {
|
||||
|
||||
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.util
|
||||
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.entity.ai.pathing.NavigationType
|
||||
import net.minecraft.item.Item
|
||||
import net.minecraft.particle.ParticleEffect
|
||||
import net.minecraft.registry.Registry
|
||||
@@ -98,19 +97,6 @@ fun BlockView.getBlockStatesWithPos(box: Box): Iterable<Pair<BlockState, BlockPo
|
||||
return states
|
||||
}
|
||||
|
||||
fun BlockView.getBlockPositions(box: Box): Iterable<BlockPos> {
|
||||
val positions = mutableListOf<BlockPos>()
|
||||
val (xRange, yRange, zRange) = box.getRanges()
|
||||
for (x in xRange) {
|
||||
for (y in yRange) {
|
||||
for (z in zRange) {
|
||||
positions.add(BlockPos(x, y, z))
|
||||
}
|
||||
}
|
||||
}
|
||||
return positions
|
||||
}
|
||||
|
||||
fun BlockView.getWaterAndLavaIn(box: Box): Pair<Boolean, Boolean> {
|
||||
var hasWater = false
|
||||
var hasLava = false
|
||||
@@ -134,63 +120,6 @@ fun Entity.canFit(vec: Vec3d): Boolean {
|
||||
return world.isSpaceEmpty(box)
|
||||
}
|
||||
|
||||
enum class PositionType {
|
||||
LAND,
|
||||
WATER,
|
||||
SEAFLOOR,
|
||||
LAVAFLOOR
|
||||
}
|
||||
|
||||
fun World.canEntityStayAt(position: BlockPos, width: Int = 1, height: Int = 1, positionType: PositionType): Boolean {
|
||||
val minX = kotlin.math.floor(position.x + 0.5 - (width - 1) / 2F).toInt()
|
||||
val maxX = kotlin.math.ceil(position.x + 0.5 + (width - 1) / 2F).toInt()
|
||||
val maxY = position.y + height
|
||||
|
||||
val minZ = kotlin.math.floor(position.z + 0.5 - (width - 1) / 2F).toInt()
|
||||
val maxZ = kotlin.math.ceil(position.z + 0.5 + (width - 1) / 2F).toInt()
|
||||
|
||||
val mutable = BlockPos.Mutable()
|
||||
for (x in minX until maxX) {
|
||||
for (y in position.y..maxY) {
|
||||
for (z in minZ until maxZ) {
|
||||
val state = getBlockState(mutable.set(x, y, z))
|
||||
|
||||
// If it's a floor check, we likely need to do something different than surrounding blocks
|
||||
if (y == position.y) {
|
||||
if (positionType == PositionType.LAND) {
|
||||
// Land entities need to be standing on solid ground
|
||||
if (state.canPathfindThrough(this, mutable, NavigationType.LAND)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
when (positionType) {
|
||||
PositionType.LAND -> {
|
||||
if (!state.canPathfindThrough(this, mutable, NavigationType.LAND)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
PositionType.WATER, PositionType.SEAFLOOR -> {
|
||||
if (!state.fluidState.isIn(FluidTags.WATER)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
PositionType.LAVAFLOOR -> {
|
||||
if (!state.fluidState.isIn(FluidTags.LAVA)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
val World.itemRegistry: Registry<Item>
|
||||
get() = registryManager.get(RegistryKeys.ITEM)
|
||||
val World.biomeRegistry: Registry<Biome>
|
||||
|
||||
+9
-7
@@ -5,30 +5,32 @@
|
||||
"identifier": "cobblemon:ancientoriginball/ballsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparkle"
|
||||
"texture": "textures/particles/balls/originball/originballsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_steady": {
|
||||
"spawn_rate": 16,
|
||||
"max_particles": 16
|
||||
"spawn_rate": 22,
|
||||
"max_particles": 24
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 0.5
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"offset": [0, 1.5, 0],
|
||||
"offset": [0, 2, 0],
|
||||
"radius": "math.random(0.5,1.5)*1.5",
|
||||
"surface_only": true,
|
||||
"direction": [0, 1, 0]
|
||||
"direction": ["math.random(-9,9)", "math.random(4,7)", "math.random(-9,9)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0.75,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, 2, 0]
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.2, 0.2],
|
||||
"size": [0.175, 0.175],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 36,
|
||||
|
||||
+11
-6
@@ -5,25 +5,30 @@
|
||||
"identifier": "cobblemon:ancientoriginball/battle/ballsendsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsendsparkle"
|
||||
"texture": "textures/particles/balls/originball/originballsendsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 8
|
||||
"minecraft:emitter_initialization": {
|
||||
"per_update_expression": "variable.radius = 0.6;"
|
||||
},
|
||||
"minecraft:emitter_rate_steady": {
|
||||
"spawn_rate": 100,
|
||||
"max_particles": 16
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.05,4)*4+0.5", "math.random(-10,10)"]
|
||||
"radius": "variable.radius*math.cos(variable.emitter_age*2080)",
|
||||
"direction": ["math.random(-5,5)*1.75", "math.random(-0.05,6)*3+0.5", "math.random(-5,5)*1.75"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*3",
|
||||
"minecraft:particle_initial_speed": "math.random(3,7)*4",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, -5, 0],
|
||||
"linear_acceleration": [0, "-math.random(5,8)", 0],
|
||||
"linear_drag_coefficient": 4
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
|
||||
+29
-15
@@ -5,38 +5,52 @@
|
||||
"identifier": "cobblemon:ancientoriginball/battle/ballsparks",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparks"
|
||||
"texture": "textures/particles/balls/originball/originballsparks"
|
||||
}
|
||||
},
|
||||
"curves": {
|
||||
"variable.sizefunny": {
|
||||
"type": "linear",
|
||||
"input": "v.particle_age",
|
||||
"horizontal_range": "v.particle_lifetime",
|
||||
"nodes": [1, 1, 1, 0.98, 0.93, 0.83, 0.58, -0.01, 0, 0]
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 10
|
||||
"num_particles": 20
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
"active_time": 0.5
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.1,4)*3+0.5", "math.random(-10,10)"]
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.1,4)*3+0.25", "math.random(-10,10)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*3.5",
|
||||
"minecraft:particle_initial_speed": "math.random(3.1,4.8)*3.5",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_drag_coefficient": 4.5
|
||||
"linear_acceleration": ["math.random(-3.5,3.5)*10", "math.random(-2.5,2.5)*10", "math.random(-3.5,3.5)*10"],
|
||||
"linear_drag_coefficient": 3.5
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.15, 0.15],
|
||||
"size": ["(0.225-(variable.particle_random_3*0.1))*v.sizefunny", "(0.225-(variable.particle_random_3*0.1))*v.sizefunny"],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 80,
|
||||
"texture_height": 8,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [8, 8],
|
||||
"step_UV": [8, 0],
|
||||
"frames_per_second": 18,
|
||||
"max_frame": 10
|
||||
"texture_width": 90,
|
||||
"texture_height": 9,
|
||||
"uv": ["math.floor(v.particle_random_3*10)*9", 0],
|
||||
"uv_size": [9, 9]
|
||||
}
|
||||
},
|
||||
"minecraft:particle_appearance_tinting": {
|
||||
"color": {
|
||||
"interpolant": "v.particle_age / v.particle_lifetime",
|
||||
"gradient": {
|
||||
"0.14": "#ffffffff",
|
||||
"0.43": "#FFFF0000",
|
||||
"0.71": "#FF7B0000"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -5,7 +5,7 @@
|
||||
"identifier": "cobblemon:ancientoriginball/battle/sendflash",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/battle/sendflash"
|
||||
"texture": "textures/particles/balls/originball/battle/originsendflash"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
@@ -27,14 +27,14 @@
|
||||
"size": [2.25, 2.25],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 1024,
|
||||
"texture_width": 1088,
|
||||
"texture_height": 64,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [64, 64],
|
||||
"step_UV": [64, 0],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 16
|
||||
"max_frame": 17
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -5,12 +5,12 @@
|
||||
"identifier": "cobblemon:ancientoriginball/casual/ballsendsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsendsparkle"
|
||||
"texture": "textures/particles/balls/originball/originballsendsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 4
|
||||
"num_particles": 6
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
@@ -21,7 +21,7 @@
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,6)*2.5",
|
||||
"minecraft:particle_initial_speed": "math.random(3,6)*3",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, -6, 0],
|
||||
"linear_drag_coefficient": 4
|
||||
|
||||
+28
-14
@@ -5,38 +5,52 @@
|
||||
"identifier": "cobblemon:ancientoriginball/casual/ballsparks",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparks"
|
||||
"texture": "textures/particles/balls/originball/originballsparks"
|
||||
}
|
||||
},
|
||||
"curves": {
|
||||
"variable.sizefunny": {
|
||||
"type": "linear",
|
||||
"input": "v.particle_age",
|
||||
"horizontal_range": "v.particle_lifetime",
|
||||
"nodes": [1, 1, 1, 0.98, 0.93, 0.83, 0.58, -0.01, 0, 0, 0]
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 5
|
||||
"num_particles": 10
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
"active_time": 0.5
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.1,4)*3+0.5", "math.random(-10,10)"]
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.1,4)*3+0.25", "math.random(-10,10)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*2.1",
|
||||
"minecraft:particle_initial_speed": "math.random(3.1,4.8)*2.5",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": ["math.random(-3.5,3.5)*10", "math.random(-2.5,2.5)*10", "math.random(-3.5,3.5)*10"],
|
||||
"linear_drag_coefficient": 3.5
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.1, 0.1],
|
||||
"size": ["(0.225-(variable.particle_random_3*0.1))*v.sizefunny", "(0.225-(variable.particle_random_3*0.1))*v.sizefunny"],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 80,
|
||||
"texture_height": 8,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [8, 8],
|
||||
"step_UV": [8, 0],
|
||||
"frames_per_second": 18,
|
||||
"max_frame": 10
|
||||
"texture_width": 90,
|
||||
"texture_height": 9,
|
||||
"uv": ["math.floor(v.particle_random_3*10)*9", 0],
|
||||
"uv_size": [9, 9]
|
||||
}
|
||||
},
|
||||
"minecraft:particle_appearance_tinting": {
|
||||
"color": {
|
||||
"interpolant": "v.particle_age / v.particle_lifetime",
|
||||
"gradient": {
|
||||
"0.14": "#ffffffff",
|
||||
"0.33": "#FFFF0000",
|
||||
"0.61": "#FF7B0000"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -5,7 +5,7 @@
|
||||
"identifier": "cobblemon:ancientoriginball/casual/sendflash",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/casual/sendcasual"
|
||||
"texture": "textures/particles/balls/originball/casual/originsendcasual"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
@@ -27,14 +27,14 @@
|
||||
"size": [1.25, 1.25],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 384,
|
||||
"texture_width": 416,
|
||||
"texture_height": 32,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [32, 32],
|
||||
"step_UV": [32, 0],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 12
|
||||
"max_frame": 13
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-8
@@ -5,30 +5,32 @@
|
||||
"identifier": "cobblemon:beastball/ballsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparkle"
|
||||
"texture": "textures/particles/balls/beastball/beastballsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_steady": {
|
||||
"spawn_rate": 16,
|
||||
"max_particles": 16
|
||||
"spawn_rate": 24,
|
||||
"max_particles": 18
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 0.5
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"offset": [0, 1.5, 0],
|
||||
"radius": "math.random(0.5,1.5)*1.5",
|
||||
"offset": [0, 1.75, 0],
|
||||
"radius": 1.25,
|
||||
"surface_only": true,
|
||||
"direction": [0, 1, 0]
|
||||
"direction": ["math.random(-9,9)", "math.random(4,7)", "math.random(-9,9)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0.75,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, 2, 0]
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.2, 0.2],
|
||||
"size": [0.15, 0.15],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 36,
|
||||
|
||||
+6
-6
@@ -5,12 +5,12 @@
|
||||
"identifier": "cobblemon:beastball/battle/ballsendsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsendsparkle"
|
||||
"texture": "textures/particles/balls/beastball/beastballsendsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 8
|
||||
"num_particles": 14
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
@@ -21,13 +21,13 @@
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*3",
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*4.5",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, -5, 0],
|
||||
"linear_drag_coefficient": 4
|
||||
"linear_acceleration": [0, -6, 0],
|
||||
"linear_drag_coefficient": 5
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.15, 0.15],
|
||||
"size": [0.125, 0.125],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 99,
|
||||
|
||||
+10
-6
@@ -5,28 +5,32 @@
|
||||
"identifier": "cobblemon:beastball/battle/ballsparks",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparks"
|
||||
"texture": "textures/particles/balls/beastball/beastballsparks"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 10
|
||||
"num_particles": 20
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.1,4)*3+0.5", "math.random(-10,10)"]
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.5,5)*5+0.5", "math.random(-10,10)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*3.5",
|
||||
"minecraft:particle_initial_spin": {
|
||||
"rotation": "math.random_integer(0,3)*90"
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(3,6)*3",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_drag_coefficient": 4.5
|
||||
"linear_acceleration": [0, -20, 0],
|
||||
"linear_drag_coefficient": 2
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.15, 0.15],
|
||||
"size": ["0.075+0.075*v.particle_random_2", "0.075+0.075*v.particle_random_2"],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 80,
|
||||
|
||||
+3
-3
@@ -5,7 +5,7 @@
|
||||
"identifier": "cobblemon:beastball/battle/sendflash",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/battle/sendflash"
|
||||
"texture": "textures/particles/balls/beastball/battle/beastsendflash"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
@@ -27,14 +27,14 @@
|
||||
"size": [2.25, 2.25],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 1024,
|
||||
"texture_width": 1088,
|
||||
"texture_height": 64,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [64, 64],
|
||||
"step_UV": [64, 0],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 16
|
||||
"max_frame": 17
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -5,12 +5,12 @@
|
||||
"identifier": "cobblemon:beastball/casual/ballsendsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsendsparkle"
|
||||
"texture": "textures/particles/balls/beastball/beastballsendsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 4
|
||||
"num_particles": 6
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
@@ -21,7 +21,7 @@
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,6)*2.5",
|
||||
"minecraft:particle_initial_speed": "math.random(3,6)*3",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, -6, 0],
|
||||
"linear_drag_coefficient": 4
|
||||
|
||||
+10
-6
@@ -5,28 +5,32 @@
|
||||
"identifier": "cobblemon:beastball/casual/ballsparks",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparks"
|
||||
"texture": "textures/particles/balls/beastball/beastballsparks"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 5
|
||||
"num_particles": 12
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.1,4)*3+0.5", "math.random(-10,10)"]
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.5,5)*5+0.5", "math.random(-10,10)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*2.1",
|
||||
"minecraft:particle_initial_spin": {
|
||||
"rotation": "math.random_integer(0,3)*90"
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(3,7)*2",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_drag_coefficient": 3.5
|
||||
"linear_acceleration": [0, -15, 0],
|
||||
"linear_drag_coefficient": 2
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.1, 0.1],
|
||||
"size": ["0.05+0.075*v.particle_random_2", "0.05+0.075*v.particle_random_2"],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 80,
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
"identifier": "cobblemon:beastball/casual/sendflash",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/casual/sendcasual"
|
||||
"texture": "textures/particles/balls/beastball/casual/beastsendcasual"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
|
||||
+19
-8
@@ -5,30 +5,32 @@
|
||||
"identifier": "cobblemon:cherishball/ballsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparkle"
|
||||
"texture": "textures/particles/balls/cherishball/cherishballsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_steady": {
|
||||
"spawn_rate": 16,
|
||||
"max_particles": 16
|
||||
"spawn_rate": 24,
|
||||
"max_particles": 18
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 0.5
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"offset": [0, 1.5, 0],
|
||||
"radius": "math.random(0.5,1.5)*1.5",
|
||||
"offset": [0, 1.75, 0],
|
||||
"radius": 1.25,
|
||||
"surface_only": true,
|
||||
"direction": [0, 1, 0]
|
||||
"direction": ["math.random(-9,9)", "math.random(4,7)", "math.random(-9,9)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0.75,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, 2, 0]
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.2, 0.2],
|
||||
"size": [0.15, 0.15],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 36,
|
||||
@@ -41,6 +43,15 @@
|
||||
"max_frame": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"minecraft:particle_appearance_tinting": {
|
||||
"color": {
|
||||
"interpolant": "v.particle_age / v.particle_lifetime",
|
||||
"gradient": {
|
||||
"0.0": "#FFFFFFFF",
|
||||
"0.19": "#FFFF8845"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+17
-6
@@ -5,12 +5,12 @@
|
||||
"identifier": "cobblemon:cherishball/battle/ballsendsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsendsparkle"
|
||||
"texture": "textures/particles/balls/cherishball/cherishballsendsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 8
|
||||
"num_particles": 14
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
@@ -21,13 +21,13 @@
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*3",
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*4.5",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, -5, 0],
|
||||
"linear_drag_coefficient": 4
|
||||
"linear_acceleration": [0, -6, 0],
|
||||
"linear_drag_coefficient": 5
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.15, 0.15],
|
||||
"size": [0.125, 0.125],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 99,
|
||||
@@ -40,6 +40,17 @@
|
||||
"max_frame": 11
|
||||
}
|
||||
}
|
||||
},
|
||||
"minecraft:particle_appearance_tinting": {
|
||||
"color": {
|
||||
"interpolant": "v.particle_age / v.particle_lifetime",
|
||||
"gradient": {
|
||||
"0.0": "#FF8DFFC6",
|
||||
"0.2": "#ffffffff",
|
||||
"0.35": "#ffffffff",
|
||||
"0.53": "#FFFF8845"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-4
@@ -5,12 +5,12 @@
|
||||
"identifier": "cobblemon:cherishball/battle/ballsparks",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparks"
|
||||
"texture": "textures/particles/balls/cherishball/cherishballsparks"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 10
|
||||
"num_particles": 8
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
@@ -21,9 +21,9 @@
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*3.5",
|
||||
"minecraft:particle_initial_speed": "math.random(3,6)*3.75",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_drag_coefficient": 4.5
|
||||
"linear_drag_coefficient": 5
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.15, 0.15],
|
||||
@@ -39,6 +39,17 @@
|
||||
"max_frame": 10
|
||||
}
|
||||
}
|
||||
},
|
||||
"minecraft:particle_appearance_tinting": {
|
||||
"color": {
|
||||
"interpolant": "v.particle_age / v.particle_lifetime",
|
||||
"gradient": {
|
||||
"0.0": "#FF8DFFC6",
|
||||
"0.2": "#ffffffff",
|
||||
"0.35": "#ffffffff",
|
||||
"0.53": "#FFFF8845"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-3
@@ -5,7 +5,7 @@
|
||||
"identifier": "cobblemon:cherishball/battle/sendflash",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/battle/sendflash"
|
||||
"texture": "textures/particles/balls/cherishball/battle/cherishsendflash"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
@@ -27,14 +27,25 @@
|
||||
"size": [2.25, 2.25],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 1024,
|
||||
"texture_width": 1088,
|
||||
"texture_height": 64,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [64, 64],
|
||||
"step_UV": [64, 0],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 16
|
||||
"max_frame": 17
|
||||
}
|
||||
}
|
||||
},
|
||||
"minecraft:particle_appearance_tinting": {
|
||||
"color": {
|
||||
"interpolant": "v.particle_age / v.particle_lifetime",
|
||||
"gradient": {
|
||||
"0.0": "#FF8DFFC6",
|
||||
"0.2": "#ffffffff",
|
||||
"0.35": "#ffffffff",
|
||||
"0.53": "#FFFF8845"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-3
@@ -5,12 +5,12 @@
|
||||
"identifier": "cobblemon:cherishball/casual/ballsendsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsendsparkle"
|
||||
"texture": "textures/particles/balls/cherishball/cherishballsendsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 4
|
||||
"num_particles": 6
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
@@ -21,7 +21,7 @@
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,6)*2.5",
|
||||
"minecraft:particle_initial_speed": "math.random(3,6)*3",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, -6, 0],
|
||||
"linear_drag_coefficient": 4
|
||||
@@ -40,6 +40,17 @@
|
||||
"max_frame": 11
|
||||
}
|
||||
}
|
||||
},
|
||||
"minecraft:particle_appearance_tinting": {
|
||||
"color": {
|
||||
"interpolant": "v.particle_age / v.particle_lifetime",
|
||||
"gradient": {
|
||||
"0.0": "#FF8DFFC6",
|
||||
"0.2": "#ffffffff",
|
||||
"0.35": "#ffffffff",
|
||||
"0.53": "#FFFF8845"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-3
@@ -5,7 +5,7 @@
|
||||
"identifier": "cobblemon:cherishball/casual/ballsparks",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparks"
|
||||
"texture": "textures/particles/balls/cherishball/cherishballsparks"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
@@ -21,9 +21,9 @@
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*2.1",
|
||||
"minecraft:particle_initial_speed": "math.random(3,7)*2",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_drag_coefficient": 3.5
|
||||
"linear_drag_coefficient": 3
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.1, 0.1],
|
||||
@@ -39,6 +39,17 @@
|
||||
"max_frame": 10
|
||||
}
|
||||
}
|
||||
},
|
||||
"minecraft:particle_appearance_tinting": {
|
||||
"color": {
|
||||
"interpolant": "v.particle_age / v.particle_lifetime",
|
||||
"gradient": {
|
||||
"0.0": "#FF8DFFC6",
|
||||
"0.2": "#ffffffff",
|
||||
"0.35": "#ffffffff",
|
||||
"0.53": "#FFFF8845"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-3
@@ -5,7 +5,7 @@
|
||||
"identifier": "cobblemon:cherishball/casual/sendflash",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/casual/sendcasual"
|
||||
"texture": "textures/particles/balls/cherishball/casual/cherishsendcasual"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
@@ -27,14 +27,25 @@
|
||||
"size": [1.25, 1.25],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 384,
|
||||
"texture_width": 416,
|
||||
"texture_height": 32,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [32, 32],
|
||||
"step_UV": [32, 0],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 12
|
||||
"max_frame": 13
|
||||
}
|
||||
}
|
||||
},
|
||||
"minecraft:particle_appearance_tinting": {
|
||||
"color": {
|
||||
"interpolant": "v.particle_age / v.particle_lifetime",
|
||||
"gradient": {
|
||||
"0.0": "#FF8DFFC6",
|
||||
"0.2": "#ffffffff",
|
||||
"0.35": "#ffffffff",
|
||||
"0.53": "#FFFF8845"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -5,22 +5,22 @@
|
||||
"identifier": "cobblemon:dreamball/ballsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparkle"
|
||||
"texture": "textures/particles/balls/dreamball/dreamballsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_steady": {
|
||||
"spawn_rate": 16,
|
||||
"max_particles": 16
|
||||
"spawn_rate": 20,
|
||||
"max_particles": 14
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 0.5
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"offset": [0, 1.5, 0],
|
||||
"radius": "math.random(0.5,1.5)*1.5",
|
||||
"offset": [0, 1.25, 0],
|
||||
"radius": "1.25",
|
||||
"surface_only": true,
|
||||
"direction": [0, 1, 0]
|
||||
"direction": "outwards"
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
|
||||
+6
-6
@@ -5,12 +5,12 @@
|
||||
"identifier": "cobblemon:dreamball/battle/ballsendsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsendsparkle"
|
||||
"texture": "textures/particles/balls/dreamball/dreamballsendsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 8
|
||||
"num_particles": 14
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
@@ -21,13 +21,13 @@
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*3",
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*4.5",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, -5, 0],
|
||||
"linear_drag_coefficient": 4
|
||||
"linear_acceleration": [0, -6, 0],
|
||||
"linear_drag_coefficient": 5
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.15, 0.15],
|
||||
"size": [0.125, 0.125],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 99,
|
||||
|
||||
+4
-4
@@ -5,12 +5,12 @@
|
||||
"identifier": "cobblemon:dreamball/battle/ballsparks",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparks"
|
||||
"texture": "textures/particles/balls/dreamball/dreamballsparks"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 10
|
||||
"num_particles": 8
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
@@ -21,9 +21,9 @@
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*3.5",
|
||||
"minecraft:particle_initial_speed": "math.random(3,6)*3.75",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_drag_coefficient": 4.5
|
||||
"linear_drag_coefficient": 5
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.15, 0.15],
|
||||
|
||||
+3
-3
@@ -5,7 +5,7 @@
|
||||
"identifier": "cobblemon:dreamball/battle/sendflash",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/battle/sendflash"
|
||||
"texture": "textures/particles/balls/dreamball/battle/dreamsendflash"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
@@ -27,14 +27,14 @@
|
||||
"size": [2.25, 2.25],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 1024,
|
||||
"texture_width": 1088,
|
||||
"texture_height": 64,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [64, 64],
|
||||
"step_UV": [64, 0],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 16
|
||||
"max_frame": 17
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -5,12 +5,12 @@
|
||||
"identifier": "cobblemon:dreamball/casual/ballsendsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsendsparkle"
|
||||
"texture": "textures/particles/balls/dreamball/dreamballsendsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 4
|
||||
"num_particles": 6
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
@@ -21,7 +21,7 @@
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,6)*2.5",
|
||||
"minecraft:particle_initial_speed": "math.random(3,6)*3",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, -6, 0],
|
||||
"linear_drag_coefficient": 4
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user