Compare commits

...
Author SHA1 Message Date
Instrafe 376a420474 Updated Changelog 2026-01-11 10:30:53 -05:00
Instrafe a8e2db25f8 Fixed Scraggy and Scrafty's spawns not having the natural preset 2026-01-11 10:27:47 -05:00
Hiroku 2bb85718d7 Merge branch 'main' into 'main'
Fix Adorn compatibility

See merge request cable-mc/cobblemon!2112
2026-01-11 12:21:25 +00:00
Tate Frost ee187d7b89 Delete file + update Adorn resource pack metadata
- Delete config file that was committed in error
- Update Adorn resource pack metadata to reflect new wood type
2026-01-10 22:30:27 -06:00
Tate Frost 3532cac278 Update CHANGELOG.md 2026-01-10 22:18:01 -06:00
Hiroku 1447ab25b4 Merge branch 'CombeeWorldGenFix' into 'main'
CombeeWorldGenFix

See merge request cable-mc/cobblemon!2071
2026-01-11 02:55:56 +00:00
Hiroku 9a06ca78c6 Merge branch 'fix-mongo-driver' into 'main'
Fix MongoDB ClassNotFoundException by including drivers at runtime

See merge request cable-mc/cobblemon!2098
2026-01-11 02:47:10 +00:00
Hiroku f6ba70634b Merge branch 'double-battle-gimmicks' into 'main'
Fix double battle gimmicks not being processed

See merge request cable-mc/cobblemon!2094
2026-01-11 02:46:36 +00:00
Hiroku 148fd04a93 Merge branch 'molang-evaluate_expression' into 'main'
molang addition: exception handling for run_molang

See merge request cable-mc/cobblemon!2102
2026-01-11 02:12:07 +00:00
Hiroku 17f60623ee Merge branch 'effect-id-regex-update' into 'main'
Custom messages for datapack moves and abilities

See merge request cable-mc/cobblemon!2106
2026-01-11 02:08:42 +00:00
Hiroku c5ece27c11 Merge branch '1861-galarien_mrmime_mount' into 'main'
Fix Galarian Mr. Mime incorrectly being rideable.

Closes #1861

See merge request cable-mc/cobblemon!2107
2026-01-11 02:02:14 +00:00
Hiroku 296ccd1a76 Merge branch 'main' into 'main'
Fix pasture block incorrect hit-box when facing north and south.

See merge request cable-mc/cobblemon!2109
2026-01-11 02:01:44 +00:00
Tate Frost 08b58e2f78 Fix Adorn compatibility
- Fixed Apricorn block model rotation for counters/sinks/cupboards/drawers to match that of most recent version of Adorn
- Added Saccharine wood + Adorn compatibility
2026-01-07 02:04:52 -06:00
Merv 62d2b8db2d Edit CHANGELOG.md 2026-01-06 18:47:45 +00:00
Merv 3869f7ed93 Merge branch cobblemon:main into main 2026-01-05 23:09:08 +00:00
Dragonwhisper92 c9c44872d6 Updated Changelog. 2026-01-05 19:35:05 +00:00
Dragonwhisper92 cae53efedc Updated ActivateInstruction.kt to have an optional message parameter. 2026-01-05 19:14:40 +00:00
Polymeta 5fac24cee8 Merge branch 'Molang-SimpleDateFormat-Fix' into 'main'
Fixed Molang functions:

See merge request cable-mc/cobblemon!2105
2026-01-05 11:22:45 +00:00
Polymeta 1954dfec80 Merge branch '1784-riding_stats_order' into 'main'
Fix riding stat boosts to always render in the same order

Closes #1784

See merge request cable-mc/cobblemon!2108
2026-01-05 11:20:29 +00:00
Landon 2eea2b64c2 Merge branch 'bag-clause' into 'main'
Bag Clause (Preventing Item use in Battles)

See merge request cable-mc/cobblemon!1849
2026-01-05 08:12:36 +00:00
GDWR a127a93be8 Sort boosts when rendering to remove the jumping of stats between items
The sort uses the key. As `RidingStat` it sorts them by the enum value.
2026-01-04 20:27:42 +00:00
GDWR 9b32f85817 Set an empty riding definition for Galarian Mr. Mime to avoid inheriting the default definition 2026-01-04 17:28:02 +00:00
Dragonwhisper92 ec139d2677 Updated Effect.kt to use a custom REGEX entry 2026-01-04 16:46:44 +00:00
Landon Wills 4327be0cf9 Omit bag clause from getting sent to showdown 2026-01-04 02:22:32 -05:00
Landon Wills c25c832b31 Remove import 2026-01-04 01:21:20 -05:00
Landon Wills eabaabc535 Move bag clause check to bag items instead of pokemon entity 2026-01-04 01:19:26 -05:00
Dragonwhisper92 9acf97f5a0 Updated CHANGELOG.md 2026-01-04 00:18:24 +00:00
Dragonwhisper92 24fc212c76 Updated CHANGELOG.md 2026-01-04 00:15:32 +00:00
Hiroku 04f88bdd63 Merge branch 'form-change-move-sanitization-fix' into 'main'
Fix the improper sanitization of moves on mons with compounding properties

Closes #1853 and #1846

See merge request cable-mc/cobblemon!2085
2026-01-04 00:05:26 +00:00
Dragonwhisper92 a4eb58aa57 Fixed molang functions:
- date_local_time
- date_of
- date_is_after
too use the correct SimpleDateFormat of "dd/MM/yyyy"
2026-01-03 23:40:12 +00:00
Merv 6704d4e5ee Maybe fix pasture block incorrect hitbox 2026-01-03 02:05:03 +00:00
Hiroku c88087de29 Merge branch 'main' into 'main'
Small improvements to the Battle AI

See merge request cable-mc/cobblemon!2101
2026-01-02 00:38:26 +00:00
Konoha 86bb802140 adjustment: exception handling to run_molang 2026-01-01 11:44:29 -05:00
GGavino1 6b644b384d Updated CHANGELOG.md to include AI changes 2026-01-01 15:00:15 +00:00
Konoha c370af8914 feature: molang function for safe evaluation of booleans 2025-12-31 22:23:50 -05:00
GGavino1 1cd6d2bfc7 Edit StrongBattleAI.kt 2025-12-31 23:15:52 +00:00
Konoha 1edeae2a60 fix: let's actually fix 2025-12-27 09:48:49 -05:00
mkh 409f1056b9 fix: Add MongoDB driver dependency to Fabric/NeoForge build configuration and shade it into the mod jar to resolve ClassNotFoundException. 2025-12-26 17:31:46 +08:00
Landon Wills d8c470db3d Oops, forgot a file 2025-12-23 01:28:50 -05:00
Landon Wills c642c4b84b Update changelog 2025-12-23 01:22:01 -05:00
Landon Wills 0b80f7e547 Make the gimmick buttons work with the back button 2025-12-23 01:18:35 -05:00
Landon Wills d543f45607 Fix double battle gimmicks not being processed, prevent people from trying to use the same gimmick multiple times on the same turn 2025-12-23 00:43:31 -05:00
Konoha 2b4fdfd219 changelog: sanitization fix 2025-12-21 15:40:17 -05:00
Hiroku 1a3b655d3f Merge branch 'the-tiniest-of-tiny-changes' into 'main'
Edit pokemon_model.json

See merge request cable-mc/cobblemon!2091
2025-12-20 12:41:36 +00:00
dhi_holo 1f5f278970 Edit pokemon_model.json 2025-12-20 21:25:12 +10:00
Hiroku 0b4eb5239a Merge branch 'in-flight-dismounting-config' into 'main'
Add enable in-flight dismounting config

See merge request cable-mc/cobblemon!2079
2025-12-20 06:01:12 +00:00
lionandHiroku 118e8f6205 Add enable in-flight dismounting config 2025-12-20 06:01:12 +00:00
Hiroku cf126c5906 Merge branch 'molang-is-love-molang-is-life' into 'main'
Fixed the `run_script` Molang function to not fail if the environment's context is null.

See merge request cable-mc/cobblemon!2090
2025-12-20 01:59:22 +00:00
Spicy 645cf61911 Fixed the run_script Molang function to not fail if the environment's context is null. 2025-12-19 19:48:27 -06:00
Hiroku 87d5ede3dd Merge branch 'RestoreCombeeLeavesPathing' into 'main'
RestoreCombeeLeavesPathing

See merge request cable-mc/cobblemon!2046
2025-12-19 07:36:50 +00:00
Hiroku 203e5d89cd Merge branch 'label-consistency' into 'main'
Who are we if not consistent?

See merge request cable-mc/cobblemon!1985
2025-12-19 07:36:21 +00:00
Konoha ce611cc61c cleanup: fix redundancies in form change sanitization 2025-12-18 21:17:48 -05:00
JazzMcNade f6ad7ff865 Fix changelog 2025-12-17 21:08:46 -06:00
JazzMcNade d69627a9c8 Merge branch 'main' into CombeeWorldGenFix 2025-12-17 20:05:09 -06:00
JazzMcNade 54e8763470 Fixed a bug in which Combees could become stuck inside of leaves 2025-12-13 21:17:59 -06:00
JazzMcNade db34687df0 Merge branch 'main' into RestoreCombeeLeavesPathing 2025-12-13 21:11:57 -06:00
Konoha 7f008d85ff fix: form_change move updates no longer sanitize the sets of compounding property mons 2025-12-13 18:37:37 -05:00
Polymeta 06ebf51078 Merge branch 'Wii-Break-It-Wii-Fix-It' into 'main'
Boat Tags and Mint Leaves

Closes #1855

See merge request cable-mc/cobblemon!2082
2025-12-13 22:14:32 +00:00
Polymeta 39c5bcd73c Merge branch 'even-more-seasonings' into 'main'
Adding Missing Effects for Seasonings

See merge request cable-mc/cobblemon!1991
2025-12-13 22:13:24 +00:00
CeejayandPolymeta 8f5f158b60 Adding Missing Effects for Seasonings 2025-12-13 22:13:24 +00:00
dhi_holo 3bc1e35125 Update CHANGELOG.md 2025-12-13 18:42:50 +10:00
dhi_holo 460bedddae Boat Tags
Resolves #1855
2025-12-13 18:12:24 +10:00
dhi_holo 8b64c315f3 Merge branch 'main' into Wii-Break-It-Wii-Fix-It 2025-12-13 17:51:15 +10:00
dhi_holo 7c824a2b72 OVERSIGHTS 2025-12-13 17:50:57 +10:00
JazzMcNade 9dac604a93 Merge branch 'main' into RestoreCombeeLeavesPathing 2025-12-10 00:20:49 -06:00
JazzMcNade 8540a73885 Fix for error occurring while populating bee nests with pokemon on world gen 2025-12-04 01:38:56 -06:00
Neovitalism 25ce784a60 Hopefully fixes changelog
Idk why gitlab didn't detect that when merging main
2025-12-03 10:17:48 -06:00
Neovitalism 5358cccb62 Merge branch 'main' into label-consistency 2025-12-03 10:09:41 -06:00
JazzMcNade 698fa9dff9 Merge branch 'main' into RestoreCombeeLeavesPathing 2025-12-01 00:46:50 -06:00
JazzMcNade a8949cf1f9 changelog 2025-11-25 21:49:38 -06:00
JazzMcNade 61db6334f9 Restores Combee pathing through leaves 2025-11-25 21:37:57 -06:00
Neovitalism 46d278ca55 key \:) 2025-11-17 03:18:02 -06:00
Neovitalism 339038956d Support for deserialization from any key
...I think.
2025-11-17 03:09:21 -06:00
Neovitalism 116a93d8cc Update CHANGELOG.md 2025-11-16 04:19:32 -06:00
Neovitalism acebc35d3f Who are we if not consistent?
Before, this property was called `PokemonFlagProperty`, had the key `tag`, and checked pokémon's labels. It was also in a package by itself.

Now, it's moved down into the properties package, renamed to LabelProperty, and the key "label" was added, keeping "tag" as a secondary for those that are using it currently.
2025-11-16 04:10:45 -06:00
Konoha aee89f1c92 Preliminary Bag Clause implementation 2025-09-09 18:15:37 -04:00
163 changed files with 1804 additions and 356 deletions
+34 -2
View File
@@ -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())
}
@@ -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
}
@@ -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
}
@@ -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))
@@ -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 {
@@ -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()
}
@@ -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 } ||
@@ -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++
}
}
@@ -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)
@@ -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)
}
}
@@ -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 {
@@ -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
}
@@ -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)
}
}
}
}
@@ -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
@@ -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>()
}
@@ -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

@@ -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"}]}
@@ -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"}]}
@@ -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"}]}
@@ -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"}]}
@@ -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"}]}
@@ -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"}]}
@@ -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"}]}
@@ -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"}]}
@@ -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"}]}
@@ -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"}]}
@@ -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"}]}
@@ -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"}]}
@@ -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"}]}
@@ -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"}]}
@@ -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"}]}
@@ -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"}]}
@@ -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"}]}
@@ -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