Compare commits

..
68 changed files with 465 additions and 857 deletions

No files matched your search

+4 -13
View File
@@ -6,16 +6,10 @@
- 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 official Controlify Support
- 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 mood particles! Pokémon now visually react to certain actions:
- Angry particles when attacking a mob.
- Annoyed particles when a player tries to feed them while they’re already full.
- Sweat droplets when they run out of stamina while being ridden.
### Changes
- Ride sounds have been separated into stereo for passengers and mono for other players. Riding will now sound more spacious.
@@ -34,9 +28,6 @@
- Fixed crashing when riding due to malformed json file, instead resetting it
- 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.
### 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.
-9
View File
@@ -32,10 +32,6 @@ repositories {
maven(url = "https://api.modrinth.com/maven")
maven(url = "https://maven.neoforged.net/releases")
maven(url = "https://maven.gegy.dev")
exclusiveContent {
forRepository { maven(url = "https://maven.isxander.dev/releases") }
filter { includeGroup("dev.isxander") }
}
mavenLocal()
}
@@ -66,11 +62,6 @@ dependencies {
// Unit Testing
testImplementation(libs.bundles.unitTesting)
// Controlify Compat, same as flywheel so we pick one and only use the api
modCompileOnlyApi("dev.isxander:controlify:2.4.3+1.21.1-fabric") {
isTransitive = false
}
}
tasks.withType<Test> {
@@ -21,14 +21,12 @@ import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import com.llamalad7.mixinextras.sugar.Local;
import com.mojang.blaze3d.Blaze3D;
import kotlin.Pair;
import kotlin.jvm.functions.Function4;
import net.minecraft.client.Minecraft;
import net.minecraft.client.MouseHandler;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.util.Mth;
import net.minecraft.util.SmoothDouble;
import net.minecraft.world.phys.Vec3;
import org.joml.Vector2d;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
@@ -148,12 +146,6 @@ public abstract class MouseHandlerMixin {
pokeVehicle.clampPassengerRotation(player);
}
for(Function4<LocalPlayer, Double, Double, Double, Vector2d> rideFun : CobblemonClient.INSTANCE.getRidingTurnInputHandler().values()) {
Vector2d vec = rideFun.invoke(player, cursorDeltaX, cursorDeltaY, d);
cursorDeltaX = vec.x;
cursorDeltaY = vec.y;
}
// If the ride is not orientation controllable then return and perform the normal turnPlayer logic
if (!(vehicle instanceof OrientationControllable controllableVehicle) || !controllableVehicle.getOrientationController().isActive()) {
xMouseSmoother.reset();
@@ -201,7 +201,6 @@ object Cobblemon {
implementation.registerEntityDataSerializers()
implementation.registerCriteria()
implementation.registerEntitySubPredicates()
implementation.registerMobEffects()
DispenserBehaviorRegistry.registerDispenserBehaviors()
DropEntry.register("command", CommandDropEntry::class.java)
@@ -117,11 +117,6 @@ interface CobblemonImplementation {
fun registerEntitySubPredicates()
/**
* TODO
*/
fun registerMobEffects()
/**
* Add a feature to the current platform implementation.
@@ -1,33 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common
import com.cobblemon.mod.common.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())
}
@@ -1,22 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.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
}
@@ -1,27 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.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
}
@@ -1,33 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.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
}
}
@@ -92,13 +92,17 @@ interface PokemonAndMoveSelectingItem {
}
fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon): Boolean {
if (stack.`is`(CobblemonItemTags.POKE_FOOD)) {
return !pokemon.isFull()
if (pokemon.entity == null && stack.`is`(CobblemonItemTags.POKE_FOOD) && pokemon.isFull()) {
return false
}
return true
}
fun canUseOnBattlePokemon(stack: ItemStack, battlePokemon: BattlePokemon): Boolean = bagItem!!.canUse(stack, battlePokemon.actor.battle, battlePokemon)
fun canUseOnBattlePokemon(stack: ItemStack, battlePokemon: BattlePokemon): Boolean {
return bagItem!!.canUse(stack, battlePokemon.actor.battle, battlePokemon)
}
fun canUseOnMove(stack: ItemStack, pokemon: Pokemon, move: Move): Boolean = canUseOnMove(stack, move)
fun canUseOnMove(stack: ItemStack, move: Move): Boolean
@@ -107,13 +107,16 @@ interface PokemonSelectingItem {
}
fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon): Boolean {
if (stack.`is`(CobblemonItemTags.POKE_FOOD)) {
return !pokemon.isFull()
if (pokemon.entity == null && stack.`is`(CobblemonItemTags.POKE_FOOD) && pokemon.isFull()) {
return false
}
return true
}
fun canUseOnBattlePokemon(stack: ItemStack, battlePokemon: BattlePokemon): Boolean = bagItem!!.canUse(stack, battlePokemon.actor.battle, battlePokemon)
fun canUseOnBattlePokemon(stack: ItemStack, battlePokemon: BattlePokemon): Boolean {
return bagItem!!.canUse(stack, battlePokemon.actor.battle, battlePokemon)
}
fun interactWithSpecificBattle(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon): InteractionResultHolder<ItemStack> {
return if (canUseOnBattlePokemon(stack, battlePokemon)) {
@@ -1566,8 +1566,9 @@ object MoLangFunctions {
}
map.put("feed_pokemon") { params ->
val amount = params.getDouble(0)
val playSound = params.getBooleanOrNull(1) ?: true
pokemon.feedPokemon(amount.toInt(), playSound)
val playSound = params.getBooleanOrNull(1) != false
val playMoodParticles = params.getBooleanOrNull(2) != false
return@put DoubleValue(pokemon.feedPokemon(amount.toInt(), playSound, playMoodParticles))
}
map.put("behaviour") { pokemon.form.behaviour.struct }
map.put("behavior") { pokemon.form.behaviour.struct } // Inferior
@@ -22,7 +22,6 @@ import com.cobblemon.mod.common.api.riding.posing.PoseOption
import com.cobblemon.mod.common.api.riding.posing.PoseProvider
import com.cobblemon.mod.common.api.riding.sound.RideSoundSettingsList
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.blockPositionsAsListRounded
@@ -145,12 +144,11 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
) {
val sprintTimerTickLength = 7 // Emulate vanillas tick timer length
var hasDoubleTapped = false
val forward = Minecraft.getInstance().player?.input?.up == true
// If you are not sprinting and you just pressed down and theres no
if (!state.forwardHeldLastTick.get() && forward && !state.sprinting.get() && state.sprintTickTimer.get() == 0) {
if (!state.forwardHeldLastTick.get() && Minecraft.getInstance().options.keyUp.isDown() && !state.sprinting.get() && state.sprintTickTimer.get() == 0) {
state.sprintTickTimer.set(sprintTimerTickLength)
} else if (!state.forwardHeldLastTick.get() && forward && state.sprintTickTimer.get() != 0) { // If has double tapped
} else if (!state.forwardHeldLastTick.get() && Minecraft.getInstance().options.keyUp.isDown() && state.sprintTickTimer.get() != 0) { // If has double tapped
hasDoubleTapped = true
}else if(!state.sprinting.get() && state.sprintTickTimer.get() > 0) {
state.sprintTickTimer.set(state.sprintTickTimer.get() - 1)
@@ -158,9 +156,9 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
state.sprintTickTimer.set(0)
}
val tryingToSprint = hasDoubleTapped || CobblemonClient.ridingSprintHandler.any { it.value.invoke() }
val tryingToSprint = (Minecraft.getInstance().options.keySprint.isDown() && Minecraft.getInstance().options.keyUp.isDown()) || hasDoubleTapped
if (state.stamina.get() <= 0.0f || !forward) {
if (state.stamina.get() <= 0.0f || !Minecraft.getInstance().options.keyUp.isDown()) {
// If stamina runs out or the player is not holding forward then stop sprinting
state.sprinting.set(false)
if (state.stamina.get() <= 0.0f) {
@@ -174,8 +172,8 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
state.sprinting.set(true)
}
// Take note of whether forward was held last tick
state.forwardHeldLastTick.set(forward)
// Take not of whether forward was held last tick
state.forwardHeldLastTick.set(Minecraft.getInstance().options.keyUp.isDown())
}
fun tickStamina(
@@ -74,7 +74,6 @@ import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.platform.events.PlatformEvents
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.isLookingAt
import net.minecraft.client.Minecraft
import net.minecraft.client.color.block.BlockColor
@@ -84,19 +83,16 @@ import net.minecraft.client.gui.screens.Screen
import net.minecraft.client.model.BoatModel
import net.minecraft.client.model.ChestBoatModel
import net.minecraft.client.model.PlayerModel
import net.minecraft.client.player.LocalPlayer
import net.minecraft.client.renderer.RenderType
import net.minecraft.client.renderer.blockentity.HangingSignRenderer
import net.minecraft.client.renderer.blockentity.SignRenderer
import net.minecraft.client.renderer.entity.EntityRenderer
import net.minecraft.client.renderer.entity.LivingEntityRenderer
import net.minecraft.client.resources.PlayerSkin
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.packs.resources.ResourceManager
import net.minecraft.world.InteractionHand
import net.minecraft.world.entity.player.Player
import net.minecraft.world.phys.AABB
import org.joml.Vector2d
object CobblemonClient {
@@ -116,8 +112,6 @@ object CobblemonClient {
val battleOverlay: BattleOverlay by lazy { BattleOverlay() }
val pokedexUsageContext: PokedexUsageContext by lazy { PokedexUsageContext() }
val rideControlsOverlay: RideControlsOverlay by lazy { RideControlsOverlay() }
val ridingTurnInputHandler: MutableMap<ResourceLocation, (LocalPlayer, Double, Double, Double) -> Vector2d> = mutableMapOf()
val ridingSprintHandler: MutableMap<ResourceLocation, () -> Boolean> = mutableMapOf()
fun onLogin() {
clientPlayerData = ClientGeneralPlayerData()
@@ -201,8 +195,6 @@ object CobblemonClient {
ClientPlayerIcon.onTick()
PartyOverlayDataControl.tick(event.client.isPaused)
}
ridingSprintHandler.put(cobblemonResource("normal")) { Minecraft.getInstance().options.keySprint.isDown }
}
private fun registerTooltipManagers() {
@@ -74,12 +74,12 @@ class InteractWheelButton(
y = y,
width = width,
height = height,
vOffset = if ((isHovered(mouseX.toFloat(), mouseY.toFloat()) || isFocused) && isEnabled) height else 0,
vOffset = if (isHovered(mouseX.toFloat(), mouseY.toFloat()) && isEnabled) height else 0,
textureHeight = height * 2,
alpha = if (isEnabled) 1f else 0.4F
)
if(isEnabled && (isHovered(mouseX.toFloat(), mouseY.toFloat()) || isFocused)){
if(isEnabled && isHovered(mouseX.toFloat(), mouseY.toFloat())){
tooltipText?.let {
context.renderTooltip(Minecraft.getInstance().font, Component.translatable(it), mouseX, mouseY)
}
@@ -23,9 +23,9 @@ class InteractWheelGUI(private val options: Multimap<Orientation, InteractWheelO
private val backgroundResource = cobblemonResource("textures/gui/interact/interact_wheel_base.png")
}
val buttons = mutableListOf<InteractWheelButton>()
var maxPage = 1
var currentPage = 0
private val buttons = mutableListOf<InteractWheelButton>()
private var maxPage = 1
private var currentPage = 0
override fun renderBlurredBackground(delta: Float) { }
override fun renderMenuBackground(context: GuiGraphics) {}
@@ -77,7 +77,7 @@ class InteractWheelGUI(private val options: Multimap<Orientation, InteractWheelO
currentPage = page
buttons.forEach { removeWidget(it) }
buttons.clear()
val orientations = Orientation.entries.toTypedArray()
val orientations = Orientation.values()
orientations.forEach { orientation ->
val option = options[orientation].toList().getOrNull(page)
addButton(orientation, option)
@@ -1,319 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.integration.controlify
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.OrientationControllable
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.CobblemonClient.ridingTurnInputHandler
import com.cobblemon.mod.common.client.gui.battle.BattleGUI
import com.cobblemon.mod.common.client.gui.behaviour.BehaviourEditorScreen
import com.cobblemon.mod.common.client.gui.config.CobblemonConfigScreen
import com.cobblemon.mod.common.client.gui.cookingpot.CookingPotScreen
import com.cobblemon.mod.common.client.gui.debug.riding.RidingStatsDebugGUI
import com.cobblemon.mod.common.client.gui.dialogue.DialogueScreen
import com.cobblemon.mod.common.client.gui.interact.battleRequest.BattleConfigureGUI
import com.cobblemon.mod.common.client.gui.interact.moveselect.MoveSelectGUI
import com.cobblemon.mod.common.client.gui.interact.partyselect.PartySelectGUI
import com.cobblemon.mod.common.client.gui.interact.wheel.InteractWheelGUI
import com.cobblemon.mod.common.client.gui.npc.NPCEditorScreen
import com.cobblemon.mod.common.client.gui.pc.PCGUI
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUI
import com.cobblemon.mod.common.client.gui.pokenav.PokeNav
import com.cobblemon.mod.common.client.gui.snapshots.SnapshotWarningScreen
import com.cobblemon.mod.common.client.gui.startselection.StarterSelectionScreen
import com.cobblemon.mod.common.client.gui.summary.Summary
import com.cobblemon.mod.common.client.gui.trade.TradeGUI
import com.cobblemon.mod.common.client.integration.controlify.gui.CobblemonGUIProcessor
import com.cobblemon.mod.common.client.integration.controlify.gui.InteractWheelProcessor
import com.cobblemon.mod.common.client.keybind.CobblemonKeyBinds
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.cobblemonResource
import dev.isxander.controlify.api.ControlifyApi
import dev.isxander.controlify.api.bind.ControlifyBindApi
import dev.isxander.controlify.api.bind.InputBindingBuilder
import dev.isxander.controlify.api.bind.InputBindingSupplier
import dev.isxander.controlify.api.entrypoint.ControlifyEntrypoint
import dev.isxander.controlify.api.entrypoint.InitContext
import dev.isxander.controlify.api.entrypoint.PreInitContext
import dev.isxander.controlify.bindings.BindContext
import dev.isxander.controlify.bindings.ControlifyBindings
import dev.isxander.controlify.bindings.RadialIcons
import dev.isxander.controlify.screenop.ScreenProcessorFactory
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.screens.Screen
import net.minecraft.client.player.LocalPlayer
import net.minecraft.network.chat.Component
import net.minecraft.world.item.Items
import org.joml.Vector2d
import kotlin.jvm.optionals.getOrNull
import kotlin.reflect.KClass
import kotlin.reflect.full.primaryConstructor
class CobblemonControlifyEntrypoint : ControlifyEntrypoint {
override fun onControlifyInit(initContext: InitContext) {
ridingTurnInputHandler.put(
cobblemonResource("compat.controlify"),
({ localPlayer: LocalPlayer, xDelta: Double, yDelta: Double, deltaTime: Double ->
val vec = Vector2d(xDelta, yDelta)
val controller = initContext.controlify().currentController.getOrNull()
val vehicle = localPlayer.vehicle
if (vehicle is OrientationControllable && vehicle.orientationController.isActive() && initContext.controlify().currentInputMode().isController && controller != null){
val multiplier = deltaTime * 1500
val config = controller.input().getOrNull()?.config()?.config()
val vSensitivity = config?.vLookSensitivity ?: 0.9f
val hSensitivity = config?.hLookSensitivity ?: 1f
// Should never be null once bindings are set
var vAxis = (RIDING_DOWN!!.on(controller).analogueNow() - RIDING_UP!!.on(controller).analogueNow()).toDouble()
var hAxis = (RIDING_RIGHT!!.on(controller).analogueNow() - RIDING_LEFT!!.on(controller).analogueNow()).toDouble()
vAxis *= multiplier * vSensitivity
hAxis *= multiplier * hSensitivity
vec.x = hAxis
vec.y = vAxis
}
vec
})
)
CobblemonClient.ridingSprintHandler.put(
cobblemonResource("compat.controlify")
) {
initContext.controlify().currentController.getOrNull()?.let { ControlifyBindings.SPRINT.on(it).digitalNow() } == true
}
}
override fun onControlifyPreInit(initContext: PreInitContext) {
val bindings = ControlifyBindApi.get()
bindings.registerBindContext(ORIENTATION_CONTROLLER_ACTIVE)
RIDING_UP =
bindings.registerBinding { builder: InputBindingBuilder ->
builder
.id(cobblemonResource("riding_up"))
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
.name(Component.translatable("controlify.bind.cobblemon.riding_up"))
.allowedContexts(ORIENTATION_CONTROLLER_ACTIVE, BindContext.IN_GAME)
}
RIDING_DOWN =
bindings.registerBinding { builder: InputBindingBuilder ->
builder
.id(cobblemonResource("riding_down"))
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
.name(Component.translatable("controlify.bind.cobblemon.riding_down"))
.allowedContexts(ORIENTATION_CONTROLLER_ACTIVE, BindContext.IN_GAME)
}
RIDING_LEFT =
bindings.registerBinding { builder: InputBindingBuilder ->
builder
.id(cobblemonResource("riding_left"))
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
.name(Component.translatable("controlify.bind.cobblemon.riding_left"))
.allowedContexts(ORIENTATION_CONTROLLER_ACTIVE, BindContext.IN_GAME)
}
RIDING_RIGHT =
bindings.registerBinding { builder: InputBindingBuilder ->
builder
.id(cobblemonResource("riding_right"))
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
.name(Component.translatable("controlify.bind.cobblemon.riding_right"))
.allowedContexts(ORIENTATION_CONTROLLER_ACTIVE, BindContext.IN_GAME)
}
HIDE_PARTY =
bindings.registerBinding { builder: InputBindingBuilder ->
builder
.id(cobblemonResource("hide_party"))
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
.name(Component.translatable("key.cobblemon.hideparty"))
.allowedContexts(BindContext.IN_GAME)
.radialCandidate(RadialIcons.getItem(Items.BARRIER))
.addKeyCorrelation(CobblemonKeyBinds.HIDE_PARTY)
.keyEmulation(CobblemonKeyBinds.HIDE_PARTY)
}
SUMMARY =
bindings.registerBinding { builder: InputBindingBuilder ->
builder
.id(cobblemonResource("summary"))
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
.name(Component.translatable("key.cobblemon.summary"))
.allowedContexts(BindContext.IN_GAME)
.radialCandidate(RadialIcons.getItem(CobblemonItems.GREAT_BALL))
.addKeyCorrelation(CobblemonKeyBinds.SUMMARY)
.keyEmulation(CobblemonKeyBinds.SUMMARY)
}
PARTY_OVERLAY_DOWN =
bindings.registerBinding { builder: InputBindingBuilder ->
builder
.id(cobblemonResource("party_overlay_down"))
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
.name(Component.translatable("key.cobblemon.downshiftparty"))
.allowedContexts(HAS_POKEMON, BindContext.IN_GAME)
.radialCandidate(RadialIcons.EMPTY)
.addKeyCorrelation(CobblemonKeyBinds.PARTY_OVERLAY_DOWN)
.keyEmulation(CobblemonKeyBinds.PARTY_OVERLAY_DOWN)
}
PARTY_OVERLAY_UP =
bindings.registerBinding { builder: InputBindingBuilder ->
builder
.id(cobblemonResource("party_overlay_up"))
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
.name(Component.translatable("key.cobblemon.upshiftparty"))
.allowedContexts(HAS_POKEMON, BindContext.IN_GAME)
.radialCandidate(RadialIcons.EMPTY)
.addKeyCorrelation(CobblemonKeyBinds.PARTY_OVERLAY_UP)
.keyEmulation(CobblemonKeyBinds.PARTY_OVERLAY_DOWN)
}
SEND_OUT_POKEMON =
bindings.registerBinding { builder: InputBindingBuilder ->
builder
.id(cobblemonResource("send_out_pokemon"))
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
.name(Component.translatable("key.cobblemon.throwpartypokemon"))
.allowedContexts(HAS_POKEMON, BindContext.IN_GAME)
.radialCandidate(RadialIcons.getItem(CobblemonItems.POKE_BALL))
.addKeyCorrelation(CobblemonKeyBinds.SEND_OUT_POKEMON)
.keyEmulation(CobblemonKeyBinds.SEND_OUT_POKEMON)
}
RIDING_FREELOOK =
bindings.registerBinding { builder: InputBindingBuilder ->
builder
.id(cobblemonResource("riding_freelook"))
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
.name(Component.translatable("key.cobblemon.ridingfreelook"))
.allowedContexts(RIDING_POKEMON, BindContext.IN_GAME)
.radialCandidate(RadialIcons.EMPTY)
.addKeyCorrelation(CobblemonKeyBinds.RIDING_FREELOOK)
.keyEmulation(CobblemonKeyBinds.RIDING_FREELOOK)
}
INTERACT_WHEEL_UP_AXIS =
bindings.registerBinding { builder: InputBindingBuilder ->
builder
.id(cobblemonResource("interact_wheel_up"))
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
.name(Component.translatable("controlify.bind.cobblemon.interact_wheel_up"))
.allowedContexts(INTERACT_WHEEL_SCREEN, BindContext.IN_GAME)
}
INTERACT_WHEEL_DOWN_AXIS =
bindings.registerBinding { builder: InputBindingBuilder ->
builder
.id(cobblemonResource("interact_wheel_down"))
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
.name(Component.translatable("controlify.bind.cobblemon.interact_wheel_down"))
.allowedContexts(INTERACT_WHEEL_SCREEN, BindContext.IN_GAME)
}
INTERACT_WHEEL_RIGHT_AXIS =
bindings.registerBinding { builder: InputBindingBuilder ->
builder
.id(cobblemonResource("interact_wheel_right"))
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
.name(Component.translatable("controlify.bind.cobblemon.interact_wheel_right"))
.allowedContexts(INTERACT_WHEEL_SCREEN, BindContext.IN_GAME)
}
INTERACT_WHEEL_LEFT_AXIS =
bindings.registerBinding { builder: InputBindingBuilder ->
builder
.id(cobblemonResource("interact_wheel_left"))
.category(Component.translatable("controlify.category.cobblemon.cobblemon"))
.name(Component.translatable("controlify.bind.cobblemon.interact_wheel_left"))
.allowedContexts(INTERACT_WHEEL_SCREEN, BindContext.IN_GAME)
}
addProcessor(InteractWheelGUI::class, InteractWheelProcessor::class)
// This is the lazy way to do all of these (just using the vmouse), if someone with more time and dedication did this that would be better
addProcessor(BattleGUI::class, CobblemonGUIProcessor::class)
addProcessor(BehaviourEditorScreen::class, CobblemonGUIProcessor::class)
addProcessor(CobblemonConfigScreen::class, CobblemonGUIProcessor::class)
addProcessor(CookingPotScreen::class, CobblemonGUIProcessor::class)
addProcessor(RidingStatsDebugGUI::class, CobblemonGUIProcessor::class)
addProcessor(DialogueScreen::class, CobblemonGUIProcessor::class)
addProcessor(BattleConfigureGUI::class, CobblemonGUIProcessor::class)
addProcessor(MoveSelectGUI::class, CobblemonGUIProcessor::class)
addProcessor(PartySelectGUI::class, CobblemonGUIProcessor::class)
addProcessor(NPCEditorScreen::class, CobblemonGUIProcessor::class)
addProcessor(PCGUI::class, CobblemonGUIProcessor::class)
addProcessor(PokedexGUI::class, CobblemonGUIProcessor::class)
addProcessor(PokeNav::class, CobblemonGUIProcessor::class)
addProcessor(SnapshotWarningScreen::class, CobblemonGUIProcessor::class)
addProcessor(StarterSelectionScreen::class, CobblemonGUIProcessor::class)
addProcessor(Summary::class, CobblemonGUIProcessor::class)
addProcessor(TradeGUI::class, CobblemonGUIProcessor::class)
}
override fun onControllersDiscovered(controlifyApi: ControlifyApi) {
}
// This is jank, but I did it after I got my wisdom teeth extracted so tbh I think I did good enough, but I won't be offended if someone changes it to something sane.
fun addProcessor(t: KClass<out Screen>, processorClazz: KClass<out CobblemonGUIProcessor>) {
ScreenProcessorFactory.registerProvider(t.java) {
processorClazz.primaryConstructor?.call(it)
}
}
companion object {
var RIDING_UP: InputBindingSupplier? = null
var RIDING_DOWN: InputBindingSupplier? = null
var RIDING_RIGHT: InputBindingSupplier? = null
var RIDING_LEFT: InputBindingSupplier? = null
var HIDE_PARTY: InputBindingSupplier? = null
var SUMMARY: InputBindingSupplier? = null
var PARTY_OVERLAY_DOWN: InputBindingSupplier? = null
var PARTY_OVERLAY_UP: InputBindingSupplier? = null
var SEND_OUT_POKEMON: InputBindingSupplier? = null
var RIDING_FREELOOK: InputBindingSupplier? = null
var INTERACT_WHEEL_UP_AXIS: InputBindingSupplier? = null
var INTERACT_WHEEL_DOWN_AXIS: InputBindingSupplier? = null
var INTERACT_WHEEL_LEFT_AXIS: InputBindingSupplier? = null
var INTERACT_WHEEL_RIGHT_AXIS: InputBindingSupplier? = null
val RIDING_POKEMON: BindContext = BindContext(
cobblemonResource("riding"),
{ mc: Minecraft ->
mc.player?.vehicle is PokemonEntity
}
)
val ORIENTATION_CONTROLLER_ACTIVE: BindContext = BindContext(
cobblemonResource("orientation_controller_active"),
{ mc: Minecraft ->
val localPlayer = mc.player
if (localPlayer == null) return@BindContext false
val vehicle = localPlayer.vehicle
vehicle is OrientationControllable && vehicle.getOrientationController().isActive()
}
)
val HAS_POKEMON: BindContext = BindContext(
cobblemonResource("has_pokemon"),
{mc: Minecraft ->
!CobblemonClient.storage.party.isEmpty()
}
)
val INTERACT_WHEEL_SCREEN: BindContext = BindContext(
cobblemonResource("wheel_screen"),
{ it.screen is InteractWheelGUI}
)
}
}
@@ -1,22 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.integration.controlify.gui
import com.cobblemon.mod.common.client.integration.controlify.gui.component.ControllerComponentManager
import dev.isxander.controlify.screenop.ScreenProcessor
import dev.isxander.controlify.virtualmouse.VirtualMouseBehaviour
import net.minecraft.client.gui.screens.Screen
open class CobblemonGUIProcessor(open val screen: Screen) : ScreenProcessor<Screen>(screen) {
val controllerComponentManager = ControllerComponentManager(screen)
override fun virtualMouseBehaviour(): VirtualMouseBehaviour {
return VirtualMouseBehaviour.DISABLED
}
}
@@ -1,70 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.integration.controlify.gui
import com.cobblemon.mod.common.client.gui.interact.wheel.InteractWheelGUI
import com.cobblemon.mod.common.client.integration.controlify.CobblemonControlifyEntrypoint
import dev.isxander.controlify.controller.ControllerEntity
import dev.isxander.controlify.controller.haptic.HapticEffects
import dev.isxander.controlify.screenop.ScreenControllerEventListener
import net.minecraft.util.Mth
import kotlin.math.abs
// Lots of this is taken from the RadialMenu in Controlify to make this screen feel consistent with it
class InteractWheelProcessor(override val screen: InteractWheelGUI) : CobblemonGUIProcessor(screen), ScreenControllerEventListener {
private var selectedButton = -1
private var idleTicks: Int = 0
private var idleTicksTimeout: Int? = null
init {
addEventListener(this)
}
override fun onControllerInput(controller: ControllerEntity) {
if (idleTicksTimeout == null) {
idleTicksTimeout = controller.input().orElseThrow().confObj().radialButtonFocusTimeoutTicks
}
// If not created from entrypoint then something is very wrong
val x = CobblemonControlifyEntrypoint.INTERACT_WHEEL_RIGHT_AXIS!!.on(controller).analogueNow()
- CobblemonControlifyEntrypoint.INTERACT_WHEEL_LEFT_AXIS!!.on(controller).analogueNow()
val y = CobblemonControlifyEntrypoint.INTERACT_WHEEL_DOWN_AXIS!!.on(controller).analogueNow()
- CobblemonControlifyEntrypoint.INTERACT_WHEEL_UP_AXIS!!.on(controller).analogueNow()
val threshold = controller.input().orElseThrow().config().config().buttonActivationThreshold
if (abs(x) >= threshold || abs(y) >= threshold) {
val angle = Mth.wrapDegrees(Mth.RAD_TO_DEG * Mth.atan2(y.toDouble(), x.toDouble()) - 90f) + 180f
val buttonCount = screen.buttons.size
val each = 360f / buttonCount
val newSelected = Mth.floor((angle + each / 2f) / each) % buttonCount
if (newSelected != selectedButton) {
selectedButton = newSelected
controller.hdHaptics().ifPresent { haptics -> haptics.playHaptic(HapticEffects.NAVIGATE) }
}
for (button in 0..<buttonCount) {
val selected = button == selectedButton
screen.buttons[button].isFocused = selected
}
idleTicks = 0
} else {
idleTicks = idleTicks+ 1
if (idleTicks>= idleTicksTimeout!! && selectedButton != -1) {
selectedButton = -1
for (button in screen.buttons) {
button.isFocused = false
}
controller.hdHaptics().ifPresent { haptics -> haptics.playHaptic(HapticEffects.NAVIGATE) }
}
}
}
}
@@ -1,33 +0,0 @@
package com.cobblemon.mod.common.client.integration.controlify.gui.component
import net.minecraft.client.gui.components.events.GuiEventListener
import net.minecraft.client.gui.screens.Screen
class ControllerComponent<T : Screen> {
var left: (T) -> ControllerComponent<T>? = { null }
var right: (T) -> ControllerComponent<T>? = { null }
var up: (T) -> ControllerComponent<T>? = { null }
var down: (T) -> ControllerComponent<T>? = { null }
var associatedGUIElement: GuiEventListener? = null
fun pairLeft(leftComponent: ControllerComponent<T>) {
left = { leftComponent }
leftComponent.right = { this }
}
fun pairRight(rightComponent: ControllerComponent<T>) {
right = { rightComponent }
rightComponent.left = { this }
}
fun pairUp(upComponent: ControllerComponent<T>) {
up = { upComponent }
upComponent.down = { this }
}
fun pairDown(downComponent: ControllerComponent<T>) {
down = { downComponent }
downComponent.up = { this }
}
}
@@ -1,17 +0,0 @@
package com.cobblemon.mod.common.client.integration.controlify.gui.component
import net.minecraft.client.gui.screens.Screen
class ControllerComponentManager<T : Screen>(val screen: T) {
var focused: ControllerComponent<T>?
get() = focused
set(value) {
focused = value
focused?.associatedGUIElement?.let { screen.focused = it }
}
fun left() = focused?.left?.invoke(screen)?.let { focused = it }
fun right() = focused?.right?.invoke(screen)?.let { focused = it }
fun up() = focused?.up?.invoke(screen)?.let { focused = it }
fun down() = focused?.down?.invoke(screen)?.let { focused = it }
}
@@ -9,7 +9,10 @@
package com.cobblemon.mod.common.entity.ai
import com.bedrockk.molang.Expression
import com.cobblemon.mod.common.CobblemonMemories
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.getMemorySafely
import com.cobblemon.mod.common.util.mainThreadRuntime
import com.cobblemon.mod.common.util.resolveInt
import com.cobblemon.mod.common.util.withQueryValue
@@ -29,12 +32,23 @@ object FleeFromAttackerTask {
Trigger { _, entity, _ ->
val hurtByEntity = it.get(hurtByEntity)
val avoidTarget = it.tryGet(avoidTarget).orElse(null)
if (avoidTarget != null && avoidTarget == hurtByEntity.uuid) {
if (avoidTarget != null && avoidTarget == hurtByEntity) {
return@Trigger false
}
mainThreadRuntime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
val avoidDurationTicks = mainThreadRuntime.resolveInt(avoidDurationTicks)
val pokemonEntity = entity as? PokemonEntity
pokemonEntity?.let {
it.after(1.0f) {
it.playMoodParticle("mood_stress")
}
}
entity.brain.setMemoryWithExpiry(MemoryModuleType.AVOID_TARGET, hurtByEntity, avoidDurationTicks.toLong())
return@Trigger true
}
}
@@ -8,6 +8,7 @@
package com.cobblemon.mod.common.entity.ai
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.ai.behavior.OneShot
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
@@ -24,6 +25,10 @@ object GetAngryAtAttackerTask {
Trigger { _, entity, _ ->
val hurtByEntity = it.get(hurtByEntity)
val angryAt = it.tryGet(angryAt).orElse(null)
if (angryAt == null && hurtByEntity != null) {
(entity as PokemonEntity?)?.playMoodParticle("mood_anger_steam")
}
if (angryAt != null && angryAt == hurtByEntity.uuid) {
return@Trigger false
}
@@ -82,6 +82,7 @@ import com.cobblemon.mod.common.entity.pokemon.effects.EffectTracker
import com.cobblemon.mod.common.entity.pokemon.effects.IllusionEffect
import com.cobblemon.mod.common.net.messages.client.OpenBehaviourEditorPacket
import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimationPacket
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokemonPacket
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
@@ -419,6 +420,9 @@ open class PokemonEntity(
var occupiedSeats = arrayOfNulls<Entity>(seats.size)
var moodParticleLock = false
var playedZeroStaminaParticle = false
init {
delegate.initialize(this)
delegate.changePokemon(pokemon)
@@ -833,6 +837,28 @@ open class PokemonEntity(
return future
}
fun playMoodParticle(particleName: String) {
if (moodParticleLock) return
cry()
SpawnSnowstormEntityParticlePacket(
cobblemonResource(particleName),
id,
listOf("head", "top")
).sendToPlayersAround(
x,
y,
z,
64.0,
level().dimension()
)
moodParticleLock = true
after(5.0f) {
moodParticleLock = false
}
}
override fun saveWithoutId(nbt: CompoundTag): CompoundTag {
val tethering = this.tethering
if (tethering != null) {
@@ -2213,6 +2239,8 @@ open class PokemonEntity(
ifRidingAvailable { _, _, state ->
state.stamina.set(entityData.get(RIDE_STAMINA))
}
playedZeroStaminaParticle = false
}
}
@@ -2241,12 +2269,26 @@ open class PokemonEntity(
override fun tickRidden(driver: Player, movementInput: Vec3) {
super.tickRidden(driver, movementInput)
ifRidingAvailable { behaviour, settings, state ->
behaviour.tick(settings, state, this, driver, movementInput)
if (entityData.get(RIDE_STAMINA) == -1F) {
state.stamina.set(1F, forced = true)
}
if (!level().isClientSide) {
val stamina = state.stamina.get()
if (stamina <= 0f) {
if (!playedZeroStaminaParticle) {
playMoodParticle("mood_stress")
playedZeroStaminaParticle = true
}
} else {
playedZeroStaminaParticle = false
}
}
if (!this.level().isClientSide) {
val pose = behaviour.pose(settings, state, this)
if (pose != this.entityData.get(POSE_TYPE)) {
@@ -44,6 +44,11 @@ class DefendOwnerSensor : Sensor<PokemonEntity>(10) {
return@findClosest false
}.map { mob -> mob as LivingEntity }
val previousAttacker = entity.brain.getMemorySafely(CobblemonMemories.NEAREST_VISIBLE_ATTACKER)
if (nearestAttacker.isPresent && previousAttacker.isEmpty) {
entity.playMoodParticle("mood_anger_steam")
}
entity.brain.setMemory(CobblemonMemories.NEAREST_VISIBLE_ATTACKER, nearestAttacker)
}
}
@@ -9,6 +9,7 @@
package com.cobblemon.mod.common.entity.pokemon.ai.tasks
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.getMemorySafely
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.Mob
import net.minecraft.world.entity.ai.behavior.OneShot
@@ -60,7 +61,12 @@ object AttackHostileMobsTask {
}
if (hostile != null) {
if (currentTarget == null) {
(entity as? PokemonEntity)?.playMoodParticle("mood_anger_steam")
}
entity.brain.setMemory(MemoryModuleType.ATTACK_TARGET, hostile)
true
} else {
false
@@ -91,7 +91,7 @@ class EatHeldItemTask(entity: PokemonEntity) : Behavior<PokemonEntity>(
}
this.timelastEaten = time
if (itemConfig != null && itemConfig.fullnessValue > 0) {
entity.pokemon.feedPokemon(itemConfig.fullnessValue, false)
entity.pokemon.feedPokemon(itemConfig.fullnessValue, false, false)
}
// Check if the result item is something that should be dropped
resultItemStack = entity.pokemon.heldItem()
@@ -13,7 +13,9 @@ import com.cobblemon.mod.common.api.apricorn.Apricorn
import com.cobblemon.mod.common.api.item.PokemonSelectingItem
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.client.pot.CookingQuality
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.network.chat.Component
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
@@ -91,7 +93,9 @@ class AprijuiceItem(val type: Apricorn): CobblemonItem(Properties().stacksTo(16)
return InteractionResultHolder.fail(stack)
}
pokemon.feedPokemon(1)
if (!pokemon.feedPokemon(1)) {
return InteractionResultHolder.fail(stack)
}
val boosts = getBoosts(stack)
pokemon.addRideBoosts(boosts.mapValues { it.value.toFloat() })
@@ -96,8 +96,9 @@ class PokePuffItem : Item(Properties().stacksTo(64)), PokemonSelectingItem {
return InteractionResultHolder.fail(stack)
}
// Feed the Pokémon 4 fullness points
pokemon.feedPokemon(4)
if (!pokemon.feedPokemon(4)) {
return InteractionResultHolder.fail(stack)
}
val friendshipChange = PokePuffUtils.calculateFriendshipChange(stack, pokemon.nature)
@@ -54,14 +54,16 @@ class FriendshipRaisingBerryItem(block: BerryBlock, val stat: Stat) : BerryItem(
val evLowerAmount = max(genericRuntime.resolveInt(CobblemonMechanics.berries.evLowerAmount), 0)
val decreasedEVs = pokemon.evs.add(stat, -evLowerAmount, ItemEvSource(player, stack, pokemon)) != 0
return if (increasedFriendship || decreasedEVs) {
pokemon.feedPokemon(1)
stack.consume(1, player)
InteractionResultHolder.success(stack)
} else {
InteractionResultHolder.pass(stack)
if (!increasedFriendship && !decreasedEVs) {
return InteractionResultHolder.pass(stack)
}
if (!pokemon.feedPokemon(1)) {
return InteractionResultHolder.fail(stack)
}
stack.consume(1, player)
return InteractionResultHolder.success(stack)
}
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
@@ -54,7 +54,10 @@ class HealingBerryItem(block: BerryBlock, val amount: () -> ExpressionLike): Ber
return InteractionResultHolder.fail(stack)
}
pokemon.feedPokemon(1)
if (!pokemon.feedPokemon(1)) {
return InteractionResultHolder.fail(stack)
}
pokemon.currentHealth = Integer.min(pokemon.currentHealth + genericRuntime.resolveInt(amount(), pokemon), pokemon.maxHealth)
stack.consume(1, player)
return InteractionResultHolder.success(stack)
@@ -62,7 +65,7 @@ class HealingBerryItem(block: BerryBlock, val amount: () -> ExpressionLike): Ber
override fun applyToBattlePokemon(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon) {
super.applyToBattlePokemon(player, stack, battlePokemon)
battlePokemon.originalPokemon.feedPokemon(1)
battlePokemon.originalPokemon.feedPokemon(1, playMoodParticle = false)
}
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
@@ -48,21 +48,26 @@ class PPRestoringBerryItem(block: BerryBlock, val amount: () -> ExpressionLike):
&& super.canUseOnPokemon(stack, pokemon)
override fun applyToPokemon(player: ServerPlayer, stack: ItemStack, pokemon: Pokemon, move: Move) {
if (canUseOnPokemon(stack, pokemon) && canUseOnMove(stack, move)) {
pokemon.feedPokemon(1)
val moveToRecover = pokemon.moveSet.find { it.template == move.template }
if (moveToRecover != null && moveToRecover.currentPp < moveToRecover.maxPp) {
moveToRecover.currentPp =
min(moveToRecover.maxPp, moveToRecover.currentPp + genericRuntime.resolveInt(amount(), pokemon))
if (!canUseOnPokemon(stack, pokemon) && canUseOnMove(stack, move)) {
return
}
stack.consume(1, player)
}
if (!pokemon.feedPokemon(1)) {
return
}
val moveToRecover = pokemon.moveSet.find { it.template == move.template }
if (moveToRecover != null && moveToRecover.currentPp < moveToRecover.maxPp) {
moveToRecover.currentPp =
min(moveToRecover.maxPp, moveToRecover.currentPp + genericRuntime.resolveInt(amount(), pokemon))
stack.consume(1, player)
}
}
override fun applyToBattlePokemon(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon, move: Move) {
super.applyToBattlePokemon(player, stack, battlePokemon, move)
battlePokemon.originalPokemon.feedPokemon(1)
battlePokemon.originalPokemon.feedPokemon(1, playMoodParticle = false)
}
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
@@ -59,7 +59,9 @@ class PortionHealingBerryItem(block: BerryBlock, val canCauseConfusion: Boolean,
}
// count these berries as multiple feedings due to the amount they heal
pokemon.feedPokemon(5)
if (!pokemon.feedPokemon(5)) {
return InteractionResultHolder.fail(stack)
}
var amount = Integer.min(pokemon.currentHealth + (genericRuntime.resolveFloat(portion(), pokemon) * pokemon.maxHealth).toInt(), pokemon.maxHealth)
CobblemonEvents.POKEMON_HEALED.postThen(PokemonHealedEvent(pokemon, amount, this), { cancelledEvent -> return InteractionResultHolder.fail(stack)}) { event ->
@@ -73,7 +75,7 @@ class PortionHealingBerryItem(block: BerryBlock, val canCauseConfusion: Boolean,
override fun applyToBattlePokemon(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon) {
super.applyToBattlePokemon(player, stack, battlePokemon)
battlePokemon.originalPokemon.feedPokemon(5)
battlePokemon.originalPokemon.feedPokemon(5, playMoodParticle = false)
}
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
@@ -58,19 +58,23 @@ class StatusCuringBerryItem(block: BerryBlock, vararg val status: Status): Berry
stack: ItemStack,
pokemon: Pokemon
): InteractionResultHolder<ItemStack>? {
return if (canUseOnPokemon(stack, pokemon)) {
pokemon.feedPokemon(1)
pokemon.status = null
stack.consume(1, player)
InteractionResultHolder.success(stack)
} else {
InteractionResultHolder.fail(stack)
if (!canUseOnPokemon(stack, pokemon)) {
return InteractionResultHolder.fail(stack)
}
if (!pokemon.feedPokemon(1)) {
return InteractionResultHolder.fail(stack)
}
pokemon.status = null
stack.consume(1, player)
return InteractionResultHolder.success(stack)
}
override fun applyToBattlePokemon(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon) {
super.applyToBattlePokemon(player, stack, battlePokemon)
battlePokemon.originalPokemon.feedPokemon(1)
battlePokemon.originalPokemon.feedPokemon(1, playMoodParticle = false)
}
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
@@ -53,7 +53,10 @@ class BerryJuiceItem : CobblemonItem(Properties()), PokemonSelectingItem, Healin
if (!canUseOnPokemon(stack, pokemon)) {
return InteractionResultHolder.fail(stack)
}
pokemon.feedPokemon(1)
if (!pokemon.feedPokemon(1)) {
return InteractionResultHolder.fail(stack)
}
var amount = Integer.min(pokemon.currentHealth + 20, pokemon.maxHealth)
CobblemonEvents.POKEMON_HEALED.postThen(PokemonHealedEvent(pokemon, amount, this), { cancelledEvent -> return InteractionResultHolder.fail(stack)}) { event ->
@@ -74,7 +77,9 @@ class BerryJuiceItem : CobblemonItem(Properties()), PokemonSelectingItem, Healin
override fun applyToBattlePokemon(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon) {
super.applyToBattlePokemon(player, stack, battlePokemon)
battlePokemon.originalPokemon.feedPokemon(1)
battlePokemon.originalPokemon.feedPokemon(1, playMoodParticle = false)
if (!player.hasInfiniteMaterials()) {
val woodenBowlItemStack = ItemStack(Items.BOWL)
if (!player.inventory.add(woodenBowlItemStack)) {
@@ -33,7 +33,10 @@ class FreshStartMochiItem : CobblemonItem(Properties()), PokemonSelectingItem {
return InteractionResultHolder.fail(stack)
}
pokemon.feedPokemon(1)
if (!pokemon.feedPokemon(1)) {
return InteractionResultHolder.fail(stack)
}
pokemon.evs.forEach {
pokemon.evs[it.key] = 0
}
@@ -24,7 +24,9 @@ class MochiItem(stat: Stats): EVIncreaseItem(stat, 4) {
return InteractionResultHolder.fail(stack)
}
pokemon.feedPokemon(1)
if (!pokemon.feedPokemon(1)) {
return InteractionResultHolder.fail(stack)
}
return super.applyToPokemon(player, stack, pokemon)
}
@@ -35,16 +35,9 @@ class SinisterTeaItem : Item(
val effectsComponent = stack.get(CobblemonItemComponents.MOB_EFFECTS)
if (effectsComponent != null) {
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)
}
for (effect in effectsComponent.mobEffects) {
val effectCopy = MobEffectInstance(effect)
user.addEffect(effectCopy)
}
}
}
@@ -897,6 +897,10 @@ open class Pokemon : ShowdownIdentifiable {
this.recall()
}
fun playMoodParticle(particleName: String) {
entity?.playMoodParticle(particleName)
}
fun heal() {
CobblemonEvents.POKEMON_HEALED.postThen(PokemonHealedEvent(this)) { event ->
this.currentHealth = maxHealth
@@ -964,23 +968,13 @@ open class Pokemon : ShowdownIdentifiable {
else -> 0 // For weights less than 0.1
}
fun feedPokemon(feedCount: Int, playSound: Boolean = true) {
// play sounds from the entity first (itemstack is consumed outside of this function)
if (this.entity != null && playSound) {
val fullnessPercent = ((this.currentFullness).toFloat() / (this.getMaxFullness()).toFloat()) * (.5f)
if (this.currentFullness >= this.getMaxFullness()) {
this.entity?.playSound(CobblemonSounds.BERRY_EAT_FULL, 1F, 1F)
}
else {
this.entity?.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F + fullnessPercent)
}
}
fun feedPokemon(feedCount: Int, playSound: Boolean = true, playMoodParticle: Boolean = true): Boolean {
playFullnessEffects(playSound, playMoodParticle)
// if it is already full we don't need to do anything
// TODO this can happen when feeding in battle since we are temporarily ignoring fullness checks for pp/hp/status berries
if (isFull()) {
return
return false
}
this.currentFullness = (this.currentFullness + feedCount).coerceIn(0, this.getMaxFullness())
@@ -989,6 +983,31 @@ open class Pokemon : ShowdownIdentifiable {
if (this.currentFullness == 1) {
this.resetMetabolismCycle()
}
return true
}
private fun playFullnessEffects(playSound: Boolean = true, playMoodParticle: Boolean = true) {
if (!playSound && !playMoodParticle) return
val pokemonEntity = entity ?: return
val fullnessPercent = ((this.currentFullness).toFloat() / (this.getMaxFullness()).toFloat()) * (.5f)
if (!isFull()) {
if (playSound) {
pokemonEntity.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F + fullnessPercent)
}
return
}
if (playSound) {
pokemonEntity.playSound(CobblemonSounds.BERRY_EAT_FULL, 1F, 1F)
if (playMoodParticle) {
pokemonEntity.playMoodParticle("mood_annoyed")
}
}
}
// decrease a pokemon's Fullness value by a certain amount
@@ -0,0 +1,55 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:mood_anger_steam",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/mood/steam_center_double"
}
},
"events": {
"veins": {
"particle_effect": {
"effect": "cobblemon:mood_anger_veins",
"type": "emitter"
}
}
},
"components": {
"minecraft:emitter_rate_instant": {
"num_particles": 1
},
"minecraft:emitter_lifetime_looping": {
"active_time": 1,
"sleep_time": 0.25
},
"minecraft:emitter_lifetime_events": {
"creation_event": "veins"
},
"minecraft:emitter_shape_point": {
"offset": [0, "math.clamp((v.entity_radius*1.2),0.48,0.96)*0.75", 0]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": 1
},
"minecraft:particle_initial_speed": 0,
"minecraft:particle_motion_dynamic": {},
"minecraft:particle_appearance_billboard": {
"size": ["math.clamp((v.entity_radius*1.5),0.9,2.4)", "math.clamp((v.entity_radius*0.5),0.3,0.8)"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 48,
"texture_height": 176,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [48, 16],
"step_UV": [0, 16],
"max_frame": 11,
"stretch_to_lifetime": true
}
}
}
}
}
}
@@ -0,0 +1,66 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:mood_anger_veins",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/mood/vein_red"
}
},
"components": {
"minecraft:emitter_initialization": {
"creation_expression": "v.particle_size = math.clamp((v.entity_radius*0.75),0.15,0.4);"
},
"minecraft:emitter_rate_steady": {
"spawn_rate": 1,
"max_particles": 1
},
"minecraft:emitter_lifetime_looping": {
"active_time": 1,
"sleep_time": 0.25
},
"minecraft:emitter_shape_point": {
"direction": ["math.random(-1,1)", 1.5, "math.random(-1,1)"]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": 1.25
},
"minecraft:particle_initial_spin": {
"rotation": "math.random_integer(-1,2)*90"
},
"minecraft:particle_initial_speed": "v.particle_size*13",
"minecraft:particle_motion_dynamic": {
"linear_acceleration": [0, 0.75, 0],
"linear_drag_coefficient": "v.particle_size*15"
},
"minecraft:particle_appearance_billboard": {
"size": ["math.clamp((v.entity_radius*0.75),0.15,0.3)", "math.clamp((v.entity_radius*0.75),0.15,0.3)"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 22,
"texture_height": 11,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [11, 11],
"step_UV": [11, 0],
"frames_per_second": 6,
"max_frame": 2,
"loop": true
}
}
},
"minecraft:particle_motion_collision": {},
"minecraft:particle_appearance_lighting": {},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age/v.particle_lifetime",
"gradient": {
"0.86": "#ffffffff",
"1.0": "#FF000000"
}
}
}
}
}
}
@@ -0,0 +1,49 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:mood_annoyed",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/mood/scribble_purple"
}
},
"components": {
"minecraft:emitter_initialization": {
"creation_expression": "v.particle_size = math.clamp((v.entity_radius*0.75),0.2,0.5);"
},
"minecraft:emitter_rate_instant": {
"num_particles": 1
},
"minecraft:emitter_lifetime_once": {
"active_time": 2
},
"minecraft:emitter_shape_point": {
"direction": [0, 1, 0]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": 1
},
"minecraft:particle_initial_speed": "v.particle_size*10",
"minecraft:particle_motion_dynamic": {
"linear_drag_coefficient": 3
},
"minecraft:particle_appearance_billboard": {
"size": ["math.clamp((v.entity_radius*0.75),0.2,0.5)", "math.clamp((v.entity_radius*0.75),0.2,0.5)"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 168,
"texture_height": 14,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [14, 14],
"step_UV": [14, 0],
"frames_per_second": 10,
"max_frame": 12
}
}
},
"minecraft:particle_appearance_lighting": {}
}
}
}
@@ -0,0 +1,47 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:mood_stress",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/mood/sweat_blue"
}
},
"components": {
"minecraft:emitter_initialization": {
"creation_expression": "v.particle_height = math.clamp((v.entity_radius*1.2),0.48,0.96);"
},
"minecraft:emitter_rate_instant": {
"num_particles": 1
},
"minecraft:emitter_lifetime_looping": {
"active_time": 1
},
"minecraft:emitter_shape_point": {
"offset": [0, "math.clamp((v.entity_radius*1.2),0.48,0.96)*0.75", 0]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": 0.45
},
"minecraft:particle_initial_speed": 0,
"minecraft:particle_motion_dynamic": {},
"minecraft:particle_appearance_billboard": {
"size": ["math.clamp((v.entity_radius*1.2),0.48,0.96)", "math.clamp((v.entity_radius*0.65),0.26,0.52)"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 216,
"texture_height": 13,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [24, 13],
"step_UV": [24, 0],
"max_frame": 9,
"stretch_to_lifetime": true
}
}
},
"minecraft:particle_appearance_lighting": {}
}
}
}
@@ -820,14 +820,6 @@
"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",
@@ -3523,7 +3515,6 @@
"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",
@@ -9457,11 +9448,5 @@
"stat.cobblemon.reel_ins": "PokéRod Catches",
"stat.cobblemon.riding_land": "Distance by Pokémon on Land",
"stat.cobblemon.riding_air": "Distance by Pokémon in Air",
"stat.cobblemon.riding_liquid": "Distance by Pokémon in Liquid",
"controlify.category.cobblemon.cobblemon": "Cobblemon",
"controlify.bind.cobblemon.riding_up": "Look Up",
"controlify.bind.cobblemon.riding_down": "Look Down",
"controlify.bind.cobblemon.riding_left": "Look Left",
"controlify.bind.cobblemon.riding_right": "Look Right"
"stat.cobblemon.riding_liquid": "Distance by Pokémon in Liquid"
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 599 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 979 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

@@ -1,28 +0,0 @@
{
"defaults": {
"cobblemon:riding_up": {
"axis": "controlify:axis/right_stick_up"
},
"cobblemon:riding_down": {
"axis": "controlify:axis/right_stick_down"
},
"cobblemon:riding_left": {
"axis": "controlify:axis/right_stick_left"
},
"cobblemon:riding_right": {
"axis": "controlify:axis/right_stick_right"
},
"cobblemon:interact_wheel_up": {
"axis": "controlify:axis/right_stick_up"
},
"cobblemon:interact_wheel_down": {
"axis": "controlify:axis/right_stick_down"
},
"cobblemon:interact_wheel_left": {
"axis": "controlify:axis/right_stick_left"
},
"cobblemon:interact_wheel_right": {
"axis": "controlify:axis/right_stick_right"
}
}
}
@@ -17,7 +17,7 @@
"conditions": {
"items": [
{
"items": "#cobblemon:mint_leaves"
"items": "#cobblemon:mint_leaf"
}
]
}
@@ -26,7 +26,7 @@
},
{
"content": 2,
"tag": "#cobblemon:mint_leaves"
"tag": "#cobblemon:mint_leaf"
},
{
"content": 2,
@@ -1,14 +0,0 @@
{
"ingredient": "cobblemon:mental_herb",
"colour": "light_blue",
"mobEffects": [
{
"effect": "cobblemon:mental_restoration",
"duration": 200,
"amplifier": 0,
"ambient": false,
"visible": true,
"showIcon": true
}
]
}
@@ -1,14 +0,0 @@
{
"ingredient": "minecraft:milk_bucket",
"colour": "white",
"mobEffects": [
{
"effect": "cobblemon:cleanse_all",
"duration": 1,
"amplifier": 0,
"ambient": false,
"visible": true,
"showIcon": true
}
]
}
@@ -1,14 +0,0 @@
{
"ingredient": "cobblemon:moomoo_milk",
"colour": "white",
"mobEffects": [
{
"effect": "cobblemon:cleanse_all",
"duration": 1,
"amplifier": 0,
"ambient": false,
"visible": true,
"showIcon": true
}
]
}
@@ -1,14 +0,0 @@
{
"ingredient": "cobblemon:white_herb",
"colour": "white",
"mobEffects": [
{
"effect": "cobblemon:cleanse_negative",
"duration": 1,
"amplifier": 0,
"ambient": false,
"visible": true,
"showIcon": true
}
]
}
@@ -1,7 +1,6 @@
{
"values": [
"cobblemon:apricorn_boat",
"cobblemon:saccharine_boat",
"#cobblemon:chest_boats"
"cobblemon:apricorn_chest_boat"
]
}
@@ -1,6 +0,0 @@
{
"values": [
"cobblemon:apricorn_chest_boat",
"cobblemon:saccharine_chest_boat"
]
}
@@ -11,7 +11,6 @@
"cobblemon:black_glasses",
"cobblemon:black_sludge",
"cobblemon:blunder_policy",
"cobblemon:bright_powder",
"cobblemon:cell_battery",
"cobblemon:charcoal_stick",
"cobblemon:choice_band",
@@ -20,7 +19,6 @@
"cobblemon:cleanse_tag",
"cobblemon:clear_amulet",
"cobblemon:covert_cloak",
"cobblemon:damp_rock",
"cobblemon:destiny_knot",
"cobblemon:deep_sea_scale",
"cobblemon:deep_sea_tooth",
@@ -38,9 +36,7 @@
"cobblemon:focus_sash",
"cobblemon:grip_claw",
"cobblemon:hard_stone",
"cobblemon:heat_rock",
"cobblemon:heavy_duty_boots",
"cobblemon:icy_rock",
"cobblemon:iron_ball",
"cobblemon:kings_rock",
"cobblemon:lagging_tail",
@@ -52,13 +48,9 @@
"cobblemon:lucky_egg",
"cobblemon:luminous_moss",
"cobblemon:magnet",
"cobblemon:medicinal_leek",
"cobblemon:mental_herb",
"cobblemon:metal_powder",
"cobblemon:metal_coat",
"cobblemon:metronome",
"cobblemon:miracle_seed",
"cobblemon:mirror_herb",
"cobblemon:muscle_band",
"cobblemon:mystic_water",
"cobblemon:never_melt_ice",
@@ -67,13 +59,11 @@
"cobblemon:power_band",
"cobblemon:power_belt",
"cobblemon:power_bracer",
"cobblemon:power_herb",
"cobblemon:power_lens",
"cobblemon:power_weight",
"cobblemon:protective_pads",
"cobblemon:punching_glove",
"cobblemon:quick_claw",
"cobblemon:quick_powder",
"cobblemon:razor_claw",
"cobblemon:razor_fang",
"cobblemon:red_card",
@@ -88,9 +78,7 @@
"cobblemon:silk_scarf",
"cobblemon:silver_powder",
"cobblemon:smoke_ball",
"cobblemon:smooth_rock",
"cobblemon:soft_sand",
"cobblemon:soothe_bell",
"cobblemon:spell_tag",
"cobblemon:sticky_barb",
"cobblemon:terrain_extender",
@@ -99,13 +87,41 @@
"cobblemon:twisted_spoon",
"cobblemon:utility_umbrella",
"cobblemon:weakness_policy",
"cobblemon:white_herb",
"cobblemon:wide_lens",
"cobblemon:wise_glasses",
"cobblemon:zoom_lens",
"cobblemon:bright_powder",
"cobblemon:metal_powder",
"cobblemon:quick_powder",
"cobblemon:mental_herb",
"cobblemon:mirror_herb",
"cobblemon:power_herb",
"cobblemon:white_herb",
"cobblemon:damp_rock",
"cobblemon:heat_rock",
"cobblemon:smooth_rock",
"cobblemon:icy_rock",
"cobblemon:life_orb",
"cobblemon:toxic_orb",
"cobblemon:flame_orb",
"cobblemon:white_herb",
"cobblemon:smoke_ball",
"cobblemon:lucky_egg",
"cobblemon:kings_rock",
"cobblemon:deep_sea_scale",
"cobblemon:deep_sea_tooth",
"cobblemon:metal_coat",
"cobblemon:medicinal_leek",
"minecraft:bone",
"minecraft:snowball",
"#cobblemon:type_gems",
"#cobblemon:held/terrain_seeds"
"#cobblemon:held/terrain_seeds",
"cobblemon:scope_lens",
"cobblemon:terrain_extender",
"cobblemon:throat_spray",
"cobblemon:utility_umbrella",
"cobblemon:wide_lens",
"cobblemon:zoom_lens"
]
}
@@ -7,8 +7,6 @@
"minecraft:dead_bush",
"minecraft:honey_bottle",
"minecraft:pink_petals",
"minecraft:spore_blossom",
"minecraft:chorus_flower",
"minecraft:poisonous_potato",
"minecraft:rotten_flesh",
"minecraft:spore_blossom",
@@ -17,9 +15,9 @@
"cobblemon:big_root",
"cobblemon:energy_root",
"cobblemon:galarica_nuts",
"#cobblemon:herbs",
"cobblemon:mirror_herb",
"cobblemon:pep_up_flower",
"minecraft:milk_bucket",
"cobblemon:moomoo_milk"
"cobblemon:power_herb",
"cobblemon:revival_herb"
]
}
@@ -13,9 +13,9 @@
"cobblemon:big_root",
"cobblemon:energy_root",
"cobblemon:galarica_nuts",
"#cobblemon:herbs",
"cobblemon:mirror_herb",
"cobblemon:pep_up_flower",
"minecraft:milk_bucket",
"cobblemon:moomoo_milk"
"cobblemon:power_herb",
"cobblemon:revival_herb"
]
}
@@ -1,6 +1,6 @@
{
"replace": false,
"values": [
"#cobblemon:chest_boats"
"cobblemon:apricorn_chest_boat"
]
}
@@ -11,7 +11,6 @@ package com.cobblemon.mod.fabric
import com.cobblemon.mod.common.*
import com.cobblemon.mod.common.advancement.CobblemonCriteria
import com.cobblemon.mod.common.advancement.predicate.CobblemonEntitySubPredicates
import com.cobblemon.mod.common.CobblemonMobEffects
import com.cobblemon.mod.common.api.net.serializers.*
import com.cobblemon.mod.common.item.group.CobblemonItemGroups
import com.cobblemon.mod.common.loot.LootInjector
@@ -355,12 +354,6 @@ object CobblemonFabric : CobblemonImplementation {
CompostingChanceRegistry.INSTANCE.add(item, chance)
}
override fun registerMobEffects() {
CobblemonMobEffects.register { identifier, effect ->
Registry.register(CobblemonMobEffects.registry, identifier, effect)
}
}
private class CobblemonReloadListener(private val identifier: ResourceLocation, private val reloader: PreparableReloadListener, private val dependencies: Collection<ResourceLocation>) : IdentifiableResourceReloadListener {
override fun reload(synchronizer: PreparableReloadListener.PreparationBarrier, manager: ResourceManager, prepareProfiler: ProfilerFiller, applyProfiler: ProfilerFiller, prepareExecutor: Executor, applyExecutor: Executor): CompletableFuture<Void> = this.reloader.reload(synchronizer, manager, prepareProfiler, applyProfiler, prepareExecutor, applyExecutor)
@@ -30,9 +30,6 @@
],
"modmenu": [
"com.cobblemon.mod.fabric.client.integration.modmenu.CobblemonModMenu"
],
"controlify": [
"com.cobblemon.mod.common.client.integration.controlify.CobblemonControlifyEntrypoint"
]
},
"mixins": [
@@ -16,7 +16,6 @@ import com.cobblemon.mod.common.CobblemonRecipeCategories.COOKING_POT_MISC
import com.cobblemon.mod.common.CobblemonRecipeCategories.COOKING_POT_SEARCH
import com.cobblemon.mod.common.advancement.CobblemonCriteria
import com.cobblemon.mod.common.advancement.predicate.CobblemonEntitySubPredicates
import com.cobblemon.mod.common.CobblemonMobEffects
import com.cobblemon.mod.common.api.net.serializers.*
import com.cobblemon.mod.common.item.group.CobblemonItemGroups
import com.cobblemon.mod.common.loot.LootInjector
@@ -462,16 +461,6 @@ class CobblemonNeoForge : CobblemonImplementation {
// returns one single json setup that you can paste in the compostables.json values block and done
}
override fun registerMobEffects() {
MOD_BUS.addListener<RegisterEvent> { event ->
event.register(CobblemonMobEffects.resourceKey) { helper ->
CobblemonMobEffects.register { identifier, effect ->
helper.register(identifier, effect)
}
}
}
}
private fun onVillagerTradesRegistry(e: VillagerTradesEvent) {
CobblemonTradeOffers.tradeOffersFor(e.type).forEach { tradeOffer ->
// Will never be null between 1 n 5
@@ -1 +0,0 @@
com.cobblemon.mod.common.client.integration.controlify.CobblemonControlifyEntrypoint