mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-24 08:06:24 -04:00
Compare commits
13
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86d48df9fe | ||
|
|
3401ba9cbb | ||
|
|
dac9ccb461 | ||
|
|
191a62f693 | ||
|
|
d8d410e539 | ||
|
|
b7c6e1ea77 | ||
|
|
186812d6fd | ||
|
|
1c0bdc766a | ||
|
|
c697bcd2e9 | ||
|
|
9d6ff01d80 | ||
|
|
1691853a19 | ||
|
|
4e9a4e1e5a | ||
|
|
6450255a0b |
@@ -1,3 +0,0 @@
|
||||
### Additions
|
||||
|
||||
- Added the ability to ride Pokémon by shift-right clicking and selecting the ride option.
|
||||
+1
-17
@@ -6,10 +6,6 @@
|
||||
- Added `/cobblemonconfig reload` command to reload `main.json` configuration. **Note:** Some settings require a server restart to take effect; use this command cautiously.
|
||||
- Added `blacklisted_items_to_hold` and `whitelisted_items_to_hold` tags to allow for controlling which items players can give to their Pokémon. If the whitelist is empty, it will consider all item as allowed (unless they are in the blacklist).
|
||||
- Pokémon now follow the mouse cursor on the Summary screen, with an option to disable this in the settings.
|
||||
- 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`.
|
||||
@@ -25,15 +21,6 @@
|
||||
- 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.
|
||||
@@ -47,14 +34,11 @@
|
||||
|
||||
### 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)
|
||||
|
||||
@@ -2175,4 +2159,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.
|
||||
@@ -36,8 +36,6 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
implementation(libs.bundles.kotlin)
|
||||
implementation("jakarta.websocket:jakarta.websocket-api:2.2.0")
|
||||
|
||||
modImplementation(libs.fabric.loader)
|
||||
modApi(libs.molang)
|
||||
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common;
|
||||
|
||||
import net.minecraft.util.Mth;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface Rollable {
|
||||
|
||||
// From Minecraft's Camera
|
||||
Vector3f FORWARDS = new Vector3f(0.0F, 0.0F, -1.0F);
|
||||
Vector3f UP = new Vector3f(0.0F, 1.0F, 0.0F);
|
||||
Vector3f LEFT = new Vector3f(-1.0F, 0.0F, 0.0F);
|
||||
|
||||
@Nullable Matrix3f getOrientation();
|
||||
|
||||
Rollable updateOrientation(Function<Matrix3f, Matrix3f> update);
|
||||
|
||||
/**
|
||||
* @return The forward vector (0, 0, -1) after the rotation matrix is applied.
|
||||
*/
|
||||
default Vector3f getForwardVector() {
|
||||
if (getOrientation() == null) return new Vector3f(FORWARDS);
|
||||
return getOrientation().transform(FORWARDS, new Vector3f());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The left vector (-1, 0, 0) after the rotation matrix is applied.
|
||||
*/
|
||||
default Vector3f getLeftVector() {
|
||||
if (getOrientation() == null) return new Vector3f(LEFT);
|
||||
return getOrientation().transform(LEFT, new Vector3f());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The up vector (0, 1, 0) after the rotation matrix is applied.
|
||||
*/
|
||||
default Vector3f getUpVector() {
|
||||
if (getOrientation() == null) return new Vector3f(UP);
|
||||
return getOrientation().transform(UP, new Vector3f());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param yaw change in degrees
|
||||
* @return The Rollable object this method was called on
|
||||
*/
|
||||
|
||||
default Rollable rotateYaw(float yaw) {
|
||||
return updateOrientation(prev -> prev.rotateY((float) Math.toRadians(-yaw)));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pitch change in degrees
|
||||
* @return The Rollable object this method was called on
|
||||
*/
|
||||
|
||||
default Rollable rotatePitch(float pitch) {
|
||||
return updateOrientation(prev -> prev.rotateX((float) Math.toRadians(-pitch)));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param roll change in degrees
|
||||
* @return The Rollable object this method was called on
|
||||
*/
|
||||
default Rollable rotateRoll(float roll) {
|
||||
return updateOrientation(prev -> prev.rotateZ((float) Math.toRadians(-roll)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Order matters when rotating an object. If you need a different order, individually call rotateYaw, rotatePitch, and rotateRoll
|
||||
*
|
||||
* @param yaw change in degrees
|
||||
* @param pitch change in degrees
|
||||
* @param roll change in degrees
|
||||
* @return The Rollable object this method was called on
|
||||
*/
|
||||
default Rollable rotate(float yaw, float pitch, float roll) {
|
||||
return rotateYaw(yaw).rotatePitch(pitch).rotateRoll(roll);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The pitch angle in degrees as a float.
|
||||
* Value is between [-180, 180] with 0 being South, 90 being West, 180/-180 being North, and -90 being East
|
||||
*/
|
||||
default float getYaw() {
|
||||
return (float) Mth.wrapDegrees(-Math.toDegrees(FORWARDS.angleSigned(getForwardVector(), UP)) + 180);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The yaw angle in degrees as a float.
|
||||
* Value is between [-90, 90] with 0 being straight forward, 90 being straight down, and -90 being straight up
|
||||
*/
|
||||
default float getPitch() {
|
||||
return (float) Mth.wrapDegrees(-Math.toDegrees(Math.asin(getForwardVector().y)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The roll angle in degrees as a float.
|
||||
* Value is between [-180, 180] with 0 being no roll (normal), 90 being 90 degrees CW, 180/-180 being 180 degrees CW/CCW, and -90 being 90 degrees CCW
|
||||
*/
|
||||
default float getRoll() {
|
||||
//Cobblemon.LOGGER.info("{}", (float) Math.toDegrees(getUpVector().angleSigned(UP, getForwardVector())));
|
||||
return (float) Mth.wrapDegrees(-Math.toDegrees(getUpVector().angleSigned(UP, getForwardVector())));
|
||||
}
|
||||
|
||||
boolean shouldRoll();
|
||||
|
||||
void clearRotation();
|
||||
|
||||
}
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.api.scheduling.ClientTaskTracker;
|
||||
import net.minecraft.client.DeltaTracker;
|
||||
+1
-15
@@ -6,22 +6,18 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.item.PokedexItem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.client.renderer.ItemInHandRenderer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.joml.Quaternionf;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ItemInHandRenderer.class)
|
||||
@@ -31,15 +27,5 @@ public class ItemInHandRendererMixin {
|
||||
if (abstractClientPlayer.isUsingItem() && abstractClientPlayer.getUseItem().getItem() instanceof PokedexItem) {
|
||||
ci.cancel();
|
||||
}
|
||||
else if (abstractClientPlayer instanceof Rollable rollable && rollable.shouldRoll()) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Redirect(method = "renderHandsWithItems", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;mulPose(Lorg/joml/Quaternionf;)V", ordinal = 1))
|
||||
private void cobblemon$renderHandswithItems(PoseStack instance, Quaternionf quaternion) {
|
||||
if (!(Minecraft.getInstance().player instanceof Rollable rollable && rollable.shouldRoll())) {
|
||||
instance.mulPose(quaternion);
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.ModAPI;
|
||||
@@ -40,8 +40,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
*/
|
||||
@Mixin(ItemRenderer.class)
|
||||
public abstract class ItemRendererMixin {
|
||||
// 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";
|
||||
@Unique private final String MODEL_PATH = 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.client;
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
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.client;
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Bone;
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext;
|
||||
+6
-31
@@ -6,9 +6,8 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext;
|
||||
@@ -23,18 +22,16 @@ import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
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.callback.CallbackInfo;
|
||||
|
||||
@Mixin(MouseHandler.class)
|
||||
public class MouseHandlerMixin {
|
||||
@Shadow private double accumulatedScrollY;
|
||||
@Shadow @Final private Minecraft minecraft;
|
||||
@Shadow
|
||||
private double accumulatedScrollY;
|
||||
|
||||
@Unique SmoothDouble pitchSmoother = new SmoothDouble();
|
||||
@Unique SmoothDouble rollSmoother = new SmoothDouble();
|
||||
@Shadow @Final private Minecraft minecraft;
|
||||
|
||||
@Shadow @Final private SmoothDouble smoothTurnY;
|
||||
|
||||
@@ -96,6 +93,7 @@ public class MouseHandlerMixin {
|
||||
)
|
||||
)
|
||||
public boolean cobblemon$modifyRotation(LocalPlayer player, double cursorDeltaX, double cursorDeltaY, @Local(argsOnly = true) double d) {
|
||||
// I know this technically doesn't need to be a WrapWithCondition, but it'll make things easier later for riding.
|
||||
PokedexUsageContext usageContext = CobblemonClient.INSTANCE.getPokedexUsageContext();
|
||||
if (usageContext.getScanningGuiOpen()) {
|
||||
this.smoothTurnY.reset();
|
||||
@@ -107,30 +105,7 @@ public class MouseHandlerMixin {
|
||||
player.turn(this.accumulatedDX * sensitivity, (this.accumulatedDY * sensitivity));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(player instanceof Rollable rollable)) return true;
|
||||
if (!rollable.shouldRoll()) {
|
||||
pitchSmoother.reset();
|
||||
rollSmoother.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
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))
|
||||
private void cobblemon$maintainMovementWhenInScreens(CallbackInfo ci, @Local(ordinal = 1) double e) {
|
||||
if (minecraft.player == null) return;
|
||||
if (!(minecraft.player instanceof Rollable rollable)) return;
|
||||
if (!rollable.shouldRoll()) return;
|
||||
if (minecraft.isPaused()) return;
|
||||
|
||||
var pitch = pitchSmoother.getNewDeltaValue(0, e);
|
||||
var roll = rollSmoother.getNewDeltaValue(0, e);
|
||||
rollable.rotate(0.0F, (float)pitch, (float)roll);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,15 +10,12 @@ package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.CobblemonItems;
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents;
|
||||
import com.cobblemon.mod.common.api.events.item.LeftoversCreatedEvent;
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies;
|
||||
import com.cobblemon.mod.common.api.riding.Rideable;
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore;
|
||||
import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore;
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.ScannableEntity;
|
||||
import com.cobblemon.mod.common.pokemon.FormData;
|
||||
@@ -29,10 +26,6 @@ import com.cobblemon.mod.common.util.CompoundTagExtensionsKt;
|
||||
import com.cobblemon.mod.common.util.CompoundTagUtilities;
|
||||
import com.cobblemon.mod.common.util.DataKeys;
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
@@ -45,10 +38,8 @@ import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
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 org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix3f;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
@@ -62,11 +53,10 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Mixin(Player.class)
|
||||
public abstract class PlayerMixin extends LivingEntity implements Rollable, ScannableEntity {
|
||||
public abstract class PlayerMixin extends LivingEntity implements ScannableEntity {
|
||||
|
||||
@Shadow public abstract CompoundTag getShoulderEntityLeft();
|
||||
|
||||
@@ -84,7 +74,6 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
|
||||
|
||||
@Shadow public abstract void displayClientMessage(Component message, boolean overlay);
|
||||
|
||||
@Unique private Matrix3f orientation = null;
|
||||
|
||||
protected PlayerMixin(EntityType<? extends LivingEntity> p_20966_, Level p_20967_) {
|
||||
super(p_20966_, p_20967_);
|
||||
@@ -178,7 +167,8 @@ 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 && (Object) this instanceof ServerPlayer player) {
|
||||
if (!level().isClientSide) {
|
||||
ServerPlayer player = (ServerPlayer)(Object)this;
|
||||
boolean invulnerableInBattle = this.level().getGameRules().getBoolean(CobblemonGameRules.BATTLE_INVULNERABILITY);
|
||||
boolean inBattle = Cobblemon.INSTANCE.getBattleRegistry().getBattleByParticipatingPlayer(player) != null;
|
||||
if (invulnerableInBattle && inBattle) {
|
||||
@@ -235,81 +225,4 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
|
||||
public LivingEntity resolveEntityScan() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void absMoveTo(double x, double y, double z, float yaw, float pitch) {
|
||||
if (shouldRoll()) {
|
||||
this.absMoveTo(x, y, z);
|
||||
this.setYRot(yaw % 360.0f);
|
||||
this.setXRot(pitch % 360.0f);
|
||||
this.yRotO = this.getYRot();
|
||||
this.xRotO = this.getXRot();
|
||||
}
|
||||
else {
|
||||
this.absMoveTo(x, y, z);
|
||||
this.absRotateTo(yaw, pitch);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "tick", at = @At("HEAD"))
|
||||
public void tick(CallbackInfo ci) {
|
||||
if (this.shouldRoll()) {
|
||||
// Proof of concept for yaw movement
|
||||
if (this.getMainHandItem().is(Items.STICK)) {
|
||||
this.rotateYaw(2);
|
||||
}
|
||||
else if (this.getMainHandItem().is(Items.BLAZE_ROD)) {
|
||||
this.rotateYaw(-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Matrix3f getOrientation() {
|
||||
return orientation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rollable updateOrientation(Function<Matrix3f, Matrix3f> update) {
|
||||
if (!shouldRoll()) return this;
|
||||
|
||||
if (this.orientation == null) {
|
||||
this.orientation = new Matrix3f();
|
||||
this.rotate(getYRot() - 180, getXRot(), 0);
|
||||
}
|
||||
this.orientation = update.apply(this.orientation);
|
||||
setYRot(this.getYaw());
|
||||
setXRot(this.getPitch());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRoll() {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (!this.equals(player)) return false;
|
||||
if (player.isHolding(Items.DIAMOND)) return true;
|
||||
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return false;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return false;
|
||||
|
||||
return pokemonEntity.getRiding().shouldRoll(pokemonEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearRotation() {
|
||||
this.orientation = null;
|
||||
}
|
||||
|
||||
@WrapOperation(
|
||||
method = "rideTick()V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;wantsToStopRiding()Z")
|
||||
)
|
||||
public boolean delegateDismountToController(Player instance, Operation<Boolean> original) {
|
||||
if (this.getVehicle() instanceof Rideable vehicle) {
|
||||
return vehicle.getRiding().dismountOnShift() && original.call(instance);
|
||||
}
|
||||
return original.call(instance);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.render.ClientPlayerIcon;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(PlayerRenderer.class)
|
||||
public class PlayerRendererMixin {
|
||||
|
||||
@Inject(method = "render", at = @At(value = "TAIL"))
|
||||
public void renderPlayer(AbstractClientPlayer player, float f, float g, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, CallbackInfo ci) {
|
||||
ClientPlayerIcon.Companion.onRenderPlayer(player);
|
||||
}
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
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.callback.CallbackInfo;
|
||||
|
||||
@Mixin(Camera.class)
|
||||
public abstract class CameraMixin {
|
||||
@Shadow @Final private static float DEFAULT_CAMERA_DISTANCE;
|
||||
|
||||
@Shadow private Entity entity;
|
||||
@Shadow @Final private Quaternionf rotation;
|
||||
@Shadow @Final private Vector3f forwards;
|
||||
@Shadow @Final private Vector3f up;
|
||||
@Shadow @Final private Vector3f left;
|
||||
@Shadow private float xRot;
|
||||
@Shadow private float yRot;
|
||||
|
||||
@Shadow public abstract float getXRot();
|
||||
|
||||
@Shadow public abstract float getYRot();
|
||||
|
||||
@Unique private float returnTimer = 0;
|
||||
@Unique private float rollAngleStart = 0;
|
||||
@Unique Minecraft minecraft = Minecraft.getInstance();
|
||||
|
||||
@Unique boolean disableRollableCameraDebug = false;
|
||||
|
||||
@Inject(method = "setRotation", at = @At("HEAD"), cancellable = true)
|
||||
public void open_camera$setRotation(float f, float g, CallbackInfo ci) {
|
||||
if (!(this.entity instanceof Rollable rollable) || disableRollableCameraDebug) return;
|
||||
if (!rollable.shouldRoll() && rollable.getOrientation() != null) {
|
||||
if(this.returnTimer < 1) {
|
||||
//Rotation is taken from entity since we no longer handle mouse ourselves
|
||||
//Stops a period of time when you can't input anything.
|
||||
rollable.getOrientation().set(
|
||||
new Matrix3f()
|
||||
.rotateY((float) Math.toRadians(180 - this.entity.getYRot()))
|
||||
.rotateX((float) Math.toRadians(-this.entity.getXRot()))
|
||||
);
|
||||
if(rollAngleStart == 0){
|
||||
this.returnTimer = 1;
|
||||
rollable.clearRotation();
|
||||
return;
|
||||
}
|
||||
rollable.getOrientation().rotateZ((float) Math.toRadians(-rollAngleStart*(1-returnTimer)));
|
||||
applyRotation();
|
||||
this.returnTimer += .05F;
|
||||
ci.cancel();
|
||||
} else {
|
||||
this.returnTimer = 1;
|
||||
rollable.clearRotation();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (rollable.getOrientation() == null) return;
|
||||
applyRotation();
|
||||
|
||||
this.returnTimer = 0;
|
||||
this.rollAngleStart = rollable.getRoll();
|
||||
ci.cancel();
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void applyRotation(){
|
||||
if (!(this.entity instanceof Rollable rollable) || rollable.getOrientation() == null) return;
|
||||
var newRotation = rollable.getOrientation().normal(new Matrix3f()).getNormalizedRotation(new Quaternionf());
|
||||
if (this.minecraft.options.getCameraType().isMirrored()) {
|
||||
newRotation.rotateY((float)Math.toRadians(180));
|
||||
}
|
||||
this.rotation.set(newRotation);
|
||||
this.xRot = rollable.getPitch();
|
||||
this.yRot = rollable.getYaw();
|
||||
this.forwards.set(rollable.getForwardVector());
|
||||
this.up.set(rollable.getUpVector());
|
||||
this.left.set(rollable.getLeftVector());
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.render.player.MountedPlayerRenderer;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import net.minecraft.client.model.HumanoidModel;
|
||||
import net.minecraft.client.model.geom.ModelPart;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
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.callback.CallbackInfo;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@Mixin(HumanoidModel.class)
|
||||
public class HumanoidModelMixin {
|
||||
@Unique HashMap<String, ModelPart> relevantPartsByName = new HashMap<>();
|
||||
|
||||
@Shadow @Final
|
||||
public ModelPart head;
|
||||
@Shadow @Final
|
||||
public ModelPart rightArm;
|
||||
@Shadow @Final
|
||||
public ModelPart leftArm;
|
||||
@Shadow @Final
|
||||
public ModelPart rightLeg;
|
||||
@Shadow @Final
|
||||
public ModelPart leftLeg;
|
||||
|
||||
@Inject(method = "setupAnim*", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/model/geom/ModelPart;copyFrom(Lnet/minecraft/client/model/geom/ModelPart;)V", shift = At.Shift.BEFORE))
|
||||
public void cobblemon$animateRiders(
|
||||
LivingEntity entity,
|
||||
float limbSwing,
|
||||
float limbSwingAmount,
|
||||
float ageInTicks,
|
||||
float netHeadYaw,
|
||||
float headPitch,
|
||||
CallbackInfo ci
|
||||
) {
|
||||
if (relevantPartsByName.isEmpty()) {
|
||||
relevantPartsByName.put("arm_left", leftArm);
|
||||
relevantPartsByName.put("arm_right", rightArm);
|
||||
relevantPartsByName.put("leg_left", leftLeg);
|
||||
relevantPartsByName.put("leg_right", rightLeg);
|
||||
relevantPartsByName.put("head", head);
|
||||
}
|
||||
|
||||
Entity vehicle = entity.getVehicle();
|
||||
if (vehicle instanceof PokemonEntity && entity instanceof AbstractClientPlayer) {
|
||||
MountedPlayerRenderer.INSTANCE.animate((PokemonEntity) vehicle, (AbstractClientPlayer) entity, relevantPartsByName, netHeadYaw, headPitch, ageInTicks, limbSwing, limbSwingAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork;
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.net.messages.server.orientation.C2SUpdateOrientationPacket;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import org.joml.Matrix3f;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(LocalPlayer.class)
|
||||
public class LocalPlayerMixin {
|
||||
|
||||
@Unique Matrix3f cobblemon$lastOrientation;
|
||||
|
||||
@Inject(method = "sendPosition", at = @At("TAIL"))
|
||||
private void cobblemon_updateRotationMatrix(CallbackInfo ci) {
|
||||
if (!(this instanceof Rollable rollable)) return;
|
||||
if (rollable.getOrientation() == cobblemon$lastOrientation) return;
|
||||
cobblemon$lastOrientation = rollable.getOrientation() != null ? new Matrix3f(rollable.getOrientation()) : null;
|
||||
CobblemonNetwork.INSTANCE.sendToServer(new C2SUpdateOrientationPacket(rollable.getOrientation()));
|
||||
}
|
||||
|
||||
@Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientPacketListener;send(Lnet/minecraft/network/protocol/Packet;)V"))
|
||||
private void cobblemon_updateRotationMatrixPassenger(CallbackInfo ci) {
|
||||
if (!(this instanceof Rollable rollable)) return;
|
||||
if (rollable.getOrientation() == cobblemon$lastOrientation) return;
|
||||
cobblemon$lastOrientation = rollable.getOrientation() != null ? new Matrix3f(rollable.getOrientation()) : null;
|
||||
CobblemonNetwork.INSTANCE.sendToServer(new C2SUpdateOrientationPacket(rollable.getOrientation()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
import com.cobblemon.mod.common.api.riding.Rideable;
|
||||
import com.cobblemon.mod.common.api.riding.RidingManager;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import net.minecraft.client.model.PlayerModel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(PlayerModel.class)
|
||||
public class PlayerModelMixin {
|
||||
@Inject(method = "setupAnim(Lnet/minecraft/world/entity/LivingEntity;FFFFF)V", at = @At(value = "HEAD"))
|
||||
private void cobblemon$setHeadRotation(LivingEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, CallbackInfo ci){
|
||||
if (!(entity instanceof Player)) return;
|
||||
Entity vehicle = entity.getVehicle();
|
||||
|
||||
if (!(vehicle instanceof PokemonEntity)) return;
|
||||
RidingManager ridingManager = ((Rideable) vehicle).getRiding();
|
||||
if (ridingManager.shouldRotatePlayerHead((PokemonEntity) vehicle)) return;
|
||||
|
||||
netHeadYaw = 0f;
|
||||
headPitch = 0f;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.render.ClientPlayerIcon;
|
||||
import com.cobblemon.mod.common.client.render.player.MountedPlayerRenderer;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(PlayerRenderer.class)
|
||||
public class PlayerRendererMixin {
|
||||
@Inject(method = "render(Lnet/minecraft/world/entity/LivingEntity;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At(value = "TAIL"))
|
||||
public void cobblemon$clientPlayerIcon(LivingEntity entity, float entityYaw, float partialTicks, PoseStack poseStack, MultiBufferSource buffer, int packedLight, CallbackInfo ci) {
|
||||
ClientPlayerIcon.Companion.onRenderPlayer((Player) entity);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "setupRotations(Lnet/minecraft/client/player/AbstractClientPlayer;Lcom/mojang/blaze3d/vertex/PoseStack;FFFF)V",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void cobblemon$modifyRoll(AbstractClientPlayer player, PoseStack poseStack, float a, float b, float partialTicks, float i, CallbackInfo ci) {
|
||||
if (player.isPassenger()) {
|
||||
var vehicle = player.getVehicle();
|
||||
if (vehicle instanceof PokemonEntity entity) {
|
||||
MountedPlayerRenderer.INSTANCE.render(player, entity, poseStack, a, b, partialTicks, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +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.entity;
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(Entity.class)
|
||||
public abstract class EntityMixin {
|
||||
|
||||
@Shadow @Nullable public abstract Entity getVehicle();
|
||||
|
||||
@Inject(method = "updateInWaterStateAndDoWaterCurrentPushing", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/Entity;wasTouchingWater:Z", ordinal = 1), cancellable = true)
|
||||
public void cobblemon$verifyActuallyTouchingWater(CallbackInfo ci) {
|
||||
if(this.getVehicle() instanceof PokemonEntity) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,62 +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.riding;
|
||||
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(LocalPlayer.class)
|
||||
public class JetMixin {
|
||||
|
||||
@Shadow private int jumpRidingTicks;
|
||||
@Shadow private float jumpRidingScale;
|
||||
|
||||
private float jetStrength;
|
||||
|
||||
// @Redirect(method = "tickMovement", at = @At(target = "Lnet/minecraft/entity/JumpingMount;getJumpCooldown()I", value = "INVOKE"))
|
||||
// public int cobblemon$tryHandlingJet(JumpingMount mount) {
|
||||
// if(mount instanceof PokemonEntity pokemon) {
|
||||
//// if(pokemon.getDataTracker().get(PokemonEntity.MOVING)) {
|
||||
//// ++this.field_3938;
|
||||
//// if (this.field_3938 < 11) {
|
||||
//// this.jetStrength = (float) this.field_3938 * 0.1F;
|
||||
//// } else {
|
||||
// this.mountJumpStrength = 0.8F + 2.0F / (float) (this.field_3938 - 9) * 0.1F;
|
||||
//// }
|
||||
//// } else {
|
||||
//// this.field_3938 = 0;
|
||||
//// this.jetStrength = 0;
|
||||
//// }
|
||||
//
|
||||
//// return -1;
|
||||
// }
|
||||
//
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
@Inject(
|
||||
method = "aiStep",
|
||||
at = @At(
|
||||
target = "Lnet/minecraft/client/player/LocalPlayer;jumpRidingScale:F",
|
||||
value = "FIELD",
|
||||
ordinal = 4,
|
||||
shift = At.Shift.AFTER
|
||||
),
|
||||
locals = LocalCapture.CAPTURE_FAILSOFT
|
||||
)
|
||||
public void cobblemon$applyCachedJumpStrength(CallbackInfo ci) {
|
||||
this.jumpRidingScale = this.jetStrength;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -62,24 +62,11 @@ 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.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.*
|
||||
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.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.command.argument.*
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import com.cobblemon.mod.common.config.LastChangedVersion
|
||||
import com.cobblemon.mod.common.config.constraint.IntConstraint
|
||||
@@ -93,32 +80,16 @@ 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.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.*
|
||||
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.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.util.*
|
||||
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
|
||||
@@ -141,8 +112,7 @@ import java.io.File
|
||||
import java.io.FileReader
|
||||
import java.io.FileWriter
|
||||
import java.io.PrintWriter
|
||||
import java.util.UUID
|
||||
import kotlin.collections.set
|
||||
import java.util.*
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.properties.Delegates
|
||||
import kotlin.reflect.full.memberProperties
|
||||
@@ -182,10 +152,6 @@ 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>(
|
||||
@@ -312,7 +278,6 @@ object Cobblemon {
|
||||
|
||||
SHINY_ASPECT.register()
|
||||
GENDER_ASPECT.register()
|
||||
COSMETIC_SLOT_ASPECT.register()
|
||||
|
||||
SpeciesFeatures.types["choice"] = ChoiceSpeciesFeatureProvider::class.java
|
||||
SpeciesFeatures.types["flag"] = FlagSpeciesFeatureProvider::class.java
|
||||
@@ -348,7 +313,6 @@ object Cobblemon {
|
||||
}
|
||||
PlatformEvents.SERVER_TICK_PRE.subscribe {
|
||||
ServerRealTimeTaskTracker.update()
|
||||
showdownServer.onTick()
|
||||
}
|
||||
PlatformEvents.SERVER_STARTING.subscribe { event ->
|
||||
val server = event.server
|
||||
@@ -425,24 +389,21 @@ object Cobblemon {
|
||||
PlatformEvents.SERVER_STARTED.subscribe {
|
||||
bestSpawner.onServerStarted()
|
||||
battleRegistry.onServerStarted()
|
||||
showdownServer.onServerStarted()
|
||||
}
|
||||
PlatformEvents.SERVER_TICK_POST.subscribe { ServerTickHandler.onTick(it.server) }
|
||||
|
||||
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")
|
||||
}
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,9 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
|
||||
@JvmField
|
||||
val PC: BlockEntityType<PCBlockEntity> = this.create("pc", BlockEntityType.Builder.of(::PCBlockEntity, CobblemonBlocks.PC).build(null))
|
||||
|
||||
@JvmField
|
||||
val STADIUM: BlockEntityType<StadiumBlockEntity> = this.create("stadium_terminal", BlockEntityType.Builder.of(::StadiumBlockEntity, CobblemonBlocks.STADIUM).build(null))
|
||||
|
||||
@JvmField
|
||||
val LECTERN: BlockEntityType<LecternBlockEntity> = this.create("lectern", BlockEntityType.Builder.of(::LecternBlockEntity, CobblemonBlocks.LECTERN).build(null))
|
||||
|
||||
|
||||
@@ -354,6 +354,9 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val PC = create("pc", PCBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F).noOcclusion().lightLevel { if ((it.getValue(PCBlock.ON) as Boolean) && (it.getValue(PCBlock.PART) == PCBlock.PCPart.TOP)) 10 else 0 }))
|
||||
|
||||
@JvmField
|
||||
val STADIUM = create("stadium_terminal", StadiumBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F)))
|
||||
|
||||
@JvmField
|
||||
val LECTERN = create("lectern", LecternBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).sound(SoundType.WOOD).strength(2.5F).ignitedByLava()))
|
||||
|
||||
|
||||
@@ -8,53 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
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.cobblemon.mod.common.command.*
|
||||
import com.mojang.brigadier.CommandDispatcher
|
||||
import net.minecraft.commands.CommandBuildContext
|
||||
import net.minecraft.commands.CommandSourceStack
|
||||
@@ -111,6 +65,5 @@ 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)
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.api.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,7 +9,6 @@
|
||||
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
|
||||
@@ -87,20 +86,13 @@ object CobblemonFlows : DataRegistry {
|
||||
observable.emit(this)
|
||||
}
|
||||
|
||||
fun run(
|
||||
eventResourceLocation: ResourceLocation,
|
||||
context: Map<String, MoValue>,
|
||||
functions: Map<String, (MoParams) -> Any> = emptyMap(),
|
||||
cancelable: Cancelable? = null
|
||||
) {
|
||||
fun run(eventResourceLocation: ResourceLocation, context: Map<String, MoValue>, 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
|
||||
|
||||
@@ -272,6 +272,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val PC = blockItem("pc", CobblemonBlocks.PC)
|
||||
@JvmField
|
||||
val STADIUM = blockItem("stadium_terminal", CobblemonBlocks.STADIUM)
|
||||
@JvmField
|
||||
val PASTURE = blockItem("pasture", CobblemonBlocks.PASTURE)
|
||||
@JvmField
|
||||
val DISPLAY_CASE = blockItem("display_case", CobblemonBlocks.DISPLAY_CASE)
|
||||
|
||||
@@ -47,14 +47,7 @@ import com.cobblemon.mod.common.client.net.storage.party.SetPartyPokemonHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.party.SetPartyReferenceHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.pc.*
|
||||
import com.cobblemon.mod.common.client.net.toast.ToastPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeAcceptanceChangedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeCancelledHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeCompletedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeOfferExpiredHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeOfferNotificationHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeProcessStartedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeStartedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeUpdatedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.*
|
||||
import com.cobblemon.mod.common.net.PacketRegisterInfo
|
||||
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.SetClientPlayerDataPacket
|
||||
@@ -94,41 +87,17 @@ import com.cobblemon.mod.common.net.messages.client.storage.party.InitializePart
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.MoveClientPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyReferencePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.ClosePCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.InitializePCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.MoveClientPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.OpenPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.RenamePCBoxPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.ChangePCBoxWallpaperPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.RequestPCBoxWallpapersPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.SetPCBoxWallpapersPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.toast.ToastPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeAcceptanceChangedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeCompletedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferExpiredPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferNotificationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeProcessStartedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.*
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.PokedexUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BattleChallengeResponsePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BenchMovePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.RequestMoveSwapPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.RequestPlayerInteractionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamLeavePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamRequestPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamResponsePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.*
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.*
|
||||
import com.cobblemon.mod.common.net.messages.server.block.AdjustBlockEntityViewerCountPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectedPacket
|
||||
@@ -139,14 +108,12 @@ import com.cobblemon.mod.common.net.messages.server.callback.partymove.PartyPoke
|
||||
import com.cobblemon.mod.common.net.messages.server.dialogue.EscapeDialoguePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.dialogue.InputToDialoguePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.npc.SaveNPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.orientation.C2SUpdateOrientationPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.PasturePokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.UnpastureAllPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.FinishScanningPacket
|
||||
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
|
||||
@@ -154,22 +121,19 @@ import com.cobblemon.mod.common.net.messages.server.storage.SwapPCPartyPokemonPa
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.ReleasePartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.AcceptTradeRequestPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.CancelTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.ChangeTradeAcceptancePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.PerformTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket
|
||||
import com.cobblemon.mod.common.net.serverhandling.ChallengeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.ChallengeResponseHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.RequestInteractionsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.BattleSelectActionsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.RemoveSpectatorHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamLeaveHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestResponseHandler
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePCPokemonToPartyPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePartyPokemonToPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.PCBoxWallpapersPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.ReleasePCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.RequestChangePCBoxWallpaperPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.RequestRenamePCBoxPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.SortPCBoxPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.SwapPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.UnlinkPlayerFromPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.block.AdjustBlockEntityViewerCountHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectCancelledHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectedHandler
|
||||
@@ -181,14 +145,12 @@ import com.cobblemon.mod.common.net.serverhandling.dialogue.EscapeDialogueHandle
|
||||
import com.cobblemon.mod.common.net.serverhandling.dialogue.InputToDialogueHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.evolution.AcceptEvolutionHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.npc.SaveNPCHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.orientation.OrientationPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.PasturePokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpastureAllPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpasturePokemonHandler
|
||||
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
|
||||
@@ -200,12 +162,7 @@ import com.cobblemon.mod.common.net.serverhandling.storage.party.MovePartyPokemo
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.party.ReleasePCPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.party.SwapPartyPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.AcceptTradeRequestHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.CancelTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.ChangeTradeAcceptanceHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.OfferTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.PerformTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.*
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
@@ -218,11 +175,13 @@ import net.minecraft.server.level.ServerPlayer
|
||||
* @since November 27th, 2021
|
||||
*/
|
||||
object CobblemonNetwork {
|
||||
//private val logger = LogUtils.getLogger()
|
||||
|
||||
fun ServerPlayer.sendPacket(packet: NetworkPacket<*>) {
|
||||
sendPacketToPlayer(this, packet)
|
||||
}
|
||||
fun sendToServer(packet: NetworkPacket<*>) {
|
||||
//logger.info("[C->S] ${packet.type()}")
|
||||
Cobblemon.implementation.networkManager.sendToServer(packet)
|
||||
}
|
||||
fun sendToAllPlayers(packet: NetworkPacket<*>) = sendPacketToPlayers(server()!!.playerList.players, packet)
|
||||
@@ -261,7 +220,6 @@ 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()))
|
||||
@@ -352,7 +310,6 @@ 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))
|
||||
@@ -412,7 +369,6 @@ 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))
|
||||
@@ -499,13 +455,11 @@ object CobblemonNetwork {
|
||||
// NPC packets
|
||||
list.add(PacketRegisterInfo(SaveNPCPacket.ID, SaveNPCPacket::decode, SaveNPCHandler))
|
||||
|
||||
// Orientation packet(s)
|
||||
list.add(PacketRegisterInfo(C2SUpdateOrientationPacket.ID, C2SUpdateOrientationPacket::decode, OrientationPacketHandler))
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
fun sendPacketToPlayer(player: ServerPlayer, packet: NetworkPacket<*>) {
|
||||
//logger.info("[S->C] ${packet.type()}")
|
||||
Cobblemon.implementation.networkManager.sendPacketToPlayer(player, packet)
|
||||
}
|
||||
}
|
||||
}
|
||||
+25
-1
@@ -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,3 +43,27 @@ 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,6 +11,7 @@ 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
|
||||
@@ -36,8 +37,11 @@ object Abilities : DataRegistry {
|
||||
PotentialAbility.types.add(CommonAbilityType)
|
||||
PotentialAbility.types.add(HiddenAbilityType)
|
||||
this.abilityMap.clear()
|
||||
Cobblemon.showdownServer.getAbilityIds().forEach { abilityId ->
|
||||
this.register(AbilityTemplate(abilityId))
|
||||
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.LOGGER.info("Loaded {} abilities", this.abilityMap.size)
|
||||
this.observable.emit(this)
|
||||
|
||||
+6
-17
@@ -8,10 +8,6 @@
|
||||
|
||||
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
|
||||
|
||||
/**
|
||||
@@ -31,15 +27,8 @@ interface BattleContext {
|
||||
/** The [BattleContext.Type] tied to this [BattleContext]. */
|
||||
val type: Type
|
||||
|
||||
/** 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 [BattlePokemon] that directly or indirectly caused this [BattleContext]. */
|
||||
val origin: BattlePokemon?
|
||||
|
||||
/**
|
||||
* The type of [BattleContext].
|
||||
@@ -70,10 +59,10 @@ interface BattleContext {
|
||||
}
|
||||
|
||||
data class BasicContext(
|
||||
override val id: String,
|
||||
override val turn: Int,
|
||||
override val type: BattleContext.Type,
|
||||
override val origin: AbstractBattlePokemon?
|
||||
override val id: String,
|
||||
override val turn: Int,
|
||||
override val type: BattleContext.Type,
|
||||
override val origin: BattlePokemon?
|
||||
) : BattleContext
|
||||
|
||||
data class MissingContext(
|
||||
|
||||
+5
-6
@@ -13,7 +13,6 @@ 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
|
||||
|
||||
@@ -120,8 +119,8 @@ class BattleMessage(rawMessage: String) {
|
||||
return this
|
||||
}
|
||||
|
||||
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 } }
|
||||
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 } }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,7 +142,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): AbstractBattlePokemon? {
|
||||
fun battlePokemon(index: Int, battle: PokemonBattle): BattlePokemon? {
|
||||
val (actorID, pokemonID) = this.pnxAndUuid(index) ?: return null
|
||||
return this.battlePokemon(actorID, pokemonID, battle)
|
||||
}
|
||||
@@ -155,7 +154,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"): AbstractBattlePokemon? {
|
||||
fun battlePokemonFromOptional(battle: PokemonBattle, optionalArg: String = "of"): BattlePokemon? {
|
||||
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
|
||||
@@ -238,7 +237,7 @@ class BattleMessage(rawMessage: String) {
|
||||
null
|
||||
}
|
||||
|
||||
private fun battlePokemon(pnx: String, pokemonID: String, battle: PokemonBattle): AbstractBattlePokemon? = try {
|
||||
private fun battlePokemon(pnx: String, pokemonID: String, battle: PokemonBattle): BattlePokemon? = try {
|
||||
battle.getBattlePokemon(pnx, pokemonID)
|
||||
} catch (_: Exception) {
|
||||
null
|
||||
|
||||
+23
-31
@@ -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,7 +51,6 @@ 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
|
||||
@@ -75,28 +74,27 @@ 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.battlePokemonProvider.getKnownPokemon()
|
||||
.filterIsInstance<BattlePokemon>()
|
||||
.forEach { battlePokemon ->
|
||||
battlePokemon.effectedPokemon.evolutionProxy.current().progress()
|
||||
.filterIsInstance<LastBattleCriticalHitsEvolutionProgress>()
|
||||
.forEach { it.reset() }
|
||||
}
|
||||
actor.pokemonList.forEach { battlePokemon ->
|
||||
battlePokemon.effectedPokemon.evolutionProxy.current().progress()
|
||||
.filterIsInstance<LastBattleCriticalHitsEvolutionProgress>()
|
||||
.forEach { it.reset() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +109,7 @@ open class PokemonBattle(
|
||||
val players = playerUUIDs.mapNotNull { it.getPlayer() }
|
||||
val spectators = mutableSetOf<UUID>()
|
||||
|
||||
val battleId = UUID.randomUUID().toString()
|
||||
val battleId = UUID.randomUUID()
|
||||
|
||||
val showdownMessages = mutableListOf<String>()
|
||||
val battleLog = mutableListOf<String>()
|
||||
@@ -212,10 +210,10 @@ open class PokemonBattle(
|
||||
*
|
||||
* Returns null if the pnx key is invalid or the uuid does not exist.
|
||||
*/
|
||||
fun getBattlePokemon(pnx: String, pokemonID: String): AbstractBattlePokemon {
|
||||
fun getBattlePokemon(pnx: String, pokemonID: String): BattlePokemon {
|
||||
val actor = actors.find { it.showdownId == pnx.substring(0, 2) }
|
||||
?: throw IllegalStateException("Invalid pnx: $pnx - unknown actor")
|
||||
return actor.battlePokemonProvider.getKnownPokemon().find { it.uuid.toString() == pokemonID }
|
||||
return actor.pokemonList.find { it.uuid.toString() == pokemonID }
|
||||
?: throw IllegalStateException("Invalid pnx: $pnx - unknown pokemon")
|
||||
}
|
||||
|
||||
@@ -227,7 +225,7 @@ open class PokemonBattle(
|
||||
|
||||
fun writeShowdownAction(vararg messages: String) {
|
||||
log(messages.joinToString("\n"))
|
||||
showdownBattle.sendMessages(messages.toList())
|
||||
ShowdownService.service.send(battleId, messages.toList().toTypedArray())
|
||||
}
|
||||
|
||||
fun turn(newTurnNumber: Int) {
|
||||
@@ -246,13 +244,9 @@ open class PokemonBattle(
|
||||
fun end() {
|
||||
ended = true
|
||||
this.actors.forEach { actor ->
|
||||
val faintedPokemons = actor.battlePokemonProvider.getKnownPokemon()
|
||||
.filter { it.health <= 0 }
|
||||
.filterIsInstance<BattlePokemon>()
|
||||
val faintedPokemons = actor.pokemonList.filter { it.health <= 0 }
|
||||
actor.getSide().getOppositeSide().actors.forEach { opponent ->
|
||||
val opponentNonFaintedPokemons = opponent.battlePokemonProvider.getKnownPokemon()
|
||||
.filter { it.health > 0 }
|
||||
.filterIsInstance<BattlePokemon>()
|
||||
val opponentNonFaintedPokemons = opponent.pokemonList.filter { it.health > 0 }
|
||||
faintedPokemons.forEach { faintedPokemon ->
|
||||
for (opponentPokemon in opponentNonFaintedPokemons) {
|
||||
val facedFainted = opponentPokemon.facedOpponents.contains(faintedPokemon)
|
||||
@@ -275,7 +269,7 @@ open class PokemonBattle(
|
||||
else -> continue
|
||||
}
|
||||
val experience = Cobblemon.experienceCalculator.calculate(opponentPokemon, faintedPokemon, multiplier)
|
||||
if (experience > 0 && actor.battlePokemonProvider.getKnownPokemon().all { it.health <= 0 }) {
|
||||
if (experience > 0 && actor.pokemonList.all { it.health <= 0 }) {
|
||||
opponent.awardExperience(opponentPokemon, experience)
|
||||
}
|
||||
Cobblemon.evYieldCalculator.calculate(opponentPokemon, faintedPokemon).forEach { (stat, amount) ->
|
||||
@@ -308,15 +302,13 @@ open class PokemonBattle(
|
||||
.filterIsInstance<PokemonEntity>()
|
||||
.forEach{it.pokemon.heal()}
|
||||
actors.forEach { actor ->
|
||||
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()
|
||||
}
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
sendUpdate(BattleEndPacket())
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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
@@ -1,16 +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
|
||||
|
||||
/**
|
||||
* 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()
|
||||
}
|
||||
+10
-20
@@ -8,12 +8,15 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.battles.model.actor
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
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.*
|
||||
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.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.exception.IllegalActionChoiceException
|
||||
@@ -28,11 +31,10 @@ import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
abstract class BattleActor(
|
||||
val uuid: UUID,
|
||||
val battlePokemonProvider: BattlePokemonProvider,
|
||||
val battleAi: BattleAI? = null
|
||||
val pokemonList: MutableList<BattlePokemon>
|
||||
) {
|
||||
init {
|
||||
battlePokemonProvider.getKnownPokemon().forEach { it.actor = this }
|
||||
pokemonList.forEach { it.actor = this }
|
||||
}
|
||||
|
||||
val struct = asMoLangValue()
|
||||
@@ -71,7 +73,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 }
|
||||
|
||||
open fun turn() {
|
||||
fun turn() {
|
||||
val request = request ?: return
|
||||
responses.clear()
|
||||
if(activePokemon.any { it.isAlive() }) {
|
||||
@@ -153,19 +155,7 @@ abstract class BattleActor(
|
||||
sendUpdate(BattleMessagePacket(component))
|
||||
}
|
||||
open fun awardExperience(battlePokemon: BattlePokemon, experience: Int) {}
|
||||
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 sendUpdate(packet: NetworkPacket<*>) {}
|
||||
|
||||
open fun win(otherWinners: List<BattleActor>, losers: List<BattleActor>) {}
|
||||
open fun lose(winners: List<BattleActor>, otherLosers: List<BattleActor>) {}
|
||||
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
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
@@ -1,14 +0,0 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
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
|
||||
}
|
||||
@@ -99,6 +99,7 @@ class Berry(
|
||||
val weight: Float,
|
||||
val boneMealChance: Float
|
||||
) {
|
||||
|
||||
@Transient
|
||||
var identifier: ResourceLocation = identifier
|
||||
internal set
|
||||
@@ -158,7 +159,7 @@ class Berry(
|
||||
* Calculates the yield for a berry tree being planted or replanted after a life cycle.
|
||||
* Triggers [BerryYieldCalculationEvent].
|
||||
*
|
||||
* @param world The [Level] the tree is present in.
|
||||
* @param world The [World] 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.
|
||||
@@ -172,10 +173,9 @@ 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(RICH_MULCH_MIN, RICH_MULCH_MAX)
|
||||
yield += world.random.nextIntBetweenInclusive(1, 2)
|
||||
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() } + RICH_MULCH_MAX
|
||||
fun maxYield() = this.baseYield.last + this.growthFactors.sumOf { it.maxYield() }
|
||||
|
||||
/**
|
||||
* Checks if this berry can mutate with the given [partner].
|
||||
@@ -231,7 +231,6 @@ 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")
|
||||
@@ -248,6 +247,10 @@ 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)
|
||||
@@ -336,8 +339,6 @@ 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()
|
||||
|
||||
@@ -15,10 +15,12 @@ package com.cobblemon.mod.common.api.berry
|
||||
* @author Licious
|
||||
* @since November 28th, 2022
|
||||
*/
|
||||
enum class Flavor(val colour: Int) {
|
||||
SPICY(0x00FF00),
|
||||
DRY(0xFF0000),
|
||||
SWEET(0x0000FF),
|
||||
BITTER(0xFFFF00),
|
||||
SOUR(0xFF00FF);
|
||||
enum class Flavor {
|
||||
|
||||
SPICY,
|
||||
DRY,
|
||||
SWEET,
|
||||
BITTER,
|
||||
SOUR
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.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
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@ package com.cobblemon.mod.common.api.entity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.world.damagesource.DamageSource
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.Entity.MoveFunction
|
||||
import net.minecraft.world.entity.player.Player
|
||||
|
||||
interface PokemonSideDelegate : EntitySideDelegate<PokemonEntity> {
|
||||
|
||||
@@ -8,10 +8,6 @@
|
||||
|
||||
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.
|
||||
*
|
||||
@@ -25,9 +21,4 @@ abstract class Cancelable {
|
||||
fun cancel() {
|
||||
isCanceled = true
|
||||
}
|
||||
|
||||
val cancelFunc: Pair<String, (MoParams) -> MoValue> = "cancel" to {
|
||||
cancel()
|
||||
DoubleValue.ONE
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,6 @@ import com.cobblemon.mod.common.api.reactive.EventObservable
|
||||
import com.cobblemon.mod.common.api.reactive.Observable.Companion.filter
|
||||
import com.cobblemon.mod.common.api.reactive.Observable.Companion.map
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.riding.events.SelectDriverEvent
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
@@ -212,10 +211,6 @@ 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>()
|
||||
@@ -258,12 +253,4 @@ object CobblemonEvents {
|
||||
val HATCH_EGG_PRE = CancelableObservable<HatchEggEvent.Pre>()
|
||||
@JvmField
|
||||
val HATCH_EGG_POST = EventObservable<HatchEggEvent.Post>()
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
//
|
||||
// Riding
|
||||
//
|
||||
// -------------------------------------------------------------------------------------
|
||||
@JvmField
|
||||
val SELECT_DRIVER = EventObservable<SelectDriverEvent>()
|
||||
}
|
||||
|
||||
+12
-1
@@ -8,12 +8,16 @@
|
||||
|
||||
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]
|
||||
@@ -33,6 +37,13 @@ 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 context.getStruct()
|
||||
"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()) },
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
-3
@@ -11,7 +11,6 @@ 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
|
||||
|
||||
@@ -31,8 +30,6 @@ 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,6 +13,8 @@ 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,15 +8,9 @@
|
||||
|
||||
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
|
||||
|
||||
@@ -38,34 +32,4 @@ 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
|
||||
}
|
||||
)
|
||||
}
|
||||
+2
-1
@@ -20,7 +20,8 @@ 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,11 +9,13 @@
|
||||
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 and cosmetic items.
|
||||
* The base for all the events related to held items.
|
||||
*
|
||||
* @see [Pre]
|
||||
* @see [Post]
|
||||
@@ -26,7 +28,7 @@ interface HeldItemEvent {
|
||||
val pokemon: Pokemon
|
||||
|
||||
/**
|
||||
* Fired at the start of [Pokemon.swapHeldItem] and [Pokemon.swapCosmeticItem].
|
||||
* Fired at the start of [Pokemon.swapHeldItem].
|
||||
*
|
||||
* This event should be used to mutate the results of this transaction.
|
||||
*
|
||||
@@ -42,7 +44,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] and [Pokemon.swapCosmeticItem].
|
||||
* Fired at the end of [Pokemon.swapHeldItem].
|
||||
*
|
||||
* @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,7 +9,6 @@
|
||||
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
|
||||
|
||||
/**
|
||||
@@ -24,11 +23,4 @@ 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
|
||||
}
|
||||
)
|
||||
}
|
||||
+1
-4
@@ -13,7 +13,6 @@ 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
|
||||
@@ -48,9 +47,7 @@ sealed interface PokedexDataChangedEvent {
|
||||
override val knowledge: PokedexEntryProgress,
|
||||
override val playerUUID: UUID,
|
||||
override val record: FormDexRecord
|
||||
) : PokedexDataChangedEvent, Cancelable() {
|
||||
val functions = moLangFunctionMap(cancelFunc)
|
||||
}
|
||||
) : PokedexDataChangedEvent, Cancelable()
|
||||
|
||||
class Post(
|
||||
override val dataSource: PokedexEntityData,
|
||||
|
||||
-8
@@ -8,12 +8,8 @@
|
||||
|
||||
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(
|
||||
@@ -24,8 +20,4 @@ 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 },
|
||||
)
|
||||
}
|
||||
+1
-11
@@ -8,10 +8,7 @@
|
||||
|
||||
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
|
||||
|
||||
@@ -28,11 +25,4 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
data class EvolutionAcceptedEvent(
|
||||
override val pokemon: Pokemon,
|
||||
override val evolution: Evolution
|
||||
) : Cancelable(), EvolutionEvent {
|
||||
val context = mutableMapOf<String, MoValue>(
|
||||
"pokemon" to pokemon.struct,
|
||||
"evolution" to evolution.asMoLangValue()
|
||||
)
|
||||
|
||||
val functions = moLangFunctionMap(cancelFunc)
|
||||
}
|
||||
) : Cancelable(), EvolutionEvent
|
||||
+1
-8
@@ -8,8 +8,6 @@
|
||||
|
||||
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
|
||||
|
||||
@@ -25,9 +23,4 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
data class EvolutionCompleteEvent(
|
||||
override val pokemon: Pokemon,
|
||||
override val evolution: Evolution
|
||||
) : EvolutionEvent {
|
||||
val context = mutableMapOf<String, MoValue>(
|
||||
"pokemon" to pokemon.struct,
|
||||
"evolution" to evolution.asMoLangValue()
|
||||
)
|
||||
}
|
||||
) : EvolutionEvent
|
||||
+1
-20
@@ -8,13 +8,8 @@
|
||||
|
||||
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.
|
||||
@@ -30,18 +25,4 @@ data class EvolutionTestedEvent(
|
||||
override val evolution: Evolution,
|
||||
val originalResult: Boolean,
|
||||
var result: Boolean
|
||||
) : 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
|
||||
}
|
||||
)
|
||||
}
|
||||
) : EvolutionEvent
|
||||
|
||||
-3
@@ -16,9 +16,6 @@ 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) {
|
||||
|
||||
+7
-12
@@ -19,6 +19,7 @@ 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
|
||||
@@ -43,7 +44,6 @@ 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,16 +52,13 @@ interface PokemonAndMoveSelectingItem {
|
||||
player.sendSystemMessage(battleLang("bagitem.cannot").red())
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
//val battlePokemon = actor.battlePokemonProvider.getKnownPokemon().find { it.effectedPokemon == entity?.pokemon }
|
||||
val battlePokemon = actor.pokemonList.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) {
|
||||
@@ -143,16 +140,14 @@ interface PokemonAndMoveSelectingItem {
|
||||
}
|
||||
|
||||
fun interactGeneralBattle(player: ServerPlayer, stack: ItemStack, actor: BattleActor): InteractionResultHolder<ItemStack>? {
|
||||
/*
|
||||
PartyMoveSelectCallbacks.createFromPokemon(
|
||||
player = player,
|
||||
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 }!!) },
|
||||
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 }!!) },
|
||||
canSelectMove = ::canUseOnMove,
|
||||
handler = { pk, mv -> applyToBattlePokemon(player, stack, actor.battlePokemonProvider.getKnownPokemon().find { it.effectedPokemon == pk }!!, mv) }
|
||||
handler = { pk, mv -> applyToBattlePokemon(player, stack, actor.pokemonList.find { it.effectedPokemon == pk }!!, mv) }
|
||||
)
|
||||
*/
|
||||
|
||||
return InteractionResultHolder.success(stack)
|
||||
}
|
||||
|
||||
@@ -18,11 +18,7 @@ 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.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 com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.InteractionResultHolder
|
||||
@@ -50,7 +46,7 @@ interface PokemonSelectingItem {
|
||||
|
||||
player.getBattleState()?.let { (_, actor) ->
|
||||
if (bagItem == null) return InteractionResultHolder.fail(stack)
|
||||
// val battlePokemon = actor.battlePokemonProvider.getKnownPokemon().find { it.effectedPokemon == entity?.pokemon }
|
||||
val battlePokemon = actor.pokemonList.find { it.effectedPokemon == entity?.pokemon }
|
||||
|
||||
if (!actor.canFitForcedAction()) {
|
||||
player.sendSystemMessage(battleLang("bagitem.cannot").red())
|
||||
@@ -59,12 +55,9 @@ 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) {
|
||||
@@ -147,16 +140,13 @@ interface PokemonSelectingItem {
|
||||
}
|
||||
|
||||
fun interactGeneralBattle(player: ServerPlayer, stack: ItemStack, actor: BattleActor): InteractionResultHolder<ItemStack> {
|
||||
/*
|
||||
PartySelectCallbacks.createBattleSelect(
|
||||
player = player,
|
||||
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 }!!) }
|
||||
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 }!!) }
|
||||
)
|
||||
|
||||
*/
|
||||
|
||||
return InteractionResultHolder.success(stack)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,6 @@ 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
|
||||
@@ -62,12 +60,8 @@ 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
|
||||
@@ -1008,82 +1002,6 @@ 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())
|
||||
@@ -1116,24 +1034,6 @@ 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,
|
||||
@@ -1270,24 +1170,6 @@ 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,7 +13,6 @@ 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
|
||||
@@ -22,10 +21,7 @@ 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
|
||||
@@ -122,56 +118,6 @@ 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,9 +10,17 @@ 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
|
||||
@@ -32,7 +40,57 @@ object Moves : DataRegistry {
|
||||
override fun reload(manager: ResourceManager) {
|
||||
this.allMoves.clear()
|
||||
this.idMapping.clear()
|
||||
Cobblemon.showdownServer.getMoves().forEach(::register)
|
||||
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.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,6 +8,9 @@
|
||||
|
||||
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
|
||||
@@ -772,6 +775,17 @@ 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)) }
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.pokemon
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.abilities.AbilityPool
|
||||
import com.cobblemon.mod.common.api.abilities.AbilityTemplate
|
||||
@@ -33,8 +32,6 @@ import com.cobblemon.mod.common.api.pokemon.moves.Learnset
|
||||
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
|
||||
@@ -47,29 +44,7 @@ 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.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.adapters.*
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.common.collect.HashBasedTable
|
||||
import com.google.gson.Gson
|
||||
@@ -78,7 +53,6 @@ import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.advancements.critereon.ItemPredicate
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
@@ -119,7 +93,6 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
.registerTypeAdapter(DropEntry::class.java, DropEntryAdapter)
|
||||
.registerTypeAdapter(CompoundTag::class.java, NbtCompoundAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(Component::class.java, TextAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, BiomeLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Block::class.java).type, BlockLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
|
||||
@@ -127,9 +100,6 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
.registerTypeAdapter(EggGroup::class.java, EggGroupAdapter)
|
||||
.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()
|
||||
.create()
|
||||
@@ -151,10 +121,8 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
this.species.forEach(Species::initialize)
|
||||
this.species.forEach(Species::resolveEvolutionMoves)
|
||||
Cobblemon.showdownThread.queue {
|
||||
if (it is CobblemonShowdownBattleServer) {
|
||||
it.registerSpecies()
|
||||
it.indicateSpeciesInitialized()
|
||||
}
|
||||
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.network.chat.Component
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
/**
|
||||
* Responsible for querying [BattlePokemon] for the presence of held items and their consumption.
|
||||
|
||||
@@ -1,25 +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.riding
|
||||
|
||||
import net.minecraft.world.entity.PlayerRideableJumping
|
||||
|
||||
/**
|
||||
* Represents an entity that supports riding.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
interface Rideable : PlayerRideableJumping {
|
||||
|
||||
/**
|
||||
* Denotes the manager responsible for handling any instance of riding taking place on an entity
|
||||
*/
|
||||
val riding: RidingManager
|
||||
|
||||
}
|
||||
@@ -1,128 +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.riding
|
||||
|
||||
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.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
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
|
||||
|
||||
data class RidingManager(val entity: PokemonEntity) {
|
||||
var lastSpeed = 0F
|
||||
var states: MutableMap<ResourceLocation, RidingState> = mutableMapOf()
|
||||
var deltaRotation = Vec2.ZERO
|
||||
|
||||
val runtime: MoLangRuntime by lazy {
|
||||
MoLangRuntime()
|
||||
.setup()
|
||||
.withQueryValue("entity", entity.struct)
|
||||
.also {
|
||||
it.environment.query.addFunction("passenger_count") { DoubleValue(entity.passengers.size.toDouble()) }
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : RidingState> getState(id: ResourceLocation, constructor: (PokemonEntity) -> T): T {
|
||||
val storedState = states[id]
|
||||
if (storedState == null) {
|
||||
val newState = constructor(entity)
|
||||
states[id] = newState
|
||||
return newState
|
||||
}
|
||||
|
||||
return storedState as T
|
||||
}
|
||||
|
||||
fun getController(entity: PokemonEntity): RideController? {
|
||||
return entity.pokemon.riding.controller?.takeIf { it.condition.invoke(entity) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Responsible for handling riding conditions and transitions amongst controllers. This will tick
|
||||
* whenever the entity receives a tickControlled interaction.
|
||||
*/
|
||||
fun tick(entity: PokemonEntity, driver: Player, input: Vec3) {
|
||||
val controller = getController(entity) ?: return
|
||||
|
||||
val pose = controller.pose(entity)
|
||||
entity.entityData.set(PokemonEntity.POSE_TYPE, pose)
|
||||
|
||||
// driver.displayClientMessage(Component.literal("Speed: ").withStyle { it.withColor(ChatFormatting.GREEN) }.append(Component.literal("$lastSpeed b/t")), true)
|
||||
}
|
||||
|
||||
fun speed(entity: PokemonEntity, driver: Player): Float {
|
||||
val controller = getController(entity) ?: return 0.05F
|
||||
this.lastSpeed = controller.speed(entity, driver)
|
||||
return this.lastSpeed
|
||||
}
|
||||
|
||||
fun controlledRotation(entity: PokemonEntity, driver: Player): Vec2 {
|
||||
val controller = getController(entity) ?: return entity.rotationVector
|
||||
val previousRotation = entity.rotationVector
|
||||
val rotation = controller.rotation(entity, driver)
|
||||
this.deltaRotation = Vec2(rotation.x - previousRotation.x, rotation.y - previousRotation.y)
|
||||
return rotation
|
||||
}
|
||||
|
||||
fun clampPassengerRotation(entity: PokemonEntity, driver: LivingEntity) {
|
||||
val controller = getController(entity) ?: return
|
||||
return controller.clampPassengerRotation(entity, driver)
|
||||
}
|
||||
|
||||
fun updatePassengerRotation(entity: PokemonEntity, driver: LivingEntity) {
|
||||
val controller = getController(entity) ?: return
|
||||
return controller.updatePassengerRotation(entity, driver)
|
||||
}
|
||||
|
||||
fun velocity(entity: PokemonEntity, driver: Player, input: Vec3): Vec3 {
|
||||
val controller = getController(entity) ?: return Vec3.ZERO
|
||||
return controller.velocity(entity, driver, input)
|
||||
}
|
||||
|
||||
fun canJump(entity: PokemonEntity, driver: Player): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.canJump(entity, driver)
|
||||
}
|
||||
|
||||
fun jumpVelocity(entity: PokemonEntity, driver: Player, jumpStrength: Int): Vec3 {
|
||||
val controller = getController(entity) ?: return Vec3.ZERO
|
||||
return controller.jumpForce(entity, driver, jumpStrength)
|
||||
}
|
||||
|
||||
fun gravity(entity: PokemonEntity, regularGravity: Double): Double? {
|
||||
val controller = getController(entity) ?: return null
|
||||
return controller.gravity(entity, regularGravity)
|
||||
}
|
||||
|
||||
fun shouldRoll(entity: PokemonEntity): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.shouldRoll(entity)
|
||||
}
|
||||
|
||||
fun shouldRotatePlayerHead(entity: PokemonEntity): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.shouldRotatePlayerHead()
|
||||
}
|
||||
|
||||
fun shouldRotatePokemonHead(entity: PokemonEntity): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.shouldRotatePokemonHead()
|
||||
}
|
||||
|
||||
//FIXME: Make this not just be false for all controllers lol
|
||||
fun dismountOnShift(): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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.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
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class RidingProperties(
|
||||
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, RidingStatDefinition> = buffer.readMap(
|
||||
{ buffer.readEnum<RidingStat>(RidingStat::class.java) },
|
||||
{ RidingStatDefinition.decode(buffer) }
|
||||
)
|
||||
val seats: List<Seat> = buffer.readList { _ -> Seat.decode(buffer) }
|
||||
val conditions = buffer.readList { buffer.readString().asExpression() }
|
||||
val controller = buffer.readNullable { _ ->
|
||||
val key = buffer.readIdentifier()
|
||||
val controller = RideControllerAdapter.types[key]?.getConstructor()?.newInstance() ?: error("Unknown controller key: $key")
|
||||
controller.decode(buffer)
|
||||
return@readNullable controller
|
||||
}
|
||||
|
||||
return RidingProperties(stats = stats, seats = seats, conditions = conditions, controller = controller)
|
||||
}
|
||||
}
|
||||
|
||||
val canRide: Boolean
|
||||
get() = seats.isNotEmpty() && controller != null
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeMap(
|
||||
stats,
|
||||
{ _, stat -> buffer.writeEnum(stat) },
|
||||
{ _, stat -> stat.encode(buffer) }
|
||||
)
|
||||
buffer.writeCollection(seats) { _, seat -> seat.encode(buffer) }
|
||||
buffer.writeCollection(conditions) { _, condition -> buffer.writeString(condition.getString()) }
|
||||
buffer.writeNullable(controller) { _, controller -> controller.encode(buffer) }
|
||||
}
|
||||
|
||||
fun calculate(stat: RidingStat, style: RidingStyle, boosts: Int): Float {
|
||||
val definitions = stats[stat] ?: return 0F
|
||||
return definitions.calculate(style, boosts)
|
||||
}
|
||||
|
||||
fun hasStat(stat: RidingStat, style: RidingStyle): Boolean {
|
||||
return stats[stat]?.ranges?.containsKey(style) == true
|
||||
}
|
||||
}
|
||||
@@ -1,18 +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.riding
|
||||
|
||||
/**
|
||||
* Honestly having a base interface is probably unnecessary I'm just considering whether there's going to be some
|
||||
* kind of shared state later.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 6th, 2024
|
||||
*/
|
||||
interface RidingState
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding
|
||||
|
||||
/**
|
||||
* A general medium for riding. Mainly used for categorizing which stats to pull from and for
|
||||
* presenting a simplified view of riding to users.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since February 17th, 2025
|
||||
*/
|
||||
enum class RidingStyle {
|
||||
LAND,
|
||||
LIQUID,
|
||||
AIR
|
||||
}
|
||||
@@ -1,91 +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.riding
|
||||
|
||||
import com.cobblemon.mod.common.api.net.Encodable
|
||||
import com.cobblemon.mod.common.api.riding.controller.RidingAnimation
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
/**
|
||||
* Seat Properties are responsible for the base information that would then be used to construct a Seat on an entity.
|
||||
*/
|
||||
data class Seat(
|
||||
val locator: String = "seat_1",
|
||||
val offset: Vec3 = Vec3.ZERO,
|
||||
val poseOffsets: MutableList<SeatPoseOffset> = mutableListOf(),
|
||||
val poseAnimations: MutableList<SeatPoseAnimations> = mutableListOf()
|
||||
) : Encodable {
|
||||
fun getOffset(poseType: PoseType) : Vec3 {
|
||||
return poseOffsets.firstOrNull { poseType in it.poseTypes }?.offset ?: offset
|
||||
}
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeString(locator)
|
||||
buffer.writeDouble(offset.x)
|
||||
buffer.writeDouble(offset.y)
|
||||
buffer.writeDouble(offset.z)
|
||||
buffer.writeCollection(poseOffsets) { _, offset -> offset.encode(buffer) }
|
||||
buffer.writeCollection(poseAnimations) { _, animations -> animations.encode(buffer) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) : Seat {
|
||||
return Seat(
|
||||
buffer.readString(),
|
||||
Vec3(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()),
|
||||
buffer.readList { SeatPoseOffset.decode(buffer) },
|
||||
buffer.readList { SeatPoseAnimations.decode(buffer) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SeatPoseOffset {
|
||||
val poseTypes = mutableSetOf<PoseType>()
|
||||
var offset = Vec3.ZERO
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeCollection(poseTypes) { _, poseType -> buffer.writeString(poseType.name) }
|
||||
buffer.writeDouble(offset.x)
|
||||
buffer.writeDouble(offset.y)
|
||||
buffer.writeDouble(offset.z)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) : SeatPoseOffset {
|
||||
val offset = SeatPoseOffset()
|
||||
offset.poseTypes.addAll(buffer.readList { buffer.readString().let { PoseType.valueOf(it) } })
|
||||
offset.offset = Vec3(buffer.readDouble(), buffer.readDouble(), buffer.readDouble())
|
||||
return offset
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SeatPoseAnimations {
|
||||
val poseTypes = mutableSetOf<PoseType>()
|
||||
var animations = mutableListOf<RidingAnimation>()
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeCollection(poseTypes) { _, poseType -> buffer.writeString(poseType.name) }
|
||||
buffer.writeCollection(animations) { _, animation -> animation.encode(buffer) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) : SeatPoseAnimations {
|
||||
val animations = SeatPoseAnimations()
|
||||
animations.poseTypes.addAll(buffer.readList { buffer.readString().let { PoseType.valueOf(it) } })
|
||||
animations.animations = buffer.readList { RidingAnimation.decode(buffer) }
|
||||
return animations
|
||||
}
|
||||
}
|
||||
}
|
||||
-106
@@ -1,106 +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.riding.controller
|
||||
|
||||
import com.cobblemon.mod.common.api.net.Decodable
|
||||
import com.cobblemon.mod.common.api.net.Encodable
|
||||
import com.cobblemon.mod.common.api.riding.RidingState
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
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.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
/**
|
||||
* A riding controller is the internal control mechanism for determining how a pokemon
|
||||
* handles during riding. Controllers come into play once the pokemon being ridden has
|
||||
* established the path it's capable of. For instance, a land based controller could have
|
||||
* the pokemon experience drifting after movement, or generic movement. It's up to the
|
||||
* controller to decide how the pokemon behaves.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
interface RideController : Encodable, Decodable {
|
||||
|
||||
/** A reference key used to denote the individual controller */
|
||||
val key: ResourceLocation
|
||||
|
||||
/**
|
||||
* Specifies the provider of poses which helps control updating the current pose on the pokemon
|
||||
* being ridden. Controllers are expected to define the pose types responsible for posing the entity
|
||||
* through all expected conditions. It should define a default pose, that will be used in all cases
|
||||
* where a pose does not meet the current conditions for the current mount. Typically, this will be
|
||||
* an idle pose.
|
||||
*/
|
||||
val poseProvider: PoseProvider
|
||||
|
||||
/**
|
||||
* Represents a condition that must be met for this controller to be active. For instance, this can be used
|
||||
* to evaluate things such as current velocity or block state of the entity.
|
||||
*/
|
||||
val condition: (PokemonEntity) -> Boolean
|
||||
|
||||
/**
|
||||
* Specifies the pose the ridden mount should be positioned in. This queries the pose provider using
|
||||
* the entity as a means of determining the conditions the entity is currently under. This allows for
|
||||
* dynamic pose updates.
|
||||
*/
|
||||
fun pose(entity: PokemonEntity) : PoseType {
|
||||
return this.poseProvider.select(entity)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the current speed of the mount.
|
||||
*/
|
||||
fun speed(entity: PokemonEntity, driver: Player) : Float
|
||||
|
||||
/**
|
||||
* Sets the rotation of the mount. This is typically based on the controlling driver and is manipulated as
|
||||
* necessary.
|
||||
*/
|
||||
fun rotation(entity: PokemonEntity, driver: LivingEntity) : Vec2
|
||||
|
||||
fun clampPassengerRotation(entity: PokemonEntity, driver: LivingEntity) {}
|
||||
|
||||
fun updatePassengerRotation(entity: PokemonEntity, driver: LivingEntity) {
|
||||
driver.yRot = entity.yRot
|
||||
}
|
||||
|
||||
/**
|
||||
* Manipulates the movement input as necessary by the controller. This is primarily used to apply limits
|
||||
* to the types of movements. For instance, we can apply limits to any sort of sideways movement input, so that
|
||||
* it would otherwise be slower than normal forward movement.
|
||||
*/
|
||||
fun velocity(entity: PokemonEntity, driver: Player, input: Vec3) : Vec3
|
||||
|
||||
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 shouldRoll(entity: PokemonEntity): Boolean = false
|
||||
|
||||
fun getRuntime(entity: PokemonEntity) = entity.riding.runtime
|
||||
|
||||
fun shouldRotatePokemonHead(): Boolean = false
|
||||
fun shouldRotatePlayerHead(): Boolean = false
|
||||
|
||||
fun <T : RidingState> getState(entity: PokemonEntity, constructor: (PokemonEntity) -> T): T {
|
||||
return entity.riding.getState(key, constructor)
|
||||
}
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeIdentifier(this.key)
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +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.riding.controller
|
||||
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class RidingAnimation(
|
||||
val fileName: String,
|
||||
val animationName: String
|
||||
) {
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeString(fileName)
|
||||
buffer.writeString(animationName)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) : RidingAnimation {
|
||||
return RidingAnimation(
|
||||
buffer.readString(),
|
||||
buffer.readString()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
-15
@@ -1,15 +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.riding.controller.posing
|
||||
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import java.util.function.Predicate
|
||||
|
||||
data class PoseOption(val pose: PoseType, val condition: Predicate<PokemonEntity>)
|
||||
-31
@@ -1,31 +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.riding.controller.posing
|
||||
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
|
||||
class PoseProvider(private val fallback: PoseType) {
|
||||
|
||||
private val options = mutableListOf<PoseOption>()
|
||||
|
||||
fun select(entity: PokemonEntity) : PoseType {
|
||||
return this.options.stream()
|
||||
.filter { it.condition.test(entity) }
|
||||
.map { it.pose }
|
||||
.findFirst()
|
||||
.orElse(this.fallback)
|
||||
}
|
||||
|
||||
fun with(option: PoseOption) : PoseProvider {
|
||||
this.options.add(option)
|
||||
return this
|
||||
}
|
||||
|
||||
}
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.events
|
||||
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
data class SelectDriverEvent(val options: Set<LivingEntity>) {
|
||||
|
||||
private var result: DriverSuggestion? = null
|
||||
|
||||
fun result(): LivingEntity? {
|
||||
return this.result?.entity
|
||||
}
|
||||
|
||||
/**
|
||||
* Suggests a particular living entity as a potential driver. Only non-negative
|
||||
* values are permitted by this function. All priority values with lesser priorities
|
||||
* will be outright ignored.
|
||||
*/
|
||||
fun suggest(target: LivingEntity, priority: Int) {
|
||||
if (priority >= 0 && priority > (this.result?.priority ?: -1)) {
|
||||
this.result = DriverSuggestion(target, priority)
|
||||
}
|
||||
}
|
||||
|
||||
data class DriverSuggestion(val entity: LivingEntity, val priority: Int)
|
||||
}
|
||||
@@ -1,38 +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.riding.stats
|
||||
|
||||
import com.cobblemon.mod.common.api.berry.Flavor
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
/**
|
||||
* A stat that is used for riding Pokémon. The exact implementation of each of these depends on the [com.cobblemon.mod.common.api.riding.controller.RideController].
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since February 17th, 2025
|
||||
*/
|
||||
enum class RidingStat(
|
||||
val flavour: Flavor
|
||||
) {
|
||||
SPEED(Flavor.SWEET),
|
||||
ACCELERATION(Flavor.SPICY),
|
||||
SKILL(Flavor.DRY),
|
||||
JUMP(Flavor.BITTER),
|
||||
STAMINA(Flavor.SOUR);
|
||||
|
||||
companion object {
|
||||
fun getByName(name: String) = RidingStat.entries.firstOrNull { it.name.equals(name, ignoreCase = true) }
|
||||
}
|
||||
|
||||
val displayName: Component
|
||||
get() = lang("riding.stat.${name.lowercase()}.name")
|
||||
val description: Component
|
||||
get() = lang("riding.stat.${name.lowercase()}.desc")
|
||||
}
|
||||
-70
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.stats
|
||||
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.net.IntSize
|
||||
import com.cobblemon.mod.common.util.readSizedInt
|
||||
import com.cobblemon.mod.common.util.readText
|
||||
import com.cobblemon.mod.common.util.writeSizedInt
|
||||
import com.cobblemon.mod.common.util.writeText
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
/**
|
||||
* The definition of all the different information related to a specific [RidingStat] on a Pokémon species.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since February 17th, 2025
|
||||
*/
|
||||
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]. */
|
||||
var displayName: Component? = null
|
||||
/** Description for the stat, if null falls back to [RidingStat.description]. */
|
||||
var description: Component? = null
|
||||
|
||||
fun calculate(style: RidingStyle, aprijuiceBoost: Int): Float {
|
||||
val range = ranges[style] ?: ranges[RidingStyle.LAND] ?: return 0F
|
||||
val boostQuotient = aprijuiceBoost / 255F
|
||||
return range.first + (range.last - range.first) * boostQuotient
|
||||
}
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeNullable(displayName) { _, it -> buffer.writeText(it) }
|
||||
buffer.writeNullable(description) { _, it -> buffer.writeText(it) }
|
||||
buffer.writeMap(
|
||||
ranges,
|
||||
{ _, it -> buffer.writeEnum(it) },
|
||||
{ _, it ->
|
||||
buffer.writeSizedInt(IntSize.U_BYTE, it.first)
|
||||
buffer.writeSizedInt(IntSize.U_BYTE, it.last)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
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 RidingStatDefinition().apply {
|
||||
this.displayName = displayName
|
||||
this.description = description
|
||||
this.ranges.putAll(ranges)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-6
@@ -8,11 +8,9 @@
|
||||
|
||||
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
|
||||
@@ -22,8 +20,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 kotlin.math.ceil
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import kotlin.math.ceil
|
||||
|
||||
/**
|
||||
* A [SpawnDetail] for spawning a [PokemonEntity].
|
||||
@@ -71,9 +69,7 @@ class PokemonSpawnDetail : SpawnDetail() {
|
||||
}
|
||||
|
||||
override fun autoLabel() {
|
||||
struct.addFunction("pokemon") { pokemon.asMoLangValue() }
|
||||
struct.addFunction("min_level") { DoubleValue(getDerivedLevelRange().start.toDouble()) }
|
||||
struct.addFunction("max_level") { DoubleValue(getDerivedLevelRange().endInclusive.toDouble()) }
|
||||
val pokemonStruct = pokemon.asStruct()
|
||||
if (pokemon.species != null) {
|
||||
val species = PokemonSpecies.getByIdentifier(pokemon.species!!.asIdentifierDefaultingNamespace())
|
||||
if (species != null) {
|
||||
@@ -92,6 +88,7 @@ class PokemonSpawnDetail : SpawnDetail() {
|
||||
}
|
||||
}
|
||||
|
||||
struct.setDirectly("pokemon", pokemonStruct)
|
||||
super.autoLabel()
|
||||
}
|
||||
|
||||
|
||||
+13
-14
@@ -8,12 +8,12 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.spawning.detail
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.struct.ArrayStruct
|
||||
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.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,7 +21,6 @@ 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
|
||||
|
||||
/**
|
||||
@@ -56,21 +55,21 @@ abstract class SpawnDetail : ModDependant {
|
||||
|
||||
var labels = mutableListOf<String>()
|
||||
|
||||
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) } }
|
||||
)
|
||||
val struct: VariableStruct = VariableStruct()
|
||||
|
||||
override var neededInstalledMods = listOf<String>()
|
||||
override var neededUninstalledMods = listOf<String>()
|
||||
|
||||
open fun autoLabel() {}
|
||||
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 getName() = displayName?.asTranslated() ?: id.text()
|
||||
|
||||
|
||||
@@ -124,10 +124,7 @@ 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,11 +42,7 @@ object BagItems : DataRegistry {
|
||||
|
||||
init {
|
||||
observable.subscribe {
|
||||
if (Cobblemon.showdownServer is CobblemonShowdownBattleServer) {
|
||||
Cobblemon.showdownThread.queue {
|
||||
(Cobblemon.showdownServer as CobblemonShowdownBattleServer).registerBagItems()
|
||||
}
|
||||
}
|
||||
Cobblemon.showdownThread.queue(ShowdownService::registerBagItems)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
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
|
||||
@@ -24,15 +25,29 @@ 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 com.cobblemon.mod.common.util.swap
|
||||
import java.util.UUID
|
||||
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 java.util.UUID
|
||||
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 kotlin.collections.set
|
||||
import kotlin.collections.sortedBy
|
||||
|
||||
object BattleBuilder {
|
||||
@JvmOverloads
|
||||
@@ -77,21 +92,18 @@ object BattleBuilder {
|
||||
val errors = ErroredBattleStart()
|
||||
|
||||
for ((player, actor) in arrayOf(player1 to player1Actor, player2 to player2Actor)) {
|
||||
/*
|
||||
if (actor.battlePokemonProvider.getKnownPokemon().filter { it.health > 0 }.size < battleFormat.battleType.slotsPerActor) {
|
||||
if (actor.pokemonList.filter { it.health > 0 }.size < battleFormat.battleType.slotsPerActor) {
|
||||
errors.participantErrors[actor] += BattleStartError.insufficientPokemon(
|
||||
actorEntity = player,
|
||||
requiredCount = battleFormat.battleType.slotsPerActor,
|
||||
hadCount = actor.battlePokemonProvider.getKnownPokemon().filter { it.health > 0 }.size
|
||||
hadCount = actor.pokemonList.filter { it.health > 0 }.size
|
||||
)
|
||||
}
|
||||
|
||||
if (actor.battlePokemonProvider.getKnownPokemon().any { it.entity?.isBusy == true }) {
|
||||
if (actor.pokemonList.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)
|
||||
}
|
||||
@@ -159,21 +171,18 @@ object BattleBuilder {
|
||||
}
|
||||
|
||||
for ((player, actor) in players.zip(playerActors)) {
|
||||
/*
|
||||
if (actor.battlePokemonProvider.getKnownPokemon().size < battleFormat.battleType.slotsPerActor) {
|
||||
if (actor.pokemonList.size < battleFormat.battleType.slotsPerActor) {
|
||||
errors.participantErrors[actor] += BattleStartError.insufficientPokemon(
|
||||
actorEntity = player,
|
||||
requiredCount = battleFormat.battleType.slotsPerActor,
|
||||
hadCount = actor.battlePokemonProvider.getKnownPokemon().size
|
||||
hadCount = actor.pokemonList.size
|
||||
)
|
||||
}
|
||||
|
||||
if (actor.battlePokemonProvider.getKnownPokemon().any { it.entity?.isBusy == true }) {
|
||||
if (actor.pokemonList.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)
|
||||
}
|
||||
@@ -243,30 +252,26 @@ 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.battlePokemonProvider.getKnownPokemon().size
|
||||
hadCount = playerActor.pokemonList.size
|
||||
)
|
||||
}
|
||||
|
||||
if (playerActor.battlePokemonProvider.getKnownPokemon().size < battleFormat.battleType.slotsPerActor) {
|
||||
if (playerActor.pokemonList.size < battleFormat.battleType.slotsPerActor) {
|
||||
errors.participantErrors[playerActor] += BattleStartError.insufficientPokemon(
|
||||
actorEntity = player,
|
||||
requiredCount = battleFormat.battleType.slotsPerActor,
|
||||
hadCount = playerActor.battlePokemonProvider.getKnownPokemon().size
|
||||
hadCount = playerActor.pokemonList.size
|
||||
)
|
||||
}
|
||||
|
||||
if (playerActor.battlePokemonProvider.getKnownPokemon().any { it.entity?.isBusy == true }) {
|
||||
if (playerActor.pokemonList.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)
|
||||
}
|
||||
@@ -275,8 +280,6 @@ object BattleBuilder {
|
||||
errors.participantErrors[wildActor] += BattleStartError.alreadyInBattle(wildActor)
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
playerActor.battleTheme = pokemonEntity.getBattleTheme()
|
||||
|
||||
return if (errors.isEmpty) {
|
||||
@@ -315,16 +318,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.battlePokemonProvider.getKnownPokemon().size < battleFormat.battleType.slotsPerActor) {
|
||||
|
||||
if (playerActor.pokemonList.size < battleFormat.battleType.slotsPerActor) {
|
||||
errors.participantErrors[playerActor] += BattleStartError.insufficientPokemon(
|
||||
actorEntity = player,
|
||||
requiredCount = battleFormat.battleType.slotsPerActor,
|
||||
hadCount = playerActor.battlePokemonProvider.getKnownPokemon().size
|
||||
hadCount = playerActor.pokemonList.size
|
||||
)
|
||||
}
|
||||
|
||||
@@ -337,20 +340,20 @@ object BattleBuilder {
|
||||
return errors
|
||||
}
|
||||
|
||||
val npcActor = NPCBattleActor(npcEntity, npcParty)
|
||||
val npcActor = NPCBattleActor(npcEntity, npcParty, npcEntity.skill ?: npcEntity.npc.skill)
|
||||
// if (npcEntity.battleIds.get().isPresent) {
|
||||
// errors.participantErrors[npcActor] += BattleStartError.alreadyInBattle(npcActor)
|
||||
// }
|
||||
|
||||
if (npcActor.battlePokemonProvider.getKnownPokemon().filter { it.health > 0 }.size < battleFormat.battleType.slotsPerActor) {
|
||||
if (npcActor.pokemonList.filter { it.health > 0 }.size < battleFormat.battleType.slotsPerActor) {
|
||||
errors.participantErrors[npcActor] += BattleStartError.insufficientPokemon(
|
||||
actorEntity = npcEntity,
|
||||
requiredCount = battleFormat.battleType.slotsPerActor,
|
||||
hadCount = npcActor.battlePokemonProvider.getKnownPokemon().size
|
||||
hadCount = npcActor.pokemonList.size
|
||||
)
|
||||
}
|
||||
|
||||
if (playerActor.battlePokemonProvider.getKnownPokemon().any { it.entity?.isBusy == true }) {
|
||||
if (playerActor.pokemonList.any { it.entity?.isBusy == true }) {
|
||||
errors.participantErrors[playerActor] += BattleStartError.targetIsBusy(player.displayName ?: player.name)
|
||||
}
|
||||
|
||||
@@ -367,8 +370,6 @@ object BattleBuilder {
|
||||
} else {
|
||||
errors
|
||||
}
|
||||
*/
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,7 +398,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.showdown.runner.remote.RemoteShowdownBattle
|
||||
import com.cobblemon.mod.common.battles.runner.ShowdownService
|
||||
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<String, PokemonBattle>()
|
||||
private val battleMap = ConcurrentHashMap<UUID, PokemonBattle>()
|
||||
|
||||
fun onServerStarted() {
|
||||
battleMap.clear()
|
||||
@@ -161,23 +161,22 @@ object BattleRegistry {
|
||||
repeat(battle.format.battleType.slotsPerActor) {
|
||||
actor.activePokemon.add(ActiveBattlePokemon(actor))
|
||||
}
|
||||
val entities = actor.battlePokemonProvider.getKnownPokemon().mapNotNull { it.entity }
|
||||
val entities = actor.pokemonList.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.battlePokemonProvider.getKnownPokemon().packTeam()}"}""")
|
||||
messages.add(""">player ${actor.showdownId} {"name":"${actor.uuid}","team":"${actor.pokemonList.packTeam()}"}""")
|
||||
}
|
||||
|
||||
// -> Set team size
|
||||
for (actor in battle.actors.sortedBy { it.showdownId }) {
|
||||
messages.add(">${actor.showdownId} team ${actor.battlePokemonProvider.getKnownPokemon().count()}")
|
||||
messages.add(">${actor.showdownId} team ${actor.pokemonList.count()}")
|
||||
}
|
||||
|
||||
// Compiles the request and sends it off
|
||||
val showdownBattle = Cobblemon.showdownServer.initializeNewBattle(battle.battleId.toString(), messages.toTypedArray())
|
||||
battle.showdownBattle = showdownBattle
|
||||
ShowdownService.service.startBattle(battle, messages.toTypedArray())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -215,32 +214,12 @@ 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: String) : PokemonBattle? {
|
||||
fun getBattle(id: UUID) : 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.battlePokemonProvider.getKnownPokemon().find { it.uuid == newPokemonId }
|
||||
val pokemon = activeBattlePokemon.actor.pokemonList.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.battlePokemonProvider.getKnownPokemon().indexOfFirst { it.uuid == newPokemonId } + 1}"
|
||||
return "switch ${activeBattlePokemon.actor.pokemonList.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<String, BattleMessage>()
|
||||
val lastCauser = mutableMapOf<UUID, 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: String, message: String) {
|
||||
fun interpretMessage(battleId: UUID, 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: AbstractBattlePokemon) {
|
||||
fun broadcastOptionalAbility(battle: PokemonBattle, effect: Effect?, pokemon: BattlePokemon) {
|
||||
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: AbstractBattlePokemon) {
|
||||
fun broadcastAbility(battle: PokemonBattle, effect: Effect, pokemon: BattlePokemon) {
|
||||
if (effect.type != Effect.Type.ABILITY) return
|
||||
battle.dispatchWaiting(0.5F) {
|
||||
val lang = battleLang("ability.generic", pokemon.getName(), effect.typelessData).yellow()
|
||||
|
||||
@@ -8,30 +8,28 @@
|
||||
|
||||
package com.cobblemon.mod.common.battles
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.showdown.runner.ShowdownBattleServer
|
||||
import java.util.LinkedList
|
||||
import java.util.Queue
|
||||
import com.cobblemon.mod.common.battles.runner.ShowdownService
|
||||
import java.util.*
|
||||
import java.util.concurrent.CountDownLatch
|
||||
|
||||
class ShowdownThread : Thread("Cobblemon Showdown") {
|
||||
|
||||
private val latch = CountDownLatch(1)
|
||||
|
||||
private val whenReady : Queue<(ShowdownBattleServer) -> Unit> = LinkedList()
|
||||
private val whenReady : Queue<(ShowdownService) -> Unit> = LinkedList()
|
||||
|
||||
fun launch() {
|
||||
this.start()
|
||||
this.latch.await()
|
||||
for (action in whenReady) {
|
||||
action(Cobblemon.showdownServer)
|
||||
action(ShowdownService.service)
|
||||
}
|
||||
}
|
||||
|
||||
fun queue(action: (ShowdownBattleServer) -> Unit) {
|
||||
fun queue(action: (ShowdownService) -> Unit) {
|
||||
if (this.latch.count == 0L) {
|
||||
action(Cobblemon.showdownServer)
|
||||
action(ShowdownService.service)
|
||||
} else {
|
||||
this.whenReady.add(action)
|
||||
}
|
||||
@@ -39,7 +37,7 @@ class ShowdownThread : Thread("Cobblemon Showdown") {
|
||||
|
||||
override fun run() {
|
||||
LOGGER.info("Starting showdown service...")
|
||||
Cobblemon.showdownServer.connect()
|
||||
ShowdownService.service.openConnection()
|
||||
LOGGER.info("Showdown has been started!")
|
||||
this.latch.countDown()
|
||||
}
|
||||
|
||||
+10
-8
@@ -8,19 +8,21 @@
|
||||
|
||||
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.BattleActor
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.StaticBattlePokemonProvider
|
||||
import com.cobblemon.mod.common.api.battles.model.ai.BattleAI
|
||||
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 net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import java.util.UUID
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
open class MultiPokemonBattleActor(
|
||||
uuid: UUID = UUID.randomUUID(),
|
||||
pokemonList: List<BattlePokemon>
|
||||
) : BattleActor(uuid, StaticBattlePokemonProvider(pokemonList)) {
|
||||
class MultiPokemonBattleActor(
|
||||
pokemonList: List<BattlePokemon>,
|
||||
artificialDecider: BattleAI = RandomBattleAI(),
|
||||
uuid: UUID = UUID.randomUUID()
|
||||
) : AIBattleActor(uuid, pokemonList, artificialDecider) {
|
||||
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,25 +13,24 @@ 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<AbstractBattlePokemon>,
|
||||
) : BattleActor(uuid, StaticBattlePokemonProvider(pokemonList.toMutableList())), EntityBackedBattleActor<ServerPlayer> {
|
||||
pokemonList: List<BattlePokemon>,
|
||||
) : BattleActor(uuid, pokemonList.toMutableList()), EntityBackedBattleActor<ServerPlayer> {
|
||||
|
||||
override val initialPos: Vec3?
|
||||
override val entity: ServerPlayer?
|
||||
|
||||
+10
-6
@@ -8,24 +8,28 @@
|
||||
|
||||
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 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
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class PokemonBattleActor(
|
||||
uuid: UUID,
|
||||
val pokemon: BattlePokemon,
|
||||
override val fleeDistance: Float,
|
||||
) : MultiPokemonBattleActor(uuid, listOf(pokemon)), EntityBackedBattleActor<PokemonEntity>, FleeableBattleActor {
|
||||
artificialDecider: BattleAI = RandomBattleAI()
|
||||
) : AIBattleActor(uuid, listOf(pokemon), artificialDecider), EntityBackedBattleActor<PokemonEntity>, FleeableBattleActor {
|
||||
|
||||
override val initialPos: Vec3?
|
||||
init {
|
||||
@@ -52,7 +56,7 @@ class PokemonBattleActor(
|
||||
if (packet is BattleEndPacket) {
|
||||
// Do some shit
|
||||
val entity = entity ?: return
|
||||
entity.battleId = ""
|
||||
entity.battleId = null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
|
||||
package com.cobblemon.mod.common.battles.actor
|
||||
|
||||
import com.cobblemon.mod.common.api.battles.model.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.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
@@ -19,7 +21,8 @@ class TrainerBattleActor(
|
||||
val trainerName: String,
|
||||
uuid: UUID,
|
||||
pokemonList: List<BattlePokemon>,
|
||||
) : BattleActor(uuid, StaticBattlePokemonProvider(pokemonList)) {
|
||||
artificialDecider: BattleAI
|
||||
) : AIBattleActor(uuid, pokemonList, artificialDecider) {
|
||||
override fun getName() = trainerName.asTranslated()
|
||||
override fun nameOwned(name: String): MutableComponent = battleLang("owned_pokemon", this.getName(), name)
|
||||
override val type = ActorType.NPC
|
||||
|
||||
@@ -8,13 +8,21 @@
|
||||
|
||||
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,
|
||||
@@ -22,7 +30,7 @@ class RandomBattleAI : BattleAI {
|
||||
forceSwitch: Boolean
|
||||
): ShowdownActionResponse {
|
||||
if (forceSwitch || activeBattlePokemon.isGone()) {
|
||||
val switchTo = activeBattlePokemon.actor.battlePokemonProvider.getKnownPokemon().filter { it.canBeSentOut() }.randomOrNull()
|
||||
val switchTo = activeBattlePokemon.actor.pokemonList.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)
|
||||
@@ -46,6 +54,4 @@ class RandomBattleAI : BattleAI {
|
||||
MoveActionResponse(move.id, (chosenTarget as ActiveBattlePokemon).getPNX())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
@@ -10,31 +10,32 @@ 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.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.battles.*
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import java.util.UUID
|
||||
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 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
|
||||
@@ -350,7 +351,7 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
forceSwitch: Boolean
|
||||
): ShowdownActionResponse {
|
||||
if (forceSwitch || activeBattlePokemon.isGone()) {
|
||||
val switchTo = activeBattlePokemon.actor.battlePokemonProvider.getKnownPokemon().filter { it.canBeSentOut() }.randomOrNull()
|
||||
val switchTo = activeBattlePokemon.actor.pokemonList.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)
|
||||
@@ -628,19 +629,14 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
|
||||
if (forceSwitch || activeBattlePokemon.isGone()) {
|
||||
if ((forceSwitch && battle.turn == 1) || (activeBattlePokemon.isGone() && battle.turn == 1)) {
|
||||
val switchTo = activeBattlePokemon.actor.battlePokemonProvider.getKnownPokemon()
|
||||
.filterIsInstance<BattlePokemon>()
|
||||
.filter { it.canBeSentOut() }
|
||||
.randomOrNull()
|
||||
val switchTo = activeBattlePokemon.actor.pokemonList.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.battlePokemonProvider.getKnownPokemon()
|
||||
.filterIsInstance<BattlePokemon>()
|
||||
.filter { (it.health > 0) && (it.uuid != (activeBattlePokemon.battlePokemon?.uuid ?: true)) } //it.uuid != mon.pokemon!!.uuid && it.health > 0 }
|
||||
val availableSwitches = activeBattlePokemon.actor.pokemonList.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) }
|
||||
@@ -655,7 +651,7 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
|
||||
//return SwitchActionResponse(switchTo.uuid)
|
||||
|
||||
/*val availableSwitches = p2Actor.battlePokemonProvider.getKnownPokemon().filter { it.health > 0 } //it.uuid != mon.pokemon!!.uuid && it.health > 0 }
|
||||
/*val availableSwitches = p2Actor.pokemonList.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)
|
||||
@@ -778,10 +774,8 @@ 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.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 }
|
||||
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 }
|
||||
|
||||
// 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
|
||||
@@ -856,12 +850,10 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
|
||||
// Deal with non-weather related field changing effects
|
||||
for (move in moveset.moves.filter { !it.disabled }) {
|
||||
val availableSwitches = p2Actor.battlePokemonProvider.getKnownPokemon()
|
||||
.filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }
|
||||
.filterIsInstance<BattlePokemon>()
|
||||
val availableSwitches = p2Actor.pokemonList.filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }
|
||||
|
||||
// Tailwind
|
||||
if (move.pp > 0 && move.id == "tailwind" && move.id != npcSideTailwindCondition && p2Actor.battlePokemonProvider.getKnownPokemon().filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }.size > 2) {
|
||||
if (move.pp > 0 && move.id == "tailwind" && move.id != npcSideTailwindCondition && p2Actor.pokemonList.filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }.size > 2) {
|
||||
return chooseMove(move, activeBattlePokemon)
|
||||
}
|
||||
|
||||
@@ -882,7 +874,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.battlePokemonProvider.getKnownPokemon().filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }.size > 1) {
|
||||
&& p2Actor.pokemonList.filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }.size > 1) {
|
||||
return chooseMove(move, activeBattlePokemon)
|
||||
}
|
||||
|
||||
@@ -890,7 +882,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.battlePokemonProvider.getKnownPokemon().filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }.size > 1) {
|
||||
&& p2Actor.pokemonList.filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }.size > 1) {
|
||||
return chooseMove(move, activeBattlePokemon)
|
||||
}
|
||||
}
|
||||
@@ -1283,9 +1275,7 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
|
||||
// switch out
|
||||
if (shouldSwitchOut(request, battle, activeBattlePokemon, moveset)) {
|
||||
val availableSwitches = p1Actor.battlePokemonProvider.getKnownPokemon()
|
||||
.filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }
|
||||
.filterIsInstance<BattlePokemon>()
|
||||
val availableSwitches = p1Actor.pokemonList.filter { it.uuid != mon.pokemon!!.uuid && it.health > 0 }
|
||||
val bestEstimation = availableSwitches.maxOfOrNull { estimateMatchup(activeBattlePokemon, request, battle, it.effectedPokemon) }
|
||||
/*availableSwitches.forEach {
|
||||
estimateMatchup(request, battle, it.effectedPokemon)
|
||||
@@ -1487,9 +1477,7 @@ 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.battlePokemonProvider.getKnownPokemon()
|
||||
.filter { it.uuid != mon.activePokemon.pokemon!!.uuid && it.health > 0 }
|
||||
.filterIsInstance<BattlePokemon>()
|
||||
val availableSwitches = p2Actor.pokemonList.filter { it.uuid != mon.activePokemon.pokemon!!.uuid && it.health > 0 }
|
||||
|
||||
val currentNPCAbility = request.side?.pokemon!!.first().ability
|
||||
|
||||
@@ -1796,7 +1784,7 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
|
||||
val p1Boosts = battle.side1.activePokemon.firstOrNull()?.battlePokemon?.statChanges
|
||||
val playerSide1 = battle.side1.actors.first()
|
||||
val numPlayerPokemon = playerSide1.battlePokemonProvider.getKnownPokemon().count()
|
||||
val numPlayerPokemon = playerSide1.pokemonList.count()
|
||||
|
||||
|
||||
/*val lastMajorBattleMessage = if (battle.majorBattleActions.entries.isNotEmpty()) battle.majorBattleActions?.entries?.last()?.value?.rawMessage else ""
|
||||
@@ -1841,9 +1829,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.battlePokemonProvider.getKnownPokemon().count()
|
||||
val numNPCPokemon = playerSide2.pokemonList.count()
|
||||
|
||||
//val nextAvailablePokemon = playerSide2.battlePokemonProvider.getKnownPokemon().filter { it.health != 0 }.first().effectedPokemon.uuid
|
||||
//val nextAvailablePokemon = playerSide2.pokemonList.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
|
||||
@@ -1870,7 +1858,7 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
//mon.stats = pokemon.stats
|
||||
p1.activePokemon.moves = pokemon1.moveSet.getMoves()
|
||||
p1.nRemainingMons = battle.side1.actors.sumOf { actor ->
|
||||
actor.battlePokemonProvider.getKnownPokemon().count { pokemon ->
|
||||
actor.pokemonList.count { pokemon ->
|
||||
pokemon.health != 0
|
||||
}
|
||||
}
|
||||
@@ -1883,7 +1871,7 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
p1.party[partyPokemonIndex] = p1.activePokemon
|
||||
}
|
||||
|
||||
//p1.availableSwitches = playerSide1.battlePokemonProvider.getKnownPokemon().filter { it.uuid != p1.pokemon.uuid && it.health > 0 }
|
||||
//p1.availableSwitches = playerSide1.pokemonList.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)
|
||||
@@ -1901,7 +1889,7 @@ class StrongBattleAI(skill: Int) : BattleAI {
|
||||
//mon.stats = pokemon.stats
|
||||
p2.activePokemon.moves = pokemon2.moveSet.getMoves()
|
||||
p2.nRemainingMons = battle.side2.actors.sumOf { actor ->
|
||||
actor.battlePokemonProvider.getKnownPokemon().count { pokemon ->
|
||||
actor.pokemonList.count { pokemon ->
|
||||
pokemon.health != 0
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -11,7 +11,9 @@ 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
|
||||
@@ -21,8 +23,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 net.minecraft.network.chat.Component
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
/**
|
||||
* Format: |-activate|POKEMON|EFFECT
|
||||
@@ -57,7 +59,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,
|
||||
@@ -79,7 +81,6 @@ 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(" ", ""))
|
||||
@@ -91,8 +92,6 @@ 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)
|
||||
|
||||
+4
-2
@@ -15,6 +15,7 @@ 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
|
||||
@@ -51,11 +52,12 @@ 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
|
||||
providers = providers,
|
||||
level = battle.players.firstOrNull()?.level()
|
||||
)
|
||||
this.future = actionEffect.run(context)
|
||||
holds = context.holds // Reference so future things can check on this action effect's holds
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user