mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-27 12:36:24 -04:00
Compare commits
64
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ce2a7a83e | ||
|
|
26d97f2043 | ||
|
|
c4f5416bb3 | ||
|
|
8066a92ab5 | ||
|
|
f149439da8 | ||
|
|
95dd6cbfcb | ||
|
|
551b3ebe87 | ||
|
|
89914813a1 | ||
|
|
742ec131d5 | ||
|
|
4175c36388 | ||
|
|
f6ed1b38f8 | ||
|
|
c299967cce | ||
|
|
b79f569def | ||
|
|
944144a671 | ||
|
|
586b5a860f | ||
|
|
29d91fb191 | ||
|
|
183d85a3b6 | ||
|
|
0795b06ca0 | ||
|
|
6fdd87f5cf | ||
|
|
3b364a4590 | ||
|
|
9f866aa292 | ||
|
|
4e4417d4df | ||
|
|
900ca0cd8d | ||
|
|
5448031cae | ||
|
|
abd92c2325 | ||
|
|
a3ac3c36e6 | ||
|
|
36ce262755 | ||
|
|
9246523853 | ||
|
|
db2c2f0089 | ||
|
|
3a090ba01c | ||
|
|
3c4481c9cc | ||
|
|
4e73a19ade | ||
|
|
c58ba08a65 | ||
|
|
18940956a8 | ||
|
|
68520307b4 | ||
|
|
84825dbd69 | ||
|
|
b231a80b68 | ||
|
|
d2796b8755 | ||
|
|
1ab3ca8628 | ||
|
|
f4da1436a5 | ||
|
|
9a0b779ca3 | ||
|
|
2bcb42270a | ||
|
|
51472d2369 | ||
|
|
2cb430d927 | ||
|
|
7bbfbf5852 | ||
|
|
93a368a844 | ||
|
|
5c934a0b66 | ||
|
|
1a4034ded4 | ||
|
|
dbd73c53ea | ||
|
|
25d17a271b | ||
|
|
e9b3940eb6 | ||
|
|
e442ca2732 | ||
|
|
b34e1f30d1 | ||
|
|
8747d3cd6f | ||
|
|
ca7a4e12be | ||
|
|
9c3b713c4a | ||
|
|
6c0c352001 | ||
|
|
51c1706a9a | ||
|
|
5320704702 | ||
|
|
91e28616a9 | ||
|
|
8df06a4836 | ||
|
|
f2c9886ae0 | ||
|
|
d74ca7b70d | ||
|
|
ba7a3ab3c2 |
+43
-4
@@ -1,5 +1,47 @@
|
||||
# Changelog
|
||||
## [1.6.0 - The Record Catch Update (Month Xth, 2024)](#1-6-0)
|
||||
## [1.6.1 (Release TBD)](#1-6-1)
|
||||
|
||||
### Additions
|
||||
- Added config setting `maxPokedexScanningDetectionRange` to control from what distance the player can scan Pokémon using the Pokédex.
|
||||
- Added the `is_standing_on_blocks(depth, blocks...)` MoLang function, which returns whether the specified entity is standing on a specific block or set of blocks. Example usage: `q.is_standing_on_blocks(2, minecraft:sand)`
|
||||
- Added config setting `hideUnimplementedPokemonInThePokedex` which hides unimplemented Pokémon from the Pokédex when set to true.
|
||||
- Added molang particle queries for getting distance to targeted entities
|
||||
- Added debug renderer for poseable entity locators
|
||||
- Added `baseScale` property to NPCs.
|
||||
|
||||
### Fixes
|
||||
- Fix Pokédex sometimes crashing when switching forms
|
||||
- Fix crash related to Tom's Simple Storage and Fossil Machine
|
||||
- Fixed not being able to retrieve a fossil from the Fossil Machine with an empty hand
|
||||
- Fix Pokémon being collidable while being captured by a Pokéball.
|
||||
- Fixed `full_party`, `own_zangoose_seviper`, `use_revive` and `use_candy` Advancement triggers
|
||||
- Fixed `healing_machine` Advancement by using the correct 1.21 trigger
|
||||
- Fixed an issue where the first Pokémon in the pastured Pokémon list clipped into the interface.
|
||||
- Fixed all Pokémon facing South on spawn
|
||||
- Fixed not being able to retrieve a fossil from the Fossil Machine with an empty hand
|
||||
- Parametric particle motion now works
|
||||
- Event spawned particles now work
|
||||
- Particles can now have independent coordinate spaces
|
||||
- Fixed bait being consumed when not reeling in any pokémon.
|
||||
- Fix Miltank milk magically disappearing out of your bucket
|
||||
- Fix Cobblemon Nicknames migrating from 1.5.2 not being displayed properly
|
||||
- Fix capitalization in one of our config fields, but allowing typo'd version to still be valid
|
||||
- Fix Pokerod not working if lure or luck of the sea enchantments get removed by other mods
|
||||
- Fix crashes related to Pokémon when they are ready to evolve while holding an enchanted item
|
||||
- Fix crashes that sometimes occur when evolving Nincada
|
||||
- Fix plants not being compostible on NeoForge
|
||||
- Fix hide UI (F1 key) not hiding the party overlay.
|
||||
- Fixed NPC MoLang command `player_lose_command` not working.
|
||||
- Corrected misaligned tooltips with editboxes in the NPC editor screen.
|
||||
- Fixed Pokémon riding two boats when attempting to deploy a platform on water.
|
||||
- Made berry trees be shearable by dispenser blocks
|
||||
- Fix the summary screen showing there's experience to reach the next level when at level cap.
|
||||
- Fix Pokémon forgetting moves when evolving on specific cases.
|
||||
- Fixed Adorn compatibility, including improvements when using JEI/REI (Apricorn items now show up under the collapsed entries rather than standalone)
|
||||
- Fix error message appearing on battle log when using Solar Beam with Sunny Day.
|
||||
- Fix Pokémon Model offsets for larger species.
|
||||
|
||||
## [1.6.0 - The Record Catch Update (December 25th, 2024)](#1-6-0)
|
||||
#### "Now that there's a fishing mechanic, the mod is actually good!"
|
||||
|
||||
### Additions
|
||||
@@ -124,9 +166,6 @@
|
||||
#### Gen 9
|
||||
- Wattrel
|
||||
- Kilowattrel
|
||||
- Wiglett
|
||||
- Wugtrio
|
||||
- Flamigo
|
||||
- Veluza
|
||||
- Farigiraf
|
||||
- Klawf
|
||||
|
||||
@@ -9,6 +9,20 @@
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper;
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel;
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState;
|
||||
import com.cobblemon.mod.common.entity.PosableEntity;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.joml.Vector3f;
|
||||
import org.spongepowered.asm.mixin.Debug;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -34,4 +48,39 @@ public class EntityRenderDispatcherMixin {
|
||||
public void resourceManagerReloadHook(ResourceManager resourceManager, CallbackInfo ci) {
|
||||
CobblemonClient.INSTANCE.onAddLayer(this.playerRenderers);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "renderHitbox(Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;Lnet/minecraft/world/entity/Entity;FFFF)V",
|
||||
at = @At(value = "TAIL")
|
||||
)
|
||||
private static void renderLocators(
|
||||
PoseStack poseStack,
|
||||
VertexConsumer buffer,
|
||||
Entity entity,
|
||||
float red,
|
||||
float green,
|
||||
float blue,
|
||||
float alpha,
|
||||
CallbackInfo ci
|
||||
) {
|
||||
if (entity instanceof PosableEntity posableEntity) {
|
||||
if (posableEntity.getDelegate() instanceof PosableState state) {
|
||||
state.getLocatorStates().forEach((locator, matrix) -> {
|
||||
poseStack.pushPose();
|
||||
Vec3 pos = matrix.getOrigin().subtract(entity.position());
|
||||
LevelRenderer.renderLineBox(
|
||||
poseStack,
|
||||
buffer,
|
||||
AABB.ofSize(pos, 0.25, 0.25, 0.25),
|
||||
0F,
|
||||
1F,
|
||||
0F,
|
||||
1F
|
||||
);
|
||||
poseStack.popPose();
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,7 +206,7 @@ object Cobblemon {
|
||||
storage.onPlayerDataSync(it)
|
||||
playerDataManager.syncAllToPlayer(it)
|
||||
starterHandler.handleJoin(it)
|
||||
ServerSettingsPacket(this.config.preventCompletePartyDeposit, this.config.displayEntityLevelLabel, this.config.displayEntityNameLabel).sendToPlayer(it)
|
||||
ServerSettingsPacket(this.config.preventCompletePartyDeposit, this.config.displayEntityLevelLabel, this.config.displayEntityNameLabel, this.config.maxPokemonLevel).sendToPlayer(it)
|
||||
}
|
||||
PlatformEvents.SERVER_PLAYER_LOGOUT.subscribe {
|
||||
PCLinkManager.removeLink(it.player.uuid)
|
||||
|
||||
+2
-53
@@ -33,12 +33,13 @@ class PartyCheckCriterion(
|
||||
override fun matches(player: ServerPlayer, context: PlayerPartyStore): Boolean {
|
||||
val matches = mutableListOf<ResourceLocation>()
|
||||
party.forEach {
|
||||
if (it == "any".asIdentifierDefaultingNamespace()) {
|
||||
if (it == "any".asIdentifierDefaultingNamespace("minecraft") || it == "any".asIdentifierDefaultingNamespace()) {
|
||||
matches.add(it)
|
||||
}
|
||||
}
|
||||
val partyCount = context.count()
|
||||
if (matches.containsAll(party) && party.size == partyCount && matches.size == partyCount) return true
|
||||
matches.clear()
|
||||
context.iterator().forEach {
|
||||
if (party.contains(it.species.resourceIdentifier)) {
|
||||
matches.add(it.species.resourceIdentifier)
|
||||
@@ -47,55 +48,3 @@ class PartyCheckCriterion(
|
||||
return matches.containsAll(party) && matches.size == party.size
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*class PartyCheckCriterion(id: Identifier, entity: LootContextPredicate) : SimpleCriterionCondition<PartyCheckContext>(id, entity){
|
||||
val party = mutableListOf<Identifier>()
|
||||
override fun toJson(json: JsonObject) {
|
||||
json.add("party", JsonArray(party.size).also {
|
||||
party.forEach { pokemon -> it.add(pokemon.toString()) }
|
||||
})
|
||||
}
|
||||
|
||||
override fun fromJson(json: JsonObject) {
|
||||
party.clear()
|
||||
json.getAsJsonArray("party").forEach { element ->
|
||||
party.add(element.asString.asIdentifierDefaultingNamespace())
|
||||
}
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: PartyCheckContext): Boolean {
|
||||
val playerParty = player.party()
|
||||
val matches = mutableListOf<Identifier>()
|
||||
party.forEach {
|
||||
if (it == "any".asIdentifierDefaultingNamespace()) {
|
||||
matches.add(it)
|
||||
}
|
||||
}
|
||||
val partyCount = playerParty.count()
|
||||
if (matches.containsAll(party) && party.size == partyCount && matches.size == partyCount) return true
|
||||
playerParty.iterator().forEach {
|
||||
if (party.contains(it.species.resourceIdentifier)) {
|
||||
matches.add(it.species.resourceIdentifier)
|
||||
}
|
||||
}
|
||||
return matches.containsAll(party) && matches.size == partyCount
|
||||
}
|
||||
}
|
||||
|
||||
open class PartyCheckContext(val party : PlayerPartyStore)*/
|
||||
@@ -96,11 +96,12 @@ interface PokemonSelectingItem {
|
||||
player.sendSystemMessage(battleLang("bagitem.invalid").red())
|
||||
} else {
|
||||
battlePokemon.actor.forceChoose(BagItemActionResponse(bagItem, battlePokemon))
|
||||
val stackName = BuiltInRegistries.ITEM.getKey(stack.item)
|
||||
if (!player.isCreative) {
|
||||
stack.shrink(1)
|
||||
battlePokemon.actor.itemsUsed.add(bagItem)
|
||||
}
|
||||
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(battlePokemon.effectedPokemon.species.resourceIdentifier, BuiltInRegistries.ITEM.getKey(stack.item)))
|
||||
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(battlePokemon.effectedPokemon.species.resourceIdentifier, stackName))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,4 +149,4 @@ interface PokemonSelectingItem {
|
||||
|
||||
return InteractionResultHolder.success(stack)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -514,6 +514,17 @@ object MoLangFunctions {
|
||||
.map { it.asMostSpecificMoLangValue() }
|
||||
.asArrayValue()
|
||||
}
|
||||
map.put("is_standing_on_blocks") { params ->
|
||||
val depth = params.getDouble(0).toInt()
|
||||
val blocks: MutableSet<Block> = mutableSetOf()
|
||||
for (blockIndex in 1..<params.params.size) {
|
||||
val blockString = params.getString(blockIndex)
|
||||
val block = BuiltInRegistries.BLOCK.get(blockString.asIdentifierDefaultingNamespace("minecraft"))
|
||||
blocks.add(block)
|
||||
}
|
||||
|
||||
return@put if (entity.isStandingOn(blocks, depth)) DoubleValue.ONE else DoubleValue.ZERO
|
||||
}
|
||||
if (entity is PosableEntity) {
|
||||
map.put("play_animation") { params ->
|
||||
val animation = params.getString(0)
|
||||
@@ -603,7 +614,8 @@ object MoLangFunctions {
|
||||
val context = ActionEffectContext(
|
||||
actionEffect = actionEffect,
|
||||
providers = mutableListOf(NPCProvider(npc)),
|
||||
runtime = runtime
|
||||
runtime = runtime,
|
||||
level = npc.level()
|
||||
)
|
||||
npc.actionEffect = context
|
||||
npc.brain.setMemory(CobblemonMemories.ACTIVE_ACTION_EFFECT, context)
|
||||
|
||||
+3
-1
@@ -15,6 +15,7 @@ import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.level.Level
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
/**
|
||||
@@ -69,7 +70,8 @@ class ActionEffectContext(
|
||||
val runtime: MoLangRuntime,
|
||||
var canBeInterrupted: Boolean = false,
|
||||
var interrupted: Boolean = false,
|
||||
var currentKeyframes: MutableList<ActionEffectKeyframe> = mutableListOf()
|
||||
var currentKeyframes: MutableList<ActionEffectKeyframe> = mutableListOf(),
|
||||
var level: Level? = null
|
||||
) {
|
||||
inline fun <reified T> findOneProvider() = providers.filterIsInstance<T>().firstOrNull()
|
||||
}
|
||||
|
||||
+32
-6
@@ -24,6 +24,7 @@ import net.minecraft.server.level.ServerLevel
|
||||
|
||||
/**
|
||||
* Spawns particles on the entity based on the given particle effect and locator.
|
||||
* Optionally, you can specify target that ends up setting the destination pos on the spawned ParticleStorm
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since January 21st, 2024
|
||||
@@ -32,14 +33,25 @@ class EntityParticlesActionEffectKeyframe : ConditionalActionEffectKeyframe(), E
|
||||
override val entityCondition = "q.entity.is_user".asExpressionLike()
|
||||
var effect: String? = null
|
||||
var locators: List<String> = listOf("target")
|
||||
var targetLocators: Set<String>? = null
|
||||
|
||||
val delay: ExpressionLike = "0".asExpressionLike()
|
||||
val visibilityRange = 200
|
||||
|
||||
override fun playWhenTrue(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
val entities = context.providers
|
||||
val allEntities = context.providers
|
||||
.filterIsInstance<EntityProvider>()
|
||||
.flatMap { prov -> prov.entities.filter { test(context, it, isUser = prov is UsersProvider) } }
|
||||
.flatMap { prov -> prov.entities }
|
||||
|
||||
val userEntities = context.providers
|
||||
.filterIsInstance<UsersProvider>()
|
||||
.flatMap { prov -> prov.entities }
|
||||
|
||||
val targetEntities = context.providers
|
||||
.filterIsInstance<TargetsProvider>()
|
||||
.flatMap { prov -> prov.entities}
|
||||
|
||||
val sourceEntities = allEntities.filter { test(context, it, it in userEntities) }
|
||||
|
||||
val effectIdentifier = try {
|
||||
effect?.asExpressionLike()?.resolveString(context.runtime)?.takeIf { it != "0" } ?: effect
|
||||
@@ -47,10 +59,24 @@ class EntityParticlesActionEffectKeyframe : ConditionalActionEffectKeyframe(), E
|
||||
effect
|
||||
}?.asIdentifierDefaultingNamespace() ?: return skip()
|
||||
|
||||
entities.filter { it is PosableEntity }.forEach { entity ->
|
||||
val packet = SpawnSnowstormEntityParticlePacket(effectIdentifier, entity.id, (locators).toList())
|
||||
val players = (entity.level() as ServerLevel).getPlayers { it.distanceTo(entity) <= visibilityRange }
|
||||
packet.sendToPlayers(players)
|
||||
//Things could be a little weird here since TECHNICALLY it might be possible for a battle to be happening across dimensions
|
||||
val calcedLevel = (context.level as? ServerLevel) ?: allEntities.first().level() as ServerLevel
|
||||
val players = calcedLevel.getPlayers { player ->
|
||||
allEntities.any { player.distanceTo(it) <= visibilityRange }
|
||||
}
|
||||
|
||||
|
||||
sourceEntities.filter { it is PosableEntity }.forEach { entity ->
|
||||
if (targetLocators == null) {
|
||||
val packet = SpawnSnowstormEntityParticlePacket(effectIdentifier, entity.id, locators)
|
||||
packet.sendToPlayers(players)
|
||||
}
|
||||
else {
|
||||
targetEntities.forEach { targetEntity ->
|
||||
val packet = SpawnSnowstormEntityParticlePacket(effectIdentifier, entity.id, locators, targetEntity.id, targetLocators!!.toList())
|
||||
packet.sendToPlayers(players)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return delayedFuture(seconds = delay.resolveFloat(context.runtime))
|
||||
|
||||
@@ -38,6 +38,7 @@ class NPCClass {
|
||||
var resourceIdentifier: ResourceLocation = cobblemonResource("dummy")
|
||||
var names: MutableList<Component> = mutableListOf()
|
||||
var aspects: MutableSet<String> = mutableSetOf() // These only make sense when applied via presets
|
||||
var baseScale: Float = 1F
|
||||
var hitbox = EntityDimensions.scalable(0.6F, 1.8F).withEyeHeight(1.62F)
|
||||
var modelScale: Float = 0.94F
|
||||
var battleConfiguration = NPCBattleConfiguration()
|
||||
@@ -62,6 +63,7 @@ class NPCClass {
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeString(resourceIdentifier.toString())
|
||||
buffer.writeCollection(names) { _, v -> buffer.writeText(v) }
|
||||
buffer.writeFloat(baseScale)
|
||||
buffer.writeFloat(hitbox.width)
|
||||
buffer.writeFloat(hitbox.height)
|
||||
buffer.writeBoolean(hitbox.fixed)
|
||||
@@ -100,6 +102,7 @@ class NPCClass {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
resourceIdentifier = ResourceLocation.parse(buffer.readString().toString())
|
||||
names = buffer.readList { buffer.readText().copy() }.toMutableList()
|
||||
baseScale = buffer.readFloat()
|
||||
val length = buffer.readFloat()
|
||||
val width = buffer.readFloat()
|
||||
val fixed = buffer.readBoolean()
|
||||
|
||||
@@ -26,6 +26,7 @@ class NPCPreset {
|
||||
var canDespawn: Boolean? = null
|
||||
var interaction: NPCInteractConfiguration? = null
|
||||
var names: MutableSet<Component>? = null
|
||||
var baseScale: Float? = null
|
||||
var hitbox: EntityDimensions? = null
|
||||
var ai: List<BrainConfig>? = null
|
||||
var skill: Int? = null
|
||||
@@ -51,6 +52,7 @@ class NPCPreset {
|
||||
// aiScripts?.let { npcClass.aiScripts.addAll(it) }
|
||||
interaction?.let { npcClass.interaction = it }
|
||||
names?.let { npcClass.names.addAll(it) }
|
||||
baseScale?.let { npcClass.baseScale = it }
|
||||
hitbox?.let { npcClass.hitbox = it }
|
||||
skill?.let { npcClass.skill = it }
|
||||
autoHealParty?.let { npcClass.autoHealParty = it }
|
||||
|
||||
@@ -32,9 +32,10 @@ class SearchFilter(val pokedexManager: AbstractPokedexManager, val searchString:
|
||||
if (searchString == "") return true
|
||||
|
||||
val species = PokemonSpecies.getByIdentifier(entry.speciesId) ?: return false
|
||||
if (pokedexManager.getHighestKnowledgeFor(entry) == PokedexEntryProgress.NONE) return false
|
||||
val highestKnowledgeForEntry = pokedexManager.getHighestKnowledgeFor(entry)
|
||||
if (highestKnowledgeForEntry == PokedexEntryProgress.NONE) return false
|
||||
|
||||
when(searchByType) {
|
||||
when (searchByType) {
|
||||
SearchByType.ABILITIES -> {
|
||||
if (pokedexManager.getHighestKnowledgeFor(entry) !== PokedexEntryProgress.CAUGHT) return false
|
||||
val abilityList = mutableListOf<String>()
|
||||
|
||||
@@ -130,7 +130,7 @@ interface Evolution : EvolutionLike {
|
||||
owner.party().getFirstAvailablePosition() ?: return false
|
||||
|
||||
// Add shed Pokemon to player's party
|
||||
val shedPokemon = pokemon.clone()
|
||||
val shedPokemon = pokemon.clone(registryAccess = owner.registryAccess())
|
||||
shedPokemon.removeHeldItem()
|
||||
innerShedder.apply(shedPokemon)
|
||||
shedPokemon.caughtBall = ((pokeballStack?.item ?: CobblemonItems.POKE_BALL) as PokeBallItem).pokeBall
|
||||
@@ -190,15 +190,23 @@ interface Evolution : EvolutionLike {
|
||||
}
|
||||
|
||||
fun evolutionMethod(pokemon: Pokemon) {
|
||||
// This ensures the Pokémon doesn't lose moves during evolution
|
||||
// (e.g., Oshawott evolving at level 17 knowing Razor Shell, while Dewott only learns it at level 18).
|
||||
val previousSpeciesLearnableMoves = pokemon.relearnableMoves
|
||||
|
||||
this.result.apply(pokemon)
|
||||
this.learnableMoves.forEach { move ->
|
||||
|
||||
val movesToLearn = previousSpeciesLearnableMoves + this.learnableMoves
|
||||
movesToLearn.forEach { move ->
|
||||
if (pokemon.moveSet.hasSpace()) {
|
||||
pokemon.moveSet.add(move.create())
|
||||
} else {
|
||||
pokemon.benchedMoves.add(BenchedMove(move, 0))
|
||||
}
|
||||
|
||||
pokemon.getOwnerPlayer()?.sendSystemMessage(lang("experience.learned_move", pokemon.getDisplayName(), move.displayName))
|
||||
}
|
||||
|
||||
// we want to instantly tick for example you might only evolve your Bulbasaur at level 34 so Venusaur should be immediately available
|
||||
pokemon.evolutions.filterIsInstance<PassiveEvolution>().forEach { evolution -> evolution.attemptEvolution(pokemon) }
|
||||
pokemon.lockedEvolutions.filterIsInstance<PassiveEvolution>().forEach { evolution -> evolution.attemptEvolution(pokemon) }
|
||||
|
||||
+4
-1
@@ -31,6 +31,7 @@ class BedrockParticleEmitter(
|
||||
var rate: ParticleEmitterRate = InstantParticleEmitterRate(),
|
||||
var shape: ParticleEmitterShape = SphereParticleEmitterShape(),
|
||||
var lifetime: ParticleEmitterLifetime = OnceEmitterLifetime(NumberExpression(1.0)),
|
||||
var space: EmitterSpace = EmitterSpace(),
|
||||
var eventTimeline: EventTriggerTimeline = EventTriggerTimeline(mutableMapOf()),
|
||||
var creationEvents: MutableList<SimpleEventTrigger> = mutableListOf(),
|
||||
var expirationEvents: MutableList<SimpleEventTrigger> = mutableListOf(),
|
||||
@@ -45,18 +46,20 @@ class BedrockParticleEmitter(
|
||||
ParticleEmitterRate.codec.fieldOf("rate").forGetter { it.rate },
|
||||
ParticleEmitterShape.codec.fieldOf("shape").forGetter { it.shape },
|
||||
ParticleEmitterLifetime.codec.fieldOf("lifetime").forGetter { it.lifetime },
|
||||
EmitterSpace.CODEC.fieldOf("space").forGetter { it.space },
|
||||
EventTriggerTimeline.CODEC.fieldOf("eventTimeline").forGetter { it.eventTimeline },
|
||||
SimpleEventTrigger.CODEC.listOf().fieldOf("creationEvents").forGetter { it.creationEvents },
|
||||
SimpleEventTrigger.CODEC.listOf().fieldOf("expirationEvents").forGetter { it.expirationEvents },
|
||||
EventTriggerTimeline.CODEC.fieldOf("travelDistanceEvents").forGetter { it.travelDistanceEvents },
|
||||
LoopingTravelDistanceEventTrigger.CODEC.listOf().fieldOf("loopingTravelDistanceEvents").forGetter { it.loopingTravelDistanceEvents }
|
||||
).apply(instance) { startExpressions, updateExpressions, rate, shape, lifetime, eventTimeline, creationEvents, expirationEvents, travelDistanceEvents, loopingTravelDistanceEvents ->
|
||||
).apply(instance) { startExpressions, updateExpressions, rate, shape, lifetime, space, eventTimeline, creationEvents, expirationEvents, travelDistanceEvents, loopingTravelDistanceEvents ->
|
||||
BedrockParticleEmitter(
|
||||
startExpressions = startExpressions,
|
||||
updateExpressions = updateExpressions,
|
||||
shape = shape,
|
||||
rate = rate,
|
||||
lifetime = lifetime,
|
||||
space = space,
|
||||
eventTimeline = eventTimeline,
|
||||
creationEvents = creationEvents,
|
||||
expirationEvents = expirationEvents,
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.snowstorm
|
||||
|
||||
import com.cobblemon.mod.common.api.data.ArbitrarilyMappedSerializableCompanion
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper
|
||||
import com.cobblemon.mod.common.util.codec.CodecUtils
|
||||
import com.cobblemon.mod.common.util.codec.optionalFieldOfWithDefault
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import org.joml.AxisAngle4f
|
||||
import org.joml.Matrix4f
|
||||
import org.joml.Vector3f
|
||||
|
||||
class EmitterSpace(
|
||||
var scaling: ScalingMode = ScalingMode.WORLD
|
||||
) {
|
||||
companion object {
|
||||
val CODEC: Codec<EmitterSpace> = RecordCodecBuilder.create { instance ->
|
||||
instance.group(
|
||||
Codec.STRING.optionalFieldOfWithDefault("scaling", "world").forGetter { it.scaling.toString() }
|
||||
).apply(instance) { scaling ->
|
||||
EmitterSpace(
|
||||
ScalingMode.valueOf(scaling.uppercase())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun initializeEmitterMatrix(rootMatrix: MatrixWrapper, locatorMatrix: MatrixWrapper): MatrixWrapper {
|
||||
val rootRotation = rootMatrix.matrix.getRotation(AxisAngle4f())
|
||||
val scale = Vector3f()
|
||||
|
||||
if (scaling == ScalingMode.ENTITY) {
|
||||
locatorMatrix.matrix.getScale(scale)
|
||||
}
|
||||
else {
|
||||
rootMatrix.matrix.getScale(scale)
|
||||
//Incase they are multiplying some axis by -1 to rotate
|
||||
scale.x = Math.signum(scale.x)
|
||||
scale.y = Math.signum(scale.y)
|
||||
scale.z = Math.signum(scale.z)
|
||||
}
|
||||
|
||||
val particleScale = Vector3f(scale.x, scale.y, scale.z)
|
||||
//Presumably we will want to make the initial rotation configurable instead of always using root
|
||||
val particleRawMatrix = Matrix4f().scale(particleScale).rotate(rootRotation)
|
||||
return MatrixWrapper().updateMatrix(particleRawMatrix).updatePosition(locatorMatrix.getOrigin())
|
||||
}
|
||||
|
||||
enum class ScalingMode {
|
||||
WORLD,
|
||||
ENTITY
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Matrix4f
|
||||
|
||||
/**
|
||||
* An event that can be referenced from various particle event triggers. The events are not necessarily particles,
|
||||
@@ -77,9 +78,11 @@ class ParticleEvent(
|
||||
fun run(storm: ParticleStorm, particle: SnowstormParticle?) {
|
||||
particleEffect?.let { effect ->
|
||||
val bedrockParticleOptions = BedrockParticleOptionsRepository.getEffect(effect.effect) ?: return@let
|
||||
val rootMatrix = when (effect.type) {
|
||||
EventParticleOptions.EventParticleType.EMITTER-> MatrixWrapper().updatePosition(storm.matrixWrapper.position).updateMatrix(storm.matrixWrapper.matrix)
|
||||
EventParticleOptions.EventParticleType.EMITTER_BOUND -> storm.matrixWrapper
|
||||
val particleMatrix = when (effect.type) {
|
||||
//It may seem incorrect to clone for both of these, but the locator matrix determines whether the
|
||||
//emitter follows the locator. We don't want the child emitter to affect the parent emitter so we make a copy
|
||||
EventParticleOptions.EventParticleType.EMITTER,
|
||||
EventParticleOptions.EventParticleType.EMITTER_BOUND -> storm.emitterSpaceMatrix.clone()
|
||||
EventParticleOptions.EventParticleType.PARTICLE,
|
||||
EventParticleOptions.EventParticleType.PARTICLE_WITH_VELOCITY -> (particle?.let {
|
||||
Vec3(
|
||||
@@ -87,7 +90,19 @@ class ParticleEvent(
|
||||
it.getY(),
|
||||
it.getZ()
|
||||
)
|
||||
} ?: Vec3(storm.getX(), storm.getY(), storm.getZ())).let { MatrixWrapper().updatePosition(it) }
|
||||
} ?: Vec3(storm.getX(), storm.getY(), storm.getZ())).let {
|
||||
val matrixWrapper = MatrixWrapper()
|
||||
matrixWrapper.updatePosition(it)
|
||||
//We only want the orientation of the original matrix, not position/translation
|
||||
matrixWrapper.updateMatrix(Matrix4f(storm.emitterSpaceMatrix.matrix).setTranslation(0F, 0F, 0F))
|
||||
}
|
||||
}
|
||||
|
||||
val locatorMatrix = when (effect.type) {
|
||||
EventParticleOptions.EventParticleType.EMITTER -> particleMatrix
|
||||
EventParticleOptions.EventParticleType.EMITTER_BOUND -> storm.locatorSpaceMatrix
|
||||
EventParticleOptions.EventParticleType.PARTICLE,
|
||||
EventParticleOptions.EventParticleType.PARTICLE_WITH_VELOCITY -> particleMatrix
|
||||
}
|
||||
|
||||
val sourceVelocity = when (effect.type) {
|
||||
@@ -105,17 +120,24 @@ class ParticleEvent(
|
||||
|
||||
val newStorm = ParticleStorm(
|
||||
effect = bedrockParticleOptions,
|
||||
matrixWrapper = rootMatrix,
|
||||
emitterSpaceMatrix = particleMatrix,
|
||||
locatorSpaceMatrix = locatorMatrix,
|
||||
world = storm.world,
|
||||
sourceVelocity = sourceVelocity,
|
||||
sourceAlive = storm.sourceAlive,
|
||||
sourceVisible = storm.sourceVisible,
|
||||
onDespawn = {},
|
||||
runtime = MoLangRuntime().setup().also { it.environment.query = storm.runtime.environment.query },
|
||||
targetPos = storm.targetPos,
|
||||
runtime = MoLangRuntime().setup(),
|
||||
entity = storm.entity
|
||||
)
|
||||
|
||||
effect.expression?.resolve(newStorm.runtime)
|
||||
//The reason this doesn't use the newStorms runtime is that the parent storm can add queries AFTER
|
||||
//the child storm spawns in. Say a parent storm has a creation event. The child spawns before the parent
|
||||
//When the parent tries to add its queries, it overwrites the child's
|
||||
val tempRuntime = MoLangRuntime().setup().also {
|
||||
it.environment.query = storm.runtime.environment.query
|
||||
}
|
||||
effect.expression?.resolve(tempRuntime)
|
||||
|
||||
newStorm.spawn()
|
||||
}
|
||||
|
||||
@@ -77,16 +77,17 @@ class ParametricParticleMotion(
|
||||
|
||||
override fun getInitialVelocity(runtime: MoLangRuntime, storm: ParticleStorm, particlePos: Vec3, emitterPos: Vec3) = Vec3.ZERO
|
||||
override fun getVelocity(runtime: MoLangRuntime, particle: SnowstormParticle, velocity: Vec3): Vec3 {
|
||||
val stormPosition = Vec3(
|
||||
particle.storm.getX(),
|
||||
particle.storm.getY(),
|
||||
particle.storm.getZ()
|
||||
val particlePositionWS = Vec3(
|
||||
particle.getX(),
|
||||
particle.getY(),
|
||||
particle.getZ()
|
||||
)
|
||||
val offset = runtime.resolveVec3d(this.offset)
|
||||
val particlePosition =
|
||||
Vec3(particle.getX(), particle.getY(), particle.getZ())
|
||||
val desiredPosition = stormPosition.add(offset)
|
||||
return desiredPosition.subtract(particlePosition)
|
||||
val matrix = particle.matrixWrapper
|
||||
|
||||
val targetPosPS = runtime.resolveVec3d(offset)
|
||||
val targetPosWS = matrix.transformPosition(targetPosPS)
|
||||
|
||||
return targetPosWS.subtract(particlePositionWS)
|
||||
}
|
||||
|
||||
override fun getParticleDirection(runtime: MoLangRuntime, storm: ParticleStorm, velocity: Vec3, minSpeed: Float) = runtime.resolveVec3d(direction).normalize()
|
||||
@@ -277,7 +278,7 @@ class CustomMotionDirection(
|
||||
runtime.resolveDouble(direction.second),
|
||||
runtime.resolveDouble(direction.third)
|
||||
)
|
||||
return storm.matrixWrapper.matrix.transformDirection(v)
|
||||
return storm.emitterSpaceMatrix.matrix.transformDirection(v)
|
||||
}
|
||||
|
||||
override fun <T> encode(ops: DynamicOps<T>) = CODEC.encodeStart(ops, this)
|
||||
|
||||
+5
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.api.spawning.condition
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
|
||||
import com.cobblemon.mod.common.api.spawning.context.FishingSpawningContext
|
||||
import com.cobblemon.mod.common.util.itemRegistry
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper
|
||||
import net.minecraft.world.item.enchantment.Enchantments
|
||||
@@ -27,6 +28,10 @@ class FishingSpawningCondition: SpawningCondition<FishingSpawningContext>() {
|
||||
|
||||
var rod: RegistryLikeCondition<Item>? = null
|
||||
var neededNearbyBlocks: MutableList<RegistryLikeCondition<Block>>? = null
|
||||
var minLureLevel: Int? = null
|
||||
var maxLureLevel: Int? = null
|
||||
var bait: ResourceLocation? = null
|
||||
var rodType: ResourceLocation? = null
|
||||
|
||||
override fun fits(ctx: FishingSpawningContext): Boolean {
|
||||
if (!super.fits(ctx)) {
|
||||
|
||||
-4
@@ -59,10 +59,6 @@ abstract class SpawningCondition<T : SpawningContext> {
|
||||
var isThundering: Boolean? = null
|
||||
var timeRange: TimeRange? = null
|
||||
var structures: MutableList<Either<ResourceLocation, TagKey<Structure>>>? = null
|
||||
var minLureLevel: Int? = null
|
||||
var maxLureLevel: Int? = null
|
||||
var bait: ResourceLocation? = null
|
||||
var rodType: ResourceLocation? = null
|
||||
var isSlimeChunk: Boolean? = null
|
||||
|
||||
@Transient
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ class BestSpawnerConfig {
|
||||
val buckets = mutableListOf(
|
||||
SpawnBucket("common", 93.8F),
|
||||
SpawnBucket("uncommon", 5F),
|
||||
SpawnBucket("rare", 1.0F),
|
||||
SpawnBucket("rare", 0.5F),
|
||||
SpawnBucket("ultra-rare", 0.2F)
|
||||
)
|
||||
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ abstract class JsonBackedPlayerDataStoreBackend<T : InstancedPlayerData>(
|
||||
override fun load(uuid: UUID): T {
|
||||
val playerFile = filePath(uuid)
|
||||
playerFile.parentFile.mkdirs()
|
||||
return if (playerFile.exists()) {
|
||||
return if (playerFile.exists() && playerFile.length() > 0L) {
|
||||
gson.fromJson(BufferedReader(FileReader(playerFile)), classToken).also {
|
||||
// Resolves old data that's missing new properties
|
||||
val newProps = it::class.memberProperties.filterIsInstance<KMutableProperty<*>>().filter { member -> member.getter.call(it) == null }
|
||||
|
||||
+2
-2
@@ -37,11 +37,11 @@ abstract class NbtBackedPlayerData<T : InstancedPlayerData>(
|
||||
override fun load(uuid: UUID): T {
|
||||
val playerFile = filePath(uuid)
|
||||
playerFile.parentFile.mkdirs()
|
||||
return if (playerFile.exists()) {
|
||||
return if (playerFile.exists() && playerFile.length() > 0L) {
|
||||
val input = NbtIo.read(playerFile.toPath())
|
||||
val decodeResult = NbtOps.INSTANCE.withDecoder(codec).apply(input)
|
||||
decodeResult.getPartialOrThrow {
|
||||
Cobblemon.LOGGER.error("Error decoding pokedex for player uuid ${uuid}")
|
||||
Cobblemon.LOGGER.error("Error decoding $subfolder for player uuid $uuid")
|
||||
Cobblemon.LOGGER.error(it)
|
||||
throw UnsupportedOperationException()
|
||||
}.first
|
||||
|
||||
@@ -27,7 +27,7 @@ import net.minecraft.world.phys.Vec3
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Responsible for managing [BattleChallenge]s and initiating PVP [PokemonBattle]s.
|
||||
* Responsible for managing [BattleChallenge]s and initiating PVP [com.cobblemon.mod.common.api.battles.model.PokemonBattle]s.
|
||||
*
|
||||
* @author Segfault Guy, JazzMcNade
|
||||
* @since October 28th, 2024
|
||||
@@ -122,7 +122,7 @@ object ChallengeManager : RequestManager<ChallengeManager.BattleChallenge>() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun isValidInteraction(player: ServerPlayer, target: ServerPlayer) = player.canInteractWith(target, Cobblemon.config.BattlePvPMaxDistance)
|
||||
override fun isValidInteraction(player: ServerPlayer, target: ServerPlayer) = player.canInteractWith(target, Cobblemon.config.battlePvPMaxDistance)
|
||||
|
||||
override fun canAccept(request: BattleChallenge): Boolean {
|
||||
if (request is MultiBattleChallenge) {
|
||||
@@ -132,7 +132,7 @@ object ChallengeManager : RequestManager<ChallengeManager.BattleChallenge>() {
|
||||
if (existingReceiverTeam == null || existingSenderTeam == null) {
|
||||
request.notifySender(true, "error.missing_team")
|
||||
request.notifyReceiver(true, "error.missing_team")
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
val players = existingReceiverTeam.teamPlayers + existingSenderTeam.teamPlayers
|
||||
|
||||
@@ -54,7 +54,7 @@ object ShowdownInterpreter {
|
||||
}
|
||||
|
||||
listOf(
|
||||
"player", "teamsize", "gametype", "gen", "tier", "rated", "clearpoke", "poke", "teampreview", "start", "rule", "t:", "", "capture"
|
||||
"player", "teamsize", "gametype", "gen", "tier", "rated", "clearpoke", "poke", "teampreview", "start", "rule", "t:", "", "capture", "-anim"
|
||||
).forEach { updateInstructionParser[it] = { _, _, _, _ -> IgnoredInstruction() } }
|
||||
|
||||
updateInstructionParser["-ability"] = { _, instructionSet, message, _ -> AbilityInstruction(instructionSet, message) }
|
||||
|
||||
+2
-1
@@ -63,7 +63,8 @@ class ActivateInstruction(val instructionSet: InstructionSet, val message: Battl
|
||||
val context = ActionEffectContext(
|
||||
actionEffect = actionEffect,
|
||||
runtime = runtime,
|
||||
providers = providers
|
||||
providers = providers,
|
||||
level = battle.players.firstOrNull()?.level()
|
||||
)
|
||||
this.future = actionEffect.run(context)
|
||||
holds = context.holds // Reference so future things can check on this action effect's holds
|
||||
|
||||
+2
-1
@@ -56,7 +56,8 @@ class BoostInstruction(battle: PokemonBattle, val message: BattleMessage, val is
|
||||
val context = ActionEffectContext(
|
||||
actionEffect = actionEffect,
|
||||
runtime = runtime,
|
||||
providers = providers
|
||||
providers = providers,
|
||||
level = battle.players.firstOrNull()?.level()
|
||||
)
|
||||
this.future = actionEffect.run(context)
|
||||
holds = context.holds // Reference so future things can check on this action effect's holds
|
||||
|
||||
+2
-1
@@ -52,7 +52,8 @@ class CantInstruction(val message: BattleMessage): ActionEffectInstruction {
|
||||
val context = ActionEffectContext(
|
||||
actionEffect = actionEffect,
|
||||
runtime = runtime,
|
||||
providers = providers
|
||||
providers = providers,
|
||||
level = battle.players.firstOrNull()?.level()
|
||||
)
|
||||
this.future = actionEffect.run(context)
|
||||
holds = context.holds // Reference so future things can check on this action effect's holds
|
||||
|
||||
+2
-1
@@ -114,7 +114,8 @@ class DamageInstruction(
|
||||
val context = ActionEffectContext(
|
||||
actionEffect = actionEffect,
|
||||
runtime = runtime,
|
||||
providers = providers
|
||||
providers = providers,
|
||||
level = battle.players.firstOrNull()?.level()
|
||||
)
|
||||
this.future = actionEffect.run(context)
|
||||
holds = context.holds // Reference so future things can check on this action effect's holds
|
||||
|
||||
+2
-1
@@ -102,7 +102,8 @@ class MoveInstruction(
|
||||
val context = ActionEffectContext(
|
||||
actionEffect = actionEffect,
|
||||
runtime = runtime,
|
||||
providers = providers
|
||||
providers = providers,
|
||||
level = battle.players.firstOrNull()?.level()
|
||||
)
|
||||
|
||||
val subsequentInstructions = instructionSet.findInstructionsCausedBy(this)
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.properties.BattleCloneProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import java.util.UUID
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
|
||||
@@ -35,7 +36,8 @@ open class BattlePokemon(
|
||||
lateinit var actor: BattleActor
|
||||
companion object {
|
||||
fun safeCopyOf(pokemon: Pokemon): BattlePokemon {
|
||||
val effectedPokemon = pokemon.clone()
|
||||
//TOOD figure out a closer registry access (might have to break some method signatures for this (1.7?)
|
||||
val effectedPokemon = pokemon.clone(registryAccess = server()?.registryAccess() ?: throw IllegalStateException("No registry access available"))
|
||||
BattleCloneProperty.isBattleClone().apply(effectedPokemon)
|
||||
UncatchableProperty.uncatchable().apply(effectedPokemon)
|
||||
return BattlePokemon(
|
||||
|
||||
@@ -26,6 +26,7 @@ import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.world.InteractionHand
|
||||
@@ -54,7 +55,7 @@ import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
|
||||
class BerryBlock(private val berryIdentifier: ResourceLocation, settings: Properties) : BaseEntityBlock(settings), BonemealableBlock, Mulchable {
|
||||
class BerryBlock(private val berryIdentifier: ResourceLocation, settings: Properties) : BaseEntityBlock(settings), BonemealableBlock, Mulchable, ShearableBlock {
|
||||
|
||||
private val lookupDirections = setOf(Direction.NORTH, Direction.EAST, Direction.WEST, Direction.SOUTH)
|
||||
|
||||
@@ -186,12 +187,11 @@ class BerryBlock(private val berryIdentifier: ResourceLocation, settings: Proper
|
||||
if (player.getItemInHand(InteractionHand.MAIN_HAND).`is`(Items.BONE_MEAL) && !this.isMaxAge(state)) {
|
||||
return InteractionResult.PASS
|
||||
} else if (this.isMaxAge(state)) {
|
||||
val blockEntity = world.getBlockEntity(pos) as? BerryBlockEntity ?: return InteractionResult.PASS
|
||||
blockEntity.harvest(world, state, pos, player).forEach { drop ->
|
||||
Block.popResource(world, pos, drop)
|
||||
return if (harvestBerry(world, state, pos, player)) {
|
||||
InteractionResult.sidedSuccess(world.isClientSide)
|
||||
} else {
|
||||
InteractionResult.PASS
|
||||
}
|
||||
world.playSound(null, pos, CobblemonSounds.BERRY_HARVEST, SoundSource.BLOCKS, 0.4F, 1F)
|
||||
return InteractionResult.sidedSuccess(world.isClientSide)
|
||||
}
|
||||
return super.useWithoutItem(state, world, pos, player, blockHitResult)
|
||||
}
|
||||
@@ -334,4 +334,19 @@ class BerryBlock(private val berryIdentifier: ResourceLocation, settings: Proper
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun attemptShear(world: Level, state: BlockState, pos: BlockPos, successCallback: () -> Unit): Boolean {
|
||||
return if (this.isMaxAge(state)) {
|
||||
harvestBerry(world, state, pos)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
private fun harvestBerry(world: Level, state: BlockState, pos: BlockPos, player: Player? = null): Boolean {
|
||||
val blockEntity = world.getBlockEntity(pos) as? BerryBlockEntity ?: return false
|
||||
blockEntity.harvest(world, state, pos, player).forEach { drop ->
|
||||
Block.popResource(world, pos, drop)
|
||||
}
|
||||
world.playSound(null, pos, SoundEvents.SHEEP_SHEAR, SoundSource.BLOCKS, 1F, 1F)
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -225,7 +225,7 @@ class BerryBlockEntity(pos: BlockPos, state: BlockState) : BlockEntity(Cobblemon
|
||||
* @param player The [Player] harvesting the tree.
|
||||
* @return The resulting [ItemStack]s to be dropped.
|
||||
*/
|
||||
fun harvest(world: Level, state: BlockState, pos: BlockPos, player: Player): Collection<ItemStack> {
|
||||
fun harvest(world: Level, state: BlockState, pos: BlockPos, player: Player?): Collection<ItemStack> {
|
||||
val drops = arrayListOf<ItemStack>()
|
||||
val unique = this.growthPoints.groupingBy { it }.eachCount()
|
||||
unique.forEach { (identifier, amount) ->
|
||||
@@ -248,6 +248,10 @@ class BerryBlockEntity(pos: BlockPos, state: BlockState) : BlockEntity(Cobblemon
|
||||
return drops
|
||||
}
|
||||
|
||||
fun harvest(world: Level, state: BlockState, pos: BlockPos): Collection<ItemStack>{
|
||||
return harvest(world, state, pos, null);
|
||||
}
|
||||
|
||||
override fun loadAdditional(nbt: CompoundTag, registryLookup: HolderLookup.Provider) {
|
||||
this.berryIdentifier = ResourceLocation.parse(nbt.getString(BERRY).takeIf { it.isNotBlank() } ?: "cobblemon:pecha")
|
||||
this.wasLoading = true
|
||||
@@ -330,7 +334,7 @@ class BerryBlockEntity(pos: BlockPos, state: BlockState) : BlockEntity(Cobblemon
|
||||
this.setChanged()
|
||||
}
|
||||
|
||||
private fun refresh(world: Level, pos: BlockPos, state: BlockState, player: Player) {
|
||||
private fun refresh(world: Level, pos: BlockPos, state: BlockState, player: Player?) {
|
||||
val newState = state.setValue(BerryBlock.AGE, 3)
|
||||
world.setBlock(pos, newState, UPDATE_CLIENTS)
|
||||
world.gameEvent(player, GameEvent.BLOCK_CHANGE, pos)
|
||||
|
||||
+1
-1
@@ -118,7 +118,7 @@ class RestorationTankBlockEntity(
|
||||
}
|
||||
|
||||
override fun getSlotsForFace(side: Direction): IntArray {
|
||||
return if (side == Direction.DOWN) intArrayOf(0, 1, 2, 3, 4, 5, 6, 7) else intArrayOf(-1)
|
||||
return if (side == Direction.DOWN) intArrayOf(0, 1, 2, 3, 4, 5, 6, 7) else intArrayOf()
|
||||
}
|
||||
|
||||
override fun canPlaceItemThroughFace(slot: Int, stack: ItemStack, direction: Direction?): Boolean {
|
||||
|
||||
+1
-1
@@ -155,7 +155,7 @@ class FossilMultiblockStructure (
|
||||
|
||||
// Reclaim the last fossil from the machine if their hand is empty
|
||||
if (player.getItemInHand(InteractionHand.MAIN_HAND).isEmpty) {
|
||||
if(!this.isRunning() && this.hasCreatedPokemon) {
|
||||
if(!this.isRunning() && !this.hasCreatedPokemon) {
|
||||
if (fossilInventory.isEmpty()) {
|
||||
return InteractionResult.CONSUME
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ object CobblemonClient {
|
||||
|
||||
@JvmStatic
|
||||
val builtinResourcePacks = listOf<CobblemonResourcePack>(
|
||||
CobblemonResourcePack(id = "adorncompatibility", name = "Adorn Compatibility", activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED, neededMods = setOf("adorn")),
|
||||
CobblemonResourcePack(id = "adorncompatibility", name = "Adorn Compatibility", activationBehaviour = ResourcePackActivationBehaviour.ALWAYS_ENABLED, neededMods = setOf("adorn")),
|
||||
CobblemonResourcePack(id = "gyaradosjump", name = "Gyarados Jump Patterns", activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED),
|
||||
CobblemonResourcePack(id = "regionbiasforms", name = "Region Bias Forms", activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED),
|
||||
CobblemonResourcePack(id = "uniqueshinyforms", name = "Shinies for Magikarp Jump", activationBehaviour = ResourcePackActivationBehaviour.NORMAL),
|
||||
|
||||
+9
-4
@@ -14,6 +14,7 @@ import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.entity.PokemonSideDelegate
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addEntityFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunctions
|
||||
import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
@@ -43,8 +44,6 @@ import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
companion object {
|
||||
@@ -193,15 +192,18 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
val ballType =
|
||||
currentEntity.pokemon.caughtBall.name.path.toLowerCase().replace("_", "")
|
||||
val mode = if (currentEntity.isBattling) "battle" else "casual"
|
||||
//TODO: A lot of this is probably able to be simplified by just using a single particle with events
|
||||
//Do it in the particle file, not code.
|
||||
val sendflash =
|
||||
BedrockParticleOptionsRepository.getEffect(cobblemonResource("${ballType}/${mode}/sendflash"))
|
||||
sendflash?.let { effect ->
|
||||
val wrapper = MatrixWrapper()
|
||||
val matrix = PoseStack()
|
||||
matrix.translate(newPos.x, newPos.y, newPos.z)
|
||||
//This could potentially cause strange issues if the matrix has a translation component here.
|
||||
wrapper.updateMatrix(matrix.last().pose())
|
||||
wrapper.updatePosition(Vec3(newPos.x, newPos.y, newPos.z))
|
||||
val world = Minecraft.getInstance().level ?: return@let
|
||||
ParticleStorm(effect, wrapper, world).spawn()
|
||||
ParticleStorm(effect, wrapper, wrapper, world).spawn()
|
||||
val ballsparks =
|
||||
BedrockParticleOptionsRepository.getEffect(cobblemonResource("${ballType}/${mode}/ballsparks"))
|
||||
val ballsendsparkle =
|
||||
@@ -212,6 +214,7 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
ParticleStorm(
|
||||
effect,
|
||||
wrapper,
|
||||
wrapper,
|
||||
world
|
||||
).spawn()
|
||||
}
|
||||
@@ -219,6 +222,7 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
ParticleStorm(
|
||||
effect,
|
||||
wrapper,
|
||||
wrapper,
|
||||
world
|
||||
).spawn()
|
||||
}
|
||||
@@ -229,6 +233,7 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
ParticleStorm(
|
||||
effect,
|
||||
wrapper,
|
||||
wrapper,
|
||||
world
|
||||
).spawn()
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ class PartyOverlay : Gui(Minecraft.getInstance()) {
|
||||
if (!screenExemptions.contains(minecraft.screen?.javaClass as Class<out Screen>))
|
||||
return
|
||||
}
|
||||
if (minecraft.debugOverlay.showDebugScreen()) {
|
||||
if (minecraft.options.hideGui || minecraft.debugOverlay.showDebugScreen()) {
|
||||
return
|
||||
}
|
||||
// Hiding if toggled via Keybind
|
||||
|
||||
+10
-2
@@ -23,6 +23,7 @@ import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.ContainerObjectSelectionList
|
||||
import net.minecraft.client.gui.components.EditBox
|
||||
import net.minecraft.client.gui.components.Tooltip
|
||||
import net.minecraft.client.gui.components.WidgetTooltipHolder
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener
|
||||
import net.minecraft.client.gui.narration.NarratableEntry
|
||||
|
||||
@@ -124,6 +125,9 @@ class ConfigVariableList(
|
||||
var textValue = value
|
||||
var booleanValue = value.let { it.toDoubleOrNull() == 1.0 || it.toBooleanStrictOrNull() == true }
|
||||
|
||||
val tooltip = Tooltip.create(variable.description)
|
||||
val tooltipHolder = WidgetTooltipHolder().also { it.set(tooltip) }
|
||||
|
||||
val editBox = EditBox(
|
||||
client.font,
|
||||
parent.listX,
|
||||
@@ -133,7 +137,6 @@ class ConfigVariableList(
|
||||
variable.displayName,
|
||||
).also {
|
||||
it.isBordered = false
|
||||
it.tooltip = Tooltip.create(variable.description)
|
||||
it.height = SLOT_HEIGHT - 16
|
||||
it.setMaxLength(250)
|
||||
it.value = value
|
||||
@@ -145,6 +148,7 @@ class ConfigVariableList(
|
||||
it.setFilter { value -> value.toDoubleOrNull() != null || value.isBlank() || value == "." || value == "-" }
|
||||
}
|
||||
}
|
||||
|
||||
val toggleButton = NPCEditorButton(
|
||||
parent.listX.toFloat(),
|
||||
parent.listY + 6F,
|
||||
@@ -156,7 +160,7 @@ class ConfigVariableList(
|
||||
parent.parent.dto.variables[variable.variableName] = if (booleanValue) "1" else "0"
|
||||
(it as NPCEditorButton).cycleButtonState = booleanValue
|
||||
}.also {
|
||||
it.tooltip = Tooltip.create(variable.description)
|
||||
it.tooltip = tooltip
|
||||
}
|
||||
|
||||
init {
|
||||
@@ -211,6 +215,10 @@ class ConfigVariableList(
|
||||
editBox.x = x + 4
|
||||
editBox.y = y + 18
|
||||
editBox.render(context, mouseX, mouseY, partialTicks)
|
||||
|
||||
// Manually renders the tooltip for the edit box because disabling its border messes everything up
|
||||
val isEditBoxHovered = mouseX >= x && mouseX <= x + SLOT_WIDTH - 1 && mouseY >= y + 15 && mouseY <= y + 15 + 14
|
||||
tooltipHolder.refreshTooltipForNextRenderPass(isEditBoxHovered, editBox.isFocused, editBox.rectangle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -192,7 +192,8 @@ class PasturePokemonScrollList(
|
||||
partialTicks: Float
|
||||
) {
|
||||
val x = rowLeft - 4
|
||||
val y = rowTop
|
||||
val y = rowTop + 2
|
||||
|
||||
val matrixStack = context.pose()
|
||||
blitk(
|
||||
matrixStack = matrixStack,
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.gui.pokedex
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
@@ -411,6 +412,13 @@ class PokedexGUI private constructor(
|
||||
var entries = filteredPokedex
|
||||
.flatMap { it.getEntries() }
|
||||
|
||||
if (Cobblemon.config.hideUnimplementedPokemonInThePokedex) {
|
||||
entries = entries.filter {
|
||||
val species = PokemonSpecies.getByIdentifier(it.speciesId) ?: return@filter false
|
||||
return@filter species.implemented
|
||||
}
|
||||
}
|
||||
|
||||
for (filter in getFilters()) {
|
||||
entries = entries.filter { filter.test(it) }
|
||||
}
|
||||
|
||||
+2
@@ -595,6 +595,8 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
|
||||
}
|
||||
|
||||
private fun switchForm(nextIndex: Boolean) {
|
||||
selectedPoseIndex = 0
|
||||
|
||||
if (nextIndex) {
|
||||
if (selectedFormIndex < visibleForms.lastIndex) selectedFormIndex++
|
||||
else selectedFormIndex = 0
|
||||
|
||||
+6
-3
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.SoundlessWidget
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.common.reformatNatureTextIfMinted
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.settings.ServerSettings
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
@@ -164,8 +165,9 @@ class InfoWidget(
|
||||
val experience = pokemon.experience.toString().text()
|
||||
val experienceForThisLevel =
|
||||
pokemon.experience - if (pokemon.level == 1) 0 else pokemon.experienceGroup.getExperience(pokemon.level)
|
||||
val nextLevel = (pokemon.level + 1).coerceAtMost(ServerSettings.maxPokemonLevel)
|
||||
val experienceToNext =
|
||||
pokemon.experienceGroup.getExperience(pokemon.level + 1) - pokemon.experienceGroup.getExperience(pokemon.level)
|
||||
pokemon.experienceGroup.getExperience(nextLevel) - pokemon.experienceGroup.getExperience(pokemon.level)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
@@ -176,10 +178,11 @@ class InfoWidget(
|
||||
shadow = true
|
||||
)
|
||||
|
||||
val experienceToNextText = Component.literal(experienceToNext.toString())
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = experienceToNext.toString().text(),
|
||||
x = (x + 127) - (mcFont.width(experienceToNext.toString().text()) * smallTextScale),
|
||||
text = experienceToNextText,
|
||||
x = (x + 127) - (mcFont.width(experienceToNextText) * smallTextScale),
|
||||
y = y + 137,
|
||||
scale = smallTextScale,
|
||||
shadow = true
|
||||
|
||||
+37
-3
@@ -8,18 +8,52 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.net.effect
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.client.ClientMoLangFunctions.setupClient
|
||||
import com.cobblemon.mod.common.client.particle.BedrockParticleOptionsRepository
|
||||
import com.cobblemon.mod.common.client.particle.ParticleStorm
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.Entity
|
||||
|
||||
object SpawnSnowstormEntityParticleHandler : ClientNetworkPacketHandler<SpawnSnowstormEntityParticlePacket> {
|
||||
override fun handle(packet: SpawnSnowstormEntityParticlePacket, client: Minecraft) {
|
||||
val world = Minecraft.getInstance().level ?: return
|
||||
val effect = BedrockParticleOptionsRepository.getEffect(packet.effectId) ?: return
|
||||
val entity = world.getEntity(packet.entityId) as? LivingEntity ?: return
|
||||
ParticleStorm.createAtEntity(world, effect, entity, packet.locator).forEach(ParticleStorm::spawn)
|
||||
val sourceEntity = world.getEntity(packet.sourceEntityId) as? PosableEntity ?: return
|
||||
val targetedEntity = packet.targetedEntityId?.let { world.getEntity(it) }
|
||||
sourceEntity as Entity
|
||||
val sourceState = sourceEntity.delegate as PosableState
|
||||
val targetState = (targetedEntity as? PosableEntity)?.delegate as? PosableState
|
||||
val sourceLocators = packet.sourceLocators.firstNotNullOfOrNull { sourceState.getMatchingLocators(it).takeIf { it.isNotEmpty() } } ?: return
|
||||
val targetedLocator = packet.targetLocators?.firstOrNull { targetState?.getMatchingLocators(it)?.isNotEmpty() == true }
|
||||
val rootMatrix = sourceState.locatorStates["root"]!!
|
||||
|
||||
sourceLocators.forEach { locator ->
|
||||
val locatorMatrix = sourceState.locatorStates[locator]!!
|
||||
|
||||
val particleMatrix = effect.emitter.space.initializeEmitterMatrix(rootMatrix, locatorMatrix)
|
||||
val particleRuntime = MoLangRuntime().setup().setupClient()
|
||||
particleRuntime.environment.query.addFunction("entity") { sourceState.runtime.environment.query }
|
||||
|
||||
val storm = ParticleStorm(
|
||||
effect = effect,
|
||||
emitterSpaceMatrix = particleMatrix,
|
||||
locatorSpaceMatrix = locatorMatrix,
|
||||
world = world,
|
||||
runtime = particleRuntime,
|
||||
sourceVelocity = { sourceEntity.deltaMovement },
|
||||
sourceAlive = { !sourceEntity.isRemoved },
|
||||
sourceVisible = { !sourceEntity.isInvisible },
|
||||
targetPos = if (targetedEntity != null) { { targetedLocator?.let { targetState?.locatorStates?.get(it) }?.getOrigin() ?: targetedEntity.position() } } else null,
|
||||
entity = sourceEntity
|
||||
)
|
||||
|
||||
storm.spawn()
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-1
@@ -11,13 +11,19 @@ package com.cobblemon.mod.common.client.net.effect
|
||||
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.client.particle.BedrockParticleOptionsRepository
|
||||
import com.cobblemon.mod.common.client.particle.ParticleStorm
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
|
||||
import net.minecraft.client.Minecraft
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
|
||||
object SpawnSnowstormParticleHandler : ClientNetworkPacketHandler<SpawnSnowstormParticlePacket> {
|
||||
override fun handle(packet: SpawnSnowstormParticlePacket, client: Minecraft) {
|
||||
val wrapper = MatrixWrapper()
|
||||
val matrix = PoseStack()
|
||||
wrapper.updateMatrix(matrix.last().pose())
|
||||
wrapper.updatePosition(packet.position)
|
||||
val world = Minecraft.getInstance().level ?: return
|
||||
val effect = BedrockParticleOptionsRepository.getEffect(packet.effectId) ?: return
|
||||
ParticleStorm.createAtPosition(world, effect, packet.position).spawn()
|
||||
ParticleStorm(effect, wrapper, wrapper, world).spawn()
|
||||
}
|
||||
}
|
||||
+1
@@ -18,6 +18,7 @@ object ServerSettingsPacketHandler : ClientNetworkPacketHandler<ServerSettingsPa
|
||||
ServerSettings.preventCompletePartyDeposit = packet.preventCompletePartyDeposit
|
||||
ServerSettings.displayEntityLevelLabel = packet.displayEntityLevelLabel
|
||||
ServerSettings.displayEntityNameLabel = packet.displayEntityNameLabel
|
||||
ServerSettings.maxPokemonLevel = packet.maxPokemonLevel
|
||||
}
|
||||
|
||||
}
|
||||
+9
-5
@@ -31,12 +31,16 @@ object BedrockParticleOptionsRepository {
|
||||
fun loadEffects(resourceManager: ResourceManager) {
|
||||
LOGGER.info("Loading particle effects...")
|
||||
effects.clear()
|
||||
|
||||
resourceManager.listResources("bedrock/particles") { path -> path.endsWith(".particle.json") }.forEach { identifier, resource ->
|
||||
resource.open().use { stream ->
|
||||
val json = String(stream.readAllBytes(), StandardCharsets.UTF_8)
|
||||
val effect = SnowstormParticleReader.loadEffect(GSON.fromJson(json, JsonObject::class.java))
|
||||
effects[effect.id] = effect
|
||||
try {
|
||||
resource.open().use { stream ->
|
||||
val json = String(stream.readAllBytes(), StandardCharsets.UTF_8)
|
||||
val effect = SnowstormParticleReader.loadEffect(GSON.fromJson(json, JsonObject::class.java))
|
||||
effects[effect.id] = effect
|
||||
}
|
||||
}
|
||||
catch (e: Exception) {
|
||||
LOGGER.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.particle
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.struct.VariableStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
@@ -22,8 +23,10 @@ import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.particle.SnowstormParticleOptions
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.math.geometry.transformDirection
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.multiplayer.ClientLevel
|
||||
import net.minecraft.client.particle.NoRenderParticle
|
||||
@@ -42,15 +45,21 @@ import net.minecraft.world.level.Level
|
||||
*/
|
||||
class ParticleStorm(
|
||||
val effect: BedrockParticleOptions,
|
||||
val matrixWrapper: MatrixWrapper,
|
||||
val emitterSpaceMatrix: MatrixWrapper,
|
||||
//This is a mildly inaccurate name. This matrix is basically the matrix we want to peg our movement to.
|
||||
//Often times, this is the locator matrix, but sometimes, when we want the emitter to NOT track the locator, this value is the same obj as emitterSpaceMatrix.
|
||||
//Currently only position is tracked. Ideally we would come up with a way to configure whether the emitter tracks any combination of position/rotation (or neither)
|
||||
//on this matrix.
|
||||
val locatorSpaceMatrix: MatrixWrapper,
|
||||
val world: ClientLevel,
|
||||
val sourceVelocity: () -> Vec3 = { Vec3.ZERO },
|
||||
val sourceAlive: () -> Boolean = { true },
|
||||
val sourceVisible: () -> Boolean = { true },
|
||||
val targetPos: (() -> Vec3)? = null,
|
||||
val onDespawn: () -> Unit = {},
|
||||
val runtime: MoLangRuntime = MoLangRuntime(),
|
||||
val entity: Entity? = null
|
||||
): NoRenderParticle(world, matrixWrapper.getOrigin().x, matrixWrapper.getOrigin().y, matrixWrapper.getOrigin().z) {
|
||||
val entity: Entity? = null,
|
||||
): NoRenderParticle(world, emitterSpaceMatrix.getOrigin().x, emitterSpaceMatrix.getOrigin().y, emitterSpaceMatrix.getOrigin().z) {
|
||||
fun spawn() {
|
||||
if (entity != null) {
|
||||
runtime.environment.query
|
||||
@@ -69,6 +78,9 @@ class ParticleStorm(
|
||||
}
|
||||
if (entity is PosableEntity) {
|
||||
runtime.environment.query.addFunction("entity") { entity.struct }
|
||||
if (targetPos != null) {
|
||||
addAttackingFunctions(targetPos)
|
||||
}
|
||||
} else if (entity is Player) {
|
||||
runtime.environment.query.addFunction("entity") { entity.asMoLangValue() }
|
||||
}
|
||||
@@ -83,6 +95,43 @@ class ParticleStorm(
|
||||
Minecraft.getInstance().particleEngine.add(this)
|
||||
}
|
||||
|
||||
fun addAttackingFunctions(destinationPosSupplier: (() -> Vec3)) {
|
||||
runtime.environment.query.addFunction("target_deltax") { params ->
|
||||
DoubleValue(distanceTo(destinationPosSupplier.invoke()).x)
|
||||
}
|
||||
runtime.environment.query.addFunction("target_deltay") { params ->
|
||||
DoubleValue(distanceTo(destinationPosSupplier.invoke()).y * -1)
|
||||
}
|
||||
runtime.environment.query.addFunction("target_deltaz") { params ->
|
||||
DoubleValue(distanceTo(destinationPosSupplier.invoke()).z)
|
||||
}
|
||||
runtime.environment.query.addFunction("target_distance") { params ->
|
||||
DoubleValue(distanceTo(destinationPosSupplier.invoke()).length())
|
||||
}
|
||||
|
||||
runtime.environment.setSimpleVariable("target_deltax", DoubleValue(distanceTo(destinationPosSupplier.invoke()).x))
|
||||
runtime.environment.setSimpleVariable("target_deltay", DoubleValue(distanceTo(destinationPosSupplier.invoke()).y))
|
||||
runtime.environment.setSimpleVariable("target_deltaz", DoubleValue(distanceTo(destinationPosSupplier.invoke()).z))
|
||||
runtime.environment.setSimpleVariable("target_distance", DoubleValue(distanceTo(destinationPosSupplier.invoke()).length()))
|
||||
}
|
||||
|
||||
//These are variables that need to be different per particle instance
|
||||
fun lockParticleVars(struct: VariableStruct) {
|
||||
val destinationPos = targetPos?.invoke() ?: return
|
||||
struct.setDirectly(
|
||||
"target_deltax", DoubleValue(distanceTo(destinationPos).x)
|
||||
)
|
||||
struct.setDirectly(
|
||||
"target_deltay", DoubleValue(distanceTo(destinationPos).y * -1)
|
||||
)
|
||||
struct.setDirectly(
|
||||
"target_deltaz", DoubleValue(distanceTo(destinationPos).z),
|
||||
)
|
||||
struct.setDirectly(
|
||||
"target_distance", DoubleValue(distanceTo(destinationPos).length()),
|
||||
)
|
||||
}
|
||||
|
||||
fun getX() = x
|
||||
fun getY() = y
|
||||
fun getZ() = z
|
||||
@@ -108,7 +157,7 @@ class ParticleStorm(
|
||||
val matrix = PoseStack()
|
||||
matrix.translate(position.x, position.y, position.z)
|
||||
wrapper.updateMatrix(matrix.last().pose())
|
||||
return ParticleStorm(effect, wrapper, world)
|
||||
return ParticleStorm(effect, wrapper, wrapper, world)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,7 +173,8 @@ class ParticleStorm(
|
||||
particleRuntime.environment.query.addFunction("entity") { state.runtime.environment.query }
|
||||
ParticleStorm(
|
||||
effect = effect,
|
||||
matrixWrapper = matrixWrapper,
|
||||
emitterSpaceMatrix = matrixWrapper,
|
||||
locatorSpaceMatrix = matrixWrapper,
|
||||
world = world,
|
||||
runtime = particleRuntime,
|
||||
sourceVelocity = { entity.deltaMovement },
|
||||
@@ -141,7 +191,8 @@ class ParticleStorm(
|
||||
return listOf(
|
||||
ParticleStorm(
|
||||
effect = effect,
|
||||
matrixWrapper = matrixWrapper,
|
||||
emitterSpaceMatrix = matrixWrapper,
|
||||
locatorSpaceMatrix = matrixWrapper,
|
||||
world = world,
|
||||
runtime = particleRuntime,
|
||||
sourceVelocity = { entity.deltaMovement },
|
||||
@@ -192,7 +243,7 @@ class ParticleStorm(
|
||||
return
|
||||
}
|
||||
|
||||
val pos = matrixWrapper.getOrigin()
|
||||
val pos = locatorSpaceMatrix.getOrigin()
|
||||
xo = x
|
||||
yo = y
|
||||
zo = z
|
||||
@@ -201,6 +252,9 @@ class ParticleStorm(
|
||||
y = pos.y
|
||||
z = pos.z
|
||||
|
||||
//Keeps emitter attached to locator
|
||||
emitterSpaceMatrix.updatePosition(locatorSpaceMatrix.getOrigin())
|
||||
|
||||
val oldDistanceTravelled = distanceTravelled
|
||||
distanceTravelled += Vec3(x - xo, y - yo, z - zo).length().toFloat()
|
||||
|
||||
@@ -255,7 +309,12 @@ class ParticleStorm(
|
||||
contextStorm = null
|
||||
}
|
||||
|
||||
fun transformPosition(position: Vec3): Vec3 = matrixWrapper.transformPosition(position)
|
||||
fun transformPosition(position: Vec3): Vec3 = emitterSpaceMatrix.transformPosition(position)
|
||||
|
||||
fun transformDirection(direction: Vec3): Vec3 = matrixWrapper.matrix.transformDirection(direction)
|
||||
fun transformDirection(direction: Vec3): Vec3 = emitterSpaceMatrix.matrix.transformDirection(direction)
|
||||
|
||||
//Gets distance between emitter pos and destination pos in emitter space
|
||||
fun distanceTo(destinationPos: Vec3): Vec3 {
|
||||
return emitterSpaceMatrix.transformWorldToParticle(Vec3(x, y, z)).subtract(emitterSpaceMatrix.transformWorldToParticle(destinationPos))
|
||||
}
|
||||
}
|
||||
@@ -38,4 +38,6 @@ class MatrixWrapper {
|
||||
return position.add(matrix.getOrigin())
|
||||
}
|
||||
fun transformPosition(position: Vec3) = this.position.add(matrix.transformPosition(position))
|
||||
fun transformWorldToParticle(position: Vec3) = Matrix4f(matrix).invertAffine().transformPosition(position.subtract(this.position))
|
||||
fun clone() = MatrixWrapper().updateMatrix(matrix).updatePosition(position)
|
||||
}
|
||||
+49
-41
@@ -8,12 +8,16 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.ModAPI
|
||||
import com.cobblemon.mod.common.api.snowstorm.ParticleMaterial
|
||||
import com.cobblemon.mod.common.api.snowstorm.UVDetails
|
||||
import com.cobblemon.mod.common.client.particle.ParticleStorm
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.math.geometry.transformDirection
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.resolveDouble
|
||||
import com.mojang.blaze3d.platform.GlStateManager
|
||||
@@ -37,6 +41,7 @@ import org.joml.AxisAngle4d
|
||||
import org.joml.Quaterniond
|
||||
import org.joml.Vector3d
|
||||
import org.joml.Vector3f
|
||||
import kotlin.random.Random
|
||||
|
||||
class SnowstormParticle(
|
||||
val storm: ParticleStorm,
|
||||
@@ -45,7 +50,10 @@ class SnowstormParticle(
|
||||
y: Double,
|
||||
z: Double,
|
||||
initialVelocity: Vec3,
|
||||
var invisible: Boolean = false
|
||||
//Usually, this will be the storms runtime. But sometimes particles need to have variables different from their emitter, so the VariableStruct will differ
|
||||
val runtime: MoLangRuntime,
|
||||
val matrixWrapper: MatrixWrapper,
|
||||
var invisible: Boolean = false,
|
||||
) : Particle(world, x, y, z) {
|
||||
companion object {
|
||||
const val MAXIMUM_DISTANCE_CHANGE_PER_TICK_FOR_FRICTION = 0.005
|
||||
@@ -59,11 +67,6 @@ class SnowstormParticle(
|
||||
|
||||
var texture = storm.effect.particle.texture
|
||||
|
||||
val random1 = storm.runtime.environment.variable.map["particle_random_1"]
|
||||
val random2 = storm.runtime.environment.variable.map["particle_random_2"]
|
||||
val random3 = storm.runtime.environment.variable.map["particle_random_3"]
|
||||
val random4 = storm.runtime.environment.variable.map["particle_random_4"]
|
||||
|
||||
var localX = x - storm.getX()
|
||||
var localY = y - storm.getY()
|
||||
var localZ = z - storm.getZ()
|
||||
@@ -95,30 +98,25 @@ class SnowstormParticle(
|
||||
|
||||
fun getSpriteFromAtlas(): TextureAtlasSprite {
|
||||
val atlas = Minecraft.getInstance().particleEngine.textureAtlas
|
||||
|
||||
// val field = atlas::class.java.getDeclaredField("sprites")
|
||||
// field.isAccessible = true
|
||||
// val map = field.get(atlas) as Map<Identifier, Sprite>
|
||||
// println(map.keys.joinToString { it.toString() })
|
||||
val sprite = atlas.getSprite(storm.effect.particle.texture)
|
||||
// println(storm.effect.particle.texture)
|
||||
return sprite
|
||||
}
|
||||
|
||||
private fun applyRandoms() {
|
||||
storm.runtime.environment.variable.setDirectly("particle_random_1", random1)
|
||||
storm.runtime.environment.variable.setDirectly("particle_random_2", random2)
|
||||
storm.runtime.environment.variable.setDirectly("particle_random_3", random3)
|
||||
storm.runtime.environment.variable.setDirectly("particle_random_4", random4)
|
||||
//Will having these emitter randoms not equal the real emitter randoms be a problem?
|
||||
runtime.environment.setSimpleVariable("emitter_random_1", DoubleValue(Random.Default.nextDouble()))
|
||||
runtime.environment.setSimpleVariable("emitter_random_2", DoubleValue(Random.Default.nextDouble()))
|
||||
runtime.environment.setSimpleVariable("emitter_random_3", DoubleValue(Random.Default.nextDouble()))
|
||||
runtime.environment.setSimpleVariable("emitter_random_4", DoubleValue(Random.Default.nextDouble()))
|
||||
}
|
||||
|
||||
init {
|
||||
setParticleSpeed(initialVelocity.x, initialVelocity.y, initialVelocity.z)
|
||||
roll = -storm.effect.particle.rotation.getInitialRotation(storm.runtime).toFloat()
|
||||
roll = -storm.effect.particle.rotation.getInitialRotation(runtime).toFloat()
|
||||
oRoll = roll
|
||||
angularVelocity = storm.effect.particle.rotation.getInitialAngularVelocity(storm.runtime)
|
||||
angularVelocity = storm.effect.particle.rotation.getInitialAngularVelocity(runtime)
|
||||
friction = 1F
|
||||
lifetime = (storm.runtime.resolveDouble(storm.effect.particle.maxAge) * 20).toInt()
|
||||
lifetime = (runtime.resolveDouble(storm.effect.particle.maxAge) * 20).toInt()
|
||||
storm.particles.add(this)
|
||||
gravity = 0F
|
||||
particleTextureSheet = if (invisible) NO_RENDER else PARTICLE_SHEET_TRANSLUCENT
|
||||
@@ -140,8 +138,8 @@ class SnowstormParticle(
|
||||
|
||||
applyRandoms()
|
||||
setParticleAgeInRuntime()
|
||||
storm.effect.curves.forEach { it.apply(storm.runtime) }
|
||||
storm.runtime.execute(storm.effect.particle.renderExpressions)
|
||||
storm.effect.curves.forEach { it.apply(runtime) }
|
||||
runtime.execute(storm.effect.particle.renderExpressions)
|
||||
|
||||
// // TODO need to implement the other materials but not sure exactly what they are GL wise
|
||||
when (storm.effect.particle.material) {
|
||||
@@ -173,7 +171,7 @@ class SnowstormParticle(
|
||||
val g = (pos.y + originPos.y - vec3d.y()).toFloat()
|
||||
val h = (pos.z + originPos.z - vec3d.z()).toFloat()
|
||||
val quaternion = storm.effect.particle.cameraMode.getRotation(
|
||||
matrixWrapper = storm.matrixWrapper,
|
||||
matrixWrapper = matrixWrapper,
|
||||
prevAngle = oRoll,
|
||||
angle = roll,
|
||||
deltaTicks = tickDelta,
|
||||
@@ -184,8 +182,8 @@ class SnowstormParticle(
|
||||
cameraPitch = camera.xRot,
|
||||
viewDirection = viewDirection
|
||||
)
|
||||
val xSize = storm.runtime.resolveDouble(storm.effect.particle.sizeX).toFloat() / 1.5.toFloat()
|
||||
val ySize = storm.runtime.resolveDouble(storm.effect.particle.sizeY).toFloat() / 1.5.toFloat()
|
||||
val xSize = runtime.resolveDouble(storm.effect.particle.sizeX).toFloat() / 1.5.toFloat()
|
||||
val ySize = runtime.resolveDouble(storm.effect.particle.sizeY).toFloat() / 1.5.toFloat()
|
||||
|
||||
val particleVertices = arrayOf(
|
||||
Vector3f(xSize, -ySize, 0.0f),
|
||||
@@ -200,8 +198,8 @@ class SnowstormParticle(
|
||||
vertex.add(f, g, h)
|
||||
}
|
||||
|
||||
val uvs = storm.effect.particle.uvMode.get(storm.runtime, age / 20.0, lifetime / 20.0, uvDetails)
|
||||
val colour = storm.effect.particle.tinting.getTint(storm.runtime)
|
||||
val uvs = storm.effect.particle.uvMode.get(runtime, age / 20.0, lifetime / 20.0, uvDetails)
|
||||
val colour = storm.effect.particle.tinting.getTint(runtime)
|
||||
|
||||
val spriteURange = sprite.u1 - sprite.u0
|
||||
val spriteVRange = sprite.v1 - sprite.v0
|
||||
@@ -240,21 +238,21 @@ class SnowstormParticle(
|
||||
|
||||
override fun tick() {
|
||||
if (storm.effect.space.localPosition) {
|
||||
originPos = storm.matrixWrapper.getOrigin()
|
||||
originPos = matrixWrapper.getOrigin()
|
||||
}
|
||||
|
||||
applyRandoms()
|
||||
setParticleAgeInRuntime()
|
||||
storm.effect.curves.forEach { it.apply(storm.runtime) }
|
||||
storm.runtime.execute(storm.effect.particle.updateExpressions)
|
||||
angularVelocity = storm.effect.particle.rotation.getAngularVelocity(storm.runtime, -roll.toDouble(), angularVelocity) / 20
|
||||
storm.effect.curves.forEach { it.apply(runtime) }
|
||||
runtime.execute(storm.effect.particle.updateExpressions)
|
||||
angularVelocity = storm.effect.particle.rotation.getAngularVelocity(runtime, -roll.toDouble(), angularVelocity) / 20
|
||||
|
||||
if (age >= lifetime || storm.runtime.resolveBoolean(storm.effect.particle.killExpression)) {
|
||||
if (age >= lifetime || runtime.resolveBoolean(storm.effect.particle.killExpression)) {
|
||||
runExpirationEvents()
|
||||
remove()
|
||||
return
|
||||
} else {
|
||||
val velocity = storm.effect.particle.motion.getVelocity(storm.runtime, this,
|
||||
val velocity = storm.effect.particle.motion.getVelocity(runtime, this,
|
||||
Vec3(xd, yd, zd)
|
||||
)
|
||||
xd = velocity.x
|
||||
@@ -266,7 +264,7 @@ class SnowstormParticle(
|
||||
}
|
||||
|
||||
viewDirection = storm.effect.particle.viewDirection.getDirection(
|
||||
runtime = storm.runtime,
|
||||
runtime = runtime,
|
||||
lastDirection = viewDirection,
|
||||
currentVelocity = Vec3(xd, yd, zd)
|
||||
).normalize()
|
||||
@@ -282,7 +280,17 @@ class SnowstormParticle(
|
||||
oldAxisRotation = axisRotation
|
||||
prevRotatedLocal = oldAxisRotation.transform(Vector3d(prevLocalX, prevLocalY, prevLocalZ))
|
||||
|
||||
storm.matrixWrapper.matrix.getRotation(axisRotation)
|
||||
//This is a bit of a hack. Technically local rotation is supposed to make it so the particle uses
|
||||
//the emitter's rotation - but we've made it so the emitter doesn't actually follow the locators rotation, only position.
|
||||
//So instead of being bound to the emitter, the particle is actually bound to the locator for local rotation.
|
||||
//If you're messing with this - make sure evo particles still rotate with the pokemon
|
||||
if (storm.effect.space.localRotation) {
|
||||
storm.locatorSpaceMatrix.matrix.getRotation(axisRotation)
|
||||
}
|
||||
else {
|
||||
matrixWrapper.matrix.getRotation(axisRotation)
|
||||
}
|
||||
|
||||
rotatedLocal = axisRotation.transform(Vector3d(prevLocalX, prevLocalY, prevLocalZ))
|
||||
Quaterniond().rotateTo(prevRotatedLocal, rotatedLocal).get(currentRotation)
|
||||
|
||||
@@ -295,7 +303,7 @@ class SnowstormParticle(
|
||||
|
||||
override fun move(dx: Double, dy: Double, dz: Double) {
|
||||
val collision = storm.effect.particle.collision
|
||||
val radius = storm.runtime.resolveDouble(collision.radius)
|
||||
val radius = runtime.resolveDouble(collision.radius)
|
||||
boundingBox = AABB.ofSize(Vec3(x, y, z), radius, radius, radius)
|
||||
if (dx == 0.0 && dy == 0.0 && dz == 0.0) {
|
||||
updatePosition()
|
||||
@@ -306,7 +314,7 @@ class SnowstormParticle(
|
||||
var dy = dy
|
||||
var dz = dz
|
||||
|
||||
if (storm.runtime.resolveBoolean(collision.enabled) && radius > 0.0 && !storm.effect.space.isLocalSpace) {
|
||||
if (runtime.resolveBoolean(collision.enabled) && radius > 0.0 && !storm.effect.space.isLocalSpace) {
|
||||
hasPhysics = true
|
||||
|
||||
val newMovement = checkCollision(Vec3(dx, dy, dz))
|
||||
@@ -359,7 +367,7 @@ class SnowstormParticle(
|
||||
}
|
||||
|
||||
fun updatePosition() {
|
||||
val localVector = if (storm.effect.space.localRotation) storm.transformDirection(
|
||||
val localVector = if (storm.effect.space.localRotation) storm.locatorSpaceMatrix.matrix.transformDirection(
|
||||
Vec3(
|
||||
localX,
|
||||
localY,
|
||||
@@ -374,8 +382,8 @@ class SnowstormParticle(
|
||||
private fun checkCollision(movement: Vec3): Vec3 {
|
||||
val collision = storm.effect.particle.collision
|
||||
var box = boundingBox
|
||||
val bounciness = storm.runtime.resolveDouble(collision.bounciness)
|
||||
val friction = storm.runtime.resolveDouble(collision.friction)
|
||||
val bounciness = runtime.resolveDouble(collision.bounciness)
|
||||
val friction = runtime.resolveDouble(collision.friction)
|
||||
val expiresOnContact = collision.expiresOnContact
|
||||
|
||||
val collisions = level.getBlockCollisions(null, box.expandTowards(movement))
|
||||
@@ -513,8 +521,8 @@ class SnowstormParticle(
|
||||
|
||||
|
||||
private fun setParticleAgeInRuntime() {
|
||||
storm.runtime.environment.variable.setDirectly("particle_age", DoubleValue(age / 20.0))
|
||||
storm.runtime.environment.variable.setDirectly("particle_lifetime", DoubleValue(lifetime / 20.0))
|
||||
runtime.environment.variable.setDirectly("particle_age", DoubleValue(age / 20.0))
|
||||
runtime.environment.variable.setDirectly("particle_lifetime", DoubleValue(lifetime / 20.0))
|
||||
}
|
||||
|
||||
override fun getRenderType() = particleTextureSheet
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ class PokemonItemRenderer : CobblemonBuiltinItemRenderer {
|
||||
state.setPoseToFirstSuitable(PoseType.PORTRAIT)
|
||||
model.applyAnimations(null, state, 0F, 0F, 0F, 0F, 0F)
|
||||
|
||||
matrices.translate(model.profileTranslation.x, model.profileTranslation.y, model.profileTranslation.z - 4.0)
|
||||
matrices.translate(model.profileTranslation.x, model.profileTranslation.y, -4.0)
|
||||
matrices.scale(model.profileScale, model.profileScale, 0.15F)
|
||||
|
||||
val rotation = Quaternionf().fromEulerXYZDegrees(Vector3f(transformations.rotation.x, transformations.rotation.y, transformations.rotation.z))
|
||||
|
||||
+6
-5
@@ -35,7 +35,6 @@ import com.cobblemon.mod.common.client.render.models.blockbench.quirk.ModelQuirk
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.quirk.QuirkData
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.multiplayer.ClientLevel
|
||||
@@ -44,8 +43,8 @@ import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Matrix4f
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import kotlin.text.get
|
||||
|
||||
/**
|
||||
* Represents some kind of animation state for an entity or GUI element or other renderable component in the game.
|
||||
@@ -185,15 +184,17 @@ abstract class PosableState : Schedulable {
|
||||
val entity = getEntity() ?: return@addFunction Unit
|
||||
val world = entity.level() as ClientLevel
|
||||
|
||||
val matrixWrapper = locatorStates[locator] ?: locatorStates["root"]!!
|
||||
|
||||
val rootMatrix = locatorStates["root"]!!
|
||||
val locatorMatrix = locatorStates[locator] ?: locatorStates["root"]!!
|
||||
val particleMatrix = effect.emitter.space.initializeEmitterMatrix(rootMatrix, locatorMatrix)
|
||||
val particleRuntime = MoLangRuntime().setup().setupClient()
|
||||
particleRuntime.environment.query.addFunction("entity") { runtime.environment.query }
|
||||
|
||||
val storm = ParticleStorm(
|
||||
effect = effect,
|
||||
entity = entity,
|
||||
matrixWrapper = matrixWrapper,
|
||||
emitterSpaceMatrix = particleMatrix,
|
||||
locatorSpaceMatrix = locatorMatrix,
|
||||
world = world,
|
||||
runtime = particleRuntime,
|
||||
sourceVelocity = { entity.deltaMovement },
|
||||
|
||||
+4
-1
@@ -54,9 +54,12 @@ class PoseAdapter(
|
||||
addCondition("isTouchingWater") { entity, expectedValue -> entity.isInWater == expectedValue }
|
||||
addCondition("isInWaterOrRain") { entity, expectedValue -> entity.isInWaterOrRain == expectedValue }
|
||||
addCondition("isUnderWater") { entity, expectedValue -> entity.isUnderWater == expectedValue }
|
||||
|
||||
// Kept for compatibility
|
||||
addCondition("isStandingOnRedSand") { entity, expectedValue -> entity.isStandingOnRedSand() == expectedValue }
|
||||
addCondition("isStandingOnSand") { entity, expectedValue -> entity.isStandingOnSand() == expectedValue }
|
||||
addCondition("isStandingOnSandOrRedSand") { entity, expectedValue -> entity.isStandingOnSandOrRedSand() == expectedValue }
|
||||
|
||||
addCondition("isDusk") { entity, expectedValue -> entity.isDusk() == expectedValue }
|
||||
|
||||
conditionsList.addAll(poseConditionReader(json))
|
||||
@@ -93,4 +96,4 @@ class PoseAdapter(
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-2
@@ -14,6 +14,7 @@ import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.snowstorm.BedrockParticleOptions
|
||||
import com.cobblemon.mod.common.client.particle.ParticleStorm
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
@@ -32,6 +33,7 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Matrix4f
|
||||
import java.util.*
|
||||
|
||||
data class BedrockAnimationGroup(
|
||||
@@ -66,7 +68,10 @@ class BedrockParticleKeyframe(
|
||||
override fun run(entity: Entity?, state: PosableState) {
|
||||
entity ?: return
|
||||
val world = entity.level() as? ClientLevel ?: return
|
||||
val matrixWrapper = state.locatorStates[locator] ?: state.locatorStates["root"]!!
|
||||
|
||||
val rootMatrix = state.locatorStates["root"]!!
|
||||
val locatorMatrix = state.locatorStates[locator] ?: state.locatorStates["root"]!!
|
||||
val particleMatrix = effect.emitter.space.initializeEmitterMatrix(rootMatrix, locatorMatrix)
|
||||
|
||||
if (this in state.poseParticles) {
|
||||
return
|
||||
@@ -79,7 +84,8 @@ class BedrockParticleKeyframe(
|
||||
|
||||
val storm = ParticleStorm(
|
||||
effect = effect,
|
||||
matrixWrapper = matrixWrapper,
|
||||
emitterSpaceMatrix = particleMatrix,
|
||||
locatorSpaceMatrix = locatorMatrix,
|
||||
world = world,
|
||||
runtime = particleRuntime,
|
||||
sourceVelocity = { entity.deltaMovement },
|
||||
|
||||
@@ -24,4 +24,6 @@ object ServerSettings {
|
||||
var preventCompletePartyDeposit = Cobblemon.config.preventCompletePartyDeposit
|
||||
var displayEntityLevelLabel = Cobblemon.config.displayEntityLevelLabel
|
||||
var displayEntityNameLabel = Cobblemon.config.displayEntityNameLabel
|
||||
var maxPokemonLevel = Cobblemon.config.maxPokemonLevel
|
||||
|
||||
}
|
||||
@@ -27,7 +27,7 @@ object AbandonMultiTeam {
|
||||
val command = dispatcher.register(
|
||||
Commands.literal("abandonmultiteam")
|
||||
.permission(CobblemonPermissions.ABANDON_MULTITEAM)
|
||||
.executes { execute(it,) }
|
||||
.executes { execute(it) }
|
||||
)
|
||||
dispatcher.register(command.alias(ALIAS))
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.pokeball.catching.calculators.CobblemonCaptureCa
|
||||
import com.cobblemon.mod.common.util.adapters.CaptureCalculatorAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IntRangeAdapter
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
class CobblemonConfig {
|
||||
companion object {
|
||||
@@ -239,13 +240,17 @@ class CobblemonConfig {
|
||||
var tradeMaxDistance = 12F
|
||||
|
||||
@NodeCategory(Category.Battles)
|
||||
var BattlePvPMaxDistance = 32F
|
||||
@SerializedName("battlePvPMaxDistance", alternate = ["BattlePvPMaxDistance"])
|
||||
var battlePvPMaxDistance = 32F
|
||||
|
||||
@NodeCategory(Category.Battles)
|
||||
var battleSpectateMaxDistance = 64F
|
||||
|
||||
@NodeCategory(Category.World)
|
||||
var entityInteractionMaxDistance = 64F
|
||||
@NodeCategory(Category.Pokedex)
|
||||
var maxPokedexScanningDetectionRange = 10.0
|
||||
|
||||
@NodeCategory(Category.Pokedex)
|
||||
var hideUnimplementedPokemonInThePokedex = false
|
||||
|
||||
@NodeCategory(Category.Debug)
|
||||
var enableDebugKeys = false
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.cobblemon.mod.common.datafixer.fix.EvolutionProxyNestingFix
|
||||
import com.cobblemon.mod.common.datafixer.fix.FeatureFix
|
||||
import com.cobblemon.mod.common.datafixer.fix.IvEvToIdentifierFix
|
||||
import com.cobblemon.mod.common.datafixer.fix.MovesetJsonFix
|
||||
import com.cobblemon.mod.common.datafixer.fix.NicknameFix
|
||||
import com.cobblemon.mod.common.datafixer.fix.ShoulderStateJsonFix
|
||||
import com.cobblemon.mod.common.datafixer.fix.TeraTypeFix
|
||||
import com.cobblemon.mod.common.datafixer.fix.TradeableMissingFix
|
||||
@@ -87,6 +88,7 @@ object CobblemonSchemas {
|
||||
builder.addFixer(FeatureFix(schema1))
|
||||
builder.addFixer(MovesetJsonFix(schema1))
|
||||
builder.addFixer(ShoulderStateJsonFix(schema1))
|
||||
builder.addFixer(NicknameFix(schema1))
|
||||
}
|
||||
|
||||
private class CobblemonDataFixerCodec<R>(private val baseCodec: Codec<R>, private val typeReference: TypeReference) : Codec<R> {
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.datafixer.fix
|
||||
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonParseException
|
||||
import com.google.gson.JsonParser
|
||||
import com.mojang.datafixers.schemas.Schema
|
||||
import com.mojang.serialization.Dynamic
|
||||
import com.mojang.serialization.DynamicOps
|
||||
import com.mojang.serialization.JsonOps
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.chat.ComponentSerialization
|
||||
import net.minecraft.resources.RegistryOps
|
||||
|
||||
class NicknameFix(outputSchema: Schema) : PokemonFix(outputSchema) {
|
||||
override fun fixPokemonData(dynamic: Dynamic<*>): Dynamic<*> {
|
||||
val nickname = dynamic.get("Nickname").asString().result()
|
||||
if (!nickname.isPresent) {
|
||||
return dynamic // no nickname
|
||||
}
|
||||
var jsonElement: JsonElement
|
||||
try {
|
||||
jsonElement = JsonParser.parseString(nickname.get())
|
||||
} catch (_: JsonParseException) {
|
||||
return dynamic // no json
|
||||
}
|
||||
ComponentSerialization.CODEC.parse(asJsonOps(dynamic.ops), jsonElement).result().ifPresent {
|
||||
if (dynamic.value is CompoundTag) {
|
||||
var rootTag = dynamic.value as CompoundTag
|
||||
rootTag.put("Nickname", ComponentSerialization.CODEC.encodeStart(dynamic.ops as RegistryOps<CompoundTag>, it).result().get())
|
||||
}
|
||||
else if (dynamic.value is JsonElement) {
|
||||
var rootTag = (dynamic.value as JsonElement).asJsonObject
|
||||
rootTag.remove("Nickname")
|
||||
rootTag.add("Nickname", ComponentSerialization.CODEC.encodeStart(asJsonOps(dynamic.ops), it).result().get())
|
||||
}
|
||||
}
|
||||
|
||||
return dynamic
|
||||
}
|
||||
|
||||
private fun <T> asJsonOps(ops: DynamicOps<T>): DynamicOps<JsonElement> {
|
||||
return if (ops is RegistryOps<T>) {
|
||||
ops.withParent(JsonOps.INSTANCE)
|
||||
} else {
|
||||
JsonOps.INSTANCE
|
||||
}
|
||||
}
|
||||
}
|
||||
+17
-13
@@ -33,8 +33,8 @@ import com.cobblemon.mod.common.item.interactive.PokerodItem
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.util.toBlockPos
|
||||
import kotlin.math.sqrt
|
||||
import net.minecraft.advancements.CriteriaTriggers
|
||||
import net.minecraft.client.resources.sounds.EntityBoundSoundInstance
|
||||
import net.minecraft.core.BlockPos
|
||||
@@ -71,6 +71,7 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets
|
||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
|
||||
import net.minecraft.world.phys.EntityHitResult
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import kotlin.math.sqrt
|
||||
|
||||
|
||||
class PokeRodFishingBobberEntity(type: EntityType<out PokeRodFishingBobberEntity>, world: Level) : FishingHook(type, world) {
|
||||
@@ -182,7 +183,7 @@ class PokeRodFishingBobberEntity(type: EntityType<out PokeRodFishingBobberEntity
|
||||
}
|
||||
|
||||
fun chooseAdjustedSpawnBucket(buckets: List<SpawnBucket>, luckOfTheSeaLevel: Int): SpawnBucket {
|
||||
val baseIncreases = listOf(2.5F, 0.5F, 0.2F) // Base increases for the first three buckets beyond the first
|
||||
val baseIncreases = listOf(2.5F, 0.9F, 0.35F) // Base increases for the first three buckets beyond the first
|
||||
val adjustedWeights = buckets.mapIndexed { index, bucket ->
|
||||
if (index == 0) {
|
||||
// Placeholder, will be recalculated
|
||||
@@ -618,11 +619,11 @@ class PokeRodFishingBobberEntity(type: EntityType<out PokeRodFishingBobberEntity
|
||||
return 0
|
||||
},
|
||||
{ event ->
|
||||
// decrememnt the bait count on the rod itself when reeling in a pokemon
|
||||
PokerodItem.consumeBait(rodStack!!)
|
||||
|
||||
// spawn the pokemon from the chosen bucket at the bobber's location
|
||||
spawnPokemonFromFishing(bobberOwner, chosenBucket, rodStack!!)
|
||||
if (spawnPokemonFromFishing(bobberOwner, chosenBucket, rodStack!!)) {
|
||||
// decrememnt the bait count on the rod itself when reeling in a pokemon
|
||||
PokerodItem.consumeBait(rodStack!!)
|
||||
}
|
||||
|
||||
val serverWorld = level() as ServerLevel
|
||||
|
||||
@@ -676,7 +677,7 @@ class PokeRodFishingBobberEntity(type: EntityType<out PokeRodFishingBobberEntity
|
||||
entity.deltaMovement = tossVelocity
|
||||
}
|
||||
|
||||
fun spawnPokemonFromFishing(player: Player, chosenBucket: SpawnBucket, rodItemStack: ItemStack) {
|
||||
fun spawnPokemonFromFishing(player: Player, chosenBucket: SpawnBucket, rodItemStack: ItemStack): Boolean {
|
||||
var hookedEntityID: Int? = null
|
||||
|
||||
val spawner = BestSpawner.fishingSpawner
|
||||
@@ -696,16 +697,17 @@ class PokeRodFishingBobberEntity(type: EntityType<out PokeRodFishingBobberEntity
|
||||
influences = listOf(PlayerLevelRangeInfluence(player as ServerPlayer, TYPICAL_VARIATION))
|
||||
)
|
||||
|
||||
if (result == null) {
|
||||
// This has a chance to fail, if the position has no suitability for a fishing context
|
||||
// it could also just be a miss which
|
||||
// means two attempts to spawn in the same location can have differing results (which is expected for
|
||||
// randomness).
|
||||
player.sendSystemMessage("Not even a nibble".red())
|
||||
// it could also just be a miss which
|
||||
// means two attempts to spawn in the same location can have differing results (which is expected for
|
||||
// randomness).
|
||||
if (result == null) {
|
||||
player.sendSystemMessage(lang("fishing.no_bite").red())
|
||||
return false
|
||||
}
|
||||
|
||||
var spawnedPokemon: PokemonEntity? = null
|
||||
val resultingSpawn = result?.get()
|
||||
val resultingSpawn = result.get()
|
||||
|
||||
if (resultingSpawn is EntitySpawnResult) {
|
||||
for (entity in resultingSpawn.entities) {
|
||||
@@ -756,6 +758,8 @@ class PokeRodFishingBobberEntity(type: EntityType<out PokeRodFishingBobberEntity
|
||||
}
|
||||
spawnedPokemon?.forceBattle(player as ServerPlayer)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun checkBaitSuccessRate(successChance: Double): Boolean {
|
||||
|
||||
@@ -111,6 +111,8 @@ class NPCEntity(world: Level) : AgeableMob(CobblemonEntities.NPC, world), Npc, P
|
||||
|
||||
var skill: Int? = null // range from 0 - 5
|
||||
|
||||
var baseScale: Float? = null
|
||||
|
||||
var hitbox: EntityDimensions? = null
|
||||
|
||||
var party: NPCPartyStore? = null
|
||||
@@ -347,6 +349,10 @@ class NPCEntity(world: Level) : AgeableMob(CobblemonEntities.NPC, world), Npc, P
|
||||
it.putByteArray(DataKeys.NPC_PLAYER_TEXTURE_TEXTURE, playerTexture.texture)
|
||||
})
|
||||
}
|
||||
val baseScale = baseScale
|
||||
if (baseScale != null) {
|
||||
nbt.putFloat(DataKeys.NPC_BASE_SCALE, baseScale)
|
||||
}
|
||||
val hitbox = hitbox
|
||||
if (hitbox != null) {
|
||||
nbt.put(DataKeys.NPC_HITBOX, CompoundTag().also {
|
||||
@@ -406,6 +412,7 @@ class NPCEntity(world: Level) : AgeableMob(CobblemonEntities.NPC, world), Npc, P
|
||||
this.isInvulnerable = if (nbt.contains(DataKeys.NPC_IS_INVULNERABLE)) nbt.getBoolean(DataKeys.NPC_IS_INVULNERABLE) else null
|
||||
this.isLeashable = if (nbt.contains(DataKeys.NPC_IS_LEASHABLE)) nbt.getBoolean(DataKeys.NPC_IS_LEASHABLE) else null
|
||||
this.allowProjectileHits = if (nbt.contains(DataKeys.NPC_ALLOW_PROJECTILE_HITS)) nbt.getBoolean(DataKeys.NPC_ALLOW_PROJECTILE_HITS) else null
|
||||
this.baseScale = if (nbt.contains(DataKeys.NPC_BASE_SCALE)) nbt.getFloat(DataKeys.NPC_BASE_SCALE) else null
|
||||
this.hitbox = if (nbt.contains(DataKeys.NPC_HITBOX)) {
|
||||
val hitboxNBT = nbt.getCompound(DataKeys.NPC_HITBOX)
|
||||
|
||||
@@ -453,7 +460,17 @@ class NPCEntity(world: Level) : AgeableMob(CobblemonEntities.NPC, world), Npc, P
|
||||
override fun isPersistenceRequired(): Boolean {
|
||||
return super.isPersistenceRequired() || !npc.canDespawn
|
||||
}
|
||||
override fun getDimensions(pose: Pose): EntityDimensions = hitbox ?: npc.hitbox
|
||||
|
||||
override fun getScale(): Float {
|
||||
return baseScale ?: npc.baseScale
|
||||
}
|
||||
|
||||
override fun getDimensions(pose: Pose): EntityDimensions {
|
||||
val hitbox = hitbox ?: npc.hitbox
|
||||
val scaledHitbox = hitbox.scale(baseScale ?: npc.baseScale)
|
||||
|
||||
return scaledHitbox
|
||||
}
|
||||
|
||||
override fun isPushable(): Boolean {
|
||||
return isMovable ?: npc.isMovable
|
||||
|
||||
+1
-2
@@ -416,7 +416,7 @@ class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragMod
|
||||
matrix.translate(x, y, z)
|
||||
wrapper.updateMatrix(matrix.last().pose())
|
||||
val world = Minecraft.getInstance().level ?: return@let
|
||||
ParticleStorm(effect, wrapper, world).spawn()
|
||||
ParticleStorm(effect, wrapper, wrapper, world).spawn()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -456,7 +456,6 @@ class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragMod
|
||||
after(seconds = 2.2F) {
|
||||
// Time to begin falling
|
||||
pokemonEntity.phasingTargetId = -1
|
||||
pokemonEntity.beamMode = 0
|
||||
pokemonEntity.isInvisible = true
|
||||
captureState = CaptureState.FALL
|
||||
after(seconds = 1.5F) {
|
||||
|
||||
@@ -442,8 +442,8 @@ open class PokemonEntity(
|
||||
|
||||
if (ticksLived <= 20) {
|
||||
clearRestriction()
|
||||
// val spawnDirection = entityData.get(SPAWN_DIRECTION).takeIf { it.isFinite() } ?: 0F
|
||||
// yBodyRot = (spawnDirection * 1000F).toInt() / 1000F
|
||||
val spawnDirection = entityData.get(SPAWN_DIRECTION).takeIf { it.isFinite() } ?: 0F
|
||||
yBodyRot = (spawnDirection * 1000F).toInt() / 1000F
|
||||
}
|
||||
|
||||
if (this.tethering != null && !this.tethering!!.box.contains(this.x, this.y, this.z)) {
|
||||
@@ -522,6 +522,10 @@ open class PokemonEntity(
|
||||
return super.isInvulnerableTo(damageSource)
|
||||
}
|
||||
|
||||
override fun canRide(vehicle: Entity): Boolean {
|
||||
return platform == PlatformType.NONE && super.canRide(vehicle)
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method that checks if this Pokémon has the [UncatchableProperty.uncatchable] property.
|
||||
*
|
||||
@@ -819,7 +823,7 @@ open class PokemonEntity(
|
||||
itemStack.hurtAndBreak(1, player, EquipmentSlot.MAINHAND)
|
||||
return InteractionResult.SUCCESS
|
||||
} else if (itemStack.`is`(Items.BUCKET)) {
|
||||
if (pokemon.getFeature<FlagSpeciesFeature>(DataKeys.CAN_BE_MILKED) != null) {
|
||||
if (pokemon.aspects.any { it.contains(DataKeys.CAN_BE_MILKED) }) {
|
||||
player.playSound(SoundEvents.GOAT_MILK, 1.0f, 1.0f)
|
||||
val milkBucket = ItemUtils.createFilledResult(itemStack, player, Items.MILK_BUCKET.defaultInstance)
|
||||
player.setItemInHand(hand, milkBucket)
|
||||
@@ -1366,13 +1370,17 @@ open class PokemonEntity(
|
||||
if (beamMode != 3) super.pushEntities()
|
||||
}
|
||||
|
||||
/*
|
||||
private fun updateEyeHeight() {
|
||||
@Suppress("CAST_NEVER_SUCCEEDS")
|
||||
(this as com.cobblemon.mod.common.mixin.accessor.AccessorEntity).standingEyeHeight(this.getActiveEyeHeight(EntityPose.STANDING, this.type.dimensions))
|
||||
override fun isPushable(): Boolean {
|
||||
return beamMode != 3 && super.isPushable()
|
||||
}
|
||||
|
||||
*/
|
||||
/*
|
||||
private fun updateEyeHeight() {
|
||||
@Suppress("CAST_NEVER_SUCCEEDS")
|
||||
(this as com.cobblemon.mod.common.mixin.accessor.AccessorEntity).standingEyeHeight(this.getActiveEyeHeight(EntityPose.STANDING, this.type.dimensions))
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
fun isFlying() = this.getBehaviourFlag(PokemonBehaviourFlag.FLYING)
|
||||
|
||||
|
||||
@@ -52,8 +52,9 @@ interface BagItemLike {
|
||||
}
|
||||
|
||||
battlePokemon.actor.forceChoose(BagItemActionResponse(bagItem, battlePokemon))
|
||||
val stackName = BuiltInRegistries.ITEM.getKey(stack.item)
|
||||
stack.shrink(1)
|
||||
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(battlePokemon.effectedPokemon.species.resourceIdentifier, BuiltInRegistries.ITEM.getKey(stack.item)))
|
||||
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(battlePokemon.effectedPokemon.species.resourceIdentifier, stackName))
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,12 +219,8 @@ class PokerodItem(val pokeRodId: ResourceLocation, settings: Properties) : Fishi
|
||||
} else { // if the bobber is not out yet
|
||||
|
||||
if (!world.isClientSide) {
|
||||
val lureLevel = EnchantmentHelper.getItemEnchantmentLevel(
|
||||
world.enchantmentRegistry.getHolder(Enchantments.LURE).get(), itemStack
|
||||
)
|
||||
val luckLevel = EnchantmentHelper.getItemEnchantmentLevel(
|
||||
world.enchantmentRegistry.getHolder(Enchantments.LUCK_OF_THE_SEA).get(), itemStack
|
||||
)
|
||||
val lureLevel = world.enchantmentRegistry.getHolder(Enchantments.LURE).map { EnchantmentHelper.getItemEnchantmentLevel(it, itemStack) }.orElse(0)
|
||||
val luckLevel = world.enchantmentRegistry.getHolder(Enchantments.LUCK_OF_THE_SEA).map { EnchantmentHelper.getItemEnchantmentLevel(it, itemStack) }.orElse(0)
|
||||
|
||||
val bobberEntity = PokeRodFishingBobberEntity(
|
||||
user,
|
||||
|
||||
@@ -73,10 +73,11 @@ class ReviveItem(val max: Boolean): CobblemonItem(Properties()), HealingSource {
|
||||
if (actor.canFitForcedAction() && bp.health <= 0 && battle.turn == turn && stack.isHeld(player)) {
|
||||
player.playSound(CobblemonSounds.ITEM_USE, 1F, 1F)
|
||||
actor.forceChoose(BagItemActionResponse(bagItem = bagItem, target = bp, data = bp.uuid.toString()))
|
||||
val stackName = BuiltInRegistries.ITEM.getKey(stack.item)
|
||||
if (!player.isCreative) {
|
||||
stack.shrink(1)
|
||||
}
|
||||
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(bp.effectedPokemon.species.resourceIdentifier, BuiltInRegistries.ITEM.getKey(stack.item)))
|
||||
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(bp.effectedPokemon.species.resourceIdentifier, stackName))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,14 +94,15 @@ class ReviveItem(val max: Boolean): CobblemonItem(Properties()), HealingSource {
|
||||
amount = event.amount
|
||||
}
|
||||
pk.currentHealth = amount
|
||||
val stackName = BuiltInRegistries.ITEM.getKey(stack.item)
|
||||
if (!player.isCreative) {
|
||||
stack.shrink(1)
|
||||
}
|
||||
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(pk.species.resourceIdentifier, BuiltInRegistries.ITEM.getKey(stack.item)))
|
||||
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(pk.species.resourceIdentifier, stackName))
|
||||
}
|
||||
}
|
||||
}
|
||||
return InteractionResultHolder.success(stack)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+24
-4
@@ -16,24 +16,44 @@ import net.minecraft.resources.ResourceLocation
|
||||
|
||||
/**
|
||||
* Packet that spawns a snowstorm particle effect on a specified entity and specified locator.
|
||||
* Can specify an optional target+locator to pass through to the spawned particle
|
||||
*
|
||||
* Handled by [SpawnSnowstormEntityParticleHandler]
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since January 21st, 2024
|
||||
*/
|
||||
class SpawnSnowstormEntityParticlePacket(val effectId: ResourceLocation, val entityId: Int, val locator: List<String> = listOf("root")) : NetworkPacket<SpawnSnowstormEntityParticlePacket> {
|
||||
class SpawnSnowstormEntityParticlePacket(
|
||||
val effectId: ResourceLocation,
|
||||
val sourceEntityId: Int,
|
||||
val sourceLocators: List<String> = listOf("root"),
|
||||
val targetedEntityId: Int? = null,
|
||||
val targetLocators: List<String>? = null
|
||||
) : NetworkPacket<SpawnSnowstormEntityParticlePacket> {
|
||||
companion object {
|
||||
val ID = cobblemonResource("spawn_snowstorm_entity_particle")
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = SpawnSnowstormEntityParticlePacket(buffer.readIdentifier(), buffer.readInt(), buffer.readList { buffer.readString() })
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): SpawnSnowstormEntityParticlePacket {
|
||||
val effectId = buffer.readIdentifier()
|
||||
val sourceEntityId = buffer.readInt()
|
||||
val sourceLocators = buffer.readList { buffer.readString() }
|
||||
val targetedEntityId = buffer.readNullable { it.readInt() }
|
||||
val targetLocators = buffer.readNullable { buffer.readList { buffer.readString() }}
|
||||
return SpawnSnowstormEntityParticlePacket(effectId, sourceEntityId, sourceLocators, targetedEntityId, targetLocators)
|
||||
}
|
||||
}
|
||||
|
||||
override val id = ID
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeIdentifier(effectId)
|
||||
buffer.writeInt(entityId)
|
||||
buffer.writeCollection(locator) { _, value -> buffer.writeString(value) }
|
||||
buffer.writeInt(sourceEntityId)
|
||||
buffer.writeCollection(sourceLocators) { _, value -> buffer.writeString(value) }
|
||||
buffer.writeNullable(targetedEntityId) { _, value -> buffer.writeInt(value) }
|
||||
buffer.writeNullable(targetLocators) { _, value ->
|
||||
buffer.writeCollection(value) { _, locator ->
|
||||
buffer.writeString(locator)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -18,13 +18,14 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.evolution.CobblemonEvolutionDisplay
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import io.netty.buffer.ByteBuf
|
||||
import net.minecraft.core.RegistryAccess
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class AddEvolutionPacket(pokemon: () -> Pokemon, value: EvolutionDisplay) : SingleUpdatePacket<EvolutionDisplay, AddEvolutionPacket>(pokemon, value) {
|
||||
|
||||
override val id = ID
|
||||
|
||||
constructor(pokemon: Pokemon, value: Evolution) : this({ pokemon }, value.convertToDisplay(pokemon))
|
||||
constructor(pokemon: Pokemon, value: Evolution, registryAccess: RegistryAccess) : this({ pokemon }, value.convertToDisplay(pokemon, registryAccess))
|
||||
|
||||
override fun encodeValue(buffer: RegistryFriendlyByteBuf) {
|
||||
this.value.encode(buffer)
|
||||
@@ -40,8 +41,8 @@ class AddEvolutionPacket(pokemon: () -> Pokemon, value: EvolutionDisplay) : Sing
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = AddEvolutionPacket(decodePokemon(buffer), decodeDisplay(buffer))
|
||||
|
||||
internal fun Evolution.convertToDisplay(pokemon: Pokemon): EvolutionDisplay {
|
||||
val result = pokemon.clone()
|
||||
internal fun Evolution.convertToDisplay(pokemon: Pokemon, registryAccess: RegistryAccess): EvolutionDisplay {
|
||||
val result = pokemon.clone(registryAccess = registryAccess)
|
||||
this.result.apply(result)
|
||||
val expectedDisplay = CobblemonEvolutionDisplay(this.id, result)
|
||||
val event = EvolutionDisplayEvent(result, expectedDisplay, this)
|
||||
|
||||
+2
-1
@@ -16,13 +16,14 @@ import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.Add
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.AddEvolutionPacket.Companion.encode
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.core.RegistryAccess
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class RemoveEvolutionPacket(pokemon: () -> Pokemon, value: EvolutionDisplay) : SingleUpdatePacket<EvolutionDisplay, RemoveEvolutionPacket>(pokemon, value) {
|
||||
|
||||
override val id = ID
|
||||
|
||||
constructor(pokemon: Pokemon, value: Evolution) : this({ pokemon }, value.convertToDisplay(pokemon))
|
||||
constructor(pokemon: Pokemon, value: Evolution, registryAccess: RegistryAccess) : this({ pokemon }, value.convertToDisplay(pokemon, registryAccess))
|
||||
|
||||
override fun encodeValue(buffer: RegistryFriendlyByteBuf) {
|
||||
this.value.encode(buffer)
|
||||
|
||||
+8
-2
@@ -19,15 +19,21 @@ import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
* @author Licious
|
||||
* @since September 25th, 2022
|
||||
*/
|
||||
class ServerSettingsPacket internal constructor(val preventCompletePartyDeposit: Boolean, val displayEntityLevelLabel: Boolean, val displayEntityNameLabel: Boolean) : NetworkPacket<ServerSettingsPacket> {
|
||||
class ServerSettingsPacket internal constructor(
|
||||
val preventCompletePartyDeposit: Boolean,
|
||||
val displayEntityLevelLabel: Boolean,
|
||||
val displayEntityNameLabel: Boolean,
|
||||
val maxPokemonLevel: Int
|
||||
) : NetworkPacket<ServerSettingsPacket> {
|
||||
override val id = ID
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeBoolean(Cobblemon.config.preventCompletePartyDeposit)
|
||||
buffer.writeBoolean(Cobblemon.config.displayEntityLevelLabel)
|
||||
buffer.writeBoolean(Cobblemon.config.displayEntityNameLabel)
|
||||
buffer.writeInt(Cobblemon.config.maxPokemonLevel)
|
||||
}
|
||||
companion object {
|
||||
val ID = cobblemonResource("server_settings")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = ServerSettingsPacket(buffer.readBoolean(), buffer.readBoolean(), buffer.readBoolean())
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = ServerSettingsPacket(buffer.readBoolean(), buffer.readBoolean(), buffer.readBoolean(), buffer.readInt())
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -56,7 +56,7 @@ object RequestInteractionsHandler : ServerNetworkPacketHandler<RequestPlayerInte
|
||||
val isTargetBattling = BattleRegistry.getBattleByParticipatingPlayerId(packet.targetId) != null
|
||||
if (isTargetBattling and Cobblemon.config.allowSpectating && squaredDistance <= Cobblemon.config.battleSpectateMaxDistance.pow(2)) {
|
||||
options[PlayerInteractOptionsPacket.Options.SPECTATE_BATTLE] = PlayerInteractOptionsPacket.OptionStatus.AVAILABLE
|
||||
} else if (squaredDistance <= Cobblemon.config.BattlePvPMaxDistance.pow(2)) {
|
||||
} else if (squaredDistance <= Cobblemon.config.battlePvPMaxDistance.pow(2)) {
|
||||
// LOS and distance checks passed, now check parties and add appropriate options
|
||||
val playerPartyCount = player.party().count { pokemon -> !pokemon.isFainted() }
|
||||
val targetPartyCount = (targetPlayerEntity as ServerPlayer).party().count { pokemon -> !pokemon.isFainted() }
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.cobblemon.mod.common.util.normalizeToArray
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonPrimitive
|
||||
import com.mojang.serialization.JsonOps
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import org.joml.Vector4f
|
||||
|
||||
@@ -55,6 +56,7 @@ object SnowstormParticleReader {
|
||||
val collisionJson = componentsJson.get("minecraft:particle_motion_collision")?.asJsonObject
|
||||
val spaceJson = componentsJson.get("minecraft:emitter_local_space")?.asJsonObject
|
||||
val particleLifetimeEventsJson = componentsJson.get("minecraft:particle_lifetime_events")?.asJsonObject
|
||||
val emitterSpaceJson = componentsJson.get("cobblemon:emitter_space")?.asJsonObject ?: JsonObject()
|
||||
|
||||
val id = ResourceLocation.parse(descJson.get("identifier").asString)
|
||||
val maxAge = particleLifetimeJson?.get("max_lifetime")?.asString?.asExpression() ?: 0.0.asExpression()
|
||||
@@ -391,6 +393,8 @@ object SnowstormParticleReader {
|
||||
key.toDouble() to value.normalizeToArray().map { it.asString }.toMutableList()
|
||||
}?.toMap()?.toMutableMap() ?: mutableMapOf())
|
||||
|
||||
val emitterSpace = EmitterSpace.CODEC.decode(JsonOps.INSTANCE, emitterSpaceJson).result().get().first
|
||||
|
||||
return BedrockParticleOptions(
|
||||
id = id,
|
||||
events = events,
|
||||
@@ -400,6 +404,7 @@ object SnowstormParticleReader {
|
||||
rate = rate,
|
||||
shape = shape,
|
||||
lifetime = lifetime,
|
||||
space = emitterSpace,
|
||||
eventTimeline = emitterEventTimeline,
|
||||
creationEvents = emitterCreationEvents,
|
||||
expirationEvents = emitterExpirationEvents,
|
||||
|
||||
@@ -8,7 +8,10 @@
|
||||
|
||||
package com.cobblemon.mod.common.particle
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.struct.VariableStruct
|
||||
import com.cobblemon.mod.common.api.snowstorm.BedrockParticleOptions
|
||||
import com.cobblemon.mod.common.api.snowstorm.ParticleMotionType
|
||||
import com.cobblemon.mod.common.client.particle.ParticleStorm
|
||||
import com.cobblemon.mod.common.client.render.SnowstormParticle
|
||||
import com.mojang.serialization.MapCodec
|
||||
@@ -53,12 +56,32 @@ class SnowstormParticleType : ParticleType<SnowstormParticleOptions>(true) {
|
||||
velocityY: Double,
|
||||
velocityZ: Double
|
||||
): Particle {
|
||||
//Particles with local position move with their emitter
|
||||
val isLocal = parameters.effect.space.localPosition
|
||||
val storm = ParticleStorm.contextStorm!!
|
||||
|
||||
//Particles may need to have variables that are specific to the instance of the particle
|
||||
//For instance, distance variables are different per particle, it can't be tied to the emitter
|
||||
//since the emitter can move separately from the particle
|
||||
//We keep everything else from the storm. Just separate var structs
|
||||
val runtime = MoLangRuntime()
|
||||
runtime.environment.query = storm.runtime.environment.query
|
||||
val mapClone = storm.runtime.environment.variable.map.entries.associateBy({it.key}, {it.value})
|
||||
val varStruct = VariableStruct(mapClone)
|
||||
storm.lockParticleVars(varStruct)
|
||||
runtime.environment.variable = varStruct
|
||||
runtime.environment.context = storm.runtime.environment.context
|
||||
runtime.environment.temp = storm.runtime.environment.temp
|
||||
|
||||
|
||||
return SnowstormParticle(
|
||||
ParticleStorm.contextStorm!!,
|
||||
storm,
|
||||
world,
|
||||
x, y, z,
|
||||
Vec3(velocityX, velocityY, velocityZ),
|
||||
invisible = false
|
||||
runtime,
|
||||
invisible = false,
|
||||
matrixWrapper = if (isLocal) storm.emitterSpaceMatrix else storm.emitterSpaceMatrix.clone()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.pokedex.scanner
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext.Companion.BLOCK_LENGTH_PER_ZOOM_STAGE
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.level.ClipContext
|
||||
@@ -16,13 +17,11 @@ import net.minecraft.world.phys.HitResult
|
||||
|
||||
//Handles the actual raycasting to figure out what pokemon we are looking at
|
||||
object PokemonScanner {
|
||||
val RAY_LENGTH = 10.0
|
||||
|
||||
//This basically draws a box around the casting entity, finds all entities in the box, then finds the one that a ray emanating from the player hits first
|
||||
fun detectEntity(castingEntity: Entity, zoomLevel: Int): Entity? {
|
||||
val eyePos = castingEntity.getEyePosition(1.0F)
|
||||
val lookVec = castingEntity.getViewVector(1.0F)
|
||||
val maxDistance = RAY_LENGTH + zoomLevel
|
||||
val maxDistance = Cobblemon.config.maxPokedexScanningDetectionRange + zoomLevel
|
||||
val boundingBoxSize = 12.0 + zoomLevel
|
||||
var closestEntity: Entity? = null
|
||||
var closestDistance = maxDistance
|
||||
@@ -99,6 +98,6 @@ object PokemonScanner {
|
||||
}
|
||||
|
||||
fun isEntityInRange(castingEntity: Entity, targetEntity: Entity, zoomLevel: Int): Boolean {
|
||||
return targetEntity.position().distanceTo(castingEntity.position()) <= RAY_LENGTH + (zoomLevel * BLOCK_LENGTH_PER_ZOOM_STAGE)
|
||||
return targetEntity.position().distanceTo(castingEntity.position()) <= Cobblemon.config.maxPokedexScanningDetectionRange + (zoomLevel * BLOCK_LENGTH_PER_ZOOM_STAGE)
|
||||
}
|
||||
}
|
||||
@@ -981,10 +981,20 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
return CODEC.decode(ops, data).ifSuccess { this.copyFrom(it.first) }
|
||||
}
|
||||
|
||||
fun clone(newUUID: Boolean = true): Pokemon {
|
||||
/**
|
||||
* Clones the provided pokemon into a completely new instance.
|
||||
*
|
||||
* @param registryAccess Registry Access used for serialization context. WILL BECOME REQUIRED IN 1.7, currently falls back to server registry access
|
||||
* @param newUUID Whether or not the pokemon should receive a new UUID or not, which will completely untie it from the original
|
||||
*
|
||||
* @return The cloned pokemon
|
||||
*/
|
||||
fun clone(newUUID: Boolean = true, registryAccess: RegistryAccess? = null): Pokemon {
|
||||
// NBT is faster, ops type doesn't really matter
|
||||
val encoded = CODEC.encodeStart(NbtOps.INSTANCE, this).orThrow
|
||||
val result = CODEC.decode(NbtOps.INSTANCE, encoded).orThrow.first
|
||||
var ops = (registryAccess ?: server()?.registryAccess() ?: throw IllegalStateException("No registry access for cloning available"))
|
||||
.createSerializationContext(NbtOps.INSTANCE)
|
||||
val encoded = CODEC.encodeStart(ops, this).orThrow
|
||||
val result = CODEC.decode(ops, encoded).orThrow.first
|
||||
result.isClient = this.isClient
|
||||
if (newUUID) {
|
||||
result.uuid = UUID.randomUUID()
|
||||
@@ -1623,7 +1633,7 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
private val _state = registerObservable(SimpleObservable<PokemonState>()) { PokemonStateUpdatePacket({ this }, it) }
|
||||
private val _status = registerObservable(SimpleObservable<PersistentStatus?>()) { StatusUpdatePacket({ this }, it) }
|
||||
private val _caughtBall = registerObservable(SimpleObservable<PokeBall>()) { CaughtBallUpdatePacket({ this }, it) }
|
||||
private val _benchedMoves = registerObservable(benchedMoves.observable) { BenchedMovesUpdatePacket({ this }, it) }
|
||||
private val _benchedMoves = registerObservable(benchedMoves.observable) { BenchedMovesUpdatePacket({ this }, BenchedMoves().also {copy -> copy.copyFrom(it)}) }
|
||||
private val _ivs = registerObservable(ivs.observable) { IVsUpdatePacket({ this }, it as IVs) }
|
||||
private val _evs = registerObservable(evs.observable) { EVsUpdatePacket({ this }, it as EVs) }
|
||||
private val _aspects = registerObservable(SimpleObservable<Set<String>>()) { AspectsUpdatePacket({ this }, it) }
|
||||
|
||||
+3
-2
@@ -19,6 +19,7 @@ import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.Add
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.ClearEvolutionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.RemoveEvolutionPacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
|
||||
@@ -73,7 +74,7 @@ class ServerEvolutionController(
|
||||
|
||||
override fun add(element: Evolution): Boolean {
|
||||
if (this.evolutions.add(element)) {
|
||||
this.pokemon.notify(AddEvolutionPacket(this.pokemon, element))
|
||||
this.pokemon.notify(AddEvolutionPacket(this.pokemon, element, this.pokemon.getOwnerEntity()?.registryAccess() ?: server()?.registryAccess() ?: throw IllegalStateException("No registry access available")))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -109,7 +110,7 @@ class ServerEvolutionController(
|
||||
|
||||
override fun remove(element: Evolution): Boolean {
|
||||
if (this.evolutions.remove(element)) {
|
||||
this.pokemon.notify(RemoveEvolutionPacket(this.pokemon, element))
|
||||
this.pokemon.notify(RemoveEvolutionPacket(this.pokemon, element, this.pokemon.getOwnerEntity()?.registryAccess() ?: server()?.registryAccess() ?: throw IllegalStateException("No registry access available")))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -219,6 +219,7 @@ object DataKeys {
|
||||
const val NPC_IS_INVULNERABLE = "IsInvulnerable"
|
||||
const val NPC_IS_LEASHABLE = "IsLeashable"
|
||||
const val NPC_ALLOW_PROJECTILE_HITS = "AllowProjectileHits"
|
||||
const val NPC_BASE_SCALE = "BaseScale"
|
||||
const val NPC_HITBOX = "Hitbox"
|
||||
const val NPC_HITBOX_WIDTH = "Width"
|
||||
const val NPC_HITBOX_HEIGHT = "Height"
|
||||
|
||||
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.util
|
||||
|
||||
import com.google.common.collect.ImmutableMap
|
||||
import com.mojang.serialization.Dynamic
|
||||
import com.mojang.serialization.DynamicOps
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.nbt.NbtOps
|
||||
@@ -18,6 +17,7 @@ import net.minecraft.nbt.Tag
|
||||
import net.minecraft.network.syncher.EntityDataAccessor
|
||||
import net.minecraft.network.syncher.SynchedEntityData
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.Blocks
|
||||
import net.minecraft.world.phys.AABB
|
||||
import net.minecraft.world.phys.Vec3
|
||||
@@ -188,47 +188,32 @@ fun Entity.setPositionSafely(pos: Vec3): Boolean {
|
||||
}
|
||||
}
|
||||
|
||||
fun Entity.isStandingOnSandOrRedSand(): Boolean {
|
||||
val sandDepth = 2 // Define the depth you want to check
|
||||
for (a in 1..sandDepth) {
|
||||
val sandBlockState = this.level().getBlockState(blockPosition().below(a))
|
||||
val sandBlock = sandBlockState.block
|
||||
if (sandBlock == Blocks.SAND && !sandBlockState.isAir && sandBlockState.isCollisionShapeFullBlock(this.level(), blockPosition().below(a))) {
|
||||
return true
|
||||
}
|
||||
if (sandBlock == Blocks.RED_SAND && !sandBlockState.isAir && sandBlockState.isCollisionShapeFullBlock(this.level(), blockPosition().below(a))) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun Entity.isDusk(): Boolean {
|
||||
val time = level().dayTime % 24000
|
||||
return time in 12000..13000
|
||||
}
|
||||
|
||||
fun Entity.isStandingOnSand(): Boolean {
|
||||
val sandDepth = 2 // Define the depth you want to check
|
||||
for (a in 1..sandDepth) {
|
||||
val sandBlockState = this.level().getBlockState(blockPosition().below(a))
|
||||
val sandBlock = sandBlockState.block
|
||||
if (sandBlock == Blocks.SAND && !sandBlockState.isAir && sandBlockState.isCollisionShapeFullBlock(this.level(), blockPosition().below(a))) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return isStandingOn(setOf(Blocks.SAND))
|
||||
}
|
||||
|
||||
fun Entity.isStandingOnRedSand(): Boolean {
|
||||
val redSandDepth = 2 // Define the depth you want to check
|
||||
for (i in 1..redSandDepth) {
|
||||
val redSandBlockState = this.level().getBlockState(blockPosition().below(i))
|
||||
val redSandBlock = redSandBlockState.block
|
||||
if (redSandBlock == Blocks.RED_SAND && !redSandBlockState.isAir && redSandBlockState.isCollisionShapeFullBlock(this.level(), blockPosition().below(i))) {
|
||||
return true
|
||||
}
|
||||
return isStandingOn(setOf(Blocks.RED_SAND))
|
||||
}
|
||||
|
||||
fun Entity.isStandingOnSandOrRedSand(): Boolean {
|
||||
return isStandingOn(setOf(Blocks.SAND, Blocks.RED_SAND))
|
||||
}
|
||||
|
||||
fun Entity.isStandingOn(blocks: Set<Block>, depth: Int = 2): Boolean {
|
||||
for (currentDepth in 1..depth) {
|
||||
val bellowBlockPos = blockPosition().below(currentDepth)
|
||||
val blockState = level().getBlockState(bellowBlockPos)
|
||||
|
||||
if (blockState.isAir || !blockState.isCollisionShapeFullBlock(level(), bellowBlockPos)) continue
|
||||
if (blocks.contains(blockState.block)) return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ object NPCClassAdapter : JsonDeserializer<NPCClass> {
|
||||
obj.get("resourceIdentifier")?.let { npcClass.resourceIdentifier = it.asString.asIdentifierDefaultingNamespace() }
|
||||
obj.get("aspects")?.let { npcClass.aspects = it.normalizeToArray().map { it.asString }.toMutableSet() }
|
||||
obj.get("variation")?.let { it.asJsonObject.entrySet().forEach { (key, value) -> npcClass.variations[key] = ctx.deserialize(value, NPCVariationProvider::class.java) } }
|
||||
obj.get("baseScale")?.let { npcClass.baseScale = it.asFloat }
|
||||
obj.get("hitbox")?.let { npcClass.hitbox = ctx.deserialize(it, EntityDimensions::class.java) }
|
||||
obj.get("battleConfiguration")?.let { npcClass.battleConfiguration = ctx.deserialize(it, NPCBattleConfiguration::class.java) }
|
||||
obj.get("interaction")?.let { npcClass.interaction = ctx.deserialize(it, NPCInteractConfiguration::class.java) }
|
||||
|
||||
+3
-1
@@ -20,6 +20,7 @@ import com.cobblemon.mod.common.pokemon.evolution.controller.ServerEvolutionCont
|
||||
import com.cobblemon.mod.common.pokemon.status.PersistentStatusContainer
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.codec.CodecUtils
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.MapCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
@@ -98,7 +99,8 @@ internal data class ClientPokemonP2(
|
||||
pokemon.faintedTimer,
|
||||
pokemon.healTimer,
|
||||
Optional.ofNullable((pokemon.evolutionProxy.current() as? ServerEvolutionController)?.let {
|
||||
ClientEvolutionController.Intermediate(it.map { it.convertToDisplay(pokemon) }.toSet())
|
||||
//TOOD figure out a closer registry access (might have to break some method signatures for this (1.7?)
|
||||
ClientEvolutionController.Intermediate(it.map { it.convertToDisplay(pokemon, registryAccess = server()?.registryAccess() ?: throw IllegalStateException("No registry access available")) }.toSet())
|
||||
}),
|
||||
pokemon.shiny,
|
||||
pokemon.nature,
|
||||
|
||||
+68
-45
@@ -1,47 +1,70 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientazureball/ballsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_steady": {
|
||||
"spawn_rate": 16,
|
||||
"max_particles": 16
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 0.5
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"offset": [0, 1.5, 0],
|
||||
"radius": "math.random(0.5,1.5)*1.5",
|
||||
"surface_only": true,
|
||||
"direction": [0, 1, 0]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0.75,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.2, 0.2],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 36,
|
||||
"texture_height": 9,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [9, 9],
|
||||
"step_UV": [9, 0],
|
||||
"frames_per_second": 12,
|
||||
"max_frame": 4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientazureball/ballsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_steady": {
|
||||
"spawn_rate": 16,
|
||||
"max_particles": 16
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 0.5
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"offset": [
|
||||
0,
|
||||
1.5,
|
||||
0
|
||||
],
|
||||
"radius": "math.random(0.5,1.5)*1.5",
|
||||
"surface_only": true,
|
||||
"direction": [
|
||||
0,
|
||||
1,
|
||||
0
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0.75,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 36,
|
||||
"texture_height": 9,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
9,
|
||||
9
|
||||
],
|
||||
"step_UV": [
|
||||
9,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 12,
|
||||
"max_frame": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+67
-44
@@ -1,46 +1,69 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientazureball/battle/ballsendsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsendsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 8
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.05,4)*4+0.5", "math.random(-10,10)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*3",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, -5, 0],
|
||||
"linear_drag_coefficient": 4
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.15, 0.15],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 99,
|
||||
"texture_height": 9,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [9, 9],
|
||||
"step_UV": [9, 0],
|
||||
"frames_per_second": 18,
|
||||
"max_frame": 11
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientazureball/battle/ballsendsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsendsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 8
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": [
|
||||
"math.random(-10,10)",
|
||||
"math.random(-0.05,4)*4+0.5",
|
||||
"math.random(-10,10)"
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*3",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [
|
||||
0,
|
||||
-5,
|
||||
0
|
||||
],
|
||||
"linear_drag_coefficient": 4
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
0.15,
|
||||
0.15
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 99,
|
||||
"texture_height": 9,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
9,
|
||||
9
|
||||
],
|
||||
"step_UV": [
|
||||
9,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 18,
|
||||
"max_frame": 11
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+62
-43
@@ -1,45 +1,64 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientazureball/battle/ballsparks",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparks"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 10
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.1,4)*3+0.5", "math.random(-10,10)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*3.5",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_drag_coefficient": 4.5
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.15, 0.15],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 80,
|
||||
"texture_height": 8,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [8, 8],
|
||||
"step_UV": [8, 0],
|
||||
"frames_per_second": 18,
|
||||
"max_frame": 10
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientazureball/battle/ballsparks",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparks"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 10
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": [
|
||||
"math.random(-10,10)",
|
||||
"math.random(-0.1,4)*3+0.5",
|
||||
"math.random(-10,10)"
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*3.5",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_drag_coefficient": 4.5
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
0.15,
|
||||
0.15
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 80,
|
||||
"texture_height": 8,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
8,
|
||||
8
|
||||
],
|
||||
"step_UV": [
|
||||
8,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 18,
|
||||
"max_frame": 10
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+60
-41
@@ -1,43 +1,62 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientazureball/battle/sendflash",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/battle/sendflash"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_looping": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_point": {
|
||||
"offset": [0, 0.5, 0]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [2.25, 2.25],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 1024,
|
||||
"texture_height": 64,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [64, 64],
|
||||
"step_UV": [64, 0],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 16
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientazureball/battle/sendflash",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/battle/sendflash"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_looping": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_point": {
|
||||
"offset": [
|
||||
0,
|
||||
0.5,
|
||||
0
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
2.25,
|
||||
2.25
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 1024,
|
||||
"texture_height": 64,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
64,
|
||||
64
|
||||
],
|
||||
"step_UV": [
|
||||
64,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 16
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+67
-44
@@ -1,46 +1,69 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientazureball/casual/ballsendsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsendsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 4
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.05,4)*4+0.5", "math.random(-10,10)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,6)*2.5",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, -6, 0],
|
||||
"linear_drag_coefficient": 4
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.15, 0.15],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 99,
|
||||
"texture_height": 9,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [9, 9],
|
||||
"step_UV": [9, 0],
|
||||
"frames_per_second": 18,
|
||||
"max_frame": 11
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientazureball/casual/ballsendsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsendsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 4
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": [
|
||||
"math.random(-10,10)",
|
||||
"math.random(-0.05,4)*4+0.5",
|
||||
"math.random(-10,10)"
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,6)*2.5",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [
|
||||
0,
|
||||
-6,
|
||||
0
|
||||
],
|
||||
"linear_drag_coefficient": 4
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
0.15,
|
||||
0.15
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 99,
|
||||
"texture_height": 9,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
9,
|
||||
9
|
||||
],
|
||||
"step_UV": [
|
||||
9,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 18,
|
||||
"max_frame": 11
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+62
-43
@@ -1,45 +1,64 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientazureball/casual/ballsparks",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparks"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 5
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.1,4)*3+0.5", "math.random(-10,10)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*2.1",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_drag_coefficient": 3.5
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.1, 0.1],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 80,
|
||||
"texture_height": 8,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [8, 8],
|
||||
"step_UV": [8, 0],
|
||||
"frames_per_second": 18,
|
||||
"max_frame": 10
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientazureball/casual/ballsparks",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparks"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 5
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": [
|
||||
"math.random(-10,10)",
|
||||
"math.random(-0.1,4)*3+0.5",
|
||||
"math.random(-10,10)"
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*2.1",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_drag_coefficient": 3.5
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
0.1,
|
||||
0.1
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 80,
|
||||
"texture_height": 8,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
8,
|
||||
8
|
||||
],
|
||||
"step_UV": [
|
||||
8,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 18,
|
||||
"max_frame": 10
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+60
-41
@@ -1,43 +1,62 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientazureball/casual/sendflash",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/casual/sendcasual"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_looping": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_point": {
|
||||
"offset": [0, 0.5, 0]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [1.25, 1.25],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 384,
|
||||
"texture_height": 32,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [32, 32],
|
||||
"step_UV": [32, 0],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 12
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientazureball/casual/sendflash",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/casual/sendcasual"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_looping": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_point": {
|
||||
"offset": [
|
||||
0,
|
||||
0.5,
|
||||
0
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
1.25,
|
||||
1.25
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 384,
|
||||
"texture_height": 32,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
32,
|
||||
32
|
||||
],
|
||||
"step_UV": [
|
||||
32,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 12
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+68
-45
@@ -1,47 +1,70 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientcitrineball/ballsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_steady": {
|
||||
"spawn_rate": 16,
|
||||
"max_particles": 16
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 0.5
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"offset": [0, 1.5, 0],
|
||||
"radius": "math.random(0.5,1.5)*1.5",
|
||||
"surface_only": true,
|
||||
"direction": [0, 1, 0]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0.75,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.2, 0.2],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 36,
|
||||
"texture_height": 9,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [9, 9],
|
||||
"step_UV": [9, 0],
|
||||
"frames_per_second": 12,
|
||||
"max_frame": 4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientcitrineball/ballsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_steady": {
|
||||
"spawn_rate": 16,
|
||||
"max_particles": 16
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 0.5
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"offset": [
|
||||
0,
|
||||
1.5,
|
||||
0
|
||||
],
|
||||
"radius": "math.random(0.5,1.5)*1.5",
|
||||
"surface_only": true,
|
||||
"direction": [
|
||||
0,
|
||||
1,
|
||||
0
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0.75,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 36,
|
||||
"texture_height": 9,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
9,
|
||||
9
|
||||
],
|
||||
"step_UV": [
|
||||
9,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 12,
|
||||
"max_frame": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+67
-44
@@ -1,46 +1,69 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientcitrineball/battle/ballsendsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsendsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 8
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.05,4)*4+0.5", "math.random(-10,10)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*3",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, -5, 0],
|
||||
"linear_drag_coefficient": 4
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.15, 0.15],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 99,
|
||||
"texture_height": 9,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [9, 9],
|
||||
"step_UV": [9, 0],
|
||||
"frames_per_second": 18,
|
||||
"max_frame": 11
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientcitrineball/battle/ballsendsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsendsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 8
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": [
|
||||
"math.random(-10,10)",
|
||||
"math.random(-0.05,4)*4+0.5",
|
||||
"math.random(-10,10)"
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*3",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [
|
||||
0,
|
||||
-5,
|
||||
0
|
||||
],
|
||||
"linear_drag_coefficient": 4
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
0.15,
|
||||
0.15
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 99,
|
||||
"texture_height": 9,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
9,
|
||||
9
|
||||
],
|
||||
"step_UV": [
|
||||
9,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 18,
|
||||
"max_frame": 11
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+62
-43
@@ -1,45 +1,64 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientcitrineball/battle/ballsparks",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparks"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 10
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.1,4)*3+0.5", "math.random(-10,10)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*3.5",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_drag_coefficient": 4.5
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.15, 0.15],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 80,
|
||||
"texture_height": 8,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [8, 8],
|
||||
"step_UV": [8, 0],
|
||||
"frames_per_second": 18,
|
||||
"max_frame": 10
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientcitrineball/battle/ballsparks",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparks"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 10
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": [
|
||||
"math.random(-10,10)",
|
||||
"math.random(-0.1,4)*3+0.5",
|
||||
"math.random(-10,10)"
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*3.5",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_drag_coefficient": 4.5
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
0.15,
|
||||
0.15
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 80,
|
||||
"texture_height": 8,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
8,
|
||||
8
|
||||
],
|
||||
"step_UV": [
|
||||
8,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 18,
|
||||
"max_frame": 10
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+60
-41
@@ -1,43 +1,62 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientcitrineball/battle/sendflash",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/battle/sendflash"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_looping": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_point": {
|
||||
"offset": [0, 0.5, 0]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [2.25, 2.25],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 1024,
|
||||
"texture_height": 64,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [64, 64],
|
||||
"step_UV": [64, 0],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 16
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientcitrineball/battle/sendflash",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/battle/sendflash"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_looping": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_point": {
|
||||
"offset": [
|
||||
0,
|
||||
0.5,
|
||||
0
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
2.25,
|
||||
2.25
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 1024,
|
||||
"texture_height": 64,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
64,
|
||||
64
|
||||
],
|
||||
"step_UV": [
|
||||
64,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 16
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+67
-44
@@ -1,46 +1,69 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientcitrineball/casual/ballsendsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsendsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 4
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.05,4)*4+0.5", "math.random(-10,10)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,6)*2.5",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, -6, 0],
|
||||
"linear_drag_coefficient": 4
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.15, 0.15],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 99,
|
||||
"texture_height": 9,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [9, 9],
|
||||
"step_UV": [9, 0],
|
||||
"frames_per_second": 18,
|
||||
"max_frame": 11
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientcitrineball/casual/ballsendsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsendsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 4
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": [
|
||||
"math.random(-10,10)",
|
||||
"math.random(-0.05,4)*4+0.5",
|
||||
"math.random(-10,10)"
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,6)*2.5",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [
|
||||
0,
|
||||
-6,
|
||||
0
|
||||
],
|
||||
"linear_drag_coefficient": 4
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
0.15,
|
||||
0.15
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 99,
|
||||
"texture_height": 9,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
9,
|
||||
9
|
||||
],
|
||||
"step_UV": [
|
||||
9,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 18,
|
||||
"max_frame": 11
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+62
-43
@@ -1,45 +1,64 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientcitrineball/casual/ballsparks",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparks"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 5
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.1,4)*3+0.5", "math.random(-10,10)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*2.1",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_drag_coefficient": 3.5
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.1, 0.1],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 80,
|
||||
"texture_height": 8,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [8, 8],
|
||||
"step_UV": [8, 0],
|
||||
"frames_per_second": 18,
|
||||
"max_frame": 10
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientcitrineball/casual/ballsparks",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/ballsparks"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 5
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": [
|
||||
"math.random(-10,10)",
|
||||
"math.random(-0.1,4)*3+0.5",
|
||||
"math.random(-10,10)"
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,7)*2.1",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_drag_coefficient": 3.5
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
0.1,
|
||||
0.1
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 80,
|
||||
"texture_height": 8,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
8,
|
||||
8
|
||||
],
|
||||
"step_UV": [
|
||||
8,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 18,
|
||||
"max_frame": 10
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+60
-41
@@ -1,43 +1,62 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientcitrineball/casual/sendflash",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/casual/sendcasual"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_looping": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_point": {
|
||||
"offset": [0, 0.5, 0]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [1.25, 1.25],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 384,
|
||||
"texture_height": 32,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [32, 32],
|
||||
"step_UV": [32, 0],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 12
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientcitrineball/casual/sendflash",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/pokeball/casual/sendcasual"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_looping": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_point": {
|
||||
"offset": [
|
||||
0,
|
||||
0.5,
|
||||
0
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
1.25,
|
||||
1.25
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 384,
|
||||
"texture_height": 32,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
32,
|
||||
32
|
||||
],
|
||||
"step_UV": [
|
||||
32,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 12
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+74
-47
@@ -1,49 +1,76 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientfeatherball/ballsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/ancientfeatherball/ancientfeatherballsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_steady": {
|
||||
"spawn_rate": 20,
|
||||
"max_particles": 18
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 0.5
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"offset": [0, 1.75, 0],
|
||||
"radius": "1.25",
|
||||
"surface_only": true,
|
||||
"direction": ["math.random(-9,9)", "math.random(4,7)", "math.random(-9,9)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0.75,
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, 2, 0]
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.15, 0.15],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 36,
|
||||
"texture_height": 9,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [9, 9],
|
||||
"step_UV": [9, 0],
|
||||
"frames_per_second": 12,
|
||||
"max_frame": 4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientfeatherball/ballsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/ancientfeatherball/ancientfeatherballsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_steady": {
|
||||
"spawn_rate": 20,
|
||||
"max_particles": 18
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 0.5
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"offset": [
|
||||
0,
|
||||
1.75,
|
||||
0
|
||||
],
|
||||
"radius": "1.25",
|
||||
"surface_only": true,
|
||||
"direction": [
|
||||
"math.random(-9,9)",
|
||||
"math.random(4,7)",
|
||||
"math.random(-9,9)"
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0.75,
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [
|
||||
0,
|
||||
2,
|
||||
0
|
||||
]
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
0.15,
|
||||
0.15
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 36,
|
||||
"texture_height": 9,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
9,
|
||||
9
|
||||
],
|
||||
"step_UV": [
|
||||
9,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 12,
|
||||
"max_frame": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+67
-44
@@ -1,46 +1,69 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientfeatherball/battle/ballsendsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/ancientfeatherball/ancientfeatherballsendsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 12
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.05,3)*4+0.5", "math.random(-10,10)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,6.5)*3.5",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, 0, 0],
|
||||
"linear_drag_coefficient": 4
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.15, 0.15],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 99,
|
||||
"texture_height": 9,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [9, 9],
|
||||
"step_UV": [9, 0],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 11
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientfeatherball/battle/ballsendsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/ancientfeatherball/ancientfeatherballsendsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 12
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": [
|
||||
"math.random(-10,10)",
|
||||
"math.random(-0.05,3)*4+0.5",
|
||||
"math.random(-10,10)"
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,6.5)*3.5",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"linear_drag_coefficient": 4
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
0.15,
|
||||
0.15
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 99,
|
||||
"texture_height": 9,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
9,
|
||||
9
|
||||
],
|
||||
"step_UV": [
|
||||
9,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 11
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+71
-48
@@ -1,50 +1,73 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientfeatherball/battle/ancientfeatherballsparks",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/ancientfeatherball/ancientfeatherballsparks"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_steady": {
|
||||
"spawn_rate": 156,
|
||||
"max_particles": 14
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.1,4)*3+0.5", "math.random(-10,10)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_spin": {
|
||||
"rotation": "(math.random_integer(1,4)*90)"
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(3,7)*4.5",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": ["math.random(-4,4)", 0, "math.random(-4,4)"],
|
||||
"linear_drag_coefficient": 5
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.2, 0.2],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 96,
|
||||
"texture_height": 8,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [8, 8],
|
||||
"step_UV": [8, 0],
|
||||
"frames_per_second": 30,
|
||||
"max_frame": 12
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientfeatherball/battle/ancientfeatherballsparks",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/ancientfeatherball/ancientfeatherballsparks"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_steady": {
|
||||
"spawn_rate": 156,
|
||||
"max_particles": 14
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": [
|
||||
"math.random(-10,10)",
|
||||
"math.random(-0.1,4)*3+0.5",
|
||||
"math.random(-10,10)"
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_spin": {
|
||||
"rotation": "(math.random_integer(1,4)*90)"
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(3,7)*4.5",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [
|
||||
"math.random(-4,4)",
|
||||
0,
|
||||
"math.random(-4,4)"
|
||||
],
|
||||
"linear_drag_coefficient": 5
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 96,
|
||||
"texture_height": 8,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
8,
|
||||
8
|
||||
],
|
||||
"step_UV": [
|
||||
8,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 30,
|
||||
"max_frame": 12
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+60
-41
@@ -1,43 +1,62 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientfeatherball/battle/sendflash",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/ancientfeatherball/battle/ancientfeatherflash"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_looping": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_point": {
|
||||
"offset": [0, 0.5, 0]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [2.25, 2.25],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 768,
|
||||
"texture_height": 64,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [64, 64],
|
||||
"step_UV": [64, 0],
|
||||
"frames_per_second": 30,
|
||||
"max_frame": 12
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientfeatherball/battle/sendflash",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/ancientfeatherball/battle/ancientfeatherflash"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_looping": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_point": {
|
||||
"offset": [
|
||||
0,
|
||||
0.5,
|
||||
0
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
2.25,
|
||||
2.25
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 768,
|
||||
"texture_height": 64,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
64,
|
||||
64
|
||||
],
|
||||
"step_UV": [
|
||||
64,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 30,
|
||||
"max_frame": 12
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+67
-44
@@ -1,46 +1,69 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientfeatherball/casual/ballsendsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/ancientfeatherball/ancientfeatherballsendsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 6
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.05,3)*4+0.5", "math.random(-10,10)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,6.5)*2.8",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, 0, 0],
|
||||
"linear_drag_coefficient": 4
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.15, 0.15],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 99,
|
||||
"texture_height": 9,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [9, 9],
|
||||
"step_UV": [9, 0],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 11
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientfeatherball/casual/ballsendsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/ancientfeatherball/ancientfeatherballsendsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 6
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": [
|
||||
"math.random(-10,10)",
|
||||
"math.random(-0.05,3)*4+0.5",
|
||||
"math.random(-10,10)"
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,6.5)*2.8",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"linear_drag_coefficient": 4
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
0.15,
|
||||
0.15
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 99,
|
||||
"texture_height": 9,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
9,
|
||||
9
|
||||
],
|
||||
"step_UV": [
|
||||
9,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 11
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+65
-46
@@ -1,48 +1,67 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientfeatherball/casual/ballsparks",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/ancientfeatherball/ancientfeatherballsparks"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 8
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": ["math.random(-10,10)", "math.random(-0.1,4)*3+0.5", "math.random(-10,10)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_spin": {
|
||||
"rotation": "(math.random_integer(1,4)*90)"
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,5)*3",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_drag_coefficient": 3
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.2, 0.2],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 96,
|
||||
"texture_height": 8,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [8, 8],
|
||||
"step_UV": [8, 0],
|
||||
"frames_per_second": 30,
|
||||
"max_frame": 12
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientfeatherball/casual/ballsparks",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/ancientfeatherball/ancientfeatherballsparks"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 8
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"direction": [
|
||||
"math.random(-10,10)",
|
||||
"math.random(-0.1,4)*3+0.5",
|
||||
"math.random(-10,10)"
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_spin": {
|
||||
"rotation": "(math.random_integer(1,4)*90)"
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(4,5)*3",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_drag_coefficient": 3
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 96,
|
||||
"texture_height": 8,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
8,
|
||||
8
|
||||
],
|
||||
"step_UV": [
|
||||
8,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 30,
|
||||
"max_frame": 12
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+60
-41
@@ -1,43 +1,62 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientfeatherball/casual/sendflash",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/ancientfeatherball/casual/ancientfeathercasual"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_looping": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_point": {
|
||||
"offset": [0, 0.5, 0]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [1.25, 1.25],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 384,
|
||||
"texture_height": 32,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [32, 32],
|
||||
"step_UV": [32, 0],
|
||||
"frames_per_second": 30,
|
||||
"max_frame": 12
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientfeatherball/casual/sendflash",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/ancientfeatherball/casual/ancientfeathercasual"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_looping": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_point": {
|
||||
"offset": [
|
||||
0,
|
||||
0.5,
|
||||
0
|
||||
]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
1.25,
|
||||
1.25
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 384,
|
||||
"texture_height": 32,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
32,
|
||||
32
|
||||
],
|
||||
"step_UV": [
|
||||
32,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 30,
|
||||
"max_frame": 12
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+64
-45
@@ -1,47 +1,66 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientgigatonball/ballsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/ancientgigatonball/ancientgigatonballsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_steady": {
|
||||
"spawn_rate": 24,
|
||||
"max_particles": 16
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 0.5
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"offset": [0, 1.5, 0],
|
||||
"radius": "math.random(0.5,1.5)*1.5",
|
||||
"surface_only": true,
|
||||
"direction": "outwards"
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0.75,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.2, 0.2],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 36,
|
||||
"texture_height": 9,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [9, 9],
|
||||
"step_UV": [9, 0],
|
||||
"frames_per_second": 12,
|
||||
"max_frame": 4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:ancientgigatonball/ballsparkle",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/balls/ancientgigatonball/ancientgigatonballsparkle"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_steady": {
|
||||
"spawn_rate": 24,
|
||||
"max_particles": 16
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 0.5
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"offset": [
|
||||
0,
|
||||
1.5,
|
||||
0
|
||||
],
|
||||
"radius": "math.random(0.5,1.5)*1.5",
|
||||
"surface_only": true,
|
||||
"direction": "outwards"
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0.75,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [
|
||||
0.2,
|
||||
0.2
|
||||
],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 36,
|
||||
"texture_height": 9,
|
||||
"flipbook": {
|
||||
"base_UV": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"size_UV": [
|
||||
9,
|
||||
9
|
||||
],
|
||||
"step_UV": [
|
||||
9,
|
||||
0
|
||||
],
|
||||
"frames_per_second": 12,
|
||||
"max_frame": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"cobblemon:emitter_space": {
|
||||
"scaling": "entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user