Compare commits
106
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aeedec0b6d | ||
|
|
a37fdf709a | ||
|
|
5023f28d04 | ||
|
|
67de28386a | ||
|
|
cd37d3538e | ||
|
|
3d03ee5eb3 | ||
|
|
0b685ed453 | ||
|
|
115e990df6 | ||
|
|
2ee38f0a29 | ||
|
|
756ef48ba2 | ||
|
|
2c4df6622a | ||
|
|
425c41bc4b | ||
|
|
9f7a99b583 | ||
|
|
f1213abdf4 | ||
|
|
9b1d847f59 | ||
|
|
bf900a0167 | ||
|
|
d60d828e93 | ||
|
|
703282eca1 | ||
|
|
5d7e6f6487 | ||
|
|
4e3e6405d0 | ||
|
|
1e161a52ee | ||
|
|
65b2204783 | ||
|
|
76d9137ae4 | ||
|
|
9f6c44fd75 | ||
|
|
6c086f5555 | ||
|
|
a9115bfb15 | ||
|
|
f2c5113f0b | ||
|
|
e29a2402e9 | ||
|
|
aa4857abbb | ||
|
|
d29653233d | ||
|
|
1b51a128d7 | ||
|
|
245011cf5e | ||
|
|
100bf7fee4 | ||
|
|
be043a0ea1 | ||
|
|
a902f4a8a3 | ||
|
|
442f54839f | ||
|
|
20a97984a2 | ||
|
|
d1517548bd | ||
|
|
3e1f9dc9b0 | ||
|
|
fd19e65f79 | ||
|
|
6b10d81bc8 | ||
|
|
f3b9c03fc2 | ||
|
|
92653c1307 | ||
|
|
c372114da5 | ||
|
|
2b95138c46 | ||
|
|
864e6be461 | ||
|
|
c02fa1f85e | ||
|
|
503b1069fd | ||
|
|
f1d593d53c | ||
|
|
55dd486044 | ||
|
|
3263837137 | ||
|
|
a471fcd948 | ||
|
|
a14bfd55d1 | ||
|
|
725e819e89 | ||
|
|
b52b843206 | ||
|
|
74c65e22cb | ||
|
|
c348520a9b | ||
|
|
78dd5f334a | ||
|
|
67318c9307 | ||
|
|
31c48407df | ||
|
|
43da7ecece | ||
|
|
0957de86c7 | ||
|
|
daae444fa9 | ||
|
|
79423ef5ee | ||
|
|
6255f7dc31 | ||
|
|
ff10306372 | ||
|
|
aaf7daa45b | ||
|
|
ae550f78c4 | ||
|
|
66e4194a3e | ||
|
|
12e6b76504 | ||
|
|
93861af71f | ||
|
|
0c80748012 | ||
|
|
fcf832c22c | ||
|
|
a065aff744 | ||
|
|
d77f424a83 | ||
|
|
d5d2a2cec3 | ||
|
|
036e150191 | ||
|
|
0bf1d84675 | ||
|
|
b1b8e658b2 | ||
|
|
f984b21929 | ||
|
|
0a5193b209 | ||
|
|
43f1f1c30d | ||
|
|
c16597ae41 | ||
|
|
f76e7582d2 | ||
|
|
40761d87db | ||
|
|
89a9ad0bfb | ||
|
|
20291c54a5 | ||
|
|
d6fdfe6ebc | ||
|
|
9f63b62651 | ||
|
|
392632b7d4 | ||
|
|
0d377dcbe0 | ||
|
|
88c31bcb7b | ||
|
|
8efea17ae6 | ||
|
|
cdbf569bbc | ||
|
|
0415cf8a69 | ||
|
|
79af092888 | ||
|
|
812d42a42f | ||
|
|
3f114706fa | ||
|
|
9514a1d470 | ||
|
|
f99168f1c3 | ||
|
|
adce1d8838 | ||
|
|
e95c82b5af | ||
|
|
dd273ffef2 | ||
|
|
82548b5383 | ||
|
|
ad73202e17 | ||
|
|
2965a04742 |
No files matched your search
+7
-2
@@ -154,9 +154,14 @@
|
||||
- Poké Ball recipes now use tags for their center ingredient, rather than specificied Copper Ingot, Iron Ingot, Gold Ingot, and Diamond, allowing for further datapack customisation.
|
||||
- Starter Toast now closes once corresponding button is pressed once.
|
||||
- Moved some items in the vanilla Food & Drinks category.
|
||||
- Stacked Cobblemon Potion Bases can now be quick moved into Brewing Stands.
|
||||
- Changed Healer recipe to swap the Max Revive for a Revive.
|
||||
- Upped the rate that Gastly drop Ghast Tears from 2.5% to 5%.
|
||||
- Pokémon with a low Blaze Powder drop chance now drop it more frequently in the Nether.
|
||||
- Reorganised a few advancements.
|
||||
|
||||
### Fixes
|
||||
- Resized Snorlax
|
||||
- Resized Snorlax.
|
||||
- Re-added the recipe for the Iron Vitamin.
|
||||
- Cleaned up empty evolutions declaration in species files (no, I'm not listing all 169 by name).
|
||||
- Fixed Exeggcute not being able to evolve.
|
||||
@@ -188,13 +193,13 @@
|
||||
- Made PokemonProperties.parse more interoperable with Java.
|
||||
- Added the ``HeldItemEvent``, this comes with 2 implementation ``HeldItemEvent.Pre`` and ``HeldItemEvent.Post``.
|
||||
- API to support dynamic lighting in any mod that implements this feature has been added to all Species & Forms, see LightingData class for details.
|
||||
- Added a Mixin for the BrewingStandScreenHandler to fix the incorrect handling of quickMove in Fabric.
|
||||
- Corrections to the ability implementation have been made that make ``Ability.forced`` function as intended and never reroll an ability for a Pokémon, please check your implementations to ensure the corrected behavior is intended for your use case.
|
||||
- ``Pokemon.ability`` no longer has a public setter, please migrate to using ``Pokemon#updateAbility``, this handles the ability coordinate storage for you when necessary.
|
||||
- ``Ability.forced``, ``Ability.index`` and ``Ability.priority`` have all had their setters internalized, there is no longer any need to manually adjust these migrate to the method mentioned above to handle that process for you.
|
||||
- ``AbilityChanger`` has been added to API alongside some implementations, this is subject to change as the ability capsule and patch currently only expect the traditional behaviour in the Pokémon games of 1 to 2 regular abilities and 1 hidden.
|
||||
- ``Pokemon#rollAbility`` has been added, this rerolls a legal ability for the Pokémon.
|
||||
- `docs/cobblemon-tags` tags and spawn-presets can now be auto-generated from the current tags in the cobblemon mod with the `generateSpawnPresetList.py` and `generateTagList.py` scripts.
|
||||
- `public_spawns_to_json.py` script has been added to give the powerful spawn.json generator a simplistic UI.
|
||||
|
||||
### Datapack & Resourcepack Creators
|
||||
- The maximum amount of fossils that can fit in the Fossil Analyzer can be adjusted in the config.
|
||||
|
||||
@@ -67,24 +67,13 @@ import com.cobblemon.mod.common.api.storage.player.factory.JsonPlayerDataStoreFa
|
||||
import com.cobblemon.mod.common.api.storage.player.factory.MongoPlayerDataStoreFactory
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonEntityTypeTags
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.battles.BagItems
|
||||
import com.cobblemon.mod.common.battles.BattleFormat
|
||||
import com.cobblemon.mod.common.battles.BattleRegistry
|
||||
import com.cobblemon.mod.common.battles.BattleSide
|
||||
import com.cobblemon.mod.common.battles.ShowdownThread
|
||||
import com.cobblemon.mod.common.battles.*
|
||||
import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.command.argument.DialogueArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.MoveArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PartySlotArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PokemonArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PokemonPropertiesArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PokemonStoreArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.SpawnBucketArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.*
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import com.cobblemon.mod.common.config.LastChangedVersion
|
||||
import com.cobblemon.mod.common.config.constraint.IntConstraint
|
||||
import com.cobblemon.mod.common.config.starter.StarterConfig
|
||||
import com.cobblemon.mod.common.data.CobblemonDataProvider
|
||||
import com.cobblemon.mod.common.events.AdvancementHandler
|
||||
import com.cobblemon.mod.common.events.ServerTickHandler
|
||||
@@ -105,13 +94,7 @@ 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
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.ifDedicatedServer
|
||||
import com.cobblemon.mod.common.util.isLaterVersion
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import com.cobblemon.mod.common.util.removeAmountIf
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.world.feature.CobblemonPlacedFeatures
|
||||
import com.cobblemon.mod.common.world.feature.ore.CobblemonOrePlacedFeatures
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
@@ -132,13 +115,16 @@ import org.apache.logging.log4j.Logger
|
||||
import java.io.File
|
||||
import java.io.FileReader
|
||||
import java.io.FileWriter
|
||||
import java.io.PrintWriter
|
||||
import java.util.*
|
||||
import kotlin.collections.filterIsInstance
|
||||
import kotlin.collections.forEach
|
||||
import kotlin.collections.listOf
|
||||
import kotlin.collections.set
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.properties.Delegates
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import kotlin.reflect.jvm.javaField
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
object Cobblemon {
|
||||
const val MODID = "cobblemon"
|
||||
@@ -166,7 +152,6 @@ object Cobblemon {
|
||||
var storage = PokemonStoreManager()
|
||||
var molangData = NbtMoLangDataStoreFactory
|
||||
lateinit var playerData: PlayerDataStoreManager
|
||||
lateinit var starterConfig: StarterConfig
|
||||
val dataProvider: DataProvider = CobblemonDataProvider
|
||||
var permissionValidator: PermissionValidator by Delegates.observable(LaxPermissionValidator().also { it.initialize() }) { _, _, newValue -> newValue.initialize() }
|
||||
var statProvider: StatProvider = CobblemonStatProvider
|
||||
@@ -477,27 +462,6 @@ object Cobblemon {
|
||||
this.saveConfig()
|
||||
|
||||
bestSpawner.loadConfig()
|
||||
PokemonSpecies.observable.subscribe { starterConfig = this.loadStarterConfig() }
|
||||
}
|
||||
|
||||
fun loadStarterConfig(): StarterConfig {
|
||||
if (config.exportStarterConfig) {
|
||||
val file = File("config/cobblemon/starters.json")
|
||||
file.parentFile.mkdirs()
|
||||
if (!file.exists()) {
|
||||
val config = StarterConfig()
|
||||
val pw = PrintWriter(file)
|
||||
StarterConfig.GSON.toJson(config, pw)
|
||||
pw.close()
|
||||
return config
|
||||
}
|
||||
val reader = FileReader(file)
|
||||
val config = StarterConfig.GSON.fromJson(reader, StarterConfig::class.java)
|
||||
reader.close()
|
||||
return config
|
||||
} else {
|
||||
return StarterConfig()
|
||||
}
|
||||
}
|
||||
|
||||
fun saveConfig() {
|
||||
|
||||
@@ -160,7 +160,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
@JvmField
|
||||
val BIG_ROOT = this.create("big_root", BigRootBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DARK_GREEN).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.BIG_ROOT_SOUNDS)))
|
||||
@JvmField
|
||||
val REVIVAL_HERB = this.create("revival_herb", RevivalHerbBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).mapColor(MapColor.DARK_GREEN).burnable().noCollision().breakInstantly().sounds(BlockSoundGroup.CROP)))
|
||||
val REVIVAL_HERB = this.create("revival_herb", RevivalHerbBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).mapColor(MapColor.DARK_GREEN).burnable().noCollision().breakInstantly().sounds(CobblemonSounds.REVIVAL_HERB_SOUNDS)))
|
||||
|
||||
@JvmField
|
||||
val TUMBLESTONE_CLUSTER = tumblestoneBlock("tumblestone_cluster", GrowableStoneBlock.STAGE_3, 7, 3, null)
|
||||
@@ -428,7 +428,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, RegistryKey<Registry<
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val VIVICHOKE_SEEDS = this.create("vivichoke_seeds", VivichokeBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DARK_GREEN).noCollision().ticksRandomly().breakInstantly().sounds(BlockSoundGroup.CROP)))
|
||||
val VIVICHOKE_SEEDS = this.create("vivichoke_seeds", VivichokeBlock(AbstractBlock.Settings.create().pistonBehavior(PistonBehavior.DESTROY).burnable().mapColor(MapColor.DARK_GREEN).noCollision().ticksRandomly().breakInstantly().sounds(CobblemonSounds.VIVICHOKE_SOUNDS)))
|
||||
@JvmField
|
||||
val PEP_UP_FLOWER = this.create("pep_up_flower", FlowerBlock(StatusEffects.LEVITATION, 10, AbstractBlock.Settings.create().mapColor(MapColor.DARK_GREEN).noCollision().breakInstantly().sounds(BlockSoundGroup.GRASS).offset(AbstractBlock.OffsetType.XZ).pistonBehavior(PistonBehavior.DESTROY)))
|
||||
@JvmField
|
||||
|
||||
@@ -99,27 +99,27 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
|
||||
val MULCH_REMOVE = this.create("mulch.remove")
|
||||
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_ACTIVATE = this.create("fossilmachine.activate")
|
||||
val FOSSIL_MACHINE_ACTIVATE = this.create("fossil_machine.activate")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_ACTIVE_LOOP = this.create("fossilmachine.active_loop")
|
||||
val FOSSIL_MACHINE_ACTIVE_LOOP = this.create("fossil_machine.active_loop")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_ASSEMBLE = this.create("fossilmachine.assemble")
|
||||
val FOSSIL_MACHINE_ASSEMBLE = this.create("fossil_machine.assemble")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_DNA_FULL = this.create("fossilmachine.dna_full")
|
||||
val FOSSIL_MACHINE_DNA_FULL = this.create("fossil_machine.dna_full")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_FINISHED = this.create("fossilmachine.finished")
|
||||
val FOSSIL_MACHINE_FINISHED = this.create("fossil_machine.finished")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_INSERT_DNA = this.create("fossilmachine.insert_dna")
|
||||
val FOSSIL_MACHINE_INSERT_DNA = this.create("fossil_machine.insert_dna")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_INSERT_DNA_SMALL = this.create("fossilmachine.insert_dna_small")
|
||||
val FOSSIL_MACHINE_INSERT_DNA_SMALL = this.create("fossil_machine.insert_dna_small")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_INSERT_FOSSIL = this.create("fossilmachine.insert_fossil")
|
||||
val FOSSIL_MACHINE_INSERT_FOSSIL = this.create("fossil_machine.insert_fossil")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_RETRIEVE_FOSSIL = this.create("fossilmachine.retrieve_fossil")
|
||||
val FOSSIL_MACHINE_RETRIEVE_FOSSIL = this.create("fossil_machine.retrieve_fossil")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_RETRIEVE_POKEMON = this.create("fossilmachine.retrieve_pokemon")
|
||||
val FOSSIL_MACHINE_RETRIEVE_POKEMON = this.create("fossil_machine.retrieve_pokemon")
|
||||
@JvmField
|
||||
val FOSSIL_MACHINE_UNPROTECTED = this.create("fossilmachine.unprotected")
|
||||
val FOSSIL_MACHINE_UNPROTECTED = this.create("fossil_machine.unprotected")
|
||||
|
||||
@JvmField
|
||||
val COIN_POUCH_BREAK = this.create("coin_pouch.break")
|
||||
@@ -155,11 +155,21 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
|
||||
@JvmField
|
||||
val ENERGY_ROOT_PLACE = this.create("energy_root.place")
|
||||
|
||||
@JvmField
|
||||
val VIVICHOKE_BREAK = this.create("vivichoke.break")
|
||||
@JvmField
|
||||
val VIVICHOKE_PLACE = this.create("vivichoke.place")
|
||||
|
||||
@JvmField
|
||||
val MINT_BREAK = this.create("mint.break")
|
||||
@JvmField
|
||||
val MINT_PLACE = this.create("mint.place")
|
||||
|
||||
@JvmField
|
||||
val REVIVAL_HERB_BREAK = this.create("revival_herb.break")
|
||||
@JvmField
|
||||
val REVIVAL_HERB_PLACE = this.create("revival_herb.place")
|
||||
|
||||
@JvmField
|
||||
val MEDICINAL_LEEK_BREAK = this.create("medicinal_leek.break")
|
||||
@JvmField
|
||||
@@ -277,6 +287,15 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
|
||||
SoundEvents.BLOCK_GRASS_FALL
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val VIVICHOKE_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
VIVICHOKE_BREAK,
|
||||
SoundEvents.BLOCK_GRASS_STEP,
|
||||
VIVICHOKE_PLACE,
|
||||
SoundEvents.BLOCK_GRASS_HIT,
|
||||
SoundEvents.BLOCK_GRASS_FALL
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val MINT_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
MINT_BREAK,
|
||||
@@ -286,6 +305,15 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
|
||||
SoundEvents.BLOCK_GRASS_FALL
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val REVIVAL_HERB_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
REVIVAL_HERB_BREAK,
|
||||
SoundEvents.BLOCK_GRASS_STEP,
|
||||
REVIVAL_HERB_PLACE,
|
||||
SoundEvents.BLOCK_GRASS_HIT,
|
||||
SoundEvents.BLOCK_GRASS_FALL
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val GILDED_CHEST_SOUNDS = BlockSoundGroup(1f, 1f,
|
||||
GILDED_CHEST_BREAK,
|
||||
|
||||
@@ -35,8 +35,8 @@ abstract class MultiblockBlock(properties: Settings) : BlockWithEntity(propertie
|
||||
itemStack: ItemStack?
|
||||
) {
|
||||
if (world is ServerWorld) {
|
||||
val multiblockEntity = world.getBlockEntity(pos) as MultiblockEntity
|
||||
multiblockEntity.multiblockBuilder?.validate(world)
|
||||
val multiblockEntity = world.getBlockEntity(pos) as? MultiblockEntity
|
||||
multiblockEntity?.multiblockBuilder?.validate(world)
|
||||
}
|
||||
super.onPlaced(world, pos, state, placer, itemStack)
|
||||
}
|
||||
@@ -52,8 +52,8 @@ 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) {
|
||||
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)
|
||||
|
||||
@@ -397,7 +397,7 @@ open class PokemonProperties {
|
||||
return false
|
||||
}
|
||||
}
|
||||
nickname?.takeIf { it != pokemon.nickname }?.let { return false }
|
||||
nickname?.takeIf { it.string != pokemon.nickname?.string }?.let { return false }
|
||||
form?.takeIf { !it.equals(pokemon.form.name, true) }?.let { return false }
|
||||
friendship?.takeIf { it != pokemon.friendship }?.let { return false }
|
||||
pokeball?.takeIf { it != pokemon.caughtBall.name.toString() }?.let { return false }
|
||||
@@ -437,7 +437,7 @@ open class PokemonProperties {
|
||||
}
|
||||
} catch (_: InvalidIdentifierException) {}
|
||||
}
|
||||
nickname?.takeIf { it != properties.nickname }?.let { return false }
|
||||
nickname?.takeIf { it.string != properties.nickname?.string }?.let { return false }
|
||||
form?.takeIf { !it.equals(properties.form, true) }?.let { return false }
|
||||
friendship?.takeIf { it != properties.friendship }?.let { return false }
|
||||
pokeball?.takeIf { it != properties.pokeball }?.let { return false }
|
||||
|
||||
+3
-1
@@ -12,6 +12,8 @@ import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.PlayerSpawner
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.PlayerSpawnerFactory
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
import java.util.UUID
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
|
||||
@@ -34,7 +36,7 @@ object CobblemonWorldSpawnerManager : SpawnerManager() {
|
||||
|
||||
fun onPlayerLogin(player: ServerPlayerEntity) {
|
||||
// Disables spawning
|
||||
if (!Cobblemon.config.enableSpawning) {
|
||||
if (!Cobblemon.config.enableSpawning || server()?.gameRules?.getBoolean(CobblemonGameRules.DO_POKEMON_SPAWNING) == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.spawning.influence.SpawningInfluence
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.Spawner
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.TickingSpawner
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules.DO_POKEMON_SPAWNING
|
||||
|
||||
/**
|
||||
* A manager of various spawners. This is a class in which you should register
|
||||
@@ -49,7 +51,7 @@ open class SpawnerManager {
|
||||
|
||||
open fun onServerTick() {
|
||||
// Disables spawning
|
||||
if (!Cobblemon.config.enableSpawning) {
|
||||
if (!Cobblemon.config.enableSpawning || server()?.gameRules?.getBoolean(DO_POKEMON_SPAWNING) == false) {
|
||||
return
|
||||
}
|
||||
influences.removeIf { it.isExpired() }
|
||||
|
||||
@@ -63,9 +63,6 @@ abstract class AreaSpawner(
|
||||
|
||||
override fun run(cause: SpawnCause): Pair<SpawningContext, SpawnDetail>? {
|
||||
val area = getArea(cause)
|
||||
if (area?.world?.gameRules?.getBoolean(DO_POKEMON_SPAWNING) == false) {
|
||||
return null
|
||||
}
|
||||
val constrainedArea = if (area != null) constrainArea(area) else null
|
||||
if (constrainedArea != null) {
|
||||
|
||||
|
||||
+6
-11
@@ -6,24 +6,19 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.config.starter
|
||||
package com.cobblemon.mod.common.api.starter
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.pokemon.RenderablePokemon
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import net.minecraft.text.Text
|
||||
|
||||
data class StarterCategory(
|
||||
val name: String,
|
||||
val displayName: String,
|
||||
val displayName: Text,
|
||||
val pokemon: List<PokemonProperties>
|
||||
) {
|
||||
fun asRenderableStarterCategory() = RenderableStarterCategory(name, displayName, pokemon.map { it.asRenderablePokemon() })
|
||||
}
|
||||
)
|
||||
|
||||
data class RenderableStarterCategory(
|
||||
val name: String,
|
||||
val displayName: String,
|
||||
val displayName: Text,
|
||||
val pokemon: List<RenderablePokemon>
|
||||
) {
|
||||
val displayNameText = displayName.asTranslated()
|
||||
}
|
||||
)
|
||||
@@ -8,12 +8,12 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.starter
|
||||
|
||||
import com.cobblemon.mod.common.config.starter.StarterCategory
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
interface StarterHandler {
|
||||
fun getStarterList(player: ServerPlayerEntity): List<StarterCategory>
|
||||
fun getStarters(player: ServerPlayerEntity): Map<Identifier, StarterCategory>
|
||||
fun handleJoin(player: ServerPlayerEntity)
|
||||
fun requestStarterChoice(player: ServerPlayerEntity)
|
||||
fun chooseStarter(player: ServerPlayerEntity, categoryName: String, index: Int)
|
||||
fun chooseStarter(player: ServerPlayerEntity, categoryId: Identifier, index: Int)
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.starter
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.data.DataRegistry
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
|
||||
import com.cobblemon.mod.common.util.adapters.PlainJsonTextAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.pokemonPropertiesShortAdapter
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.resource.ResourceType
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
/**
|
||||
* The registry for starter Pokémon.
|
||||
*
|
||||
* The data here is used by the [CobblemonStarterHandler].
|
||||
*
|
||||
* 3rd party is not enforced to respect this registry.
|
||||
*/
|
||||
object StarterRegistry : JsonDataRegistry<StarterCategory> {
|
||||
override val gson: Gson = GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.disableHtmlEscaping()
|
||||
.registerTypeAdapter(Text::class.java, PlainJsonTextAdapter)
|
||||
.registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter)
|
||||
.create()
|
||||
override val typeToken: TypeToken<StarterCategory> = TypeToken.get(StarterCategory::class.java)
|
||||
override val id: Identifier = cobblemonResource("starter")
|
||||
override val resourcePath: String = id.path
|
||||
override val type: ResourceType = ResourceType.SERVER_DATA
|
||||
override val observable: SimpleObservable<out DataRegistry> = SimpleObservable()
|
||||
private val categories = hashMapOf<Identifier, StarterCategory>()
|
||||
|
||||
// We let the default starter handler sync the client
|
||||
// This is to prevent unnecessary packets depending on impl
|
||||
override fun sync(player: ServerPlayerEntity) {}
|
||||
|
||||
override fun reload(data: Map<Identifier, StarterCategory>) {
|
||||
this.categories.clear()
|
||||
this.categories += data
|
||||
Cobblemon.LOGGER.info("Loaded {} starters ({} categories)", this.categories.values.sumOf { it.pokemon.size }, this.categories.size)
|
||||
}
|
||||
|
||||
fun all(): Map<Identifier, StarterCategory> = this.categories
|
||||
|
||||
fun keys(): Set<Identifier> = this.categories.keys
|
||||
|
||||
fun categories(): Collection<StarterCategory> = this.categories.values
|
||||
|
||||
fun categoryOf(key: Identifier): StarterCategory? = this.categories[key]
|
||||
|
||||
fun categoryOf(key: String): StarterCategory? = this.categories[key.asIdentifierDefaultingNamespace()]
|
||||
}
|
||||
@@ -37,7 +37,7 @@ data class PlayerData(
|
||||
fun defaultData(forPlayer: UUID) = PlayerData(
|
||||
uuid = forPlayer,
|
||||
starterPrompted = false,
|
||||
starterLocked = !Cobblemon.starterConfig.allowStarterOnJoin,
|
||||
starterLocked = !Cobblemon.config.allowStarterOnJoin,
|
||||
starterSelected = false,
|
||||
starterUUID = null,
|
||||
keyItems = mutableSetOf(),
|
||||
|
||||
@@ -62,8 +62,8 @@ class MonitorBlock(properties: Settings) : MultiblockBlock(properties) {
|
||||
if(world == null || pos == null) {
|
||||
return 0
|
||||
}
|
||||
val monitorEntity = world.getBlockEntity(pos) as MultiblockEntity
|
||||
val multiBlockEntity = monitorEntity.multiblockStructure
|
||||
val monitorEntity = world.getBlockEntity(pos) as? MultiblockEntity
|
||||
val multiBlockEntity = monitorEntity?.multiblockStructure
|
||||
if(multiBlockEntity != null) {
|
||||
return multiBlockEntity.getComparatorOutput(state, world, pos)
|
||||
}
|
||||
|
||||
@@ -149,8 +149,8 @@ class RestorationTankBlock(properties: Settings) : MultiblockBlock(properties),
|
||||
if(world == null || pos == null) {
|
||||
return 0
|
||||
}
|
||||
val tankEntity = world.getBlockEntity(pos) as MultiblockEntity
|
||||
val multiBlockEntity = tankEntity.multiblockStructure
|
||||
val tankEntity = world.getBlockEntity(pos) as? MultiblockEntity
|
||||
val multiBlockEntity = tankEntity?.multiblockStructure
|
||||
if(multiBlockEntity != null) {
|
||||
return multiBlockEntity.getComparatorOutput(state, world, pos)
|
||||
}
|
||||
@@ -180,7 +180,7 @@ class RestorationTankBlock(properties: Settings) : MultiblockBlock(properties),
|
||||
return
|
||||
}
|
||||
val tankEntity = world.getBlockEntity(pos) as? MultiblockEntity
|
||||
tankEntity?.multiblockStructure!!.onTriggerEvent(state, world, pos, random)
|
||||
tankEntity?.multiblockStructure?.onTriggerEvent(state, world, pos, random)
|
||||
}
|
||||
|
||||
override fun getOutlineShape(
|
||||
|
||||
@@ -9,15 +9,23 @@
|
||||
package com.cobblemon.mod.common.block
|
||||
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonBlockTags
|
||||
import com.cobblemon.mod.common.block.chest.GildedChestBlock
|
||||
import net.minecraft.block.*
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.fluid.FluidState
|
||||
import net.minecraft.fluid.Fluids
|
||||
import net.minecraft.item.ItemPlacementContext
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.server.world.ServerWorld
|
||||
import net.minecraft.state.StateManager
|
||||
import net.minecraft.state.property.BooleanProperty
|
||||
import net.minecraft.state.property.Properties
|
||||
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.world.BlockView
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.world.WorldAccess
|
||||
import net.minecraft.world.WorldView
|
||||
|
||||
@@ -28,7 +36,18 @@ class TumblestoneBlock(
|
||||
height: Int,
|
||||
xzOffset: Int,
|
||||
nextStage: Block?
|
||||
) : GrowableStoneBlock(settings, stage, height, xzOffset, nextStage) {
|
||||
) : GrowableStoneBlock(settings, stage, height, xzOffset, nextStage), Waterloggable {
|
||||
|
||||
init {
|
||||
this.defaultState = this.stateManager.defaultState
|
||||
.with(FACING, Direction.DOWN)
|
||||
.with(WATERLOGGED, false)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val WATERLOGGED = BooleanProperty.of("waterlogged")
|
||||
}
|
||||
|
||||
override fun canGrow(pos: BlockPos, world: BlockView): Boolean {
|
||||
if (stage == MAX_STAGE) return false
|
||||
val iterator: Iterator<BlockPos> =
|
||||
@@ -43,4 +62,31 @@ class TumblestoneBlock(
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getFluidState(state: BlockState): FluidState {
|
||||
return if (state.get(GildedChestBlock.WATERLOGGED)) {
|
||||
Fluids.WATER.getStill(false)
|
||||
} else super.getFluidState(state)
|
||||
}
|
||||
|
||||
override fun appendProperties(builder: StateManager.Builder<Block, BlockState>) {
|
||||
super.appendProperties(builder)
|
||||
builder.add(GildedChestBlock.WATERLOGGED)
|
||||
}
|
||||
|
||||
override fun getPlacementState(blockPlaceContext: ItemPlacementContext): BlockState? {
|
||||
return super.getPlacementState(blockPlaceContext)?.with(GildedChestBlock.WATERLOGGED, blockPlaceContext.world.getFluidState(blockPlaceContext.blockPos).fluid == Fluids.WATER)
|
||||
|
||||
}
|
||||
|
||||
override fun getStateForNeighborUpdate(
|
||||
state: BlockState,
|
||||
direction: Direction,
|
||||
neighborState: BlockState,
|
||||
world: WorldAccess,
|
||||
pos: BlockPos,
|
||||
neighborPos: BlockPos
|
||||
): BlockState? {
|
||||
if (state.get(GildedChestBlock.WATERLOGGED)) world.scheduleFluidTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world))
|
||||
return super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos)
|
||||
}
|
||||
}
|
||||
@@ -16,20 +16,15 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import com.cobblemon.mod.common.util.toVec3d
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockRenderType
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.BlockWithEntity
|
||||
import net.minecraft.block.Blocks
|
||||
import net.minecraft.block.HorizontalFacingBlock
|
||||
import net.minecraft.block.ShapeContext
|
||||
import net.minecraft.block.Waterloggable
|
||||
import net.minecraft.block.*
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.entity.ai.pathing.NavigationType
|
||||
import net.minecraft.entity.mob.PiglinBrain
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.fluid.FluidState
|
||||
import net.minecraft.fluid.Fluids
|
||||
import net.minecraft.item.ItemPlacementContext
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.screen.ScreenHandler
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.sound.SoundCategory
|
||||
@@ -38,12 +33,7 @@ import net.minecraft.state.property.BooleanProperty
|
||||
import net.minecraft.state.property.Properties
|
||||
import net.minecraft.text.MutableText
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.ActionResult
|
||||
import net.minecraft.util.BlockMirror
|
||||
import net.minecraft.util.BlockRotation
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.ItemScatterer
|
||||
import net.minecraft.util.*
|
||||
import net.minecraft.util.hit.BlockHitResult
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Direction
|
||||
@@ -106,7 +96,7 @@ class GildedChestBlock(settings: Settings, val type: Type = Type.RED) : BlockWit
|
||||
neighborPos: BlockPos
|
||||
): BlockState {
|
||||
if (state.get(WATERLOGGED)) world.scheduleFluidTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world))
|
||||
return super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos)
|
||||
return super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos)
|
||||
}
|
||||
|
||||
override fun getFluidState(state: BlockState): FluidState {
|
||||
@@ -258,4 +248,17 @@ class GildedChestBlock(settings: Settings, val type: Type = Type.RED) : BlockWit
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onPlaced(
|
||||
world: World,
|
||||
pos: BlockPos,
|
||||
state: BlockState,
|
||||
placer: LivingEntity?,
|
||||
itemStack: ItemStack
|
||||
) {
|
||||
val blockEntity = world.getBlockEntity(pos)
|
||||
if (itemStack.hasCustomName() && blockEntity is GildedChestBlockEntity) {
|
||||
blockEntity.customName = itemStack.name
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -42,7 +42,7 @@ open class FossilMultiblockEntity(
|
||||
field
|
||||
} else if (masterBlockPos != null && masterBlockPos != pos) {
|
||||
val chunkPos = ChunkPos(masterBlockPos)
|
||||
if (world?.chunkManager?.isChunkLoaded(chunkPos.x, chunkPos.z) == true) {
|
||||
if (world?.chunkManager?.isChunkLoaded(chunkPos.x, chunkPos.z) == true) {
|
||||
val entity: FossilMultiblockEntity? = world?.getBlockEntity(masterBlockPos) as FossilMultiblockEntity?
|
||||
field = entity?.multiblockStructure
|
||||
}
|
||||
|
||||
+1
-1
@@ -140,7 +140,7 @@ class PokemonPastureBlockEntity(pos: BlockPos, val state: BlockState) : BlockEnt
|
||||
if (fixedPosition != null) {
|
||||
entity.setPosition(fixedPosition.toCenterPos().subtract(0.0, 0.5, 0.0))
|
||||
val pc = Cobblemon.storage.getPC(player.uuid)
|
||||
entity.beamMode = 1
|
||||
entity.beamMode = 2
|
||||
afterOnServer(seconds = SendOutPokemonHandler.SEND_OUT_DURATION) {
|
||||
entity.beamMode = 0
|
||||
}
|
||||
|
||||
+12
-12
@@ -117,10 +117,10 @@ class FossilMultiblockBuilder(val centerPos: BlockPos) : MultiblockStructureBuil
|
||||
val monitorPos = monitorPositions[fossilTankIndex]
|
||||
val fossilAnalyzerPos = fossilAnalyzerPositions[fossilTankIndex]!!
|
||||
val restorationTankPos = restorationTankPositions[fossilTankIndex]!!
|
||||
val monitorEntity = world.getBlockEntity(monitorPos) as MultiblockEntity
|
||||
val analyzerEntity = world.getBlockEntity(fossilAnalyzerPos) as MultiblockEntity
|
||||
val tankBaseEntity = world.getBlockEntity(restorationTankPos) as MultiblockEntity
|
||||
val tankTopEntity = world.getBlockEntity(restorationTankPos.up()) as MultiblockEntity
|
||||
val monitorEntity = world.getBlockEntity(monitorPos) as? MultiblockEntity
|
||||
val analyzerEntity = world.getBlockEntity(fossilAnalyzerPos) as? MultiblockEntity
|
||||
val tankBaseEntity = world.getBlockEntity(restorationTankPos) as? MultiblockEntity
|
||||
val tankTopEntity = world.getBlockEntity(restorationTankPos.up()) as? MultiblockEntity
|
||||
val structure = FossilMultiblockStructure(monitorPos, fossilAnalyzerPos, restorationTankPos)
|
||||
|
||||
structure.tankConnectorDirection = dirsToCheck.filter {
|
||||
@@ -128,20 +128,20 @@ class FossilMultiblockBuilder(val centerPos: BlockPos) : MultiblockStructureBuil
|
||||
return@filter adjPos == fossilAnalyzerPos
|
||||
}.first()
|
||||
|
||||
analyzerEntity.multiblockStructure = structure
|
||||
tankBaseEntity.multiblockStructure = structure
|
||||
tankTopEntity.multiblockStructure = structure
|
||||
monitorEntity.multiblockStructure = structure
|
||||
analyzerEntity?.multiblockStructure = structure
|
||||
tankBaseEntity?.multiblockStructure = structure
|
||||
tankTopEntity?.multiblockStructure = structure
|
||||
monitorEntity?.multiblockStructure = structure
|
||||
structure.syncToClient(world)
|
||||
structure.markDirty(world)
|
||||
|
||||
world.playSound(null, centerPos, CobblemonSounds.FOSSIL_MACHINE_ASSEMBLE, SoundCategory.BLOCKS)
|
||||
|
||||
//Set these to null so the builders can be freed
|
||||
analyzerEntity.multiblockBuilder = null
|
||||
tankBaseEntity.multiblockBuilder = null
|
||||
tankTopEntity.multiblockBuilder = null
|
||||
monitorEntity.multiblockBuilder = null
|
||||
analyzerEntity?.multiblockBuilder = null
|
||||
tankBaseEntity?.multiblockBuilder = null
|
||||
tankTopEntity?.multiblockBuilder = null
|
||||
monitorEntity?.multiblockBuilder = null
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
+15
-15
@@ -306,22 +306,22 @@ class FossilMultiblockStructure (
|
||||
}
|
||||
|
||||
override fun onBreak(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity?) {
|
||||
val monitorEntity = world.getBlockEntity(monitorPos) as MultiblockEntity
|
||||
val analyzerEntity = world.getBlockEntity(analyzerPos) as MultiblockEntity
|
||||
val tankBaseEntity = world.getBlockEntity(tankBasePos) as MultiblockEntity
|
||||
val tankTopEntity = world.getBlockEntity(tankBasePos.up()) as MultiblockEntity
|
||||
val state = world.getBlockState(tankBaseEntity.pos)
|
||||
val monitorEntity = world.getBlockEntity(monitorPos) as? MultiblockEntity
|
||||
val analyzerEntity = world.getBlockEntity(analyzerPos) as? MultiblockEntity
|
||||
val tankBaseEntity = world.getBlockEntity(tankBasePos) as? MultiblockEntity
|
||||
val tankTopEntity = world.getBlockEntity(tankBasePos.up()) as? MultiblockEntity
|
||||
val state = world.getBlockState(tankBaseEntity?.pos)
|
||||
val direction = state.get(HorizontalFacingBlock.FACING).getOpposite()
|
||||
val wildPokemon: Pokemon? = this.createdPokemon
|
||||
|
||||
monitorEntity.multiblockStructure = null
|
||||
analyzerEntity.multiblockStructure = null
|
||||
tankBaseEntity.multiblockStructure = null
|
||||
tankTopEntity.multiblockStructure = null
|
||||
monitorEntity.masterBlockPos = null
|
||||
analyzerEntity.masterBlockPos = null
|
||||
tankBaseEntity.masterBlockPos = null
|
||||
tankTopEntity.masterBlockPos = null
|
||||
monitorEntity?.multiblockStructure = null
|
||||
analyzerEntity?.multiblockStructure = null
|
||||
tankBaseEntity?.multiblockStructure = null
|
||||
tankTopEntity?.multiblockStructure = null
|
||||
monitorEntity?.masterBlockPos = null
|
||||
analyzerEntity?.masterBlockPos = null
|
||||
tankBaseEntity?.masterBlockPos = null
|
||||
tankTopEntity?.masterBlockPos = null
|
||||
|
||||
// Drop fossils from machine as long as the machine is not started or near completion
|
||||
if (this.timeRemaining == -1 || this.timeRemaining >= 20) {
|
||||
@@ -619,8 +619,8 @@ class FossilMultiblockStructure (
|
||||
}
|
||||
|
||||
const val TICKS_PER_MINUTE = 1200
|
||||
const val MATERIAL_TO_START = 256
|
||||
const val TIME_TO_TAKE = TICKS_PER_MINUTE * 15
|
||||
const val MATERIAL_TO_START = 128
|
||||
const val TIME_TO_TAKE = TICKS_PER_MINUTE * 12
|
||||
const val TIME_PER_STAGE = TIME_TO_TAKE / 8
|
||||
const val PROTECTION_TIME = TICKS_PER_MINUTE * 5
|
||||
|
||||
|
||||
+62
-38
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.client.entity
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.entity.PokemonSideDelegate
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.getQueryStruct
|
||||
@@ -22,7 +21,6 @@ import com.cobblemon.mod.common.api.scheduling.lerpOnClient
|
||||
import com.cobblemon.mod.common.client.particle.BedrockParticleEffectRepository
|
||||
import com.cobblemon.mod.common.client.particle.ParticleStorm
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper
|
||||
import com.cobblemon.mod.common.client.render.SnowstormParticle
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.PrimaryAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.StatefulAnimation
|
||||
@@ -34,11 +32,8 @@ import com.cobblemon.mod.common.util.MovingSoundInstance
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.client.util.math.MatrixStack
|
||||
import java.lang.Float.min
|
||||
import kotlin.math.abs
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.entity.data.TrackedData
|
||||
import net.minecraft.particle.ParticleTypes
|
||||
import net.minecraft.sound.SoundCategory
|
||||
import net.minecraft.sound.SoundEvent
|
||||
import net.minecraft.util.Hand
|
||||
@@ -105,6 +100,8 @@ class PokemonClientDelegate : PoseableEntityState<PokemonEntity>(), PokemonSideD
|
||||
this.addPrimaryAnimation(primaryAnimation)
|
||||
}
|
||||
} else if (data == PokemonEntity.BEAM_MODE) {
|
||||
// If you make adjustments to this code, make sure to Find Usages for both PokemonEntity.beamMode and PokemonEntity.BEAM_MODE
|
||||
// TODO: change beamMode to an enum, or a set of booleans (send-out vs recall, delay vs delay)
|
||||
val beamMode = currentEntity.beamMode
|
||||
when (beamMode) {
|
||||
0 -> { /* Do nothing */ }
|
||||
@@ -141,39 +138,37 @@ class PokemonClientDelegate : PoseableEntityState<PokemonEntity>(), PokemonSideD
|
||||
currentEntity.after(seconds = POKEBALL_AIR_TIME){
|
||||
beamStartTime = System.currentTimeMillis()
|
||||
ballDone = true
|
||||
if (client.soundManager.get(CobblemonSounds.POKE_BALL_OPEN.id) != null && !playedSendOutSound) {
|
||||
currentEntity.owner?.let {
|
||||
client.world?.playSound(client.player, soundPos.x, soundPos.y, soundPos.z, SoundEvent.of(CobblemonSounds.POKE_BALL_SEND_OUT.id), SoundCategory.PLAYERS, 0.6f, 1f)
|
||||
playedSendOutSound = true
|
||||
/// create end rod particles in a 0.1 radius around the soundPos with a count of 50 and a random velocity of 0.1
|
||||
sendOutPosition?.let{
|
||||
val newPos = it.add(sendOutOffset)
|
||||
val ballType = currentEntity.pokemon.caughtBall.name.path.toLowerCase().replace("_","")
|
||||
val mode = if(currentEntity.isBattling) "battle" else "casual"
|
||||
val sendflash = BedrockParticleEffectRepository.getEffect(cobblemonResource("${ballType}/${mode}/sendflash"))
|
||||
sendflash?.let { effect ->
|
||||
val wrapper = MatrixWrapper()
|
||||
val matrix = MatrixStack()
|
||||
matrix.translate(newPos.x, newPos.y, newPos.z)
|
||||
wrapper.updateMatrix(matrix.peek().positionMatrix)
|
||||
val world = MinecraftClient.getInstance().world ?: return@let
|
||||
if (client.soundManager.get(CobblemonSounds.POKE_BALL_SEND_OUT.id) != null && !playedSendOutSound) {
|
||||
client.world?.playSound(client.player, soundPos.x, soundPos.y, soundPos.z, SoundEvent.of(CobblemonSounds.POKE_BALL_SEND_OUT.id), SoundCategory.PLAYERS, 0.6f, 1f)
|
||||
playedSendOutSound = true
|
||||
}
|
||||
// Display ball-specific particles
|
||||
sendOutPosition?.let{
|
||||
val newPos = it.add(sendOutOffset)
|
||||
val ballType = currentEntity.pokemon.caughtBall.name.path.lowercase().replace("_","")
|
||||
val mode = if(currentEntity.isBattling) "battle" else "casual"
|
||||
val sendflash = BedrockParticleEffectRepository.getEffect(cobblemonResource("${ballType}/${mode}/sendflash"))
|
||||
sendflash?.let { effect ->
|
||||
val wrapper = MatrixWrapper()
|
||||
val matrix = MatrixStack()
|
||||
matrix.translate(newPos.x, newPos.y, newPos.z)
|
||||
wrapper.updateMatrix(matrix.peek().positionMatrix)
|
||||
val world = MinecraftClient.getInstance().world ?: return@let
|
||||
ParticleStorm(effect, wrapper, world).spawn()
|
||||
val ballsparks = BedrockParticleEffectRepository.getEffect(cobblemonResource("${ballType}/${mode}/ballsparks"))
|
||||
val ballsendsparkle = BedrockParticleEffectRepository.getEffect(cobblemonResource("${ballType}/${mode}/ballsendsparkle"))
|
||||
// using afterOnClient because it's such a small timeframe that it's unlikely the entity has been removed & we'd like the precision
|
||||
afterOnClient(seconds = 0.01667f) {
|
||||
ballsparks?.let { effect ->
|
||||
ParticleStorm(effect, wrapper, world).spawn()
|
||||
val ballsparks = BedrockParticleEffectRepository.getEffect(cobblemonResource("${ballType}/${mode}/ballsparks"))
|
||||
val ballsendsparkle = BedrockParticleEffectRepository.getEffect(cobblemonResource("${ballType}/${mode}/ballsendsparkle"))
|
||||
// using afterOnClient because it's such a small timeframe that it's unlikely the entity has been removed & we'd like the precision
|
||||
afterOnClient(seconds = 0.01667f) {
|
||||
ballsparks?.let { effect ->
|
||||
ParticleStorm(effect, wrapper, world).spawn()
|
||||
}
|
||||
ballsendsparkle?.let { effect ->
|
||||
ParticleStorm(effect, wrapper, world).spawn()
|
||||
}
|
||||
currentEntity.after(seconds = 0.4f) {
|
||||
val ballsparkle = BedrockParticleEffectRepository.getEffect(cobblemonResource("${ballType}/ballsparkle"))
|
||||
ballsparkle?.let { effect ->
|
||||
ParticleStorm(effect, wrapper, world).spawn()
|
||||
}
|
||||
}
|
||||
}
|
||||
ballsendsparkle?.let { effect ->
|
||||
ParticleStorm(effect, wrapper, world).spawn()
|
||||
}
|
||||
currentEntity.after(seconds = 0.4f) {
|
||||
val ballsparkle = BedrockParticleEffectRepository.getEffect(cobblemonResource("${ballType}/ballsparkle"))
|
||||
ballsparkle?.let { effect ->
|
||||
ParticleStorm(effect, wrapper, world).spawn()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -190,7 +185,35 @@ class PokemonClientDelegate : PoseableEntityState<PokemonEntity>(), PokemonSideD
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
2 -> {
|
||||
// Scaling up with no delay and no particles
|
||||
playedSendOutSound = false
|
||||
entityScaleModifier = 0F
|
||||
currentEntity.isInvisible = false
|
||||
val soundPos = currentEntity.pos
|
||||
val client = MinecraftClient.getInstance()
|
||||
|
||||
if (client.soundManager.get(CobblemonSounds.POKE_BALL_SEND_OUT.id) != null && !playedSendOutSound) {
|
||||
client.world?.playSound(
|
||||
client.player,
|
||||
soundPos.x,
|
||||
soundPos.y,
|
||||
soundPos.z,
|
||||
CobblemonSounds.POKE_BALL_SEND_OUT,
|
||||
SoundCategory.PLAYERS,
|
||||
0.6f,
|
||||
1f
|
||||
)
|
||||
playedSendOutSound = true
|
||||
}
|
||||
lerpOnClient(BEAM_SHRINK_TIME) { entityScaleModifier = it }
|
||||
currentEntity.after(seconds = BEAM_SHRINK_TIME * 2) {
|
||||
ballOffset = 0f
|
||||
ballRotOffset = 0f
|
||||
sendOutPosition = null
|
||||
}
|
||||
}
|
||||
3 -> {
|
||||
// Scaling down into pokeball
|
||||
entityScaleModifier = 1F
|
||||
beamStartTime = System.currentTimeMillis()
|
||||
@@ -203,6 +226,7 @@ class PokemonClientDelegate : PoseableEntityState<PokemonEntity>(), PokemonSideD
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> { /* Do nothing */ }
|
||||
}
|
||||
} else if (data == PokemonEntity.LABEL_LEVEL) {
|
||||
currentEntity.dataTracker.get(PokemonEntity.LABEL_LEVEL)
|
||||
|
||||
+21
-17
@@ -27,7 +27,7 @@ import com.cobblemon.mod.common.client.gui.summary.widgets.type.DualTypeWidget
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.type.SingleTypeWidget
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.type.TypeWidget
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.config.starter.RenderableStarterCategory
|
||||
import com.cobblemon.mod.common.api.starter.RenderableStarterCategory
|
||||
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
|
||||
import com.cobblemon.mod.common.pokemon.RenderablePokemon
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
@@ -40,6 +40,7 @@ import net.minecraft.client.gui.screen.Screen
|
||||
import net.minecraft.client.sound.PositionedSoundInstance
|
||||
import net.minecraft.client.toast.Toast
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
/**
|
||||
* Starterselection Screen Thingy
|
||||
@@ -47,7 +48,7 @@ import net.minecraft.text.Text
|
||||
* @author Qu
|
||||
* @since 2022-06-18
|
||||
*/
|
||||
class StarterSelectionScreen(private val categories: List<RenderableStarterCategory>): Screen("cobblemon.ui.starter.title".asTranslated()) {
|
||||
class StarterSelectionScreen(categories: Map<Identifier, RenderableStarterCategory>): Screen("cobblemon.ui.starter.title".asTranslated()) {
|
||||
|
||||
companion object {
|
||||
// Size of UI at scale 1
|
||||
@@ -64,8 +65,9 @@ class StarterSelectionScreen(private val categories: List<RenderableStarterCateg
|
||||
private val doubleTypeBackground = cobblemonResource("textures/gui/starterselection/starterselection_type_slot2.png")
|
||||
}
|
||||
|
||||
private val categories = categories.toSortedMap { a, b -> a.compareTo(b) }
|
||||
private var currentSelection = 0
|
||||
private lateinit var currentCategory: RenderableStarterCategory
|
||||
private lateinit var currentCategoryId: Identifier
|
||||
private lateinit var modelWidget: ModelWidget
|
||||
private lateinit var currentPokemon: RenderablePokemon
|
||||
private lateinit var typeWidget: TypeWidget
|
||||
@@ -95,7 +97,7 @@ class StarterSelectionScreen(private val categories: List<RenderableStarterCateg
|
||||
paneWidth = 71, paneHeight = BASE_HEIGHT - 11,
|
||||
topOffset = 6, bottomOffset = 5,
|
||||
entryHeight = 20, entryWidth = 57,
|
||||
categories = categories,
|
||||
categories = this.categories,
|
||||
x = x - 2, y = y + 8,
|
||||
starterSelectionScreen = this
|
||||
)
|
||||
@@ -120,8 +122,8 @@ class StarterSelectionScreen(private val categories: List<RenderableStarterCateg
|
||||
addDrawableChild(rightButton)
|
||||
addDrawableChild(leftButton)
|
||||
|
||||
currentCategory = categories.first()
|
||||
currentPokemon = currentCategory.pokemon[currentSelection]
|
||||
currentCategoryId = categories.firstKey()
|
||||
currentPokemon = this.currentCategory().pokemon[currentSelection]
|
||||
|
||||
with(currentPokemon) {
|
||||
modelWidget = ModelWidget(
|
||||
@@ -142,11 +144,11 @@ class StarterSelectionScreen(private val categories: List<RenderableStarterCateg
|
||||
) {
|
||||
CobblemonNetwork.sendPacketToServer(
|
||||
SelectStarterPacket(
|
||||
categoryName = currentCategory.name,
|
||||
categoryId = currentCategoryId,
|
||||
selected = currentSelection
|
||||
)
|
||||
)
|
||||
MinecraftClient.getInstance().setScreen(null)
|
||||
this.close()
|
||||
}
|
||||
|
||||
addDrawableChild(selectionButton)
|
||||
@@ -161,7 +163,7 @@ class StarterSelectionScreen(private val categories: List<RenderableStarterCateg
|
||||
starterRoundaboutLeft = StarterRoundabout(
|
||||
pX = x + 89, pY = height / 2 + 84,
|
||||
pWidth = StarterRoundabout.MODEL_WIDTH, pHeight = StarterRoundabout.MODEL_HEIGHT,
|
||||
pokemon = currentCategory.pokemon[leftOfCurrentSelection()],
|
||||
pokemon = this.currentCategory().pokemon[leftOfCurrentSelection()],
|
||||
clickAction = { _, _ -> this.left() },
|
||||
rotationVector = this.modelWidget.rotVec
|
||||
)
|
||||
@@ -169,7 +171,7 @@ class StarterSelectionScreen(private val categories: List<RenderableStarterCateg
|
||||
starterRoundaboutRight = StarterRoundabout(
|
||||
pX = x + 149, pY = height / 2 + 84,
|
||||
pWidth = StarterRoundabout.MODEL_WIDTH, pHeight = StarterRoundabout.MODEL_HEIGHT,
|
||||
pokemon = currentCategory.pokemon[rightOfCurrentSelection()],
|
||||
pokemon = this.currentCategory().pokemon[rightOfCurrentSelection()],
|
||||
clickAction = { _, _ -> this.right() },
|
||||
rotationVector = this.modelWidget.rotVec
|
||||
)
|
||||
@@ -276,8 +278,8 @@ class StarterSelectionScreen(private val categories: List<RenderableStarterCateg
|
||||
super.render(context, mouseX, mouseY, delta)
|
||||
}
|
||||
|
||||
fun changeCategory(category: RenderableStarterCategory) {
|
||||
currentCategory = category
|
||||
fun changeCategory(id: Identifier) {
|
||||
currentCategoryId = id
|
||||
currentSelection = 0
|
||||
updateSelection()
|
||||
}
|
||||
@@ -288,7 +290,7 @@ class StarterSelectionScreen(private val categories: List<RenderableStarterCateg
|
||||
updateSelection()
|
||||
}
|
||||
|
||||
private fun rightOfCurrentSelection() : Int = if (currentSelection + 1 <= currentCategory.pokemon.size - 1) currentSelection + 1 else 0
|
||||
private fun rightOfCurrentSelection() : Int = if (currentSelection + 1 <= this.currentCategory().pokemon.size - 1) currentSelection + 1 else 0
|
||||
|
||||
private fun left() {
|
||||
MinecraftClient.getInstance().soundManager.play(PositionedSoundInstance.master(CobblemonSounds.GUI_CLICK, 1.0F))
|
||||
@@ -296,16 +298,16 @@ class StarterSelectionScreen(private val categories: List<RenderableStarterCateg
|
||||
updateSelection()
|
||||
}
|
||||
|
||||
private fun leftOfCurrentSelection() : Int = if (currentSelection - 1 == -1) currentCategory.pokemon.size - 1 else currentSelection - 1
|
||||
private fun leftOfCurrentSelection() : Int = if (currentSelection - 1 == -1) this.currentCategory().pokemon.size - 1 else currentSelection - 1
|
||||
|
||||
private fun updateSelection() {
|
||||
currentPokemon = currentCategory.pokemon[currentSelection].also {
|
||||
currentPokemon = this.currentCategory().pokemon[currentSelection].also {
|
||||
modelWidget.pokemon = it
|
||||
typeWidget = typeWidget(it, (width - BASE_WIDTH) / 2, (height - BASE_HEIGHT) / 2)
|
||||
}
|
||||
starterRoundaboutLeft.pokemon = currentCategory.pokemon[leftOfCurrentSelection()]
|
||||
starterRoundaboutLeft.pokemon = this.currentCategory().pokemon[leftOfCurrentSelection()]
|
||||
starterRoundaboutCenter.pokemon = currentPokemon
|
||||
starterRoundaboutRight.pokemon = currentCategory.pokemon[rightOfCurrentSelection()]
|
||||
starterRoundaboutRight.pokemon = this.currentCategory().pokemon[rightOfCurrentSelection()]
|
||||
}
|
||||
|
||||
private fun typeWidget(pokemon: RenderablePokemon, x: Int, y: Int) : TypeWidget {
|
||||
@@ -324,5 +326,7 @@ class StarterSelectionScreen(private val categories: List<RenderableStarterCateg
|
||||
)
|
||||
}
|
||||
|
||||
private fun currentCategory(): RenderableStarterCategory = this.categories[this.currentCategoryId]!!
|
||||
|
||||
override fun shouldPause() = true
|
||||
}
|
||||
+9
-19
@@ -12,14 +12,14 @@ import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.startselection.StarterSelectionScreen
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.config.starter.RenderableStarterCategory
|
||||
import com.cobblemon.mod.common.api.starter.RenderableStarterCategory
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.client.gui.DrawContext
|
||||
import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget
|
||||
import net.minecraft.client.sound.PositionedSoundInstance
|
||||
import net.minecraft.client.util.math.MatrixStack
|
||||
import net.minecraft.text.Text
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
class CategoryList(
|
||||
private val paneWidth: Int,
|
||||
@@ -28,7 +28,7 @@ class CategoryList(
|
||||
bottomOffset: Int,
|
||||
private val entryWidth: Int,
|
||||
entryHeight: Int,
|
||||
private val categories: List<RenderableStarterCategory>,
|
||||
private val categories: Map<Identifier, RenderableStarterCategory>,
|
||||
val x: Int, val y: Int,
|
||||
private val minecraft: MinecraftClient = MinecraftClient.getInstance(),
|
||||
private val starterSelectionScreen: StarterSelectionScreen
|
||||
@@ -44,7 +44,6 @@ class CategoryList(
|
||||
companion object {
|
||||
private const val CATEGORY_BUTTON_WIDTH = 51.5f
|
||||
private const val CATEGORY_BUTTON_HEIGHT = 16f
|
||||
private const val ENTRY_X_OFFSET = 10f
|
||||
private val categoryResource = cobblemonResource("textures/gui/starterselection/starterselection_slot.png")
|
||||
}
|
||||
|
||||
@@ -53,19 +52,12 @@ class CategoryList(
|
||||
this.setRenderHorizontalShadows(false)
|
||||
this.setRenderBackground(false)
|
||||
this.setRenderSelection(false)
|
||||
}
|
||||
|
||||
private var entriesCreated = false
|
||||
|
||||
private fun createEntries() = categories.map {
|
||||
Category(it)
|
||||
this.categories.forEach { (id, category) ->
|
||||
this.addEntry(Category(id, category))
|
||||
}
|
||||
}
|
||||
|
||||
override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
if (!entriesCreated) {
|
||||
createEntries().forEach { addEntry(it) }
|
||||
entriesCreated = true
|
||||
}
|
||||
context.enableScissor(
|
||||
x,
|
||||
y,
|
||||
@@ -80,15 +72,13 @@ class CategoryList(
|
||||
this.updateSize(this.paneWidth, this.paneHeight, this.y, this.y + this.paneHeight)
|
||||
this.setLeftPos(this.x)
|
||||
}
|
||||
|
||||
private fun scale(n: Int): Int = (this.client.window.scaleFactor * n).toInt()
|
||||
override fun getRowWidth() = this.entryWidth
|
||||
override fun getScrollbarPositionX(): Int {
|
||||
return this.left + this.width - 5
|
||||
}
|
||||
|
||||
|
||||
inner class Category(private val category: RenderableStarterCategory) : Entry<Category>() {
|
||||
inner class Category(private val id: Identifier, private val category: RenderableStarterCategory) : Entry<Category>() {
|
||||
|
||||
override fun render(
|
||||
context: DrawContext,
|
||||
@@ -121,7 +111,7 @@ class CategoryList(
|
||||
)
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = category.displayNameText,
|
||||
text = category.displayName.copy(),
|
||||
x = x + 28,
|
||||
y = y + 4.5F,
|
||||
scale = 1F,
|
||||
@@ -132,7 +122,7 @@ class CategoryList(
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
starterSelectionScreen.changeCategory(category = category)
|
||||
starterSelectionScreen.changeCategory(this.id)
|
||||
minecraft.soundManager.play(PositionedSoundInstance.master(CobblemonSounds.GUI_CLICK, 1.0F))
|
||||
return true
|
||||
}
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ class RestorationTankRenderer(ctx: BlockEntityRendererFactory.Context) : BlockEn
|
||||
|
||||
val fluidModel = if (struct.isRunning()) FLUID_MODELS[8]
|
||||
else if (struct.createdPokemon != null) FLUID_MODELS[7]
|
||||
else FLUID_MODELS[fillLevel-1]
|
||||
else FLUID_MODELS[fillLevel.coerceAtMost(FLUID_MODELS.size - 1) - 1]
|
||||
fluidModel.getQuads(entity.cachedState, null, entity.world?.random).forEach { quad ->
|
||||
transparentBuffer?.quad(matrices.peek(), quad, 0.75f, 0.75f, 0.75f, light, OverlayTexture.DEFAULT_UV)
|
||||
}
|
||||
|
||||
+5
@@ -67,6 +67,11 @@ abstract class PokeBallPoseableState : PoseableEntityState<EmptyPokeBallEntity>(
|
||||
setStatefulAnimations(currentModel!!.bedrockStateful(group, "critical"))
|
||||
}
|
||||
}
|
||||
EmptyPokeBallEntity.CaptureState.BROKEN_FREE -> {
|
||||
doLater {
|
||||
setStatefulAnimations(currentModel!!.bedrockStateful(group, "break"))
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -32,7 +32,6 @@ import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.util.math.DoubleRange
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import com.cobblemon.mod.common.util.math.remap
|
||||
import kotlin.math.*
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.client.font.TextRenderer
|
||||
import net.minecraft.client.render.*
|
||||
@@ -53,6 +52,7 @@ import org.joml.Math
|
||||
import org.joml.Quaternionf
|
||||
import org.joml.Vector3f
|
||||
import org.joml.Vector4f
|
||||
import kotlin.math.*
|
||||
|
||||
class PokemonRenderer(
|
||||
context: EntityRendererFactory.Context
|
||||
@@ -60,7 +60,7 @@ class PokemonRenderer(
|
||||
companion object {
|
||||
val recallBeamColour = Vector4f(1F, 0.1F, 0.1F, 1F)
|
||||
fun ease(x: Double): Double {
|
||||
return 1 - (1 - x).pow(3);
|
||||
return 1 - (1 - x).pow(3)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ class PokemonRenderer(
|
||||
if (entity.beamMode != 0) {
|
||||
renderTransition(
|
||||
modelNow,
|
||||
entity.beamMode == 1,
|
||||
entity.beamMode,
|
||||
entity,
|
||||
partialTicks,
|
||||
poseMatrix,
|
||||
@@ -130,7 +130,7 @@ class PokemonRenderer(
|
||||
|
||||
fun renderTransition(
|
||||
modelNow: PoseableEntityModel<PokemonEntity>,
|
||||
sendingOut: Boolean,
|
||||
beamMode: Int,
|
||||
entity: PokemonEntity,
|
||||
partialTicks: Float,
|
||||
poseMatrix: MatrixStack,
|
||||
@@ -139,7 +139,7 @@ class PokemonRenderer(
|
||||
clientDelegate: PokemonClientDelegate
|
||||
) {
|
||||
val s = clientDelegate.secondsSinceBeamEffectStarted
|
||||
if (modelNow is PokemonPoseableModel && !sendingOut) {
|
||||
if (modelNow is PokemonPoseableModel && beamMode == 3) {
|
||||
if (s > BEAM_EXTEND_TIME) {
|
||||
val value = (s - BEAM_EXTEND_TIME) / BEAM_SHRINK_TIME
|
||||
val colourValue = 1F - min(0.6F, value)
|
||||
@@ -163,9 +163,9 @@ class PokemonRenderer(
|
||||
}
|
||||
}
|
||||
|
||||
if (clientDelegate.sendOutPosition == null && sendingOut) {
|
||||
if (clientDelegate.sendOutPosition == null && beamMode == 1) {
|
||||
clientDelegate.sendOutPosition = beamSourcePosition
|
||||
} else if (sendingOut) {
|
||||
} else if (beamMode == 1) {
|
||||
clientDelegate.sendOutPosition = clientDelegate.sendOutPosition!!.add(0.0, 0.04, 0.0)
|
||||
beamSourcePosition = clientDelegate.sendOutPosition!!
|
||||
}
|
||||
@@ -184,9 +184,9 @@ class PokemonRenderer(
|
||||
poseMatrix.multiply(RotationAxis.POSITIVE_Y.rotation(-angle.toFloat() + (180 * Math.PI / 180).toFloat()))
|
||||
|
||||
// TODO: if you want to remove the open ball, add `!clientDelegate.ballDone` to the if statement
|
||||
if (sendingOut && !clientDelegate.ballDone){
|
||||
if (beamMode == 1 && !clientDelegate.ballDone){
|
||||
if(entity.pokemon.caughtBall.name.toString().contains("beast")){
|
||||
// get rotation angle on x acis for facingDir
|
||||
// get rotation angle on x-axis for facingDir
|
||||
val xAngleFacingDir = MathHelper.atan2(facingDir.y, sqrt(facingDir.x * facingDir.x + facingDir.z * facingDir.z))
|
||||
poseMatrix.multiply(RotationAxis.POSITIVE_X.rotation(-xAngleFacingDir.toFloat()))
|
||||
}
|
||||
@@ -203,7 +203,7 @@ class PokemonRenderer(
|
||||
)
|
||||
}
|
||||
poseMatrix.pop()
|
||||
if (!sendingOut) {
|
||||
if (beamMode == 3) {
|
||||
renderBeam(poseMatrix, partialTicks, entity, phaseTarget, buffer, offsetDirection)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-16
@@ -9,11 +9,7 @@
|
||||
package com.cobblemon.mod.common.command
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.permission.CobblemonPermissions
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.net.messages.client.starter.OpenStarterUIPacket
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.util.permission
|
||||
import com.mojang.brigadier.Command.SINGLE_SUCCESS
|
||||
import com.mojang.brigadier.CommandDispatcher
|
||||
@@ -38,18 +34,7 @@ object OpenStarterScreenCommand {
|
||||
|
||||
private fun execute(context: CommandContext<ServerCommandSource>) : Int {
|
||||
val player = EntityArgumentType.getPlayer(context, "player")
|
||||
val playerData = Cobblemon.playerData.get(player)
|
||||
if (playerData.starterSelected) {
|
||||
context.source.sendFeedback({ lang("ui.starter.hasalreadychosen", player.name).red() }, true)
|
||||
return 0
|
||||
}
|
||||
if (playerData.starterLocked) {
|
||||
playerData.starterLocked = false
|
||||
playerData.sendToPlayer(player)
|
||||
}
|
||||
playerData.starterPrompted = true
|
||||
Cobblemon.playerData.saveSingle(playerData)
|
||||
player.sendPacket(OpenStarterUIPacket(Cobblemon.starterHandler.getStarterList(player)))
|
||||
Cobblemon.starterHandler.requestStarterChoice(player)
|
||||
return SINGLE_SUCCESS
|
||||
}
|
||||
|
||||
|
||||
@@ -113,6 +113,12 @@ class CobblemonConfig {
|
||||
@NodeCategory(Category.Starter)
|
||||
var exportStarterConfig = false
|
||||
|
||||
@NodeCategory(Category.Starter)
|
||||
var allowStarterOnJoin = true
|
||||
|
||||
@NodeCategory(Category.Starter)
|
||||
var promptStarterOnceOnly = true
|
||||
|
||||
@NodeCategory(Category.Battles)
|
||||
var autoUpdateShowdown = true
|
||||
|
||||
|
||||
@@ -1,128 +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.config.starter
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.config.Category
|
||||
import com.cobblemon.mod.common.config.LastChangedVersion
|
||||
import com.cobblemon.mod.common.config.NodeCategory
|
||||
import com.cobblemon.mod.common.util.adapters.pokemonPropertiesShortAdapter
|
||||
import com.google.gson.GsonBuilder
|
||||
|
||||
class StarterConfig {
|
||||
companion object {
|
||||
val GSON = GsonBuilder()
|
||||
.disableHtmlEscaping()
|
||||
.setPrettyPrinting()
|
||||
.registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter)
|
||||
.create()
|
||||
}
|
||||
|
||||
@NodeCategory(Category.Starter)
|
||||
var allowStarterOnJoin = true
|
||||
|
||||
@NodeCategory(Category.Starter)
|
||||
@LastChangedVersion("1.5.0")
|
||||
var promptStarterOnceOnly = true
|
||||
|
||||
@NodeCategory(Category.Starter)
|
||||
var starters = mutableListOf(
|
||||
StarterCategory(
|
||||
name = "Kanto",
|
||||
displayName = "cobblemon.starterselection.category.kanto",
|
||||
pokemon = mutableListOf(
|
||||
PokemonProperties.parse("Bulbasaur level=10"),
|
||||
PokemonProperties.parse("Charmander level=10"),
|
||||
PokemonProperties.parse("Squirtle level=10"),
|
||||
)
|
||||
),
|
||||
StarterCategory(
|
||||
name = "Johto",
|
||||
displayName = "cobblemon.starterselection.category.johto",
|
||||
pokemon = mutableListOf(
|
||||
PokemonProperties.parse("Chikorita level=10"),
|
||||
PokemonProperties.parse("Cyndaquil level=10"),
|
||||
PokemonProperties.parse("Totodile level=10"),
|
||||
)
|
||||
),
|
||||
StarterCategory(
|
||||
name = "Hoenn",
|
||||
displayName = "cobblemon.starterselection.category.hoenn",
|
||||
pokemon = mutableListOf(
|
||||
PokemonProperties.parse("Treecko level=10"),
|
||||
PokemonProperties.parse("Torchic level=10"),
|
||||
PokemonProperties.parse("Mudkip level=10"),
|
||||
)
|
||||
),
|
||||
StarterCategory(
|
||||
name = "Sinnoh",
|
||||
displayName = "cobblemon.starterselection.category.sinnoh",
|
||||
pokemon = mutableListOf(
|
||||
PokemonProperties.parse("Turtwig level=10"),
|
||||
PokemonProperties.parse("Chimchar level=10"),
|
||||
PokemonProperties.parse("Piplup level=10"),
|
||||
)
|
||||
),
|
||||
StarterCategory(
|
||||
name = "Unova",
|
||||
displayName = "cobblemon.starterselection.category.unova",
|
||||
pokemon = mutableListOf(
|
||||
PokemonProperties.parse("Snivy level=10"),
|
||||
PokemonProperties.parse("Tepig level=10"),
|
||||
PokemonProperties.parse("Oshawott level=10"),
|
||||
)
|
||||
),
|
||||
StarterCategory(
|
||||
name = "Kalos",
|
||||
displayName = "cobblemon.starterselection.category.kalos",
|
||||
pokemon = mutableListOf(
|
||||
PokemonProperties.parse("Chespin level=10"),
|
||||
PokemonProperties.parse("Fennekin level=10"),
|
||||
PokemonProperties.parse("Froakie level=10"),
|
||||
)
|
||||
),
|
||||
StarterCategory(
|
||||
name = "Alola",
|
||||
displayName = "cobblemon.starterselection.category.alola",
|
||||
pokemon = mutableListOf(
|
||||
PokemonProperties.parse("Rowlet level=10"),
|
||||
PokemonProperties.parse("Litten level=10"),
|
||||
PokemonProperties.parse("Popplio level=10"),
|
||||
)
|
||||
),
|
||||
StarterCategory(
|
||||
name = "Galar",
|
||||
displayName = "cobblemon.starterselection.category.galar",
|
||||
pokemon = mutableListOf(
|
||||
PokemonProperties.parse("Grookey level=10"),
|
||||
PokemonProperties.parse("Scorbunny level=10"),
|
||||
PokemonProperties.parse("Sobble level=10"),
|
||||
)
|
||||
),
|
||||
StarterCategory(
|
||||
name = "Paldea",
|
||||
displayName = "cobblemon.starterselection.category.paldea",
|
||||
pokemon = mutableListOf(
|
||||
PokemonProperties.parse("Sprigatito level=10"),
|
||||
PokemonProperties.parse("Fuecoco level=10"),
|
||||
PokemonProperties.parse("Quaxly level=10"),
|
||||
)
|
||||
)
|
||||
//,
|
||||
// StarterCategory(
|
||||
// name = "Johto",
|
||||
// displayName = lang("starterselection.category.johto"),
|
||||
// pokemon = mutableListOf(
|
||||
// PokemonProperties().also { it.level = 5 ; it.species = "Chikorita" },
|
||||
// PokemonProperties().also { it.level = 5 ; it.species = "Cyndaquil" },
|
||||
// PokemonProperties().also { it.level = 5 ; it.species = "Totodile" }
|
||||
// )
|
||||
// )
|
||||
)
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import com.cobblemon.mod.common.api.pokemon.feature.SpeciesFeatures
|
||||
import com.cobblemon.mod.common.api.spawning.CobblemonSpawnPools
|
||||
import com.cobblemon.mod.common.api.spawning.CobblemonSpawnRules
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnDetailPresets
|
||||
import com.cobblemon.mod.common.api.starter.StarterRegistry
|
||||
import com.cobblemon.mod.common.battles.BagItems
|
||||
import com.cobblemon.mod.common.net.messages.client.data.UnlockReloadPacket
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
@@ -63,6 +64,7 @@ object CobblemonDataProvider : DataProvider {
|
||||
this.register(Abilities)
|
||||
this.register(PokemonSpecies)
|
||||
this.register(SpeciesAdditions)
|
||||
this.register(StarterRegistry)
|
||||
this.register(PokeBalls)
|
||||
this.register(PropertiesCompletionProvider)
|
||||
this.register(SpawnDetailPresets)
|
||||
|
||||
+25
-15
@@ -21,9 +21,8 @@ import com.cobblemon.mod.common.api.net.serializers.Vec3DataSerializer
|
||||
import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.api.pokeball.catching.CaptureContext
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
import com.cobblemon.mod.common.api.scheduling.Schedulable
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.scheduling.Schedulable
|
||||
import com.cobblemon.mod.common.api.scheduling.ScheduledTask
|
||||
import com.cobblemon.mod.common.api.scheduling.SchedulingTracker
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
@@ -37,17 +36,12 @@ import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.Poseable
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonServerDelegate
|
||||
import com.cobblemon.mod.common.net.messages.client.animation.PlayPoseableAnimationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleCaptureStartPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokeballPacket
|
||||
import com.cobblemon.mod.common.pokeball.PokeBall
|
||||
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
|
||||
import com.cobblemon.mod.common.util.isServerSide
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.util.playSoundServer
|
||||
import com.cobblemon.mod.common.util.sendParticlesServer
|
||||
import com.cobblemon.mod.common.util.setPositionSafely
|
||||
import com.cobblemon.mod.common.util.update
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.entity.EntityDimensions
|
||||
import net.minecraft.entity.EntityPose
|
||||
import net.minecraft.entity.EntityType
|
||||
@@ -70,6 +64,7 @@ import net.minecraft.util.math.MathHelper
|
||||
import net.minecraft.util.math.MathHelper.PI
|
||||
import net.minecraft.util.math.Vec3d
|
||||
import net.minecraft.world.World
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
class EmptyPokeBallEntity : ThrownItemEntity, Poseable, WaterDragModifier, Schedulable {
|
||||
enum class CaptureState {
|
||||
@@ -78,7 +73,8 @@ class EmptyPokeBallEntity : ThrownItemEntity, Poseable, WaterDragModifier, Sched
|
||||
FALL,
|
||||
SHAKE,
|
||||
CAPTURED,
|
||||
CAPTURED_CRITICAL
|
||||
CAPTURED_CRITICAL,
|
||||
BROKEN_FREE
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -135,6 +131,7 @@ class EmptyPokeBallEntity : ThrownItemEntity, Poseable, WaterDragModifier, Sched
|
||||
CaptureState.FALL -> setNoGravity(false)
|
||||
CaptureState.SHAKE -> setNoGravity(true)
|
||||
CaptureState.CAPTURED, CaptureState.CAPTURED_CRITICAL -> {}
|
||||
CaptureState.BROKEN_FREE -> {}
|
||||
}
|
||||
}
|
||||
dataTrackerEmitter.emit(data)
|
||||
@@ -348,25 +345,27 @@ class EmptyPokeBallEntity : ThrownItemEntity, Poseable, WaterDragModifier, Sched
|
||||
|
||||
world.playSoundServer(pos, CobblemonSounds.POKE_BALL_SHAKE, volume = 0.8F)
|
||||
// Emits a shake by changing the value to the opposite of what it currently is. Sends an update to the client basically.
|
||||
// We could replace this with a packet but it feels awfully excessive when we already have 5 bajillion packets.
|
||||
// We could replace this with a packet, but it feels awfully excessive when we already have 5 bajillion packets.
|
||||
dataTracker.update(SHAKE) { !it }
|
||||
}
|
||||
|
||||
private fun breakFree() {
|
||||
val pokemon = capturingPokemon ?: return
|
||||
pokemon.setPosition(pos)
|
||||
pokemon.beamMode = 1
|
||||
pokemon.beamMode = 2
|
||||
pokemon.isInvisible = false
|
||||
|
||||
if (pokemon.battleId == null) {
|
||||
pokemon.pokemon.status?.takeIf { it.status == Statuses.SLEEP }?.let { pokemon.pokemon.status = null }
|
||||
}
|
||||
|
||||
after(seconds = 0.25F) {
|
||||
captureState = CaptureState.BROKEN_FREE
|
||||
world.playSoundServer(pos, CobblemonSounds.POKE_BALL_OPEN, volume = 0.8F)
|
||||
|
||||
after(seconds = 1F) {
|
||||
pokemon.busyLocks.remove(this)
|
||||
captureFuture.complete(false)
|
||||
world.sendParticlesServer(ParticleTypes.CLOUD, pos, 20, Vec3d(0.0, 0.2, 0.0), 0.05)
|
||||
world.playSoundServer(pos, CobblemonSounds.POKE_BALL_OPEN, volume = 0.8F)
|
||||
discard()
|
||||
}
|
||||
}
|
||||
@@ -381,6 +380,17 @@ class EmptyPokeBallEntity : ThrownItemEntity, Poseable, WaterDragModifier, Sched
|
||||
captureState = CaptureState.HIT
|
||||
val mul = if (random.nextBoolean()) 1 else -1
|
||||
world.playSoundServer(pos, CobblemonSounds.POKE_BALL_HIT, volume = 0.4F)
|
||||
|
||||
// Hit Pokémon plays recoil animation
|
||||
val pkt = PlayPoseableAnimationPacket(pokemonEntity.id, setOf("recoil"), emptySet())
|
||||
pkt.sendToPlayersAround(
|
||||
x = pokemonEntity.x,
|
||||
y = pokemonEntity.y,
|
||||
z = pokemonEntity.z,
|
||||
worldKey = pokemonEntity.world.registryKey,
|
||||
distance = 50.0
|
||||
)
|
||||
|
||||
// Bounce backwards away from the hit Pokémon
|
||||
velocity = displace.multiply(-1.0, 0.0, -1.0).normalize().rotateY(mul * PI/3).multiply(0.1, 0.0, 0.1).add(0.0, 1.0 / 3, 0.0)
|
||||
pokemonEntity.phasingTargetId = this.id
|
||||
@@ -389,7 +399,7 @@ class EmptyPokeBallEntity : ThrownItemEntity, Poseable, WaterDragModifier, Sched
|
||||
velocity = Vec3d.ZERO
|
||||
setNoGravity(true)
|
||||
world.playSoundServer(pos, CobblemonSounds.POKE_BALL_CAPTURE_STARTED, volume = 0.6F)
|
||||
pokemonEntity.beamMode = 2
|
||||
pokemonEntity.beamMode = 3
|
||||
}
|
||||
|
||||
after(seconds = 2.2F) {
|
||||
|
||||
@@ -28,7 +28,6 @@ import com.cobblemon.mod.common.api.scheduling.Schedulable
|
||||
import com.cobblemon.mod.common.api.scheduling.SchedulingTracker
|
||||
import com.cobblemon.mod.common.api.storage.InvalidSpeciesException
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes.FIRE
|
||||
import com.cobblemon.mod.common.battles.BagItems
|
||||
import com.cobblemon.mod.common.battles.BattleBuilder
|
||||
import com.cobblemon.mod.common.battles.BattleRegistry
|
||||
@@ -54,12 +53,9 @@ import com.cobblemon.mod.common.pokemon.activestate.InactivePokemonState
|
||||
import com.cobblemon.mod.common.pokemon.activestate.ShoulderedState
|
||||
import com.cobblemon.mod.common.pokemon.ai.FormPokemonBehaviour
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.ItemInteractionEvolution
|
||||
import com.cobblemon.mod.common.pokemon.misc.GimmighoulStashHandler
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
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.control.MoveControl
|
||||
import net.minecraft.entity.ai.goal.EatGrassGoal
|
||||
@@ -106,6 +102,8 @@ import net.minecraft.util.math.Vec3d
|
||||
import net.minecraft.world.EntityView
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.world.event.GameEvent
|
||||
import java.util.*
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
@Suppress("unused")
|
||||
open class PokemonEntity(
|
||||
@@ -332,7 +330,7 @@ open class PokemonEntity(
|
||||
* Prevents fire type Pokémon from taking fire damage.
|
||||
*/
|
||||
override fun isFireImmune(): Boolean {
|
||||
return FIRE in pokemon.types || !behaviour.moving.swim.hurtByLava
|
||||
return pokemon.isFireImmune()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -377,10 +375,10 @@ open class PokemonEntity(
|
||||
if (dataTracker.get(PHASING_TARGET_ID) == -1 && owner != null) {
|
||||
owner.getWorld().playSoundServer(pos, CobblemonSounds.POKE_BALL_RECALL, volume = 0.6F)
|
||||
dataTracker.set(PHASING_TARGET_ID, owner.id)
|
||||
dataTracker.set(BEAM_MODE, 2)
|
||||
dataTracker.set(BEAM_MODE, 3)
|
||||
val state = pokemon.state
|
||||
after(seconds = SEND_OUT_DURATION) {
|
||||
// only recall if the pokemon hasn't been recalled yet for this state
|
||||
// only recall if the Pokémon hasn't been recalled yet for this state
|
||||
if (state == pokemon.state) {
|
||||
pokemon.recall()
|
||||
}
|
||||
@@ -663,6 +661,16 @@ open class PokemonEntity(
|
||||
pokemon.lastFlowerFed = itemStack
|
||||
return ActionResult.success(world.isClient)
|
||||
}
|
||||
} else if(!player.isSneaking && (itemStack.isOf(CobblemonItems.RELIC_COIN)
|
||||
|| itemStack.isOf(CobblemonItems.RELIC_COIN_POUCH)
|
||||
|| itemStack.isOf(CobblemonItems.RELIC_COIN_SACK)
|
||||
|| itemStack.isOf(Items.NETHERITE_SCRAP)
|
||||
|| itemStack.isOf(Items.NETHERITE_INGOT)
|
||||
|| itemStack.isOf(Items.NETHERITE_BLOCK))) {
|
||||
|
||||
if(GimmighoulStashHandler.interactMob(player, hand, pokemon)) {
|
||||
return ActionResult.SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -205,7 +205,7 @@ class PokemonServerDelegate : PokemonSideDelegate {
|
||||
if (owner != null) {
|
||||
entity.world.playSoundServer(owner.pos, CobblemonSounds.POKE_BALL_RECALL, volume = 0.6F)
|
||||
entity.dataTracker.set(PokemonEntity.PHASING_TARGET_ID, owner.id)
|
||||
entity.dataTracker.set(PokemonEntity.BEAM_MODE, 2)
|
||||
entity.dataTracker.set(PokemonEntity.BEAM_MODE, 3)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-7
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.util.getWaterAndLavaIn
|
||||
import com.cobblemon.mod.common.util.math.geometry.toDegrees
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.sqrt
|
||||
import net.minecraft.entity.ai.control.MoveControl
|
||||
@@ -75,9 +76,9 @@ class PokemonMoveControl(val pokemonEntity: PokemonEntity) : MoveControl(pokemon
|
||||
entity.setSidewaysSpeed(sidewaysMovement)
|
||||
state = State.WAIT
|
||||
} else if (state == State.MOVE_TO) {
|
||||
val xDist = targetX - entity.x
|
||||
val zDist = targetZ - entity.z
|
||||
val yDist = targetY - entity.y
|
||||
var xDist = targetX - entity.x
|
||||
var zDist = targetZ - entity.z
|
||||
var yDist = targetY - entity.y
|
||||
|
||||
val horizontalDistanceFromTarget = xDist * xDist + zDist * zDist
|
||||
val closeHorizontally = horizontalDistanceFromTarget < VERY_CLOSE
|
||||
@@ -99,12 +100,13 @@ class PokemonMoveControl(val pokemonEntity: PokemonEntity) : MoveControl(pokemon
|
||||
verticalHandled = true
|
||||
entity.upwardSpeed = 0F
|
||||
entity.movementSpeed = 0F
|
||||
// Refinement is to prevent the entity from spinning around trying to get to a super precise location.
|
||||
val refine: (Double) -> Double = { if (abs(it) < 0.05) 0.0 else it }
|
||||
|
||||
val fullDistance = Vec3d(
|
||||
refine(xDist),
|
||||
if (inFluid || pokemonEntity.getBehaviourFlag(PokemonBehaviourFlag.FLYING)) refine(yDist + 0.05) else 0.0,
|
||||
refine(zDist)
|
||||
xDist,
|
||||
refine(yDist + 0.05), // + 0.05 for dealing with swimming out of water, they otherwise get stuck on the lip
|
||||
zDist
|
||||
)
|
||||
|
||||
val direction = fullDistance.normalize()
|
||||
@@ -112,8 +114,13 @@ class PokemonMoveControl(val pokemonEntity: PokemonEntity) : MoveControl(pokemon
|
||||
val scale = min(adjustedSpeed.toDouble(), fullDistance.length())
|
||||
|
||||
entity.velocity = direction.multiply(scale)
|
||||
|
||||
xDist = fullDistance.x
|
||||
zDist = fullDistance.z
|
||||
yDist = fullDistance.y
|
||||
} else {
|
||||
val forwardSpeed = min(adjustedSpeed, sqrt(horizontalDistanceFromTarget).toFloat())
|
||||
// division is to slow the speed down a bit so they don't overshoot when they get there.
|
||||
val forwardSpeed = min(adjustedSpeed, max(horizontalDistanceFromTarget.toFloat() / 2, 0.15F))
|
||||
entity.movementSpeed = forwardSpeed
|
||||
}
|
||||
|
||||
|
||||
@@ -12,12 +12,14 @@ import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
|
||||
import com.cobblemon.mod.common.pokeball.PokeBall
|
||||
import com.cobblemon.mod.common.util.isServerSide
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.TypedActionResult
|
||||
import net.minecraft.world.World
|
||||
import kotlin.math.cos
|
||||
|
||||
class PokeBallItem(
|
||||
val pokeBall : PokeBall
|
||||
@@ -36,8 +38,12 @@ class PokeBallItem(
|
||||
|
||||
private fun throwPokeBall(world: World, player: ServerPlayerEntity) {
|
||||
val pokeBallEntity = EmptyPokeBallEntity(pokeBall, player.world, player).apply {
|
||||
// setPos(player.x, player.y + player.standingEyeHeight - 0.2, player.z)
|
||||
setVelocity(player, player.pitch - 5, player.yaw, 0.0f, pokeBall.throwPower, 1.0f)
|
||||
val overhandFactor: Float = if (player.pitch < 0) {
|
||||
5f * cos(player.pitch.toRadians())
|
||||
} else {
|
||||
5f
|
||||
}
|
||||
setVelocity(player, player.pitch - overhandFactor, player.yaw, 0.0f, pokeBall.throwPower, 1.0f)
|
||||
setPosition(pos.add(velocity.normalize().multiply(1.0)))
|
||||
owner = player
|
||||
}
|
||||
|
||||
+13
-28
@@ -9,48 +9,33 @@
|
||||
package com.cobblemon.mod.common.net.messages.client.starter
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.config.starter.RenderableStarterCategory
|
||||
import com.cobblemon.mod.common.config.starter.StarterCategory
|
||||
import com.cobblemon.mod.common.api.starter.RenderableStarterCategory
|
||||
import com.cobblemon.mod.common.api.starter.StarterCategory
|
||||
import com.cobblemon.mod.common.pokemon.RenderablePokemon
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
class OpenStarterUIPacket internal constructor(val categories: List<RenderableStarterCategory>) : NetworkPacket<OpenStarterUIPacket> {
|
||||
class OpenStarterUIPacket(val categories: Map<Identifier, RenderableStarterCategory>) : NetworkPacket<OpenStarterUIPacket> {
|
||||
|
||||
override val id = ID
|
||||
|
||||
constructor(categories: Collection<StarterCategory>) : this(categories.map { it.asRenderableStarterCategory() })
|
||||
|
||||
override fun encode(buffer: PacketByteBuf) {
|
||||
buffer.writeInt(categories.size)
|
||||
categories.forEach {
|
||||
buffer.writeString(it.name)
|
||||
buffer.writeString(it.displayName)
|
||||
buffer.writeInt(it.pokemon.size)
|
||||
it.pokemon.forEach { it.saveToBuffer(buffer) }
|
||||
buffer.writeMap(this.categories, PacketByteBuf::writeIdentifier) { categoryBuffer, category ->
|
||||
categoryBuffer.writeText(category.displayName)
|
||||
categoryBuffer.writeCollection(category.pokemon) { pokemonBuffer, renderable ->
|
||||
renderable.saveToBuffer(pokemonBuffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("open_starter")
|
||||
fun decode(buffer: PacketByteBuf): OpenStarterUIPacket {
|
||||
val numCategories = buffer.readInt()
|
||||
val categories = arrayListOf<RenderableStarterCategory>()
|
||||
for (i in 0 until numCategories) {
|
||||
val name = buffer.readString()
|
||||
val displayName = buffer.readString()
|
||||
val numProperties = buffer.readInt()
|
||||
val renderablePokemon = mutableListOf<RenderablePokemon>()
|
||||
repeat(times = numProperties) {
|
||||
renderablePokemon.add(RenderablePokemon.loadFromBuffer(buffer))
|
||||
}
|
||||
categories.add(
|
||||
RenderableStarterCategory(
|
||||
name = name,
|
||||
displayName = displayName,
|
||||
pokemon = renderablePokemon
|
||||
)
|
||||
)
|
||||
val categories = buffer.readMap(PacketByteBuf::readIdentifier) { categoryBuffer ->
|
||||
val displayName = buffer.readText()
|
||||
val renderablePokemon = categoryBuffer.readList(RenderablePokemon::loadFromBuffer)
|
||||
return@readMap RenderableStarterCategory(displayName, renderablePokemon)
|
||||
}
|
||||
return OpenStarterUIPacket(categories)
|
||||
}
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ class SetClientPlayerDataPacket(val promptStarter: Boolean, val starterLocked: B
|
||||
playerData: PlayerData,
|
||||
resetStarterPrompt: Boolean? = null
|
||||
) : this(
|
||||
!playerData.starterPrompted || !Cobblemon.starterConfig.promptStarterOnceOnly,
|
||||
!playerData.starterPrompted || !Cobblemon.config.promptStarterOnceOnly,
|
||||
playerData.starterLocked,
|
||||
playerData.starterSelected,
|
||||
playerData.starterUUID,
|
||||
|
||||
+4
-3
@@ -11,16 +11,17 @@ package com.cobblemon.mod.common.net.messages.server
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
class SelectStarterPacket(val categoryName: String, val selected: Int) : NetworkPacket<SelectStarterPacket> {
|
||||
class SelectStarterPacket(val categoryId: Identifier, val selected: Int) : NetworkPacket<SelectStarterPacket> {
|
||||
override val id = ID
|
||||
override fun encode(buffer: PacketByteBuf) {
|
||||
buffer.writeString(this.categoryName)
|
||||
buffer.writeIdentifier(this.categoryId)
|
||||
buffer.writeInt(this.selected)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("select_starter")
|
||||
fun decode(buffer: PacketByteBuf): SelectStarterPacket = SelectStarterPacket(buffer.readString(), buffer.readInt())
|
||||
fun decode(buffer: PacketByteBuf): SelectStarterPacket = SelectStarterPacket(buffer.readIdentifier(), buffer.readInt())
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -16,6 +16,6 @@ import net.minecraft.server.network.ServerPlayerEntity
|
||||
|
||||
object SelectStarterPacketHandler : ServerNetworkPacketHandler<SelectStarterPacket> {
|
||||
override fun handle(packet: SelectStarterPacket, server: MinecraftServer, player: ServerPlayerEntity) {
|
||||
Cobblemon.starterHandler.chooseStarter(player, packet.categoryName, packet.selected)
|
||||
Cobblemon.starterHandler.chooseStarter(player, packet.categoryId, packet.selected)
|
||||
}
|
||||
}
|
||||
+5
-7
@@ -13,11 +13,10 @@ import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
|
||||
import com.cobblemon.mod.common.pokemon.activestate.ActivePokemonState
|
||||
import com.cobblemon.mod.common.pokemon.activestate.ShoulderedState
|
||||
import com.cobblemon.mod.common.util.toVec3d
|
||||
import com.cobblemon.mod.common.util.traceBlockCollision
|
||||
import com.cobblemon.mod.common.util.raycastSafeSendout
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.math.Vec3d
|
||||
import net.minecraft.world.RaycastContext
|
||||
|
||||
object SendOutPokemonHandler : ServerNetworkPacketHandler<SendOutPokemonPacket> {
|
||||
|
||||
@@ -31,11 +30,10 @@ object SendOutPokemonHandler : ServerNetworkPacketHandler<SendOutPokemonPacket>
|
||||
return
|
||||
}
|
||||
val state = pokemon.state
|
||||
|
||||
if (state is ShoulderedState || state !is ActivePokemonState) {
|
||||
val trace = player.traceBlockCollision(maxDistance = 15F)
|
||||
if (trace != null && !player.world.getBlockState(trace.blockPos.up()).isSolid) {
|
||||
val position = Vec3d(trace.location.x, trace.blockPos.up().toVec3d().y, trace.location.z)
|
||||
val position = player.raycastSafeSendout(pokemon, 12.0, 5.0, RaycastContext.FluidHandling.ANY)
|
||||
|
||||
if (position != null) {
|
||||
pokemon.sendOutWithAnimation(player, player.serverWorld, position)
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -49,6 +49,7 @@ import com.cobblemon.mod.common.api.storage.StoreCoordinates
|
||||
import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore
|
||||
import com.cobblemon.mod.common.api.storage.pc.PCStore
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.api.types.tera.TeraType
|
||||
import com.cobblemon.mod.common.api.types.tera.TeraTypes
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
@@ -72,6 +73,7 @@ import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonPrimitive
|
||||
import com.mojang.serialization.Dynamic
|
||||
import com.mojang.serialization.JsonOps
|
||||
import net.minecraft.block.*
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.item.ItemStack
|
||||
@@ -80,6 +82,7 @@ import net.minecraft.nbt.NbtElement.COMPOUND_TYPE
|
||||
import net.minecraft.nbt.NbtList
|
||||
import net.minecraft.nbt.NbtOps
|
||||
import net.minecraft.nbt.NbtString
|
||||
import net.minecraft.registry.tag.FluidTags
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.server.world.ServerWorld
|
||||
import net.minecraft.text.MutableText
|
||||
@@ -88,9 +91,11 @@ import net.minecraft.text.TextContent
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.InvalidIdentifierException
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.MathHelper.ceil
|
||||
import net.minecraft.util.math.MathHelper.clamp
|
||||
import net.minecraft.util.math.Vec3d
|
||||
import net.minecraft.world.World
|
||||
import java.util.*
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import kotlin.math.absoluteValue
|
||||
@@ -534,6 +539,7 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
val rotatedOffset = Vec3d(shoulderHorizontalOffset, approxShoulderMonHight, 0.0).rotateY(-rotation * (Math.PI.toFloat() / 180f))
|
||||
val currentPosition = player.pos.add(rotatedOffset)
|
||||
|
||||
recall()
|
||||
sendOut(level, currentPosition) {
|
||||
// Play some sound indicating hopping off
|
||||
level.playSoundServer(currentPosition, CobblemonSounds.PC_DROP, volume = 0.6F)
|
||||
@@ -614,6 +620,52 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
}
|
||||
}
|
||||
|
||||
fun isFireImmune(): Boolean {
|
||||
return ElementalTypes.FIRE in types || !form.behaviour.moving.swim.hurtByLava
|
||||
}
|
||||
|
||||
fun isPositionSafe(world: World, pos: Vec3d): Boolean {
|
||||
return isPositionSafe(world, pos.toBlockPos())
|
||||
}
|
||||
|
||||
fun isPositionSafe(world: World, pos1: BlockPos): Boolean {
|
||||
// To make sure a location is safe, both the block the Pokemon is standing ON,
|
||||
// and the block it's standing IN need to be safe. pos2 represents the other position in that set.
|
||||
val pos2: BlockPos = if (world.getBlockState(pos1).isSolid) {
|
||||
pos1.up()
|
||||
} else {
|
||||
pos1.down()
|
||||
}
|
||||
|
||||
val positions = arrayOf(pos1, pos2)
|
||||
var isSafe = true
|
||||
|
||||
for (pos in positions) {
|
||||
if (isSafe) {
|
||||
val block = world.getBlockState(pos).block
|
||||
|
||||
if (block is SweetBerryBushBlock ||
|
||||
block is CactusBlock ||
|
||||
block is WitherRoseBlock
|
||||
) {
|
||||
isSafe = false
|
||||
}
|
||||
|
||||
if (!this.isFireImmune()) {
|
||||
if (block is FireBlock ||
|
||||
block is MagmaBlock ||
|
||||
block is CampfireBlock ||
|
||||
world.getBlockState(pos).fluidState.isIn(FluidTags.LAVA)
|
||||
) {
|
||||
isSafe = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return isSafe
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method that checks if this Pokémon species or form data contains the [CobblemonPokemonLabels.LEGENDARY] label.
|
||||
* This is used in Pokémon officially considered legendary.
|
||||
|
||||
+34
-13
@@ -11,10 +11,13 @@ package com.cobblemon.mod.common.pokemon.misc
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.events.pokemon.HeldItemEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.interaction.HeldItemUpdatedEvent
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.IntSpeciesFeature
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.item.Item
|
||||
import net.minecraft.item.Items
|
||||
import net.minecraft.sound.SoundCategory
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.Hand
|
||||
|
||||
/**
|
||||
* Handles logic relating to Gimmighoul's Coin Stash and Scrap Stash bars.
|
||||
@@ -30,13 +33,30 @@ object GimmighoulStashHandler {
|
||||
val SCRAP_VALUE = 1
|
||||
val INGOT_VALUE = SCRAP_VALUE * 4
|
||||
val BLOCK_VALUE = INGOT_VALUE * 9
|
||||
fun interactMob(player: PlayerEntity, hand: Hand, pokemon:Pokemon) : Boolean {
|
||||
val itemStack = player.getStackInHand(hand)
|
||||
var success = false
|
||||
if(player is ServerPlayerEntity && pokemon.getOwnerPlayer() == player) {
|
||||
success = handleItem(pokemon, itemStack.item)
|
||||
if(success) {
|
||||
itemStack.decrement(1)
|
||||
}
|
||||
}
|
||||
return success
|
||||
}
|
||||
|
||||
fun giveHeldItem(event: HeldItemEvent.Post) {
|
||||
val goldHoard = event.pokemon.getFeature<IntSpeciesFeature>("gimmighoul_coins")
|
||||
val netheriteHoard = event.pokemon.getFeature<IntSpeciesFeature>("gimmighoul_netherite")
|
||||
|
||||
val pokemon = event.pokemon
|
||||
val item = event.received.item
|
||||
if(handleItem(pokemon, item)) {
|
||||
pokemon.removeHeldItem()
|
||||
}
|
||||
}
|
||||
fun handleItem(pokemon: Pokemon, item: Item) : Boolean {
|
||||
val goldHoard = pokemon.getFeature<IntSpeciesFeature>("gimmighoul_coins")
|
||||
val netheriteHoard = pokemon.getFeature<IntSpeciesFeature>("gimmighoul_netherite")
|
||||
if (goldHoard != null && goldHoard.value < 999) {
|
||||
val increase = when (event.received.item) {
|
||||
val increase = when (item) {
|
||||
CobblemonItems.RELIC_COIN -> COIN_VALUE
|
||||
CobblemonItems.RELIC_COIN_POUCH -> POUCH_VALUE
|
||||
CobblemonItems.RELIC_COIN_SACK -> SACK_VALUE
|
||||
@@ -46,14 +66,14 @@ object GimmighoulStashHandler {
|
||||
if (increase != 0) {
|
||||
goldHoard.value += increase
|
||||
if (goldHoard.value > 999) goldHoard.value = 999
|
||||
if (event.pokemon.entity != null) event.pokemon.entity!!.playSound(CobblemonSounds.GIMMIGHOUL_GIVE_ITEM_SMALL, 1f, 1f)
|
||||
event.pokemon.markFeatureDirty(goldHoard)
|
||||
event.pokemon.removeHeldItem()
|
||||
if (pokemon.entity != null) pokemon.entity!!.playSound(CobblemonSounds.GIMMIGHOUL_GIVE_ITEM_SMALL, 1f, 1f)
|
||||
pokemon.markFeatureDirty(goldHoard)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if (netheriteHoard != null && netheriteHoard.value < 256) {
|
||||
val increase = when (event.received.item) {
|
||||
val increase = when (item) {
|
||||
Items.NETHERITE_SCRAP -> SCRAP_VALUE
|
||||
Items.NETHERITE_INGOT -> INGOT_VALUE
|
||||
Items.NETHERITE_BLOCK -> BLOCK_VALUE
|
||||
@@ -63,11 +83,12 @@ object GimmighoulStashHandler {
|
||||
if (increase != 0) {
|
||||
netheriteHoard.value += increase
|
||||
if (netheriteHoard.value > 256) netheriteHoard.value = 256
|
||||
if (event.pokemon.entity != null) event.pokemon.entity!!.playSound(CobblemonSounds.GIMMIGHOUL_GIVE_ITEM_SMALL, 1f, 1f)
|
||||
event.pokemon.markFeatureDirty(netheriteHoard)
|
||||
event.pokemon.removeHeldItem()
|
||||
if (pokemon.entity != null) pokemon.entity!!.playSound(CobblemonSounds.GIMMIGHOUL_GIVE_ITEM_SMALL, 1f, 1f)
|
||||
pokemon.markFeatureDirty(netheriteHoard)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,73 +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.starter
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.advancement.CobblemonCriteria
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.starter.StarterChosenEvent
|
||||
import com.cobblemon.mod.common.api.starter.StarterHandler
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.net.messages.client.starter.OpenStarterUIPacket
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
|
||||
open class CobblemonStarterHandler : StarterHandler {
|
||||
|
||||
override fun getStarterList(player: ServerPlayerEntity) = Cobblemon.starterConfig.starters
|
||||
|
||||
override fun handleJoin(player: ServerPlayerEntity) {}
|
||||
|
||||
override fun requestStarterChoice(player: ServerPlayerEntity) {
|
||||
val playerData = Cobblemon.playerData.get(player)
|
||||
if (playerData.starterSelected) {
|
||||
playerData.sendToPlayer(player)
|
||||
player.sendMessage(lang("ui.starter.alreadyselected").red(), true)
|
||||
} else if (playerData.starterLocked) {
|
||||
player.sendMessage(lang("ui.starter.cannotchoose").red(), true)
|
||||
} else {
|
||||
OpenStarterUIPacket(getStarterList(player)).sendToPlayer(player)
|
||||
playerData.starterPrompted = true
|
||||
Cobblemon.playerData.saveSingle(playerData)
|
||||
}
|
||||
}
|
||||
|
||||
override fun chooseStarter(player: ServerPlayerEntity, categoryName: String, index: Int) {
|
||||
val playerData = Cobblemon.playerData.get(player)
|
||||
if (playerData.starterSelected) {
|
||||
return player.sendMessage(lang("ui.starter.alreadyselected").red(), true)
|
||||
} else if (playerData.starterLocked) {
|
||||
return player.sendMessage(lang("ui.starter.cannotchoose").red(), true)
|
||||
}
|
||||
|
||||
val category = getStarterList(player).find { it.name == categoryName } ?: return
|
||||
|
||||
if (index > category.pokemon.size) {
|
||||
return
|
||||
}
|
||||
|
||||
val properties = category.pokemon[index]
|
||||
val pokemon = properties.create()
|
||||
|
||||
CobblemonEvents.STARTER_CHOSEN.postThen(StarterChosenEvent(player, properties, pokemon)) {
|
||||
Cobblemon.storage.getParty(player).add(
|
||||
it.pokemon.also {
|
||||
playerData.starterSelected = true
|
||||
playerData.starterUUID = it.uuid
|
||||
if (player.world.gameRules.getBoolean(CobblemonGameRules.SHINY_STARTERS)) { pokemon.shiny = true }
|
||||
}
|
||||
)
|
||||
CobblemonCriteria.PICK_STARTER.trigger(player, pokemon)
|
||||
Cobblemon.playerData.saveSingle(playerData)
|
||||
playerData.sendToPlayer(player)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.starter
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.advancement.CobblemonCriteria
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.starter.StarterChosenEvent
|
||||
import com.cobblemon.mod.common.api.starter.RenderableStarterCategory
|
||||
import com.cobblemon.mod.common.api.starter.StarterCategory
|
||||
import com.cobblemon.mod.common.api.starter.StarterHandler
|
||||
import com.cobblemon.mod.common.api.starter.StarterRegistry
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.net.messages.client.starter.OpenStarterUIPacket
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.Identifier
|
||||
|
||||
open class CobblemonStarterHandler : StarterHandler {
|
||||
|
||||
override fun getStarters(player: ServerPlayerEntity): Map<Identifier, StarterCategory> = StarterRegistry.all()
|
||||
|
||||
// No OP the starters are sent out when the open UI packet is sent out instead
|
||||
override fun handleJoin(player: ServerPlayerEntity) {}
|
||||
|
||||
override fun requestStarterChoice(player: ServerPlayerEntity) {
|
||||
if (!this.isAbleToSelect(player)) {
|
||||
return
|
||||
}
|
||||
val playerData = Cobblemon.playerData.get(player)
|
||||
val renderable = this.getStarters(player).entries.associate { (id, category) ->
|
||||
val renderable = category.pokemon.map {
|
||||
// Let the actual Pokémon be created and apply the shiny accordingly
|
||||
// This won't be accurate with random but I mean what else do you want me to do
|
||||
val pokemon = it.create()
|
||||
// While they can still be shiny a random shiny from the #create doesn't mean the actual starter will be shiny
|
||||
// This tries to be realistic
|
||||
pokemon.shiny = player.world.gameRules.getBoolean(CobblemonGameRules.SHINY_STARTERS)
|
||||
pokemon.asRenderablePokemon()
|
||||
}
|
||||
id to RenderableStarterCategory(category.displayName, renderable)
|
||||
}
|
||||
OpenStarterUIPacket(renderable).sendToPlayer(player)
|
||||
playerData.starterPrompted = true
|
||||
Cobblemon.playerData.saveSingle(playerData)
|
||||
}
|
||||
|
||||
override fun chooseStarter(player: ServerPlayerEntity, categoryId: Identifier, index: Int) {
|
||||
if (!this.isAbleToSelect(player)) {
|
||||
return
|
||||
}
|
||||
val category = this.getStarters(player)[categoryId] ?: return
|
||||
val properties = category.pokemon.getOrNull(index) ?: return
|
||||
val pokemon = properties.create()
|
||||
val playerData = Cobblemon.playerData.get(player)
|
||||
CobblemonEvents.STARTER_CHOSEN.postThen(StarterChosenEvent(player, properties, pokemon)) { event ->
|
||||
Cobblemon.storage.getParty(player).add(
|
||||
event.pokemon.also {
|
||||
playerData.starterSelected = true
|
||||
playerData.starterUUID = it.uuid
|
||||
if (player.world.gameRules.getBoolean(CobblemonGameRules.SHINY_STARTERS)) { pokemon.shiny = true }
|
||||
}
|
||||
)
|
||||
CobblemonCriteria.PICK_STARTER.trigger(player, pokemon)
|
||||
Cobblemon.playerData.saveSingle(playerData)
|
||||
playerData.sendToPlayer(player)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the [player] can select a starter.
|
||||
* If not gives them an appropriate feedback message.
|
||||
*
|
||||
* @param player The [ServerPlayerEntity] being tested.
|
||||
* @return If the [player] can pick a starter.
|
||||
*/
|
||||
private fun isAbleToSelect(player: ServerPlayerEntity): Boolean {
|
||||
val playerData = Cobblemon.playerData.get(player)
|
||||
if (playerData.starterSelected) {
|
||||
player.sendMessage(lang("ui.starter.alreadyselected").red(), true)
|
||||
return false
|
||||
} else if (playerData.starterLocked) {
|
||||
player.sendMessage(lang("ui.starter.cannotchoose").red(), true)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,11 +13,32 @@ import net.minecraft.entity.data.DataTracker
|
||||
import net.minecraft.entity.data.TrackedData
|
||||
import net.minecraft.util.function.BooleanBiFunction
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Box
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.util.math.Vec3d
|
||||
import net.minecraft.util.shape.VoxelShapes
|
||||
|
||||
fun Entity.setPositionSafely(pos: Vec3d): Boolean {
|
||||
// TODO: Rework this function. Best way to do it would be to define a vertical and horizontal min/max shift based on the Pokemon's hitbox.
|
||||
// Then loop through horizontal/vertical shifts, and detect collisions in three categories: suffocation, damaging blocks, and general collision
|
||||
// The closest position with the least severe collision types will be selected to move the Pokemon to
|
||||
// The throw could be cancelled if there are no viable locations without severe problems
|
||||
|
||||
// Optional: use getBlockCollisions iterator and VoxelShapes.combineAndSimplify to create a single cube to represent collision area
|
||||
// Use that cube to "push" the Pokemon out of the wall at an angle
|
||||
// Note: may not work well with L shape wall collisions
|
||||
// val collisions = world.getBlockCollisions(this, box).iterator()
|
||||
// if (collisions.hasNext()) {
|
||||
// var collisionShape = collisions.next()
|
||||
// while (collisions.hasNext()) {
|
||||
// collisionShape = VoxelShapes.union(collisionShape, collisions.next())
|
||||
// println(collisionShape)
|
||||
// }
|
||||
// } else {
|
||||
// setPosition(pos)
|
||||
// return true
|
||||
// }
|
||||
|
||||
var result = pos
|
||||
val eyes = pos.withAxis(Direction.Axis.Y, pos.y + this.standingEyeHeight)
|
||||
|
||||
@@ -29,27 +50,6 @@ fun Entity.setPositionSafely(pos: Vec3d): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
val yChanges = listOf(1.0, -1.0, 2.0, -2.0)
|
||||
var previousChange = 0.0
|
||||
for (yChange in yChanges) {
|
||||
box = box.offset(0.0, yChange - previousChange, 0.0)
|
||||
val it = world.getBlockCollisions(this, box).iterator()
|
||||
previousChange = yChange
|
||||
if (it.hasNext()) {
|
||||
continue
|
||||
} else {
|
||||
val roundedY = (pos.y + yChange).toInt()
|
||||
box = box.offset(0.0, roundedY - pos.y, 0.0)
|
||||
// If the rounded position actually collides again, then don't round at all.
|
||||
if (world.getBlockCollisions(this, box).iterator().hasNext()) {
|
||||
setPosition(pos.add(0.0, yChange, 0.0))
|
||||
return true
|
||||
}
|
||||
setPosition(Vec3d(pos.x, roundedY.toDouble(), pos.z))
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
for (target in BlockPos.stream(box)) {
|
||||
val blockState = this.world.getBlockState(target)
|
||||
val collides = !blockState.isAir &&
|
||||
@@ -73,13 +73,13 @@ fun Entity.setPositionSafely(pos: Vec3d): Boolean {
|
||||
result = result.add(Vec3d(0.0, 0.0, 1 + (conflict.z - box.minZ + (1.0 / 8.0))))
|
||||
}
|
||||
Direction.SOUTH -> {
|
||||
result = result.add(Vec3d(0.0, 0.0, -1 * (1 - (conflict.z - box.minZ) + (1.0 / 8.0))))
|
||||
result = result.add(Vec3d(0.0, 0.0, (conflict.z - box.maxZ) - (1.0 / 8.0)))
|
||||
}
|
||||
Direction.WEST -> {
|
||||
result = result.add(Vec3d(1 + (conflict.x - box.minX + (1.0 / 8.0)), 0.0, 0.0))
|
||||
}
|
||||
Direction.EAST -> {
|
||||
result = result.add(Vec3d(-1 * (1 - (conflict.x - box.minX) + (1.0 / 8.0)), 0.0, 0.0))
|
||||
result = result.add(Vec3d((conflict.x - box.maxX) - (1.0 / 8.0), 0.0, 0.0))
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
@@ -89,12 +89,90 @@ fun Entity.setPositionSafely(pos: Vec3d): Boolean {
|
||||
}
|
||||
}
|
||||
|
||||
box = boundingBox.offset(result)
|
||||
if (!world.getBlockCollisions(this, box).iterator().hasNext()) {
|
||||
this.setPosition(result)
|
||||
return true
|
||||
} else {
|
||||
val yChanges = listOf(1.0, -1.0, 2.0, -2.0)
|
||||
var previousChange = 0.0
|
||||
|
||||
// If the Pokemon still collides with blocks after horizontal shifting, try vertical shifting from the shifted position
|
||||
for (yChange in yChanges) {
|
||||
box = box.offset(0.0, yChange - previousChange, 0.0)
|
||||
previousChange = yChange
|
||||
if (world.getBlockCollisions(this, box).iterator().hasNext()) {
|
||||
continue
|
||||
} else {
|
||||
val roundedY = (result.y + yChange).toInt()
|
||||
box = box.offset(0.0, roundedY - result.y, 0.0)
|
||||
// If the rounded position actually collides again, then don't round at all.
|
||||
if (world.getBlockCollisions(this, box).iterator().hasNext()) {
|
||||
result = result.add(0.0, yChange, 0.0)
|
||||
this.setPosition(result)
|
||||
return true
|
||||
} else {
|
||||
result = Vec3d(result.x, roundedY.toDouble(), result.z)
|
||||
this.setPosition(result)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If vertical shifting from the new position still collides, try vertical shifting from the original pos
|
||||
previousChange = 0.0
|
||||
box = boundingBox.offset(pos)
|
||||
for (yChange in yChanges) {
|
||||
box = box.offset(0.0, yChange - previousChange, 0.0)
|
||||
previousChange = yChange
|
||||
if (world.getBlockCollisions(this, box).iterator().hasNext()) {
|
||||
continue
|
||||
} else {
|
||||
val roundedY = (result.y + yChange).toInt()
|
||||
box = box.offset(0.0, roundedY - result.y, 0.0)
|
||||
// If the rounded position actually collides again, then don't round at all.
|
||||
if (world.getBlockCollisions(this, box).iterator().hasNext()) {
|
||||
result = result.add(0.0, yChange, 0.0)
|
||||
this.setPosition(result)
|
||||
return true
|
||||
} else {
|
||||
result = Vec3d(result.x, roundedY.toDouble(), result.z)
|
||||
this.setPosition(result)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (conflicts.size >= 3) {
|
||||
this.setPosition(pos)
|
||||
}
|
||||
|
||||
this.setPosition(result)
|
||||
return true
|
||||
// This final check guarantees that the sendout will return to the original position if the Pokemon will suffocate in the new one
|
||||
// This will only happen if the horizontal shift moved the Pokemon into a suffocating position, and there was no valid vertical shift
|
||||
val resultEyes = result.withAxis(Direction.Axis.Y, result.y + this.standingEyeHeight)
|
||||
val resultEyeBox = Box.of(resultEyes, width.toDouble(), 1.0E-6, width.toDouble())
|
||||
var collides = false
|
||||
|
||||
for (target in BlockPos.stream(resultEyeBox)) {
|
||||
val blockState = this.world.getBlockState(target)
|
||||
collides = !blockState.isAir &&
|
||||
blockState.shouldSuffocate(this.world, target) &&
|
||||
VoxelShapes.matchesAnywhere(
|
||||
blockState.getCollisionShape(this.world, target)
|
||||
.offset(target.x.toDouble(), target.y.toDouble(), target.z.toDouble()),
|
||||
VoxelShapes.cuboid(box),
|
||||
BooleanBiFunction.AND
|
||||
)
|
||||
if (collides) break
|
||||
}
|
||||
if (collides) {
|
||||
this.setPosition(pos)
|
||||
return true
|
||||
} else {
|
||||
this.setPosition(result)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
fun Entity.distanceTo(pos: BlockPos): Double {
|
||||
|
||||
@@ -19,7 +19,7 @@ import com.cobblemon.mod.common.api.reactive.Observable.Companion.filter
|
||||
import com.cobblemon.mod.common.api.reactive.Observable.Companion.takeFirst
|
||||
import com.cobblemon.mod.common.battles.BattleRegistry
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import java.util.UUID
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
@@ -30,10 +30,11 @@ import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.sound.SoundCategory
|
||||
import net.minecraft.sound.SoundEvents
|
||||
import net.minecraft.util.Identifier
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.Box
|
||||
import net.minecraft.util.math.Direction
|
||||
import net.minecraft.util.math.Vec3d
|
||||
import net.minecraft.util.hit.BlockHitResult
|
||||
import net.minecraft.util.math.*
|
||||
import net.minecraft.world.RaycastContext
|
||||
import java.util.*
|
||||
import kotlin.math.min
|
||||
|
||||
// Stuff like getting their party
|
||||
fun ServerPlayerEntity.party() = Cobblemon.storage.getParty(this)
|
||||
@@ -251,6 +252,91 @@ fun findDirectionForIntercept(p0: Vec3d, p1: Vec3d, blockPos: BlockPos): Directi
|
||||
return minDirection
|
||||
}
|
||||
|
||||
fun ServerPlayerEntity.raycast(maxDistance: Float, fluidHandling: RaycastContext.FluidHandling?): BlockHitResult {
|
||||
val f = pitch
|
||||
val g = yaw
|
||||
val vec3d = eyePos
|
||||
val h = MathHelper.cos(-g * 0.017453292f - 3.1415927f)
|
||||
val i = MathHelper.sin(-g * 0.017453292f - 3.1415927f)
|
||||
val j = -MathHelper.cos(-f * 0.017453292f)
|
||||
val k = MathHelper.sin(-f * 0.017453292f)
|
||||
val l = i * j
|
||||
val n = h * j
|
||||
val vec3d2 = vec3d.add(l.toDouble() * maxDistance, k.toDouble() * maxDistance, n.toDouble() * maxDistance)
|
||||
return world.raycast(RaycastContext(vec3d, vec3d2, RaycastContext.ShapeType.OUTLINE, fluidHandling, this))
|
||||
}
|
||||
|
||||
fun ServerPlayerEntity.raycastSafeSendout(pokemon: Pokemon, maxDistance: Double, dropHeight: Double, fluidHandling: RaycastContext.FluidHandling?): Vec3d? {
|
||||
// Crazy math stuff, don't worry about it
|
||||
val f = pitch
|
||||
val g = yaw
|
||||
val vec3d = eyePos
|
||||
val h = MathHelper.cos(-g * 0.017453292f - 3.1415927f)
|
||||
val i = MathHelper.sin(-g * 0.017453292f - 3.1415927f)
|
||||
val j = -MathHelper.cos(-f * 0.017453292f)
|
||||
val k = MathHelper.sin(-f * 0.017453292f)
|
||||
val l = i * j
|
||||
val n = h * j
|
||||
val vec3d2 = vec3d.add(l.toDouble() * maxDistance, k.toDouble() * maxDistance, n.toDouble() * maxDistance)
|
||||
val result = world.raycast(RaycastContext(vec3d, vec3d2, RaycastContext.ShapeType.OUTLINE, fluidHandling, this))
|
||||
|
||||
|
||||
if (world.getBlockState(result.blockPos).isAir) {
|
||||
// If the trace returns air, the player isn't aiming at any blocks within range
|
||||
var traceDown: TraceResult?
|
||||
val minDrop = min(2.5, maxDistance)
|
||||
val stepDistance = 0.05
|
||||
var step = minDrop
|
||||
var stepDrop = minDrop
|
||||
var stepPos: Vec3d
|
||||
var traceHeight: Double
|
||||
var smallestHeight = dropHeight
|
||||
var fallLoc: TraceResult? = null
|
||||
|
||||
// Try to find a valid block below the player's aim instead
|
||||
while (step <= maxDistance) {
|
||||
stepPos = vec3d.add(l.toDouble() * step, k.toDouble() * step, n.toDouble() * step)
|
||||
if (minDrop != maxDistance) {
|
||||
stepDrop = ((step - minDrop) / (maxDistance - minDrop)) * dropHeight
|
||||
}
|
||||
traceDown = stepPos.traceDownwards(this.world, maxDistance = stepDrop.toFloat())
|
||||
if (traceDown != null && pokemon.isPositionSafe(world, traceDown.blockPos)) {
|
||||
traceHeight = (stepPos.y - traceDown.location.y)
|
||||
if (traceHeight < smallestHeight) {
|
||||
smallestHeight = traceHeight
|
||||
fallLoc = traceDown
|
||||
}
|
||||
}
|
||||
|
||||
step += stepDistance
|
||||
}
|
||||
|
||||
// If a valid block was found below the player's aim, return the location directly above it
|
||||
return fallLoc?.blockPos?.up()?.toCenterPos()
|
||||
} else if (result.side != Direction.UP) {
|
||||
// If the player targets the side or bottom of a block, try to find a valid spot in front of / below that block
|
||||
val offset: Double = if (result.side == Direction.DOWN) {
|
||||
0.125 + pokemon.form.hitbox.height*pokemon.form.baseScale*0.5
|
||||
} else {
|
||||
0.125 + pokemon.form.hitbox.width*pokemon.form.baseScale*0.5
|
||||
}
|
||||
|
||||
val posOffset = result.pos.offset(result.side, offset)
|
||||
|
||||
val traceDown = posOffset.traceDownwards(this.world, maxDistance = dropHeight.toFloat())
|
||||
|
||||
return if (traceDown == null || !pokemon.isPositionSafe(world, traceDown.blockPos)) {
|
||||
null
|
||||
} else {
|
||||
return Vec3d(traceDown.location.x, traceDown.blockPos.up().toVec3d().y, traceDown.location.z)
|
||||
}
|
||||
} else if (!this.world.getBlockState(result.blockPos.up()).isSolid && pokemon.isPositionSafe(world, result.blockPos)) {
|
||||
// If the player is targeting the top of a block, and the block above it isn't solid, it will spawn on that block
|
||||
return Vec3d(result.pos.x, result.blockPos.up().toVec3d().y, result.pos.z)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun PlayerInventory.usableItems() = offHand + main
|
||||
|
||||
/**
|
||||
|
||||
@@ -124,3 +124,41 @@ val World.itemRegistry: Registry<Item>
|
||||
get() = registryManager.get(RegistryKeys.ITEM)
|
||||
val World.biomeRegistry: Registry<Biome>
|
||||
get() = registryManager.get(RegistryKeys.BIOME)
|
||||
|
||||
|
||||
fun Vec3d.traceDownwards(
|
||||
world: World,
|
||||
maxDistance: Float = 10F,
|
||||
stepDistance: Float = 0.5F,
|
||||
): TraceResult? {
|
||||
var step = stepDistance
|
||||
val startPos = Vec3d(x, y, z)
|
||||
val direction = Vec3d(0.0, -1.0, 0.0)
|
||||
|
||||
var lastBlockPos = startPos.toBlockPos()
|
||||
|
||||
while (step <= maxDistance) {
|
||||
val location = startPos.add(direction.multiply(step.toDouble()))
|
||||
step += stepDistance
|
||||
|
||||
val blockPos = location.toBlockPos()
|
||||
|
||||
if (blockPos == lastBlockPos) {
|
||||
continue
|
||||
} else {
|
||||
lastBlockPos = blockPos
|
||||
}
|
||||
|
||||
val block = world.getBlockState(blockPos)
|
||||
if (!block.isAir) {
|
||||
val dir = findDirectionForIntercept(startPos, location, blockPos)
|
||||
return TraceResult(
|
||||
location = location,
|
||||
blockPos = blockPos,
|
||||
direction = dir
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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.util.adapters
|
||||
|
||||
import com.google.gson.*
|
||||
import net.minecraft.text.Text
|
||||
import java.lang.reflect.Type
|
||||
|
||||
object PlainJsonTextAdapter : JsonDeserializer<Text>, JsonSerializer<Text> {
|
||||
override fun deserialize(jElement: JsonElement, type: Type, context: JsonDeserializationContext): Text {
|
||||
return Text.Serializer.fromJson(jElement) ?: throw IllegalArgumentException("Cannot resolve null text")
|
||||
}
|
||||
|
||||
override fun serialize(text: Text, type: Type, context: JsonSerializationContext): JsonElement = JsonPrimitive(Text.Serializer.toJson(text))
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"maxScale": 0.8,
|
||||
"maxScale": 0.55,
|
||||
"yTranslation": 0,
|
||||
"yGrowthPoint": 0.5625,
|
||||
"animations": [
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"maxScale": 0.75,
|
||||
"maxScale": 0.85,
|
||||
"yTranslation": 0.1,
|
||||
"yGrowthPoint": 0.3125,
|
||||
|
||||
|
||||
@@ -884,7 +884,7 @@
|
||||
"advancements.cobblemon.obtain_leek.description": "Obtain a Medicinal Leek, a wild crop that grows in freshwater",
|
||||
"advancements.cobblemon.medicinal_brew": "Local Apothecary",
|
||||
"advancements.cobblemon.medicinal_brew.description": "Brew a Medicinal Leek to create the basis for your healing needs",
|
||||
"advancements.cobblemon.brew_potion": "You cannot handle my Potions",
|
||||
"advancements.cobblemon.brew_potion": "You Cannot Handle My Potions",
|
||||
"advancements.cobblemon.brew_potion.description": "Brew an Oran Berry into Medicinal Brew to create a Potion",
|
||||
"advancements.cobblemon.brew_full_restore": "Champion's Choice",
|
||||
"advancements.cobblemon.brew_full_restore.description": "Follow the brewing tree and create a Full Restore with a Lum Berry and Max Potion",
|
||||
@@ -934,12 +934,12 @@
|
||||
"advancements.cobblemon.obtain_fossil.description": "Discover a fossil buried in ancient ruins",
|
||||
"advancements.cobblemon.evolve_gholdengo_netherite": "Cover thee in Debris",
|
||||
"advancements.cobblemon.evolve_gholdengo_netherite.description": "Evolve a Gimmighoul into a fully netherite-coated Gholdengo",
|
||||
"advancements.cobblemon.resurrect_pokemon": "Life finds a way",
|
||||
"advancements.cobblemon.resurrect_pokemon": "Life Finds a Way",
|
||||
"advancements.cobblemon.resurrect_pokemon.description": "Obtain a Fossil Pokémon from a Resurrection Machine",
|
||||
"advancements.cobblemon.obtain_tumblestone": "The Rolling Stone",
|
||||
"advancements.cobblemon.obtain_tumblestone.description": "Safely extract a Tumblestone from suspicious sand or gravel",
|
||||
"advancements.cobblemon.grow_tumblestone": "Heat from stone, stone from heat",
|
||||
"advancements.cobblemon.grow_tumblestone.description": "Place a Tumblestone near Lava or Magma, allowing the Tumblestone to grow slowly over time",
|
||||
"advancements.cobblemon.grow_tumblestone": "Tumbling Down",
|
||||
"advancements.cobblemon.grow_tumblestone.description": "Place a Tumblestone near Lava or Magma to grow it over time",
|
||||
"advancements.cobblemon.craft_ancient_balls": "A true Antiquarian",
|
||||
"advancements.cobblemon.craft_ancient_balls.description": "Utilize Tumblestones to craft all fifteen Ancient Balls",
|
||||
|
||||
@@ -1534,6 +1534,7 @@
|
||||
|
||||
"gamerule.doPokemonSpawning": "Spawn Pokémon",
|
||||
"gamerule.doShinyStarters": "Starters will be shiny",
|
||||
"gamerule.doPokemonLoot": "Drop Pokémon Loot",
|
||||
"cobblemon.command.checkspawns.invalid-bucket": "Invalid Spawn Bucket",
|
||||
"cobblemon.command.checkspawns.spawns": "Spawns",
|
||||
"cobblemon.command.checkspawns.nothing": "Nothing can spawn here right now.",
|
||||
|
||||
@@ -38,7 +38,13 @@
|
||||
"predicate": {
|
||||
"custom_model_data": 6
|
||||
},
|
||||
"model": "cobblemon:item/cobblemon"
|
||||
"model": "cobblemon:item/shiny_marker"
|
||||
},
|
||||
{
|
||||
"predicate": {
|
||||
"custom_model_data": 7
|
||||
},
|
||||
"model": "cobblemon:item/link_cable"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "cobblemon:item/advancements/shiny_icon"
|
||||
}
|
||||
}
|
||||
@@ -104,49 +104,54 @@
|
||||
"berry.eat": {
|
||||
"sounds": [ "cobblemon:berry_eat" ]
|
||||
},
|
||||
"fossilmachine.activate": {
|
||||
"fossil_machine.activate": {
|
||||
"subtitle": "cobblemon.subtitle.fossilmachine.activate",
|
||||
"sounds": [ "cobblemon:fossilmachine/activate" ]
|
||||
"sounds": [ { "name": "cobblemon:block/fossil_machine/fossil_machine_activate", "volume": 0.8 } ]
|
||||
},
|
||||
"fossilmachine.active_loop": {
|
||||
"fossil_machine.active_loop": {
|
||||
"subtitle": "cobblemon.subtitle.fossilmachine.active_loop",
|
||||
"sounds": [ "cobblemon:fossilmachine/active_loop" ]
|
||||
"sounds": [ { "name": "cobblemon:block/fossil_machine/fossil_machine_active_loop", "volume": 0.6 } ]
|
||||
},
|
||||
"fossilmachine.assemble": {
|
||||
"fossil_machine.assemble": {
|
||||
"subtitle": "cobblemon.subtitle.fossilmachine.assemble",
|
||||
"sounds": [ "cobblemon:fossilmachine/assemble" ]
|
||||
"sounds": [ { "name": "cobblemon:block/fossil_machine/fossil_machine_assemble", "volume": 0.3 } ]
|
||||
},
|
||||
"fossilmachine.dna_full": {
|
||||
"fossil_machine.dna_full": {
|
||||
"subtitle": "cobblemon.subtitle.fossilmachine.dna_full",
|
||||
"sounds": [ "cobblemon:fossilmachine/dna_full" ]
|
||||
"sounds": [ "cobblemon:block/fossil_machine/fossil_machine_dna_full" ]
|
||||
},
|
||||
"fossilmachine.finished": {
|
||||
"fossil_machine.finished": {
|
||||
"subtitle": "cobblemon.subtitle.fossilmachine.finished",
|
||||
"sounds": [ "cobblemon:fossilmachine/finished" ]
|
||||
"sounds": [ "cobblemon:block/fossil_machine/fossil_machine_finished" ]
|
||||
},
|
||||
"fossilmachine.insert_dna": {
|
||||
"fossil_machine.insert_dna": {
|
||||
"subtitle": "cobblemon.subtitle.fossilmachine.insert_dna",
|
||||
"sounds": [ "cobblemon:fossilmachine/insert_dna" ]
|
||||
"sounds": [ "cobblemon:block/fossil_machine/fossil_machine_insert_dna" ]
|
||||
},
|
||||
"fossilmachine.insert_dna_small": {
|
||||
"fossil_machine.insert_dna_small": {
|
||||
"subtitle": "cobblemon.subtitle.fossilmachine.insert_dna_small",
|
||||
"sounds": [ "cobblemon:fossilmachine/insert_dna_small" ]
|
||||
"sounds": [
|
||||
{ "name": "cobblemon:block/fossil_machine/fossil_machine_insert_dna_small_1", "volume": 0.7 },
|
||||
{ "name": "cobblemon:block/fossil_machine/fossil_machine_insert_dna_small_2", "volume": 0.7 },
|
||||
{ "name": "cobblemon:block/fossil_machine/fossil_machine_insert_dna_small_3", "volume": 0.7 },
|
||||
{ "name": "cobblemon:block/fossil_machine/fossil_machine_insert_dna_small_4", "volume": 0.7 }
|
||||
]
|
||||
},
|
||||
"fossilmachine.insert_fossil": {
|
||||
"fossil_machine.insert_fossil": {
|
||||
"subtitle": "cobblemon.subtitle.fossilmachine.insert_fossil",
|
||||
"sounds": [ "cobblemon:fossilmachine/insert_fossil" ]
|
||||
"sounds": [ "cobblemon:block/fossil_machine/fossil_machine_insert_fossil" ]
|
||||
},
|
||||
"fossilmachine.retrieve_fossil": {
|
||||
"fossil_machine.retrieve_fossil": {
|
||||
"subtitle": "cobblemon.subtitle.fossilmachine.retrieve_fossil",
|
||||
"sounds": [ "cobblemon:fossilmachine/retrieve_fossil" ]
|
||||
"sounds": [ "cobblemon:block/fossil_machine/fossil_machine_retrieve_fossil" ]
|
||||
},
|
||||
"fossilmachine.retrieve_pokemon": {
|
||||
"fossil_machine.retrieve_pokemon": {
|
||||
"subtitle": "cobblemon.subtitle.fossilmachine.retrieve_pokemon",
|
||||
"sounds": [ "cobblemon:fossilmachine/retrieve_pokemon" ]
|
||||
"sounds": [ "cobblemon:block/fossil_machine/fossil_machine_retrieve_pokemon" ]
|
||||
},
|
||||
"fossilmachine.unprotected": {
|
||||
"fossil_machine.unprotected": {
|
||||
"subtitle": "cobblemon.subtitle.fossilmachine.unprotected",
|
||||
"sounds": [ "cobblemon:fossilmachine/unprotected" ]
|
||||
"sounds": [ "cobblemon:block/fossil_machine/fossil_machine_unprotected" ]
|
||||
},
|
||||
"gimmighoul.give_item_small": {
|
||||
"sounds": [ "cobblemon:gimmighoul_give_item_small" ]
|
||||
@@ -164,10 +169,10 @@
|
||||
},
|
||||
"coin_pouch.hit": {
|
||||
"sounds": [
|
||||
"cobblemon:block/coin_pouch/coin_pouch_block_hit_1",
|
||||
"cobblemon:block/coin_pouch/coin_pouch_block_hit_2",
|
||||
"cobblemon:block/coin_pouch/coin_pouch_block_hit_3",
|
||||
"cobblemon:block/coin_pouch/coin_pouch_block_hit_4"
|
||||
{ "name": "cobblemon:block/coin_pouch/coin_pouch_block_hit_1", "volume": 0.6 },
|
||||
{ "name": "cobblemon:block/coin_pouch/coin_pouch_block_hit_2", "volume": 0.6 },
|
||||
{ "name": "cobblemon:block/coin_pouch/coin_pouch_block_hit_3", "volume": 0.6 },
|
||||
{ "name": "cobblemon:block/coin_pouch/coin_pouch_block_hit_4", "volume": 0.6 }
|
||||
]
|
||||
},
|
||||
"coin_pouch.place": {
|
||||
@@ -204,10 +209,10 @@
|
||||
},
|
||||
"tumblestone.hit": {
|
||||
"sounds": [
|
||||
"cobblemon:block/tumblestone/tumblestone_hit_1",
|
||||
"cobblemon:block/tumblestone/tumblestone_hit_2",
|
||||
"cobblemon:block/tumblestone/tumblestone_hit_3",
|
||||
"cobblemon:block/tumblestone/tumblestone_hit_4"
|
||||
{ "name": "cobblemon:block/tumblestone/tumblestone_hit_1", "volume": 0.8 },
|
||||
{ "name": "cobblemon:block/tumblestone/tumblestone_hit_2", "volume": 0.8 },
|
||||
{ "name": "cobblemon:block/tumblestone/tumblestone_hit_3", "volume": 0.8 },
|
||||
{ "name": "cobblemon:block/tumblestone/tumblestone_hit_4", "volume": 0.8 }
|
||||
]
|
||||
},
|
||||
"tumblestone.place": {
|
||||
@@ -304,6 +309,20 @@
|
||||
"cobblemon:block/plants/medicinal_leek/medicinal_leek_plant_3"
|
||||
]
|
||||
},
|
||||
"vivichoke.break": {
|
||||
"sounds": [
|
||||
"cobblemon:block/plants/vivichoke/vivichoke_break_1",
|
||||
"cobblemon:block/plants/vivichoke/vivichoke_break_2",
|
||||
"cobblemon:block/plants/vivichoke/vivichoke_break_3"
|
||||
]
|
||||
},
|
||||
"vivichoke.place": {
|
||||
"sounds": [
|
||||
"cobblemon:block/plants/vivichoke/vivichoke_place_1",
|
||||
"cobblemon:block/plants/vivichoke/vivichoke_place_2",
|
||||
"cobblemon:block/plants/vivichoke/vivichoke_place_3"
|
||||
]
|
||||
},
|
||||
"mint.break": {
|
||||
"sounds": [
|
||||
"cobblemon:block/plants/mint/mint_break_1",
|
||||
@@ -318,6 +337,20 @@
|
||||
"cobblemon:block/plants/mint/mint_place_3"
|
||||
]
|
||||
},
|
||||
"revival_herb.break": {
|
||||
"sounds": [
|
||||
"cobblemon:block/plants/revival_herb/revival_herb_break_1",
|
||||
"cobblemon:block/plants/revival_herb/revival_herb_break_2",
|
||||
"cobblemon:block/plants/revival_herb/revival_herb_break_3"
|
||||
]
|
||||
},
|
||||
"revival_herb.place": {
|
||||
"sounds": [
|
||||
"cobblemon:block/plants/revival_herb/revival_herb_place_1",
|
||||
"cobblemon:block/plants/revival_herb/revival_herb_place_2",
|
||||
"cobblemon:block/plants/revival_herb/revival_herb_place_3"
|
||||
]
|
||||
},
|
||||
"gilded_chest.break": {
|
||||
"sounds": [
|
||||
"cobblemon:block/gilded_chest/gilded_chest_break_1",
|
||||
@@ -374,58 +407,220 @@
|
||||
"sounds": [ "cobblemon:supereffective" ]
|
||||
},
|
||||
"impact.normal": {
|
||||
"sounds": [ "cobblemon:attacks/impacts/impact_normal" ]
|
||||
"sounds": [
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fighting_1", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fighting_2", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fighting_3", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fighting_4", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fighting_5", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fighting_6", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fighting_7", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fighting_8", "volume": 0.8 }
|
||||
]
|
||||
},
|
||||
"impact.ice": {
|
||||
"sounds": [ "cobblemon:attacks/impacts/impact_ice" ]
|
||||
"sounds": [
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ice_1", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ice_2", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ice_3", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ice_4", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ice_5", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ice_6", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ice_7", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ice_8", "volume": 0.8 }
|
||||
]
|
||||
},
|
||||
"impact.water": {
|
||||
"sounds": [ "cobblemon:attacks/impacts/impact_water" ]
|
||||
"sounds": [
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_water_1", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_water_2", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_water_3", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_water_4", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_water_5", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_water_6", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_water_7", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_water_8", "volume": 0.8 }
|
||||
]
|
||||
},
|
||||
"impact.fire": {
|
||||
"sounds": [ "cobblemon:attacks/impacts/impact_fire" ]
|
||||
"sounds": [
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fire_1", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fire_2", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fire_3", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fire_4", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fire_5", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fire_6", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fire_7", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fire_8", "volume": 0.8 }
|
||||
]
|
||||
},
|
||||
"impact.electric": {
|
||||
"sounds": [ "cobblemon:attacks/impacts/impact_electric" ]
|
||||
"sounds": [
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_electric_1", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_electric_2", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_electric_3", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_electric_4", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_electric_5", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_electric_6", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_electric_7", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_electric_8", "volume": 0.8 }
|
||||
]
|
||||
},
|
||||
"impact.grass": {
|
||||
"sounds": [ "cobblemon:attacks/impacts/impact_grass" ]
|
||||
"sounds": [
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_grass_1", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_grass_2", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_grass_3", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_grass_4", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_grass_5", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_grass_6", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_grass_7", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_grass_8", "volume": 0.8 }
|
||||
]
|
||||
},
|
||||
"impact.fighting": {
|
||||
"sounds": [ "cobblemon:attacks/impacts/impact_fighting" ]
|
||||
"sounds": [
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fighting_1", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fighting_2", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fighting_3", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fighting_4", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fighting_5", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fighting_6", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fighting_7", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fighting_8", "volume": 0.8 }
|
||||
]
|
||||
},
|
||||
"impact.poison": {
|
||||
"sounds": [ "cobblemon:attacks/impacts/impact_poison" ]
|
||||
"sounds": [
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_poison_1", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_poison_2", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_poison_3", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_poison_4", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_poison_5", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_poison_6", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_poison_7", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_poison_8", "volume": 0.8 }
|
||||
]
|
||||
},
|
||||
"impact.ground": {
|
||||
"sounds": [ "cobblemon:attacks/impacts/impact_ground" ]
|
||||
"sounds": [
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ground_1", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ground_2", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ground_3", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ground_4", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ground_5", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ground_6", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ground_7", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ground_8", "volume": 0.8 }
|
||||
]
|
||||
},
|
||||
"impact.flying": {
|
||||
"sounds": [ "cobblemon:attacks/impacts/impact_flying" ]
|
||||
"sounds": [
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_flying_1", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_flying_2", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_flying_3", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_flying_4", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_flying_5", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_flying_6", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_flying_7", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_flying_8", "volume": 0.8 }
|
||||
]
|
||||
},
|
||||
"impact.psychic": {
|
||||
"sounds": [ "cobblemon:attacks/impacts/impact_psychic" ]
|
||||
"sounds": [
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_psychic_1", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_psychic_2", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_psychic_3", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_psychic_4", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_psychic_5", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_psychic_6", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_psychic_7", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_psychic_8", "volume": 0.8 }
|
||||
]
|
||||
},
|
||||
"impact.bug": {
|
||||
"sounds": [ "cobblemon:attacks/impacts/impact_bug" ]
|
||||
"sounds": [
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_bug_1", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_bug_2", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_bug_3", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_bug_4", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_bug_5", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_bug_6", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_bug_7", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_bug_8", "volume": 0.8 }
|
||||
]
|
||||
},
|
||||
"impact.rock": {
|
||||
"sounds": [ "cobblemon:attacks/impacts/impact_rock" ]
|
||||
"sounds": [
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_rock_1", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_rock_2", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_rock_3", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_rock_4", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_rock_5", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_rock_6", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_rock_7", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_rock_8", "volume": 0.8 }
|
||||
]
|
||||
},
|
||||
"impact.ghost": {
|
||||
"sounds": [ "cobblemon:attacks/impacts/impact_ghost" ]
|
||||
"sounds": [
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ghost_1", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ghost_2", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ghost_3", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ghost_4", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ghost_5", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ghost_6", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ghost_7", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_ghost_8", "volume": 0.8 }
|
||||
]
|
||||
},
|
||||
"impact.dragon": {
|
||||
"sounds": [ "cobblemon:attacks/impacts/impact_dragon" ]
|
||||
"sounds": [
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_dragon_1", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_dragon_2", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_dragon_3", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_dragon_4", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_dragon_5", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_dragon_6", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_dragon_7", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_dragon_8", "volume": 0.8 }
|
||||
]
|
||||
},
|
||||
"impact.dark": {
|
||||
"sounds": [ "cobblemon:attacks/impacts/impact_dark" ]
|
||||
"sounds": [
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_dark_1", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_dark_2", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_dark_3", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_dark_4", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_dark_5", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_dark_6", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_dark_7", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_dark_8", "volume": 0.8 }
|
||||
]
|
||||
},
|
||||
"impact.steel": {
|
||||
"sounds": [ "cobblemon:attacks/impacts/impact_steel" ]
|
||||
"sounds": [
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_steel_1", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_steel_2", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_steel_3", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_steel_4", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_steel_5", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_steel_6", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_steel_7", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_steel_8", "volume": 0.8 }
|
||||
]
|
||||
},
|
||||
"impact.fairy": {
|
||||
"sounds": [ "cobblemon:attacks/impacts/impact_fairy" ]
|
||||
"sounds": [
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fairy_1", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fairy_2", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fairy_3", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fairy_4", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fairy_5", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fairy_6", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fairy_7", "volume": 0.8 },
|
||||
{ "name": "cobblemon:attacks/impact_generic/impact_generic_fairy_8", "volume": 0.8 }
|
||||
]
|
||||
},
|
||||
"pokemon.bulbasaur.ambient": {
|
||||
"sounds": [ "cobblemon:pokemon/bulbasaur/bulbasaur_ambient" ]
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Loaded 100 of 1068 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user