mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-11-02 14:28:54 -05:00
Compare commits
77
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65c40b0e39 | ||
|
|
9943f75d09 | ||
|
|
945c764bee | ||
|
|
756e484582 | ||
|
|
ecc73a3d2c | ||
|
|
36d1008f29 | ||
|
|
1441625a6b | ||
|
|
0fb5d4f69b | ||
|
|
6ca16a0161 | ||
|
|
e4346687fc | ||
|
|
2f31db2232 | ||
|
|
e0f26923b7 | ||
|
|
52cff9472a | ||
|
|
c4935c3128 | ||
|
|
7831421399 | ||
|
|
a059979220 | ||
|
|
09bab5b2aa | ||
|
|
358d2604fb | ||
|
|
bbd0415c92 | ||
|
|
9f553fc6c1 | ||
|
|
51f8bb6ad5 | ||
|
|
cf93c0d544 | ||
|
|
2e6bef608b | ||
|
|
dcba7a5ab7 | ||
|
|
4e3b1eb641 | ||
|
|
6f949ce858 | ||
|
|
a04cd3162a | ||
|
|
8b551159a6 | ||
|
|
05b8621a81 | ||
|
|
1068d3e078 | ||
|
|
c1d6a9563c | ||
|
|
f426b16f1d | ||
|
|
c944fc1ac6 | ||
|
|
c68df830a7 | ||
|
|
0432441868 | ||
|
|
dcd0959600 | ||
|
|
7f631174d7 | ||
|
|
379344036f | ||
|
|
759f0800cd | ||
|
|
0ed0270d18 | ||
|
|
478e714a2d | ||
|
|
6005c04e64 | ||
|
|
75f76ae228 | ||
|
|
31a955fed1 | ||
|
|
4f1517e336 | ||
|
|
6772d95d25 | ||
|
|
a29f9d7bce | ||
|
|
2ff6559b5e | ||
|
|
fc6739f640 | ||
|
|
6ff4eef7dc | ||
|
|
82151c3944 | ||
|
|
0af4588a14 | ||
|
|
3c07ca973b | ||
|
|
60f3393f3f | ||
|
|
c6a1518e0d | ||
|
|
e816e41df1 | ||
|
|
96a9844fa4 | ||
|
|
8febe77edb | ||
|
|
ef89d8fcd8 | ||
|
|
0253a4dd7a | ||
|
|
5259ea0455 | ||
|
|
f637768e3d | ||
|
|
ef867a02d5 | ||
|
|
e0456939a9 | ||
|
|
7210063026 | ||
|
|
94e52f6f82 | ||
|
|
cba0c138b0 | ||
|
|
b748e39877 | ||
|
|
0d311593cc | ||
|
|
a1031f3dc9 | ||
|
|
e753e05c67 | ||
|
|
ed292bcaea | ||
|
|
c2f1176aca | ||
|
|
637ad2e510 | ||
|
|
e08ddc4fc4 | ||
|
|
0da8243f05 | ||
|
|
2774360d4c |
No files matched your search
+17
-1
@@ -6,6 +6,10 @@
|
||||
- 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.
|
||||
- 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.
|
||||
- Added `visibility/hidden`, `visibility/hat` and `visibility/face` tags to control where and how certain items are rendered.
|
||||
|
||||
### Changes
|
||||
- Renamed `chargeGainedPerTick` config to `secondsToChargeHealingMachine`.
|
||||
@@ -21,6 +25,15 @@
|
||||
- Fixed fling not using Item Names for minecraft held items that substitute Pokémon items
|
||||
- Fixed evolutions sometimes preventing players from logging in to servers
|
||||
- Fixed rendering of shoulder-mounted Pokémon desyncing between clients
|
||||
- Fixed apricorn chest boats forgetting their inventories when being unloaded
|
||||
- Fixed moves not updating correctly between form changes resulting in illegal movesets
|
||||
- Fixed crash sometimes occurring with the "Oritech" mod
|
||||
- Fixed crashes due to an incorrect Java version handing out an obscure crash.
|
||||
- Fixed some berries being able to rarely get too many berries and cause a crash.
|
||||
- Fixed status curing berries not playing the berry eating sound, same for healing berries used mid-battle.
|
||||
- Fixed owned Pokémon sometimes being un-interactable after the player relogs fast
|
||||
- Fixed field name in evolution requirements for Spewpa Pokeball.
|
||||
- Fixed LevelUpCriterion logic to correctly check that the Pokémon is a preEvo.
|
||||
|
||||
### Developer
|
||||
- A finished battle now has winners and losers set inside of `PokemonBattle` instead of them always being empty.
|
||||
@@ -34,11 +47,14 @@
|
||||
|
||||
### Changes
|
||||
- When using the `cobblemon` or `generation_9` capture calculators a critical capture with a single shake will always play for successful captures when you've already registered the Pokémon as caught in your Pokédex.
|
||||
|
||||
### 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
|
||||
- The `itemCondition` for a held item evolution requirement
|
||||
- The `fossils` for a fossil entry
|
||||
- Added MoLang flows for `poke_ball_capture_calculated`, `evolution_tested`, `evolution_accepted`, `evolution_completed`
|
||||
- Added `interpolate` boolean property to animated textures to allow gradual colour changes between frames.
|
||||
|
||||
## [1.6.1 (January 26th, 2025)](#1-6-1)
|
||||
|
||||
@@ -2159,4 +2175,4 @@ Thank you so much to all of our community translators that bring the mod to the
|
||||
- Added species, ability, and move translations for `ko_ko`, `jp_jp`, `fr_fr`, `es_es`, `it_it`, and `zh_cn`.
|
||||
|
||||
## [1.0.0 (November 12th, 2022)](#1-0-0)
|
||||
- Initial release.
|
||||
- Initial release.
|
||||
@@ -1,6 +1,6 @@
|
||||
# Cobblemon
|
||||
|
||||
An open-source Pokémon mod for Minecraft Java Edition, written in Kotlin for Fabric and Forge.
|
||||
An open-source Pokémon mod for Minecraft Java Edition, written in Kotlin for Fabric and NeoForge.
|
||||
|
||||
## Getting started
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
implementation(libs.bundles.kotlin)
|
||||
implementation("jakarta.websocket:jakarta.websocket-api:2.2.0")
|
||||
|
||||
modImplementation(libs.fabric.loader)
|
||||
modApi(libs.molang)
|
||||
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
{
|
||||
"lastSavedVersion": "1.7.0",
|
||||
"maxPokemonLevel": 100,
|
||||
"maxPokemonFriendship": 255,
|
||||
"announceDropItems": true,
|
||||
"defaultDropItemMethod": "on-entity",
|
||||
"ambientPokemonCryTicks": 1080,
|
||||
"defaultBoxCount": 30,
|
||||
"pokemonSaveIntervalSeconds": 30,
|
||||
"storageFormat": "nbt",
|
||||
"preventCompletePartyDeposit": false,
|
||||
"mongoDBConnectionString": "mongodb://localhost:27017",
|
||||
"mongoDBDatabaseName": "cobblemon",
|
||||
"maxVerticalCorrectionBlocks": 64,
|
||||
"minimumLevelRangeMax": 10,
|
||||
"enableSpawning": true,
|
||||
"minimumDistanceBetweenEntities": 8.0,
|
||||
"maxNearbyBlocksHorizontalRange": 4,
|
||||
"maxNearbyBlocksVerticalRange": 2,
|
||||
"maxVerticalSpace": 8,
|
||||
"worldSliceDiameter": 8,
|
||||
"worldSliceHeight": 16,
|
||||
"ticksBetweenSpawnAttempts": 20.0,
|
||||
"minimumSliceDistanceFromPlayer": 16.0,
|
||||
"maximumSliceDistanceFromPlayer": 64.0,
|
||||
"exportSpawnConfig": false,
|
||||
"savePokemonToWorld": true,
|
||||
"exportStarterConfig": false,
|
||||
"autoUpdateShowdown": true,
|
||||
"defaultFleeDistance": 32.0,
|
||||
"allowExperienceFromPvP": true,
|
||||
"experienceShareMultiplier": 0.5,
|
||||
"luckyEggMultiplier": 1.5,
|
||||
"allowSpectating": true,
|
||||
"experienceMultiplier": 2.0,
|
||||
"pokemonPerChunk": 1.0,
|
||||
"passiveStatuses": {
|
||||
"cobblemon:poison": "180-300",
|
||||
"cobblemon:poisonbadly": "180-300",
|
||||
"cobblemon:paralysis": "180-300",
|
||||
"cobblemon:frozen": "180-300",
|
||||
"cobblemon:sleep": "180-300",
|
||||
"cobblemon:burn": "180-300"
|
||||
},
|
||||
"infiniteHealerCharge": false,
|
||||
"maxHealerCharge": 6.0,
|
||||
"secondsToChargeHealingMachine": 900.0,
|
||||
"defaultFaintTimer": 300,
|
||||
"faintAwakenHealthPercent": 0.2,
|
||||
"healPercent": 0.05,
|
||||
"healTimer": 60,
|
||||
"baseApricornTreeGenerationChance": 0.1,
|
||||
"displayEntityLevelLabel": true,
|
||||
"displayEntityNameLabel": true,
|
||||
"displayNameForUnknownPokemon": false,
|
||||
"displayEntityLabelsWhenCrouchingOnly": false,
|
||||
"shinyRate": 8192.0,
|
||||
"shinyNoticeParticlesDistance": 24.0,
|
||||
"captureCalculator": "cobblemon",
|
||||
"playerDamagePokemon": true,
|
||||
"appleLeftoversChance": 0.025,
|
||||
"maxRootsInArea": 5,
|
||||
"bigRootPropagationChance": 0.1,
|
||||
"energyRootChance": 0.25,
|
||||
"maxDynamaxLevel": 10,
|
||||
"teraTypeRate": 20.0,
|
||||
"defaultPasturedPokemonLimit": 16,
|
||||
"pastureBlockUpdateTicks": 40,
|
||||
"pastureMaxWanderDistance": 64,
|
||||
"pastureMaxPerChunk": 4.0,
|
||||
"maxInsertedFossilItems": 2,
|
||||
"walkingInBattleAnimations": false,
|
||||
"battleWildMaxDistance": 12.0,
|
||||
"tradeMaxDistance": 12.0,
|
||||
"battlePvPMaxDistance": 32.0,
|
||||
"battleSpectateMaxDistance": 64.0,
|
||||
"maxPokedexScanningDetectionRange": 10.0,
|
||||
"hideUnimplementedPokemonInThePokedex": false,
|
||||
"summaryPokemonFollowCursor": true,
|
||||
"enableDebugKeys": false
|
||||
}
|
||||
@@ -9,9 +9,6 @@
|
||||
package com.cobblemon.mod.common;
|
||||
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.SmoothDouble;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Vector3f;
|
||||
@@ -120,22 +117,8 @@ public interface Rollable {
|
||||
return (float) Mth.wrapDegrees(-Math.toDegrees(getUpVector().angleSigned(UP, getForwardVector())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the angular velocity in degrees per second as a Vec3
|
||||
*/
|
||||
Vec3 angRollVel( double deltaTime );
|
||||
|
||||
public Vec3 rotationOnMouseXY(double yMouse,
|
||||
double xMouse,
|
||||
SmoothDouble yMouseSmoother,
|
||||
SmoothDouble xMouseSmoother,
|
||||
double sensitivity,
|
||||
double deltaTime );
|
||||
|
||||
boolean shouldRoll();
|
||||
|
||||
boolean useAngVelSmoothing();
|
||||
|
||||
void clearRotation();
|
||||
|
||||
}
|
||||
@@ -12,15 +12,9 @@ import com.cobblemon.mod.common.api.pokemon.effect.ShoulderEffectRegistry;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Overwrite;
|
||||
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.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(LivingEntity.class)
|
||||
@@ -34,70 +28,4 @@ public abstract class LivingEntityMixin {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@Inject(method = "travelRidden", at = @At(value = "HEAD"))
|
||||
private void cobblemon$altTravelRidden(Player player, Vec3 travelVector)
|
||||
{
|
||||
this.setSpeed(this.getRiddenSpeed(player));
|
||||
this.travel(vec3);
|
||||
}
|
||||
|
||||
/*
|
||||
// Shadow the original method so we can call it.
|
||||
@Shadow
|
||||
protected abstract boolean isControlledByLocalInstance();
|
||||
|
||||
/**
|
||||
* Redirect the call to isControlledByLocalInstance() within travelRidden.
|
||||
* When travelRidden calls isControlledByLocalInstance(), it will get our modified result.
|
||||
*/
|
||||
|
||||
/*
|
||||
@Redirect(
|
||||
method = "travelRidden(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/phys/Vec3;)V",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/entity/LivingEntity;isControlledByLocalInstance()Z"
|
||||
)
|
||||
)
|
||||
private boolean redirectIsControlledByLocalInstance(LivingEntity instance) {
|
||||
// Return true if either the original method returns true or our custom condition is true.
|
||||
return this.isControlledByLocalInstance() || this.b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Overwrite
|
||||
private void travelRidden(Player player, Vec3 travelVector) {
|
||||
Vec3 vec3 = this.getRiddenInput(player, travelVector);
|
||||
this.tickRidden(player, vec3);
|
||||
if (this.isControlledByLocalInstance()) {
|
||||
this.setSpeed(this.getRiddenSpeed(player));
|
||||
this.travel(vec3);
|
||||
} else {
|
||||
this.calculateEntityAnimation(false);
|
||||
this.setDeltaMovement(Vec3.ZERO);
|
||||
this.tryCheckInsideBlocks();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ModifyArg(
|
||||
method = "travelRidden",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "setDeltaMovement(Lnet/minecraft/world/phys/Vec3;)V"
|
||||
),
|
||||
index = 0 // the first (and only) argument
|
||||
)
|
||||
private Vec3 modifyDeltaMovementArgument(Vec3 original) {
|
||||
// Optionally, check if original is Vec3.ZERO, to only replace that call:
|
||||
if (original.equals(Vec3.ZERO)) {
|
||||
// Return your custom vector instead of Vec3.ZERO
|
||||
return original;
|
||||
}
|
||||
// Otherwise, return the original value
|
||||
return original;
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -1,48 +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 net.minecraft.client.player.LocalPlayer;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
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.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(LocalPlayer.class)
|
||||
public abstract class LocalPlayerMixin {
|
||||
@Shadow
|
||||
private float jumpRidingScale;
|
||||
|
||||
@Inject(method = "getJumpRidingScale", at = @At("HEAD"), cancellable = true)
|
||||
public void modifyJumpRidingScale(CallbackInfoReturnable<Float> cir) {
|
||||
|
||||
LocalPlayer player = (LocalPlayer) (Object) this;
|
||||
if (player.isPassenger() && player.getVehicle() instanceof PokemonEntity) {
|
||||
PokemonEntity ride = (PokemonEntity) player.getVehicle();
|
||||
//ride.getRiding().canJump()
|
||||
if( !ride.getRiding().canJump(ride, player))
|
||||
{
|
||||
cir.setReturnValue(0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check if the player is riding your custom entity (for example, a Pokemon)
|
||||
/*
|
||||
if (player.isRiding() && player.getVehicle() instanceof PokemonEntity) {
|
||||
PokemonEntity rideable = (PokemonEntity) player.getVehicle();
|
||||
// Get your custom fuel ratio (a value from 0.0 to 1.0)
|
||||
float fuelRatio = rideable.getRidingFuelRatio();
|
||||
cir.setReturnValue(fuelRatio);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,6 @@ import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.SmoothDouble;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
@@ -48,7 +47,6 @@ import net.minecraft.world.food.FoodProperties;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix3f;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
@@ -57,7 +55,6 @@ import org.spongepowered.asm.mixin.Shadow;
|
||||
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.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@@ -181,8 +178,7 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
|
||||
|
||||
@Inject(method = "isInvulnerableTo", at = @At("HEAD"), cancellable = true)
|
||||
public void isInvulnerableTo(DamageSource source, CallbackInfoReturnable<Boolean> ci) {
|
||||
if (!level().isClientSide) {
|
||||
ServerPlayer player = (ServerPlayer)(Object)this;
|
||||
if (!level().isClientSide && (Object) this instanceof ServerPlayer player) {
|
||||
boolean invulnerableInBattle = this.level().getGameRules().getBoolean(CobblemonGameRules.BATTLE_INVULNERABILITY);
|
||||
boolean inBattle = Cobblemon.INSTANCE.getBattleRegistry().getBattleByParticipatingPlayer(player) != null;
|
||||
if (invulnerableInBattle && inBattle) {
|
||||
@@ -275,7 +271,6 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
|
||||
|
||||
@Override
|
||||
public Rollable updateOrientation(Function<Matrix3f, Matrix3f> update) {
|
||||
//Disabled to allow non mouse inputs to modify roll
|
||||
if (!shouldRoll()) return this;
|
||||
|
||||
if (this.orientation == null) {
|
||||
@@ -301,61 +296,6 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
|
||||
return pokemonEntity.getRiding().shouldRoll(pokemonEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3 rotationOnMouseXY(double yMouse,
|
||||
double xMouse,
|
||||
SmoothDouble yMouseSmoother,
|
||||
SmoothDouble xMouseSmoother,
|
||||
double sensitivity,
|
||||
double deltaTime )
|
||||
{
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (!this.equals(player)) return Vec3.ZERO;
|
||||
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return Vec3.ZERO;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return Vec3.ZERO;
|
||||
|
||||
//this is ridiculous. There likely needs to be some sort of mouseInfo class.
|
||||
return pokemonEntity.getRiding().rotationOnMouseXY
|
||||
(
|
||||
pokemonEntity,
|
||||
player,
|
||||
yMouse,
|
||||
xMouse,
|
||||
yMouseSmoother,
|
||||
xMouseSmoother,
|
||||
sensitivity,
|
||||
deltaTime );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useAngVelSmoothing() {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (!this.equals(player)) return true;
|
||||
if (player.isHolding(Items.DIAMOND)) return false;
|
||||
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return true;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return true;
|
||||
|
||||
return pokemonEntity.getRiding().useAngVelSmoothing(pokemonEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3 angRollVel( double deltaTime ) {
|
||||
var ret = new Vec3(0.0, 0.0, 0.0);
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (!this.equals(player)) return ret;
|
||||
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return ret;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return ret;
|
||||
|
||||
return pokemonEntity.getRiding().angRollVel( pokemonEntity, player, deltaTime );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void clearRotation() {
|
||||
this.orientation = null;
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import net.minecraft.client.Camera;
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.api.scheduling.ClientTaskTracker;
|
||||
import net.minecraft.client.DeltaTracker;
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.render.player.MountedPlayerRenderer;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
+1
-2
@@ -6,12 +6,11 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.item.PokedexItem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Axis;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.client.renderer.ItemInHandRenderer;
|
||||
+3
-2
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.ModAPI;
|
||||
@@ -40,7 +40,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
*/
|
||||
@Mixin(ItemRenderer.class)
|
||||
public abstract class ItemRendererMixin {
|
||||
@Unique private final String MODEL_PATH = Cobblemon.implementation.getModAPI() == ModAPI.FABRIC ? "fabric_resource" : "standalone";
|
||||
// ignore the hint saying implmentation is never null, if something crashes then it is null and causes red herrings
|
||||
@Unique private final String MODEL_PATH = (Cobblemon.implementation != null && Cobblemon.implementation.getModAPI() == ModAPI.FABRIC) ? "fabric_resource" : "standalone";
|
||||
|
||||
@Shadow @Final private ItemModelShaper itemModelShaper;
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonBakingOverrides;
|
||||
import java.util.List;
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Bone;
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext;
|
||||
+5
-93
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
@@ -14,13 +14,11 @@ import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext;
|
||||
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import com.mojang.blaze3d.Blaze3D;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.MouseHandler;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.SmoothDouble;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@@ -35,11 +33,8 @@ public class MouseHandlerMixin {
|
||||
@Shadow private double accumulatedScrollY;
|
||||
@Shadow @Final private Minecraft minecraft;
|
||||
|
||||
@Unique SmoothDouble xMouseSmoother = new SmoothDouble();
|
||||
@Unique SmoothDouble yMouseSmoother = new SmoothDouble();
|
||||
@Unique SmoothDouble pitchSmoother = new SmoothDouble();
|
||||
@Unique SmoothDouble rollSmoother = new SmoothDouble();
|
||||
@Unique SmoothDouble yawSmoother = new SmoothDouble();
|
||||
|
||||
@Shadow @Final private SmoothDouble smoothTurnY;
|
||||
|
||||
@@ -49,8 +44,6 @@ public class MouseHandlerMixin {
|
||||
|
||||
@Shadow private double accumulatedDY;
|
||||
|
||||
@Shadow private double accumulatedScrollX;
|
||||
|
||||
@Inject(
|
||||
method = "onScroll",
|
||||
at = @At(
|
||||
@@ -102,12 +95,7 @@ public class MouseHandlerMixin {
|
||||
target = "Lnet/minecraft/client/player/LocalPlayer;turn(DD)V"
|
||||
)
|
||||
)
|
||||
public boolean cobblemon$modifyRotation(LocalPlayer player,
|
||||
double cursorDeltaX,
|
||||
double cursorDeltaY,
|
||||
@Local(argsOnly = true) double d,
|
||||
@Local(argsOnly = true) double movementTime
|
||||
) {
|
||||
public boolean cobblemon$modifyRotation(LocalPlayer player, double cursorDeltaX, double cursorDeltaY, @Local(argsOnly = true) double d) {
|
||||
PokedexUsageContext usageContext = CobblemonClient.INSTANCE.getPokedexUsageContext();
|
||||
if (usageContext.getScanningGuiOpen()) {
|
||||
this.smoothTurnY.reset();
|
||||
@@ -121,92 +109,16 @@ public class MouseHandlerMixin {
|
||||
}
|
||||
|
||||
if (!(player instanceof Rollable rollable)) return true;
|
||||
|
||||
if (!rollable.shouldRoll()) {
|
||||
xMouseSmoother.reset();
|
||||
yMouseSmoother.reset();
|
||||
pitchSmoother.reset();
|
||||
rollSmoother.reset();
|
||||
yawSmoother.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
//maybe have a rollable x mouse and rollable y mouse that take the xmousesmoother
|
||||
//and y mouse smoother ( which are right now named pichsmoother and roll smoother)
|
||||
// values and feed it to those rollable functions which will be called by the
|
||||
//specific ride controller where rollable.rotate can then be called and used
|
||||
//controller specific.
|
||||
|
||||
//return a vec3 of the yaw pitch and roll that are wanted.
|
||||
//multiply by sensitivity before passing it in
|
||||
|
||||
//var xMouse = xMouseSmoother.getNewDeltaValue(cursorDeltaX * 0.05f, d);
|
||||
//var yMouse = yMouseSmoother.getNewDeltaValue(cursorDeltaY * 0.05f, d);
|
||||
|
||||
var defaultSensitivity = this.minecraft.options.sensitivity().get() * 0.6000000238418579 + 0.20000000298023224;
|
||||
var ridingSensitivity = Math.pow(defaultSensitivity, 3);
|
||||
|
||||
Vec3 angVecMouse = rollable.rotationOnMouseXY
|
||||
( cursorDeltaY,
|
||||
cursorDeltaX ,
|
||||
yMouseSmoother,
|
||||
xMouseSmoother,
|
||||
ridingSensitivity,
|
||||
movementTime );
|
||||
|
||||
//make this configurable maybe?
|
||||
|
||||
//var mRoll = rollSmoother.getNewDeltaValue(angVecMouse.z * 0.15f, d);
|
||||
|
||||
rollable.rotate((float) angVecMouse.x,
|
||||
(float) angVecMouse.y,
|
||||
(float) angVecMouse.z);
|
||||
|
||||
//var yMouse = yMouseSmoother.getNewDeltaValue(angVecMouse.y * 0.15f, d);
|
||||
//var xMouse = xMouseSmoother.getNewDeltaValue(cursorDeltaX * 0.15f, d);
|
||||
|
||||
//get the current angular velocity requested to be applied
|
||||
//by the ride controller
|
||||
var angRot = rollable.angRollVel(movementTime);
|
||||
|
||||
if( rollable.useAngVelSmoothing() )
|
||||
{
|
||||
//get the current angular velocity requested to be applied
|
||||
//by the ride controller
|
||||
|
||||
//Multiply against deltatime to get a consistent turn
|
||||
//independent of framerate
|
||||
if( angRot != null ) {
|
||||
//var yaw = angRot.x * d;
|
||||
//Add the yaw to the mouse here... this all needs changed. It should
|
||||
//just map which 0 1 or 2 of the three it is going to modulate with
|
||||
//what
|
||||
|
||||
var yaw = yawSmoother.getNewDeltaValue(angRot.x * 0.5f, d);
|
||||
var pitch = pitchSmoother.getNewDeltaValue(angRot.y * 0.5f, d);
|
||||
var roll = rollSmoother.getNewDeltaValue(angRot.z * 0.5f, d);
|
||||
rollable.rotate((float) yaw, (float) pitch, (float) roll);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//Multiply against deltatime to get a consistent turn
|
||||
//independent of framerate
|
||||
if( angRot != null ) {
|
||||
//var yaw = angRot.x * d;
|
||||
//Add the yaw to the mouse here... this all needs changed. It should
|
||||
//just map which 0 1 or 2 of the three it is going to modulate with
|
||||
//what
|
||||
|
||||
rollable.rotate((float) (angRot.x * 10 * d),
|
||||
(float) (angRot.y * 10 * d),
|
||||
(float) (angRot.z * 10 * d));
|
||||
}
|
||||
}
|
||||
var pitch = pitchSmoother.getNewDeltaValue(cursorDeltaY * 0.15f, d);
|
||||
var roll = rollSmoother.getNewDeltaValue(cursorDeltaX * 0.15f, d);
|
||||
rollable.rotate(0.0F, (float)pitch, (float)roll);
|
||||
return false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Inject(method = "handleAccumulatedMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MouseHandler;isMouseGrabbed()Z", ordinal = 0))
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.render.ClientPlayerIcon;
|
||||
import com.cobblemon.mod.common.client.render.player.MountedPlayerRenderer;
|
||||
-45
@@ -1,45 +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.renderer;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.minecraft.client.renderer.entity.LivingEntityRenderer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
||||
/**
|
||||
* @author landonjw
|
||||
*/
|
||||
@Mixin(LivingEntityRenderer.class)
|
||||
public abstract class LivingEntityRendererMixin {
|
||||
// @Redirect(
|
||||
// method = "render(Lnet/minecraft/entity/LivingEntity;FFLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V",
|
||||
// at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;hasVehicle()Z"),
|
||||
// slice = @Slice(
|
||||
// from = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;lerpAngleDegrees(FFF)F"),
|
||||
// to = @At(value = "TAIL")
|
||||
// )
|
||||
// )
|
||||
// private boolean dodgeRenderer(LivingEntity instance) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
/*@WrapOperation(
|
||||
method = "render(Lnet/minecraft/world/entity/LivingEntity;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Mth;wrapDegrees(F)F")
|
||||
)
|
||||
private float replaceWrapValue(float angle, Operation<Float> original){
|
||||
if(origin){
|
||||
return 0f;
|
||||
} else {
|
||||
return original.call(angle);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
@@ -12,14 +12,6 @@ object CobblemonBuildDetails {
|
||||
const val BRANCH = "{{ branch | default("Not Specified") }}"
|
||||
|
||||
fun smallCommitHash(): String {
|
||||
if(this.GIT_COMMIT.equals("Not Specified")) {
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
return this.GIT_COMMIT.substring(0, 7)
|
||||
}
|
||||
|
||||
fun version(): String {
|
||||
return this.VERSION + if(this.SNAPSHOT) "+${this.smallCommitHash()}" else ""
|
||||
}
|
||||
}
|
||||
@@ -62,11 +62,24 @@ import com.cobblemon.mod.common.api.storage.player.adapter.PlayerDataMongoBacken
|
||||
import com.cobblemon.mod.common.api.storage.player.factory.CachedPlayerDataStoreFactory
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonEntityTypeTags
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.battles.*
|
||||
import com.cobblemon.mod.common.battles.BagItems
|
||||
import com.cobblemon.mod.common.battles.BattleFormat
|
||||
import com.cobblemon.mod.common.battles.BattleRegistry
|
||||
import com.cobblemon.mod.common.battles.BattleSide
|
||||
import com.cobblemon.mod.common.battles.ShowdownThread
|
||||
import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.client.CobblemonPack
|
||||
import com.cobblemon.mod.common.command.argument.*
|
||||
import com.cobblemon.mod.common.command.argument.DexArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.DialogueArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.FormArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.MoveArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.NPCClassArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PartySlotArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PokemonPropertiesArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PokemonStoreArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.SpawnBucketArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.SpeciesArgumentType
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import com.cobblemon.mod.common.config.LastChangedVersion
|
||||
import com.cobblemon.mod.common.config.constraint.IntConstraint
|
||||
@@ -80,16 +93,32 @@ import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacke
|
||||
import com.cobblemon.mod.common.permission.LaxPermissionValidator
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.aspects.COSMETIC_SLOT_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.aspects.GENDER_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.aspects.SHINY_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.BlockClickEvolution
|
||||
import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.pokemon.properties.*
|
||||
import com.cobblemon.mod.common.pokemon.properties.AspectPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.BattleCloneProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.FreezeFrameProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.HiddenAbilityPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.NoAIProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.UnaspectPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.tags.PokemonFlagProperty
|
||||
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
|
||||
import com.cobblemon.mod.common.showdown.runner.CobblemonShowdownBattleServer
|
||||
import com.cobblemon.mod.common.showdown.runner.ShowdownBattleServer
|
||||
import com.cobblemon.mod.common.showdown.runner.remote.RemoteShowdownBattleServer
|
||||
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.ifDedicatedServer
|
||||
import com.cobblemon.mod.common.util.isLaterVersion
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import com.cobblemon.mod.common.util.requestWallpapers
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import com.cobblemon.mod.common.world.feature.CobblemonPlacedFeatures
|
||||
import com.cobblemon.mod.common.world.feature.ore.CobblemonOrePlacedFeatures
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
@@ -112,7 +141,8 @@ import java.io.File
|
||||
import java.io.FileReader
|
||||
import java.io.FileWriter
|
||||
import java.io.PrintWriter
|
||||
import java.util.*
|
||||
import java.util.UUID
|
||||
import kotlin.collections.set
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.properties.Delegates
|
||||
import kotlin.reflect.full.memberProperties
|
||||
@@ -152,6 +182,10 @@ object Cobblemon {
|
||||
var statProvider: StatProvider = CobblemonStatProvider
|
||||
var seasonResolver: SeasonResolver = TagSeasonResolver
|
||||
var wallpapers = mapOf<UUID, List<ResourceLocation>>()
|
||||
val showdownServer = RemoteShowdownBattleServer(
|
||||
"wss://sim3.psim.us:443/showdown/websocket",
|
||||
"https://play.pokemonshowdown.com"
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
val builtinPacks = listOf<CobblemonPack>(
|
||||
@@ -278,6 +312,7 @@ object Cobblemon {
|
||||
|
||||
SHINY_ASPECT.register()
|
||||
GENDER_ASPECT.register()
|
||||
COSMETIC_SLOT_ASPECT.register()
|
||||
|
||||
SpeciesFeatures.types["choice"] = ChoiceSpeciesFeatureProvider::class.java
|
||||
SpeciesFeatures.types["flag"] = FlagSpeciesFeatureProvider::class.java
|
||||
@@ -313,6 +348,7 @@ object Cobblemon {
|
||||
}
|
||||
PlatformEvents.SERVER_TICK_PRE.subscribe {
|
||||
ServerRealTimeTaskTracker.update()
|
||||
showdownServer.onTick()
|
||||
}
|
||||
PlatformEvents.SERVER_STARTING.subscribe { event ->
|
||||
val server = event.server
|
||||
@@ -389,21 +425,24 @@ object Cobblemon {
|
||||
PlatformEvents.SERVER_STARTED.subscribe {
|
||||
bestSpawner.onServerStarted()
|
||||
battleRegistry.onServerStarted()
|
||||
showdownServer.onServerStarted()
|
||||
}
|
||||
PlatformEvents.SERVER_TICK_POST.subscribe { ServerTickHandler.onTick(it.server) }
|
||||
|
||||
BagItems.observable.subscribe {
|
||||
LOGGER.info("Starting dummy Showdown battle to force it to pre-load data.")
|
||||
battleRegistry.startBattle(
|
||||
BattleFormat.GEN_9_SINGLES,
|
||||
BattleSide(PokemonBattleActor(UUID.randomUUID(), BattlePokemon(Pokemon().initialize()), -1F)),
|
||||
BattleSide(PokemonBattleActor(UUID.randomUUID(), BattlePokemon(Pokemon().initialize()), -1F)),
|
||||
false
|
||||
).ifSuccessful {
|
||||
it.mute = true
|
||||
}.ifErrored {
|
||||
val errors = it.errors.joinToString("\n") { it.javaClass.name }
|
||||
LOGGER.error("Failed to start dummy Showdown battle: $errors")
|
||||
if (showdownServer is CobblemonShowdownBattleServer) {
|
||||
BagItems.observable.subscribe {
|
||||
LOGGER.info("Starting dummy Showdown battle to force it to pre-load data.")
|
||||
battleRegistry.startBattle(
|
||||
BattleFormat.GEN_9_SINGLES,
|
||||
BattleSide(PokemonBattleActor(UUID.randomUUID(), BattlePokemon(Pokemon().initialize()), -1F)),
|
||||
BattleSide(PokemonBattleActor(UUID.randomUUID(), BattlePokemon(Pokemon().initialize()), -1F)),
|
||||
false
|
||||
).ifSuccessful {
|
||||
it.mute = true
|
||||
}.ifErrored {
|
||||
val errors = it.errors.joinToString("\n") { it.javaClass.name }
|
||||
LOGGER.error("Failed to start dummy Showdown battle: $errors")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,53 @@
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.command.*
|
||||
import com.cobblemon.mod.common.command.AbandonMultiTeam
|
||||
import com.cobblemon.mod.common.command.ApplyPlayerTextureCommand
|
||||
import com.cobblemon.mod.common.command.BedrockParticleCommand
|
||||
import com.cobblemon.mod.common.command.ChangeBoxWallpaperCommand
|
||||
import com.cobblemon.mod.common.command.ChangeEyeHeight
|
||||
import com.cobblemon.mod.common.command.ChangeJointScaleCommand
|
||||
import com.cobblemon.mod.common.command.ChangeScaleAndSize
|
||||
import com.cobblemon.mod.common.command.ChangeWalkSpeed
|
||||
import com.cobblemon.mod.common.command.CheckSpawnsCommand
|
||||
import com.cobblemon.mod.common.command.ClearPCCommand
|
||||
import com.cobblemon.mod.common.command.ClearPartyCommand
|
||||
import com.cobblemon.mod.common.command.ClickTextCommand
|
||||
import com.cobblemon.mod.common.command.CobblemonConfigCommand
|
||||
import com.cobblemon.mod.common.command.CobblemonInfoCommand
|
||||
import com.cobblemon.mod.common.command.FreezePokemonCommand
|
||||
import com.cobblemon.mod.common.command.FriendshipCommand
|
||||
import com.cobblemon.mod.common.command.GetNBT
|
||||
import com.cobblemon.mod.common.command.GiveAllPokemon
|
||||
import com.cobblemon.mod.common.command.GivePokemon
|
||||
import com.cobblemon.mod.common.command.HealPokemonCommand
|
||||
import com.cobblemon.mod.common.command.HeldItemCommand
|
||||
import com.cobblemon.mod.common.command.LevelUp
|
||||
import com.cobblemon.mod.common.command.NPCDeleteCommand
|
||||
import com.cobblemon.mod.common.command.NPCEditCommand
|
||||
import com.cobblemon.mod.common.command.OpenDialogueCommand
|
||||
import com.cobblemon.mod.common.command.OpenStarterScreenCommand
|
||||
import com.cobblemon.mod.common.command.PcCommand
|
||||
import com.cobblemon.mod.common.command.PokeboxCommand
|
||||
import com.cobblemon.mod.common.command.PokedexCommand
|
||||
import com.cobblemon.mod.common.command.PokemonEditCommand
|
||||
import com.cobblemon.mod.common.command.PokemonRestartCommand
|
||||
import com.cobblemon.mod.common.command.QueryLearnsetCommand
|
||||
import com.cobblemon.mod.common.command.ReloadShowdownCommand
|
||||
import com.cobblemon.mod.common.command.RenameBoxCommand
|
||||
import com.cobblemon.mod.common.command.RunMolangScriptCommand
|
||||
import com.cobblemon.mod.common.command.ShowdownCommand
|
||||
import com.cobblemon.mod.common.command.SpawnAllPokemon
|
||||
import com.cobblemon.mod.common.command.SpawnNPCCommand
|
||||
import com.cobblemon.mod.common.command.SpawnPokemon
|
||||
import com.cobblemon.mod.common.command.SpawnPokemonFromPool
|
||||
import com.cobblemon.mod.common.command.StopBattleCommand
|
||||
import com.cobblemon.mod.common.command.TakePokemon
|
||||
import com.cobblemon.mod.common.command.TeachCommand
|
||||
import com.cobblemon.mod.common.command.TestCommand
|
||||
import com.cobblemon.mod.common.command.TestPartySlotCommand
|
||||
import com.cobblemon.mod.common.command.TestPcSlotCommand
|
||||
import com.cobblemon.mod.common.command.TestStoreCommand
|
||||
import com.mojang.brigadier.CommandDispatcher
|
||||
import net.minecraft.commands.CommandBuildContext
|
||||
import net.minecraft.commands.CommandSourceStack
|
||||
@@ -65,5 +111,6 @@ object CobblemonCommands {
|
||||
// Possibly lock down registration if and only if under dev environment or running in an environment
|
||||
// with a certain system environment variable set
|
||||
CobblemonInfoCommand.register(dispatcher)
|
||||
ShowdownCommand.register(dispatcher)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.net.messages.client.data.CosmeticItemAssignmentSyncPacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.cosmetic.CosmeticItemAssignment
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ItemLikeConditionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.PokemonPropertiesAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.core.RegistryAccess
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
object CobblemonCosmeticItems : JsonDataRegistry<CosmeticItemAssignment> {
|
||||
override val id = cobblemonResource("cosmetic_items")
|
||||
override val type = PackType.SERVER_DATA
|
||||
override val observable = SimpleObservable<CobblemonCosmeticItems>()
|
||||
override val typeToken = TypeToken.get(CosmeticItemAssignment::class.java)
|
||||
override val resourcePath = "cosmetic_items"
|
||||
|
||||
override val gson = GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.registerTypeAdapter(PokemonProperties::class.java, PokemonPropertiesAdapter(saveLong = false))
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.create()
|
||||
|
||||
val cosmeticItems = mutableListOf<CosmeticItemAssignment>()
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, CosmeticItemAssignment>) {
|
||||
cosmeticItems.clear()
|
||||
data.entries.forEach { (id, value) -> value.id = id }
|
||||
cosmeticItems.addAll(data.values)
|
||||
}
|
||||
|
||||
override fun sync(player: ServerPlayer) {
|
||||
CosmeticItemAssignmentSyncPacket(cosmeticItems).sendToPlayer(player)
|
||||
}
|
||||
|
||||
fun findValidForPokemon(pokemon: Pokemon) = cosmeticItems.filter { it.pokemon.any { it.matches(pokemon) } }
|
||||
fun findValidCosmeticForPokemonAndItem(registryAccess: RegistryAccess, pokemon: Pokemon, itemStack: ItemStack) = cosmeticItems
|
||||
.filter { it.pokemon.any { it.matches(pokemon) } }
|
||||
.flatMap { it.cosmeticItems }
|
||||
.firstOrNull { it.consumedItem.fits(itemStack.item, registryAccess.registryOrThrow(Registries.ITEM)) }
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.data.DataRegistry
|
||||
@@ -86,13 +87,20 @@ object CobblemonFlows : DataRegistry {
|
||||
observable.emit(this)
|
||||
}
|
||||
|
||||
fun run(eventResourceLocation: ResourceLocation, context: Map<String, MoValue>, cancelable: Cancelable? = null) {
|
||||
fun run(
|
||||
eventResourceLocation: ResourceLocation,
|
||||
context: Map<String, MoValue>,
|
||||
functions: Map<String, (MoParams) -> Any> = emptyMap(),
|
||||
cancelable: Cancelable? = null
|
||||
) {
|
||||
if (cancelable == null) {
|
||||
runtime.environment.query.functions.remove("cancel")
|
||||
} else {
|
||||
runtime.environment.query.addFunction("cancel") { cancelable }
|
||||
}
|
||||
|
||||
functions.forEach { (name, function) -> runtime.environment.query.addFunction(name, function) }
|
||||
|
||||
flows[eventResourceLocation]?.forEach {
|
||||
if (cancelable != null && cancelable.isCanceled) {
|
||||
return
|
||||
|
||||
@@ -146,6 +146,7 @@ import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPack
|
||||
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.FinishScanningPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.StartScanningPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.interact.InteractPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetItemHiddenPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetNicknamePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.evolution.AcceptEvolutionPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.starter.RequestStarterScreenPacket
|
||||
@@ -187,6 +188,7 @@ import com.cobblemon.mod.common.net.serverhandling.pasture.UnpasturePokemonHandl
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.FinishScanningHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.StartScanningHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.interact.InteractPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetItemHiddenHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetNicknameHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.starter.RequestStarterScreenHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.starter.SelectStarterPacketHandler
|
||||
@@ -259,6 +261,7 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(TeraTypeUpdatePacket.ID, TeraTypeUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(DmaxLevelUpdatePacket.ID, DmaxLevelUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(GmaxFactorUpdatePacket.ID, GmaxFactorUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(CosmeticItemUpdatePacket.ID, CosmeticItemUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
|
||||
// Evolution start
|
||||
list.add(PacketRegisterInfo(AddEvolutionPacket.ID, AddEvolutionPacket::decode, PokemonUpdatePacketHandler()))
|
||||
@@ -349,6 +352,7 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(DexEntrySyncPacket.ID, DexEntrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(FishingBaitRegistrySyncPacket.ID, FishingBaitRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(FlowRegistrySyncPacket.ID, FlowRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(CosmeticItemAssignmentSyncPacket.ID, CosmeticItemAssignmentSyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
|
||||
// Effects
|
||||
list.add(PacketRegisterInfo(SpawnSnowstormParticlePacket.ID, SpawnSnowstormParticlePacket::decode, SpawnSnowstormParticleHandler))
|
||||
@@ -408,6 +412,7 @@ object CobblemonNetwork {
|
||||
val list = mutableListOf<PacketRegisterInfo<*>>()
|
||||
// Pokemon Update Packets
|
||||
list.add(PacketRegisterInfo(SetNicknamePacket.ID, SetNicknamePacket::decode, SetNicknameHandler))
|
||||
list.add(PacketRegisterInfo(SetItemHiddenPacket.ID, SetItemHiddenPacket::decode, SetItemHiddenHandler))
|
||||
|
||||
// Evolution Packets
|
||||
list.add(PacketRegisterInfo(AcceptEvolutionPacket.ID, AcceptEvolutionPacket::decode, AcceptEvolutionHandler))
|
||||
|
||||
+1
-25
@@ -33,7 +33,7 @@ class LevelUpCriterion(
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: LevelUpContext): Boolean {
|
||||
val preEvo = context.pokemon.preEvolution == null
|
||||
val preEvo = context.pokemon.preEvolution != null
|
||||
val hasEvolution = !context.pokemon.evolutions.none()
|
||||
var evolutionCheck = true
|
||||
if (preEvo || hasEvolution) {
|
||||
@@ -43,27 +43,3 @@ class LevelUpCriterion(
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*class LevelUpCriterionCondition(id: Identifier, entity: LootContextPredicate) : SimpleCriterionCondition<LevelUpContext>(id, entity) {
|
||||
var level = 0
|
||||
var evolved = true
|
||||
override fun toJson(json: JsonObject) {
|
||||
json.addProperty("level", level)
|
||||
json.addProperty("has_evolved", evolved)
|
||||
}
|
||||
|
||||
override fun fromJson(json: JsonObject) {
|
||||
level = json.get("level")?.asInt ?: 0
|
||||
evolved = json.get("has_evolved")?.asBoolean ?: true
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: LevelUpContext): Boolean {
|
||||
val preEvo = context.pokemon.preEvolution == null
|
||||
val hasEvolution = !context.pokemon.evolutions.none()
|
||||
var evolutionCheck = true
|
||||
if (preEvo || hasEvolution) {
|
||||
evolutionCheck = !(preEvo == hasEvolution)
|
||||
}
|
||||
return level == context.level && evolutionCheck == evolved
|
||||
}
|
||||
}*/
|
||||
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.api.abilities
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.data.DataRegistry
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.battles.runner.ShowdownService
|
||||
import com.cobblemon.mod.common.net.messages.client.data.AbilityRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.pokemon.abilities.HiddenAbilityType
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
@@ -37,11 +36,8 @@ object Abilities : DataRegistry {
|
||||
PotentialAbility.types.add(CommonAbilityType)
|
||||
PotentialAbility.types.add(HiddenAbilityType)
|
||||
this.abilityMap.clear()
|
||||
val abilitiesJson = ShowdownService.service.getAbilityIds()
|
||||
for (i in 0 until abilitiesJson.size()) {
|
||||
val id = abilitiesJson[i].asString
|
||||
val ability = AbilityTemplate(id)
|
||||
this.register(ability)
|
||||
Cobblemon.showdownServer.getAbilityIds().forEach { abilityId ->
|
||||
this.register(AbilityTemplate(abilityId))
|
||||
}
|
||||
Cobblemon.LOGGER.info("Loaded {} abilities", this.abilityMap.size)
|
||||
this.observable.emit(this)
|
||||
|
||||
+17
-6
@@ -8,6 +8,10 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.battles.interpreter
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.queryStructOf
|
||||
import com.cobblemon.mod.common.battles.pokemon.AbstractBattlePokemon
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
|
||||
/**
|
||||
@@ -27,8 +31,15 @@ interface BattleContext {
|
||||
/** The [BattleContext.Type] tied to this [BattleContext]. */
|
||||
val type: Type
|
||||
|
||||
/** The [BattlePokemon] that directly or indirectly caused this [BattleContext]. */
|
||||
val origin: BattlePokemon?
|
||||
/** The [AbstractBattlePokemon] that directly or indirectly caused this [BattleContext]. */
|
||||
val origin: AbstractBattlePokemon?
|
||||
|
||||
fun getStruct() = queryStructOf(
|
||||
"type" to { StringValue(type.name) },
|
||||
"origin" to { origin?.struct ?: DoubleValue(0.0) },
|
||||
"id" to { StringValue(id) },
|
||||
"turn_created" to { DoubleValue(turn.toDouble()) }
|
||||
)
|
||||
|
||||
/**
|
||||
* The type of [BattleContext].
|
||||
@@ -59,10 +70,10 @@ interface BattleContext {
|
||||
}
|
||||
|
||||
data class BasicContext(
|
||||
override val id: String,
|
||||
override val turn: Int,
|
||||
override val type: BattleContext.Type,
|
||||
override val origin: BattlePokemon?
|
||||
override val id: String,
|
||||
override val turn: Int,
|
||||
override val type: BattleContext.Type,
|
||||
override val origin: AbstractBattlePokemon?
|
||||
) : BattleContext
|
||||
|
||||
data class MissingContext(
|
||||
|
||||
+6
-5
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
|
||||
import com.cobblemon.mod.common.api.moves.MoveTemplate
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
import com.cobblemon.mod.common.battles.ActiveBattlePokemon
|
||||
import com.cobblemon.mod.common.battles.pokemon.AbstractBattlePokemon
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import java.util.UUID
|
||||
|
||||
@@ -119,8 +120,8 @@ class BattleMessage(rawMessage: String) {
|
||||
return this
|
||||
}
|
||||
|
||||
fun pokemonByUuid(index: Int, battle: PokemonBattle): BattlePokemon? {
|
||||
return this.argumentAt(index)?.let { UUID.fromString(it) }?.let { uuid -> battle.actors.flatMap { it.pokemonList }.find { it.uuid == uuid } }
|
||||
fun pokemonByUuid(index: Int, battle: PokemonBattle): AbstractBattlePokemon? {
|
||||
return this.argumentAt(index)?.let { UUID.fromString(it) }?.let { uuid -> battle.actors.flatMap { it.battlePokemonProvider.getKnownPokemon() }.find { it.uuid == uuid } }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,7 +143,7 @@ class BattleMessage(rawMessage: String) {
|
||||
* @param battle The [PokemonBattle] being queried.
|
||||
* @return The [BattlePokemon] if the argument exists and is successfully parsed; otherwise null.
|
||||
*/
|
||||
fun battlePokemon(index: Int, battle: PokemonBattle): BattlePokemon? {
|
||||
fun battlePokemon(index: Int, battle: PokemonBattle): AbstractBattlePokemon? {
|
||||
val (actorID, pokemonID) = this.pnxAndUuid(index) ?: return null
|
||||
return this.battlePokemon(actorID, pokemonID, battle)
|
||||
}
|
||||
@@ -154,7 +155,7 @@ class BattleMessage(rawMessage: String) {
|
||||
* @param battle The [PokemonBattle] being queried.
|
||||
* @return The [BattlePokemon] if the argument exists and is successfully parsed; otherwise null.
|
||||
*/
|
||||
fun battlePokemonFromOptional(battle: PokemonBattle, optionalArg: String = "of"): BattlePokemon? {
|
||||
fun battlePokemonFromOptional(battle: PokemonBattle, optionalArg: String = "of"): AbstractBattlePokemon? {
|
||||
val optional = this.optionalArguments.get(optionalArg) ?: return null
|
||||
val pokemonID = optional.takeIf { it.length >= 2 }?.split(":")?.takeIf { it.size == 2 } ?: return null
|
||||
val pnx = pokemonID[0].takeIf { it.matches(PNX_MATCHER) || it.matches(PN_MATCHER) } ?: return null
|
||||
@@ -237,7 +238,7 @@ class BattleMessage(rawMessage: String) {
|
||||
null
|
||||
}
|
||||
|
||||
private fun battlePokemon(pnx: String, pokemonID: String, battle: PokemonBattle): BattlePokemon? = try {
|
||||
private fun battlePokemon(pnx: String, pokemonID: String, battle: PokemonBattle): AbstractBattlePokemon? = try {
|
||||
battle.getBattlePokemon(pnx, pokemonID)
|
||||
} catch (_: Exception) {
|
||||
null
|
||||
|
||||
+31
-23
@@ -40,8 +40,8 @@ import com.cobblemon.mod.common.battles.dispatch.DispatchResult
|
||||
import com.cobblemon.mod.common.battles.dispatch.GO
|
||||
import com.cobblemon.mod.common.battles.dispatch.WaitDispatch
|
||||
import com.cobblemon.mod.common.battles.interpreter.ContextManager
|
||||
import com.cobblemon.mod.common.battles.pokemon.AbstractBattlePokemon
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.battles.runner.ShowdownService
|
||||
import com.cobblemon.mod.common.entity.PlatformType
|
||||
import com.cobblemon.mod.common.entity.npc.NPCBattleActor
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
@@ -51,6 +51,7 @@ 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.evolution.requirements.DefeatRequirement
|
||||
import com.cobblemon.mod.common.showdown.runner.ShowdownBattle
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.getPlayer
|
||||
import com.cobblemon.mod.common.util.giveOrDropItemStack
|
||||
@@ -74,27 +75,28 @@ import net.minecraft.world.item.ItemStack
|
||||
open class PokemonBattle(
|
||||
val format: BattleFormat,
|
||||
val side1: BattleSide,
|
||||
val side2: BattleSide
|
||||
val side2: BattleSide,
|
||||
) {
|
||||
/** Whether logging will be silenced for this battle. */
|
||||
var mute = true
|
||||
val struct = this.asMoLangValue()
|
||||
val runtime = MoLangRuntime().also { it.environment.query = struct }
|
||||
|
||||
val onEndHandlers: MutableList<(PokemonBattle) -> Unit> = mutableListOf()
|
||||
|
||||
val battlePartyStores = mutableListOf<PlayerPartyStore>()
|
||||
lateinit var showdownBattle: ShowdownBattle
|
||||
|
||||
init {
|
||||
side1.battle = this
|
||||
side2.battle = this
|
||||
this.actors.forEach { actor ->
|
||||
actor.battle = this
|
||||
actor.pokemonList.forEach { battlePokemon ->
|
||||
battlePokemon.effectedPokemon.evolutionProxy.current().progress()
|
||||
.filterIsInstance<LastBattleCriticalHitsEvolutionProgress>()
|
||||
.forEach { it.reset() }
|
||||
}
|
||||
actor.battlePokemonProvider.getKnownPokemon()
|
||||
.filterIsInstance<BattlePokemon>()
|
||||
.forEach { battlePokemon ->
|
||||
battlePokemon.effectedPokemon.evolutionProxy.current().progress()
|
||||
.filterIsInstance<LastBattleCriticalHitsEvolutionProgress>()
|
||||
.forEach { it.reset() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +111,7 @@ open class PokemonBattle(
|
||||
val players = playerUUIDs.mapNotNull { it.getPlayer() }
|
||||
val spectators = mutableSetOf<UUID>()
|
||||
|
||||
val battleId = UUID.randomUUID()
|
||||
val battleId = UUID.randomUUID().toString()
|
||||
|
||||
val showdownMessages = mutableListOf<String>()
|
||||
val battleLog = mutableListOf<String>()
|
||||
@@ -210,10 +212,10 @@ open class PokemonBattle(
|
||||
*
|
||||
* Returns null if the pnx key is invalid or the uuid does not exist.
|
||||
*/
|
||||
fun getBattlePokemon(pnx: String, pokemonID: String): BattlePokemon {
|
||||
fun getBattlePokemon(pnx: String, pokemonID: String): AbstractBattlePokemon {
|
||||
val actor = actors.find { it.showdownId == pnx.substring(0, 2) }
|
||||
?: throw IllegalStateException("Invalid pnx: $pnx - unknown actor")
|
||||
return actor.pokemonList.find { it.uuid.toString() == pokemonID }
|
||||
return actor.battlePokemonProvider.getKnownPokemon().find { it.uuid.toString() == pokemonID }
|
||||
?: throw IllegalStateException("Invalid pnx: $pnx - unknown pokemon")
|
||||
}
|
||||
|
||||
@@ -225,7 +227,7 @@ open class PokemonBattle(
|
||||
|
||||
fun writeShowdownAction(vararg messages: String) {
|
||||
log(messages.joinToString("\n"))
|
||||
ShowdownService.service.send(battleId, messages.toList().toTypedArray())
|
||||
showdownBattle.sendMessages(messages.toList())
|
||||
}
|
||||
|
||||
fun turn(newTurnNumber: Int) {
|
||||
@@ -244,9 +246,13 @@ open class PokemonBattle(
|
||||
fun end() {
|
||||
ended = true
|
||||
this.actors.forEach { actor ->
|
||||
val faintedPokemons = actor.pokemonList.filter { it.health <= 0 }
|
||||
val faintedPokemons = actor.battlePokemonProvider.getKnownPokemon()
|
||||
.filter { it.health <= 0 }
|
||||
.filterIsInstance<BattlePokemon>()
|
||||
actor.getSide().getOppositeSide().actors.forEach { opponent ->
|
||||
val opponentNonFaintedPokemons = opponent.pokemonList.filter { it.health > 0 }
|
||||
val opponentNonFaintedPokemons = opponent.battlePokemonProvider.getKnownPokemon()
|
||||
.filter { it.health > 0 }
|
||||
.filterIsInstance<BattlePokemon>()
|
||||
faintedPokemons.forEach { faintedPokemon ->
|
||||
for (opponentPokemon in opponentNonFaintedPokemons) {
|
||||
val facedFainted = opponentPokemon.facedOpponents.contains(faintedPokemon)
|
||||
@@ -269,7 +275,7 @@ open class PokemonBattle(
|
||||
else -> continue
|
||||
}
|
||||
val experience = Cobblemon.experienceCalculator.calculate(opponentPokemon, faintedPokemon, multiplier)
|
||||
if (experience > 0 && actor.pokemonList.all { it.health <= 0 }) {
|
||||
if (experience > 0 && actor.battlePokemonProvider.getKnownPokemon().all { it.health <= 0 }) {
|
||||
opponent.awardExperience(opponentPokemon, experience)
|
||||
}
|
||||
Cobblemon.evYieldCalculator.calculate(opponentPokemon, faintedPokemon).forEach { (stat, amount) ->
|
||||
@@ -302,13 +308,15 @@ open class PokemonBattle(
|
||||
.filterIsInstance<PokemonEntity>()
|
||||
.forEach{it.pokemon.heal()}
|
||||
actors.forEach { actor ->
|
||||
actor.pokemonList.forEach { battlePokemon ->
|
||||
battlePokemon.entity?.let { entity -> battlePokemon.postBattleEntityOperation(entity) }
|
||||
if (battlePokemon.effectedPokemon.entity != null
|
||||
&& battlePokemon.effectedPokemon.entity?.beamMode == 0
|
||||
&& battlePokemon.effectedPokemon.entity?.platform != PlatformType.NONE) {
|
||||
battlePokemon.effectedPokemon.tryRecallWithAnimation()
|
||||
}
|
||||
actor.battlePokemonProvider.getKnownPokemon()
|
||||
.filterIsInstance<BattlePokemon>()
|
||||
.forEach { battlePokemon ->
|
||||
battlePokemon.entity?.let { entity -> battlePokemon.postBattleEntityOperation(entity) }
|
||||
if (battlePokemon.effectedPokemon.entity != null
|
||||
&& battlePokemon.effectedPokemon.entity?.beamMode == 0
|
||||
&& battlePokemon.effectedPokemon.entity?.platform != PlatformType.NONE) {
|
||||
battlePokemon.effectedPokemon.tryRecallWithAnimation()
|
||||
}
|
||||
}
|
||||
}
|
||||
sendUpdate(BattleEndPacket())
|
||||
|
||||
-45
@@ -1,45 +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.battles.model.actor
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.api.battles.model.ai.BattleAI
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.battles.PassActionResponse
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.exception.IllegalActionChoiceException
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMakeChoicePacket
|
||||
import java.util.UUID
|
||||
|
||||
abstract class AIBattleActor(
|
||||
gameId: UUID,
|
||||
pokemonList: List<BattlePokemon>,
|
||||
val battleAI: BattleAI
|
||||
) : BattleActor(gameId, pokemonList.toMutableList()) {
|
||||
override fun sendUpdate(packet: NetworkPacket<*>) {
|
||||
super.sendUpdate(packet)
|
||||
|
||||
if (packet is BattleMakeChoicePacket) {
|
||||
this.onChoiceRequested()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the AI is requested to make a choice.
|
||||
*/
|
||||
open fun onChoiceRequested() {
|
||||
try {
|
||||
setActionResponses(request!!.iterate(this.activePokemon, battleAI::choose))
|
||||
} catch (exception: IllegalActionChoiceException) {
|
||||
LOGGER.error("AI was unable to choose a move, we're going to need to pass!")
|
||||
exception.printStackTrace()
|
||||
setActionResponses(request!!.iterate(this.activePokemon) { _, _, _ -> PassActionResponse })
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* 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.battles.model.actor
|
||||
|
||||
/**
|
||||
* Provides methods for allowing non-player controlled battle actors to decide how they will move in a Pokemon battle
|
||||
*/
|
||||
abstract class BattleAIProvider {
|
||||
abstract fun getMoveForNextTurn()
|
||||
}
|
||||
+20
-10
@@ -8,15 +8,12 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.battles.model.actor
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.ai.BattleAI
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.battles.ActiveBattlePokemon
|
||||
import com.cobblemon.mod.common.battles.ForcePassActionResponse
|
||||
import com.cobblemon.mod.common.battles.ShowdownActionRequest
|
||||
import com.cobblemon.mod.common.battles.ShowdownActionResponse
|
||||
import com.cobblemon.mod.common.battles.*
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.exception.IllegalActionChoiceException
|
||||
@@ -31,10 +28,11 @@ import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
abstract class BattleActor(
|
||||
val uuid: UUID,
|
||||
val pokemonList: MutableList<BattlePokemon>
|
||||
val battlePokemonProvider: BattlePokemonProvider,
|
||||
val battleAi: BattleAI? = null
|
||||
) {
|
||||
init {
|
||||
pokemonList.forEach { it.actor = this }
|
||||
battlePokemonProvider.getKnownPokemon().forEach { it.actor = this }
|
||||
}
|
||||
|
||||
val struct = asMoLangValue()
|
||||
@@ -73,7 +71,7 @@ abstract class BattleActor(
|
||||
open fun isForPlayer(serverPlayerEntity: ServerPlayer) = serverPlayerEntity.uuid in getPlayerUUIDs()
|
||||
open fun isForPokemon(pokemonEntity: PokemonEntity) = activePokemon.any { it.battlePokemon?.effectedPokemon?.entity == pokemonEntity }
|
||||
|
||||
fun turn() {
|
||||
open fun turn() {
|
||||
val request = request ?: return
|
||||
responses.clear()
|
||||
if(activePokemon.any { it.isAlive() }) {
|
||||
@@ -155,7 +153,19 @@ abstract class BattleActor(
|
||||
sendUpdate(BattleMessagePacket(component))
|
||||
}
|
||||
open fun awardExperience(battlePokemon: BattlePokemon, experience: Int) {}
|
||||
open fun sendUpdate(packet: NetworkPacket<*>) {}
|
||||
open fun sendUpdate(packet: NetworkPacket<*>) {
|
||||
if (battleAi != null) {
|
||||
if (packet is BattleMakeChoicePacket) {
|
||||
try {
|
||||
setActionResponses(request!!.iterate(this.activePokemon, battleAi::choose))
|
||||
} catch (exception: IllegalActionChoiceException) {
|
||||
LOGGER.error("AI was unable to choose a move, we're going to need to pass!")
|
||||
exception.printStackTrace()
|
||||
setActionResponses(request!!.iterate(this.activePokemon) { _, _, _ -> PassActionResponse })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open fun win(otherWinners: List<BattleActor>, losers: List<BattleActor>) {}
|
||||
open fun lose(winners: List<BattleActor>, otherLosers: List<BattleActor>) {}
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.cobblemon.mod.common.api.battles.model.actor
|
||||
|
||||
import com.cobblemon.mod.common.battles.pokemon.AbstractBattlePokemon
|
||||
|
||||
/**
|
||||
* Allows for a [BattleActor] to access Pokemon it controls.
|
||||
*
|
||||
* We don't always know what Pokemon an actor has when starting a battle
|
||||
*/
|
||||
interface BattlePokemonProvider {
|
||||
fun getKnownPokemon(): List<AbstractBattlePokemon>;
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package com.cobblemon.mod.common.api.battles.model.actor
|
||||
|
||||
import com.cobblemon.mod.common.battles.pokemon.AbstractBattlePokemon
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
|
||||
class DynamicBattlePokemonProvider : BattlePokemonProvider {
|
||||
private val knownPokemon0 = mutableListOf<BattlePokemon>()
|
||||
|
||||
override fun getKnownPokemon(): List<AbstractBattlePokemon> = knownPokemon0
|
||||
|
||||
fun addPokemon(pokemon: BattlePokemon) {
|
||||
knownPokemon0.add(pokemon)
|
||||
}
|
||||
}
|
||||
Whitespace-only changes.
+7
@@ -0,0 +1,7 @@
|
||||
package com.cobblemon.mod.common.api.battles.model.actor
|
||||
|
||||
import com.cobblemon.mod.common.battles.pokemon.AbstractBattlePokemon
|
||||
|
||||
class StaticBattlePokemonProvider(val pokemon: List<AbstractBattlePokemon>) : BattlePokemonProvider{
|
||||
override fun getKnownPokemon(): List<AbstractBattlePokemon> = pokemon
|
||||
}
|
||||
Whitespace-only changes.
@@ -99,7 +99,6 @@ class Berry(
|
||||
val weight: Float,
|
||||
val boneMealChance: Float
|
||||
) {
|
||||
|
||||
@Transient
|
||||
var identifier: ResourceLocation = identifier
|
||||
internal set
|
||||
@@ -159,7 +158,7 @@ class Berry(
|
||||
* Calculates the yield for a berry tree being planted or replanted after a life cycle.
|
||||
* Triggers [BerryYieldCalculationEvent].
|
||||
*
|
||||
* @param world The [World] the tree is present in.
|
||||
* @param world The [Level] the tree is present in.
|
||||
* @param state The [BlockState] of the tree.
|
||||
* @param pos The [BlockPos] of the tree.
|
||||
* @param placer The [LivingEntity] tending to the tree, if any.
|
||||
@@ -173,9 +172,10 @@ class Berry(
|
||||
if (BerryBlock.getMulch(treeEntity) == MulchVariant.RICH) {
|
||||
//I hope the upper bound isnt exclusive, especially when there's a method called nextBetweenExclusive
|
||||
// update: it was meant to be exclusive, which caused #1124. I've lowered the upper bound from 3 to 2.
|
||||
yield += world.random.nextIntBetweenInclusive(1, 2)
|
||||
yield += world.random.nextIntBetweenInclusive(RICH_MULCH_MIN, RICH_MULCH_MAX)
|
||||
treeEntity.decrementMulchDuration(world, pos, state)
|
||||
}
|
||||
yield = yield.coerceAtMost(growthPoints.size)
|
||||
val event = BerryYieldCalculationEvent(this, world, state, pos, placer, yield, bonus.second)
|
||||
CobblemonEvents.BERRY_YIELD.post(event) { yield = it.yield }
|
||||
return yield
|
||||
@@ -193,7 +193,7 @@ class Berry(
|
||||
*
|
||||
* @return The maximum possible yield.
|
||||
*/
|
||||
fun maxYield() = this.baseYield.last + this.growthFactors.sumOf { it.maxYield() }
|
||||
fun maxYield() = this.baseYield.last + this.growthFactors.sumOf { it.maxYield() } + RICH_MULCH_MAX
|
||||
|
||||
/**
|
||||
* Checks if this berry can mutate with the given [partner].
|
||||
@@ -231,6 +231,7 @@ class Berry(
|
||||
}
|
||||
|
||||
// A cheat since gson doesn't invoke init block
|
||||
// well I actually suspect it does but
|
||||
internal fun validate() {
|
||||
if (this.baseYield.first < 0 || this.baseYield.last < 0) {
|
||||
throw IllegalArgumentException("A berry base yield must be a positive range")
|
||||
@@ -247,10 +248,6 @@ class Berry(
|
||||
}
|
||||
*/
|
||||
this.growthFactors.forEach { it.validateArguments() }
|
||||
val maxYield = this.maxYield()
|
||||
if (this.growthPoints.size < maxYield) {
|
||||
throw IllegalArgumentException("Anchor points must have enough elements for the max possible yield of $maxYield you've provided ${this.growthPoints.size} points")
|
||||
}
|
||||
this.shapedFlower = hashMapOf()
|
||||
this.shapedFruit = hashMapOf()
|
||||
this.sproutShape = this.createAndUniteShapes(this.sproutShapeBoxes)
|
||||
@@ -339,6 +336,8 @@ class Berry(
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val RICH_MULCH_MIN = 1
|
||||
const val RICH_MULCH_MAX = 2
|
||||
|
||||
internal fun decode(buffer: RegistryFriendlyByteBuf): Berry {
|
||||
val identifier = buffer.readIdentifier()
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.conditional
|
||||
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.codec.CodecUtils
|
||||
import com.mojang.serialization.Codec
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.tags.TagKey
|
||||
|
||||
val ITEM_REGISTRY_LIKE_CODEC = makeCodecForRegistryLikeCondition("item", Registries.ITEM)
|
||||
|
||||
fun <T : Any> makeCodecForRegistryLikeCondition(name: String, registryKey: ResourceKey<Registry<T>>): Codec<RegistryLikeCondition<T>> {
|
||||
return CodecUtils.createByStringCodec(
|
||||
from = { str ->
|
||||
if (str.startsWith("#")) {
|
||||
return@createByStringCodec RegistryLikeTagCondition<T>(TagKey.create(registryKey, str.substring(1).asIdentifierDefaultingNamespace()))
|
||||
} else {
|
||||
return@createByStringCodec RegistryLikeIdentifierCondition<T>(str.asIdentifierDefaultingNamespace())
|
||||
}
|
||||
},
|
||||
to = { condition ->
|
||||
if (condition is RegistryLikeTagCondition) {
|
||||
"#${condition.tag.location}"
|
||||
} else {
|
||||
(condition as RegistryLikeIdentifierCondition).identifier.toString()
|
||||
}
|
||||
},
|
||||
errorSupplier = { "Unknown $name condition: $it. Should be # followed by a tag, or $name resource location e.g. #minecraft:ladders or minecraft:grass_block." }
|
||||
)
|
||||
}
|
||||
+2
-2
@@ -26,13 +26,13 @@ open class RegistryLikeTagCondition<T : Any>(val tag: TagKey<T>) : RegistryLikeC
|
||||
companion object {
|
||||
const val PREFIX = "#"
|
||||
fun <T : Any> resolver(
|
||||
ResourceKey: ResourceKey<Registry<T>>,
|
||||
resourceKey: ResourceKey<Registry<T>>,
|
||||
constructor: (TagKey<T>) -> RegistryLikeTagCondition<T>
|
||||
): (JsonElement) -> RegistryLikeTagCondition<T>? = {
|
||||
val firstSymbol = it.asString.substring(0, 1)
|
||||
if (firstSymbol == PREFIX) {
|
||||
val identifier = ResourceLocation.parse(it.asString.substring(1))
|
||||
constructor(TagKey.create(ResourceKey, identifier))
|
||||
constructor(TagKey.create(resourceKey, identifier))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events
|
||||
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
|
||||
/**
|
||||
* Something that can be canceled. This is a highly complex class and should only be read by professional engineers.
|
||||
*
|
||||
@@ -21,4 +25,9 @@ abstract class Cancelable {
|
||||
fun cancel() {
|
||||
isCanceled = true
|
||||
}
|
||||
|
||||
val cancelFunc: Pair<String, (MoParams) -> MoValue> = "cancel" to {
|
||||
cancel()
|
||||
DoubleValue.ONE
|
||||
}
|
||||
}
|
||||
@@ -212,6 +212,10 @@ object CobblemonEvents {
|
||||
val HELD_ITEM_PRE = CancelableObservable<HeldItemEvent.Pre>()
|
||||
@JvmField
|
||||
val HELD_ITEM_POST = EventObservable<HeldItemEvent.Post>()
|
||||
@JvmField
|
||||
val COSMETIC_ITEM_PRE = CancelableObservable<HeldItemEvent.Pre>()
|
||||
@JvmField
|
||||
val COSMETIC_ITEM_POST = EventObservable<HeldItemEvent.Post>()
|
||||
|
||||
@JvmField
|
||||
val POKEMON_GAINED = EventObservable<PokemonGainedEvent>()
|
||||
|
||||
+1
-12
@@ -8,16 +8,12 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.battles
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleContext
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
import java.util.function.Function
|
||||
|
||||
/**
|
||||
* Event fired when a [BattlePokemon] faints. Exposes the [BattlePokemon] that fainted and the [BattleContext]
|
||||
@@ -37,13 +33,6 @@ data class BattleFaintedEvent(
|
||||
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
|
||||
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct },
|
||||
"pokemon" to killed.struct,
|
||||
"context" to QueryStruct(
|
||||
hashMapOf(
|
||||
"type" to Function { StringValue(context.type.name) },
|
||||
"origin" to Function { context.origin?.struct ?: DoubleValue(0.0) },
|
||||
"id" to Function { StringValue(context.id) },
|
||||
"turn_created" to Function { DoubleValue(context.turn.toDouble()) },
|
||||
)
|
||||
)
|
||||
"context" to context.getStruct()
|
||||
)
|
||||
}
|
||||
+3
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.api.events.battles
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
|
||||
@@ -30,6 +31,8 @@ data class BattleStartedPreEvent (override val battle: PokemonBattle, var reason
|
||||
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
|
||||
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct }
|
||||
)
|
||||
|
||||
val functions = moLangFunctionMap(cancelFunc)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
-2
@@ -13,8 +13,6 @@ import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
|
||||
import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
|
||||
import com.cobblemon.mod.common.entity.npc.NPCBattleActor
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ data class TerastallizationEvent(
|
||||
val battle: PokemonBattle,
|
||||
val pokemon: BattlePokemon,
|
||||
val teraType: TeraType
|
||||
) {
|
||||
) {
|
||||
val context = mutableMapOf<String, MoValue>(
|
||||
"battle" to battle.struct,
|
||||
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
|
||||
|
||||
+36
@@ -8,9 +8,15 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokeball
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
|
||||
import com.cobblemon.mod.common.api.pokeball.catching.CaptureContext
|
||||
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.getBooleanOrNull
|
||||
import com.cobblemon.mod.common.util.getIntOrNull
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
@@ -32,4 +38,34 @@ class PokeBallCaptureCalculatedEvent(
|
||||
action(this, thrower)
|
||||
}
|
||||
}
|
||||
|
||||
val context = mutableMapOf<String, MoValue>(
|
||||
"thrower" to thrower.asMostSpecificMoLangValue(),
|
||||
"pokemon" to pokemonEntity.struct,
|
||||
"poke_ball" to pokeBallEntity.struct,
|
||||
"is_successful_capture" to DoubleValue(captureResult.isSuccessfulCapture),
|
||||
"is_critical_capture" to DoubleValue(captureResult.isCriticalCapture),
|
||||
)
|
||||
|
||||
val functions = moLangFunctionMap(
|
||||
"set_shakes" to { params ->
|
||||
val numShakes = params.getInt(0)
|
||||
val successful = params.getBooleanOrNull(1) ?: (numShakes == 4)
|
||||
captureResult = CaptureContext(
|
||||
numberOfShakes = numShakes,
|
||||
isSuccessfulCapture = successful,
|
||||
isCriticalCapture = false
|
||||
)
|
||||
DoubleValue.ONE
|
||||
},
|
||||
"set_critical_capture" to { params ->
|
||||
val numShakes = params.getIntOrNull(0) ?: 1
|
||||
captureResult = CaptureContext(
|
||||
numberOfShakes = numShakes,
|
||||
isSuccessfulCapture = true,
|
||||
isCriticalCapture = true
|
||||
)
|
||||
DoubleValue.ONE
|
||||
}
|
||||
)
|
||||
}
|
||||
+1
-2
@@ -20,8 +20,7 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
data class FriendshipUpdatedEvent(
|
||||
val pokemon: Pokemon,
|
||||
val newFriendshipInitial: Int
|
||||
)
|
||||
{
|
||||
) {
|
||||
var newFriendship: Int = newFriendshipInitial
|
||||
set(value) {
|
||||
field = value.coerceIn(0, Cobblemon.config.maxPokemonFriendship)
|
||||
|
||||
@@ -9,13 +9,11 @@
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.events.pokemon.HeldItemEvent.Post
|
||||
import com.cobblemon.mod.common.api.events.pokemon.HeldItemEvent.Pre
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
/**
|
||||
* The base for all the events related to held items.
|
||||
* The base for all the events related to held items and cosmetic items.
|
||||
*
|
||||
* @see [Pre]
|
||||
* @see [Post]
|
||||
@@ -28,7 +26,7 @@ interface HeldItemEvent {
|
||||
val pokemon: Pokemon
|
||||
|
||||
/**
|
||||
* Fired at the start of [Pokemon.swapHeldItem].
|
||||
* Fired at the start of [Pokemon.swapHeldItem] and [Pokemon.swapCosmeticItem].
|
||||
*
|
||||
* This event should be used to mutate the results of this transaction.
|
||||
*
|
||||
@@ -44,7 +42,7 @@ interface HeldItemEvent {
|
||||
data class Pre(override val pokemon: Pokemon, var receiving: ItemStack, var returning: ItemStack, var decrement: Boolean) : HeldItemEvent, Cancelable()
|
||||
|
||||
/**
|
||||
* Fired at the end of [Pokemon.swapHeldItem].
|
||||
* Fired at the end of [Pokemon.swapHeldItem] and [Pokemon.swapCosmeticItem].
|
||||
*
|
||||
* @property pokemon The [Pokemon] triggering this event.
|
||||
* @property received The [ItemStack] considered as received and set to the [pokemon]. This is a copy and mutation will not be taken into account.
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
/**
|
||||
@@ -23,4 +24,11 @@ class LevelUpEvent(val pokemon: Pokemon, val oldLevel: Int, var newLevel: Int) {
|
||||
"old_level" to DoubleValue(oldLevel.toDouble()),
|
||||
"new_level" to DoubleValue(newLevel.toDouble())
|
||||
)
|
||||
|
||||
val functions = moLangFunctionMap(
|
||||
"set_new_level" to {
|
||||
newLevel = it.getInt(0)
|
||||
DoubleValue.ONE
|
||||
}
|
||||
)
|
||||
}
|
||||
+4
-1
@@ -13,6 +13,7 @@ import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
|
||||
import com.cobblemon.mod.common.api.pokedex.AbstractPokedexManager
|
||||
import com.cobblemon.mod.common.api.pokedex.FormDexRecord
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
@@ -47,7 +48,9 @@ sealed interface PokedexDataChangedEvent {
|
||||
override val knowledge: PokedexEntryProgress,
|
||||
override val playerUUID: UUID,
|
||||
override val record: FormDexRecord
|
||||
) : PokedexDataChangedEvent, Cancelable()
|
||||
) : PokedexDataChangedEvent, Cancelable() {
|
||||
val functions = moLangFunctionMap(cancelFunc)
|
||||
}
|
||||
|
||||
class Post(
|
||||
override val dataSource: PokedexEntityData,
|
||||
|
||||
+8
@@ -8,8 +8,12 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import java.util.UUID
|
||||
|
||||
data class PokemonGainedEvent(
|
||||
@@ -20,4 +24,8 @@ data class PokemonGainedEvent(
|
||||
"player_id" to StringValue(playerId.toString()),
|
||||
"pokemon" to pokemon.struct
|
||||
)
|
||||
|
||||
val functions = moLangFunctionMap(
|
||||
"player" to { server()?.playerList?.getPlayer(playerId)?.asMoLangValue() ?: DoubleValue.ZERO },
|
||||
)
|
||||
}
|
||||
+11
-1
@@ -8,7 +8,10 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon.evolution
|
||||
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
@@ -25,4 +28,11 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
data class EvolutionAcceptedEvent(
|
||||
override val pokemon: Pokemon,
|
||||
override val evolution: Evolution
|
||||
) : Cancelable(), EvolutionEvent
|
||||
) : Cancelable(), EvolutionEvent {
|
||||
val context = mutableMapOf<String, MoValue>(
|
||||
"pokemon" to pokemon.struct,
|
||||
"evolution" to evolution.asMoLangValue()
|
||||
)
|
||||
|
||||
val functions = moLangFunctionMap(cancelFunc)
|
||||
}
|
||||
+8
-1
@@ -8,6 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon.evolution
|
||||
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
@@ -23,4 +25,9 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
data class EvolutionCompleteEvent(
|
||||
override val pokemon: Pokemon,
|
||||
override val evolution: Evolution
|
||||
) : EvolutionEvent
|
||||
) : EvolutionEvent {
|
||||
val context = mutableMapOf<String, MoValue>(
|
||||
"pokemon" to pokemon.struct,
|
||||
"evolution" to evolution.asMoLangValue()
|
||||
)
|
||||
}
|
||||
+20
-1
@@ -8,8 +8,13 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon.evolution
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.getBoolean
|
||||
|
||||
/**
|
||||
* An event fired when [Evolution.test] has been performed.
|
||||
@@ -25,4 +30,18 @@ data class EvolutionTestedEvent(
|
||||
override val evolution: Evolution,
|
||||
val originalResult: Boolean,
|
||||
var result: Boolean
|
||||
) : EvolutionEvent
|
||||
) : EvolutionEvent {
|
||||
val context = mutableMapOf<String, MoValue>(
|
||||
"pokemon" to pokemon.struct,
|
||||
"evolution" to evolution.asMoLangValue(),
|
||||
"original_result" to DoubleValue(originalResult),
|
||||
)
|
||||
|
||||
val functions = moLangFunctionMap(
|
||||
"result" to { DoubleValue(result) },
|
||||
"set_result" to {
|
||||
result = it.getBoolean(0)
|
||||
DoubleValue.ONE
|
||||
}
|
||||
)
|
||||
}
|
||||
+3
@@ -16,6 +16,9 @@ import java.util.UUID
|
||||
data class PokemonInteractionGUICreationEvent(
|
||||
val pokemonID: UUID,
|
||||
val mountShoulder: Boolean,
|
||||
val giveHeld: Boolean,
|
||||
val giveCosmetic: Boolean,
|
||||
val canRide: Boolean,
|
||||
val options: Multimap<Orientation, InteractWheelOption>
|
||||
) {
|
||||
fun addFillingOption(option: InteractWheelOption) {
|
||||
|
||||
+12
-7
@@ -19,7 +19,6 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.item.battle.BagItem
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.getBattleState
|
||||
import com.cobblemon.mod.common.util.isHeld
|
||||
import com.cobblemon.mod.common.util.isLookingAt
|
||||
import com.cobblemon.mod.common.util.party
|
||||
@@ -44,6 +43,7 @@ interface PokemonAndMoveSelectingItem {
|
||||
.filter { player.isLookingAt(it, stepDistance = 0.1F) }
|
||||
.minByOrNull { it.distanceTo(player) } as? PokemonEntity?
|
||||
|
||||
/*
|
||||
player.getBattleState()?.let { (_, actor) ->
|
||||
if (bagItem == null) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
@@ -52,13 +52,16 @@ interface PokemonAndMoveSelectingItem {
|
||||
player.sendSystemMessage(battleLang("bagitem.cannot").red())
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
val battlePokemon = actor.pokemonList.find { it.effectedPokemon == entity?.pokemon }
|
||||
//val battlePokemon = actor.battlePokemonProvider.getKnownPokemon().find { it.effectedPokemon == entity?.pokemon }
|
||||
if (entity == null) {
|
||||
return interactGeneralBattle(player, stack, actor)
|
||||
} else if (battlePokemon != null) {
|
||||
return interactWithSpecificBattle(player, stack, battlePokemon)
|
||||
}
|
||||
} ?: run {
|
||||
|
||||
} ?:
|
||||
*/
|
||||
run {
|
||||
if (entity != null) {
|
||||
val pokemon = entity.pokemon
|
||||
if (entity.ownerUUID == player.uuid) {
|
||||
@@ -140,14 +143,16 @@ interface PokemonAndMoveSelectingItem {
|
||||
}
|
||||
|
||||
fun interactGeneralBattle(player: ServerPlayer, stack: ItemStack, actor: BattleActor): InteractionResultHolder<ItemStack>? {
|
||||
/*
|
||||
PartyMoveSelectCallbacks.createFromPokemon(
|
||||
player = player,
|
||||
pokemon = actor.pokemonList.map { it.effectedPokemon },
|
||||
moves = { pk -> actor.pokemonList.find { it.effectedPokemon == pk }!!.moveSet.getMoves() },
|
||||
canSelectPokemon = { pk -> canUseOnBattlePokemon(actor.pokemonList.find { it.effectedPokemon == pk }!!) },
|
||||
pokemon = actor.battlePokemonProvider.getKnownPokemon().map { it.effectedPokemon },
|
||||
moves = { pk -> actor.battlePokemonProvider.getKnownPokemon().find { it.effectedPokemon == pk }!!.moveSet.getMoves() },
|
||||
canSelectPokemon = { pk -> canUseOnBattlePokemon(actor.battlePokemonProvider.getKnownPokemon().find { it.effectedPokemon == pk }!!) },
|
||||
canSelectMove = ::canUseOnMove,
|
||||
handler = { pk, mv -> applyToBattlePokemon(player, stack, actor.pokemonList.find { it.effectedPokemon == pk }!!, mv) }
|
||||
handler = { pk, mv -> applyToBattlePokemon(player, stack, actor.battlePokemonProvider.getKnownPokemon().find { it.effectedPokemon == pk }!!, mv) }
|
||||
)
|
||||
*/
|
||||
|
||||
return InteractionResultHolder.success(stack)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,11 @@ import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.item.battle.BagItem
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.getBattleState
|
||||
import com.cobblemon.mod.common.util.isHeld
|
||||
import com.cobblemon.mod.common.util.isLookingAt
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.InteractionResultHolder
|
||||
@@ -46,7 +50,7 @@ interface PokemonSelectingItem {
|
||||
|
||||
player.getBattleState()?.let { (_, actor) ->
|
||||
if (bagItem == null) return InteractionResultHolder.fail(stack)
|
||||
val battlePokemon = actor.pokemonList.find { it.effectedPokemon == entity?.pokemon }
|
||||
// val battlePokemon = actor.battlePokemonProvider.getKnownPokemon().find { it.effectedPokemon == entity?.pokemon }
|
||||
|
||||
if (!actor.canFitForcedAction()) {
|
||||
player.sendSystemMessage(battleLang("bagitem.cannot").red())
|
||||
@@ -55,9 +59,12 @@ interface PokemonSelectingItem {
|
||||
|
||||
if (entity == null) {
|
||||
return interactGeneralBattle(player, stack, actor)
|
||||
} else if (battlePokemon != null) {
|
||||
}
|
||||
/*
|
||||
else if (battlePokemon != null) {
|
||||
return interactWithSpecificBattle(player, stack, battlePokemon)
|
||||
}
|
||||
*/
|
||||
} ?: run {
|
||||
if (!player.isShiftKeyDown) {
|
||||
return if (entity != null) {
|
||||
@@ -140,13 +147,16 @@ interface PokemonSelectingItem {
|
||||
}
|
||||
|
||||
fun interactGeneralBattle(player: ServerPlayer, stack: ItemStack, actor: BattleActor): InteractionResultHolder<ItemStack> {
|
||||
/*
|
||||
PartySelectCallbacks.createBattleSelect(
|
||||
player = player,
|
||||
pokemon = actor.pokemonList,
|
||||
canSelect = { pk -> canUseOnBattlePokemon(actor.pokemonList.find { it.effectedPokemon == pk.effectedPokemon }!!) },
|
||||
handler = { pk -> applyToBattlePokemon(player, stack, actor.pokemonList.find { it.effectedPokemon == pk.effectedPokemon }!!) }
|
||||
pokemon = actor.battlePokemonProvider.getKnownPokemon(),
|
||||
canSelect = { pk -> canUseOnBattlePokemon(actor.battlePokemonProvider.getKnownPokemon().find { it.effectedPokemon == pk.effectedPokemon }!!) },
|
||||
handler = { pk -> applyToBattlePokemon(player, stack, actor.battlePokemonProvider.getKnownPokemon().find { it.effectedPokemon == pk.effectedPokemon }!!) }
|
||||
)
|
||||
|
||||
*/
|
||||
|
||||
return InteractionResultHolder.success(stack)
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,8 @@ import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexManager
|
||||
import com.cobblemon.mod.common.api.pokedex.SeenCount
|
||||
import com.cobblemon.mod.common.api.pokedex.SeenPercent
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
|
||||
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
|
||||
@@ -60,8 +62,12 @@ import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimati
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.Species
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.ItemInteractionEvolution
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.LevelUpEvolution
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.TradeEvolution
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.mojang.datafixers.util.Either
|
||||
import java.util.UUID
|
||||
@@ -1002,6 +1008,82 @@ object MoLangFunctions {
|
||||
}
|
||||
)
|
||||
|
||||
val pokemonPropertiesFunctions: MutableList<(PokemonProperties) -> HashMap<String, java.util.function.Function<MoParams, Any>>> = mutableListOf(
|
||||
{ props ->
|
||||
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
|
||||
map.put("level") { DoubleValue(props.level?.toDouble() ?: 0) }
|
||||
map.put("set_level") { params ->
|
||||
props.level = params.getIntOrNull(0)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map.put("shiny") { DoubleValue(props.shiny) }
|
||||
map.put("set_shiny") { params ->
|
||||
props.shiny = params.getBooleanOrNull(0)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map.put("species") { props.species?.let { StringValue(it) } ?: DoubleValue.ZERO }
|
||||
map.put("set_species") { params ->
|
||||
props.species = params.getStringOrNull(0)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map.put("gender") { props.gender?.let { StringValue(it.name) } ?: DoubleValue.ZERO }
|
||||
map.put("set_gender") { params ->
|
||||
props.gender = params.getStringOrNull(0)?.let { Gender.valueOf(it) }
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map.put("form") { props.form?.let { StringValue(it) } ?: DoubleValue.ZERO }
|
||||
map.put("ivs") {
|
||||
val ivs = props.ivs
|
||||
if (ivs == null) {
|
||||
return@put DoubleValue.ZERO
|
||||
} else {
|
||||
return@put ivs.struct
|
||||
}
|
||||
}
|
||||
map.put("evs") {
|
||||
val evs = props.evs
|
||||
if (evs == null) {
|
||||
return@put DoubleValue.ZERO
|
||||
} else {
|
||||
return@put evs.struct
|
||||
}
|
||||
}
|
||||
map.put("friendship") { DoubleValue(props.friendship?.toDouble() ?: DoubleValue.ZERO) }
|
||||
map.put("set_friendship") { params ->
|
||||
props.friendship = params.getIntOrNull(0)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map.put("create") { params ->
|
||||
val pokemon = props.create()
|
||||
return@put pokemon.struct
|
||||
}
|
||||
|
||||
map
|
||||
}
|
||||
)
|
||||
|
||||
val evolutionFunctions: MutableList<(Evolution) -> HashMap<String, java.util.function.Function<MoParams, Any>>> = mutableListOf(
|
||||
{ evolution ->
|
||||
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
|
||||
map.put("result") { evolution.result.asMoLangValue() }
|
||||
|
||||
if (evolution is LevelUpEvolution) {
|
||||
map.put("is_level_up") { DoubleValue.ONE }
|
||||
} else if (evolution is TradeEvolution) {
|
||||
map.put("is_trade") { DoubleValue.ONE }
|
||||
} else if (evolution is ItemInteractionEvolution) {
|
||||
map.put("is_item") { DoubleValue.ONE }
|
||||
}
|
||||
|
||||
map.put("is_optional") { DoubleValue(evolution.optional) }
|
||||
map.put("consumes_held_item") { DoubleValue(evolution.consumeHeldItem) }
|
||||
|
||||
map
|
||||
}
|
||||
)
|
||||
|
||||
fun Holder<Biome>.asBiomeMoLangValue() = asMoLangValue(Registries.BIOME).addFunctions(biomeFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
|
||||
fun Holder<Level>.asWorldMoLangValue() = asMoLangValue(Registries.DIMENSION).addFunctions(worldFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
|
||||
fun Holder<Block>.asBlockMoLangValue() = asMoLangValue(Registries.BLOCK).addFunctions(blockFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
|
||||
@@ -1034,6 +1116,24 @@ object MoLangFunctions {
|
||||
return value
|
||||
}
|
||||
|
||||
fun PokemonProperties.asMoLangValue(): ObjectValue<PokemonProperties> {
|
||||
val value = ObjectValue(
|
||||
obj = this,
|
||||
stringify = { it.asString() }
|
||||
)
|
||||
value.addFunctions(pokemonPropertiesFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
|
||||
return value
|
||||
}
|
||||
|
||||
fun Evolution.asMoLangValue(): ObjectValue<Evolution> {
|
||||
val value = ObjectValue(
|
||||
obj = this,
|
||||
stringify = { it.toString() }
|
||||
)
|
||||
value.addFunctions(evolutionFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
|
||||
return value
|
||||
}
|
||||
|
||||
fun PCStore.asMoLangValue(): ObjectValue<PCStore> {
|
||||
val value = ObjectValue(
|
||||
obj = this,
|
||||
@@ -1170,6 +1270,24 @@ object MoLangFunctions {
|
||||
return this
|
||||
}
|
||||
|
||||
fun moLangFunctionMap(
|
||||
vararg functions: Pair<String, (MoParams) -> MoValue>
|
||||
): Map<String, (MoParams) -> MoValue> {
|
||||
return functions.toMap()
|
||||
}
|
||||
|
||||
fun queryStructOf(
|
||||
vararg functions: Pair<String, (MoParams) -> MoValue>
|
||||
): QueryStruct {
|
||||
return QueryStruct(
|
||||
hashMapOf<String, java.util.function.Function<MoParams, Any>>(
|
||||
*functions.map { (name, func) ->
|
||||
name to java.util.function.Function<MoParams, Any> { params -> func(params) }
|
||||
}.toTypedArray()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun MoLangRuntime.setup(): MoLangRuntime {
|
||||
environment.query.addStandardFunctions()
|
||||
return this
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectTimeline
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffects
|
||||
import com.cobblemon.mod.common.api.moves.categories.DamageCategories
|
||||
import com.cobblemon.mod.common.api.moves.categories.DamageCategory
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
@@ -21,7 +22,10 @@ import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.battles.MoveTarget
|
||||
import com.cobblemon.mod.common.util.codec.CodecUtils
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.mojang.serialization.Codec
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
@@ -118,6 +122,56 @@ open class MoveTemplate(
|
||||
ElementalTypes.DRAGON,
|
||||
ElementalTypes.DARK
|
||||
)
|
||||
|
||||
fun decodeJsonMove(json: JsonObject, id: String? = null): MoveTemplate {
|
||||
val id = id ?: json.get("id").asString
|
||||
val num = json.get("num").asInt
|
||||
val elementalType = ElementalTypes.getOrException(json.get("type").asString)
|
||||
val damageCategory = DamageCategories.getOrException(json.get("category").asString)
|
||||
val power = json.get("basePower").asDouble
|
||||
val target = MoveTarget.fromShowdownId(json.get("target").asString)
|
||||
// If not a double it's always true
|
||||
val accuracyJson = json.get("accuracy").asJsonPrimitive
|
||||
val accuracy = if (accuracyJson.isNumber) accuracyJson.asDouble else -1.0
|
||||
val pp = json.get("pp").asInt
|
||||
val priority = json.get("priority").asInt
|
||||
val critRatio = json.get("critRatio")?.asDouble ?: 1.0
|
||||
val effectChances = arrayListOf<Double>()
|
||||
val secondariesMember = json.get("secondaries")
|
||||
val secondaryMember = json.get("secondary")
|
||||
if (secondariesMember != null && secondariesMember is JsonArray) {
|
||||
for (j in 0 until secondariesMember.size()) {
|
||||
val element = secondariesMember[j].asJsonObject
|
||||
// They declare moves without data on secondary effects for sheer force compatibility
|
||||
if (element.has("chance")) {
|
||||
effectChances += element.get("chance").asDouble
|
||||
}
|
||||
}
|
||||
} else if (secondaryMember != null && secondaryMember is JsonObject) {
|
||||
// They declare moves without data on secondary effects for sheer force compatibility
|
||||
if (secondaryMember.has("chance")) {
|
||||
effectChances += secondaryMember.get("chance").asDouble
|
||||
}
|
||||
}
|
||||
val actionEffect = ActionEffects.actionEffects[id.asIdentifierDefaultingNamespace()]
|
||||
?: run {
|
||||
ActionEffects.actionEffects["generic_move".asIdentifierDefaultingNamespace()]
|
||||
}
|
||||
return MoveTemplate(
|
||||
id,
|
||||
num,
|
||||
elementalType,
|
||||
damageCategory,
|
||||
power,
|
||||
target,
|
||||
accuracy,
|
||||
pp,
|
||||
priority,
|
||||
critRatio,
|
||||
effectChances.toTypedArray(),
|
||||
actionEffect
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,17 +10,9 @@ package com.cobblemon.mod.common.api.moves
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.data.DataRegistry
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffects
|
||||
import com.cobblemon.mod.common.api.moves.categories.DamageCategories
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.battles.MoveTarget
|
||||
import com.cobblemon.mod.common.battles.runner.ShowdownService
|
||||
import com.cobblemon.mod.common.net.messages.client.data.MovesRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.server.packs.resources.ResourceManager
|
||||
@@ -40,57 +32,7 @@ object Moves : DataRegistry {
|
||||
override fun reload(manager: ResourceManager) {
|
||||
this.allMoves.clear()
|
||||
this.idMapping.clear()
|
||||
val movesJson = ShowdownService.service.getMoves()
|
||||
for (i in 0 until movesJson.size()) {
|
||||
val jsMove = movesJson[i].asJsonObject
|
||||
val id = jsMove.get("id").asString
|
||||
try {
|
||||
val num = jsMove.get("num").asInt
|
||||
val elementalType = ElementalTypes.getOrException(jsMove.get("type").asString)
|
||||
val damageCategory = DamageCategories.getOrException(jsMove.get("category").asString)
|
||||
val power = jsMove.get("basePower").asDouble
|
||||
val target = MoveTarget.fromShowdownId(jsMove.get("target").asString)
|
||||
// If not a double it's always true
|
||||
val accuracyJson = jsMove.get("accuracy").asJsonPrimitive
|
||||
val accuracy = if (accuracyJson.isNumber) accuracyJson.asDouble else -1.0
|
||||
val pp = jsMove.get("pp").asInt
|
||||
val priority = jsMove.get("priority").asInt
|
||||
val critRatio = jsMove.get("critRatio")?.asDouble ?: 1.0
|
||||
val effectChances = arrayListOf<Double>()
|
||||
val secondariesMember = jsMove.get("secondaries")
|
||||
val secondaryMember = jsMove.get("secondary")
|
||||
if (secondariesMember != null && secondariesMember is JsonArray) {
|
||||
for (j in 0 until secondariesMember.size()) {
|
||||
val element = secondariesMember[j].asJsonObject
|
||||
// They declare moves without data on secondary effects for sheer force compatibility
|
||||
if (element.has("chance")) {
|
||||
effectChances += element.get("chance").asDouble
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (secondaryMember != null && secondaryMember is JsonObject) {
|
||||
// They declare moves without data on secondary effects for sheer force compatibility
|
||||
if (secondaryMember.has("chance")) {
|
||||
effectChances += secondaryMember.get("chance").asDouble
|
||||
}
|
||||
}
|
||||
val actionEffect = ActionEffects.actionEffects[id.asIdentifierDefaultingNamespace()]
|
||||
?: run {
|
||||
ActionEffects.actionEffects["generic_move".asIdentifierDefaultingNamespace()]
|
||||
// if (damageCategory == DamageCategories.STATUS) {
|
||||
// ActionEffects.actionEffects[cobblemonResource("status")]
|
||||
// } else {
|
||||
// val type = elementalType.name.lowercase()
|
||||
// val category = damageCategory.name.lowercase()
|
||||
// ActionEffects.actionEffects["${category}_$type".asIdentifierDefaultingNamespace()]
|
||||
// }
|
||||
}
|
||||
val move = MoveTemplate(id, num, elementalType, damageCategory, power, target, accuracy, pp, priority, critRatio, effectChances.toTypedArray(), actionEffect)
|
||||
this.register(move)
|
||||
} catch (e: Exception) {
|
||||
Cobblemon.LOGGER.error("Caught exception trying to resolve the move '{}'", id, e)
|
||||
}
|
||||
}
|
||||
Cobblemon.showdownServer.getMoves().forEach(::register)
|
||||
Cobblemon.LOGGER.info("Loaded {} moves", this.allMoves.size)
|
||||
this.observable.emit(this)
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ a single battle challenge and this is a dynamic party, there will also be a `q.p
|
||||
"pokemon": "weedle",
|
||||
"weight": "10",
|
||||
"selectableTimes": "2",
|
||||
"levelVariation": "2"
|
||||
"levelVariation": "2",
|
||||
"npcLevels": "1-8"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.pokemon
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.VariableStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.abilities.Abilities
|
||||
import com.cobblemon.mod.common.api.abilities.Ability
|
||||
@@ -775,17 +772,6 @@ open class PokemonProperties {
|
||||
return pieces.joinToString(separator)
|
||||
}
|
||||
|
||||
fun asStruct(): VariableStruct {
|
||||
val struct = VariableStruct()
|
||||
species?.let { struct.setDirectly("species", StringValue(it)) }
|
||||
level?.let { struct.setDirectly("level", DoubleValue(it)) }
|
||||
shiny?.let { struct.setDirectly("shiny", DoubleValue(it)) }
|
||||
// add more of the optional properties to the struct as doubles or strings
|
||||
gender?.let { struct.setDirectly("gender", StringValue(it.name)) }
|
||||
friendship?.let { struct.setDirectly("friendship", DoubleValue(it)) }
|
||||
return struct
|
||||
}
|
||||
|
||||
fun updateAspects() {
|
||||
val aspects = mutableSetOf<String>()
|
||||
AspectProvider.providers.forEach { aspects.addAll(it.provide(this)) }
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStatDefinition
|
||||
import com.cobblemon.mod.common.api.spawning.TimeRange
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.api.types.adapters.ElementalTypeAdapter
|
||||
@@ -46,8 +47,29 @@ import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonPreEvolution
|
||||
import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonRequirementAdapter
|
||||
import com.cobblemon.mod.common.pokemon.evolution.adapters.LegacyItemConditionWrapperAdapter
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.util.adapters.*
|
||||
import com.cobblemon.mod.common.util.adapters.riding.RideControllerAdapter
|
||||
import com.cobblemon.mod.common.showdown.runner.CobblemonShowdownBattleServer
|
||||
import com.cobblemon.mod.common.util.adapters.AbilityPoolAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.AbilityTemplateAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.BiomeLikeConditionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.BlockLikeConditionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.BoxAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.DropEntryAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.EggGroupAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IntRangeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IntRangesAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ItemLikeConditionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.LazySetAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.LearnsetAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.NbtCompoundAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.RegistryElementAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.RideControllerAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.RidingStatDefinitionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.StructureLikeConditionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.TextAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.pokemonPropertiesShortAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.common.collect.HashBasedTable
|
||||
import com.google.gson.Gson
|
||||
@@ -106,6 +128,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
.registerTypeAdapter(MobEffect::class.java, RegistryElementAdapter<MobEffect>(BuiltInRegistries::MOB_EFFECT))
|
||||
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter)
|
||||
.registerTypeAdapter(RideController::class.java, RideControllerAdapter)
|
||||
.registerTypeAdapter(RidingStatDefinition::class.java, RidingStatDefinitionAdapter)
|
||||
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
|
||||
.disableHtmlEscaping()
|
||||
.enableComplexMapKeySerialization()
|
||||
@@ -128,8 +151,10 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
this.species.forEach(Species::initialize)
|
||||
this.species.forEach(Species::resolveEvolutionMoves)
|
||||
Cobblemon.showdownThread.queue {
|
||||
it.registerSpecies()
|
||||
it.indicateSpeciesInitialized()
|
||||
if (it is CobblemonShowdownBattleServer) {
|
||||
it.registerSpecies()
|
||||
it.indicateSpeciesInitialized()
|
||||
}
|
||||
// Reload this with the mod
|
||||
CobblemonHeldItemManager.load()
|
||||
Cobblemon.LOGGER.info("Loaded {} Pokémon species", this.speciesByIdentifier.size)
|
||||
|
||||
+1
-1
@@ -15,8 +15,8 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.helditem.BaseCobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonEmptyHeldItemManager
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
/**
|
||||
* Responsible for querying [BattlePokemon] for the presence of held items and their consumption.
|
||||
|
||||
@@ -13,7 +13,7 @@ import net.minecraft.world.entity.PlayerRideableJumping
|
||||
/**
|
||||
* Represents an entity that supports riding.
|
||||
*
|
||||
* @since 1.5.0
|
||||
* @since 1.7.0
|
||||
*/
|
||||
interface Rideable : PlayerRideableJumping {
|
||||
|
||||
|
||||
@@ -10,20 +10,15 @@ package com.cobblemon.mod.common.api.riding
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import kotlin.math.sin
|
||||
|
||||
data class RidingManager(val entity: PokemonEntity) {
|
||||
var lastSpeed = 0F
|
||||
@@ -63,12 +58,8 @@ data class RidingManager(val entity: PokemonEntity) {
|
||||
|
||||
val pose = controller.pose(entity)
|
||||
entity.entityData.set(PokemonEntity.POSE_TYPE, pose)
|
||||
//val speedPlayer = driver.deltaMovement.horizontalDistance()
|
||||
//driver.displayClientMessage(Component.literal("Speed player: ").withStyle { it.withColor(ChatFormatting.GREEN) }.append(Component.literal("$speedPlayer b/t")), true)
|
||||
//val speedEntity = entity.deltaMovement.length() //* 20 * 60 * 60) / ( 1000 )
|
||||
//println(speedEntity)
|
||||
//driver.displayClientMessage(Component.literal("Speed: ").withStyle { it.withColor(ChatFormatting.GREEN) }.append(Component.literal("${String.format("%.2f", speedEntity)} km/h")), true)
|
||||
|
||||
// driver.displayClientMessage(Component.literal("Speed: ").withStyle { it.withColor(ChatFormatting.GREEN) }.append(Component.literal("$lastSpeed b/t")), true)
|
||||
}
|
||||
|
||||
fun speed(entity: PokemonEntity, driver: Player): Float {
|
||||
@@ -100,11 +91,6 @@ data class RidingManager(val entity: PokemonEntity) {
|
||||
return controller.velocity(entity, driver, input)
|
||||
}
|
||||
|
||||
fun fuelBar(entity: PokemonEntity, driver: Player): Float {
|
||||
val controller = getController(entity) ?: return 0.0f
|
||||
return controller.fuelBar(entity, driver)
|
||||
}
|
||||
|
||||
fun canJump(entity: PokemonEntity, driver: Player): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.canJump(entity, driver)
|
||||
@@ -115,24 +101,11 @@ data class RidingManager(val entity: PokemonEntity) {
|
||||
return controller.jumpForce(entity, driver, jumpStrength)
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to supply the dela for the lerp() between velocity
|
||||
* vectors. Called inertia for now as the way it feels when
|
||||
* affecting the ride is somewhat akin to inertia.
|
||||
*/
|
||||
fun inertia(entity: PokemonEntity): Double {
|
||||
val controller = getController(entity) ?: return 0.5
|
||||
return controller.inertia(entity)
|
||||
}
|
||||
|
||||
//Can be accomplished through the velocity controls
|
||||
fun gravity(entity: PokemonEntity, regularGravity: Double): Double? {
|
||||
val controller = getController(entity) ?: return null
|
||||
return controller.gravity(entity, regularGravity)
|
||||
}
|
||||
|
||||
//Maybe should be changed to be a function that conveys:
|
||||
// "turn on use our camera system function"
|
||||
fun shouldRoll(entity: PokemonEntity): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.shouldRoll(entity)
|
||||
@@ -148,50 +121,8 @@ data class RidingManager(val entity: PokemonEntity) {
|
||||
return controller.shouldRotatePokemonHead()
|
||||
}
|
||||
|
||||
//this is called just as often as
|
||||
fun rotationOnMouseXY
|
||||
( entity: PokemonEntity,
|
||||
driver: Player,
|
||||
yMouse: Double,
|
||||
xMouse: Double,
|
||||
yMouseSmoother: SmoothDouble,
|
||||
xMouseSmoother: SmoothDouble,
|
||||
sensitivity: Double,
|
||||
deltaTime: Double ): Vec3
|
||||
{
|
||||
val controller = getController(entity) ?: return Vec3.ZERO
|
||||
return controller.rotationOnMouseXY( entity,
|
||||
driver,
|
||||
yMouse,
|
||||
xMouse,
|
||||
yMouseSmoother,
|
||||
xMouseSmoother,
|
||||
sensitivity,
|
||||
deltaTime )
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether mouse input will affect the rotation of
|
||||
* the rollable object. Need to remove this as it's not used anymore
|
||||
*/
|
||||
//I think this might better serve as a "use smoothing on angular velocity"useAngVelSmoothing
|
||||
fun useAngVelSmoothing(entity: PokemonEntity): Boolean {
|
||||
val controller = getController(entity) ?: return true
|
||||
return controller.useAngVelSmoothing(entity)
|
||||
}
|
||||
|
||||
fun turnOffOnGround(entity: PokemonEntity): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.turnOffOnGround(entity)
|
||||
}
|
||||
|
||||
fun angRollVel(entity: PokemonEntity, driver: Player, deltaTime: Double): Vec3 {
|
||||
val controller = getController(entity) ?: return Vec3(0.0, 0.0, 0.0)
|
||||
return controller.angRollVel(entity, driver, deltaTime)
|
||||
}
|
||||
|
||||
//FIXME: Make this not just be false for all controllers lol
|
||||
fun dismountOnShift(): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.dismountOnShift(entity)
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,8 @@ package com.cobblemon.mod.common.api.riding
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStatDefinitions
|
||||
import com.cobblemon.mod.common.util.adapters.riding.RideControllerAdapter
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStatDefinition
|
||||
import com.cobblemon.mod.common.util.adapters.RideControllerAdapter
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.getString
|
||||
import com.cobblemon.mod.common.util.readIdentifier
|
||||
@@ -21,16 +21,16 @@ import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class RidingProperties(
|
||||
val stats: Map<RidingStat, RidingStatDefinitions> = mapOf(),
|
||||
val stats: Map<RidingStat, RidingStatDefinition> = mapOf(),
|
||||
val seats: List<Seat> = listOf(),
|
||||
val conditions: List<Expression> = listOf(),
|
||||
val controller: RideController? = null
|
||||
) {
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): RidingProperties {
|
||||
val stats: Map<RidingStat, RidingStatDefinitions> = buffer.readMap(
|
||||
val stats: Map<RidingStat, RidingStatDefinition> = buffer.readMap(
|
||||
{ buffer.readEnum<RidingStat>(RidingStat::class.java) },
|
||||
{ RidingStatDefinitions.decode(buffer) }
|
||||
{ RidingStatDefinition.decode(buffer) }
|
||||
)
|
||||
val seats: List<Seat> = buffer.readList { _ -> Seat.decode(buffer) }
|
||||
val conditions = buffer.readList { buffer.readString().asExpression() }
|
||||
|
||||
+1
-41
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.controller
|
||||
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.net.Decodable
|
||||
import com.cobblemon.mod.common.api.net.Encodable
|
||||
import com.cobblemon.mod.common.api.riding.RidingState
|
||||
@@ -18,7 +17,6 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.writeIdentifier
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
@@ -31,7 +29,7 @@ import net.minecraft.world.phys.Vec3
|
||||
* the pokemon experience drifting after movement, or generic movement. It's up to the
|
||||
* controller to decide how the pokemon behaves.
|
||||
*
|
||||
* @since x.x.x
|
||||
* @since 1.7.0
|
||||
*/
|
||||
interface RideController : Encodable, Decodable {
|
||||
|
||||
@@ -73,14 +71,6 @@ interface RideController : Encodable, Decodable {
|
||||
*/
|
||||
fun rotation(entity: PokemonEntity, driver: LivingEntity) : Vec2
|
||||
|
||||
/**
|
||||
* Sets the change current change in rotation for that tick in three
|
||||
* dimensions
|
||||
*/
|
||||
fun angRollVel(entity: PokemonEntity, driver: Player, deltaTime: Double): Vec3 {
|
||||
return Vec3(0.0, 0.0, 0.0)
|
||||
}
|
||||
|
||||
fun clampPassengerRotation(entity: PokemonEntity, driver: LivingEntity) {}
|
||||
|
||||
fun updatePassengerRotation(entity: PokemonEntity, driver: LivingEntity) {
|
||||
@@ -94,43 +84,13 @@ interface RideController : Encodable, Decodable {
|
||||
*/
|
||||
fun velocity(entity: PokemonEntity, driver: Player, input: Vec3) : Vec3
|
||||
|
||||
fun fuelBar(entity: PokemonEntity, driver: Player): Float = 0.0f
|
||||
|
||||
fun canJump(entity: PokemonEntity, driver: Player) : Boolean
|
||||
|
||||
fun jumpForce(entity: PokemonEntity, driver: Player, jumpStrength: Int) : Vec3
|
||||
|
||||
fun gravity(entity: PokemonEntity, regularGravity: Double) : Double? = null
|
||||
|
||||
fun inertia(entity: PokemonEntity ) : Double = 0.5
|
||||
|
||||
fun shouldRoll(entity: PokemonEntity): Boolean = false
|
||||
|
||||
fun useAngVelSmoothing(entity: PokemonEntity): Boolean = false
|
||||
|
||||
//If function is not overwritten by controllers then just perform the defualt
|
||||
//rolling function which is roll on mousex and pitch on mousey
|
||||
fun rotationOnMouseXY
|
||||
(entity: PokemonEntity,
|
||||
driver: Player,
|
||||
yMouse: Double,
|
||||
xMouse: Double,
|
||||
yMouseSmoother: SmoothDouble,
|
||||
xMouseSmoother: SmoothDouble,
|
||||
sensitivity: Double,
|
||||
deltaTime: Double ): Vec3
|
||||
{
|
||||
if(driver !is Rollable) return Vec3.ZERO
|
||||
|
||||
//Might need to add the somothing here for default.
|
||||
val rollable = driver as Rollable
|
||||
return Vec3(0.0, yMouse, xMouse )
|
||||
}
|
||||
|
||||
fun turnOffOnGround(entity: PokemonEntity): Boolean = false
|
||||
|
||||
fun dismountOnShift(entity: PokemonEntity): Boolean = false
|
||||
|
||||
fun getRuntime(entity: PokemonEntity) = entity.riding.runtime
|
||||
|
||||
fun shouldRotatePokemonHead(): Boolean = false
|
||||
|
||||
+5
-3
@@ -23,7 +23,9 @@ import net.minecraft.network.chat.Component
|
||||
* @author Hiroku
|
||||
* @since February 17th, 2025
|
||||
*/
|
||||
class RidingStatDefinitions {
|
||||
class RidingStatDefinition {
|
||||
// This object gets read from a JSON adapter manually (field-by-field) so don't add fields without updating the adapter.
|
||||
|
||||
/** A map from [RidingStyle] to a minimum and maximum value for this stat. */
|
||||
val ranges = mutableMapOf<RidingStyle, IntRange>()
|
||||
/** Display name for the stat, if null falls back to [RidingStat.displayName]. */
|
||||
@@ -51,14 +53,14 @@ class RidingStatDefinitions {
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): RidingStatDefinitions {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): RidingStatDefinition {
|
||||
val displayName = buffer.readNullable { buffer.readText() }
|
||||
val description = buffer.readNullable { buffer.readText() }
|
||||
val ranges = buffer.readMap<RidingStyle, IntRange>(
|
||||
{ buffer.readEnum<RidingStyle>(RidingStyle::class.java) },
|
||||
{ IntRange(buffer.readSizedInt(IntSize.U_BYTE), buffer.readSizedInt(IntSize.U_BYTE)) }
|
||||
)
|
||||
return RidingStatDefinitions().apply {
|
||||
return RidingStatDefinition().apply {
|
||||
this.displayName = displayName
|
||||
this.description = description
|
||||
this.ranges.putAll(ranges)
|
||||
+6
-3
@@ -8,9 +8,11 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.spawning.detail
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.Cobblemon.config
|
||||
import com.cobblemon.mod.common.api.drop.DropTable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
|
||||
@@ -20,8 +22,8 @@ import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import kotlin.math.ceil
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
|
||||
/**
|
||||
* A [SpawnDetail] for spawning a [PokemonEntity].
|
||||
@@ -69,7 +71,9 @@ class PokemonSpawnDetail : SpawnDetail() {
|
||||
}
|
||||
|
||||
override fun autoLabel() {
|
||||
val pokemonStruct = pokemon.asStruct()
|
||||
struct.addFunction("pokemon") { pokemon.asMoLangValue() }
|
||||
struct.addFunction("min_level") { DoubleValue(getDerivedLevelRange().start.toDouble()) }
|
||||
struct.addFunction("max_level") { DoubleValue(getDerivedLevelRange().endInclusive.toDouble()) }
|
||||
if (pokemon.species != null) {
|
||||
val species = PokemonSpecies.getByIdentifier(pokemon.species!!.asIdentifierDefaultingNamespace())
|
||||
if (species != null) {
|
||||
@@ -88,7 +92,6 @@ class PokemonSpawnDetail : SpawnDetail() {
|
||||
}
|
||||
}
|
||||
|
||||
struct.setDirectly("pokemon", pokemonStruct)
|
||||
super.autoLabel()
|
||||
}
|
||||
|
||||
|
||||
+14
-13
@@ -8,12 +8,12 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.spawning.detail
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.ArrayStruct
|
||||
import com.bedrockk.molang.runtime.struct.VariableStruct
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.api.ModDependant
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.queryStructOf
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnBucket
|
||||
import com.cobblemon.mod.common.api.spawning.condition.CompositeSpawningCondition
|
||||
import com.cobblemon.mod.common.api.spawning.condition.SpawningCondition
|
||||
@@ -21,6 +21,7 @@ import com.cobblemon.mod.common.api.spawning.context.RegisteredSpawningContext
|
||||
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
|
||||
import com.cobblemon.mod.common.api.spawning.multiplier.WeightMultiplier
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
|
||||
/**
|
||||
@@ -55,21 +56,21 @@ abstract class SpawnDetail : ModDependant {
|
||||
|
||||
var labels = mutableListOf<String>()
|
||||
|
||||
val struct: VariableStruct = VariableStruct()
|
||||
val struct: QueryStruct = queryStructOf(
|
||||
"weight" to { DoubleValue(weight) },
|
||||
"percentage" to { DoubleValue(percentage) },
|
||||
"id" to { StringValue(id) },
|
||||
"bucket" to { StringValue(bucket.name) },
|
||||
"width" to { DoubleValue(width.toDouble()) },
|
||||
"height" to { DoubleValue(height.toDouble()) },
|
||||
"context" to { StringValue(context.name) },
|
||||
"labels" to { labels.asArrayValue { StringValue(it) } }
|
||||
)
|
||||
|
||||
override var neededInstalledMods = listOf<String>()
|
||||
override var neededUninstalledMods = listOf<String>()
|
||||
|
||||
open fun autoLabel() {
|
||||
struct.setDirectly("weight", DoubleValue(weight.toDouble()))
|
||||
struct.setDirectly("percentage", DoubleValue(percentage.toDouble()))
|
||||
struct.setDirectly("id", StringValue(id))
|
||||
struct.setDirectly("bucket", StringValue(bucket.name))
|
||||
struct.setDirectly("width", DoubleValue(width.toDouble()))
|
||||
struct.setDirectly("height", DoubleValue(height.toDouble()))
|
||||
struct.setDirectly("context", StringValue(context.name))
|
||||
struct.setDirectly("labels", ArrayStruct(labels.mapIndexed { index, s -> "$index" to StringValue(s) }.toMap()))
|
||||
}
|
||||
open fun autoLabel() {}
|
||||
|
||||
open fun getName() = displayName?.asTranslated() ?: id.text()
|
||||
|
||||
|
||||
+1
-2
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.api.spawning.rules.component
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.ast.BooleanExpression
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
|
||||
import com.cobblemon.mod.common.api.spawning.detail.SpawnDetail
|
||||
@@ -34,7 +33,7 @@ class FilterRuleComponent : SpawnRuleComponent {
|
||||
|
||||
val spawnSelector: SpawnDetailSelector = AllSpawnDetailSelector
|
||||
val contextSelector: SpawningContextSelector = AllSpawningContextSelector
|
||||
val allow: Expression = BooleanExpression(false)
|
||||
val allow: Expression = BooleanExpression(true)
|
||||
|
||||
override fun affectSpawnable(detail: SpawnDetail, ctx: SpawningContext): Boolean {
|
||||
return if (spawnSelector.selects(detail) && contextSelector.selects(ctx)) {
|
||||
|
||||
@@ -124,7 +124,10 @@ object CobblemonItemTags {
|
||||
@JvmField val POWER_LENS = create("held/power_lens")
|
||||
@JvmField val POWER_WEIGHT = create("held/power_weight")
|
||||
@JvmField val TERRAIN_SEEDS = create("held/terrain_seeds")
|
||||
|
||||
//Held Item Visibility Tags
|
||||
@JvmField val WEARABLE_FACE_ITEMS = create("held/visibility/face")
|
||||
@JvmField val WEARABLE_HAT_ITEMS = create("held/visibility/hat")
|
||||
@JvmField val HIDDEN_ITEMS = create("held/visibility/hidden")
|
||||
|
||||
|
||||
private fun create(path: String) = TagKey.create(Registries.ITEM, cobblemonResource(path))
|
||||
|
||||
@@ -13,9 +13,9 @@ import com.cobblemon.mod.common.api.PrioritizedList
|
||||
import com.cobblemon.mod.common.api.data.DataRegistry
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.battles.BagItems.bagItems
|
||||
import com.cobblemon.mod.common.battles.runner.ShowdownService
|
||||
import com.cobblemon.mod.common.item.battle.BagItem
|
||||
import com.cobblemon.mod.common.item.battle.BagItemLike
|
||||
import com.cobblemon.mod.common.showdown.runner.CobblemonShowdownBattleServer
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
@@ -42,7 +42,11 @@ object BagItems : DataRegistry {
|
||||
|
||||
init {
|
||||
observable.subscribe {
|
||||
Cobblemon.showdownThread.queue(ShowdownService::registerBagItems)
|
||||
if (Cobblemon.showdownServer is CobblemonShowdownBattleServer) {
|
||||
Cobblemon.showdownThread.queue {
|
||||
(Cobblemon.showdownServer as CobblemonShowdownBattleServer).registerBagItems()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common.battles
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore
|
||||
@@ -25,29 +24,15 @@ import com.cobblemon.mod.common.util.effectiveName
|
||||
import com.cobblemon.mod.common.util.getBattleTheme
|
||||
import com.cobblemon.mod.common.util.getPlayer
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import java.util.UUID
|
||||
import com.cobblemon.mod.common.util.swap
|
||||
import com.cobblemon.mod.common.util.update
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.collections.Iterable
|
||||
import kotlin.collections.MutableSet
|
||||
import kotlin.collections.all
|
||||
import kotlin.collections.filterIsInstance
|
||||
import kotlin.collections.first
|
||||
import kotlin.collections.flatMap
|
||||
import kotlin.collections.forEach
|
||||
import kotlin.collections.isNotEmpty
|
||||
import kotlin.collections.mapNotNull
|
||||
import kotlin.collections.mutableSetOf
|
||||
import kotlin.collections.plus
|
||||
import kotlin.collections.plusAssign
|
||||
import java.util.UUID
|
||||
import kotlin.collections.set
|
||||
import kotlin.collections.sortedBy
|
||||
|
||||
object BattleBuilder {
|
||||
@JvmOverloads
|
||||
@@ -92,18 +77,21 @@ object BattleBuilder {
|
||||
val errors = ErroredBattleStart()
|
||||
|
||||
for ((player, actor) in arrayOf(player1 to player1Actor, player2 to player2Actor)) {
|
||||
if (actor.pokemonList.filter { it.health > 0 }.size < battleFormat.battleType.slotsPerActor) {
|
||||
/*
|
||||
if (actor.battlePokemonProvider.getKnownPokemon().filter { it.health > 0 }.size < battleFormat.battleType.slotsPerActor) {
|
||||
errors.participantErrors[actor] += BattleStartError.insufficientPokemon(
|
||||
actorEntity = player,
|
||||
requiredCount = battleFormat.battleType.slotsPerActor,
|
||||
hadCount = actor.pokemonList.filter { it.health > 0 }.size
|
||||
hadCount = actor.battlePokemonProvider.getKnownPokemon().filter { it.health > 0 }.size
|
||||
)
|
||||
}
|
||||
|
||||
if (actor.pokemonList.any { it.entity?.isBusy == true }) {
|
||||
if (actor.battlePokemonProvider.getKnownPokemon().any { it.entity?.isBusy == true }) {
|
||||
errors.participantErrors[actor] += BattleStartError.targetIsBusy(player.displayName ?: player.name)
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
if (BattleRegistry.getBattleByParticipatingPlayer(player) != null) {
|
||||
errors.participantErrors[actor] += BattleStartError.alreadyInBattle(player)
|
||||
}
|
||||
@@ -171,18 +159,21 @@ object BattleBuilder {
|
||||
}
|
||||
|
||||
for ((player, actor) in players.zip(playerActors)) {
|
||||
if (actor.pokemonList.size < battleFormat.battleType.slotsPerActor) {
|
||||
/*
|
||||
if (actor.battlePokemonProvider.getKnownPokemon().size < battleFormat.battleType.slotsPerActor) {
|
||||
errors.participantErrors[actor] += BattleStartError.insufficientPokemon(
|
||||
actorEntity = player,
|
||||
requiredCount = battleFormat.battleType.slotsPerActor,
|
||||
hadCount = actor.pokemonList.size
|
||||
hadCount = actor.battlePokemonProvider.getKnownPokemon().size
|
||||
)
|
||||
}
|
||||
|
||||
if (actor.pokemonList.any { it.entity?.isBusy == true }) {
|
||||
if (actor.battlePokemonProvider.getKnownPokemon().any { it.entity?.isBusy == true }) {
|
||||
errors.participantErrors[actor] += BattleStartError.targetIsBusy(player.displayName ?: player.name)
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
if (BattleRegistry.getBattleByParticipatingPlayer(player) != null) {
|
||||
errors.participantErrors[actor] += BattleStartError.alreadyInBattle(player)
|
||||
}
|
||||
@@ -252,26 +243,30 @@ object BattleBuilder {
|
||||
val wildActor = PokemonBattleActor(pokemonEntity.pokemon.uuid, BattlePokemon(pokemonEntity.pokemon), fleeDistance)
|
||||
val errors = ErroredBattleStart()
|
||||
|
||||
/*
|
||||
if (playerTeam.isNotEmpty() && playerTeam[0].health <= 0){
|
||||
errors.participantErrors[playerActor] += BattleStartError.insufficientPokemon(
|
||||
actorEntity = player,
|
||||
requiredCount = battleFormat.battleType.slotsPerActor,
|
||||
hadCount = playerActor.pokemonList.size
|
||||
hadCount = playerActor.battlePokemonProvider.getKnownPokemon().size
|
||||
)
|
||||
}
|
||||
|
||||
if (playerActor.pokemonList.size < battleFormat.battleType.slotsPerActor) {
|
||||
if (playerActor.battlePokemonProvider.getKnownPokemon().size < battleFormat.battleType.slotsPerActor) {
|
||||
errors.participantErrors[playerActor] += BattleStartError.insufficientPokemon(
|
||||
actorEntity = player,
|
||||
requiredCount = battleFormat.battleType.slotsPerActor,
|
||||
hadCount = playerActor.pokemonList.size
|
||||
hadCount = playerActor.battlePokemonProvider.getKnownPokemon().size
|
||||
)
|
||||
}
|
||||
|
||||
if (playerActor.pokemonList.any { it.entity?.isBusy == true }) {
|
||||
if (playerActor.battlePokemonProvider.getKnownPokemon().any { it.entity?.isBusy == true }) {
|
||||
errors.participantErrors[playerActor] += BattleStartError.targetIsBusy(player.displayName ?: player.name)
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
if (BattleRegistry.getBattleByParticipatingPlayer(player) != null) {
|
||||
errors.participantErrors[playerActor] += BattleStartError.alreadyInBattle(playerActor)
|
||||
}
|
||||
@@ -280,6 +275,8 @@ object BattleBuilder {
|
||||
errors.participantErrors[wildActor] += BattleStartError.alreadyInBattle(wildActor)
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
playerActor.battleTheme = pokemonEntity.getBattleTheme()
|
||||
|
||||
return if (errors.isEmpty) {
|
||||
@@ -318,16 +315,16 @@ object BattleBuilder {
|
||||
healFirst: Boolean = false,
|
||||
party: PartyStore = player.party()
|
||||
): BattleStartResult {
|
||||
/*
|
||||
val playerTeam = party.toBattleTeam(clone = cloneParties, healPokemon = healFirst, leadingPokemon = leadingPokemon)
|
||||
val playerActor = PlayerBattleActor(player.uuid, playerTeam)
|
||||
val npcParty = npcEntity.getPartyForChallenge(listOf(player))
|
||||
val errors = ErroredBattleStart()
|
||||
|
||||
if (playerActor.pokemonList.size < battleFormat.battleType.slotsPerActor) {
|
||||
if (playerActor.battlePokemonProvider.getKnownPokemon().size < battleFormat.battleType.slotsPerActor) {
|
||||
errors.participantErrors[playerActor] += BattleStartError.insufficientPokemon(
|
||||
actorEntity = player,
|
||||
requiredCount = battleFormat.battleType.slotsPerActor,
|
||||
hadCount = playerActor.pokemonList.size
|
||||
hadCount = playerActor.battlePokemonProvider.getKnownPokemon().size
|
||||
)
|
||||
}
|
||||
|
||||
@@ -340,20 +337,20 @@ object BattleBuilder {
|
||||
return errors
|
||||
}
|
||||
|
||||
val npcActor = NPCBattleActor(npcEntity, npcParty, npcEntity.skill ?: npcEntity.npc.skill)
|
||||
val npcActor = NPCBattleActor(npcEntity, npcParty)
|
||||
// if (npcEntity.battleIds.get().isPresent) {
|
||||
// errors.participantErrors[npcActor] += BattleStartError.alreadyInBattle(npcActor)
|
||||
// }
|
||||
|
||||
if (npcActor.pokemonList.filter { it.health > 0 }.size < battleFormat.battleType.slotsPerActor) {
|
||||
if (npcActor.battlePokemonProvider.getKnownPokemon().filter { it.health > 0 }.size < battleFormat.battleType.slotsPerActor) {
|
||||
errors.participantErrors[npcActor] += BattleStartError.insufficientPokemon(
|
||||
actorEntity = npcEntity,
|
||||
requiredCount = battleFormat.battleType.slotsPerActor,
|
||||
hadCount = npcActor.pokemonList.size
|
||||
hadCount = npcActor.battlePokemonProvider.getKnownPokemon().size
|
||||
)
|
||||
}
|
||||
|
||||
if (playerActor.pokemonList.any { it.entity?.isBusy == true }) {
|
||||
if (playerActor.battlePokemonProvider.getKnownPokemon().any { it.entity?.isBusy == true }) {
|
||||
errors.participantErrors[playerActor] += BattleStartError.targetIsBusy(player.displayName ?: player.name)
|
||||
}
|
||||
|
||||
@@ -370,6 +367,8 @@ object BattleBuilder {
|
||||
} else {
|
||||
errors
|
||||
}
|
||||
*/
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -398,7 +397,7 @@ interface BattleStartError {
|
||||
companion object {
|
||||
fun alreadyInBattle(player: ServerPlayer) = AlreadyInBattleError(player.uuid, player.effectiveName())
|
||||
fun alreadyInBattle(pokemonEntity: PokemonEntity) = AlreadyInBattleError(pokemonEntity.uuid, pokemonEntity.effectiveName())
|
||||
fun alreadyInBattle(actor: BattleActor) = AlreadyInBattleError(actor.uuid, actor.getName())
|
||||
//fun alreadyInBattle(actor: BattleActor) = AlreadyInBattleError(actor.uuid, actor.getName())
|
||||
fun noParty(npcEntity: NPCEntity) = NoPartyError(npcEntity)
|
||||
fun targetIsBusy(targetName: Component) = BusyError(targetName)
|
||||
fun insufficientPokemon(
|
||||
|
||||
@@ -17,11 +17,11 @@ import com.cobblemon.mod.common.api.pokemon.helditem.HeldItemProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.battles.runner.ShowdownService
|
||||
import com.cobblemon.mod.common.showdown.runner.remote.RemoteShowdownBattle
|
||||
import com.google.gson.GsonBuilder
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
object BattleRegistry {
|
||||
|
||||
@@ -29,7 +29,7 @@ object BattleRegistry {
|
||||
.disableHtmlEscaping()
|
||||
.registerTypeAdapter(ShowdownMoveset::class.java, ShowdownMovesetAdapter)
|
||||
.create()
|
||||
private val battleMap = ConcurrentHashMap<UUID, PokemonBattle>()
|
||||
private val battleMap = ConcurrentHashMap<String, PokemonBattle>()
|
||||
|
||||
fun onServerStarted() {
|
||||
battleMap.clear()
|
||||
@@ -161,22 +161,23 @@ object BattleRegistry {
|
||||
repeat(battle.format.battleType.slotsPerActor) {
|
||||
actor.activePokemon.add(ActiveBattlePokemon(actor))
|
||||
}
|
||||
val entities = actor.pokemonList.mapNotNull { it.entity }
|
||||
val entities = actor.battlePokemonProvider.getKnownPokemon().mapNotNull { it.entity }
|
||||
entities.forEach { it.battleId = battle.battleId }
|
||||
}
|
||||
|
||||
// -> Add the players and team
|
||||
for (actor in battle.actors.sortedBy { it.showdownId }) {
|
||||
messages.add(""">player ${actor.showdownId} {"name":"${actor.uuid}","team":"${actor.pokemonList.packTeam()}"}""")
|
||||
//messages.add(""">player ${actor.showdownId} {"name":"${actor.uuid}","team":"${actor.battlePokemonProvider.getKnownPokemon().packTeam()}"}""")
|
||||
}
|
||||
|
||||
// -> Set team size
|
||||
for (actor in battle.actors.sortedBy { it.showdownId }) {
|
||||
messages.add(">${actor.showdownId} team ${actor.pokemonList.count()}")
|
||||
messages.add(">${actor.showdownId} team ${actor.battlePokemonProvider.getKnownPokemon().count()}")
|
||||
}
|
||||
|
||||
// Compiles the request and sends it off
|
||||
ShowdownService.service.startBattle(battle, messages.toTypedArray())
|
||||
val showdownBattle = Cobblemon.showdownServer.initializeNewBattle(battle.battleId.toString(), messages.toTypedArray())
|
||||
battle.showdownBattle = showdownBattle
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,12 +215,32 @@ object BattleRegistry {
|
||||
return ErroredBattleStart(mutableSetOf(BattleStartError.canceledByEvent(preBattleEvent.reason)))
|
||||
}
|
||||
|
||||
fun initializeShowdownControlledBattle(showdownBattle: RemoteShowdownBattle, playerId: UUID) {
|
||||
/*
|
||||
val battleId = showdownBattle.id
|
||||
val battle = PokemonBattle(
|
||||
BattleFormat.GEN_9_SINGLES,
|
||||
BattleSide(
|
||||
PlayerBattleActor(playerId, )
|
||||
)
|
||||
)
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
private fun createBattlePokemonFromShowdownJson(jsonObject: JsonObject): BattlePokemon {
|
||||
val pokemon = PokemonProperties.parse("")
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
fun closeBattle(battle: PokemonBattle) {
|
||||
battle.onEndHandlers.forEach { it(battle) }
|
||||
battleMap.remove(battle.battleId)
|
||||
}
|
||||
|
||||
fun getBattle(id: UUID) : PokemonBattle? {
|
||||
fun getBattle(id: String) : PokemonBattle? {
|
||||
return battleMap[id]
|
||||
}
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@ data class SwitchActionResponse(var newPokemonId: UUID) : ShowdownActionResponse
|
||||
}
|
||||
|
||||
override fun isValid(activeBattlePokemon: ActiveBattlePokemon, showdownMoveSet: ShowdownMoveset?, forceSwitch: Boolean): Boolean {
|
||||
val pokemon = activeBattlePokemon.actor.pokemonList.find { it.uuid == newPokemonId }
|
||||
val pokemon = activeBattlePokemon.actor.battlePokemonProvider.getKnownPokemon().find { it.uuid == newPokemonId }
|
||||
return when {
|
||||
pokemon == null -> false // No such Pokémon
|
||||
(!activeBattlePokemon.actor.request?.side?.pokemon?.any{ it.uuid == activeBattlePokemon.battlePokemon?.uuid && it.reviving }!! && pokemon.health <= 0) -> false // Checks if the active Pokémon is reviving, if so ignore this check. If not, return false if dead
|
||||
@@ -223,7 +223,7 @@ data class SwitchActionResponse(var newPokemonId: UUID) : ShowdownActionResponse
|
||||
}
|
||||
|
||||
override fun toShowdownString(activeBattlePokemon: ActiveBattlePokemon, showdownMoveSet: ShowdownMoveset?): String {
|
||||
return "switch ${activeBattlePokemon.actor.pokemonList.indexOfFirst { it.uuid == newPokemonId } + 1}"
|
||||
return "switch ${activeBattlePokemon.actor.battlePokemonProvider.getKnownPokemon().indexOfFirst { it.uuid == newPokemonId } + 1}"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,11 @@ import com.cobblemon.mod.common.battles.dispatch.InstructionSet
|
||||
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
|
||||
import com.cobblemon.mod.common.battles.interpreter.ContextManager
|
||||
import com.cobblemon.mod.common.battles.interpreter.instructions.*
|
||||
import com.cobblemon.mod.common.battles.pokemon.AbstractBattlePokemon
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.runOnServer
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import java.util.UUID
|
||||
import kotlin.collections.Iterator
|
||||
import kotlin.collections.filter
|
||||
import kotlin.collections.forEach
|
||||
@@ -38,7 +38,7 @@ import kotlin.collections.toTypedArray
|
||||
@Suppress("KotlinPlaceholderCountMatchesArgumentCount", "UNUSED_PARAMETER")
|
||||
object ShowdownInterpreter {
|
||||
// Stores a reference to the previous ability, activate, or move message in a battle so a minor action can refer back to it (Battle UUID : BattleMessage)
|
||||
val lastCauser = mutableMapOf<UUID, BattleMessage>()
|
||||
val lastCauser = mutableMapOf<String, BattleMessage>()
|
||||
|
||||
private val updateInstructionParser = mutableMapOf<String, (PokemonBattle, InstructionSet, BattleMessage, Iterator<BattleMessage>) -> InterpreterInstruction>()
|
||||
private val splitInstructionParser = mutableMapOf<String, (PokemonBattle, BattleActor, InstructionSet, BattleMessage, BattleMessage, Iterator<BattleMessage>) -> InterpreterInstruction>()
|
||||
@@ -218,7 +218,7 @@ object ShowdownInterpreter {
|
||||
|
||||
|
||||
|
||||
fun interpretMessage(battleId: UUID, message: String) {
|
||||
fun interpretMessage(battleId: String, message: String) {
|
||||
// Check key map and use function if matching
|
||||
if (message.startsWith("{\"winner\":\"")) {
|
||||
// The post-win message is something we don't care about just yet. It's basically a summary of what happened in the battle.
|
||||
@@ -290,13 +290,13 @@ object ShowdownInterpreter {
|
||||
}
|
||||
}
|
||||
|
||||
fun broadcastOptionalAbility(battle: PokemonBattle, effect: Effect?, pokemon: BattlePokemon) {
|
||||
fun broadcastOptionalAbility(battle: PokemonBattle, effect: Effect?, pokemon: AbstractBattlePokemon) {
|
||||
if (effect == null) return
|
||||
broadcastAbility(battle, effect, pokemon)
|
||||
}
|
||||
|
||||
// Broadcasts a generic lang to notify players of ability activations (effects are broadcasted separately)
|
||||
fun broadcastAbility(battle: PokemonBattle, effect: Effect, pokemon: BattlePokemon) {
|
||||
fun broadcastAbility(battle: PokemonBattle, effect: Effect, pokemon: AbstractBattlePokemon) {
|
||||
if (effect.type != Effect.Type.ABILITY) return
|
||||
battle.dispatchWaiting(0.5F) {
|
||||
val lang = battleLang("ability.generic", pokemon.getName(), effect.typelessData).yellow()
|
||||
|
||||
@@ -8,28 +8,30 @@
|
||||
|
||||
package com.cobblemon.mod.common.battles
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.battles.runner.ShowdownService
|
||||
import java.util.*
|
||||
import com.cobblemon.mod.common.showdown.runner.ShowdownBattleServer
|
||||
import java.util.LinkedList
|
||||
import java.util.Queue
|
||||
import java.util.concurrent.CountDownLatch
|
||||
|
||||
class ShowdownThread : Thread("Cobblemon Showdown") {
|
||||
|
||||
private val latch = CountDownLatch(1)
|
||||
|
||||
private val whenReady : Queue<(ShowdownService) -> Unit> = LinkedList()
|
||||
private val whenReady : Queue<(ShowdownBattleServer) -> Unit> = LinkedList()
|
||||
|
||||
fun launch() {
|
||||
this.start()
|
||||
this.latch.await()
|
||||
for (action in whenReady) {
|
||||
action(ShowdownService.service)
|
||||
action(Cobblemon.showdownServer)
|
||||
}
|
||||
}
|
||||
|
||||
fun queue(action: (ShowdownService) -> Unit) {
|
||||
fun queue(action: (ShowdownBattleServer) -> Unit) {
|
||||
if (this.latch.count == 0L) {
|
||||
action(ShowdownService.service)
|
||||
action(Cobblemon.showdownServer)
|
||||
} else {
|
||||
this.whenReady.add(action)
|
||||
}
|
||||
@@ -37,7 +39,7 @@ class ShowdownThread : Thread("Cobblemon Showdown") {
|
||||
|
||||
override fun run() {
|
||||
LOGGER.info("Starting showdown service...")
|
||||
ShowdownService.service.openConnection()
|
||||
Cobblemon.showdownServer.connect()
|
||||
LOGGER.info("Showdown has been started!")
|
||||
this.latch.countDown()
|
||||
}
|
||||
|
||||
+8
-10
@@ -8,21 +8,19 @@
|
||||
|
||||
package com.cobblemon.mod.common.battles.actor
|
||||
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.AIBattleActor
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.api.battles.model.ai.BattleAI
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.StaticBattlePokemonProvider
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.battles.ai.RandomBattleAI
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import java.util.UUID
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import java.util.UUID
|
||||
|
||||
class MultiPokemonBattleActor(
|
||||
pokemonList: List<BattlePokemon>,
|
||||
artificialDecider: BattleAI = RandomBattleAI(),
|
||||
uuid: UUID = UUID.randomUUID()
|
||||
) : AIBattleActor(uuid, pokemonList, artificialDecider) {
|
||||
open class MultiPokemonBattleActor(
|
||||
uuid: UUID = UUID.randomUUID(),
|
||||
pokemonList: List<BattlePokemon>
|
||||
) : BattleActor(uuid, StaticBattlePokemonProvider(pokemonList)) {
|
||||
override fun getName(): MutableComponent = "Wild Pokémon".text() // TODO probably remove by making it nullable
|
||||
override fun nameOwned(name: String): MutableComponent = Component.literal(name)
|
||||
override val type = ActorType.WILD
|
||||
|
||||
@@ -13,24 +13,25 @@ import com.cobblemon.mod.common.CobblemonNetwork
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.EntityBackedBattleActor
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.StaticBattlePokemonProvider
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.pokemon.experience.BattleExperienceSource
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.battles.pokemon.AbstractBattlePokemon
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMusicPacket
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.getPlayer
|
||||
import java.util.UUID
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import java.util.UUID
|
||||
|
||||
class PlayerBattleActor(
|
||||
uuid: UUID,
|
||||
pokemonList: List<BattlePokemon>,
|
||||
) : BattleActor(uuid, pokemonList.toMutableList()), EntityBackedBattleActor<ServerPlayer> {
|
||||
pokemonList: List<AbstractBattlePokemon>,
|
||||
) : BattleActor(uuid, StaticBattlePokemonProvider(pokemonList.toMutableList())), EntityBackedBattleActor<ServerPlayer> {
|
||||
|
||||
override val initialPos: Vec3?
|
||||
override val entity: ServerPlayer?
|
||||
|
||||
@@ -8,28 +8,24 @@
|
||||
|
||||
package com.cobblemon.mod.common.battles.actor
|
||||
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.AIBattleActor
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.EntityBackedBattleActor
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.FleeableBattleActor
|
||||
import com.cobblemon.mod.common.api.battles.model.ai.BattleAI
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.battles.ai.RandomBattleAI
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleEndPacket
|
||||
import java.util.UUID
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import java.util.UUID
|
||||
|
||||
class PokemonBattleActor(
|
||||
uuid: UUID,
|
||||
val pokemon: BattlePokemon,
|
||||
override val fleeDistance: Float,
|
||||
artificialDecider: BattleAI = RandomBattleAI()
|
||||
) : AIBattleActor(uuid, listOf(pokemon), artificialDecider), EntityBackedBattleActor<PokemonEntity>, FleeableBattleActor {
|
||||
) : MultiPokemonBattleActor(uuid, listOf(pokemon)), EntityBackedBattleActor<PokemonEntity>, FleeableBattleActor {
|
||||
|
||||
override val initialPos: Vec3?
|
||||
init {
|
||||
@@ -56,7 +52,7 @@ class PokemonBattleActor(
|
||||
if (packet is BattleEndPacket) {
|
||||
// Do some shit
|
||||
val entity = entity ?: return
|
||||
entity.battleId = null
|
||||
entity.battleId = ""
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.battles.actor
|
||||
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.AIBattleActor
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.api.battles.model.ai.BattleAI
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.*
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
@@ -21,8 +19,7 @@ class TrainerBattleActor(
|
||||
val trainerName: String,
|
||||
uuid: UUID,
|
||||
pokemonList: List<BattlePokemon>,
|
||||
artificialDecider: BattleAI
|
||||
) : AIBattleActor(uuid, pokemonList, artificialDecider) {
|
||||
) : BattleActor(uuid, StaticBattlePokemonProvider(pokemonList)) {
|
||||
override fun getName() = trainerName.asTranslated()
|
||||
override fun nameOwned(name: String): MutableComponent = battleLang("owned_pokemon", this.getName(), name)
|
||||
override val type = ActorType.NPC
|
||||
|
||||
@@ -8,21 +8,13 @@
|
||||
|
||||
package com.cobblemon.mod.common.battles.ai
|
||||
|
||||
import com.cobblemon.mod.common.api.battles.model.ai.BattleAI
|
||||
import com.cobblemon.mod.common.battles.ActiveBattlePokemon
|
||||
import com.cobblemon.mod.common.battles.DefaultActionResponse
|
||||
import com.cobblemon.mod.common.battles.MoveActionResponse
|
||||
import com.cobblemon.mod.common.battles.PassActionResponse
|
||||
import com.cobblemon.mod.common.battles.ShowdownActionResponse
|
||||
import com.cobblemon.mod.common.battles.ShowdownMoveset
|
||||
import com.cobblemon.mod.common.battles.SwitchActionResponse
|
||||
|
||||
/**
|
||||
* AI that randomly chooses a move from its moveset at a random target.
|
||||
*
|
||||
* @since January 16th, 2022
|
||||
* @author Deltric, Hiroku
|
||||
*/
|
||||
/*
|
||||
class RandomBattleAI : BattleAI {
|
||||
override fun choose(
|
||||
activeBattlePokemon: ActiveBattlePokemon,
|
||||
@@ -30,7 +22,7 @@ class RandomBattleAI : BattleAI {
|
||||
forceSwitch: Boolean
|
||||
): ShowdownActionResponse {
|
||||
if (forceSwitch || activeBattlePokemon.isGone()) {
|
||||
val switchTo = activeBattlePokemon.actor.pokemonList.filter { it.canBeSentOut() }.randomOrNull()
|
||||
val switchTo = activeBattlePokemon.actor.battlePokemonProvider.getKnownPokemon().filter { it.canBeSentOut() }.randomOrNull()
|
||||
?: return DefaultActionResponse() //throw IllegalStateException("Need to switch but no Pokémon to switch to")
|
||||
switchTo.willBeSwitchedIn = true
|
||||
return SwitchActionResponse(switchTo.uuid)
|
||||
@@ -54,4 +46,6 @@ class RandomBattleAI : BattleAI {
|
||||
MoveActionResponse(move.id, (chosenTarget as ActiveBattlePokemon).getPNX())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
@@ -10,32 +10,31 @@ package com.cobblemon.mod.common.battles.ai
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.abilities.Abilities
|
||||
import com.cobblemon.mod.common.api.abilities.AbilityPool
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleContext
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.ai.BattleAI
|
||||
import com.cobblemon.mod.common.api.data.ShowdownIdentifiable
|
||||
import com.cobblemon.mod.common.api.moves.Move
|
||||
import com.cobblemon.mod.common.api.moves.MoveTemplate
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
import com.cobblemon.mod.common.api.moves.categories.DamageCategories
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.api.pokemon.*
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Status
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.battles.*
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.battles.ActiveBattlePokemon
|
||||
import com.cobblemon.mod.common.battles.DefaultActionResponse
|
||||
import com.cobblemon.mod.common.battles.InBattleMove
|
||||
import com.cobblemon.mod.common.battles.MoveActionResponse
|
||||
import com.cobblemon.mod.common.battles.PassActionResponse
|
||||
import com.cobblemon.mod.common.battles.ShowdownActionRequest
|
||||
import com.cobblemon.mod.common.battles.ShowdownActionResponse
|
||||
import com.cobblemon.mod.common.battles.ShowdownMoveset
|
||||
import com.cobblemon.mod.common.battles.SwitchActionResponse
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.status.PersistentStatus
|
||||
import com.cobblemon.mod.common.pokemon.status.PersistentStatusContainer
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import java.util.UUID
|
||||
import kotlin.random.Random
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* AI that tries to choose the best move for the given situations. Based off of the Pokemon Trainer Tournament Simulator Github
|
||||
@@ -351,7 +350,7 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
forceSwitch: Boolean
|
||||
): ShowdownActionResponse {
|
||||
if (forceSwitch || activeBattlePokemon.isGone()) {
|
||||
val switchTo = activeBattlePokemon.actor.pokemonList.filter { it.canBeSentOut() }.randomOrNull()
|
||||
val switchTo = activeBattlePokemon.actor.battlePokemonProvider.getKnownPokemon().filter { it.canBeSentOut() }.randomOrNull()
|
||||
?: return DefaultActionResponse() //throw IllegalStateException("Need to switch but no Pokémon to switch to")
|
||||
switchTo.willBeSwitchedIn = true
|
||||
return SwitchActionResponse(switchTo.uuid)
|
||||
@@ -629,14 +628,19 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
|
||||
if (forceSwitch || activeBattlePokemon.isGone()) {
|
||||
if ((forceSwitch && battle.turn == 1) || (activeBattlePokemon.isGone() && battle.turn == 1)) {
|
||||
val switchTo = activeBattlePokemon.actor.pokemonList.filter { it.canBeSentOut() }.randomOrNull()
|
||||
val switchTo = activeBattlePokemon.actor.battlePokemonProvider.getKnownPokemon()
|
||||
.filterIsInstance<BattlePokemon>()
|
||||
.filter { it.canBeSentOut() }
|
||||
.randomOrNull()
|
||||
?: return DefaultActionResponse() //throw IllegalStateException("Need to switch but no Pokémon to switch to")
|
||||
switchTo.willBeSwitchedIn = true
|
||||
return SwitchActionResponse(switchTo.uuid)
|
||||
}
|
||||
else if ((forceSwitch && battle.turn > 1) || (activeBattlePokemon.isGone() && battle.turn > 1)) {
|
||||
|
||||
val availableSwitches = activeBattlePokemon.actor.pokemonList.filter { (it.health > 0) && (it.uuid != (activeBattlePokemon.battlePokemon?.uuid ?: true)) } //it.uuid != mon.pokemon!!.uuid && it.health > 0 }
|
||||
val availableSwitches = activeBattlePokemon.actor.battlePokemonProvider.getKnownPokemon()
|
||||
.filterIsInstance<BattlePokemon>()
|
||||
.filter { (it.health > 0) && (it.uuid != (activeBattlePokemon.battlePokemon?.uuid ?: true)) } //it.uuid != mon.pokemon!!.uuid && it.health > 0 }
|
||||
|
||||
// this gets null error after NPC faints
|
||||
val bestEstimation = availableSwitches.maxOfOrNull { estimatePartyMatchup(request, battle, it.effectedPokemon) }
|
||||
@@ -651,7 +655,7 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
|
||||
//return SwitchActionResponse(switchTo.uuid)
|
||||
|
||||
/*val availableSwitches = p2Actor.pokemonList.filter { it.health > 0 } //it.uuid != mon.pokemon!!.uuid && it.health > 0 }
|
||||
/*val availableSwitches = p2Actor.battlePokemonProvider.getKnownPokemon().filter { it.health > 0 } //it.uuid != mon.pokemon!!.uuid && it.health > 0 }
|
||||
val bestEstimation = availableSwitches.maxOfOrNull { estimateMatchup(request, battle, it.effectedPokemon) }
|
||||
*//*availableSwitches.forEach {
|
||||
estimateMatchup(request, battle, it.effectedPokemon)
|
||||
@@ -774,8 +778,10 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
|
||||
// switch out based on current matchup on the field
|
||||
if (checkSwitchOutSkill(skill) && shouldSwitchOut(request, battle, activeBattlePokemon, moveset)) {
|
||||
val availableSwitches = p2Actor.pokemonList.filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }
|
||||
val availablePlayerSwitches = p1Actor.pokemonList.filter { it.uuid != opponent.pokemon!!.uuid && it.health > 0 }
|
||||
val availableSwitches = p2Actor.battlePokemonProvider.getKnownPokemon()
|
||||
.filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }
|
||||
.filterIsInstance<BattlePokemon>()
|
||||
val availablePlayerSwitches = p1Actor.battlePokemonProvider.getKnownPokemon().filter { it.uuid != opponent.pokemon!!.uuid && it.health > 0 }
|
||||
|
||||
// todo try to detect a player switch-in based on if they do that a lot
|
||||
// todo if player is in bad matchup against current AI pokemon, and they have switched out before, then they have a chance of switching to a favorable matchup
|
||||
@@ -850,10 +856,12 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
|
||||
// Deal with non-weather related field changing effects
|
||||
for (move in moveset.moves.filter { !it.disabled }) {
|
||||
val availableSwitches = p2Actor.pokemonList.filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }
|
||||
val availableSwitches = p2Actor.battlePokemonProvider.getKnownPokemon()
|
||||
.filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }
|
||||
.filterIsInstance<BattlePokemon>()
|
||||
|
||||
// Tailwind
|
||||
if (move.pp > 0 && move.id == "tailwind" && move.id != npcSideTailwindCondition && p2Actor.pokemonList.filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }.size > 2) {
|
||||
if (move.pp > 0 && move.id == "tailwind" && move.id != npcSideTailwindCondition && p2Actor.battlePokemonProvider.getKnownPokemon().filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }.size > 2) {
|
||||
return chooseMove(move, activeBattlePokemon)
|
||||
}
|
||||
|
||||
@@ -874,7 +882,7 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
// Light Screen
|
||||
if (move.pp > 0 && move.id == "lightscreen" && move.id != npcSideScreenCondition
|
||||
&& getBaseStats(opponent.pokemon!!, "spa") > getBaseStats(opponent.pokemon!!, "atk")
|
||||
&& p2Actor.pokemonList.filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }.size > 1) {
|
||||
&& p2Actor.battlePokemonProvider.getKnownPokemon().filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }.size > 1) {
|
||||
return chooseMove(move, activeBattlePokemon)
|
||||
}
|
||||
|
||||
@@ -882,7 +890,7 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
// Reflect
|
||||
if (move.pp > 0 && move.id == "reflect" && move.id != npcSideScreenCondition
|
||||
&& getBaseStats(opponent.pokemon!!, "atk") > getBaseStats(opponent.pokemon!!, "spa")
|
||||
&& p2Actor.pokemonList.filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }.size > 1) {
|
||||
&& p2Actor.battlePokemonProvider.getKnownPokemon().filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }.size > 1) {
|
||||
return chooseMove(move, activeBattlePokemon)
|
||||
}
|
||||
}
|
||||
@@ -1275,7 +1283,9 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
|
||||
// switch out
|
||||
if (shouldSwitchOut(request, battle, activeBattlePokemon, moveset)) {
|
||||
val availableSwitches = p1Actor.pokemonList.filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }
|
||||
val availableSwitches = p1Actor.battlePokemonProvider.getKnownPokemon()
|
||||
.filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }
|
||||
.filterIsInstance<BattlePokemon>()
|
||||
val bestEstimation = availableSwitches.maxOfOrNull { estimateMatchup(activeBattlePokemon, request, battle, it.effectedPokemon) }
|
||||
/*availableSwitches.forEach {
|
||||
estimateMatchup(request, battle, it.effectedPokemon)
|
||||
@@ -1477,7 +1487,9 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
//val requestActor = request.side?.
|
||||
//val availableSwitches = request.side?.pokemon?.filter { !it.active && getHpFraction(it.condition) != 0.0 }
|
||||
//val playerAvailableSwitches =
|
||||
val availableSwitches = p2Actor.pokemonList.filter { it.uuid != mon.activePokemon.pokemon!!.uuid && it.health > 0 }
|
||||
val availableSwitches = p2Actor.battlePokemonProvider.getKnownPokemon()
|
||||
.filter { it.uuid != mon.activePokemon.pokemon!!.uuid && it.health > 0 }
|
||||
.filterIsInstance<BattlePokemon>()
|
||||
|
||||
val currentNPCAbility = request.side?.pokemon!!.first().ability
|
||||
|
||||
@@ -1784,7 +1796,7 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
|
||||
val p1Boosts = battle.side1.activePokemon.firstOrNull()?.battlePokemon?.statChanges
|
||||
val playerSide1 = battle.side1.actors.first()
|
||||
val numPlayerPokemon = playerSide1.pokemonList.count()
|
||||
val numPlayerPokemon = playerSide1.battlePokemonProvider.getKnownPokemon().count()
|
||||
|
||||
|
||||
/*val lastMajorBattleMessage = if (battle.majorBattleActions.entries.isNotEmpty()) battle.majorBattleActions?.entries?.last()?.value?.rawMessage else ""
|
||||
@@ -1829,9 +1841,9 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
val pokemon2 = battle.side2.activePokemon.firstOrNull()?.battlePokemon?.effectedPokemon
|
||||
val p2Boosts = battle.side2.activePokemon.firstOrNull()?.battlePokemon?.statChanges
|
||||
val playerSide2 = battle.side2.actors.first()
|
||||
val numNPCPokemon = playerSide2.pokemonList.count()
|
||||
val numNPCPokemon = playerSide2.battlePokemonProvider.getKnownPokemon().count()
|
||||
|
||||
//val nextAvailablePokemon = playerSide2.pokemonList.filter { it.health != 0 }.first().effectedPokemon.uuid
|
||||
//val nextAvailablePokemon = playerSide2.battlePokemonProvider.getKnownPokemon().filter { it.health != 0 }.first().effectedPokemon.uuid
|
||||
// todo make nice function for knowing what is the best switchout
|
||||
|
||||
// convert p2Boosts to a regular Map rather than a MutableMap
|
||||
@@ -1858,7 +1870,7 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
//mon.stats = pokemon.stats
|
||||
p1.activePokemon.moves = pokemon1.moveSet.getMoves()
|
||||
p1.nRemainingMons = battle.side1.actors.sumOf { actor ->
|
||||
actor.pokemonList.count { pokemon ->
|
||||
actor.battlePokemonProvider.getKnownPokemon().count { pokemon ->
|
||||
pokemon.health != 0
|
||||
}
|
||||
}
|
||||
@@ -1871,7 +1883,7 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
p1.party[partyPokemonIndex] = p1.activePokemon
|
||||
}
|
||||
|
||||
//p1.availableSwitches = playerSide1.pokemonList.filter { it.uuid != p1.pokemon.uuid && it.health > 0 }
|
||||
//p1.availableSwitches = playerSide1.battlePokemonProvider.getKnownPokemon().filter { it.uuid != p1.pokemon.uuid && it.health > 0 }
|
||||
//p1.sideConditions = pokemon.sideConditions //todo what the hell does this mean
|
||||
|
||||
p2.activePokemon = getActiveTrackerPokemon(p2, pokemon2?.uuid)
|
||||
@@ -1889,7 +1901,7 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
//mon.stats = pokemon.stats
|
||||
p2.activePokemon.moves = pokemon2.moveSet.getMoves()
|
||||
p2.nRemainingMons = battle.side2.actors.sumOf { actor ->
|
||||
actor.pokemonList.count { pokemon ->
|
||||
actor.battlePokemonProvider.getKnownPokemon().count { pokemon ->
|
||||
pokemon.health != 0
|
||||
}
|
||||
}
|
||||
|
||||
+5
-4
@@ -11,9 +11,7 @@ package com.cobblemon.mod.common.battles.interpreter.instructions
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleMessage
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.UsersProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
import com.cobblemon.mod.common.battles.ShowdownInterpreter
|
||||
import com.cobblemon.mod.common.battles.dispatch.ActionEffectInstruction
|
||||
@@ -23,8 +21,8 @@ import com.cobblemon.mod.common.battles.dispatch.InstructionSet
|
||||
import com.cobblemon.mod.common.battles.dispatch.UntilDispatch
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import net.minecraft.network.chat.Component
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
/**
|
||||
* Format: |-activate|POKEMON|EFFECT
|
||||
@@ -59,7 +57,7 @@ class ActivateInstruction(val instructionSet: InstructionSet, val message: Battl
|
||||
val actionEffect = status?.getActionEffect() ?: return@dispatch GO
|
||||
val providers = mutableListOf<Any>(battle)
|
||||
val pokemon = message.battlePokemon(0, battle) ?: return@dispatch GO
|
||||
pokemon.effectedPokemon.entity?.let { UsersProvider(it) }?.let(providers::add)
|
||||
//pokemon.effectedPokemon.entity?.let { UsersProvider(it) }?.let(providers::add)
|
||||
val context = ActionEffectContext(
|
||||
actionEffect = actionEffect,
|
||||
runtime = runtime,
|
||||
@@ -81,6 +79,7 @@ class ActivateInstruction(val instructionSet: InstructionSet, val message: Battl
|
||||
val pokemonName = pokemon.getName()
|
||||
val sourceName = message.battlePokemonFromOptional(battle)?.getName() ?: Component.literal("UNKNOWN")
|
||||
|
||||
/*
|
||||
if (effect.id == "sketch" && pokemon.effectedPokemon.moveSet.any { it.name == "sketch" } && extraEffect is String) {
|
||||
// Apply Sketch to the pokemon's current moveset if it was successfully used in battle
|
||||
val moveTemplate = Moves.getByName(extraEffect.replace(" ", ""))
|
||||
@@ -92,6 +91,8 @@ class ActivateInstruction(val instructionSet: InstructionSet, val message: Battl
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
val lang = when (effect.id) {
|
||||
// Includes a 3rd argument being the magnitude level as a number
|
||||
"magnitude" -> battleLang("activate.magnitude", message.argumentAt(2)?.toIntOrNull() ?: 1)
|
||||
|
||||
+2
-4
@@ -15,7 +15,6 @@ import com.cobblemon.mod.common.api.battles.interpreter.InvalidInstructionExcept
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffects
|
||||
import com.cobblemon.mod.common.api.moves.animations.UsersProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.battles.ShowdownInterpreter
|
||||
import com.cobblemon.mod.common.battles.dispatch.ActionEffectInstruction
|
||||
@@ -52,12 +51,11 @@ class BoostInstruction(battle: PokemonBattle, val message: BattleMessage, val is
|
||||
battle.dispatch {
|
||||
val actionEffect = if (isBoost) BOOST_EFFECT else UNBOOST_EFFECT
|
||||
val providers = mutableListOf<Any>(battle)
|
||||
pokemon.effectedPokemon.entity?.let { UsersProvider(it) }?.let(providers::add)
|
||||
// pokemon.effectedPokemon.entity?.let { UsersProvider(it) }?.let(providers::add)
|
||||
val context = ActionEffectContext(
|
||||
actionEffect = actionEffect,
|
||||
runtime = runtime,
|
||||
providers = providers,
|
||||
level = battle.players.firstOrNull()?.level()
|
||||
providers = providers
|
||||
)
|
||||
this.future = actionEffect.run(context)
|
||||
holds = context.holds // Reference so future things can check on this action effect's holds
|
||||
|
||||
+2
-4
@@ -12,7 +12,6 @@ import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleMessage
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.UsersProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
@@ -47,13 +46,12 @@ class CantInstruction(val message: BattleMessage): ActionEffectInstruction {
|
||||
val status = Statuses.getStatus(effectID)
|
||||
val actionEffect = status?.getActionEffect() ?: return@dispatch GO
|
||||
val providers = mutableListOf<Any>(battle)
|
||||
pokemon.effectedPokemon.entity?.let { UsersProvider(it) }?.let(providers::add)
|
||||
// pokemon.effectedPokemon.entity?.let { UsersProvider(it) }?.let(providers::add)
|
||||
|
||||
val context = ActionEffectContext(
|
||||
actionEffect = actionEffect,
|
||||
runtime = runtime,
|
||||
providers = providers,
|
||||
level = battle.players.firstOrNull()?.level()
|
||||
providers = providers
|
||||
)
|
||||
this.future = actionEffect.run(context)
|
||||
holds = context.holds // Reference so future things can check on this action effect's holds
|
||||
|
||||
+5
-3
@@ -11,11 +11,10 @@ package com.cobblemon.mod.common.battles.interpreter.instructions
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleMessage
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.text.yellow
|
||||
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.LastBattleCriticalHitsEvolutionProgress
|
||||
import com.cobblemon.mod.common.battles.ShowdownInterpreter
|
||||
import com.cobblemon.mod.common.battles.dispatch.InstructionSet
|
||||
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
|
||||
/**
|
||||
* Format: |-crit|POKEMON
|
||||
@@ -39,10 +38,13 @@ class CritInstruction(val message: BattleMessage, val instructionSet: Instructio
|
||||
} else {
|
||||
battle.broadcastChatMessage(battleLang("crit").yellow())
|
||||
}
|
||||
/*
|
||||
if (LastBattleCriticalHitsEvolutionProgress.supports(battlePokemon.effectedPokemon)) {
|
||||
val progress = battlePokemon.effectedPokemon.evolutionProxy.current().progressFirstOrCreate({ it is LastBattleCriticalHitsEvolutionProgress }) { LastBattleCriticalHitsEvolutionProgress() }
|
||||
progress.updateProgress(LastBattleCriticalHitsEvolutionProgress.Progress(progress.currentProgress().amount + 1))
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
battle.minorBattleActions[pokemon.uuid] = message
|
||||
}
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ class CureStatusInstruction(val message: BattleMessage): InterpreterInstruction
|
||||
|
||||
battle.dispatchWaiting {
|
||||
val pokemonName = pokemon.getName()
|
||||
pokemon.effectedPokemon.status = null
|
||||
// pokemon.effectedPokemon.status = null
|
||||
pokemon.sendUpdate()
|
||||
|
||||
if (maybeActivePokemon != null) {
|
||||
|
||||
+14
-8
@@ -25,16 +25,14 @@ import com.cobblemon.mod.common.battles.dispatch.UntilDispatch
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleHealthChangePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.DamageTakenEvolutionProgress
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.RecoilEvolutionProgress
|
||||
import com.cobblemon.mod.common.pokemon.status.statuses.persistent.PoisonStatus
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import net.minecraft.network.chat.Component
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
/**
|
||||
* Format: |-damage|POKEMON|HP STATUS
|
||||
@@ -59,7 +57,9 @@ class DamageInstruction(
|
||||
val recoiling = privateMessage.optionalArgument("from")?.equals("recoil", true) == true
|
||||
val lastCauser = instructionSet.getMostRecentCauser(comparedTo = this)
|
||||
if (recoiling) {
|
||||
doRecoilEvoChecks(battlePokemon)
|
||||
if (battlePokemon is BattlePokemon) {
|
||||
doRecoilEvoChecks(battlePokemon)
|
||||
}
|
||||
if (lastCauser is MoveInstruction) {
|
||||
battle.dispatch {
|
||||
//Is the recoil hold currently used anywhere?
|
||||
@@ -98,9 +98,12 @@ class DamageInstruction(
|
||||
var status = effect?.id?.let { Statuses.getStatus(it) }
|
||||
battle.dispatch {
|
||||
val pokemon = privateMessage.battlePokemon(0, battle) ?: return@dispatch GO
|
||||
//FIXME: This should be tracked on the AbstractBattlePokemon
|
||||
//Showdown doesnt tell us on damage if its poison or toxic so we gotta consult the entity
|
||||
if (status is PoisonStatus) {
|
||||
status = pokemon.effectedPokemon.status?.status ?: status
|
||||
if (pokemon is BattlePokemon) {
|
||||
status = pokemon.effectedPokemon.status?.status ?: status
|
||||
}
|
||||
}
|
||||
|
||||
// Damage effects without a action effect receive the generic damage effect
|
||||
@@ -109,7 +112,7 @@ class DamageInstruction(
|
||||
} ?: return@dispatch GO
|
||||
|
||||
val providers = mutableListOf<Any>(battle)
|
||||
battlePokemon.effectedPokemon.entity?.let { UsersProvider(it) }?.let(providers::add)
|
||||
battlePokemon.entity?.let { UsersProvider(it) }?.let(providers::add)
|
||||
|
||||
val context = ActionEffectContext(
|
||||
actionEffect = actionEffect,
|
||||
@@ -167,7 +170,7 @@ class DamageInstruction(
|
||||
if (causedFaint) {
|
||||
newHealthRatio = 0F
|
||||
battle.dispatch {
|
||||
battlePokemon.effectedPokemon.currentHealth = 0
|
||||
battlePokemon.health = 0
|
||||
battlePokemon.sendUpdate()
|
||||
GO
|
||||
}
|
||||
@@ -177,14 +180,17 @@ class DamageInstruction(
|
||||
val difference = maxHealth - remainingHealth
|
||||
newHealthRatio = remainingHealth.toFloat() / maxHealth
|
||||
battle.dispatchToFront {
|
||||
battlePokemon.effectedPokemon.currentHealth = remainingHealth
|
||||
//battlePokemon.curr = remainingHealth
|
||||
if (difference > 0) {
|
||||
/*
|
||||
battlePokemon.effectedPokemon.let { pokemon ->
|
||||
if (DamageTakenEvolutionProgress.supports(pokemon)) {
|
||||
val progress = pokemon.evolutionProxy.current().progressFirstOrCreate({ it is DamageTakenEvolutionProgress }) { DamageTakenEvolutionProgress() }
|
||||
progress.updateProgress(DamageTakenEvolutionProgress.Progress(progress.currentProgress().amount + difference))
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
battlePokemon.sendUpdate()
|
||||
GO
|
||||
|
||||
+3
-2
@@ -13,7 +13,6 @@ import com.cobblemon.mod.common.api.battles.interpreter.BattleMessage
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.EntityBackedBattleActor
|
||||
import com.cobblemon.mod.common.battles.dispatch.BattleDispatch
|
||||
import com.cobblemon.mod.common.battles.dispatch.InstructionSet
|
||||
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
@@ -39,7 +38,7 @@ class DragInstruction(val instructionSet: InstructionSet, val battleActor: Battl
|
||||
|
||||
val newHealth = privateMessage.argumentAt(2)!!.split(" ")[0]
|
||||
val remainingHealth = newHealth.split("/")[0].toInt()
|
||||
pokemon.effectedPokemon.currentHealth = remainingHealth
|
||||
// pokemon.effectedPokemon.currentHealth = remainingHealth
|
||||
|
||||
battle.broadcastChatMessage(battleLang("dragged_out", pokemon.getName()))
|
||||
activePokemon.battlePokemon?.let { oldPokemon ->
|
||||
@@ -50,6 +49,7 @@ class DragInstruction(val instructionSet: InstructionSet, val battleActor: Battl
|
||||
|
||||
val entity = if (battleActor is EntityBackedBattleActor<*>) battleActor.entity else null
|
||||
setOf(
|
||||
/*
|
||||
BattleDispatch {
|
||||
if (entity != null) {
|
||||
SwitchInstruction.createEntitySwitch(battle, battleActor, entity, pnx, activePokemon, pokemon, illusion, imposter)
|
||||
@@ -57,6 +57,7 @@ class DragInstruction(val instructionSet: InstructionSet, val battleActor: Battl
|
||||
SwitchInstruction.createNonEntitySwitch(battle, battleActor, pnx, activePokemon, pokemon, illusion)
|
||||
}
|
||||
}
|
||||
*/
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.battles.interpreter.instructions
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleContext
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleMessage
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.battles.dispatch.InstructionSet
|
||||
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
|
||||
+1
-3
@@ -12,9 +12,7 @@ import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleContext
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleMessage
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.battles.dispatch.InstructionSet
|
||||
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
|
||||
/**
|
||||
* Format: |-enditem|POKEMON|ITEM|(from)EFFECT
|
||||
@@ -34,7 +32,7 @@ class EndItemInstruction(val message: BattleMessage): InterpreterInstruction {
|
||||
// All logic regarding broadcasting battle messages is handled in CobblemonHeldItemManager
|
||||
val battlePokemon = message.battlePokemon(0, battle) ?: return@dispatchWaiting
|
||||
val itemEffect = message.effectAt(1) ?: return@dispatchWaiting
|
||||
battlePokemon.heldItemManager.handleEndInstruction(battlePokemon, battle, message)
|
||||
//battlePokemon.heldItemManager.handleEndInstruction(battlePokemon, battle, message)
|
||||
battle.minorBattleActions[battlePokemon.uuid] = message
|
||||
battlePokemon.contextManager.remove(itemEffect.id, BattleContext.Type.ITEM)
|
||||
if (message.hasOptionalArgument("eat")) {
|
||||
|
||||
+5
-8
@@ -13,11 +13,8 @@ import com.cobblemon.mod.common.api.battles.interpreter.BattleMessage
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.EntityBackedBattleActor
|
||||
import com.cobblemon.mod.common.api.entity.PokemonSender
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleFaintedEvent
|
||||
import com.cobblemon.mod.common.api.scheduling.delayedFuture
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.battles.ShowdownInterpreter
|
||||
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleFaintPacket
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
@@ -41,20 +38,20 @@ class FaintInstruction(battle: PokemonBattle, val message: BattleMessage) : Inte
|
||||
val pokemon = message.battlePokemon(0, battle) ?: return@dispatchFuture CompletableFuture.completedFuture(Unit)
|
||||
battle.sendUpdate(BattleFaintPacket(pnx))
|
||||
val actor = pokemon.actor
|
||||
pokemon.effectedPokemon.currentHealth = 0
|
||||
//pokemon.effectedPokemon.currentHealth = 0
|
||||
val preamble = if (actor is EntityBackedBattleActor<*>) {
|
||||
(actor.entity as? PokemonSender)?.let { sender -> pokemon.entity?.recallWithAnimation()}
|
||||
} else {
|
||||
null
|
||||
} ?: delayedFuture(seconds = waitTime)
|
||||
val context = ShowdownInterpreter.getContextFromFaint(faintingPokemon, battle)
|
||||
//val context = ShowdownInterpreter.getContextFromFaint(faintingPokemon, battle)
|
||||
|
||||
preamble.thenAccept {
|
||||
faintingPokemon.effectedPokemon.currentHealth = 0
|
||||
//faintingPokemon.effectedPokemon.currentHealth = 0
|
||||
faintingPokemon.sendUpdate()
|
||||
CobblemonEvents.BATTLE_FAINTED.post(BattleFaintedEvent(battle, pokemon, context))
|
||||
//CobblemonEvents.BATTLE_FAINTED.post(BattleFaintedEvent(battle, pokemon, context))
|
||||
battle.getActorAndActiveSlotFromPNX(pnx).second.battlePokemon = null
|
||||
faintingPokemon.contextManager.add(context)
|
||||
//faintingPokemon.contextManager.add(context)
|
||||
faintingPokemon.contextManager.clear(BattleContext.Type.STATUS, BattleContext.Type.VOLATILE, BattleContext.Type.BOOST, BattleContext.Type.UNBOOST)
|
||||
battle.majorBattleActions[faintingPokemon.uuid] = message
|
||||
}
|
||||
|
||||
+1
-3
@@ -10,8 +10,6 @@ package com.cobblemon.mod.common.battles.interpreter.instructions
|
||||
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleMessage
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.battles.instruction.FormeChangeEvent
|
||||
import com.cobblemon.mod.common.battles.ShowdownInterpreter
|
||||
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
@@ -37,7 +35,7 @@ class FormeChangeInstruction(val message: BattleMessage): InterpreterInstruction
|
||||
battle.dispatchWaiting {
|
||||
battle.minorBattleActions[battlePokemon.uuid] = message
|
||||
|
||||
CobblemonEvents.FORME_CHANGE.post(FormeChangeEvent(battle, battlePokemon, formName))
|
||||
//CobblemonEvents.FORME_CHANGE.post(FormeChangeEvent(battle, battlePokemon, formName))
|
||||
val pokemonName = battlePokemon.getName()
|
||||
val lang = when(formName) {
|
||||
"busted", "hero", "complete" -> return@dispatchWaiting
|
||||
|
||||
+7
-7
@@ -17,9 +17,6 @@ import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
import com.cobblemon.mod.common.battles.ShowdownInterpreter
|
||||
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleHealthChangePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattlePersistentStatusPacket
|
||||
import com.cobblemon.mod.common.pokemon.status.PersistentStatus
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
|
||||
/**
|
||||
@@ -53,9 +50,9 @@ class HealInstruction(val actor: BattleActor, val publicMessage: BattleMessage,
|
||||
privateMessage.hasOptionalArgument("wisher") -> {
|
||||
val name = privateMessage.optionalArgument("wisher")!!
|
||||
val showdownId = name.lowercase().replace(ShowdownIdentifiable.REGEX, "")
|
||||
val wisher = actor.pokemonList.firstOrNull { it.effectedPokemon.showdownId() == showdownId }
|
||||
//val wisher = actor.battlePokemonProvider.getKnownPokemon().firstOrNull { it.effectedPokemon.showdownId() == showdownId }
|
||||
// If no Pokémon is found this is a nickname
|
||||
battleLang("heal.wish", wisher?.getName() ?: actor.nameOwned(name))
|
||||
//battleLang("heal.wish", wisher?.getName() ?: actor.nameOwned(name))
|
||||
}
|
||||
privateMessage.hasOptionalArgument("from") -> {
|
||||
when (effect!!.type) {
|
||||
@@ -76,14 +73,15 @@ class HealInstruction(val actor: BattleActor, val publicMessage: BattleMessage,
|
||||
battleLang("heal.generic", battlePokemon.getName())
|
||||
}
|
||||
}
|
||||
battle.broadcastChatMessage(lang)
|
||||
//battle.broadcastChatMessage(lang)
|
||||
}
|
||||
battle.minorBattleActions[battlePokemon.uuid] = privateMessage
|
||||
battlePokemon.effectedPokemon.currentHealth = newHealth[0].toInt()
|
||||
//battlePokemon.effectedPokemon.currentHealth = newHealth[0].toInt()
|
||||
|
||||
// This part is not always present
|
||||
val rawStatus = rawHpAndStatus.getOrNull(1) ?: return@dispatchWaiting
|
||||
val status = Statuses.getStatus(rawStatus) ?: return@dispatchWaiting
|
||||
/*
|
||||
if (status is PersistentStatus && battlePokemon.effectedPokemon.status?.status != status) {
|
||||
battlePokemon.effectedPokemon.applyStatus(status)
|
||||
activePokemon?.let { battle.sendUpdate(BattlePersistentStatusPacket(it.getPNX(), status)) }
|
||||
@@ -91,6 +89,8 @@ class HealInstruction(val actor: BattleActor, val publicMessage: BattleMessage,
|
||||
status.applyMessage.let { battle.broadcastChatMessage(it.asTranslated(battlePokemon.getName())) }
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
-5
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.battles.interpreter.instructions
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleMessage
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.scheduling.afterOnServer
|
||||
@@ -16,6 +15,7 @@ import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
|
||||
import com.cobblemon.mod.common.battles.dispatch.DispatchResult
|
||||
import com.cobblemon.mod.common.battles.dispatch.InstructionSet
|
||||
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleInitializePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMusicPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleQueueRequestPacket
|
||||
@@ -40,12 +40,12 @@ class InitializeInstruction(val instructionSet: InstructionSet, val message: Bat
|
||||
// If a Pokémon entity is being recalled with an animation,
|
||||
// wrap up the animation and recall the Pokémon immediately.
|
||||
if (it.beamMode == 3 && battle.battlePartyStores.isEmpty()) {
|
||||
pokemon.effectedPokemon.recall()
|
||||
// pokemon.effectedPokemon.recall()
|
||||
}
|
||||
// If already on the field, initialize for the BattleInitializePacket
|
||||
else {
|
||||
activePokemon.battlePokemon = pokemon
|
||||
activePokemon.illusion = illusion
|
||||
// activePokemon.battlePokemon = pokemon
|
||||
// activePokemon.illusion = illusion
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,12 @@ class InitializeInstruction(val instructionSet: InstructionSet, val message: Bat
|
||||
}
|
||||
|
||||
battle.actors.forEach { actor ->
|
||||
actor.sendUpdate(BattleSetTeamPokemonPacket(actor.pokemonList.map { it.effectedPokemon }))
|
||||
actor.sendUpdate(BattleSetTeamPokemonPacket(
|
||||
actor.battlePokemonProvider.getKnownPokemon()
|
||||
.filterIsInstance<BattlePokemon>()
|
||||
.map { it.effectedPokemon }
|
||||
.toList()
|
||||
))
|
||||
val req = actor.request ?: return@forEach
|
||||
actor.sendUpdate(BattleQueueRequestPacket(req))
|
||||
}
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ class ItemInstruction(val message: BattleMessage): InterpreterInstruction {
|
||||
|
||||
battle.dispatchWaiting(1.5F) {
|
||||
val battlePokemon = message.battlePokemon(0, battle) ?: return@dispatchWaiting
|
||||
battlePokemon.heldItemManager.handleStartInstruction(battlePokemon, battle, message)
|
||||
//battlePokemon.heldItemManager.handleStartInstruction(battlePokemon, battle, message)
|
||||
battle.minorBattleActions[battlePokemon.uuid] = message
|
||||
battlePokemon.contextManager.add(ShowdownInterpreter.getContextFromAction(message, BattleContext.Type.ITEM, battle))
|
||||
}
|
||||
|
||||
Loaded 100 of 327 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user