forked from mirrors/cobblemon
Compare commits
76
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
376a420474 | ||
|
|
a8e2db25f8 | ||
|
|
2bb85718d7 | ||
|
|
ee187d7b89 | ||
|
|
3532cac278 | ||
|
|
1447ab25b4 | ||
|
|
9a06ca78c6 | ||
|
|
f6ba70634b | ||
|
|
148fd04a93 | ||
|
|
17f60623ee | ||
|
|
c5ece27c11 | ||
|
|
296ccd1a76 | ||
|
|
08b58e2f78 | ||
|
|
62d2b8db2d | ||
|
|
3869f7ed93 | ||
|
|
c9c44872d6 | ||
|
|
cae53efedc | ||
|
|
5fac24cee8 | ||
|
|
1954dfec80 | ||
|
|
2eea2b64c2 | ||
|
|
a127a93be8 | ||
|
|
9b32f85817 | ||
|
|
ec139d2677 | ||
|
|
4327be0cf9 | ||
|
|
c25c832b31 | ||
|
|
eabaabc535 | ||
|
|
9acf97f5a0 | ||
|
|
24fc212c76 | ||
|
|
04f88bdd63 | ||
|
|
a4eb58aa57 | ||
|
|
6704d4e5ee | ||
|
|
c88087de29 | ||
|
|
86bb802140 | ||
|
|
6b644b384d | ||
|
|
c370af8914 | ||
|
|
1cd6d2bfc7 | ||
|
|
1edeae2a60 | ||
|
|
409f1056b9 | ||
|
|
d8c470db3d | ||
|
|
c642c4b84b | ||
|
|
0b80f7e547 | ||
|
|
d543f45607 | ||
|
|
2b4fdfd219 | ||
|
|
1a3b655d3f | ||
|
|
1f5f278970 | ||
|
|
0b4eb5239a | ||
|
|
118e8f6205 | ||
|
|
cf126c5906 | ||
|
|
645cf61911 | ||
|
|
87d5ede3dd | ||
|
|
203e5d89cd | ||
|
|
ce611cc61c | ||
|
|
f6ad7ff865 | ||
|
|
d69627a9c8 | ||
|
|
54e8763470 | ||
|
|
db34687df0 | ||
|
|
7f008d85ff | ||
|
|
06ebf51078 | ||
|
|
39c5bcd73c | ||
|
|
8f5f158b60 | ||
|
|
3bc1e35125 | ||
|
|
460bedddae | ||
|
|
8b64c315f3 | ||
|
|
7c824a2b72 | ||
|
|
9dac604a93 | ||
|
|
8540a73885 | ||
|
|
25ce784a60 | ||
|
|
5358cccb62 | ||
|
|
698fa9dff9 | ||
|
|
a8949cf1f9 | ||
|
|
61db6334f9 | ||
|
|
46d278ca55 | ||
|
|
339038956d | ||
|
|
116a93d8cc | ||
|
|
acebc35d3f | ||
|
|
aee89f1c92 |
+34
-2
@@ -6,17 +6,35 @@
|
||||
- Added the Partner Mark, which party Pokémon have a very small chance to earn as the player walks, provided they have enough friendship.
|
||||
- Added trades for Saccharine Saplings, Hearty Grains, Chipped Pot, and Masterpiece Teacup to the Wandering Trader.
|
||||
- Added brewing recipe for Throat Spray.
|
||||
- Added new effects
|
||||
- Mental Restoration: Reduces "Time Since Last Rest" statistic, which controls Insomnia, by half a minute per second per effect level
|
||||
- Negative Effect Cleanse: Removes all negative effects
|
||||
- Effect Cleanse: Removes all effects
|
||||
- Added more seasonings for sinister tea
|
||||
- Mental Herb - Mental Restoration I for 10 seconds
|
||||
- White Herb - Negative Effect Cleanse
|
||||
- Milk - Effect Cleanse
|
||||
- Moomoo Milk - Effect Cleanse
|
||||
- Added `label` as an alternate key to the `tag` property.
|
||||
- Added Saccharine wood furniture for Adorn.
|
||||
|
||||
### Changes
|
||||
- Ride sounds have been separated into stereo for passengers and mono for other players. Riding will now sound more spacious.
|
||||
- Added a new config option, `Enable In-Flight Dismounting` (default: off), which lets you dismount while riding a Pokémon in the air.
|
||||
- Battle AI now uses a smarter threshold for switching, reducing unnecessary switches.
|
||||
- AI will always use the most damaging move when at low HP and when it is not switching, improving endgame decision-making.
|
||||
- Added support for optional message variants in battle activate instructions for more context-specific battle text.
|
||||
- Example: `this.add('-activate', pokemon, 'ability: example', '[msg]message1');` will parse to lang key `cobblemon.battle.activate.example.message1`
|
||||
|
||||
### Fixes
|
||||
- Fixed an issue in the OmniPathNodeMaker/Navigation that prevented Combees from pathing into and out of Saccharine leaves.
|
||||
- Fixed orientation not getting reset after crashing while flying and getting back on the Pokémon.
|
||||
- Fixed Furfrou not being trimmable on NeoForge.
|
||||
- Fixed shiny Pokémon not respecting the silent flag on spawn.
|
||||
- Fixed honey from Saccharine Leaves being harvestable at less than the max age.
|
||||
- Items given from interacting with Saccharine Leaves are placed in the active hotbar slot if possible.
|
||||
- Fix all Pokémon being saved to chunks and never despawning.
|
||||
- Fixed possible error on world generation when Combees are placed in naturally generated bee nests.
|
||||
- Fixed PokeSnacks crashing if there was no available spawn.
|
||||
- Fixed Pokémon spawn influences not being specific to regional forms
|
||||
- Fixed crashing when viewing another player in spectator mode
|
||||
@@ -25,15 +43,29 @@
|
||||
- Fixed mochi items consuming two items at a time
|
||||
- Fix item interaction sometimes not working properly when playing on servers.
|
||||
- Fixed Soothe Bell not being properly tagged as a held item.
|
||||
- Fixed Mint Leaves not being usable for filling the Resurrection Machine.
|
||||
- Added Saccharine Boats and Saccharine Boat with Chests to relevant boat tags.
|
||||
- Fixed the `run_script` Molang function to not fail if the environment's context is null.
|
||||
- Fixed the movesets of certain Pokémon being incorrectly sanitized upon reload.
|
||||
- Fixed the ordering of Aprijuice's riding stat boosts to always have the same order.
|
||||
- Fixed the Molang functions `date_local_time`, `date_of`, `date_is_after` to use the correct date format.
|
||||
- Fixed the bottom half of pasture blocks having an incorrect hit-box when facing north or south.
|
||||
|
||||
- Fixed Galarian Mr. Mime incorrectly being rideable.
|
||||
- Fixed gimmicks not being usable in double / triple battles
|
||||
- Fixed gimmick buttons showing when already used in the same turn in double / triple battles
|
||||
- Fixed Apricorn block model rotation for counters/sinks/cupboards/drawers to match that of most recent version of Adorn.
|
||||
- Fixed Scraggy & Scrafty being able to spawn on non-natural blocks in badlands
|
||||
|
||||
### Developer
|
||||
- Changed the `owner` parameter in the `OwnerQueryRequirement` interface from `ServerPlayer` to `Player`. This method is now also called on the client to verify whether a Pokémon interaction succeeded, so make sure to update your implementations to handle both server and client contexts.
|
||||
- Changed the `owner` parameter in the `OwnerQueryRequirement` interface from `ServerPlayer` to `Player`. This method is now also called on the client to verify whether a Pokémon interaction succeeded, so make sure to update your implementations to handle both server and client contexts.
|
||||
|
||||
### Molang & Datapacks
|
||||
- Ride sounds can now be set as exclusive to passengers
|
||||
- Ride sounds no longer play when submerged unless specified with a new setting
|
||||
- Exception handling has been added to `run_molang`, resolving some crashes caused by malformed MoLang expressions.
|
||||
|
||||
### Particles
|
||||
|
||||
### Localization
|
||||
- Updated translations for:
|
||||
- Updated translations for:
|
||||
|
||||
@@ -11,7 +11,9 @@ package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories;
|
||||
import com.cobblemon.mod.common.api.ai.config.task.PathToBeeHiveTaskConfig;
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.world.feature.SaccharineTreeFeature;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
@@ -42,7 +44,21 @@ public abstract class BeeOccupantMixin {
|
||||
if (cir.getReturnValue() == null) {
|
||||
final BeehiveBlockEntity.Occupant occupant = (BeehiveBlockEntity.Occupant) (Object) this;
|
||||
CompoundTag compoundTag = occupant.entityData().copyTag();
|
||||
Entity entity = EntityType.loadEntityRecursive(compoundTag, level, (entityx) -> entityx);
|
||||
String id = compoundTag.getString("id");
|
||||
Entity entity = null;
|
||||
if (id.equals(SaccharineTreeFeature.Companion.getPOKEMON_PLACEHOLD_ID())) {
|
||||
// Special case for Pokemon stuffed into a beenest upon world gen.
|
||||
// For technical reasons we cannot create them as full entities during world gen.
|
||||
// So we look for this special id tag and complete the entity when it attempts to exit a hive.
|
||||
if (compoundTag.contains("pokemonProperties")) {
|
||||
String properties = compoundTag.getString("pokemonProperties");
|
||||
PokemonProperties pokemon = PokemonProperties.Companion.parse(properties);
|
||||
entity = pokemon.createEntity(level);
|
||||
}
|
||||
} else {
|
||||
entity = EntityType.loadEntityRecursive(compoundTag, level, (entityx) -> entityx);
|
||||
}
|
||||
|
||||
if (entity instanceof PokemonEntity pokemonEntity) {
|
||||
var state = level.getBlockState(pos);
|
||||
var newPos = Vec3.ZERO;
|
||||
|
||||
@@ -91,7 +91,7 @@ import com.cobblemon.mod.common.pokemon.feature.SlowpokeTailRegrowthSpeciesFeatu
|
||||
import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.pokemon.properties.*
|
||||
import com.cobblemon.mod.common.pokemon.properties.tags.PokemonFlagProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.LabelProperty
|
||||
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
|
||||
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
|
||||
import com.cobblemon.mod.common.util.*
|
||||
@@ -201,6 +201,7 @@ object Cobblemon {
|
||||
implementation.registerEntityDataSerializers()
|
||||
implementation.registerCriteria()
|
||||
implementation.registerEntitySubPredicates()
|
||||
implementation.registerMobEffects()
|
||||
DispenserBehaviorRegistry.registerDispenserBehaviors()
|
||||
|
||||
DropEntry.register("command", CommandDropEntry::class.java)
|
||||
@@ -314,7 +315,7 @@ object Cobblemon {
|
||||
|
||||
CustomPokemonProperty.register(UncatchableProperty)
|
||||
CustomPokemonProperty.register(BattleCloneProperty)
|
||||
CustomPokemonProperty.register(PokemonFlagProperty)
|
||||
CustomPokemonProperty.register(LabelProperty)
|
||||
CustomPokemonProperty.register(HiddenAbilityPropertyType)
|
||||
CustomPokemonProperty.register(AspectPropertyType)
|
||||
CustomPokemonProperty.register(UnaspectPropertyType)
|
||||
|
||||
@@ -117,6 +117,11 @@ interface CobblemonImplementation {
|
||||
|
||||
fun registerEntitySubPredicates()
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
fun registerMobEffects()
|
||||
|
||||
|
||||
/**
|
||||
* Add a feature to the current platform implementation.
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.api.cooking.effects.CleanseAllEffect
|
||||
import com.cobblemon.mod.common.api.cooking.effects.CleanseNegativeEffect
|
||||
import com.cobblemon.mod.common.api.cooking.effects.MentalRestorationEffect
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
|
||||
object CobblemonMobEffects : PlatformRegistry<Registry<MobEffect>, ResourceKey<Registry<MobEffect>>, MobEffect>() {
|
||||
override val registry: Registry<MobEffect> = BuiltInRegistries.MOB_EFFECT
|
||||
override val resourceKey: ResourceKey<Registry<MobEffect>> = Registries.MOB_EFFECT
|
||||
|
||||
@JvmField
|
||||
val CLEANSE_NEGATIVE = create("cleanse_negative", CleanseNegativeEffect())
|
||||
|
||||
@JvmField
|
||||
val MENTAL_RESTORATION = create("mental_restoration", MentalRestorationEffect())
|
||||
|
||||
@JvmField
|
||||
val CLEANSE_ALL = create("cleanse_all", CleanseAllEffect())
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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.cooking.effects
|
||||
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
import net.minecraft.world.effect.MobEffectCategory
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
class CleanseAllEffect : MobEffect(MobEffectCategory.BENEFICIAL, 0xFFFFFF) {
|
||||
override fun isInstantenous() = true
|
||||
override fun applyInstantenousEffect(source: Entity?, indirect: Entity?, target: LivingEntity, amplifier: Int, proximity: Double) {
|
||||
target.removeAllEffects()
|
||||
}
|
||||
override fun shouldApplyEffectTickThisTick(duration: Int, amplifier: Int) = false
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.cooking.effects
|
||||
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
import net.minecraft.world.effect.MobEffectCategory
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
class CleanseNegativeEffect : MobEffect(MobEffectCategory.BENEFICIAL, 0xFFFFFF) {
|
||||
override fun isInstantenous() = true
|
||||
override fun applyInstantenousEffect(source: Entity?, indirect: Entity?, target: LivingEntity, amplifier: Int, proximity: Double) {
|
||||
val snapshot = target.activeEffects.toList()
|
||||
for (ei in snapshot) {
|
||||
if (ei.effect.value().category == MobEffectCategory.HARMFUL) {
|
||||
target.removeEffect(ei.effect)
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun shouldApplyEffectTickThisTick(duration: Int, amplifier: Int) = false
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.cooking.effects
|
||||
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.stats.Stats
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
import net.minecraft.world.effect.MobEffectCategory
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
class MentalRestorationEffect : MobEffect(MobEffectCategory.BENEFICIAL, 0xAA66FF) {
|
||||
override fun applyEffectTick(entity: LivingEntity, amplifier: Int): Boolean {
|
||||
if (entity is ServerPlayer) {
|
||||
val stats = entity.stats
|
||||
val statType = Stats.CUSTOM.get(Stats.TIME_SINCE_REST)
|
||||
val current = stats.getValue(statType)
|
||||
val reduction = 31 * (amplifier + 1)// reduce by half a minute every second per level (30 ticks removed per tick + 1 to account for the tick passing)
|
||||
val newValue = Math.max(current - reduction, 0)
|
||||
stats.setValue(entity, statType, newValue)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun shouldApplyEffectTickThisTick(duration: Int, amplifier: Int): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -311,7 +311,7 @@ object MoLangFunctions {
|
||||
runtime.environment.variable = params.environment.variable
|
||||
val args = params.params.subList(1, params.params.size)
|
||||
runtime.environment.context = ContextStruct(
|
||||
params.environment.context.map + args.mapIndexed { index, value -> "arg_${index + 1}" to value }.toMap()
|
||||
(params.environment.context?.map ?: emptyMap()) + args.mapIndexed { index, value -> "arg_${index + 1}" to value }.toMap()
|
||||
)
|
||||
val script = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
// store the args in the
|
||||
@@ -324,13 +324,24 @@ object MoLangFunctions {
|
||||
runtime.environment.context = params.environment.context
|
||||
val expression = params.getString(0).asExpressionLike()
|
||||
val delayInSeconds = params.getDoubleOrNull(1)?.toFloat() ?: 0.0f
|
||||
|
||||
fun evaluate(): MoValue {
|
||||
return try {
|
||||
runtime.resolve(expression)
|
||||
} catch (ex: Exception) {
|
||||
Cobblemon.LOGGER.warn("Failed to evaluate MoLang expression${if (delayInSeconds > 0.0f) " (delayed)" else ""}: $expression", ex)
|
||||
DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
|
||||
if (delayInSeconds > 0.0f) {
|
||||
val tracker = if (Cobblemon.implementation.environment() == Environment.SERVER) ServerTaskTracker else ClientTaskTracker
|
||||
tracker.after(delayInSeconds) {
|
||||
runtime.resolve(expression)
|
||||
evaluate()
|
||||
}
|
||||
DoubleValue.ONE
|
||||
} else {
|
||||
runtime.resolve(expression)
|
||||
evaluate()
|
||||
}
|
||||
},
|
||||
"system_time_millis" to java.util.function.Function { _ ->
|
||||
@@ -340,19 +351,19 @@ object MoLangFunctions {
|
||||
"date_local_time" to java.util.function.Function { _ ->
|
||||
val time = System.currentTimeMillis()
|
||||
val date = java.util.Date(time)
|
||||
val formatted = java.text.SimpleDateFormat("DD/MM/YYYY").format(date)
|
||||
val formatted = java.text.SimpleDateFormat("dd/MM/yyyy").format(date)
|
||||
StringValue(formatted)
|
||||
},
|
||||
"date_of" to java.util.function.Function { params ->
|
||||
val time = params.getDouble(0).toLong()
|
||||
val date = java.util.Date(time)
|
||||
val formatted = java.text.SimpleDateFormat("DD/MM/YYYY").format(date)
|
||||
val formatted = java.text.SimpleDateFormat("dd/MM/yyyy").format(date)
|
||||
StringValue(formatted)
|
||||
},
|
||||
"date_is_after" to java.util.function.Function { params ->
|
||||
val dateA = params.getString(0)
|
||||
val dateB = params.getString(1)
|
||||
val format = java.text.SimpleDateFormat("DD/MM/YYYY")
|
||||
val format = java.text.SimpleDateFormat("dd/MM/yyyy")
|
||||
val a = format.parse(dateA)
|
||||
val b = format.parse(dateB)
|
||||
DoubleValue(a.after(b))
|
||||
|
||||
+10
-8
@@ -80,7 +80,9 @@ open class ChoiceSpeciesFeatureProvider(
|
||||
|
||||
internal constructor(): this(emptyList())
|
||||
|
||||
override fun get(pokemon: Pokemon) = pokemon.getFeature<StringSpeciesFeature>(keys.first())
|
||||
override fun get(pokemon: Pokemon): StringSpeciesFeature? {
|
||||
return pokemon.features.filterIsInstance<StringSpeciesFeature>().find { it.name in keys }
|
||||
}
|
||||
|
||||
override fun invoke(pokemon: Pokemon): StringSpeciesFeature? {
|
||||
val existing = get(pokemon)
|
||||
@@ -101,15 +103,15 @@ open class ChoiceSpeciesFeatureProvider(
|
||||
}
|
||||
|
||||
override fun invoke(nbt: CompoundTag): StringSpeciesFeature? {
|
||||
return if (nbt.contains(keys.first())) {
|
||||
StringSpeciesFeature(keys.first(), "").also { it.loadFromNBT(nbt) }
|
||||
} else null
|
||||
val key = keys.find { nbt.contains(it) }
|
||||
if (key == null) return null
|
||||
return StringSpeciesFeature(key, "").also { it.loadFromNBT(nbt) }
|
||||
}
|
||||
|
||||
override fun invoke(json: JsonObject): StringSpeciesFeature? {
|
||||
return if (json.has(keys.first())) {
|
||||
StringSpeciesFeature(keys.first(), "").also { it.loadFromJSON(json) }
|
||||
} else null
|
||||
val key = keys.find { json.has(it) }
|
||||
if (key == null) return null
|
||||
return StringSpeciesFeature(key, "").also { it.loadFromJSON(json) }
|
||||
}
|
||||
|
||||
override fun fromString(value: String?): StringSpeciesFeature? {
|
||||
@@ -131,7 +133,7 @@ open class ChoiceSpeciesFeatureProvider(
|
||||
|
||||
override fun provide(properties: PokemonProperties): Set<String> {
|
||||
return if (isAspect) {
|
||||
val feature = properties.customProperties.filterIsInstance<StringSpeciesFeature>().find { it.name == keys.first() }
|
||||
val feature = properties.customProperties.filterIsInstance<StringSpeciesFeature>().find { it.name in keys }
|
||||
if (feature != null) {
|
||||
setOf(getAspect(feature))
|
||||
} else {
|
||||
|
||||
+23
-11
@@ -132,7 +132,9 @@ class FlagSpeciesFeatureProvider : SynchronizedSpeciesFeatureProvider<FlagSpecie
|
||||
|
||||
constructor(vararg keys: String) : this(keys.toList())
|
||||
|
||||
override fun get(pokemon: Pokemon) = pokemon.getFeature<FlagSpeciesFeature>(keys.first())
|
||||
override fun get(pokemon: Pokemon): FlagSpeciesFeature? {
|
||||
return pokemon.features.filterIsInstance<FlagSpeciesFeature>().find { it.name in keys }
|
||||
}
|
||||
|
||||
override fun invoke(pokemon: Pokemon): FlagSpeciesFeature? {
|
||||
return get(pokemon)
|
||||
@@ -144,15 +146,15 @@ class FlagSpeciesFeatureProvider : SynchronizedSpeciesFeatureProvider<FlagSpecie
|
||||
}
|
||||
|
||||
override fun invoke(nbt: CompoundTag): FlagSpeciesFeature? {
|
||||
return if (nbt.contains(keys.first())) {
|
||||
FlagSpeciesFeature(keys.first(), false).also { it.loadFromNBT(nbt) }
|
||||
} else null
|
||||
val key = keys.find { nbt.contains(it) }
|
||||
if (key == null) return null
|
||||
return FlagSpeciesFeature(key, false).also { it.loadFromNBT(nbt) }
|
||||
}
|
||||
|
||||
override fun invoke(json: JsonObject): FlagSpeciesFeature? {
|
||||
return if (json.has(keys.first())) {
|
||||
FlagSpeciesFeature(keys.first(), false).also { it.loadFromJSON(json) }
|
||||
} else null
|
||||
val key = keys.find { json.has(it) }
|
||||
if (key == null) return null
|
||||
return FlagSpeciesFeature(key, false).also { it.loadFromJSON(json) }
|
||||
}
|
||||
|
||||
override fun fromString(value: String?): FlagSpeciesFeature? {
|
||||
@@ -170,16 +172,26 @@ class FlagSpeciesFeatureProvider : SynchronizedSpeciesFeatureProvider<FlagSpecie
|
||||
}
|
||||
|
||||
override fun provide(pokemon: Pokemon): Set<String> {
|
||||
return if (isAspect && pokemon.getFeature<FlagSpeciesFeature>(keys.first())?.enabled == true) {
|
||||
setOf(keys.first())
|
||||
return if (isAspect) {
|
||||
val feature = pokemon.features.filterIsInstance<FlagSpeciesFeature>().find { it.name in keys }
|
||||
if (feature != null && feature.enabled) {
|
||||
setOf(keys.first())
|
||||
} else {
|
||||
emptySet()
|
||||
}
|
||||
} else {
|
||||
emptySet()
|
||||
}
|
||||
}
|
||||
|
||||
override fun provide(properties: PokemonProperties): Set<String> {
|
||||
return if (isAspect && properties.customProperties.filterIsInstance<FlagSpeciesFeature>().find { it.name == keys.first() }?.enabled == true) {
|
||||
setOf(keys.first())
|
||||
return if (isAspect) {
|
||||
val feature = properties.customProperties.filterIsInstance<FlagSpeciesFeature>().find { it.name in keys }
|
||||
if (feature != null && feature.enabled) {
|
||||
setOf(keys.first())
|
||||
} else {
|
||||
emptySet()
|
||||
}
|
||||
} else {
|
||||
emptySet()
|
||||
}
|
||||
|
||||
+6
-10
@@ -142,19 +142,15 @@ class IntSpeciesFeatureProvider : SynchronizedSpeciesFeatureProvider<IntSpeciesF
|
||||
}
|
||||
|
||||
override fun invoke(nbt: CompoundTag): IntSpeciesFeature? {
|
||||
return if (nbt.contains(keys.first())) {
|
||||
IntSpeciesFeature(keys.first(), nbt.getInt(keys.first()))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val key = keys.find { nbt.contains(it) }
|
||||
if (key == null) return null
|
||||
return IntSpeciesFeature(keys.first(), nbt.getInt(key));
|
||||
}
|
||||
|
||||
override fun invoke(json: JsonObject): IntSpeciesFeature? {
|
||||
return if (json.has(keys.first())) {
|
||||
IntSpeciesFeature(keys.first(), json.get(keys.first()).asInt)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val key = keys.find { json.has(it) }
|
||||
if (key == null) return null
|
||||
return IntSpeciesFeature(keys.first(), json.get(key).asInt)
|
||||
}
|
||||
|
||||
override fun get(pokemon: Pokemon) = pokemon.features.filterIsInstance<IntSpeciesFeature>().find { it.name in keys }
|
||||
|
||||
@@ -105,12 +105,18 @@ data class BattleFormat(
|
||||
}
|
||||
|
||||
fun toFormatJSON(): String {
|
||||
/*
|
||||
Bag clause does not exist in showdown as a rule because showdown simply has no concept of a 'bag'.
|
||||
If we try sending it, the battle will error. So this simply omits that from ever getting sent.
|
||||
If we ever find a case where we are doing this for more than just bag clause, we should make a proper abstraction.
|
||||
*/
|
||||
val rulesToSendToShowdown = ruleSet.filter { it != BattleRules.BAG_CLAUSE }
|
||||
return """
|
||||
{
|
||||
"mod": "$mod",
|
||||
"gameType": "${battleType.name}",
|
||||
"gen": $gen,
|
||||
"ruleset": [${ruleSet.joinToString { "\"$it\"" }}],
|
||||
"ruleset": [${rulesToSendToShowdown.joinToString { "\"$it\"" }}],
|
||||
"effectType": "Format"
|
||||
}
|
||||
""".trimIndent().replace("\n", "")
|
||||
|
||||
@@ -12,6 +12,7 @@ object BattleRules {
|
||||
const val OBTAINABLE = "Obtainable"
|
||||
const val PAST = "+Past"
|
||||
const val UNOBTAINABLE = "+Unobtainable"
|
||||
const val BAG_CLAUSE = "Bag Clause"
|
||||
const val TEAM_PREVIEW = "Team Preview"
|
||||
const val ENDLESS_BATTLE_CLAUSE = "Endless Battle Clause"
|
||||
const val CANCEL_MOD = "Cancel Mod"
|
||||
|
||||
@@ -289,6 +289,8 @@ class ShowdownMoveset {
|
||||
var canDynamax = false
|
||||
var maxMoves: List<InBattleGimmickMove?>? = null
|
||||
var canTerastallize: String? = null
|
||||
/** This stores a list of gimmicks that have already been used this turn by a previous Pokemon, but the full turn has not been processed (ie. double battles). */
|
||||
val pendingGimmickUsedThisTurn = mutableListOf<Gimmick>()
|
||||
|
||||
fun saveToBuffer(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeSizedInt(IntSize.U_BYTE, moves.size)
|
||||
|
||||
@@ -31,6 +31,7 @@ import kotlin.collections.associateWith
|
||||
import kotlin.collections.partition
|
||||
import kotlin.math.absoluteValue
|
||||
|
||||
|
||||
/**
|
||||
* AI that tries to choose the best move for the given situations. Based off of the Pokemon Trainer Tournament Simulator Github
|
||||
* https://github.com/cRz-Shadows/Pokemon_Trainer_Tournament_Simulator/blob/main/pokemon-showdown/sim/examples/Simulation-test-1.ts#L330
|
||||
@@ -271,6 +272,11 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
}
|
||||
activeTrackerPokemon.firstTurn = false
|
||||
|
||||
// If HP is below 30% and not switching out, always use the most damaging move
|
||||
if (activeTrackerPokemon.currentHpPercent < 0.3 && !shouldSwitchOut(aiSide, battle, activeBattlePokemon, moveset)) {
|
||||
findAndUseMostDamagingMove(activeBattlePokemon, activeTrackerPokemon, opponents, availableMoves, moveset, battle, aiSide)?.let { return it }
|
||||
}
|
||||
|
||||
// Decision-making based on move availability and switch-out condition
|
||||
if (!shouldSwitchOut(aiSide, battle, activeBattlePokemon, moveset)) {
|
||||
val nRemainingMons = activeTracker.alliedSide.actors.sumOf { actor -> actor.party.filter { it.currentHpPercent > 0 }.size }
|
||||
@@ -521,6 +527,19 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
|
||||
val opponentActiveTracker = activeTracker.opponentSide.activePokemon
|
||||
val opponentSpeedEstimations = opponentActiveTracker.map { statEstimationActive(it, Stats.SPEED) }
|
||||
|
||||
|
||||
// Only switch if a switch-in is significantly better than the current Pokémon
|
||||
val currentScore = estimateMatchup(activeBattlePokemon, side, battle)
|
||||
val bestSwitchScore = availableSwitches.maxOfOrNull { estimateMatchup(activeBattlePokemon, side, battle, it) } ?: currentScore
|
||||
val improvementThreshold = currentScore.absoluteValue * 0.25 + 2
|
||||
if (bestSwitchScore <= currentScore + improvementThreshold) {
|
||||
return false
|
||||
}
|
||||
|
||||
if(bestSwitchScore < 1) {
|
||||
return false
|
||||
}
|
||||
// todo add some way to keep track of the player's boosting to see if it needs to switch out to something that can stop it
|
||||
|
||||
// if slower speed stat than the opposing pokemon and HP is less than 20% don't switch out
|
||||
@@ -548,6 +567,8 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
if (availableSwitches.isEmpty() || availableSwitches.none { estimateMatchup(activeBattlePokemon, side, battle, it) > 0 })
|
||||
return false
|
||||
|
||||
|
||||
|
||||
// ...and a 'good' reason to switch out
|
||||
if (opponentActiveTracker.any { it.boosts.getOrDefault(Stats.ACCURACY, 0) <= accuracySwitchThreshold } ||
|
||||
opponentActiveTracker.any { it.boosts.getOrDefault(Stats.DEFENCE, 0) <= -3 } ||
|
||||
|
||||
+8
-1
@@ -114,7 +114,14 @@ class ActivateInstruction(val instructionSet: InstructionSet, val message: Battl
|
||||
}
|
||||
"maxguard", "protect" -> battleLang("activate.protect", pokemonName)
|
||||
"shadowforce", "hyperspacefury", "hyperspacehole" -> battleLang("activate.phantomforce", pokemonName)
|
||||
else -> battleLang("activate.${effect.id}", pokemonName, sourceName, extraEffect)
|
||||
else -> {
|
||||
val msgVariant = message.optionalArgument("msg")
|
||||
if (msgVariant != null) {
|
||||
battleLang("activate.${effect.id}.$msgVariant", pokemonName, sourceName, extraEffect)
|
||||
} else {
|
||||
battleLang("activate.${effect.id}", pokemonName, sourceName, extraEffect)
|
||||
}
|
||||
}
|
||||
}
|
||||
battle.broadcastChatMessage(lang)
|
||||
//We check holds here so the chat msg + particle effect happen more concurrently, instead of sequentially
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.cobblemon.mod.common.util.isInBattle
|
||||
import com.cobblemon.mod.common.util.playSoundServer
|
||||
import com.cobblemon.mod.common.util.toVec3d
|
||||
import com.cobblemon.mod.common.util.voxelShape
|
||||
import com.cobblemon.mod.common.util.rotateShape
|
||||
import com.mojang.serialization.MapCodec
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
@@ -71,10 +72,10 @@ class PastureBlock(settings: Properties): BaseEntityBlock(settings), SimpleWater
|
||||
private val WEST_AABB_TOP = buildCollider(top = true, Direction.WEST)
|
||||
private val EAST_AABB_TOP = buildCollider(top = true, Direction.EAST)
|
||||
|
||||
private val SOUTH_AABB_BOTTOM = buildCollider(top = false, Direction.SOUTH)
|
||||
private val NORTH_AABB_BOTTOM = buildCollider(top = false, Direction.NORTH)
|
||||
private val WEST_AABB_BOTTOM = buildCollider(top = false, Direction.WEST)
|
||||
private val EAST_AABB_BOTTOM = buildCollider(top = false, Direction.EAST)
|
||||
private val SOUTH_AABB_BOTTOM = rotateShape(Direction.EAST, Direction.SOUTH, EAST_AABB_BOTTOM)
|
||||
private val NORTH_AABB_BOTTOM = rotateShape(Direction.EAST, Direction.NORTH, EAST_AABB_BOTTOM)
|
||||
private val WEST_AABB_BOTTOM = rotateShape(Direction.EAST, Direction.WEST, EAST_AABB_BOTTOM)
|
||||
|
||||
private fun buildCollider(top: Boolean, direction: Direction): VoxelShape {
|
||||
if (top) {
|
||||
|
||||
@@ -11,10 +11,11 @@ package com.cobblemon.mod.common.client.battle
|
||||
import com.cobblemon.mod.common.CobblemonNetwork
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.battles.BattleFormat
|
||||
import com.cobblemon.mod.common.battles.ForcePassActionResponse
|
||||
import com.cobblemon.mod.common.battles.MoveActionResponse
|
||||
import com.cobblemon.mod.common.battles.PassActionResponse
|
||||
import com.cobblemon.mod.common.battles.ShowdownMoveset
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
@@ -61,8 +62,15 @@ class ClientBattle(
|
||||
if (index != -1) {
|
||||
while(index < pendingActionRequests.size) {
|
||||
val request = pendingActionRequests[index]
|
||||
if (request.response != PassActionResponse && request.response !is ForcePassActionResponse)
|
||||
if (request.response != PassActionResponse && request.response !is ForcePassActionResponse) {
|
||||
val response = request.response
|
||||
// If we're cancelling a turn that used a gimmick, we re-enable the ability for that gimmick to be used.
|
||||
if (response is MoveActionResponse && response.gimmickID != null) {
|
||||
val gimmick = ShowdownMoveset.Gimmick.entries.find { it.id == response.gimmickID }
|
||||
pendingActionRequests.forEach { it.moveSet?.pendingGimmickUsedThisTurn?.remove(gimmick) }
|
||||
}
|
||||
request.response = null
|
||||
}
|
||||
index++
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ class BattleMoveSelection(
|
||||
var moveTiles = baseTiles
|
||||
|
||||
val backButton = BattleBackButton(x - 11F, Minecraft.getInstance().window.guiScaledHeight - 22F)
|
||||
val gimmickButtons = moveSet.getGimmicks().mapIndexed { index, gimmick ->
|
||||
val gimmickButtons = moveSet.getGimmicks().filter { it !in moveSet.pendingGimmickUsedThisTurn }.mapIndexed { index, gimmick ->
|
||||
val initOff = BattleBackButton.WIDTH * 0.65F
|
||||
val xOff = initOff + BattleGimmickButton.SPACING * index
|
||||
BattleGimmickButton.create(gimmick, this, backButton.x + xOff, backButton.y)
|
||||
|
||||
+9
-1
@@ -17,6 +17,7 @@ import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.battles.InBattleGimmickMove
|
||||
import com.cobblemon.mod.common.battles.InBattleMove
|
||||
import com.cobblemon.mod.common.battles.MoveActionResponse
|
||||
import com.cobblemon.mod.common.battles.ShowdownMoveset
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.battle.ActiveClientBattlePokemon
|
||||
@@ -127,7 +128,7 @@ class BattleTargetSelection(
|
||||
private val isMultiTarget = multiTargetList?.firstOrNull { it.getPNX() == target.getPNX() } != null
|
||||
private val isCurrentPokemon = request.activePokemon.battlePokemon?.uuid == target.battlePokemon!!.uuid
|
||||
|
||||
open val response: MoveActionResponse get() = MoveActionResponse(targetSelection.move.id, responseTarget)
|
||||
open val response: MoveActionResponse get() = MoveActionResponse(targetSelection.move.id, responseTarget, gimmickID)
|
||||
val state = FloatingState()
|
||||
|
||||
open val selectable: Boolean get() = isMultiTarget || (responseTarget != null)
|
||||
@@ -311,6 +312,13 @@ class BattleTargetSelection(
|
||||
fun onClick() {
|
||||
if (!selectable) return
|
||||
targetSelection.playDownSound(Minecraft.getInstance().soundManager)
|
||||
// If a gimmick is used, remove the ability to use it on any pending action requests ahead of it
|
||||
if (response.gimmickID != null) {
|
||||
val gimmick = ShowdownMoveset.Gimmick.entries.first { it.id == response.gimmickID }
|
||||
CobblemonClient.battle?.pendingActionRequests?.forEach {
|
||||
it.moveSet?.pendingGimmickUsedThisTurn?.add(gimmick)
|
||||
}
|
||||
}
|
||||
targetSelection.battleGUI.selectAction(targetSelection.request, response)
|
||||
}
|
||||
}
|
||||
|
||||
+9
-9
@@ -143,18 +143,18 @@ object PartySendBinding : CobblemonBlockingKeyBinding(
|
||||
}
|
||||
|
||||
private fun canAttemptDismount(player: LocalPlayer, selectedPartyPokemon: Pokemon?): Boolean {
|
||||
if (player.vehicle !is PokemonEntity) return false
|
||||
val vehicle = player.vehicle as PokemonEntity
|
||||
if (player != vehicle.controllingPassenger) {
|
||||
return true
|
||||
}
|
||||
val vehicle = player.vehicle as? PokemonEntity ?: return false
|
||||
|
||||
if (player != vehicle.controllingPassenger) return true
|
||||
|
||||
val isAirRide = vehicle.ridingController?.context?.style == RidingStyle.AIR
|
||||
val hasLandRide = vehicle.rideProp.behaviours?.get(RidingStyle.LAND) != null
|
||||
return if (isAirRide && hasLandRide) {
|
||||
false
|
||||
} else {
|
||||
vehicle.pokemon.uuid == selectedPartyPokemon?.uuid
|
||||
|
||||
if (!Cobblemon.config.enableInFlightDismounting && isAirRide && hasLandRide) {
|
||||
return false
|
||||
}
|
||||
|
||||
return vehicle.pokemon.uuid == selectedPartyPokemon?.uuid
|
||||
}
|
||||
|
||||
private fun isRidingPokemon(player: LocalPlayer, ignoreControlling: Boolean = false): Boolean {
|
||||
|
||||
+1
-1
@@ -206,7 +206,7 @@ fun generateAdditionalRideBoostsTooltip(stack: ItemStack): MutableList<Component
|
||||
val resultLines = mutableListOf<Component>()
|
||||
resultLines.add(rideBoostSeasoningHeader)
|
||||
|
||||
for ((stat, value) in boosts) {
|
||||
for ((stat, value) in boosts.toSortedMap()) {
|
||||
val statName = stat.displayName.also { it.style = it.style.withColor(stat.flavour.colour) }
|
||||
val valueText = if (value < 0) {
|
||||
Component.literal("$value").red()
|
||||
|
||||
@@ -329,6 +329,9 @@ class CobblemonConfig {
|
||||
@CobblemonConfigField(Category.Riding, lang = "remember_riding_camera", CLIENT)
|
||||
var rememberRidingCamera = false
|
||||
|
||||
@CobblemonConfigField(Category.Riding, lang = "enable_in_flight_dismounting", CLIENT)
|
||||
var enableInFlightDismounting = false
|
||||
|
||||
@CobblemonConfigField(Category.Debug, lang = "enable_debug_keys", CLIENT)
|
||||
var enableDebugKeys = false
|
||||
|
||||
|
||||
@@ -269,9 +269,6 @@ class OmniPathNavigation(val world: Level, val entity: Mob) : GroundPathNavigati
|
||||
// If we can fly and we're airborne, return the current Y position
|
||||
return vec.y
|
||||
}
|
||||
if (world.getBlockState(blockPos).block == CobblemonBlocks.SACCHARINE_LEAVES && pather.canPathThroughSaccLeaves()) {
|
||||
return vec.y + 0.5
|
||||
}
|
||||
return if ((canFloat()) && blockGetter.getFluidState(blockPos).`is`(FluidTags.WATER)) vec.y + 0.5 else super.getGroundY(vec)
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import juuxel.adorn.block.variant.CompatBlockVariantSet
|
||||
|
||||
class AdornCompatibility : CompatBlockVariantSet() {
|
||||
override fun getWoodVariants(): List<BlockVariant?>? {
|
||||
return this.createVariants({ BlockVariant.Wood(it) }, "apricorn")
|
||||
return this.createVariants({ BlockVariant.Wood(it) }, "apricorn", "saccharine")
|
||||
}
|
||||
|
||||
override fun getModId(): String? {
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.advancement.criterion.PokemonInteractContext
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.battles.BagItemActionResponse
|
||||
import com.cobblemon.mod.common.battles.BagItems
|
||||
import com.cobblemon.mod.common.battles.BattleRules
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
@@ -41,7 +42,7 @@ interface BagItemLike {
|
||||
fun handleInteraction(player: ServerPlayer, battlePokemon: BattlePokemon, stack: ItemStack): Boolean {
|
||||
val battle = battlePokemon.actor.battle
|
||||
val bagItem = getBagItem(stack) ?: return false
|
||||
if (!battlePokemon.actor.canFitForcedAction()) {
|
||||
if (!battlePokemon.actor.canFitForcedAction() || battle.format.ruleSet.contains(BattleRules.BAG_CLAUSE)) {
|
||||
player.sendSystemMessage(battleLang("bagitem.cannot").red())
|
||||
return false
|
||||
}
|
||||
|
||||
+10
-3
@@ -35,9 +35,16 @@ class SinisterTeaItem : Item(
|
||||
val effectsComponent = stack.get(CobblemonItemComponents.MOB_EFFECTS)
|
||||
|
||||
if (effectsComponent != null) {
|
||||
for (effect in effectsComponent.mobEffects) {
|
||||
val effectCopy = MobEffectInstance(effect)
|
||||
user.addEffect(effectCopy)
|
||||
for (raw in effectsComponent.mobEffects) {
|
||||
val inst = MobEffectInstance(raw)
|
||||
val holder = inst.effect
|
||||
val effect = holder.value()
|
||||
|
||||
if (effect.isInstantenous) {
|
||||
effect.applyInstantenousEffect(user as? Player, null, user, inst.amplifier, 1.0)
|
||||
} else {
|
||||
user.addEffect(inst)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-2
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.net.serverhandling.riding
|
||||
|
||||
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.net.messages.server.riding.DismountPokemonPacket
|
||||
import net.minecraft.server.MinecraftServer
|
||||
@@ -25,12 +26,16 @@ object DismountPokemonPacketHandler : ServerNetworkPacketHandler<DismountPokemon
|
||||
|
||||
val pokemon = player.vehicle as PokemonEntity
|
||||
if (!canPlayerStopRidingPokemon(pokemon, player)) return
|
||||
|
||||
val isRidingInAir = pokemon.ridingController?.context?.style == RidingStyle.AIR
|
||||
|
||||
if (pokemon.controllingPassenger == player) {
|
||||
pokemon.passengers.forEach { it.stopRiding() }
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
player.stopRiding()
|
||||
}
|
||||
|
||||
if (isRidingInAir) pokemon.setFlying(true)
|
||||
}
|
||||
|
||||
private fun canPlayerStopRidingPokemon(pokemon: PokemonEntity, player: ServerPlayer): Boolean {
|
||||
|
||||
@@ -199,6 +199,9 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
|
||||
var form = species.standardForm
|
||||
set(value) {
|
||||
// If nothing actually changed, avoid running heavy logic (e.g. updateMovesOnFormChange when the form hasn't really "changed")
|
||||
if (field == value) return
|
||||
|
||||
// Species updates already update HP but just a form change may require it
|
||||
// Moved to before the field was set else it won't actually do the hp calc proper <3
|
||||
val quotient = clamp(currentHealth / maxHealth.toFloat(), 0F, 1F)
|
||||
@@ -2144,16 +2147,26 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
*/
|
||||
open fun self(): Pokemon = this
|
||||
|
||||
|
||||
/**
|
||||
* Function that sanitizes specific form-related moves when the form of this Pokémon changes.
|
||||
* We only want to sanitize `form_change` moves here so that intended illegalities from the user are preserved.
|
||||
*
|
||||
* E.g, Removing Overheat from Rotom when it is no longer Rotom-Heat and the target form is not compatible with Overheat.
|
||||
*/
|
||||
private fun updateMovesOnFormChange(newForm: FormData) {
|
||||
if (this.isClient) {
|
||||
return
|
||||
}
|
||||
if (this.isClient) return
|
||||
|
||||
val oldFormChangeMoves = this.form.moves.formChangeMoves.toSet()
|
||||
|
||||
// Only remove moves that were provided by the old form's form-change moves AND are not learnable by the new form
|
||||
for (i in 0 until MoveSet.MOVE_COUNT) {
|
||||
val move = this.moveSet[i]
|
||||
if (move != null && !LearnsetQuery.ANY.canLearn(move.template, newForm.moves)) {
|
||||
if (move != null && move.template in oldFormChangeMoves) {
|
||||
this.moveSet.setMove(i, null)
|
||||
}
|
||||
}
|
||||
|
||||
val benchedIterator = this.benchedMoves.iterator()
|
||||
while (benchedIterator.hasNext()) {
|
||||
val benchedMove = benchedIterator.next()
|
||||
@@ -2161,11 +2174,18 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
benchedIterator.remove()
|
||||
}
|
||||
}
|
||||
// Add form change moves
|
||||
|
||||
// Add new form's form-change moves
|
||||
newForm.moves.formChangeMoves.forEach { move ->
|
||||
// Under the hood these check if the moves already exist
|
||||
this.benchedMoves.add(BenchedMove(move, 0))
|
||||
if (this.moveSet.filterNotNull().none { it.template == move }) {
|
||||
if (this.moveSet.hasSpace()) {
|
||||
this.moveSet.add(move.create())
|
||||
} else {
|
||||
this.benchedMoves.add(BenchedMove(move, 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If moveset is empty try to find one valid move to fill it
|
||||
if (this.moveSet.filterNotNull().isEmpty()) {
|
||||
val benchedMove = this.benchedMoves.firstOrNull()
|
||||
|
||||
@@ -562,8 +562,8 @@ class OmniPathNodeMaker : NodeEvaluator() {
|
||||
//// PathType.WALKABLE
|
||||
//// } else if (blockState.canPathfindThrough(world, pos, NavigationType.AIR) && !blockStateBelow.isSideSolid(world, below, Direction.UP, SideShapeType.FULL)) {
|
||||
//// PathType.OPEN
|
||||
// } else if (blockState.`is`(BlockTags.LEAVES) && blockState.block == CobblemonBlocks.SACCHARINE_LEAVES && canPathThroughLeaves()) {
|
||||
// return PathType.OPEN
|
||||
if (canPathThroughLeaves() && blockState.block == CobblemonBlocks.SACCHARINE_LEAVES)
|
||||
return PathType.OPEN
|
||||
// } else PathType.BLOCKED
|
||||
|
||||
// This is the 1.6.1 logic but with some optimizations
|
||||
@@ -633,9 +633,6 @@ class OmniPathNodeMaker : NodeEvaluator() {
|
||||
pfContext, x, y, z, sizeX, sizeY, sizeZ, canOpenDoors, canPassDoors, set, PathType.BLOCKED, BlockPos(x, y, z), returnedEarlyPathType
|
||||
)
|
||||
|
||||
if (PathType.LEAVES in set) {
|
||||
return PathType.OPEN
|
||||
}
|
||||
|
||||
if (PathType.FENCE in set) {
|
||||
return PathType.FENCE
|
||||
@@ -755,7 +752,7 @@ class OmniPathNodeMaker : NodeEvaluator() {
|
||||
} else if (type == PathType.RAIL && block !is BaseRailBlock && pfContext.getCachedBlockState(pos.below()).block !is BaseRailBlock) {
|
||||
PathType.UNPASSABLE_RAIL
|
||||
} else if (type == PathType.LEAVES) {
|
||||
if (blockState.block === CobblemonBlocks.SACCHARINE_LEAVES && canPathThroughLeaves()) {
|
||||
if (canPathThroughLeaves() && blockState.block === CobblemonBlocks.SACCHARINE_LEAVES) {
|
||||
PathType.OPEN
|
||||
} else {
|
||||
PathType.BLOCKED
|
||||
|
||||
+4
-8
@@ -6,19 +6,15 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.properties.tags
|
||||
package com.cobblemon.mod.common.pokemon.properties
|
||||
|
||||
import com.cobblemon.mod.common.api.properties.CustomPokemonPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.StringProperty
|
||||
|
||||
object PokemonFlagProperty : CustomPokemonPropertyType<StringProperty> {
|
||||
|
||||
private const val KEY = "tag"
|
||||
|
||||
override val keys = setOf(KEY)
|
||||
object LabelProperty : CustomPokemonPropertyType<StringProperty> {
|
||||
override val keys = setOf("label", "tag")
|
||||
override val needsKey = true
|
||||
|
||||
override fun fromString(value: String?) = if (value == null) null else StringProperty(KEY, value, { _, _ -> }, { pokemon, underlyingValue -> pokemon.hasLabels(underlyingValue) })
|
||||
override fun fromString(value: String?) = if (value == null) null else StringProperty(keys.first(), value, { _, _ -> }, { pokemon, underlyingValue -> pokemon.hasLabels(underlyingValue) })
|
||||
|
||||
override fun examples() = emptySet<String>()
|
||||
}
|
||||
+15
-5
@@ -10,13 +10,14 @@ package com.cobblemon.mod.common.world.feature
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonBlocks
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonBiomeTags
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.core.Direction.UP
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.tags.BlockTags
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.world.item.component.CustomData
|
||||
import net.minecraft.world.level.WorldGenLevel
|
||||
import net.minecraft.world.level.block.Block.UPDATE_ALL
|
||||
import net.minecraft.world.level.block.Block.UPDATE_CLIENTS
|
||||
@@ -227,12 +228,20 @@ class SaccharineTreeFeature : Feature<BlockStateConfiguration>(BlockStateConfigu
|
||||
val i: Int = 2 + randomSource.nextInt(2)
|
||||
for (j in 0..<i) {
|
||||
if (isCombee > 0) {
|
||||
beehiveBlockEntity!!.storeBee(BeehiveBlockEntity.Occupant.create(randomSource.nextInt(599)))
|
||||
beehiveBlockEntity?.storeBee(BeehiveBlockEntity.Occupant.create(randomSource.nextInt(599)))
|
||||
} else {
|
||||
// We want to create a Pokemon entity here and turn it into a compound tag to store in the hive.
|
||||
// But creating a Pokemon entity during world generation can cause issues.
|
||||
// So instead we create custom compound tag that is a placeholder for an incomplete Pokemon.
|
||||
// This is caught and handled by BeeOccupantMixin.java, which turns it into a complete entity.
|
||||
val properties = "${POKEMON_ARGS} lvl=${LEVEL_RANGE.random()}"
|
||||
val pokemon = PokemonProperties.parse(properties)
|
||||
val entity = pokemon.createEntity(worldGenLevel.level)
|
||||
beehiveBlockEntity!!.addOccupant(entity)
|
||||
val compoundTag = CompoundTag()
|
||||
compoundTag.putString("id", POKEMON_PLACEHOLD_ID)
|
||||
compoundTag.putString("pokemonProperties", properties)
|
||||
val occupant = BeehiveBlockEntity.Occupant(
|
||||
CustomData.of(compoundTag), randomSource.nextInt(599), 600
|
||||
)
|
||||
beehiveBlockEntity?.storeBee(occupant)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -351,5 +360,6 @@ class SaccharineTreeFeature : Feature<BlockStateConfiguration>(BlockStateConfigu
|
||||
companion object {
|
||||
val POKEMON_ARGS = "combee"
|
||||
val LEVEL_RANGE = 5..15
|
||||
val POKEMON_PLACEHOLD_ID = "cobblemon_pokemon_entity_placeholder"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -820,6 +820,14 @@
|
||||
"cobblemon.cooking.cooking_quality.medium": "Medium",
|
||||
"cobblemon.cooking.cooking_quality.high": "High",
|
||||
|
||||
"effect.cobblemon.cleanse_all": "Effect Cleanse",
|
||||
"effect.cobblemon.cleanse_negative": "Negative Effect Cleanse",
|
||||
"effect.cobblemon.mental_restoration": "Mental Restoration",
|
||||
|
||||
"effect.cobblemon.cleanse_all": "Effect Cleanse",
|
||||
"effect.cobblemon.cleanse_negative": "Negative Effect Cleanse",
|
||||
"effect.cobblemon.mental_restoration": "Mental Restoration",
|
||||
|
||||
"cobblemon.fossil.armor": "Armor",
|
||||
"cobblemon.fossil.bird": "Bird",
|
||||
"cobblemon.fossil.claw": "Claw",
|
||||
@@ -2621,6 +2629,8 @@
|
||||
"cobblemon.config.ui.infinite_ride_stamina.tooltip": "Whether rideable Pokémon have infinite stamina.",
|
||||
"cobblemon.config.ui.remember_riding_camera": "Remember Riding Camera",
|
||||
"cobblemon.config.ui.remember_riding_camera.tooltip": "Whether the camera mode will automatically switch to the last used camera mode when mounting a rideable Pokémon.",
|
||||
"cobblemon.config.ui.enable_in_flight_dismounting": "Enable In-Flight Dismounting",
|
||||
"cobblemon.config.ui.enable_in_flight_dismounting.tooltip": "Allows players to dismount while riding a Pokémon in the air. When disabled, dismounting is only possible while on the ground.",
|
||||
|
||||
"cobblemon.config.ui.allow_starter_on_join": "Allow Starter on Join",
|
||||
"cobblemon.config.ui.prompt_starter_once_only": "Prompt Starter Once Only",
|
||||
@@ -3515,6 +3525,7 @@
|
||||
"tag.item.cobblemon.plants": "Plants",
|
||||
"tag.item.cobblemon.seeds": "Seeds",
|
||||
"tag.item.cobblemon.boats": "Boats",
|
||||
"tag.item.cobblemon.chest_boats": "Chest Boats",
|
||||
"tag.item.cobblemon.hanging_signs": "Hanging Signs",
|
||||
"tag.item.cobblemon.signs": "Signs",
|
||||
"tag.item.cobblemon.dawn_stone_ores": "Dawn Stone Ores",
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
{
|
||||
"parent": "minecraft:builtin/entity",
|
||||
"gui_light": "side"
|
||||
"gui_light": "side",
|
||||
"textures": {
|
||||
"particle": "cobblemon:item/poke_balls/cherish_ball"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 599 B |
Binary file not shown.
|
After Width: | Height: | Size: 606 B |
Binary file not shown.
|
After Width: | Height: | Size: 566 B |
+1
@@ -0,0 +1 @@
|
||||
{"parent":"minecraft:recipes/root","rewards":{"recipes":["adorn:cobblemon/saccharine_bench"]},"criteria":{"has_slab":{"trigger":"minecraft:inventory_changed","conditions":{"items":[{"items":["cobblemon:saccharine_slab"]}]}},"has_the_recipe":{"trigger":"minecraft:recipe_unlocked","conditions":{"recipe":"adorn:cobblemon/saccharine_bench"}}},"requirements":[["has_slab","has_the_recipe"]],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"parent":"minecraft:recipes/root","rewards":{"recipes":["adorn:cobblemon/saccharine_chair"]},"criteria":{"has_slab":{"trigger":"minecraft:inventory_changed","conditions":{"items":[{"items":["cobblemon:saccharine_slab"]}]}},"has_the_recipe":{"trigger":"minecraft:recipe_unlocked","conditions":{"recipe":"adorn:cobblemon/saccharine_chair"}}},"requirements":[["has_slab","has_the_recipe"]],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"parent":"minecraft:recipes/root","rewards":{"recipes":["adorn:cobblemon/saccharine_coffee_table"]},"criteria":{"has_slab":{"trigger":"minecraft:inventory_changed","conditions":{"items":[{"items":["cobblemon:saccharine_slab"]}]}},"has_the_recipe":{"trigger":"minecraft:recipe_unlocked","conditions":{"recipe":"adorn:cobblemon/saccharine_coffee_table"}}},"requirements":[["has_slab","has_the_recipe"]],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"parent":"minecraft:recipes/root","rewards":{"recipes":["adorn:cobblemon/saccharine_drawer"]},"criteria":{"has_slab":{"trigger":"minecraft:inventory_changed","conditions":{"items":[{"items":["cobblemon:saccharine_slab"]}]}},"has_the_recipe":{"trigger":"minecraft:recipe_unlocked","conditions":{"recipe":"adorn:cobblemon/saccharine_drawer"}}},"requirements":[["has_slab","has_the_recipe"]],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"parent":"minecraft:recipes/root","rewards":{"recipes":["adorn:cobblemon/saccharine_kitchen_counter"]},"criteria":{"has_planks":{"trigger":"minecraft:inventory_changed","conditions":{"items":[{"items":["cobblemon:saccharine_planks"]}]}},"has_the_recipe":{"trigger":"minecraft:recipe_unlocked","conditions":{"recipe":"adorn:cobblemon/saccharine_kitchen_counter"}}},"requirements":[["has_planks","has_the_recipe"]],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"parent":"minecraft:recipes/root","rewards":{"recipes":["adorn:cobblemon/saccharine_kitchen_cupboard"]},"criteria":{"has_planks":{"trigger":"minecraft:inventory_changed","conditions":{"items":[{"items":["cobblemon:saccharine_planks"]}]}},"has_kitchen_counter":{"trigger":"minecraft:inventory_changed","conditions":{"items":[{"items":["adorn:cobblemon/saccharine_kitchen_counter"]}]}},"has_the_recipe":{"trigger":"minecraft:recipe_unlocked","conditions":{"recipe":"adorn:cobblemon/saccharine_kitchen_cupboard"}}},"requirements":[["has_planks","has_kitchen_counter","has_the_recipe"]],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"parent":"minecraft:recipes/root","rewards":{"recipes":["adorn:cobblemon/saccharine_kitchen_sink"]},"criteria":{"has_planks":{"trigger":"minecraft:inventory_changed","conditions":{"items":[{"items":["cobblemon:saccharine_planks"]}]}},"has_the_recipe":{"trigger":"minecraft:recipe_unlocked","conditions":{"recipe":"adorn:cobblemon/saccharine_kitchen_sink"}}},"requirements":[["has_planks","has_the_recipe"]],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"parent":"minecraft:recipes/root","rewards":{"recipes":["adorn:cobblemon/saccharine_platform"]},"criteria":{"has_slab":{"trigger":"minecraft:inventory_changed","conditions":{"items":[{"items":["cobblemon:saccharine_slab"]}]}},"has_the_recipe":{"trigger":"minecraft:recipe_unlocked","conditions":{"recipe":"adorn:cobblemon/saccharine_platform"}}},"requirements":[["has_slab","has_the_recipe"]],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"parent":"minecraft:recipes/root","rewards":{"recipes":["adorn:cobblemon/saccharine_post"]},"criteria":{"has_saccharine_planks":{"trigger":"minecraft:inventory_changed","conditions":{"items":[{"items":["cobblemon:saccharine_planks"]}]}},"has_the_recipe":{"trigger":"minecraft:recipe_unlocked","conditions":{"recipe":"adorn:cobblemon/saccharine_post"}}},"requirements":[["has_saccharine_planks","has_the_recipe"]],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"parent":"minecraft:recipes/root","rewards":{"recipes":["adorn:cobblemon/saccharine_shelf"]},"criteria":{"has_slab":{"trigger":"minecraft:inventory_changed","conditions":{"items":[{"items":["cobblemon:saccharine_slab"]}]}},"has_the_recipe":{"trigger":"minecraft:recipe_unlocked","conditions":{"recipe":"adorn:cobblemon/saccharine_shelf"}}},"requirements":[["has_slab","has_the_recipe"]],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"parent":"minecraft:recipes/root","rewards":{"recipes":["adorn:cobblemon/saccharine_step"]},"criteria":{"has_slab":{"trigger":"minecraft:inventory_changed","conditions":{"items":[{"items":["cobblemon:saccharine_slab"]}]}},"has_the_recipe":{"trigger":"minecraft:recipe_unlocked","conditions":{"recipe":"adorn:cobblemon/saccharine_step"}}},"requirements":[["has_slab","has_the_recipe"]],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"parent":"minecraft:recipes/root","rewards":{"recipes":["adorn:cobblemon/saccharine_table"]},"criteria":{"has_slab":{"trigger":"minecraft:inventory_changed","conditions":{"items":[{"items":["cobblemon:saccharine_slab"]}]}},"has_the_recipe":{"trigger":"minecraft:recipe_unlocked","conditions":{"recipe":"adorn:cobblemon/saccharine_table"}}},"requirements":[["has_slab","has_the_recipe"]],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"minecraft:block","pools":[{"rolls":1,"entries":[{"type":"minecraft:item","name":"adorn:cobblemon/saccharine_bench"}],"conditions":[{"condition":"minecraft:survives_explosion"}]}],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"minecraft:block","pools":[{"rolls":1,"entries":[{"type":"minecraft:item","name":"adorn:cobblemon/saccharine_chair","conditions":[{"block":"adorn:cobblemon/saccharine_chair","properties":{"half":"lower"},"condition":"minecraft:block_state_property"}]}],"conditions":[{"condition":"minecraft:survives_explosion"}]}],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"type":"minecraft:block","pools":[{"rolls":1,"entries":[{"type":"minecraft:item","name":"adorn:cobblemon/saccharine_coffee_table"}],"conditions":[{"condition":"minecraft:survives_explosion"}]}],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"type":"minecraft:block","pools":[{"rolls":1,"entries":[{"type":"minecraft:item","name":"adorn:cobblemon/saccharine_drawer","functions":[{"function":"minecraft:copy_name","source":"block_entity"}]}],"conditions":[{"condition":"minecraft:survives_explosion"}]}],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"type":"minecraft:block","pools":[{"rolls":1,"entries":[{"type":"minecraft:item","name":"adorn:cobblemon/saccharine_kitchen_counter"}],"conditions":[{"condition":"minecraft:survives_explosion"}]}],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"type":"minecraft:block","pools":[{"rolls":1,"entries":[{"type":"minecraft:item","name":"adorn:cobblemon/saccharine_kitchen_cupboard","functions":[{"function":"minecraft:copy_name","source":"block_entity"}]}],"conditions":[{"condition":"minecraft:survives_explosion"}]}],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"type":"minecraft:block","pools":[{"rolls":1,"entries":[{"type":"minecraft:item","name":"adorn:cobblemon/saccharine_kitchen_sink"}],"conditions":[{"condition":"minecraft:survives_explosion"}]}],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"type":"minecraft:block","pools":[{"rolls":1,"entries":[{"type":"minecraft:item","name":"adorn:cobblemon/saccharine_platform"}],"conditions":[{"condition":"minecraft:survives_explosion"}]}],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"minecraft:block","pools":[{"rolls":1,"entries":[{"type":"minecraft:item","name":"adorn:cobblemon/saccharine_post"}],"conditions":[{"condition":"minecraft:survives_explosion"}]}],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"minecraft:block","pools":[{"rolls":1,"entries":[{"type":"minecraft:item","name":"adorn:cobblemon/saccharine_shelf"}],"conditions":[{"condition":"minecraft:survives_explosion"}]}],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"minecraft:block","pools":[{"rolls":1,"entries":[{"type":"minecraft:item","name":"adorn:cobblemon/saccharine_step"}],"conditions":[{"condition":"minecraft:survives_explosion"}]}],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"minecraft:block","pools":[{"rolls":1,"entries":[{"type":"minecraft:item","name":"adorn:cobblemon/saccharine_table"}],"conditions":[{"condition":"minecraft:survives_explosion"}]}],"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"crafting_shaped","group":"adorn:bench","pattern":["SSS","S S"],"key":{"S":{"item":"cobblemon:saccharine_slab"}},"result":{"id":"adorn:cobblemon/saccharine_bench","count":2},"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"crafting_shaped","group":"adorn:chair","pattern":[" S","SS","##"],"key":{"S":{"item":"cobblemon:saccharine_slab"},"#":{"tag":"c:rods/wooden"}},"result":{"id":"adorn:cobblemon/saccharine_chair","count":2},"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"crafting_shaped","group":"adorn:coffee_table","pattern":["S-S","# #"],"key":{"S":{"item":"cobblemon:saccharine_slab"},"#":{"tag":"c:rods/wooden"},"-":{"tag":"c:glass_panes"}},"result":{"id":"adorn:cobblemon/saccharine_coffee_table","count":2},"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"crafting_shaped","group":"adorn:drawer","pattern":["S","C","S"],"key":{"C":{"tag":"c:chests/wooden"},"S":{"item":"cobblemon:saccharine_slab"}},"result":{"id":"adorn:cobblemon/saccharine_drawer","count":2},"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"crafting_shaped","group":"adorn:kitchen_counter","pattern":["SS","PP"],"key":{"S":{"item":"minecraft:polished_andesite_slab"},"P":{"item":"cobblemon:saccharine_planks"}},"result":{"id":"adorn:cobblemon/saccharine_kitchen_counter","count":3},"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"crafting_shapeless","group":"adorn:kitchen_cupboard","ingredients":[{"tag":"c:chests/wooden"},{"item":"adorn:cobblemon/saccharine_kitchen_counter"},{"item":"adorn:cobblemon/saccharine_kitchen_counter"}],"result":{"id":"adorn:cobblemon/saccharine_kitchen_cupboard","count":2},"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"crafting_shapeless","group":"adorn:kitchen_sink","ingredients":[{"item":"adorn:cobblemon/saccharine_kitchen_counter"},{"tag":"c:buckets/empty"}],"result":{"id":"adorn:cobblemon/saccharine_kitchen_sink","count":1},"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"crafting_shaped","group":"adorn:platform","pattern":["S","P"],"key":{"S":{"item":"cobblemon:saccharine_slab"},"P":{"item":"adorn:cobblemon/saccharine_post"}},"result":{"id":"adorn:cobblemon/saccharine_platform","count":2},"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"crafting_shaped","group":"adorn:post","pattern":["/","/","#"],"key":{"#":{"item":"cobblemon:saccharine_planks"},"/":{"tag":"c:rods/wooden"}},"result":{"id":"adorn:cobblemon/saccharine_post","count":4},"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"crafting_shaped","group":"adorn:shelf","pattern":["---","/ /"],"key":{"-":{"item":"cobblemon:saccharine_slab"},"/":{"tag":"c:rods/wooden"}},"result":{"id":"adorn:cobblemon/saccharine_shelf","count":3},"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"crafting_shaped","group":"adorn:step","pattern":["S","#"],"key":{"S":{"item":"cobblemon:saccharine_slab"},"#":{"tag":"c:rods/wooden"}},"result":{"id":"adorn:cobblemon/saccharine_step","count":1},"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
@@ -0,0 +1 @@
|
||||
{"type":"crafting_shaped","group":"adorn:table","pattern":["SSS","# #","# #"],"key":{"S":{"item":"cobblemon:saccharine_slab"},"#":{"tag":"c:rods/wooden"}},"result":{"id":"adorn:cobblemon/saccharine_table","count":3},"fabric:load_conditions":[{"condition":"fabric:all_mods_loaded","values":["adorn"]}],"neoforge:conditions":[{"type":"neoforge:mod_loaded","modid":"adorn"}]}
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_bench", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_bench","required":false}, {"id":"adorn:cobblemon/saccharine_bench","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_chair", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_chair","required":false}, {"id":"adorn:cobblemon/saccharine_chair","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_coffee_table", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_coffee_table","required":false}, {"id":"adorn:cobblemon/saccharine_coffee_table","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_drawer", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_drawer","required":false}, {"id":"adorn:cobblemon/saccharine_drawer","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_kitchen_counter", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_kitchen_counter","required":false}, {"id":"adorn:cobblemon/saccharine_kitchen_counter","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_kitchen_cupboard", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_kitchen_cupboard","required":false}, {"id":"adorn:cobblemon/saccharine_kitchen_cupboard","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_kitchen_sink", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_kitchen_sink","required":false}, {"id":"adorn:cobblemon/saccharine_kitchen_sink","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_table", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_table","required":false}, {"id":"adorn:cobblemon/saccharine_table","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_platform", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_platform","required":false}, {"id":"adorn:cobblemon/saccharine_platform","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_post", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_post","required":false}, {"id":"adorn:cobblemon/saccharine_post","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_shelf", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_shelf","required":false}, {"id":"adorn:cobblemon/saccharine_shelf","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_step", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_step","required":false}, {"id":"adorn:cobblemon/saccharine_step","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_bench", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_bench","required":false}, {"id":"adorn:cobblemon/saccharine_bench","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_chair", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_chair","required":false}, {"id":"adorn:cobblemon/saccharine_chair","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_coffee_table", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_coffee_table","required":false}, {"id":"adorn:cobblemon/saccharine_coffee_table","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_drawer", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_drawer","required":false}, {"id":"adorn:cobblemon/saccharine_drawer","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_kitchen_counter", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_kitchen_counter","required":false}, {"id":"adorn:cobblemon/saccharine_kitchen_counter","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_kitchen_cupboard", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_kitchen_cupboard","required":false}, {"id":"adorn:cobblemon/saccharine_kitchen_cupboard","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_kitchen_sink", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_kitchen_sink","required":false}, {"id":"adorn:cobblemon/saccharine_kitchen_sink","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_table", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_table","required":false}, {"id":"adorn:cobblemon/saccharine_table","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_platform", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_platform","required":false}, {"id":"adorn:cobblemon/saccharine_platform","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_post", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_post","required":false}, {"id":"adorn:cobblemon/saccharine_post","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_shelf", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_shelf","required":false}, {"id":"adorn:cobblemon/saccharine_shelf","required":false}]}
|
||||
|
||||
@@ -1,6 +1 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
{ "id": "adorn:cobblemon/apricorn_step", "required": false }
|
||||
]
|
||||
}
|
||||
{"replace":false,"values":[{"id":"adorn:cobblemon/apricorn_step","required":false}, {"id":"adorn:cobblemon/saccharine_step","required":false}]}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"conditions": {
|
||||
"items": [
|
||||
{
|
||||
"items": "#cobblemon:mint_leaf"
|
||||
"items": "#cobblemon:mint_leaves"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
},
|
||||
{
|
||||
"content": 2,
|
||||
"tag": "#cobblemon:mint_leaf"
|
||||
"tag": "#cobblemon:mint_leaves"
|
||||
},
|
||||
{
|
||||
"content": 2,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user