mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-21 06:36:25 -04:00
Compare commits
28
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ada7f0faf8 | ||
|
|
e1eff89259 | ||
|
|
cc149a0ff2 | ||
|
|
3fea718766 | ||
|
|
4a41060533 | ||
|
|
78daec9c7b | ||
|
|
07f087c35c | ||
|
|
19f0bc29f4 | ||
|
|
531f64394a | ||
|
|
7044cb35b2 | ||
|
|
e258d6439f | ||
|
|
221e51b023 | ||
|
|
c9fe117916 | ||
|
|
af3b6e3f2a | ||
|
|
1b7759b77d | ||
|
|
698c07f0b8 | ||
|
|
b0d2df2917 | ||
|
|
f6ad1ab7aa | ||
|
|
3f85ce0c81 | ||
|
|
e25c3c3d7c | ||
|
|
f16ec1d6d3 | ||
|
|
73e59159a0 | ||
|
|
5b7b430e5f | ||
|
|
4e6f2973c2 | ||
|
|
822794230d | ||
|
|
d58603ff33 | ||
|
|
157532f372 | ||
|
|
3a1c3fc934 |
+1
-5
@@ -5,16 +5,12 @@
|
||||
- Dog Pokémon (Growlithe, Arcanine, etc.) intimidate Skeletons.
|
||||
- Cat Pokémon (Meowth, Persian, etc.) intimidate Creepers and Phantoms.
|
||||
- Sleep-related Pokémon (Munsharna, Komala, etc.) intimidate Phantoms.
|
||||
- Some Pokémon naturally hunt each other.
|
||||
- Added a Behaviour Editor to the NPC editing screen.
|
||||
- Added /behaviouredit command for opening the Behaviour Editor on Pokémon and NPCs.
|
||||
- Editing variables for Pokémon is not yet supported.
|
||||
|
||||
### Developer
|
||||
- baseScale in NPCs has been removed from classes and presets, and in the entity it is replaced with hitboxScale and renderScale.
|
||||
|
||||
### MoLang & Datapacks
|
||||
- Added a `behaviours` datapack folder which motivates the Behaviour Editor screen on NPCs and Pokémon.
|
||||
- Added very many behaviours to choose from.
|
||||
- Added many default behaviours.
|
||||
- Removed many NPC presets that now exist as behaviours. This is a breaking change if you are using NPCs with these presets.
|
||||
- NPCs with these presets should be modified to instead list under `"behaviours"` all the equivalent behaviours.
|
||||
+1
-7
@@ -4,16 +4,10 @@
|
||||
- The button on the right allows for changing the box wallpaper.
|
||||
- The option buttons on the left side allow for sorting the box by name, level, Pokédex number, gender, and type. Shift clicking allows for sorting in reverse order.
|
||||
- Added filter functionality in PC UI, which supports `PokemonProperties` (e.g. `shiny=yes` shows all shiny Pokémon).
|
||||
- Names can be filtered by exact or partial matches, e.g. entering "cha" will show Charmander, Charmeleon, etc.
|
||||
- Added `/changewallpaper <player> <boxNumber> <wallpaper>` command to change a box wallpaper through commands.
|
||||
- Added `/renamebox <player> <boxNumber> <name>` command to rename a PC box through commands.
|
||||
- Added IVs and EVs stat displays in PC.
|
||||
- Added ability to change boxes by scrolling.
|
||||
- PC will now open to last box viewed within a session.
|
||||
|
||||
### Changes
|
||||
- Slots in pastures will now have darker backgrounds and italicised Pokémon names if the Pokémon is not owned by the player.
|
||||
- The pasture slot will show the name of the Pokémon owner when hovered if the Pokémon is not owned.
|
||||
- improved filter by Name, now is available search by exact names or partial matches, for example "cha" will show Charmander, Charmeleon and Charizard among others that match.
|
||||
|
||||
### Developer
|
||||
- Added `RenamePCBoxEvent.Pre` and `RenamePCBoxEvent.Post` events to prevent players from renaming a box or changing their input.
|
||||
|
||||
+3
-49
@@ -7,7 +7,6 @@
|
||||
- Added `/cobblemonconfig reload` command to reload `main.json` configuration. **Note:** Some settings require a server restart to take effect; use this command cautiously.
|
||||
- Added `blacklisted_items_to_hold` and `whitelisted_items_to_hold` tags to allow for controlling which items players can give to their Pokémon. If the whitelist is empty, it will consider all item as allowed (unless they are in the blacklist).
|
||||
- Pokémon now follow the mouse cursor on the Summary screen, with an option to disable this in the settings.
|
||||
- Added Datapackable Item interactions with Pokemon
|
||||
- Pokémon's held items can now be rendered, with a visibility toggle in the Summary screen.
|
||||
- Added cosmetic item functionality for Pokémon. Certain cosmetic items can be given to applicable Pokémon via the interact menu.
|
||||
- Added the various log blocks as cosmetic items for Timburr and Komala.
|
||||
@@ -18,10 +17,10 @@
|
||||
- Added cosmetics for Gurdurr, Conkeldurr, Squirtle Line, Sneasler, Sandle line, Treecko line, Braixen, Delphox, and Dragonite.
|
||||
- Added `/transformmodelpart (position|rotation|scale) <modelPart> <transform: x y z>` command that can add transformations to a pokemon's model part.
|
||||
- The player executing the command must be facing the target pokemon entity. Transformations are not persistent and will revert when resources are reloaded.
|
||||
- Added `legacy` and `special` sourced moves to Pokémon.
|
||||
- Added lang keys for all moves and abilities up to Generation 9.
|
||||
- Fixed Moon Ball moon phase logic to actually work correctly
|
||||
- Added `translucent_cull` boolean option into resolver's layer to allow for translucent textures with culling
|
||||
- Added [LambDynamicLights](https://modrinth.com/mod/lambdynamiclights) support for items held by Pokémon, evolution stone blocks, evolution stone items, Pokédex, Luminous Moss, Flame Orb, and Magmarizer.
|
||||
- Added [LambDynamicLights](https://modrinth.com/mod/lambdynamiclights) support for items held by Pokémon.
|
||||
- Added the Clear Amulet, Grip Claw, Lagging Tail, Luminous Moss, Metal Alloy, Scroll of Darkness, Scroll of Waters
|
||||
- Added Recipes for Masterpiece Cup, Eject Pack
|
||||
- Added modification to Minecraft Creative Inventory search to account for item names that contain `poké` when input contains `poke`.
|
||||
@@ -31,18 +30,13 @@
|
||||
- Added `/pcsearch <player> <pokemonProperties>` command that searches for a specific Pokémon within a player's PC.
|
||||
- Added `/pctake <player> <box> <slot>` command that takes a specific Pokémon from a player's PC. Removes the pokemon if target is self or ran from the server.
|
||||
- Added Hyper Training items (IV Modification) as well as some additional candy items to do so (Health Candy, Sickly Candy)
|
||||
- Added Galarica Nut Bushes
|
||||
- Added functionality to Everstone when held by a Pokémon; suppresses evolution notification and hides evolve button in summary interface.
|
||||
|
||||
### Pokémon Added
|
||||
|
||||
#### Gen 2
|
||||
- Marill
|
||||
- Azumarill
|
||||
- Dunsparce
|
||||
|
||||
#### Gen 3
|
||||
- Azurill
|
||||
- Spoink
|
||||
- Grumpig
|
||||
- Snorunt
|
||||
@@ -80,8 +74,6 @@
|
||||
- Solosis
|
||||
- Duosion
|
||||
- Reuniclus
|
||||
- Mienfoo
|
||||
- Mienshao
|
||||
|
||||
#### Gen 6
|
||||
- Inkay
|
||||
@@ -182,12 +174,8 @@
|
||||
- Added Syrupy Apples.
|
||||
- Seel
|
||||
- Dewgong
|
||||
- Honedge
|
||||
- Doublade
|
||||
- Aegislash
|
||||
|
||||
### Changes
|
||||
- Changed pokemon caught and seen count to update based on the current pokedex being looked
|
||||
- Renamed `chargeGainedPerTick` config to `secondsToChargeHealingMachine`.
|
||||
- Made Blocks of Gold count as Big Nuggets when held by a Pokémon (for Fling functionality)
|
||||
- Players can now eat Sweet and Tart Apples, Whipped Dreams, and the Alcremie Sweets.
|
||||
@@ -225,13 +213,8 @@
|
||||
- Saccharine Leaves are now Collectable
|
||||
- Saccharine Leaves Age 1 or higher will now show Yellow particles when broken
|
||||
- Destroying a Saccharine Honey Log will now drop a Saccharine Log in stead of nothing
|
||||
- Reworked some compost chances
|
||||
- Updated interaction interface to include 4 more option spaces
|
||||
- Made lecterns that hold a Pokédex emit light.
|
||||
- Updated light levels for active PC, Pasture, Healing Machine, and Data Monitor.
|
||||
|
||||
### Fixes
|
||||
- Fixed game crashing when removing national pokedex using datapacks
|
||||
- Fixed Particles sometimes facing the wrong direction (looking at you, Swords Dance)
|
||||
- Fixed PCs always opening at box 2 instead of box 1.
|
||||
- Fixed not being able to do complex item requirements aside from just NBT with evolution conditions, requirements and fossil items.
|
||||
@@ -258,7 +241,6 @@
|
||||
- Fixed Pokémon marked as silent still playing shiny sounds and effects.
|
||||
- Fixed an issue with newer versions of Fabric API where underground Pokémon were spawning in The End.
|
||||
- Fixed spawning not working well when you're at high points surrounded by lower altitude spawning areas, such as flying.
|
||||
- Fixed some Pokémon having erroneous tutor moves if another move included a valid tutor move as a substring.
|
||||
- Fixed certain Pokémon with forms not having appropriate stock Pokédex entries.
|
||||
- Fixed issue with Pokédex Scanner that caused the open/close overlay to have the wrong opacity values
|
||||
- Fixed dragon's breath not being usable on the restoration tank when it should be
|
||||
@@ -281,22 +263,6 @@
|
||||
- Fixed issue where Pokémon spawned by the "spawnallpokemon" command potentially receiving a raft.
|
||||
- Fixed logspam on NeoForge when adorn is not installed
|
||||
- Fixed Cobblemon crashing if it tries to load a bedrock model not meant for cobblemon (example: Qlipoth Awakening)
|
||||
- Fixed Berries (and thus mulches) not being plantable on Farmers delight rich soil farmland
|
||||
- Fixed wild Pokémon vanishing when third party mods try to tame them the "vanilla" way
|
||||
- Fixed Pokémon not being able to path over skulk veins, pressure plates, fence gates, signs, lanterns, chains, and many other short blocks.
|
||||
- Fixed some cases in which Pokémon could not path over fence posts situations.
|
||||
- Fixed flyers not being able to do vertical takeoff if surrounded by blocks.
|
||||
- Fixed swimming Pokémon attempting to swim up through solid blocks.
|
||||
- Fixed Pokémon surface swimming diving downward a block for the duration of the swim.
|
||||
- Improved flyers avoiding getting stuck on fence posts.
|
||||
- Fixed air balloon battle text not correctly displaying the Pokémon or item name
|
||||
- Fixed an issue where items retrieved from a Display case would disappear if a player's inventory is full
|
||||
- Fixed Pokédex Scanner not respecting the "Invert Mouse" option.
|
||||
- Fixed a crash due to a ConcurrentModificationException that could occur during world generation.
|
||||
- Fixed Moon Ball moon phase logic to actually work correctly
|
||||
- Fixed recoil eyes on Shellder & Cloyster.
|
||||
- Fixed Shroomish spinning at lightning speed when fainting (no longer allowed to let it rip.)
|
||||
- Fixed Quaxly's animations showing hidden wing sets
|
||||
|
||||
### Developer
|
||||
- A finished battle now has winners and losers set inside of `PokemonBattle` instead of them always being empty.
|
||||
@@ -315,11 +281,6 @@
|
||||
- Updated NPCEntity pokeball throw positioning to properly account for the baseScale property.
|
||||
- Fixed `[Pokemon].copyFrom` error causing forms, IVs, and EVs to not be applied properly when using `[Pokemon].loadFromJSON` or `[Pokemon].loadFromNBT`
|
||||
- Added new item class, `WearableItem`. Instances of this class should have a corresponding 3D model. These models render when the items display context is `HEAD`.
|
||||
- Added new LearnsetQuery types:
|
||||
- `LEGAL` for moves that are innately compatible and learnable by the Pokémon.
|
||||
- `LEGACY` for moves that were once officially learnable by the Pokémon but aren't due to GameFreak's re-balancing.
|
||||
- `SPECIAL` for moves that are not learnable by the Pokémon but may have appeared in a special event or distribution.
|
||||
|
||||
- Pokemon now have a fireImmune attribute in their behaviour that can be set to true to ignore all fire damage (lava, magma blocks, etc.)
|
||||
`JSON
|
||||
{
|
||||
@@ -332,9 +293,7 @@
|
||||
- Added `Pokemon#hyperTrainIV()` and `IVs#setHyperTrainedIV(Stat, Int)`.
|
||||
- Added `HyperTrainedIvEvent.Pre` and `HyperTrainedIvEvent.Post`.
|
||||
- Added a `hoverText` option to PartySelectCallback, to display a tooltip on hovering over a Pokémon in the selection screen.
|
||||
- `PokemonEntity` instances spawned into the world now appropriately finalize the spawn for mod compatibility.
|
||||
- Added PokedexManager.obtain as a replacement for .catch which is not a friendly function name in Java.
|
||||
|
||||
|
||||
### MoLang & Datapacks
|
||||
- The following usages for item predicates can now use item conditions like advancements do, you can learn about them in the [Minecraft wiki](https://minecraft.wiki/w/Advancement_definition#minecraft:filled_bucket)
|
||||
- The `requiredContext` for an item interaction evolution
|
||||
@@ -352,9 +311,6 @@
|
||||
- Added `pokemon` as an available Molang function for the `battleActor` functions.
|
||||
- Fixed `heldItem` property inside spawn files not working and causing crashes
|
||||
- Fixed `spawn_bedrock_particles` MoLang causing crashes when used in a server environment
|
||||
- The following move sources are now valid for the `moves` array in species data:
|
||||
- `legacy:{move}`
|
||||
- `special:{move}`
|
||||
- The Pokédex form lang key definition now follows `cobblemon.ui.pokedex.info.form.{species}-{formname}` instead of `cobblemon.ui.pokedex.info.form.{formname}`.
|
||||
- Added `play_sound_on_server` as an available Molang function for the `worldHolder` & `player` functions.
|
||||
- Added `run_molang_after` as an available Molang function for the `entity` functions when schedulable.
|
||||
@@ -364,8 +320,6 @@
|
||||
- The format of the `remedies.json` file has changed to allow for individual friendshipDrop amounts per remedy
|
||||
- Fixed `entity.find_nearby_block` causing crashes when attempting to use a block tag
|
||||
- Spawn Filters can now access `v.spawn.class` to get the identifier of an NPC class for when trying to influence NPC spawns
|
||||
- Adds Flows for `STARTER_CHOSEN`, `EV_GAINED`, `POKEMON_RELEASED`, `POKEMON_NICKNAMED`, `HELD_ITEM`, and `TRADE_COMPLETED` events
|
||||
- Adds Pokemon functions for `pokeball`, `held_item` and `remove_held_item`
|
||||
- Added `pokemon.hyper_train_iv` as an available Molang function.
|
||||
|
||||
## [1.6.1 (January 26th, 2025)](#1-6-1)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
plugins {
|
||||
id("cobblemon.root-conventions")
|
||||
id ("net.nemerosa.versioning") version "3.1.0"
|
||||
}
|
||||
|
||||
version = "${project.property("mod_version")}+${project.property("mc_version")}"
|
||||
|
||||
@@ -21,6 +21,7 @@ plugins {
|
||||
|
||||
id("net.kyori.blossom")
|
||||
id("org.jetbrains.gradle.plugin.idea-ext")
|
||||
id("net.nemerosa.versioning") version "3.1.0"
|
||||
}
|
||||
|
||||
architectury {
|
||||
|
||||
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.compat;
|
||||
import com.cobblemon.mod.common.CobblemonEntities;
|
||||
import com.cobblemon.mod.common.client.render.layer.PokemonOnShoulderRenderer;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.item.PokedexItem;
|
||||
import com.cobblemon.mod.common.pokemon.FormData;
|
||||
import com.cobblemon.mod.common.pokemon.lighthing.LightingData;
|
||||
import dev.lambdaurora.lambdynlights.LambDynLights;
|
||||
@@ -37,20 +36,20 @@ public class LambDynamicLightsCompat {
|
||||
public static void hookCompat() {
|
||||
// Pokémon entities
|
||||
DynamicLightHandlers.registerDynamicLightHandler(
|
||||
CobblemonEntities.POKEMON,
|
||||
DynamicLightHandler.makeHandler(
|
||||
LambDynamicLightsCompat::resolvedPokemonLightLevel,
|
||||
pokemon -> false
|
||||
)
|
||||
CobblemonEntities.POKEMON,
|
||||
DynamicLightHandler.makeHandler(
|
||||
LambDynamicLightsCompat::resolvedPokemonLightLevel,
|
||||
pokemon -> false
|
||||
)
|
||||
);
|
||||
|
||||
// Shouldered Pokémon
|
||||
DynamicLightHandlers.registerDynamicLightHandler(
|
||||
EntityType.PLAYER,
|
||||
DynamicLightHandler.makeHandler(
|
||||
LambDynamicLightsCompat::resolvedPlayerLightLevel,
|
||||
player -> false
|
||||
)
|
||||
EntityType.PLAYER,
|
||||
DynamicLightHandler.makeHandler(
|
||||
LambDynamicLightsCompat::resolvedShoulderLightLevel,
|
||||
player -> false
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -64,13 +63,11 @@ public class LambDynamicLightsCompat {
|
||||
return Math.max(itemLightLevel, formLightLevel);
|
||||
}
|
||||
|
||||
private static int resolvedPlayerLightLevel(Player player) {
|
||||
private static int resolvedShoulderLightLevel(Player player) {
|
||||
var underwater = !player.level().getFluidState(BlockPos.containing(player.getX(), player.getEyeY(), player.getZ())).isEmpty();
|
||||
final int leftShoulderLightLevel = extractShoulderLightLevel(PokemonOnShoulderRenderer.shoulderDataFrom(player.getShoulderEntityLeft()), underwater);
|
||||
final int rightShoulderLightLevel = extractShoulderLightLevel(PokemonOnShoulderRenderer.shoulderDataFrom(player.getShoulderEntityRight()), underwater);
|
||||
final int itemLightLevel = customHeldItemLightLevel(player.getMainHandItem(), player.getOffhandItem());
|
||||
|
||||
return Math.max(itemLightLevel, Math.max(leftShoulderLightLevel, rightShoulderLightLevel));
|
||||
final int leftLightLevel = extractShoulderLightLevel(PokemonOnShoulderRenderer.shoulderDataFrom(player.getShoulderEntityLeft()), underwater);
|
||||
final int rightLightLevel = extractShoulderLightLevel(PokemonOnShoulderRenderer.shoulderDataFrom(player.getShoulderEntityRight()), underwater);
|
||||
return Math.max(leftLightLevel, rightLightLevel);
|
||||
}
|
||||
|
||||
private static Optional<Integer> extractFormLightLevel(@NotNull FormData form, boolean underwater) {
|
||||
@@ -86,17 +83,14 @@ public class LambDynamicLightsCompat {
|
||||
}
|
||||
|
||||
ItemStack item = shoulderData.getShownItem();
|
||||
int itemLightLevel = item.isEmpty() ? 0 :LambDynLights.getLuminanceFromItemStack(item, underwater);
|
||||
int itemLightLevel = item.isEmpty()?0:LambDynLights.getLuminanceFromItemStack(item, underwater);
|
||||
int formLightLevel = extractFormLightLevel(shoulderData.getForm(), underwater).orElse(0);
|
||||
|
||||
return Math.max(itemLightLevel, formLightLevel);
|
||||
}
|
||||
|
||||
private static int customHeldItemLightLevel(ItemStack mainhand, ItemStack offhand) {
|
||||
return (mainhand.getItem() instanceof PokedexItem || offhand.getItem() instanceof PokedexItem) ? 13 : 0;
|
||||
}
|
||||
|
||||
private static boolean liquidGlowModeSupport(@NotNull LightingData.LiquidGlowMode liquidGlowMode, boolean underwater) {
|
||||
return underwater ? liquidGlowMode.getGlowsUnderwater() : liquidGlowMode.getGlowsInLand();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,12 +12,14 @@ import com.cobblemon.mod.common.block.SaccharineLeafBlock;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Desc;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
import org.spongepowered.asm.mixin.injection.Slice;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@@ -40,9 +42,8 @@ public abstract class BeeEntityMixin {
|
||||
if (block instanceof SaccharineLeafBlock) {
|
||||
|
||||
int age = blockState.getValue(SaccharineLeafBlock.Companion.getAGE());
|
||||
boolean waterlogged = blockState.getValue(BlockStateProperties.WATERLOGGED);
|
||||
|
||||
if (age < 2 && !waterlogged) {
|
||||
if (age < 2) {
|
||||
this.cobblemon$result = blockState.setValue(SaccharineLeafBlock.Companion.getAGE(), age + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,54 +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.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||
import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
@Mixin(ClientPacketListener.class)
|
||||
public class ClientPacketListenerMixin {
|
||||
|
||||
@Shadow private ClientLevel level;
|
||||
|
||||
@Inject(method = "handleSetEntityPassengersPacket", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/world/entity/Entity;hasIndirectPassenger(Lnet/minecraft/world/entity/Entity;)Z", shift = At.Shift.BEFORE), cancellable = true)
|
||||
private void cobblemon$handlePokemonPassengers(ClientboundSetPassengersPacket packet, CallbackInfo ci) {
|
||||
Entity entity = this.level.getEntity(packet.getVehicle());
|
||||
if (entity instanceof PokemonEntity pokemon) {
|
||||
var passengers = new ArrayList<Entity>();
|
||||
for (int passenger : packet.getPassengers()) {
|
||||
passengers.add(this.level.getEntity(passenger));
|
||||
}
|
||||
Arrays
|
||||
.stream(pokemon.getOccupiedSeats())
|
||||
.filter(x -> !passengers.contains(x))
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(Entity::stopRiding);
|
||||
|
||||
var occupiedSeats = Arrays.asList(pokemon.getOccupiedSeats());
|
||||
passengers.stream()
|
||||
.filter(x -> !occupiedSeats.contains(x))
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(x -> x.startRiding(pokemon, true));
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+11
-22
@@ -9,19 +9,20 @@
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper;
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel;
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState;
|
||||
import com.cobblemon.mod.common.entity.PosableEntity;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderer;
|
||||
import net.minecraft.client.resources.PlayerSkin;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.joml.Vector3f;
|
||||
import org.spongepowered.asm.mixin.Debug;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -29,6 +30,11 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.Map;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
|
||||
import net.minecraft.client.renderer.entity.EntityRenderer;
|
||||
import net.minecraft.client.resources.PlayerSkin;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
|
||||
@Mixin(EntityRenderDispatcher.class)
|
||||
public class EntityRenderDispatcherMixin {
|
||||
@@ -71,23 +77,6 @@ public class EntityRenderDispatcherMixin {
|
||||
0F,
|
||||
1F
|
||||
);
|
||||
|
||||
/*if (locator.contains("middle")){
|
||||
PoseStack.Pose pose = poseStack.last();
|
||||
Vector3f vec = matrix.getMatrix().getRotation(new AxisAngle4f()).transform(new Vector3f(0, 0, -1));
|
||||
buffer.addVertex(pose, pos.toVector3f()).setColor(0xffff00ff).setNormal(pose, vec.x, vec.y, vec.z); //Forward, pink
|
||||
buffer.addVertex(pose, (float)(pos.x() + vec.x), (float)(pos.y() + vec.y), (float)(pos.z() + vec.z)).setColor(0xffff00ff).setNormal(pose, vec.x, vec.y, vec.z);
|
||||
|
||||
vec = matrix.getMatrix().getRotation(new AxisAngle4f()).transform(new Vector3f(0, 1, 0));
|
||||
buffer.addVertex(pose, pos.toVector3f()).setColor(0xffffff00).setNormal(pose, vec.x, vec.y, vec.z); //Up, yellow
|
||||
buffer.addVertex(pose, (float)(pos.x() + vec.x), (float)(pos.y() + vec.y), (float)(pos.z() + vec.z)).setColor(0xffffff00).setNormal(pose, vec.x, vec.y, vec.z);
|
||||
|
||||
vec = matrix.getMatrix().getRotation(new AxisAngle4f()).transform(new Vector3f(-1, 0, 0));
|
||||
buffer.addVertex(pose, pos.toVector3f()).setColor(0xff00ffff).setNormal(pose, vec.x, vec.y, vec.z); //Left, cyan
|
||||
buffer.addVertex(pose, (float)(pos.x() + vec.x), (float)(pos.y() + vec.y), (float)(pos.z() + vec.z)).setColor(0xff00ffff).setNormal(pose, vec.x, vec.y, vec.z);
|
||||
}*/
|
||||
|
||||
|
||||
poseStack.popPose();
|
||||
});
|
||||
|
||||
|
||||
@@ -119,12 +119,14 @@ public abstract class LocalPlayerMixin extends AbstractClientPlayer implements O
|
||||
public HitResult pick(double hitDistance, float partialTicks, boolean hitFluids) {
|
||||
Entity vehicle = this.getVehicle();
|
||||
if (vehicle instanceof PokemonEntity pokemonEntity) {
|
||||
int seatIndex = pokemonEntity.getPassengers().indexOf(this);
|
||||
Seat seat = pokemonEntity.getSeats().get(seatIndex);
|
||||
|
||||
PokemonClientDelegate delegate = (PokemonClientDelegate) pokemonEntity.getDelegate();
|
||||
String locatorName = delegate.getSeatLocator(this);
|
||||
MatrixWrapper locator = delegate.getLocatorStates().get(locatorName);
|
||||
MatrixWrapper locator = delegate.getLocatorStates().get(seat.getLocator());
|
||||
|
||||
if (locator == null) {
|
||||
return super.pick(hitDistance, partialTicks, hitFluids);
|
||||
super.pick(hitDistance, partialTicks, hitFluids);
|
||||
}
|
||||
|
||||
Vec3 locatorOffset = new Vec3(locator.getMatrix().getTranslation(new Vector3f()));
|
||||
@@ -136,7 +138,7 @@ public abstract class LocalPlayerMixin extends AbstractClientPlayer implements O
|
||||
|
||||
if (Minecraft.getInstance().options.getCameraType() == CameraType.FIRST_PERSON) {
|
||||
PosableModel model = VaryingModelRepository.INSTANCE.getPoser(pokemonEntity.getPokemon().getSpecies().getResourceIdentifier(), new FloatingState());
|
||||
offset.add(cobblemon$getFirstPersonOffset(model, locatorName));
|
||||
offset.add(cobblemon$getFirstPersonOffset(model, seat));
|
||||
}
|
||||
|
||||
Matrix3f orientation = controller.isActive() && controller.getOrientation() != null ? controller.getOrientation() : new Matrix3f();
|
||||
@@ -158,11 +160,11 @@ public abstract class LocalPlayerMixin extends AbstractClientPlayer implements O
|
||||
}
|
||||
|
||||
@Unique
|
||||
private static @NotNull Vector3f cobblemon$getFirstPersonOffset(PosableModel model, String locatorName) {
|
||||
private static @NotNull Vector3f cobblemon$getFirstPersonOffset(PosableModel model, Seat seat) {
|
||||
Map<String, Vec3> cameraOffsets = model.getFirstPersonCameraOffset();
|
||||
|
||||
if (cameraOffsets.containsKey(locatorName)) {
|
||||
return cameraOffsets.get(locatorName).toVector3f();
|
||||
if (cameraOffsets.containsKey(seat.getLocator())) {
|
||||
return cameraOffsets.get(seat.getLocator()).toVector3f();
|
||||
} else {
|
||||
return new Vector3f(0f, 0f, 0f);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(MouseHandler.class)
|
||||
public abstract class MouseHandlerMixin {
|
||||
@@ -120,12 +121,11 @@ public abstract class MouseHandlerMixin {
|
||||
if (usageContext.getScanningGuiOpen()) {
|
||||
this.smoothTurnY.reset();
|
||||
this.smoothTurnX.reset();
|
||||
var defaultSensitivity = this.minecraft.options.sensitivity().get() * 0.6 + 0.2;
|
||||
var defaultSensitivity = this.minecraft.options.sensitivity().get() * 0.6000000238418579 + 0.20000000298023224;
|
||||
var spyglassSensitivity = Math.pow(defaultSensitivity, 3);
|
||||
var lookSensitivity = spyglassSensitivity * 8.0;
|
||||
var sensitivity = Mth.lerp(usageContext.getFovMultiplier(), spyglassSensitivity, lookSensitivity);
|
||||
var yRotationFlip = this.minecraft.options.invertYMouse().get() ? -1 : 1;
|
||||
player.turn(this.accumulatedDX * sensitivity, (this.accumulatedDY * sensitivity * yRotationFlip));
|
||||
player.turn(this.accumulatedDX * sensitivity, (this.accumulatedDY * sensitivity));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
-72
@@ -1,72 +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.mixin.client.snapshots;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBuildDetails;
|
||||
import com.cobblemon.mod.common.client.gui.snapshots.SnapshotWarningScreen;
|
||||
import com.cobblemon.mod.common.client.snapshots.SnapshotAcknowledgementData;
|
||||
import com.cobblemon.mod.common.client.snapshots.SnapshotAcknowledgementReader;
|
||||
import kotlin.Unit;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Mixin(Minecraft.class)
|
||||
public final class SnapshotWarningMixin {
|
||||
|
||||
@Unique
|
||||
private final Pattern VERSION = Pattern.compile("^(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)$");
|
||||
|
||||
@Inject(method = "addInitialScreens", at = @At("TAIL"))
|
||||
public void cobblemon$addSnapshotWarningScreen(List<Function<Runnable, Screen>> output, CallbackInfo callback) {
|
||||
if (CobblemonBuildDetails.SNAPSHOT && !this.cobblemon$isAcknowledged() && !SharedConstants.IS_RUNNING_IN_IDE) {
|
||||
output.add((runnable) -> new SnapshotWarningScreen((acknowledgement, dsa) -> {
|
||||
if (acknowledgement == SnapshotWarningScreen.Acknowledgement.NO) {
|
||||
Minecraft.getInstance().stop();
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
|
||||
SnapshotAcknowledgementReader.INSTANCE.write(new SnapshotAcknowledgementData(CobblemonBuildDetails.VERSION, dsa));
|
||||
|
||||
runnable.run();
|
||||
return Unit.INSTANCE;
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Unique
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
private boolean cobblemon$isAcknowledged() {
|
||||
SnapshotAcknowledgementData data = SnapshotAcknowledgementReader.INSTANCE.read();
|
||||
if (data == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Matcher current = VERSION.matcher(CobblemonBuildDetails.VERSION);
|
||||
current.find();
|
||||
|
||||
Matcher when = VERSION.matcher(data.getVersion());
|
||||
when.find();
|
||||
|
||||
boolean alert = current.group("minor").compareTo(when.group("minor")) > 0 || current.group("major").compareTo(when.group("major")) > 0;
|
||||
return !alert && data.getDontShowAgain();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -297,6 +297,9 @@ object Cobblemon {
|
||||
SpeciesFeatures.types["flag"] = FlagSpeciesFeatureProvider::class.java
|
||||
SpeciesFeatures.types["integer"] = IntSpeciesFeatureProvider::class.java
|
||||
|
||||
SpeciesFeatures.register(
|
||||
DataKeys.CAN_BE_MILKED,
|
||||
FlagSpeciesFeatureProvider(keys = listOf(DataKeys.CAN_BE_MILKED), default = true))
|
||||
SpeciesFeatures.register(
|
||||
DataKeys.HAS_BEEN_SHEARED,
|
||||
FlagSpeciesFeatureProvider(keys = listOf(DataKeys.HAS_BEEN_SHEARED), default = false))
|
||||
|
||||
@@ -18,7 +18,6 @@ object CobblemonActivities {
|
||||
val POKEMON_SLEEPING_ACTIVITY = register(Activity("pokemon_sleeping"))
|
||||
val POKEMON_GROW_CROP = register(Activity("pokemon_grow_crop"))
|
||||
val POKEMON_SLEEP_ON_TRAINER_BED = register(Activity("pokemon_sleep_on_trainer_bed"))
|
||||
val POKEMON_HERD = register(Activity("pokemon_herd"))
|
||||
|
||||
fun register(activity: Activity): Activity {
|
||||
activities.add(activity)
|
||||
|
||||
@@ -25,8 +25,6 @@ import com.cobblemon.mod.common.util.adapters.ExpressionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionOrEntityVariableAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.MemoryModuleTypeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.SensorTypeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.TaskConfigAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.TranslatedTextAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
@@ -41,8 +39,6 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.server.packs.resources.ResourceManager
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
object CobblemonBehaviours : JsonDataRegistry<CobblemonBehaviour> {
|
||||
@@ -51,8 +47,6 @@ object CobblemonBehaviours : JsonDataRegistry<CobblemonBehaviour> {
|
||||
.registerTypeAdapter(Activity::class.java, ActivityAdapter)
|
||||
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(MemoryModuleType::class.java, MemoryModuleTypeAdapter)
|
||||
.registerTypeAdapter(SensorType::class.java, SensorTypeAdapter)
|
||||
.registerTypeAdapter(BehaviourConfig::class.java, BehaviourConfigAdapter)
|
||||
.registerTypeAdapter(TaskConfig::class.java, TaskConfigAdapter)
|
||||
.registerTypeAdapter(
|
||||
|
||||
@@ -97,6 +97,18 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
|
||||
val CAMPFIRE: BlockEntityType<CampfireBlockEntity> = this.create("campfire_pot",
|
||||
BlockEntityType.Builder.of(::CampfireBlockEntity, CobblemonBlocks.CAMPFIRE).build(null)
|
||||
)
|
||||
@JvmField
|
||||
val COPPER_OVEN: BlockEntityType<CopperOvenBlockEntity> = this.create("copper_oven",
|
||||
BlockEntityType.Builder.of(::CopperOvenBlockEntity, CobblemonBlocks.COPPER_OVEN).build(null)
|
||||
)
|
||||
@JvmField
|
||||
val COPPER_WASHER: BlockEntityType<CopperWasherBlockEntity> = this.create("copper_washer",
|
||||
BlockEntityType.Builder.of(::CopperWasherBlockEntity, CobblemonBlocks.COPPER_WASHER).build(null)
|
||||
)
|
||||
@JvmField
|
||||
val COPPER_FRIDGE: BlockEntityType<CopperFridgeBlockEntity> = this.create("copper_fridge",
|
||||
BlockEntityType.Builder.of(::CopperFridgeBlockEntity, CobblemonBlocks.COPPER_FRIDGE).build(null)
|
||||
)
|
||||
|
||||
/*@JvmField
|
||||
val LURE_CAKE: BlockEntityType<LureCakeBlockEntity> =
|
||||
|
||||
@@ -176,7 +176,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val SACCHARINE_LOG = this.create("saccharine_log", SaccharineLogBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F).sound(SoundType.WOOD).ignitedByLava()))
|
||||
@JvmField
|
||||
val SACCHARINE_LOG_SLATHERED = this.create("saccharine_log_slathered", SaccharineLogSlatheredBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F).sound(SoundType.WOOD).ignitedByLava()))
|
||||
val SACCHARINE_HONEY_LOG = this.create("saccharine_honey_log", SaccharineHoneyLogBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F).sound(SoundType.WOOD).ignitedByLava()))
|
||||
|
||||
@JvmField
|
||||
val STRIPPED_SACCHARINE_LOG = this.create("stripped_saccharine_log", RotatedPillarBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_LIGHT_BLUE).instrument(NoteBlockInstrument.BASS).strength(2.0F).sound(SoundType.WOOD).ignitedByLava())) //log("stripped_saccharine_log")
|
||||
@@ -205,7 +205,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
val SACCHARINE_FENCE = this.create("saccharine_fence", FenceBlock(BlockBehaviour.Properties.of().mapColor(SACCHARINE_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
|
||||
@JvmField
|
||||
val SACCHARINE_FENCE_GATE = this.create("saccharine_fence_gate", FenceGateBlock(SACCHARINE_WOOD_TYPE, BlockBehaviour.Properties.of().mapColor(SACCHARINE_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).strength(2.0f, 3.0f).sound(SoundType.WOOD)))
|
||||
@JvmField
|
||||
|
||||
val SACCHARINE_BUTTON = this.create("saccharine_button", BlocksInvoker.createWoodenButtonBlock(BlockSetType.OAK))
|
||||
@JvmField
|
||||
val SACCHARINE_PRESSURE_PLATE = this.create("saccharine_pressure_plate", PressurePlateBlockInvoker.`cobblemon$create`(SACCHARINE_BLOCK_SET_TYPE, BlockBehaviour.Properties.of().mapColor(SACCHARINE_PLANKS.defaultMapColor()).instrument(NoteBlockInstrument.BASS).noCollission().strength(0.5f).sound(SoundType.WOOD)))
|
||||
@@ -474,29 +474,40 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
val GIMMIGHOUL_CHEST = create("gimmighoul_chest", GildedChestBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.CHEST).noOcclusion().sound(CobblemonSounds.GILDED_CHEST_SOUNDS), GildedChestBlock.Type.FAKE))
|
||||
|
||||
@JvmField
|
||||
val MONITOR = create("monitor", MonitorBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).lightLevel { if (it.getValue(MonitorBlock.SCREEN) != MonitorBlock.MonitorScreen.OFF) 13 else 0 }))
|
||||
val MONITOR = create("monitor", MonitorBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).lightLevel { if (it.getValue(MonitorBlock.SCREEN) != MonitorBlock.MonitorScreen.OFF) 15 else 0 }))
|
||||
@JvmField
|
||||
val FOSSIL_ANALYZER = create("fossil_analyzer", FossilAnalyzerBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).noOcclusion()))
|
||||
@JvmField
|
||||
val RESTORATION_TANK = create("restoration_tank", RestorationTankBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.GLASS).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(5.0F, 6.0F).noOcclusion()))
|
||||
|
||||
@JvmField
|
||||
val HEALING_MACHINE = create("healing_machine", HealingMachineBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2f).noOcclusion().lightLevel { if (it.getValue(HealingMachineBlock.CHARGE_LEVEL) >= HealingMachineBlock.MAX_CHARGE_LEVEL) 12 else 5 }))
|
||||
val HEALING_MACHINE = create("healing_machine", HealingMachineBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2f).noOcclusion().lightLevel { if (it.getValue(HealingMachineBlock.CHARGE_LEVEL) >= HealingMachineBlock.MAX_CHARGE_LEVEL) 7 else 2 }))
|
||||
|
||||
@JvmField
|
||||
val PC = create("pc", PCBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F).noOcclusion().lightLevel { if ((it.getValue(PCBlock.ON) as Boolean) && (it.getValue(PCBlock.PART) == PCBlock.PCPart.TOP)) 13 else 0 }))
|
||||
val PC = create("pc", PCBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F).noOcclusion().lightLevel { if ((it.getValue(PCBlock.ON) as Boolean) && (it.getValue(PCBlock.PART) == PCBlock.PCPart.TOP)) 10 else 0 }))
|
||||
|
||||
@JvmField
|
||||
val LECTERN = create("lectern", LecternBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).sound(SoundType.WOOD).strength(2.5F).ignitedByLava().lightLevel { if (it.getValue(LecternBlock.EMIT_LIGHT) as Boolean) 13 else 0 }))
|
||||
val LECTERN = create("lectern", LecternBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).sound(SoundType.WOOD).strength(2.5F).ignitedByLava()))
|
||||
|
||||
@JvmField
|
||||
val DISPLAY_CASE = create("display_case", DisplayCaseBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.DISPLAY_CASE_SOUNDS).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.STONE).strength(0.3F).requiresCorrectToolForDrops()))
|
||||
val DISPLAY_CASE = create("display_case", DisplayCaseBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.DISPLAY_CASE_SOUNDS).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.STONE).strength(0.3F)))
|
||||
|
||||
@JvmField
|
||||
val COPPER_FAN = create("copper_fan", CopperFanBlock(BlockBehaviour.Properties.of().pushReaction(PushReaction.DESTROY).mapColor(MapColor.COLOR_ORANGE).requiresCorrectToolForDrops().strength(3.0F, 6.0F).sound(SoundType.COPPER)))
|
||||
@JvmField
|
||||
val COPPER_MOWER = create("copper_mower", CopperMowerBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_ORANGE).requiresCorrectToolForDrops().strength(3.0F, 6.0F).sound(SoundType.COPPER)))
|
||||
@JvmField
|
||||
val COPPER_OVEN = create("copper_oven", CopperOvenBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_ORANGE).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(3.0F, 6.0F).sound(SoundType.COPPER)))
|
||||
@JvmField
|
||||
val COPPER_WASHER = this.create("copper_washer", CopperWasherBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_ORANGE).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(3.0F, 6.0F).sound(SoundType.COPPER)))
|
||||
@JvmField
|
||||
val COPPER_FRIDGE = this.create("copper_fridge", CopperFridgeBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_ORANGE).pushReaction(PushReaction.BLOCK).requiresCorrectToolForDrops().strength(3.0F, 6.0F).sound(SoundType.COPPER)))
|
||||
|
||||
@JvmField
|
||||
val INCENSE_SWEET = create("incense_sweet", SweetIncenseBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.DISPLAY_CASE_SOUNDS).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.STONE).strength(0.3f)))
|
||||
|
||||
@JvmField
|
||||
val PASTURE = create("pasture", PastureBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BROWN).sound(SoundType.WOOD).strength(2F).noOcclusion().pushReaction(PushReaction.BLOCK).lightLevel { if ((it.getValue(PastureBlock.ON) as Boolean) && (it.getValue(PastureBlock.PART) == PastureBlock.PasturePart.TOP)) 13 else 0 }))
|
||||
val PASTURE = create("pasture", PastureBlock(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BROWN).sound(SoundType.WOOD).strength(2F).noOcclusion().pushReaction(PushReaction.BLOCK).lightLevel { if ((it.getValue(PastureBlock.ON) as Boolean) && (it.getValue(PastureBlock.PART) == PastureBlock.PasturePart.TOP)) 10 else 0 }))
|
||||
|
||||
val RED_MINT = create("red_mint", MintBlock(MintType.RED, BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_RED).noCollission().randomTicks().instabreak().sound(CobblemonSounds.MINT_SOUNDS).pushReaction(PushReaction.DESTROY)))
|
||||
@JvmField
|
||||
@@ -519,9 +530,6 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val HEARTY_GRAINS = this.create("hearty_grains", HeartyGrainsBlock(BlockBehaviour.Properties.of().pushReaction(PushReaction.DESTROY).ignitedByLava().mapColor(MapColor.PLANT).noCollission().randomTicks().instabreak().sound(CobblemonSounds.VIVICHOKE_SOUNDS)))
|
||||
|
||||
@JvmField
|
||||
val GALARICA_NUT_BUSH = this.create("galarica_nut_bush", NutBushBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).randomTicks().noCollission().sound(SoundType.SWEET_BERRY_BUSH).pushReaction(PushReaction.DESTROY)))
|
||||
|
||||
@JvmField
|
||||
val POTTED_RED_APRICORN_SAPLING = this.create("potted_red_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(RED_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
@@ -542,9 +550,9 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val HEARTY_GRAIN_BALE = this.create("hearty_grain_bale", BaleBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).instrument(NoteBlockInstrument.BANJO).strength(0.5F).sound(SoundType.GRASS)))
|
||||
@JvmField
|
||||
val TATAMI_BLOCK = this.create("tatami_block", HorizontalRotationalBlock(BlockBehaviour.Properties.of().ignitedByLava().mapColor(MapColor.PLANT).strength(0.1F).sound(SoundType.MOSS_CARPET)))
|
||||
val TATAMI_BLOCK = this.create("tatami_block", HorizontalRotationalBlock(BlockBehaviour.Properties.of().ignitedByLava().mapColor(MapColor.PLANT).sound(SoundType.GRASS)))
|
||||
@JvmField
|
||||
val TATAMI_MAT = this.create("tatami_mat", HorizontalRotationCarpetBlock(BlockBehaviour.Properties.of().ignitedByLava().mapColor(MapColor.PLANT).strength(0.1F).sound(SoundType.MOSS_CARPET)))
|
||||
val TATAMI_MAT = this.create("tatami_mat", HorizontalRotationCarpetBlock(BlockBehaviour.Properties.of().ignitedByLava().mapColor(MapColor.PLANT).sound(SoundType.GRASS)))
|
||||
|
||||
/**
|
||||
* Returns a map of all the blocks that can be stripped with an axe in the format of input - output.
|
||||
@@ -556,9 +564,11 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
APRICORN_LOG to STRIPPED_APRICORN_LOG,
|
||||
SACCHARINE_WOOD to STRIPPED_SACCHARINE_WOOD,
|
||||
SACCHARINE_LOG to STRIPPED_SACCHARINE_LOG,
|
||||
SACCHARINE_LOG_SLATHERED to STRIPPED_SACCHARINE_LOG
|
||||
SACCHARINE_HONEY_LOG to STRIPPED_SACCHARINE_LOG
|
||||
)
|
||||
|
||||
|
||||
|
||||
private fun apricornBlock(name: String, apricorn: Apricorn): ApricornBlock = this.create(name, ApricornBlock(BlockBehaviour.Properties.of().mapColor(apricorn.mapColor()).randomTicks().strength(Blocks.OAK_LOG.defaultDestroyTime(), Blocks.OAK_LOG.explosionResistance).sound(SoundType.WOOD).noOcclusion(), apricorn))
|
||||
|
||||
private fun tumblestoneBlock(name: String, stage: Int, height: Int, xzOffset: Int, nextStage: Block?) : Block {
|
||||
@@ -658,19 +668,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
Triple(APRICORN_FENCE, 5, 20),
|
||||
Triple(APRICORN_FENCE_GATE, 5, 20),
|
||||
Triple(APRICORN_SLAB, 5, 20),
|
||||
Triple(APRICORN_STAIRS, 5, 20),
|
||||
Triple(SACCHARINE_LOG, 5, 5),
|
||||
Triple(SACCHARINE_LOG_SLATHERED, 5, 5),
|
||||
Triple(STRIPPED_SACCHARINE_LOG, 5, 5),
|
||||
Triple(SACCHARINE_WOOD, 5, 5),
|
||||
Triple(STRIPPED_SACCHARINE_WOOD, 5, 5),
|
||||
Triple(SACCHARINE_PLANKS, 5, 20),
|
||||
Triple(SACCHARINE_LEAVES, 30, 60),
|
||||
Triple(SACCHARINE_FENCE, 5, 20),
|
||||
Triple(SACCHARINE_FENCE_GATE, 5, 20),
|
||||
Triple(SACCHARINE_SLAB, 5, 20),
|
||||
Triple(SACCHARINE_STAIRS, 5, 20)
|
||||
|
||||
Triple(APRICORN_STAIRS, 5, 20)
|
||||
).onEach{ data -> setFlammable(data.first, data.second, data.third) }
|
||||
}
|
||||
|
||||
|
||||
@@ -217,10 +217,10 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
val TATAMI_MAT = blockItem("tatami_mat", CobblemonBlocks.TATAMI_MAT)
|
||||
|
||||
@JvmField
|
||||
val VIVICHOKE = compostableItem("vivichoke", CobblemonItem(Item.Properties()), 0.80f)
|
||||
val VIVICHOKE = compostableItem("vivichoke")
|
||||
|
||||
@JvmField
|
||||
val VIVICHOKE_SEEDS = compostableItem("vivichoke_seeds", VivichokeItem(CobblemonBlocks.VIVICHOKE_SEEDS), 0.30f)
|
||||
val VIVICHOKE_SEEDS = compostableItem("vivichoke_seeds", VivichokeItem(CobblemonBlocks.VIVICHOKE_SEEDS))
|
||||
|
||||
@JvmField
|
||||
val RED_APRICORN = apricornItem("red", ApricornItem(CobblemonBlocks.RED_APRICORN))
|
||||
@@ -263,7 +263,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val APRICORN_PLANKS = blockItem("apricorn_planks", CobblemonBlocks.APRICORN_PLANKS)
|
||||
@JvmField
|
||||
val APRICORN_LEAVES = compostableBlockItem("apricorn_leaves", CobblemonBlocks.APRICORN_LEAVES, 0.30f)
|
||||
val APRICORN_LEAVES = compostableBlockItem("apricorn_leaves", CobblemonBlocks.APRICORN_LEAVES)
|
||||
@JvmField
|
||||
val APRICORN_BOAT = create("apricorn_boat", CobblemonBoatItem(CobblemonBoatType.APRICORN, false, Item.Properties().stacksTo(1)))
|
||||
@JvmField
|
||||
@@ -310,7 +310,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val SACCHARINE_LOG = blockItem("saccharine_log", CobblemonBlocks.SACCHARINE_LOG)
|
||||
@JvmField
|
||||
val SACCHARINE_LOG_SLATHERED = blockItem("saccharine_log_slathered", CobblemonBlocks.SACCHARINE_LOG_SLATHERED)
|
||||
val SACCHARINE_HONEY_LOG = blockItem("saccharine_honey_log", CobblemonBlocks.SACCHARINE_HONEY_LOG)
|
||||
@JvmField
|
||||
val STRIPPED_SACCHARINE_LOG = blockItem("stripped_saccharine_log", CobblemonBlocks.STRIPPED_SACCHARINE_LOG)
|
||||
@JvmField
|
||||
@@ -320,7 +320,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val SACCHARINE_PLANKS = blockItem("saccharine_planks", CobblemonBlocks.SACCHARINE_PLANKS)
|
||||
@JvmField
|
||||
val SACCHARINE_LEAVES = compostableBlockItem("saccharine_leaves", CobblemonBlocks.SACCHARINE_LEAVES, 0.35f)
|
||||
val SACCHARINE_LEAVES = compostableBlockItem("saccharine_leaves", CobblemonBlocks.SACCHARINE_LEAVES)
|
||||
@JvmField
|
||||
val SACCHARINE_BOAT = create("saccharine_boat", CobblemonBoatItem(CobblemonBoatType.SACCHARINE, false, Item.Properties().stacksTo(1)))
|
||||
@JvmField
|
||||
@@ -347,7 +347,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val SACCHARINE_HANGING_SIGN = this.create("saccharine_hanging_sign", HangingSignItem(CobblemonBlocks.SACCHARINE_HANGING_SIGN, CobblemonBlocks.SACCHARINE_WALL_HANGING_SIGN, Item.Properties().stacksTo(16)))
|
||||
@JvmField
|
||||
val SACCHARINE_SAPLING = compostableBlockItem("saccharine_sapling", CobblemonBlocks.SACCHARINE_SAPLING, 0.30f)
|
||||
val SACCHARINE_SAPLING = compostableBlockItem("saccharine_sapling", CobblemonBlocks.SACCHARINE_SAPLING)
|
||||
|
||||
@JvmField
|
||||
val BUGWORT = compostableBlockItem("bugwort", CobblemonBlocks.BUGWORT)
|
||||
@@ -483,6 +483,17 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val INCENSE_SWEET = blockItem("incense_sweet", CobblemonBlocks.INCENSE_SWEET)
|
||||
|
||||
@JvmField
|
||||
val COPPER_FAN = blockItem("copper_fan", CobblemonBlocks.COPPER_FAN)
|
||||
@JvmField
|
||||
val COPPER_MOWER = blockItem("copper_mower", CobblemonBlocks.COPPER_MOWER)
|
||||
@JvmField
|
||||
val COPPER_OVEN = blockItem("copper_oven", CobblemonBlocks.COPPER_OVEN)
|
||||
@JvmField
|
||||
val COPPER_WASHER = blockItem("copper_washer", CobblemonBlocks.COPPER_WASHER)
|
||||
@JvmField
|
||||
val COPPER_FRIDGE = blockItem("copper_fridge", CobblemonBlocks.COPPER_FRIDGE)
|
||||
|
||||
|
||||
// Evolution items
|
||||
@JvmField val LINK_CABLE = create("link_cable", LinkCableItem())
|
||||
@@ -511,9 +522,9 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField val CRACKED_POT = noSettingsItem("cracked_pot")
|
||||
@JvmField val MASTERPIECE_TEACUP = noSettingsItem("masterpiece_teacup")
|
||||
@JvmField val UNREMARKABLE_TEACUP = noSettingsItem("unremarkable_teacup")
|
||||
@JvmField val SWEET_APPLE = compostableItem("sweet_apple", foodItem(4, 0.3f), 0.65f)
|
||||
@JvmField val TART_APPLE = compostableItem("tart_apple", foodItem(4, 0.3f), 0.65f)
|
||||
@JvmField val SYRUPY_APPLE = compostableItem("syrupy_apple", foodItem(4, 0.3f), 0.65f)
|
||||
@JvmField val SWEET_APPLE = create("sweet_apple", foodItem(4, 0.3f))
|
||||
@JvmField val TART_APPLE = create("tart_apple", foodItem(4, 0.3f))
|
||||
@JvmField val SYRUPY_APPLE = create("syrupy_apple", foodItem(4, 0.3f))
|
||||
@JvmField val GALARICA_CUFF = noSettingsItem("galarica_cuff")
|
||||
@JvmField val GALARICA_WREATH = noSettingsItem("galarica_wreath")
|
||||
@JvmField val BLACK_AUGURITE = noSettingsItem("black_augurite")
|
||||
@@ -602,7 +613,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField val BERRY_JUICE = this.create("berry_juice", BerryJuiceItem())
|
||||
|
||||
@JvmField
|
||||
val GALARICA_NUTS = compostableItemNameBlockItem("galarica_nuts", CobblemonBlocks.GALARICA_NUT_BUSH)
|
||||
val GALARICA_NUTS = create("galarica_nuts", GalaricaNutItem())
|
||||
|
||||
// Hyper Training Items
|
||||
val hyperTrainingItems = mutableListOf<HyperTrainingItem>()
|
||||
@@ -685,9 +696,9 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val MEDICINAL_LEEK = heldItem("medicinal_leek", MedicinalLeekItem(CobblemonBlocks.MEDICINAL_LEEK, Item.Properties().food(FoodProperties.Builder().fast().nutrition(1).saturationModifier(0.2f).build())), "leek")
|
||||
@JvmField
|
||||
val ROASTED_LEEK = compostableItem("roasted_leek", CobblemonItem(Item.Properties().food(FoodProperties.Builder().fast().nutrition(3).saturationModifier(0.3f).build())), 0.85f)
|
||||
val ROASTED_LEEK = create("roasted_leek", CobblemonItem(Item.Properties().food(FoodProperties.Builder().fast().nutrition(3).saturationModifier(0.3f).build())))
|
||||
@JvmField
|
||||
val BRAISED_VIVICHOKE = compostableItem("braised_vivichoke", foodItem(6, 0.6F), 0.85f)
|
||||
val BRAISED_VIVICHOKE = create("braised_vivichoke", foodItem(6, 0.6F))
|
||||
@JvmField
|
||||
val VIVICHOKE_DIP = create("vivichoke_dip", object : CobblemonItem(Properties().stacksTo(1)
|
||||
.food(FoodProperties.Builder()
|
||||
@@ -703,7 +714,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
}
|
||||
})
|
||||
@JvmField
|
||||
val ENERGY_ROOT = compostableItem("energy_root", EnergyRootItem(CobblemonBlocks.ENERGY_ROOT, Item.Properties().food(FoodProperties.Builder().nutrition(1).fast().saturationModifier(0.2f).build())), 0.60f)
|
||||
val ENERGY_ROOT = compostableItem("energy_root", EnergyRootItem(CobblemonBlocks.ENERGY_ROOT, Item.Properties().food(FoodProperties.Builder().nutrition(1).fast().saturationModifier(0.2f).build())))
|
||||
@JvmField
|
||||
val REVIVAL_HERB = compostableItem("revival_herb", RevivalHerbItem(CobblemonBlocks.REVIVAL_HERB))
|
||||
@JvmField
|
||||
@@ -711,11 +722,11 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val MEDICINAL_BREW = noSettingsItem("medicinal_brew")
|
||||
@JvmField
|
||||
val REMEDY = compostableItem("remedy", RemedyItem(RemedyItem.NORMAL), 0.65f)
|
||||
val REMEDY = create("remedy", RemedyItem(RemedyItem.NORMAL))
|
||||
@JvmField
|
||||
val FINE_REMEDY = compostableItem("fine_remedy", RemedyItem(RemedyItem.FINE), 0.75f)
|
||||
val FINE_REMEDY = create("fine_remedy", RemedyItem(RemedyItem.FINE))
|
||||
@JvmField
|
||||
val SUPERB_REMEDY = compostableItem("superb_remedy", RemedyItem(RemedyItem.SUPERB), 0.85f)
|
||||
val SUPERB_REMEDY = create("superb_remedy", RemedyItem(RemedyItem.SUPERB))
|
||||
@JvmField
|
||||
val MOOMOO_MILK = noSettingsItem("moomoo_milk")
|
||||
|
||||
@@ -935,7 +946,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val ASSAULT_VEST = heldItem("assault_vest")
|
||||
@JvmField
|
||||
val BIG_ROOT = compostableBlockItem("big_root", CobblemonBlocks.BIG_ROOT, 0.40f)
|
||||
val BIG_ROOT = blockItem("big_root", CobblemonBlocks.BIG_ROOT)
|
||||
@JvmField
|
||||
val BINDING_BAND = heldItem("binding_band")
|
||||
@JvmField
|
||||
@@ -993,7 +1004,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val LAGGING_TAIL = heldItem("lagging_tail")
|
||||
@JvmField
|
||||
val LEFTOVERS = compostableHeldItem("leftovers", null, 0.50f)
|
||||
val LEFTOVERS = heldItem("leftovers")
|
||||
@JvmField
|
||||
val LIFE_ORB = heldItem("life_orb")
|
||||
@JvmField
|
||||
@@ -1480,8 +1491,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
|
||||
private fun blockItem(name: String, block: Block, rarity: Rarity = Rarity.COMMON): BlockItem = this.create(name, BlockItem(block, Item.Properties().rarity(rarity)))
|
||||
|
||||
private fun itemNameBlockItem(name: String, block: Block, rarity: Rarity = Rarity.COMMON): ItemNameBlockItem = this.create(name, ItemNameBlockItem(block, Item.Properties().rarity(rarity)))
|
||||
|
||||
private fun noSettingsItem(name: String): CobblemonItem = this.create(name, CobblemonItem(Item.Properties()))
|
||||
|
||||
private fun itemWithRarity(name: String, rarity: Rarity): CobblemonItem = this.create(name, CobblemonItem(Item.Properties().rarity(rarity)))
|
||||
@@ -1610,7 +1619,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
private fun mintItem(name: String, mintItem: MintItem): MintItem {
|
||||
val item = this.create(name, mintItem)
|
||||
mints[item.nature.displayName] = item
|
||||
compostable(item, .95f)
|
||||
compostable(item, .65f)
|
||||
return item
|
||||
}
|
||||
|
||||
@@ -1630,7 +1639,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
private fun apricornSeedItem(name: String, apricornSeedItem: ApricornSeedItem): ApricornSeedItem {
|
||||
val finalName = "${name}_apricorn_seed"
|
||||
val item = this.create(finalName, apricornSeedItem)
|
||||
compostable(item, .30f)
|
||||
compostable(item, .65f)
|
||||
return item
|
||||
}
|
||||
|
||||
@@ -1638,14 +1647,14 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
private fun mintSeed(name: String, mintBlock: MintBlock): Item {
|
||||
val finalName = "${name}_mint_seeds"
|
||||
val item = this.blockItem(finalName, mintBlock)
|
||||
compostable(item, .30f)
|
||||
compostable(item, .65f)
|
||||
return item
|
||||
}
|
||||
|
||||
private fun mintLeaf(name: String, mintLeafItem: MintLeafItem): MintLeafItem {
|
||||
val finalName = "${name}_mint_leaf"
|
||||
val item = this.create(finalName, mintLeafItem)
|
||||
compostable(item, .50f)
|
||||
compostable(item, .65f)
|
||||
return item
|
||||
}
|
||||
|
||||
@@ -1661,18 +1670,12 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
return createdItem
|
||||
}
|
||||
|
||||
private fun compostableBlockItem(name: String, block: Block, increaseLevelChance: Float = .85f): Item {
|
||||
private fun compostableBlockItem(name: String, block: Block, increaseLevelChance: Float = .65f): Item {
|
||||
val createdItem = this.blockItem(name, block)
|
||||
compostable(createdItem, increaseLevelChance)
|
||||
return createdItem
|
||||
}
|
||||
|
||||
private fun compostableItemNameBlockItem(name: String, block: Block, increaseLevelChance: Float = .30f): Item {
|
||||
val createdItem = this.itemNameBlockItem(name, block)
|
||||
compostable(createdItem, increaseLevelChance)
|
||||
return createdItem
|
||||
}
|
||||
|
||||
private fun foodItem(nutrition: Int, saturationModifier: Float): Item {
|
||||
return CobblemonItem(Item.Properties().food(FoodProperties.Builder().nutrition(nutrition).saturationModifier(saturationModifier).build()))
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.CobblemonAttackTargetData
|
||||
import com.cobblemon.mod.common.api.dialogue.ActiveDialogue
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.mojang.serialization.Codec
|
||||
@@ -43,11 +42,6 @@ object CobblemonMemories {
|
||||
val NEAREST_VISIBLE_ATTACKER = register<LivingEntity>("nearest_visible_attacker")
|
||||
val NEARBY_GROWABLE_CROPS = register<BlockPos>("nearby_growable_crops")
|
||||
val RECENTLY_ATE_GRASS = register<Boolean>("recently_ate_grass")
|
||||
/** who am i following rn? */
|
||||
val HERD_LEADER = register<String>("herd_leader", PrimitiveCodec.STRING)
|
||||
/** how many are following me rn? */
|
||||
val HERD_SIZE = register<Int>("herd_size") // Don't bother saving it, we'll try to keep count roughly.
|
||||
val ATTACK_TARGET_DATA = register<CobblemonAttackTargetData>("attack_target_data") // This is used to store additional information about the attack target, such as when to give up pursuit.
|
||||
|
||||
fun <U> register(id: String, codec: Codec<U>): MemoryModuleType<U> {
|
||||
val memoryModule = MemoryModuleType(Optional.of(codec))
|
||||
|
||||
@@ -36,7 +36,6 @@ import com.cobblemon.mod.common.client.net.pasture.ClosePastureHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.OpenPastureHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.PokemonPasturedHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.PokemonUnpasturedHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.UpdatePastureConflictFlagHandler
|
||||
import com.cobblemon.mod.common.client.net.pokedex.ServerConfirmedRegisterHandler
|
||||
import com.cobblemon.mod.common.client.net.pokemon.update.ClientboundUpdateRidingStateHandler
|
||||
import com.cobblemon.mod.common.client.net.pokemon.update.PokemonUpdatePacketHandler
|
||||
@@ -86,7 +85,6 @@ import com.cobblemon.mod.common.net.messages.client.pasture.ClosePasturePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.OpenPasturePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonPasturedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonUnpasturedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.UpdatePastureConflictFlagPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokedex.ServerConfirmedRegisterPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.*
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.AddEvolutionPacket
|
||||
@@ -142,7 +140,6 @@ import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamRequestPack
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamResponsePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.behaviour.DamageOnCollisionPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.behaviour.SetEntityBehaviourPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.block.AdjustBlockEntityViewerCountPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectCancelledPacket
|
||||
@@ -158,7 +155,6 @@ import com.cobblemon.mod.common.net.messages.server.dialogue.InputToDialoguePack
|
||||
import com.cobblemon.mod.common.net.messages.server.npc.SaveNPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.orientation.ServerboundUpdateOrientationPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.PasturePokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.SetPastureConflictPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.UnpastureAllPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.FinishScanningPacket
|
||||
@@ -170,7 +166,6 @@ import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetActiveMark
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetMarkingsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.ServerboundUpdateRidingStatePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.evolution.AcceptEvolutionPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.riding.DismountPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.starter.RequestStarterScreenPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.SwapPCPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokemonPacket
|
||||
@@ -192,7 +187,6 @@ import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamLeaveHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestResponseHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.behaviour.DamageOnCollisionPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.behaviour.SetEntityBehaviourHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.block.AdjustBlockEntityViewerCountHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectCancelledHandler
|
||||
@@ -209,7 +203,6 @@ import com.cobblemon.mod.common.net.serverhandling.evolution.AcceptEvolutionHand
|
||||
import com.cobblemon.mod.common.net.serverhandling.npc.SaveNPCHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.orientation.OrientationPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.PasturePokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.SetPastureConflictHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpastureAllPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpasturePokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.FinishScanningHandler
|
||||
@@ -220,7 +213,6 @@ import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetNicknameHan
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetActiveMarkHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetMarkingsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.ServerboundUpdateRidingStateHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.riding.DismountPokemonPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.starter.RequestStarterScreenHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.starter.SelectStarterPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.BenchMoveHandler
|
||||
@@ -426,7 +418,6 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(ClosePasturePacket.ID, ClosePasturePacket::decode, ClosePastureHandler))
|
||||
list.add(PacketRegisterInfo(PokemonPasturedPacket.ID, PokemonPasturedPacket::decode, PokemonPasturedHandler))
|
||||
list.add(PacketRegisterInfo(PokemonUnpasturedPacket.ID, PokemonUnpasturedPacket::decode, PokemonUnpasturedHandler))
|
||||
list.add(PacketRegisterInfo(UpdatePastureConflictFlagPacket.ID, UpdatePastureConflictFlagPacket::decode, UpdatePastureConflictFlagHandler))
|
||||
|
||||
// Orientation
|
||||
list.add(PacketRegisterInfo(ClientboundUpdateOrientationPacket.ID, ClientboundUpdateOrientationPacket::decode, S2CUpdateOrientationHandler))
|
||||
@@ -537,8 +528,6 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(PasturePokemonPacket.ID, PasturePokemonPacket::decode, PasturePokemonHandler))
|
||||
list.add(PacketRegisterInfo(UnpasturePokemonPacket.ID, UnpasturePokemonPacket::decode, UnpasturePokemonHandler))
|
||||
list.add(PacketRegisterInfo(UnpastureAllPokemonPacket.ID, UnpastureAllPokemonPacket::decode, UnpastureAllPokemonHandler))
|
||||
list.add(PacketRegisterInfo(SetPastureConflictPacket.ID, SetPastureConflictPacket::decode, SetPastureConflictHandler))
|
||||
|
||||
|
||||
// Block entity
|
||||
list.add(PacketRegisterInfo(AdjustBlockEntityViewerCountPacket.ID, AdjustBlockEntityViewerCountPacket::decode, AdjustBlockEntityViewerCountHandler))
|
||||
@@ -567,14 +556,12 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(ServerboundUpdateRidingStatePacket.ID, ServerboundUpdateRidingStatePacket::decode, ServerboundUpdateRidingStateHandler))
|
||||
list.add(PacketRegisterInfo(ServerboundUpdateRidingStatsPacket.ID, ServerboundUpdateRidingStatsPacket::decode, ServerboundUpdateRidingStatsHandler))
|
||||
list.add(PacketRegisterInfo(ServerboundUpdateRidingStatRangePacket.ID, ServerboundUpdateRidingStatRangePacket::decode, ServerboundUpdateRidingStatRangeHandler))
|
||||
list.add(PacketRegisterInfo(DismountPokemonPacket.ID, DismountPokemonPacket::decode, DismountPokemonPacketHandler))
|
||||
|
||||
// Cooking
|
||||
list.add(PacketRegisterInfo(ToggleCookingPotLidPacket.ID, ToggleCookingPotLidPacket::decode, ToggleCookingPotLidHandler))
|
||||
|
||||
// Behaviour Packets
|
||||
list.add(PacketRegisterInfo(SetEntityBehaviourPacket.ID, SetEntityBehaviourPacket::decode, SetEntityBehaviourHandler))
|
||||
list.add(PacketRegisterInfo(DamageOnCollisionPacket.ID, DamageOnCollisionPacket::decode, DamageOnCollisionPacketHandler))
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
@@ -24,18 +24,23 @@ object CobblemonPoiTypes: PlatformRegistry<Registry<PoiType>, ResourceKey<Regist
|
||||
override val resourceKey: ResourceKey<Registry<PoiType>> = Registries.POINT_OF_INTEREST_TYPE
|
||||
|
||||
@JvmField
|
||||
val NURSE_KEY = createKey("nurse", CobblemonBlocks.HEALING_MACHINE, 1, 1)
|
||||
val NURSE_KEY: ResourceKey<PoiType> = createKey("nurse")
|
||||
@JvmField
|
||||
val LURE_CAKE_KEY = createKey("lure_cake", CobblemonBlocks.LURE_CAKE, 0, 1)
|
||||
val NURSE = create(NURSE_KEY.location().path, PoiType(getBlockStates(CobblemonBlocks.HEALING_MACHINE), 1, 1))
|
||||
@JvmField
|
||||
val SACCHARINE_LOG_SLATHERED_KEY = createKey("saccharine_log_slathered", CobblemonBlocks.SACCHARINE_LOG_SLATHERED, 0, 1)
|
||||
val LURE_CAKE_KEY: ResourceKey<PoiType> = createKey("lure_cake")
|
||||
@JvmField
|
||||
val INCENSE_SWEET_KEY = createKey("incense_sweet", CobblemonBlocks.INCENSE_SWEET, 0, 1)
|
||||
val LURE_CAKE = create(LURE_CAKE_KEY.location().path, PoiType(getBlockStates(CobblemonBlocks.LURE_CAKE), 0, 1))
|
||||
@JvmField
|
||||
val SACCHARINE_HONEY_LOG_KEY: ResourceKey<PoiType> = createKey("saccharine_honey_log")
|
||||
@JvmField
|
||||
val SACCHARINE_HONEY_LOG = create(SACCHARINE_HONEY_LOG_KEY.location().path, PoiType(getBlockStates(CobblemonBlocks.SACCHARINE_HONEY_LOG), 0, 1))
|
||||
@JvmField
|
||||
val INCENSE_SWEET_KEY: ResourceKey<PoiType> = createKey("incense_sweet")
|
||||
@JvmField
|
||||
val INCENSE_SWEET = create(INCENSE_SWEET_KEY.location().path, PoiType(getBlockStates(CobblemonBlocks.INCENSE_SWEET), 0, 1))
|
||||
|
||||
private fun createKey(string: String, block: Block, maxTickets: Int, validRange: Int ): ResourceKey<PoiType> =
|
||||
ResourceKey.create(Registries.POINT_OF_INTEREST_TYPE, cobblemonResource(string)).also { resourceKey ->
|
||||
create(resourceKey.location().path, PoiType(getBlockStates(block), maxTickets, validRange))
|
||||
}
|
||||
private fun createKey(string: String): ResourceKey<PoiType> = ResourceKey.create(Registries.POINT_OF_INTEREST_TYPE, cobblemonResource(string))
|
||||
|
||||
private fun getBlockStates(block: Block): Set<BlockState> = ImmutableSet.copyOf(block.stateDefinition.possibleStates)
|
||||
}
|
||||
}
|
||||
+2
-26
@@ -10,11 +10,8 @@ package com.cobblemon.mod.common.api.ai
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.config.BehaviourConfig
|
||||
import com.cobblemon.mod.common.entity.MoLangScriptingEntity
|
||||
import com.mojang.serialization.Dynamic
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
import net.minecraft.world.entity.schedule.Schedule
|
||||
|
||||
@@ -25,30 +22,13 @@ class BehaviourConfigurationContext {
|
||||
var coreActivities = setOf(Activity.CORE)
|
||||
val activities = mutableListOf<ActivityConfigurationContext>()
|
||||
val schedule = Schedule.EMPTY
|
||||
val memories = mutableSetOf<MemoryModuleType<*>>()
|
||||
val sensors = mutableSetOf<SensorType<*>>()
|
||||
|
||||
fun getOrCreateActivity(activity: Activity): ActivityConfigurationContext {
|
||||
return activities.firstOrNull { it.activity == activity } ?: ActivityConfigurationContext(activity).also(activities::add)
|
||||
}
|
||||
|
||||
fun addMemories(vararg memory: MemoryModuleType<*>) {
|
||||
memories.addAll(memory)
|
||||
}
|
||||
|
||||
fun addMemories(memories: Collection<MemoryModuleType<*>>) {
|
||||
this.memories.addAll(memories)
|
||||
}
|
||||
|
||||
fun addSensors(vararg sensor: SensorType<*>) {
|
||||
sensors.addAll(sensor)
|
||||
}
|
||||
|
||||
fun addSensors(sensors: Collection<SensorType<*>>) {
|
||||
this.sensors.addAll(sensors)
|
||||
}
|
||||
|
||||
fun apply(entity: LivingEntity, behaviourConfigs: List<BehaviourConfig>, dynamic: Dynamic<*>) {
|
||||
fun apply(entity: LivingEntity, behaviourConfigs: List<BehaviourConfig>) {
|
||||
val brain = entity.brain
|
||||
|
||||
if (entity is MoLangScriptingEntity) {
|
||||
entity.registerVariables(behaviourConfigs.flatMap { it.getVariables(entity) })
|
||||
@@ -58,11 +38,7 @@ class BehaviourConfigurationContext {
|
||||
// Setup the brain config
|
||||
behaviourConfigs.forEach { it.configure(entity, this) }
|
||||
|
||||
var brain = entity.brain
|
||||
// Apply the brain config
|
||||
if (entity is MoLangScriptingEntity) {
|
||||
brain = entity.assignNewBrainWithMemoriesAndSensors(dynamic, memories, sensors)
|
||||
}
|
||||
activities.forEach { it.apply(entity) }
|
||||
brain.setCoreActivities(coreActivities)
|
||||
brain.setDefaultActivity(defaultActivity)
|
||||
|
||||
@@ -1,34 +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.ai
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
|
||||
/**
|
||||
* This is used in the AI system to store optional additional information about the attack target,
|
||||
* mainly things like when to give up pursuit, what sort of attacks are permitted, whatever. It's
|
||||
* a temporary memory, same as ATTACK_TARGET, so relogs will clear it and that's why it has no codec.
|
||||
*
|
||||
* To help you get a sense of a use case, imagine a Pidgeotto has an AI task that says it should hunt
|
||||
* Magikarp that are close to the surface. Once they've found one and chosen them as the attack target,
|
||||
* they should give up the target if the Magikarp goes too deep, but if it's attacking an entity because
|
||||
* they attacked its owner, it shouldn't give up on the target for that reason. To address this, when
|
||||
* hunting Magikarp, the Pidgeotto will set this memory to a CobblemonAttackTargetData with some
|
||||
* [Expression] that encourages the entity to give up the target if the Magikarp goes too deep.
|
||||
*
|
||||
* To make this work, any transition from the FIGHT activity will erase this memory.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since June 23rd, 2025
|
||||
*/
|
||||
class CobblemonAttackTargetData(
|
||||
/** An expression that returns false when the target is no longer worth attacking. */
|
||||
val shouldContinue: Expression = "true".asExpression()
|
||||
)
|
||||
@@ -15,11 +15,6 @@ import kotlin.jvm.optionals.getOrNull
|
||||
|
||||
typealias ExpressionOrEntityVariable = Either<Expression, MoLangConfigVariable>
|
||||
|
||||
/**
|
||||
* In the case of [ExpressionOrEntityVariable] the right side is the only one that requires visibility for a user,
|
||||
* this function is a shorthand for finding all of the values in the list that have something to show the user to
|
||||
* potentially edit.
|
||||
*/
|
||||
fun List<ExpressionOrEntityVariable>.asVariables() = mapNotNull { it.right().getOrNull() }
|
||||
|
||||
|
||||
|
||||
@@ -12,20 +12,7 @@ import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
/**
|
||||
* A wrapper for [BehaviorControl] that allows it to be used with any [LivingEntity]. If the class the task was
|
||||
* actually intended for is not the same as the entity being passed in, the task will just not run. This is just
|
||||
* a trick to allow type safety.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 19th, 2024
|
||||
*/
|
||||
class WrapperLivingEntityTask<T : LivingEntity>(val task: BehaviorControl<T>, val clazz: Class<T>) : BehaviorControl<LivingEntity> {
|
||||
companion object {
|
||||
inline fun <reified E : LivingEntity> BehaviorControl<E>.wrapped(): BehaviorControl<LivingEntity> {
|
||||
return WrapperLivingEntityTask(this, E::class.java)
|
||||
}
|
||||
}
|
||||
override fun tryStart(level: ServerLevel, entity: LivingEntity, gameTime: Long): Boolean {
|
||||
if (clazz.isInstance(entity)) {
|
||||
return task.tryStart(level, entity as T, gameTime)
|
||||
|
||||
-37
@@ -1,37 +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.ai.config
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
/**
|
||||
* Does nothing except conditionally add some memories and sensors to the brain of the entity.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since June 27th, 2025
|
||||
*/
|
||||
class AddMemoriesAndSensorsConfig : BehaviourConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val memories: Set<MemoryModuleType<*>> = emptySet()
|
||||
val sensors: Set<SensorType<*>> = mutableSetOf()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition).asVariables()
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (!checkCondition(entity, condition)) return
|
||||
behaviourConfigurationContext.addMemories(memories)
|
||||
behaviourConfigurationContext.addSensors(sensors)
|
||||
}
|
||||
}
|
||||
@@ -23,8 +23,8 @@ class AddTasksToActivity : BehaviourConfig {
|
||||
val activities = mutableListOf<Activity>()
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val tasksByPriority = mutableMapOf<Int, List<TaskConfig>>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = tasksByPriority.values.flatten().flatMap { it.getVariables(entity) } + listOf(condition).asVariables()
|
||||
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (!checkCondition(entity, condition)) return
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ class ApplyBehaviours : BehaviourConfig {
|
||||
var condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
@SerializedName("behaviours", alternate = ["behaviors"])
|
||||
val behaviours = mutableListOf<ResourceLocation>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return if (checkCondition(entity, condition)) {
|
||||
behaviours.flatMap {
|
||||
|
||||
@@ -44,7 +44,6 @@ interface BehaviourConfig {
|
||||
cobblemonResource("set_core_activities") to SetCoreActivities::class.java,
|
||||
cobblemonResource("add_variables") to AddVariablesConfig::class.java,
|
||||
cobblemonResource("set_variables") to SetVariablesConfig::class.java,
|
||||
cobblemonResource("add_memories_and_sensors") to AddMemoriesAndSensorsConfig::class.java,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+4
-10
@@ -21,25 +21,19 @@ import com.cobblemon.mod.common.util.resolve
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class CustomScriptBehaviourConfig : BehaviourConfig {
|
||||
var condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val variables: List<MoLangConfigVariable> = emptyList()
|
||||
val script: ExpressionLike = "0".asExpressionLike()
|
||||
|
||||
companion object {
|
||||
val runtime = MoLangRuntime().setup()
|
||||
}
|
||||
|
||||
var condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val variables: List<MoLangConfigVariable> = emptyList()
|
||||
val script: ExpressionLike = "0".asExpressionLike()
|
||||
val memories = emptySet<MemoryModuleType<*>>()
|
||||
val sensors = emptySet<SensorType<*>>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = variables
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (!checkCondition(entity, condition)) return
|
||||
behaviourConfigurationContext.addMemories(memories)
|
||||
behaviourConfigurationContext.addSensors(sensors)
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
runtime.resolve(script)
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ Example:
|
||||
```json
|
||||
{
|
||||
"type": "set_variables",
|
||||
"variableValues": {
|
||||
"variables": {
|
||||
"aggressive": true,
|
||||
"attack_range": "10"
|
||||
}
|
||||
|
||||
+6
-15
@@ -14,7 +14,6 @@ import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.ai.ActivityConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addStandardFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
@@ -22,42 +21,34 @@ import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
|
||||
import com.cobblemon.mod.common.util.activityRegistry
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import com.mojang.datafixers.util.Pair
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class ScriptBehaviourConfig : BehaviourConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val condition = "true".asExpressionLike()
|
||||
val script = cobblemonResource("dummy")
|
||||
val variables = mutableListOf<MoLangConfigVariable>()
|
||||
val memories = emptySet<MemoryModuleType<*>>()
|
||||
val sensors = emptySet<SensorType<*>>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = variables
|
||||
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (!checkCondition(entity, condition)) return
|
||||
override fun configure(entity: LivingEntity, context: BehaviourConfigurationContext) {
|
||||
val runtime = MoLangRuntime().setup()
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!runtime.resolveBoolean(condition)) return
|
||||
|
||||
val struct = createBrainStruct(entity, behaviourConfigurationContext)
|
||||
val struct = createBrainStruct(entity, context)
|
||||
val script = CobblemonScripts.scripts[this.script]
|
||||
?: run {
|
||||
Cobblemon.LOGGER.error("Tried loading script $script as part of an entity brain but that script does not exist")
|
||||
return
|
||||
}
|
||||
|
||||
behaviourConfigurationContext.addMemories(memories)
|
||||
behaviourConfigurationContext.addSensors(sensors)
|
||||
|
||||
runtime.resolve(script, mapOf("brain" to struct))
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
class SetDefaultActivity : BehaviourConfig {
|
||||
val activity: Activity = Activity.IDLE
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
behaviourConfigurationContext.defaultActivity = activity
|
||||
|
||||
@@ -23,6 +23,7 @@ class SetVariablesConfig : BehaviourConfig {
|
||||
var variableValues = mutableMapOf<String, ExpressionLike>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
val runtime = MoLangRuntime().setup()
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
|
||||
+2
-6
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
@@ -48,15 +47,13 @@ class AirWanderTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.WALK_TARGET, MemoryModuleType.LOOK_TARGET, CobblemonMemories.PATH_COOLDOWN)
|
||||
val wanderChanceExpression = wanderChance.asSimplifiedExpression(entity)
|
||||
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(MemoryModuleType.WALK_TARGET),
|
||||
it.registered(MemoryModuleType.LOOK_TARGET),
|
||||
it.absent(CobblemonMemories.PATH_COOLDOWN)
|
||||
).apply(it) { walkTarget, lookTarget, pathCooldown ->
|
||||
it.registered(MemoryModuleType.LOOK_TARGET)
|
||||
).apply(it) { walkTarget, lookTarget ->
|
||||
Trigger { world, entity, time ->
|
||||
if (entity !is PathfinderMob || entity.isInWater) {
|
||||
return@Trigger false
|
||||
@@ -67,7 +64,6 @@ class AirWanderTaskConfig : SingleTaskConfig {
|
||||
if (wanderChance <= 0 || world.random.nextFloat() > wanderChance) return@Trigger false
|
||||
|
||||
val rotVec = entity.getViewVector(0F)
|
||||
pathCooldown.setWithExpiry(true, 60L)
|
||||
val target = HoverRandomPos.getPos(entity, horizontalRange.resolveInt(), verticalRange.resolveInt(), rotVec.x, rotVec.y, 1.5707964f, minUpwardsMovement.resolveInt(), minDownwardsMovement.resolveInt())
|
||||
?: return@Trigger false
|
||||
walkTarget.set(WalkTarget(target, speedMultiplier.resolveFloat(), 3))
|
||||
|
||||
+9
-2
@@ -10,7 +10,9 @@ package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
@@ -21,14 +23,19 @@ class AllOfTaskConfig : TaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val tasks: List<TaskConfig> = emptyList()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = tasks.flatMap { it.getVariables(entity) }
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return if (checkCondition(entity, condition))
|
||||
tasks.flatMap { it.getVariables(entity) } + listOf(condition).asVariables()
|
||||
else
|
||||
listOf(condition).asVariables()
|
||||
}
|
||||
|
||||
override fun createTasks(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): List<BehaviorControl<in LivingEntity>> {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return emptyList()
|
||||
|
||||
return tasks.flatMap { it.createTasks(entity, behaviourConfigurationContext) }
|
||||
}
|
||||
}
|
||||
+8
-5
@@ -8,21 +8,24 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.entity.ai.AttackAngryAtTask
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class AttackAngryAtTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
val condition = booleanVariable(SharedEntityVariables.ATTACKING_CATEGORY, "should_attack_angry_at", true).asExpressible()
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition).asVariables()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.ANGRY_AT, MemoryModuleType.ATTACK_TARGET, CobblemonMemories.POKEMON_SLEEPING)
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
return AttackAngryAtTask.create()
|
||||
}
|
||||
}
|
||||
-33
@@ -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.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.AttackHostileMobsTask
|
||||
import com.mojang.serialization.Codec
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class AttackHostileMobsTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return emptyList<MoLangConfigVariable>()
|
||||
}
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
brainConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
return AttackHostileMobsTask.create()
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CODEC: Codec<AttackHostileMobsTaskConfig> = Codec.unit(AttackHostileMobsTaskConfig())
|
||||
}
|
||||
}
|
||||
+10
-5
@@ -8,16 +8,22 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.npc.ai.MeleeAttackTask
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.ManageFlightInBattleTask
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.BattleFlightTask
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
class ManageFlightInBattleTaskConfig : SingleTaskConfig {
|
||||
class BattleFlightTaskConfig : SingleTaskConfig {
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
@@ -25,7 +31,6 @@ class ManageFlightInBattleTaskConfig : SingleTaskConfig {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.POKEMON_BATTLE)
|
||||
return ManageFlightInBattleTask.create()
|
||||
return BattleFlightTask.create()
|
||||
}
|
||||
}
|
||||
+1
-10
@@ -12,31 +12,22 @@ import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.VillagerCalmDown
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class CalmDownTaskConfig : SingleTaskConfig {
|
||||
var condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition).asVariables()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.HURT_BY,
|
||||
MemoryModuleType.HURT_BY_ENTITY,
|
||||
MemoryModuleType.NEAREST_HOSTILE,
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.VILLAGER_HOSTILES)
|
||||
return VillagerCalmDown.create()
|
||||
}
|
||||
}
|
||||
-79
@@ -1,79 +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.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
/**
|
||||
* Checks nearby entities and counts how many have nominated this entity as their leader.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since June 17th, 2025
|
||||
*/
|
||||
class CountFollowersTaskConfig : SingleTaskConfig {
|
||||
val checkTicks: ExpressionOrEntityVariable = Either.left("10".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf(checkTicks).asVariables()
|
||||
}
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val checkTicksValue = checkTicks.resolveInt()
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
|
||||
CobblemonMemories.HERD_SIZE,
|
||||
CobblemonMemories.HERD_LEADER
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
return BehaviorBuilder.create { instance ->
|
||||
instance.group(
|
||||
instance.present(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES),
|
||||
instance.registered(CobblemonMemories.HERD_SIZE)
|
||||
).apply(instance) { nearbyEntities, herdCount ->
|
||||
Trigger { world, entity, _ ->
|
||||
if (world.gameTime % checkTicksValue != 0L) {
|
||||
return@Trigger false
|
||||
}
|
||||
val myUUID = entity.uuid.toString()
|
||||
val followersCount = instance.get(nearbyEntities).findAll {
|
||||
it is PokemonEntity
|
||||
&& it.brain.hasMemoryValue(CobblemonMemories.HERD_LEADER)
|
||||
&& it.brain.getMemory(CobblemonMemories.HERD_LEADER).getOrNull() == myUUID
|
||||
}.count()
|
||||
if (followersCount == 0) {
|
||||
herdCount.erase()
|
||||
} else {
|
||||
herdCount.set(followersCount)
|
||||
}
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -23,7 +23,7 @@ class DoNothingTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val minDurationTicks: ExpressionOrEntityVariable = Either.left("40".asExpression())
|
||||
val maxDurationTicks: ExpressionOrEntityVariable = Either.left("80".asExpression())
|
||||
override fun getVariables(entity: LivingEntity) = listOf(minDurationTicks, maxDurationTicks).asVariables()
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition, minDurationTicks, maxDurationTicks).asVariables()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
|
||||
-4
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
@@ -17,7 +16,6 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.EatGrassTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class EatGrassTaskConfig : SingleTaskConfig {
|
||||
companion object {
|
||||
@@ -49,8 +47,6 @@ class EatGrassTaskConfig : SingleTaskConfig {
|
||||
return null
|
||||
}
|
||||
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.WALK_TARGET, CobblemonMemories.RECENTLY_ATE_GRASS)
|
||||
|
||||
return WrapperLivingEntityTask(
|
||||
EatGrassTask(
|
||||
chance,
|
||||
|
||||
+1
-13
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.CobblemonSensors
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
@@ -22,7 +21,6 @@ import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class ExitBattleWhenHurtTaskConfig : SingleTaskConfig {
|
||||
var condition = booleanVariable(SharedEntityVariables.BATTLING_CATEGORY, "exit_battle_when_hurt", true).asExpressible()
|
||||
@@ -38,19 +36,10 @@ class ExitBattleWhenHurtTaskConfig : SingleTaskConfig {
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val includePassiveDamage = includePassiveDamage.resolveBoolean()
|
||||
if (!condition.resolveBoolean()) return null
|
||||
|
||||
val includePassiveDamage = includePassiveDamage.resolveBoolean()
|
||||
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.HURT_BY,
|
||||
MemoryModuleType.HURT_BY_ENTITY
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.HURT_BY)
|
||||
|
||||
if (entity is NPCEntity) {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.NPC_BATTLING)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.NPC_BATTLING)
|
||||
fun cancelNPCBattles(npcEntity: NPCEntity): Boolean {
|
||||
val battles = npcEntity.battleIds.mapNotNull(BattleRegistry::getBattle)
|
||||
battles.forEach { it.end() }
|
||||
@@ -69,7 +58,6 @@ class ExitBattleWhenHurtTaskConfig : SingleTaskConfig {
|
||||
}
|
||||
}
|
||||
} else if (entity is PokemonEntity) {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.POKEMON_BATTLE)
|
||||
fun cancelPokemonBattle(pokemonEntity: PokemonEntity): Boolean {
|
||||
val battle = BattleRegistry.getBattle(pokemonEntity.battleId ?: return false)
|
||||
battle?.end()
|
||||
|
||||
-4
@@ -43,10 +43,6 @@ class FindAirTaskConfig : SingleTaskConfig {
|
||||
if (entity !is PathfinderMob) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
CobblemonMemories.PATH_COOLDOWN
|
||||
)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(MemoryModuleType.WALK_TARGET),
|
||||
|
||||
-127
@@ -1,127 +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.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.ai.ToleratedHerdLeader
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class FindHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
companion object {
|
||||
/**
|
||||
* Logic used to choose the best herd leader from nearby visible entities.
|
||||
*
|
||||
* - Higher tier leaders are always preferred.
|
||||
* - Same-tier leaders that are closer are preferred except for when they're the same tier as the current leader.
|
||||
* - We don't want to exceed the target's herd size limit.
|
||||
* - We don't want to choose a leader that is themselves following a leader.
|
||||
* - Some leader definitions allow lower-level Pokémon to lead them.
|
||||
* - Leaders just have to not be in a party - pastured and wild Pokémon can mingle.
|
||||
*/
|
||||
fun getBestHerdLeader(
|
||||
currentLeader: Pair<PokemonEntity, ToleratedHerdLeader>?,
|
||||
nearbyEntities: NearestVisibleLivingEntities,
|
||||
entity: PokemonEntity
|
||||
): PokemonEntity? {
|
||||
var bestLeader: PokemonEntity? = null
|
||||
val (currentLeaderEntity, currentLeaderDefinition) = currentLeader ?: Pair(null, null)
|
||||
var bestTier = currentLeaderDefinition?.tier?.let { it + 1 } ?: 0 // Only upgrade to a higher tier leader
|
||||
var bestDistance = Float.MAX_VALUE
|
||||
nearbyEntities.findAll {
|
||||
it is PokemonEntity &&
|
||||
it != currentLeader &&
|
||||
it.pokemon.storeCoordinates.get()?.store !is PartyStore &&
|
||||
it.getHerdSize() < it.behaviour.herd.maxSize
|
||||
}.forEach { possibleLeader ->
|
||||
possibleLeader as PokemonEntity
|
||||
val matchingHerdLeader = entity.behaviour.herd.bestMatchLeader(entity, possibleLeader) ?: return@forEach
|
||||
val alreadyIsALeader = possibleLeader.brain.hasMemoryValue(CobblemonMemories.HERD_SIZE)
|
||||
val nestedHerdTier = currentLeaderEntity?.getHerdTier() ?: 0
|
||||
if (nestedHerdTier >= matchingHerdLeader.tier) {
|
||||
return@forEach // This leader is following a leader of a higher tier, we can't replace them
|
||||
}
|
||||
val distance = entity.distanceTo(possibleLeader)
|
||||
if (matchingHerdLeader.tier < bestTier) {
|
||||
return@forEach // No need to check further if this leader is worse than the best found so far
|
||||
} else if ((distance > bestDistance && !alreadyIsALeader) && matchingHerdLeader.tier == bestTier) {
|
||||
return@forEach // No need to check further if this leader is farther than the best found so far, unless they are already a leader - I'd prefer to join a pack
|
||||
} else {
|
||||
bestLeader = possibleLeader
|
||||
bestDistance = distance
|
||||
bestTier = matchingHerdLeader.tier
|
||||
}
|
||||
}
|
||||
return bestLeader ?: currentLeaderEntity
|
||||
}
|
||||
}
|
||||
|
||||
// How frequently to check for whether it should herd. Probably isn't that expensive but might use this for chance.
|
||||
val checkTicks: ExpressionOrEntityVariable = Either.left("60".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf(checkTicks).asVariables()
|
||||
}
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
|
||||
CobblemonMemories.HERD_LEADER,
|
||||
MemoryModuleType.WALK_TARGET
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val checkTicksValue = checkTicks.resolveInt()
|
||||
return BehaviorBuilder.create { instance ->
|
||||
instance.group(
|
||||
instance.present(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES),
|
||||
instance.absent(CobblemonMemories.HERD_LEADER)
|
||||
).apply(instance) { nearbyEntities, herdLeader ->
|
||||
Trigger { world, entity, _ ->
|
||||
if (world.gameTime % checkTicksValue != 0L) {
|
||||
return@Trigger false
|
||||
}
|
||||
|
||||
entity as PokemonEntity
|
||||
val bestLeader = getBestHerdLeader(
|
||||
currentLeader = null,
|
||||
nearbyEntities = instance.get(nearbyEntities),
|
||||
entity = entity
|
||||
) ?: return@Trigger false
|
||||
|
||||
herdLeader.set(bestLeader.uuid.toString())
|
||||
bestLeader.brain.eraseMemory(CobblemonMemories.HERD_LEADER)
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-10
@@ -8,8 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.CobblemonSensors
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
@@ -20,7 +18,6 @@ import com.cobblemon.mod.common.util.asExpression
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class FindRestingPlaceTaskConfig : SingleTaskConfig {
|
||||
val horizontalSearchDistance: ExpressionOrEntityVariable = Either.left("16".asExpression())
|
||||
@@ -31,13 +28,6 @@ class FindRestingPlaceTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
behaviourConfigurationContext.addMemories(
|
||||
CobblemonMemories.PATH_COOLDOWN,
|
||||
CobblemonMemories.POKEMON_DROWSY,
|
||||
MemoryModuleType.WALK_TARGET
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.POKEMON_DROWSY)
|
||||
|
||||
return WrapperLivingEntityTask(
|
||||
FindRestingPlaceTask.create(horizontalSearchDistance.resolveInt(), verticalSearchDistance.resolveInt()),
|
||||
PokemonEntity::class.java
|
||||
|
||||
-5
@@ -20,7 +20,6 @@ import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.SetWalkTargetAwayFrom
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class FleeAttackerTaskConfig : SingleTaskConfig {
|
||||
var condition = booleanVariable(SharedEntityVariables.FEAR_CATEGORY, "flee_attacker", true).asExpressible()
|
||||
@@ -39,10 +38,6 @@ class FleeAttackerTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean() || entity !is PathfinderMob) return null
|
||||
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.HURT_BY_ENTITY, MemoryModuleType.WALK_TARGET)
|
||||
behaviourConfigurationContext.addSensors(SensorType.HURT_BY)
|
||||
|
||||
val speedMultiplier = speedMultiplier.resolveFloat()
|
||||
val desiredDistance = desiredDistance.resolveInt()
|
||||
return WrapperLivingEntityTask(
|
||||
|
||||
-3
@@ -20,7 +20,6 @@ import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.SetWalkTargetAwayFrom
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class FleeNearestHostileTaskConfig : SingleTaskConfig {
|
||||
var condition = booleanVariable(SharedEntityVariables.FEAR_CATEGORY, "flee_nearest_hostile", true).asExpressible()
|
||||
@@ -35,8 +34,6 @@ class FleeNearestHostileTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean() || entity !is PathfinderMob) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.NEAREST_HOSTILE, MemoryModuleType.WALK_TARGET)
|
||||
behaviourConfigurationContext.addSensors(SensorType.VILLAGER_HOSTILES)
|
||||
val speedMultiplier = speedMultiplier.resolveFloat()
|
||||
val desiredDistance = desiredDistance.resolveInt()
|
||||
return WrapperLivingEntityTask(
|
||||
|
||||
-71
@@ -1,71 +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.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask.Companion.wrapped
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.ai.config.task.WanderTaskConfig.Companion.WANDER
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.ai.CircleAroundTask
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class FlyInCirclesTaskConfig : SingleTaskConfig {
|
||||
val poseTypes: Set<PoseType> = setOf(
|
||||
PoseType.FLY,
|
||||
PoseType.HOVER
|
||||
)
|
||||
|
||||
val minAngularVelocityDegrees = numberVariable(WANDER, "min_fly_circling_angular_velocity", 0.0).asExpressible()
|
||||
val maxAngularVelocityDegrees = numberVariable(WANDER, "max_fly_circling_angular_velocity", 1.0).asExpressible()
|
||||
val speed = numberVariable(WANDER, "fly_circling_speed", 0.6).asExpressible()
|
||||
val verticalSpeed: ExpressionOrEntityVariable = Either.left("0.0".asExpression())
|
||||
val minDurationTicks: ExpressionOrEntityVariable = Either.left("60".asExpression())
|
||||
val maxDurationTicks: ExpressionOrEntityVariable = Either.left("180".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf(
|
||||
minAngularVelocityDegrees,
|
||||
maxAngularVelocityDegrees,
|
||||
speed,
|
||||
verticalSpeed,
|
||||
minDurationTicks,
|
||||
maxDurationTicks
|
||||
).asVariables()
|
||||
}
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.WALK_TARGET, MemoryModuleType.PATH)
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
return CircleAroundTask(
|
||||
poseTypes = poseTypes,
|
||||
minTurnAngleDegrees = minAngularVelocityDegrees.resolveFloat(),
|
||||
maxTurnAngleDegrees = maxAngularVelocityDegrees.resolveFloat(),
|
||||
speed = speed.resolveFloat(),
|
||||
verticalSpeed = verticalSpeed.resolveFloat(),
|
||||
minDurationTicks = minDurationTicks.resolveFloat().toInt(),
|
||||
maxDurationTicks = maxDurationTicks.resolveFloat().toInt()
|
||||
).wrapped<PokemonEntity>()
|
||||
}
|
||||
}
|
||||
-37
@@ -1,37 +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.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask.Companion.wrapped
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.ai.FollowHerdLeaderTask
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class FollowHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf()
|
||||
}
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.HERD_LEADER, MemoryModuleType.WALK_TARGET)
|
||||
return FollowHerdLeaderTask().wrapped<PokemonEntity>()
|
||||
}
|
||||
}
|
||||
-2
@@ -20,7 +20,6 @@ import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class FollowWalkTargetTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
@@ -31,7 +30,6 @@ class FollowWalkTargetTaskConfig : SingleTaskConfig {
|
||||
|
||||
override fun createTask(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): BehaviorControl<LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.WALK_TARGET, MemoryModuleType.PATH, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)
|
||||
return WrapperLivingEntityTask(
|
||||
FollowWalkTargetTask(minRunTicks.resolveInt(), maxRunTicks.resolveInt()),
|
||||
PathfinderMob::class.java
|
||||
|
||||
-7
@@ -16,8 +16,6 @@ import com.cobblemon.mod.common.entity.ai.GetAngryAtAttackerTask
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class GetAngryAtAttackerTaskConfig : SingleTaskConfig {
|
||||
companion object {
|
||||
@@ -34,11 +32,6 @@ class GetAngryAtAttackerTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.HURT_BY_ENTITY,
|
||||
MemoryModuleType.ANGRY_AT,
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.HURT_BY)
|
||||
return GetAngryAtAttackerTask.create()
|
||||
}
|
||||
}
|
||||
+1
-10
@@ -8,8 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.CobblemonSensors
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
@@ -20,8 +18,6 @@ import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class GoToHealingMachineTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(SELF_HEALING, USE_HEALING_MACHINES, true).asExpressible()
|
||||
@@ -43,12 +39,7 @@ class GoToHealingMachineTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
MemoryModuleType.LOOK_TARGET,
|
||||
CobblemonMemories.NPC_BATTLING
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.NPC_BATTLING)
|
||||
|
||||
return GoToHealingMachineTask.create(
|
||||
horizontalSearchRange = horizontalSearchRange.asExpression(),
|
||||
verticalSearchRange = verticalSearchRange.asExpression(),
|
||||
|
||||
+3
-9
@@ -12,7 +12,6 @@ import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.OmniPathingEntity
|
||||
import com.cobblemon.mod.common.util.closestPosition
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.floor
|
||||
@@ -44,10 +43,7 @@ class GoToLandTaskConfig : SingleTaskConfig {
|
||||
if (entity !is PathfinderMob) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
CobblemonMemories.PATH_COOLDOWN
|
||||
)
|
||||
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(MemoryModuleType.WALK_TARGET),
|
||||
@@ -60,8 +56,6 @@ class GoToLandTaskConfig : SingleTaskConfig {
|
||||
|
||||
entity as PathfinderMob
|
||||
|
||||
val walkSpeedValue = walkSpeed.resolveFloat()
|
||||
|
||||
val iterable = BlockPos.betweenClosed(
|
||||
Mth.floor(entity.x - 8.0),
|
||||
entity.blockY,
|
||||
@@ -77,7 +71,7 @@ class GoToLandTaskConfig : SingleTaskConfig {
|
||||
isSafeLandPosAround(entity.level() as ServerLevel, it, entity)
|
||||
} ?: return@Trigger false
|
||||
|
||||
walkTarget.set(WalkTarget(blockPos.above(), walkSpeedValue, 0))
|
||||
walkTarget.set(WalkTarget(blockPos.above(), 0.35F, 1))
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
@@ -88,7 +82,7 @@ class GoToLandTaskConfig : SingleTaskConfig {
|
||||
val blockState = world.getBlockState(pos)
|
||||
|
||||
val isFluid = world.getFluidState(pos.above()).isEmpty.not()
|
||||
val solidBelow = blockState.isSolid || (mob is OmniPathingEntity && mob.canFly())
|
||||
val solidBelow = blockState.isSolid
|
||||
|
||||
if (isFluid || !solidBelow) {
|
||||
return false
|
||||
|
||||
-12
@@ -8,8 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.CobblemonSensors
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
@@ -17,7 +15,6 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.GoToSleepTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class GoToSleepTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
@@ -25,15 +22,6 @@ class GoToSleepTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
CobblemonMemories.POKEMON_DROWSY,
|
||||
CobblemonMemories.POKEMON_SLEEPING
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.POKEMON_DROWSY)
|
||||
return WrapperLivingEntityTask(GoToSleepTask.create(), PokemonEntity::class.java)
|
||||
}
|
||||
}
|
||||
-67
@@ -1,67 +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.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
/**
|
||||
* Immediately gets angry at the nearest visible entity that matches the [entityCondition] and is within the [range].
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since June 23rd, 2025
|
||||
*/
|
||||
class HateEntityTaskConfig : SingleTaskConfig {
|
||||
val entityCondition: Expression = "true".asExpression()
|
||||
val range: ExpressionOrEntityVariable = Either.left("24".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
val range = range.resolveFloat()
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
|
||||
MemoryModuleType.ANGRY_AT
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
return BehaviorBuilder.create { instance ->
|
||||
instance.group(
|
||||
instance.present(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES),
|
||||
instance.registered(MemoryModuleType.ANGRY_AT)
|
||||
).apply(instance) { entities, angryAt ->
|
||||
Trigger { world, entity, _ ->
|
||||
val target = instance.get(entities).findClosest {
|
||||
runtime.withQueryValue("entity", it.asMostSpecificMoLangValue())
|
||||
return@findClosest runtime.resolveBoolean(entityCondition)
|
||||
}.orElse(null)
|
||||
|
||||
if (target != null && target.distanceTo(entity) <= range) {
|
||||
angryAt.set(target.uuid)
|
||||
}
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-5
@@ -8,8 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.CobblemonSensors
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
@@ -22,7 +20,6 @@ import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class HealUsingHealingMachineTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(SELF_HEALING, USE_HEALING_MACHINES, true).asExpressible()
|
||||
@@ -37,8 +34,6 @@ class HealUsingHealingMachineTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.WALK_TARGET, CobblemonMemories.NPC_BATTLING,)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.NPC_BATTLING)
|
||||
return HealUsingHealingMachineTask(horizontalUseRange.asExpression(), verticalUseRange.asExpression())
|
||||
}
|
||||
}
|
||||
-8
@@ -8,8 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.CobblemonSensors
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
@@ -20,7 +18,6 @@ import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class LookAtBattlingPokemonTaskConfig : SingleTaskConfig {
|
||||
companion object {
|
||||
@@ -43,11 +40,6 @@ class LookAtBattlingPokemonTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!resolveBooleanVariable(LOOK_AT_BATTLING_POKEMON)) return null
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.LOOK_TARGET,
|
||||
CobblemonMemories.BATTLING_POKEMON
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.BATTLING_POKEMON)
|
||||
return LookAtBattlingPokemonTask.create(
|
||||
minDurationTicks = minDurationTicks.resolveInt(),
|
||||
maxDurationTicks = maxDurationTicks.resolveInt()
|
||||
|
||||
-4
@@ -16,8 +16,6 @@ import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.SetEntityLookTarget
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
class LookAtEntitiesTaskConfig : SingleTaskConfig {
|
||||
companion object {
|
||||
@@ -38,8 +36,6 @@ class LookAtEntitiesTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.LOOK_TARGET)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
return SetEntityLookTarget.create(maxDistance.resolveFloat())
|
||||
}
|
||||
}
|
||||
+1
-5
@@ -8,19 +8,15 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.npc.ai.LookAtSpeakerTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class LookAtSpeakerTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
) = LookAtSpeakerTask.create().also {
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.LOOK_TARGET, CobblemonMemories.DIALOGUES)
|
||||
}
|
||||
) = LookAtSpeakerTask.create()
|
||||
}
|
||||
-2
@@ -20,7 +20,6 @@ import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.Mob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.LookAtTargetSink
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class LookAtTargetTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
@@ -39,7 +38,6 @@ class LookAtTargetTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.LOOK_TARGET)
|
||||
return WrapperLivingEntityTask(LookAtTargetSink(minDurationTicks.resolveInt(), maxDurationTicks.resolveInt()), Mob::class.java)
|
||||
}
|
||||
}
|
||||
+1
-11
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
@@ -16,22 +15,13 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.LookAtTargetedBattlePokemonTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class LookAtTargetedBattlePokemonTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(
|
||||
CobblemonMemories.POKEMON_BATTLE,
|
||||
CobblemonMemories.TARGETED_BATTLE_POKEMON,
|
||||
MemoryModuleType.LOOK_TARGET,
|
||||
)
|
||||
): BehaviorControl<in LivingEntity> {
|
||||
return WrapperLivingEntityTask(LookAtTargetedBattlePokemonTask.create(), PokemonEntity::class.java)
|
||||
}
|
||||
}
|
||||
+1
-4
@@ -13,7 +13,6 @@ import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.ai.config.task.SharedEntityVariables.LOOKING_CATEGORY
|
||||
import com.cobblemon.mod.common.entity.ai.LookInDirectionTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class LookInDirectionTaskConfig : SingleTaskConfig {
|
||||
var condition = booleanVariable(LOOKING_CATEGORY, "locked_rotation", true).asExpressible()
|
||||
@@ -33,7 +32,5 @@ class LookInDirectionTaskConfig : SingleTaskConfig {
|
||||
shouldLock = condition.asExpression(),
|
||||
yaw = yaw.asExpression(),
|
||||
pitch = pitch.asExpression()
|
||||
).also {
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.LOOK_TARGET)
|
||||
}
|
||||
)
|
||||
}
|
||||
-93
@@ -1,93 +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.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import java.util.UUID
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
/**
|
||||
* Task that looks around for a better herd leader or gives up on a leader
|
||||
* that is themselves following a different Pokémon.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since June 16th, 2025
|
||||
*/
|
||||
class MaintainHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
// How frequently to check for a better herd leader
|
||||
val checkTicks: ExpressionOrEntityVariable = Either.left("60".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf(checkTicks).asVariables()
|
||||
}
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(
|
||||
CobblemonMemories.HERD_LEADER,
|
||||
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val checkTicks = checkTicks.resolveInt()
|
||||
return BehaviorBuilder.create { instance ->
|
||||
instance.group(
|
||||
instance.present(CobblemonMemories.HERD_LEADER),
|
||||
instance.present(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES)
|
||||
).apply(instance) { herdLeader, nearbyEntities ->
|
||||
Trigger { world, entity, _ ->
|
||||
entity as PokemonEntity
|
||||
if (world.gameTime % checkTicks != 0L) {
|
||||
return@Trigger false
|
||||
}
|
||||
|
||||
val leader = instance.get(herdLeader).let(UUID::fromString).let(world::getEntity) as? PokemonEntity
|
||||
val currentLeaderDefinition = leader?.let { leader ->
|
||||
entity.behaviour.herd.toleratedLeaders.find { it.pokemon.matches(leader) }
|
||||
}
|
||||
if (leader == null || currentLeaderDefinition == null) {
|
||||
entity.brain.eraseMemory(CobblemonMemories.HERD_LEADER)
|
||||
return@Trigger true // No leader, so we erase the memory
|
||||
} else {
|
||||
val bestLeader = FindHerdLeaderTaskConfig.getBestHerdLeader(
|
||||
currentLeader = (leader to currentLeaderDefinition),
|
||||
nearbyEntities = instance.get(nearbyEntities),
|
||||
entity = entity
|
||||
)
|
||||
|
||||
if (bestLeader != null && bestLeader != leader) {
|
||||
bestLeader.brain.eraseMemory(CobblemonMemories.HERD_LEADER)
|
||||
entity.brain.setMemory(CobblemonMemories.HERD_LEADER, bestLeader.uuid.toString())
|
||||
}
|
||||
}
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-6
@@ -15,12 +15,11 @@ import com.cobblemon.mod.common.entity.npc.ai.MeleeAttackTask
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class MeleeAttackTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(SharedEntityVariables.ATTACKING_CATEGORY, "attacks_melee", true).asExpressible()
|
||||
val range = numberVariable(SharedEntityVariables.ATTACKING_CATEGORY, "melee_range", 1.5F).asExpressible()
|
||||
val cooldownTicks = numberVariable(SharedEntityVariables.ATTACKING_CATEGORY, "melee_cooldown", 20).asExpressible()
|
||||
val cooldownTicks = numberVariable(SharedEntityVariables.ATTACKING_CATEGORY, "melee_cooldown", 30).asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = listOf(
|
||||
condition,
|
||||
@@ -34,10 +33,7 @@ class MeleeAttackTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.ATTACK_TARGET,
|
||||
MemoryModuleType.ATTACK_COOLING_DOWN
|
||||
)
|
||||
|
||||
return MeleeAttackTask.create(
|
||||
range = range.asExpression(),
|
||||
cooldownTicks = cooldownTicks.asExpression()
|
||||
|
||||
-156
@@ -1,156 +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.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.ai.CobblemonWalkTarget
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.closestPosition
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import java.util.function.Predicate
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.tags.FluidTags
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.level.material.FluidState
|
||||
|
||||
/**
|
||||
* Used to get entities to move into whatever their preferred fluid is, like fish
|
||||
* stranded on land trying to get back into water.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since June 15th, 2025
|
||||
*/
|
||||
class MoveIntoFluidTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val movesIntoWater: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val movesIntoLava: ExpressionOrEntityVariable = Either.left("false".asExpression())
|
||||
val speedModifier: ExpressionOrEntityVariable = Either.left("0.5".asExpression())
|
||||
|
||||
val horizontalSearchRange: ExpressionOrEntityVariable = Either.left("8".asExpression())
|
||||
val verticalSearchRange: ExpressionOrEntityVariable = Either.left("8".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity): List<MoLangConfigVariable> {
|
||||
return listOf(
|
||||
condition,
|
||||
movesIntoWater,
|
||||
movesIntoLava,
|
||||
speedModifier,
|
||||
horizontalSearchRange,
|
||||
verticalSearchRange
|
||||
).asVariables()
|
||||
}
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
CobblemonMemories.PATH_COOLDOWN
|
||||
)
|
||||
val movesIntoWater = this@MoveIntoFluidTaskConfig.movesIntoWater.resolveBoolean()
|
||||
val movesIntoLava = movesIntoLava.resolveBoolean()
|
||||
val speedModifier = speedModifier.resolveFloat()
|
||||
val horizontalSearchRange = horizontalSearchRange.resolveInt()
|
||||
val verticalSearchRange = verticalSearchRange.resolveInt()
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(MemoryModuleType.WALK_TARGET),
|
||||
it.absent(CobblemonMemories.PATH_COOLDOWN)
|
||||
).apply(it) { walkTarget, pathCooldown ->
|
||||
Trigger { world, entity, _ ->
|
||||
val isInWater = entity.isInWater
|
||||
val isInLava = entity.isInLava
|
||||
// If it's already in a place it wants to be, then we're fine.
|
||||
if (isInWater && movesIntoWater || isInLava && movesIntoLava) {
|
||||
return@Trigger false
|
||||
}
|
||||
|
||||
pathCooldown.setWithExpiry(true, 20L * 5L) // 5 seconds cooldown
|
||||
val target = findTarget(
|
||||
entity = entity,
|
||||
movesIntoWater = movesIntoWater,
|
||||
movesIntoLava = movesIntoLava,
|
||||
horizontalSearchRange = horizontalSearchRange,
|
||||
verticalSearchRange = verticalSearchRange
|
||||
)
|
||||
if (target == null) {
|
||||
return@Trigger false
|
||||
}
|
||||
|
||||
walkTarget.set(
|
||||
CobblemonWalkTarget(
|
||||
pos = target,
|
||||
speedModifier = speedModifier,
|
||||
completionRange = 0
|
||||
)
|
||||
)
|
||||
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun findTarget(
|
||||
entity: LivingEntity,
|
||||
movesIntoWater: Boolean,
|
||||
movesIntoLava: Boolean,
|
||||
horizontalSearchRange: Int,
|
||||
verticalSearchRange: Int
|
||||
): BlockPos? {
|
||||
val predicate: Predicate<FluidState> = Predicate { fluid ->
|
||||
(movesIntoWater && fluid.`is`(FluidTags.WATER)) || (movesIntoLava && fluid.`is`(FluidTags.LAVA))
|
||||
}
|
||||
val iterable = BlockPos.betweenClosed(
|
||||
Mth.floor(entity.x - horizontalSearchRange),
|
||||
Mth.floor(entity.y - verticalSearchRange),
|
||||
Mth.floor(entity.z - horizontalSearchRange),
|
||||
Mth.floor(entity.x + horizontalSearchRange),
|
||||
entity.blockY + verticalSearchRange,
|
||||
Mth.floor(entity.z + horizontalSearchRange)
|
||||
)
|
||||
|
||||
val box = entity.boundingBox
|
||||
val blockPos = entity.closestPosition(iterable) { pos ->
|
||||
val maxX = pos.x + Mth.ceil(box.xsize) - 1
|
||||
val maxY = pos.y - 1 + Mth.ceil(box.ysize) - 1
|
||||
val maxZ = pos.z + Mth.ceil(box.zsize) - 1
|
||||
|
||||
val mutable = BlockPos.MutableBlockPos()
|
||||
for (x in pos.x..maxX) {
|
||||
for (y in (pos.y - 1)..maxY) {
|
||||
for (z in pos.z..maxZ) {
|
||||
if (!entity.level().isFluidAtPosition(mutable.set(x, y, z), predicate)) {
|
||||
return@closestPosition false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return@closestPosition true
|
||||
}
|
||||
|
||||
return blockPos
|
||||
}
|
||||
}
|
||||
+2
-8
@@ -15,11 +15,10 @@ import com.cobblemon.mod.common.entity.ai.MoveToAttackTargetTask
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class MoveToAttackTargetTaskConfig : SingleTaskConfig {
|
||||
val speedMultiplier = numberVariable(SharedEntityVariables.ATTACKING_CATEGORY, "attacking_movement_speed", 0.5).asExpressible()
|
||||
val closeEnoughDistance: ExpressionOrEntityVariable = Either.left("0".asExpression())
|
||||
val closeEnoughDistance: ExpressionOrEntityVariable = Either.left("1".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = listOf(
|
||||
speedMultiplier,
|
||||
@@ -32,10 +31,5 @@ class MoveToAttackTargetTaskConfig : SingleTaskConfig {
|
||||
) = MoveToAttackTargetTask.create(
|
||||
speedMultiplier = speedMultiplier.asExpression(),
|
||||
closeEnoughDistance = closeEnoughDistance.asExpression()
|
||||
).also {
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.ATTACK_TARGET,
|
||||
MemoryModuleType.WALK_TARGET
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
-5
@@ -18,7 +18,6 @@ import com.cobblemon.mod.common.util.asExpression
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class MoveToOwnerTaskConfig : SingleTaskConfig {
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
@@ -39,10 +38,6 @@ class MoveToOwnerTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
MemoryModuleType.LOOK_TARGET
|
||||
)
|
||||
return WrapperLivingEntityTask(
|
||||
MoveToOwnerTask.create(
|
||||
condition = condition.asExpression(),
|
||||
|
||||
+5
-5
@@ -9,12 +9,12 @@
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.toDF
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.RunOne
|
||||
@@ -35,14 +35,14 @@ class OneOfTaskConfig : SingleTaskConfig {
|
||||
val task: TaskConfig = SingleTaskConfig.nothing()
|
||||
}
|
||||
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val condition: ExpressionLike = "true".asExpressionLike()
|
||||
val options = mutableListOf<OneOfTaskOption>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = options.flatMap { it.task.getVariables(entity) }
|
||||
|
||||
override fun createTask(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
if (!runtime.resolveBoolean(condition)) return null
|
||||
return RunOne(options.map { it.task.createTasks(entity, behaviourConfigurationContext).first() toDF it.weight })
|
||||
}
|
||||
}
|
||||
-1
@@ -22,7 +22,6 @@ import net.minecraft.world.phys.Vec3
|
||||
class PointToSpawnTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): BehaviorControl<in LivingEntity>? {
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.LOOK_TARGET, MemoryModuleType.WALK_TARGET)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.registered(MemoryModuleType.LOOK_TARGET),
|
||||
|
||||
@@ -188,7 +188,7 @@ The 'look_in_direction' type creates a task that will make the entity look in a
|
||||
### move_to_owner
|
||||
The 'move_to_owner' type creates a task that will make the entity move to its owner. This will only work for entities that
|
||||
can be owned, like Pokémon.
|
||||
- `condition`: A MoLang expression (with `q.entity` as the entity) that determines if the entity should move to its owner this tick. Defaults to true.
|
||||
- `condition`: A MoLang expression (with `q.entity` as the entity) that determines if this entire task should exist on the entity or not. This runs at the time of entity creation, not on tick.
|
||||
- `completionRange`: A MoLang expression that determines the distance from the owner that the entity needs to be for the path to be considered complete. Defaults to 4.
|
||||
- `speedMultiplier`: A MoLang expression that determines the speed multiplier for moving to the owner. Defaults to 0.4 which is slightly above the normal walk speed.
|
||||
- `teleportDistance`: A MoLang expression that determines the distance from the owner the entity must be before it resorts to teleporting. A value of -1 will cause it to never teleport. Defaults to 24.
|
||||
|
||||
+4
-7
@@ -9,16 +9,12 @@
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.weightedSelection
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
|
||||
@@ -39,16 +35,17 @@ class RandomTaskConfig : TaskConfig {
|
||||
val task: TaskConfig = SingleTaskConfig.nothing()
|
||||
}
|
||||
|
||||
val condition: ExpressionOrEntityVariable = Either.left("true".asExpression())
|
||||
val condition: ExpressionLike = "true".asExpressionLike()
|
||||
val choices = mutableListOf<RandomTaskChoice>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = choices.flatMap { it.task.getVariables(entity) } + listOf(condition).asVariables()
|
||||
override fun getVariables(entity: LivingEntity) = choices.flatMap { it.task.getVariables(entity) }
|
||||
|
||||
override fun createTasks(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): List<BehaviorControl<in LivingEntity>> {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return emptyList()
|
||||
if (!runtime.resolveBoolean(condition)) return emptyList()
|
||||
val task = choices.weightedSelection { it.weight }?.task ?: throw IllegalStateException("No tasks to choose from in random_task config")
|
||||
return task.createTasks(entity, behaviourConfigurationContext)
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
/**
|
||||
* Runs a registered MoLang script (from the molang datapack folder) each tick.
|
||||
@@ -39,8 +38,6 @@ class RunScript : SingleTaskConfig {
|
||||
|
||||
val script = stringVariable(SCRIPT_CATEGORY, "script", "cobblemon:dummy_script").asExpressible()
|
||||
val variables = mutableListOf<MoLangConfigVariable>()
|
||||
val memories = emptySet<MemoryModuleType<*>>()
|
||||
val sensors = emptySet<SensorType<*>>()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = listOf(script).asVariables() + variables
|
||||
|
||||
@@ -48,8 +45,6 @@ class RunScript : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? = BehaviorBuilder.create {
|
||||
behaviourConfigurationContext.addMemories(memories + MemoryModuleType.LOOK_TARGET)
|
||||
behaviourConfigurationContext.addSensors(sensors)
|
||||
it.group(
|
||||
it.registered(MemoryModuleType.LOOK_TARGET) // I think I need to have at least something here?
|
||||
).apply(it) { _ ->
|
||||
|
||||
-4
@@ -25,10 +25,6 @@ class SleepIfOnTrainerBedTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity> {
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
CobblemonMemories.POKEMON_SLEEPING
|
||||
)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.registered(MemoryModuleType.WALK_TARGET),
|
||||
|
||||
+5
-3
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
@@ -23,11 +22,14 @@ class StayAfloatTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(SharedEntityVariables.MOVEMENT_CATEGORY, "can_float", true).asExpressible()
|
||||
val chance = numberVariable(SharedEntityVariables.MOVEMENT_CATEGORY, "float_chance", 0.8F).asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition, chance).asVariables()
|
||||
override fun getVariables(entity: LivingEntity) = listOf(
|
||||
condition,
|
||||
chance
|
||||
).asVariables()
|
||||
|
||||
override fun createTask(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): BehaviorControl<LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.POKEMON_BATTLE)
|
||||
return WrapperLivingEntityTask(
|
||||
StayAfloatTask(chance.resolveFloat()),
|
||||
PathfinderMob::class.java
|
||||
|
||||
-50
@@ -1,50 +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.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask.Companion.wrapped
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import java.util.function.Predicate
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.Mob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.StopAttackingIfTargetInvalid
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
/**
|
||||
* A task config wrapping around vanilla's [StopAttackingIfTargetInvalid] that supports the optional ATTACK_TARGET_DATA
|
||||
* memory to determine if the target is still valid for attacking.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since June 23rd, 2025
|
||||
*/
|
||||
class StopAttackingIfTargetInvalidTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
val runtime = MoLangRuntime().setup()
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.ATTACK_TARGET_DATA, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)
|
||||
return StopAttackingIfTargetInvalid.create<Mob>(
|
||||
Predicate { target ->
|
||||
val targetData = entity.brain.getMemory(CobblemonMemories.ATTACK_TARGET_DATA).orElse(null) ?: return@Predicate false
|
||||
runtime.withQueryValue("entity", target.asMostSpecificMoLangValue())
|
||||
return@Predicate !runtime.resolveBoolean(targetData.shouldContinue)
|
||||
}
|
||||
).wrapped()
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -15,19 +15,18 @@ import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.StopBeingAngryIfTargetDead
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class StopBeingAngryIfAttackerDeadTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(SharedEntityVariables.ATTACKING_CATEGORY, "stop_being_angry_if_attacker_dead", true).asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = listOf(condition).asVariables()
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.ANGRY_AT)
|
||||
return StopBeingAngryIfTargetDead.create()
|
||||
}
|
||||
}
|
||||
-2
@@ -29,7 +29,5 @@ class SwitchFromActionEffectTaskConfig : SingleTaskConfig {
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}.also {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.ACTIVE_ACTION_EFFECT)
|
||||
}
|
||||
}
|
||||
-2
@@ -29,7 +29,5 @@ class SwitchFromChattingTaskConfig : SingleTaskConfig {
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}.also {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.DIALOGUES)
|
||||
}
|
||||
}
|
||||
-4
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@@ -26,12 +25,9 @@ class SwitchFromFightTaskConfig : SingleTaskConfig {
|
||||
it.absent(MemoryModuleType.ATTACK_TARGET)
|
||||
).apply(it) { _ ->
|
||||
Trigger { level, entity, _ ->
|
||||
entity.brain.eraseMemory(CobblemonMemories.ATTACK_TARGET_DATA)
|
||||
entity.brain.updateActivityFromSchedule(level.dayTime, level.gameTime)
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}.also {
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.ATTACK_TARGET)
|
||||
}
|
||||
}
|
||||
-37
@@ -1,37 +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.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
|
||||
class SwitchFromHerdTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.HERD_LEADER)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(CobblemonMemories.HERD_LEADER)
|
||||
).apply(it) { _ ->
|
||||
Trigger { world, entity, time ->
|
||||
entity.brain.updateActivityFromSchedule(world.dayTime, world.gameTime)
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-1
@@ -22,7 +22,6 @@ class SwitchFromNPCBattleTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.NPC_BATTLING)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(it.absent(CobblemonMemories.NPC_BATTLING)).apply(it) { _ ->
|
||||
Trigger { level, entity, _ ->
|
||||
|
||||
-1
@@ -22,7 +22,6 @@ class SwitchFromPokemonBattleTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.POKEMON_BATTLE)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(it.absent(CobblemonMemories.POKEMON_BATTLE)).apply(it) { _ ->
|
||||
Trigger { level, entity, _ ->
|
||||
|
||||
-1
@@ -29,7 +29,6 @@ class SwitchFromSleepOnTrainerBedTaskConfig : SingleTaskConfig {
|
||||
return null
|
||||
}
|
||||
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.POKEMON_SLEEPING)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.registered(CobblemonMemories.POKEMON_SLEEPING)
|
||||
|
||||
-1
@@ -23,7 +23,6 @@ class SwitchToActionEffectTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.ACTIVE_ACTION_EFFECT)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(CobblemonMemories.ACTIVE_ACTION_EFFECT)
|
||||
|
||||
+4
-3
@@ -24,10 +24,11 @@ class SwitchToChattingTaskConfig : SingleTaskConfig {
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
) = BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.present(CobblemonMemories.DIALOGUES)
|
||||
).apply(it) { _ ->
|
||||
it.present(CobblemonMemories.DIALOGUES),
|
||||
it.registered(MemoryModuleType.WALK_TARGET)
|
||||
).apply(it) { _, walkTarget ->
|
||||
Trigger { world, entity, _ ->
|
||||
entity.brain.eraseMemory(MemoryModuleType.WALK_TARGET) // it may not even have this memory but clear it if it got it
|
||||
walkTarget.erase()
|
||||
entity.brain.setActiveActivityIfPossible(CobblemonActivities.NPC_CHATTING)
|
||||
return@Trigger true
|
||||
}
|
||||
|
||||
-2
@@ -40,7 +40,5 @@ class SwitchToFightTaskConfig : SingleTaskConfig {
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}.also {
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.ATTACK_TARGET)
|
||||
}
|
||||
}
|
||||
-39
@@ -1,39 +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.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonActivities
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
|
||||
class SwitchToHerdTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.HERD_LEADER)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.present(CobblemonMemories.HERD_LEADER)
|
||||
).apply(it) { _ ->
|
||||
Trigger { world, entity, time ->
|
||||
entity.brain.setActiveActivityIfPossible(CobblemonActivities.POKEMON_HERD)
|
||||
entity.brain.eraseMemory(CobblemonMemories.HERD_SIZE)
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-7
@@ -8,22 +8,16 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.CobblemonSensors
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.npc.ai.SwitchToBattleTask
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class SwitchToNPCBattleTaskConfig : SingleTaskConfig {
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity> = SwitchToBattleTask.create().also {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.NPC_BATTLING)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.NPC_BATTLING)
|
||||
}
|
||||
): BehaviorControl<in LivingEntity> = SwitchToBattleTask.create()
|
||||
}
|
||||
-3
@@ -18,7 +18,6 @@ import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
class SwitchToPanicWhenHostilesNearbyTaskConfig : SingleTaskConfig {
|
||||
@@ -31,8 +30,6 @@ class SwitchToPanicWhenHostilesNearbyTaskConfig : SingleTaskConfig {
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.NEAREST_HOSTILE)
|
||||
behaviourConfigurationContext.addSensors(SensorType.VILLAGER_HOSTILES)
|
||||
return BehaviorBuilder.create {
|
||||
it.group(it.present(MemoryModuleType.NEAREST_HOSTILE))
|
||||
.apply(it) { nearestHostile ->
|
||||
|
||||
-5
@@ -18,7 +18,6 @@ import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
class SwitchToPanicWhenHurtTaskConfig : SingleTaskConfig {
|
||||
@@ -37,8 +36,6 @@ class SwitchToPanicWhenHurtTaskConfig : SingleTaskConfig {
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
if (!condition.resolveBoolean()) return null
|
||||
return if (includePassiveDamage.resolveBoolean()) {
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.HURT_BY)
|
||||
behaviourConfigurationContext.addSensors(SensorType.HURT_BY)
|
||||
BehaviorBuilder.create {
|
||||
it.group(it.present(MemoryModuleType.HURT_BY))
|
||||
.apply(it) { _ ->
|
||||
@@ -50,8 +47,6 @@ class SwitchToPanicWhenHurtTaskConfig : SingleTaskConfig {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.HURT_BY_ENTITY)
|
||||
behaviourConfigurationContext.addSensors(SensorType.HURT_BY)
|
||||
BehaviorBuilder.create {
|
||||
it.group(it.present(MemoryModuleType.HURT_BY_ENTITY))
|
||||
.apply(it) { _ ->
|
||||
|
||||
-2
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.npc.ai.SwitchToBattleTask
|
||||
@@ -21,7 +20,6 @@ class SwitchToPokemonBattleTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity> {
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.POKEMON_BATTLE)
|
||||
return SwitchToBattleTask.createForPokemon()
|
||||
}
|
||||
}
|
||||
-6
@@ -36,12 +36,6 @@ class SwitchToSleepOnTrainerBedTaskConfig : SingleTaskConfig {
|
||||
return null
|
||||
}
|
||||
|
||||
behaviourConfigurationContext.addMemories(
|
||||
CobblemonMemories.POKEMON_SLEEPING,
|
||||
CobblemonMemories.POKEMON_BATTLE,
|
||||
MemoryModuleType.WALK_TARGET
|
||||
)
|
||||
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(CobblemonMemories.POKEMON_BATTLE),
|
||||
|
||||
-74
@@ -1,74 +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.ai.config.task
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.CobblemonAttackTargetData
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.memory.MemoryStatus
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
/**
|
||||
* Directly sets the attack target of the entity to the nearest visible entity that matches the [entityCondition]
|
||||
* and is within the [range].
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since June 23rd, 2025
|
||||
*/
|
||||
class TargetEntityTaskConfig : SingleTaskConfig {
|
||||
val entityCondition: Expression = "true".asExpression()
|
||||
val range: ExpressionOrEntityVariable = Either.left("24".asExpression())
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = emptyList<MoLangConfigVariable>()
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
val range = range.resolveFloat()
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES,
|
||||
MemoryModuleType.ATTACK_TARGET,
|
||||
CobblemonMemories.ATTACK_TARGET_DATA
|
||||
)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
return BehaviorBuilder.create { instance ->
|
||||
instance.group(
|
||||
instance.present(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES),
|
||||
instance.registered(MemoryModuleType.ATTACK_TARGET)
|
||||
).apply(instance) { entities, attackTarget ->
|
||||
Trigger { world, entity, _ ->
|
||||
val target = instance.get(entities).findClosest {
|
||||
runtime.withQueryValue("entity", it.asMostSpecificMoLangValue())
|
||||
return@findClosest runtime.resolveBoolean(entityCondition)
|
||||
}.orElse(null)
|
||||
|
||||
if (target != null && target.distanceTo(entity) <= range) {
|
||||
val attackTargetData = CobblemonAttackTargetData(shouldContinue = entityCondition)
|
||||
entity.brain.setMemory(CobblemonMemories.ATTACK_TARGET_DATA, attackTargetData)
|
||||
attackTarget.set(target)
|
||||
}
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,8 +32,6 @@ import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
|
||||
/**
|
||||
* A configuration for a brain task. Its purpose is to generate a list of tasks to add to the brain of
|
||||
@@ -59,7 +57,6 @@ interface TaskConfig {
|
||||
cobblemonResource("do_nothing") to DoNothingTaskConfig::class.java,
|
||||
cobblemonResource("get_angry_at_attacker") to GetAngryAtAttackerTaskConfig::class.java,
|
||||
cobblemonResource("stop_being_angry_if_attacker_dead") to StopBeingAngryIfAttackerDeadTaskConfig::class.java,
|
||||
cobblemonResource("stop_attacking_if_target_invalid") to StopAttackingIfTargetInvalidTaskConfig::class.java,
|
||||
cobblemonResource("switch_npc_to_battle") to SwitchToNPCBattleTaskConfig::class.java,
|
||||
cobblemonResource("look_at_battling_pokemon") to LookAtBattlingPokemonTaskConfig::class.java,
|
||||
cobblemonResource("switch_npc_from_battle") to SwitchFromNPCBattleTaskConfig::class.java,
|
||||
@@ -85,7 +82,6 @@ interface TaskConfig {
|
||||
cobblemonResource("calm_down") to CalmDownTaskConfig::class.java,
|
||||
cobblemonResource("flee_attacker") to FleeAttackerTaskConfig::class.java,
|
||||
cobblemonResource("flee_nearest_hostile") to FleeNearestHostileTaskConfig::class.java,
|
||||
cobblemonResource("fly_in_circles") to FlyInCirclesTaskConfig::class.java,
|
||||
cobblemonResource("run_script") to RunScript::class.java,
|
||||
cobblemonResource("look_in_direction") to LookInDirectionTaskConfig::class.java,
|
||||
cobblemonResource("wake_up") to WakeUpTaskConfig::class.java,
|
||||
@@ -99,19 +95,9 @@ interface TaskConfig {
|
||||
cobblemonResource("eat_grass") to EatGrassTaskConfig::class.java,
|
||||
cobblemonResource("find_air") to FindAirTaskConfig::class.java,
|
||||
cobblemonResource("go_to_land") to GoToLandTaskConfig::class.java,
|
||||
cobblemonResource("manage_flight_in_battle") to ManageFlightInBattleTaskConfig::class.java,
|
||||
cobblemonResource("attack_hostile_mobs") to AttackHostileMobsTaskConfig::class.java,
|
||||
cobblemonResource("move_into_fluid") to MoveIntoFluidTaskConfig::class.java,
|
||||
cobblemonResource("find_herd_leader") to FindHerdLeaderTaskConfig::class.java,
|
||||
cobblemonResource("follow_herd_leader") to FollowHerdLeaderTaskConfig::class.java,
|
||||
cobblemonResource("switch_to_herd") to SwitchToHerdTaskConfig::class.java,
|
||||
cobblemonResource("switch_from_herd") to SwitchFromHerdTaskConfig::class.java,
|
||||
cobblemonResource("maintain_herd_leader") to MaintainHerdLeaderTaskConfig::class.java,
|
||||
cobblemonResource("count_followers") to CountFollowersTaskConfig::class.java,
|
||||
cobblemonResource("hate_entity") to HateEntityTaskConfig::class.java,
|
||||
cobblemonResource("target_entity") to TargetEntityTaskConfig::class.java,
|
||||
cobblemonResource("battle_flight_task") to BattleFlightTaskConfig::class.java
|
||||
)
|
||||
|
||||
|
||||
val runtime = MoLangRuntime().setup()
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.CobblemonSensors
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
@@ -24,11 +22,6 @@ class WakeUpTaskConfig : SingleTaskConfig {
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
): BehaviorControl<in LivingEntity>? {
|
||||
if (entity !is PokemonEntity) {
|
||||
return null
|
||||
}
|
||||
behaviourConfigurationContext.addMemories(CobblemonMemories.POKEMON_DROWSY, CobblemonMemories.POKEMON_SLEEPING)
|
||||
behaviourConfigurationContext.addSensors(CobblemonSensors.POKEMON_DROWSY)
|
||||
return WrapperLivingEntityTask(WakeUpTask.create(), PokemonEntity::class.java)
|
||||
}
|
||||
}
|
||||
+6
-80
@@ -10,16 +10,12 @@ package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.entity.ai.CobblemonWalkTarget
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.resolveFloat
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
@@ -38,57 +34,17 @@ class WanderTaskConfig : SingleTaskConfig {
|
||||
val wanderChance = numberVariable(WANDER, "wander_chance", 1/(20 * 6F)).asExpressible()
|
||||
val horizontalRange = numberVariable(WANDER, "horizontal_wander_range", 10).asExpressible()
|
||||
val verticalRange = numberVariable(WANDER, "vertical_wander_range", 5).asExpressible()
|
||||
|
||||
val speedMultiplier = numberVariable(SharedEntityVariables.MOVEMENT_CATEGORY, SharedEntityVariables.WALK_SPEED, 0.35).asExpressible()
|
||||
val avoidTargetingAir: ExpressionOrEntityVariable = Either.left("true".asExpression()) // Whether to avoid air blocks when wandering
|
||||
val minimumHeight: ExpressionOrEntityVariable = Either.left("0".asExpression()) // Height off the ground
|
||||
val maximumHeight: ExpressionOrEntityVariable = Either.left("-1".asExpression()) // Height off the ground
|
||||
|
||||
override fun getVariables(entity: LivingEntity) = listOf(
|
||||
condition,
|
||||
wanderChance,
|
||||
horizontalRange,
|
||||
verticalRange,
|
||||
speedMultiplier,
|
||||
avoidTargetingAir,
|
||||
minimumHeight,
|
||||
maximumHeight
|
||||
speedMultiplier
|
||||
).asVariables()
|
||||
|
||||
private fun applyHeightConstraints(
|
||||
pos: BlockPos,
|
||||
minimumHeight: Int,
|
||||
maximumHeight: Int,
|
||||
world: ServerLevel
|
||||
): BlockPos {
|
||||
if (minimumHeight <= 0 && maximumHeight == -1) {
|
||||
return pos // It ain't a hoverer
|
||||
}
|
||||
|
||||
val block = world.getBlockState(pos)
|
||||
val altitude = if (!block.isAir) {
|
||||
0
|
||||
} else {
|
||||
(1..64).firstOrNull {
|
||||
val newPos = pos.below(it)
|
||||
return@firstOrNull !world.getBlockState(newPos).isAir
|
||||
} ?: Int.MAX_VALUE
|
||||
}
|
||||
|
||||
if (altitude > maximumHeight && maximumHeight >= 0) {
|
||||
val excess = altitude - maximumHeight
|
||||
val excessFromMinimum = altitude - minimumHeight
|
||||
val correction = world.random.nextIntBetweenInclusive(excess, excessFromMinimum)
|
||||
return pos.atY(pos.y - correction)
|
||||
} else if (altitude < minimumHeight && minimumHeight >= 0) {
|
||||
val deficit = minimumHeight - altitude
|
||||
val deficitFromMaximum = maximumHeight - altitude
|
||||
val correction = world.random.nextIntBetweenInclusive(deficit, deficitFromMaximum)
|
||||
return pos.atY(pos.y + correction)
|
||||
} else {
|
||||
return pos
|
||||
}
|
||||
}
|
||||
|
||||
override fun createTask(
|
||||
entity: LivingEntity,
|
||||
behaviourConfigurationContext: BehaviourConfigurationContext
|
||||
@@ -98,12 +54,6 @@ class WanderTaskConfig : SingleTaskConfig {
|
||||
|
||||
val wanderChanceExpression = wanderChance.asSimplifiedExpression(entity)
|
||||
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
MemoryModuleType.LOOK_TARGET,
|
||||
CobblemonMemories.PATH_COOLDOWN
|
||||
)
|
||||
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(MemoryModuleType.WALK_TARGET),
|
||||
@@ -117,38 +67,14 @@ class WanderTaskConfig : SingleTaskConfig {
|
||||
|
||||
runtime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val wanderChance = runtime.resolveFloat(wanderChanceExpression)
|
||||
if (wanderChance <= 0 || world.random.nextFloat() > wanderChance) {
|
||||
return@Trigger false
|
||||
}
|
||||
if (wanderChance <= 0 || world.random.nextFloat() > wanderChance) return@Trigger false
|
||||
|
||||
pathCooldown.setWithExpiry(true, 40L)
|
||||
val avoidsTargetingAir = avoidTargetingAir.resolveBoolean()
|
||||
|
||||
// val targetVec = getLandTarget(entity) ?: return@Trigger true
|
||||
val targetVec = LandRandomPos.getPos(
|
||||
entity,
|
||||
horizontalRange.resolveInt(),
|
||||
verticalRange.resolveInt()
|
||||
) ?: return@Trigger false
|
||||
|
||||
val minimumHeight = minimumHeight.resolveInt()
|
||||
val maximumHeight = maximumHeight.resolveInt()
|
||||
|
||||
val pos = applyHeightConstraints(
|
||||
pos = BlockPos.containing(targetVec),
|
||||
minimumHeight = minimumHeight,
|
||||
maximumHeight = maximumHeight,
|
||||
world = world
|
||||
)
|
||||
walkTarget.set(
|
||||
CobblemonWalkTarget(
|
||||
pos = pos,
|
||||
speedModifier = speedMultiplier.resolveFloat(),
|
||||
completionRange = 0,
|
||||
nodeTypeFilter = { nodeType -> nodeType !in listOf(PathType.WATER, PathType.WATER_BORDER) },
|
||||
destinationNodeTypeFilter = { nodeType -> !avoidsTargetingAir || nodeType !in listOf(PathType.OPEN) }
|
||||
)
|
||||
)
|
||||
val targetVec = LandRandomPos.getPos(entity, horizontalRange.resolveInt(), verticalRange.resolveInt()) ?: return@Trigger false
|
||||
val pos = BlockPos.containing(targetVec)
|
||||
walkTarget.set(CobblemonWalkTarget(pos, speedMultiplier.resolveFloat(), 0, { it !in listOf(PathType.WATER, PathType.WATER_BORDER) }))
|
||||
lookTarget.erase()
|
||||
return@Trigger true
|
||||
}
|
||||
|
||||
+4
-23
@@ -8,19 +8,16 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.ai.config.task
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.ai.config.task.WanderTaskConfig.Companion.WANDER
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.entity.ai.CobblemonWalkTarget
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.resolveFloat
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
@@ -29,7 +26,7 @@ import net.minecraft.world.entity.ai.behavior.BlockPosTracker
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.level.pathfinder.PathType
|
||||
import net.minecraft.world.entity.ai.memory.WalkTarget
|
||||
|
||||
class WaterWanderTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(WANDER, "water_wanders", true).asExpressible()
|
||||
@@ -51,18 +48,11 @@ class WaterWanderTaskConfig : SingleTaskConfig {
|
||||
|
||||
val wanderChanceExpression = wanderChance.asSimplifiedExpression(entity)
|
||||
|
||||
behaviourConfigurationContext.addMemories(
|
||||
MemoryModuleType.WALK_TARGET,
|
||||
MemoryModuleType.LOOK_TARGET,
|
||||
CobblemonMemories.PATH_COOLDOWN
|
||||
)
|
||||
|
||||
return BehaviorBuilder.create {
|
||||
it.group(
|
||||
it.absent(MemoryModuleType.WALK_TARGET),
|
||||
it.registered(MemoryModuleType.LOOK_TARGET),
|
||||
it.registered(CobblemonMemories.PATH_COOLDOWN)
|
||||
).apply(it) { walkTarget, lookTarget, pathCooldown ->
|
||||
it.registered(MemoryModuleType.LOOK_TARGET)
|
||||
).apply(it) { walkTarget, lookTarget ->
|
||||
Trigger { world, entity, time ->
|
||||
if (entity !is PathfinderMob || !entity.isInWater) {
|
||||
return@Trigger false
|
||||
@@ -74,17 +64,8 @@ class WaterWanderTaskConfig : SingleTaskConfig {
|
||||
return@Trigger false
|
||||
}
|
||||
|
||||
pathCooldown.setWithExpiry(true, 60L)
|
||||
|
||||
val target = BehaviorUtils.getRandomSwimmablePos(entity, horizontalRange.resolveInt(), verticalRange.resolveInt()) ?: return@Trigger false
|
||||
walkTarget.set(
|
||||
CobblemonWalkTarget(
|
||||
pos = BlockPos.containing(target),
|
||||
nodeTypeFilter = { it == PathType.WATER || it == PathType.WATER_BORDER },
|
||||
speedModifier = speedMultiplier.resolveFloat(),
|
||||
completionRange = 1
|
||||
)
|
||||
)
|
||||
walkTarget.set(WalkTarget(target, speedMultiplier.resolveFloat(), 1))
|
||||
lookTarget.set(BlockPosTracker(target))
|
||||
return@Trigger true
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ import com.cobblemon.mod.common.net.messages.client.battle.BattleEndPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMessagePacket
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.DefeatEvolutionProgress
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.LastBattleCriticalHitsEvolutionProgress
|
||||
import com.cobblemon.mod.common.pokemon.requirements.DefeatRequirement
|
||||
import com.cobblemon.mod.common.pokemon.evolution.requirements.DefeatRequirement
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.getPlayer
|
||||
import com.cobblemon.mod.common.util.giveOrDropItemStack
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user