Compare commits

...
Author SHA1 Message Date
Segfault Guy 5661ae2cb0 Command and showdown service update for testing team validation. 2025-09-22 10:09:56 -04:00
Segfault Guy 9e9603d60d Merge remote-tracking branch 'origin/main' into experimental_showdown_changes 2025-08-20 23:39:03 -04:00
Polymeta 5b90a4d894 prevent clientActions inside dialogues being executed twice
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-08-21 00:06:31 +01:00
Polymeta 69d3ef23ef fix pokedex lookup during battle causing crashes with namespaced species
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-08-20 21:50:03 +01:00
Landon ca8bcd966f Merge branch 'playericonfix' into 'main'
don't touch my mixins if you're not going to bother testing your changes

See merge request cable-mc/cobblemon!1789
2025-08-19 19:06:49 +00:00
Segfault Guy 12c7318625 don't touch my mixins if you're not going to bother testing your changes 2025-08-19 09:42:44 -04:00
Hiroku 4f917b94e8 Merge branch 'narrator-dev-fix' into 'main'
Fixed narrator-related GUI crashes on NeoForge

See merge request cable-mc/cobblemon!1788
2025-08-19 12:03:57 +00:00
gruxor 9e82cb2516 Fixed narrator-related GUI crashes on NeoForge 2025-08-19 07:37:27 -04:00
Polymeta bbf85d5804 Merge branch 'riding-fix-failing-asserts' into 'main'
Move and rename the scaleToRange function and place it in the RidingBehaviour...

See merge request cable-mc/cobblemon!1783
2025-08-19 09:20:17 +00:00
Jackson BowesandPolymeta 9daa85750b Move and rename the scaleToRange function and place it in the RidingBehaviour... 2025-08-19 09:20:17 +00:00
Polymeta 6f7c3b0681 Merge branch 'riding-species-sprint-and-jet-crash-fix' into 'main'
Add ability to disable sprinting per species for horse and fix unneeded assert in a Jet function.

See merge request cable-mc/cobblemon!1780
2025-08-19 08:38:00 +00:00
Polymeta d262bb6136 Merge branch 'sound' into 'main'
Tatami, Hearty Grains and cooking sounds

See merge request cable-mc/cobblemon!1784
2025-08-19 08:37:18 +00:00
Polymeta 7509934394 Merge branch 'cooking-pot-ui-tweaks' into 'main'
Cooking Pot UI Tweaks + Bugfix

See merge request cable-mc/cobblemon!1785
2025-08-19 08:35:32 +00:00
GertimoshkaandPolymeta a0ae226506 Cooking Pot UI Tweaks + Bugfix 2025-08-19 08:35:32 +00:00
Hiroku 0dde8d27e6 Merge branch 'ihatebugtypes' into 'main'
kill all bug type pokemon

Closes #1541

See merge request cable-mc/cobblemon!1786
2025-08-18 05:32:06 +00:00
Segfault Guy 559e728bc3 Deprecate ContextManager. 2025-08-18 00:34:12 -04:00
Segfault Guy dcea1bc67f Merge remote-tracking branch 'origin/main' into ihatebugtypes 2025-08-18 00:29:52 -04:00
Segfault Guy 7fe91f7ad0 Original natures for flavor-bias berries 2025-08-17 14:29:18 -04:00
jackowes 085972f2d3 Add ability to disable sprinting per species for horse and fix unneeded assert in a Jet function. 2025-08-17 01:51:35 -05:00
Segfault Guy 58a5412602 Shift arbitrary battle lead to front of party while preserving order. 2025-05-02 00:48:05 -04:00
31 changed files with 167 additions and 149 deletions
+2
View File
@@ -410,6 +410,8 @@
- Added `q.has_argument_at(<index>, [argument_value])` MoLang function to several battle-related action effect contexts.
- Added `q.hit_count` MoLang function to move action effect contexts.
- Added `is_included`, `to_lower`, `to_upper`, and `string_length` as available Molang functions.
- Fixed a crash that would occur during battles if the opponent wild Pokémon species comes from a namespace other than cobblemon
- Fixed `clientActions` inside Dialogue pages being executed twice
## [1.6.1 (January 26th, 2025)](#1-6-1)
@@ -19,8 +19,6 @@ import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.entity.LivingEntityRenderer;
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;
@@ -33,9 +31,9 @@ public abstract class PlayerRendererMixin extends LivingEntityRenderer<AbstractC
super(context, model, shadowRadius);
}
@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 = "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);
}
@WrapOperation(method = "getRenderOffset(Lnet/minecraft/client/player/AbstractClientPlayer;F)Lnet/minecraft/world/phys/Vec3;", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/AbstractClientPlayer;isCrouching()Z"))
@@ -71,6 +71,7 @@ object CobblemonCommands {
MarkGiveAllCommand.register(dispatcher)
PcSearchCommand.register(dispatcher)
PcTakeCommand.register(dispatcher)
ValidateTeamCommand.register(dispatcher)
// Possibly lock down registration if and only if under dev environment or running in an environment
// with a certain system environment variable set
@@ -143,6 +143,8 @@ object CobblemonPermissions {
val CHANGE_BOX_COUNT = this.create("${COMMAND_PREFIX}boxcount", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
@JvmStatic
val SPECTATE_BATTLE = this.create("${COMMAND_PREFIX}spectatebattle", PermissionLevel.ALL_COMMANDS)
@JvmStatic
val VALIDATE_TEAM = this.create("${COMMAND_PREFIX}validateteam", PermissionLevel.ALL_COMMANDS)
@JvmStatic
val SEE_HIDDEN_NPCS = this.create("seehiddennpcs", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
@@ -101,4 +101,19 @@ interface RidingBehaviour<Settings : RidingBehaviourSettings, State : RidingBeha
* Calculate the damage a horizontal collision will do to a ridden Pokémon. This is only relevant to fast flying behaviours, fall damage is separate!
*/
fun damageOnCollision(settings: Settings, state: State, vehicle: PokemonEntity, impactVec: Vec3): Boolean = false
/**
* Internal helpers to help behaviour specific calculations
*/
companion object {
/**
* Scales a given value between a min and a max.
* The result is clamped between 0.0 and 1.0, where 0.0 represents x is at or below min
* and 1.0 represents x is at or above it.
*/
internal fun scaleToRange(x: Double, min: Double, max: Double): Double {
return ((x - min) / (max - min)).coerceIn(0.0, 1.0)
}
}
}
@@ -243,7 +243,7 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
//This rotation limit will be used to know if the ride has exceeded it and its needs correcting.
val rotMin = 15.0
val rotLimit = max(handling * sqrt(normalizeVal(state.rideVelocity.get().length(), 0.0, topSpeed)), rotMin)
val rotLimit = max(handling * sqrt(RidingBehaviour.scaleToRange(state.rideVelocity.get().length(), 0.0, topSpeed)), rotMin)
var yawDeltaDeg = deltaTime * handling * sin(Math.toRadians(controller.roll.toDouble())) //sin(Math.toRadians(controller.roll.toDouble())) * abs(cos(Math.toRadians(controller.pitch.toDouble())))
val trueYawDelt = yawDeltaDeg * abs(cos(Math.toRadians(controller.pitch.toDouble())))
@@ -299,7 +299,7 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
//modulated by speed so that when flapping idle in air you are ont wobbling around to look around
val rotMin = 15.0
var rollForce = xInput
val rotLimit = max(90 * sqrt(normalizeVal(state.rideVelocity.get().length(), 0.0, topSpeed)), rotMin)
val rotLimit = max(90 * sqrt(RidingBehaviour.scaleToRange(state.rideVelocity.get().length(), 0.0, topSpeed)), rotMin)
//Limit roll by non linearly decreasing inputs towards
// a rotation limit based on the current distance from
@@ -315,7 +315,7 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
}
//Give the ability to yaw with x mouse input when at low speeds.
val yawForce = xInput * ( 1.0 - sqrt(normalizeVal(state.rideVelocity.get().length(), 0.0, topSpeed)))
val yawForce = xInput * ( 1.0 - sqrt(RidingBehaviour.scaleToRange(state.rideVelocity.get().length(), 0.0, topSpeed)))
//Yaw locally a bit when up or down so that its more intuitive to make it out of a dive or a straight vertical
//climb
@@ -343,16 +343,6 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
return Vec3(0.0, 0.0, rollForce)
}
/*
* Normalizes the given value between a min and a max.
* The result is clamped between 0.0 and 1.0, where 0.0 represents x is at or below min
* and 1.0 represents x is at or above it.
*/
private fun normalizeVal(x: Double, min: Double, max: Double): Double {
require(max > min) { "max must be greater than min" }
return ((x - min) / (max - min)).coerceIn(0.0, 1.0)
}
override fun canJump(
settings: BirdSettings,
state: BirdState,
@@ -400,7 +390,7 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
val glideTopSpeed = vehicle.runtime.resolveDouble(settings.glidespeedExpr)
//Must I ensure that topspeed is greater than minimum?
val normalizedGlideSpeed = normalizeVal(state.rideVelocity.get().length(), topSpeed, glideTopSpeed)
val normalizedGlideSpeed = RidingBehaviour.scaleToRange(state.rideVelocity.get().length(), topSpeed, glideTopSpeed)
//Only ever want the fov change to be a max of 0.2 and for it to have non linear scaling.
return 1.0f + normalizedGlideSpeed.pow(2).toFloat() * 0.2f
@@ -229,7 +229,7 @@ class BirdNoRollBehaviour : RidingBehaviour<BirdNoRollSettings, BirdNoRollState>
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
//This rotation limit will be used to know if the ride has exceeded it and its needs correcting.
val rotMin = 15.0
val rotLimit = max(handling * sqrt(normalizeVal(state.rideVelocity.get().length(), 0.0, topSpeed)), rotMin)
val rotLimit = max(handling * sqrt(RidingBehaviour.scaleToRange(state.rideVelocity.get().length(), 0.0, topSpeed)), rotMin)
var yawDeltaDeg = deltaTime * handling * sin(Math.toRadians(controller.roll.toDouble())) //sin(Math.toRadians(controller.roll.toDouble())) * abs(cos(Math.toRadians(controller.pitch.toDouble())))
val trueYawDelt = yawDeltaDeg * abs(cos(Math.toRadians(controller.pitch.toDouble())))
@@ -283,7 +283,7 @@ class BirdNoRollBehaviour : RidingBehaviour<BirdNoRollSettings, BirdNoRollState>
val yInput = mouseYSmoother.getNewDeltaValue(mouseYc * 0.1 * invertPitch, deltaTime * smoothingSpeed);
//Give the ability to yaw with x mouse input when at low speeds.
val yawForce = xInput * ( 1.0 - min(sqrt(normalizeVal(state.rideVelocity.get().length(), 0.0, topSpeed)), 0.5))
val yawForce = xInput * ( 1.0 - min(sqrt(RidingBehaviour.scaleToRange(state.rideVelocity.get().length(), 0.0, topSpeed)), 0.5))
//Apply yaw globally as we don't want roll or pitch changes due to local yaw when looking up or down.
@@ -303,16 +303,6 @@ class BirdNoRollBehaviour : RidingBehaviour<BirdNoRollSettings, BirdNoRollState>
return Vec3.ZERO
}
/*
* Normalizes the given value between a min and a max.
* The result is clamped between 0.0 and 1.0, where 0.0 represents x is at or below min
* and 1.0 represents x is at or above it.
*/
private fun normalizeVal(x: Double, min: Double, max: Double): Double {
require(max > min) { "max must be greater than min" }
return ((x - min) / (max - min)).coerceIn(0.0, 1.0)
}
override fun canJump(
settings: BirdNoRollSettings,
state: BirdNoRollState,
@@ -360,7 +350,7 @@ class BirdNoRollBehaviour : RidingBehaviour<BirdNoRollSettings, BirdNoRollState>
val glideTopSpeed = vehicle.runtime.resolveDouble(settings.glidespeedExpr)
//Must I ensure that topspeed is greater than minimum?
val normalizedGlideSpeed = normalizeVal(state.rideVelocity.get().length(), topSpeed, glideTopSpeed)
val normalizedGlideSpeed = RidingBehaviour.scaleToRange(state.rideVelocity.get().length(), topSpeed, glideTopSpeed)
//Only ever want the fov change to be a max of 0.2 and for it to have non linear scaling.
return 1.0f + normalizedGlideSpeed.pow(2).toFloat() * 0.2f
@@ -104,7 +104,7 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
val rotAmount = 10.0f
//Take the inverse so that you turn more at higher speeds
val normSpeed = 1.0f - 0.5f*normalizeVal(state.rideVelocity.get().length(), 0.0, topSpeed).toFloat()
val normSpeed = 1.0f - 0.5f*RidingBehaviour.scaleToRange(state.rideVelocity.get().length(), 0.0, topSpeed).toFloat()
//driver.yRot += (entity.riding.deltaRotation.y - turnAmount)
//driver.setYHeadRot(driver.yHeadRot + (entity.riding.deltaRotation.y) - turnAmount)
@@ -164,7 +164,7 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
val rotDiffMod = (sqrt(abs(rotDiffNorm)) * rotDiffNorm.sign)
//Take the inverse so that you turn less at higher speeds
val normSpeed = 1.0f // = 1.0f - 0.5f*normalizeVal(state.rideVelocityocity.length(), 0.0, topSpeed).toFloat()
val normSpeed = 1.0f // = 1.0f - 0.5f*RidingBehaviour.scaleToRange(state.rideVelocityocity.length(), 0.0, topSpeed).toFloat()
val turnRate = (handling.toFloat() / 20.0f)
@@ -308,15 +308,6 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
return newVelocity
}
/*
* Normalizes the current speed between minSpeed and maxSpeed.
* The result is clamped between 0.0 and 1.0, where 0.0 represents minSpeed and 1.0 represents maxSpeed.
*/
private fun normalizeVal(currSpeed: Double, minSpeed: Double, maxSpeed: Double): Double {
require(maxSpeed > minSpeed) { "maxSpeed must be greater than minSpeed" }
return ((currSpeed - minSpeed) / (maxSpeed - minSpeed)).coerceIn(0.0, 1.0)
}
override fun angRollVel(
settings: HoverSettings,
state: HoverState,
@@ -80,7 +80,7 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
// //Calculate stamina loss due to speed
// //At max speed it will tick down 0.1 a second so the stamina will last ten seconds
// //There has got to be a better way to express this equation. It interpolates between 0.5 and 1.0
// var staminaRate = (normalizeSpeed(state.rideVelocity.get().length(), minSpeed, topSpeed))
// var staminaRate = (RidingBehaviour.scaleToRange(state.rideVelocity.get().length(), minSpeed, topSpeed))
//
// //interpolate between 0.25 and 1.0 so that you always have at least a min of 0.25 stam loss
// staminaRate = 0.25 + (0.75 * staminaRate.pow(3))
@@ -95,16 +95,6 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
return state.rideVelocity.get().length().toFloat()
}
//TODO: Move these functions to a riding util class.
/*
* Normalizes the current speed between minSpeed and maxSpeed.
* The result is clamped between 0.0 and 1.0, where 0.0 represents minSpeed and 1.0 represents maxSpeed.
*/
private fun normalizeSpeed(currSpeed: Double, minSpeed: Double, maxSpeed: Double): Double {
require(maxSpeed > minSpeed) { "maxSpeed must be greater than minSpeed" }
return ((currSpeed - minSpeed) / (maxSpeed - minSpeed)).coerceIn(0.0, 1.0)
}
override fun rotation(
settings: JetSettings,
state: JetState,
@@ -160,7 +150,7 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
//speed up and slow down based on input
if (driver.zza > 0.0 && speed < topSpeed && state.stamina.get() > 0.0f) {
//modify acceleration to be slower when at closer speeds to top speed
val accelMod = max(-(normalizeSpeed(speed, minSpeed, topSpeed)) + 1, 0.0)
val accelMod = max(-(RidingBehaviour.scaleToRange(speed, minSpeed, topSpeed)) + 1, 0.0)
state.rideVelocity.set(
Vec3(
state.rideVelocity.get().x,
@@ -178,7 +168,7 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
)
} else if (driver.zza < 0.0 && speed > minSpeed) {
//modify deccel to be slower when at closer speeds to minimum speed
val deccelMod = max((normalizeSpeed(speed, minSpeed, topSpeed) - 1).pow(2) * 4, 0.1)
val deccelMod = max((RidingBehaviour.scaleToRange(speed, minSpeed, topSpeed) - 1).pow(2) * 4, 0.1)
//Decelerate currently always a constant half of max acceleration.
state.rideVelocity.set(
@@ -324,7 +314,7 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
val minSpeed = vehicle.runtime.resolveDouble(settings.minSpeed)
//Must I ensure that topspeed is greater than minimum?
val normalizedSpeed = normalizeSpeed(state.rideVelocity.get().length(), minSpeed, topSpeed)
val normalizedSpeed = RidingBehaviour.scaleToRange(state.rideVelocity.get().length(), minSpeed, topSpeed)
//TODO: Determine if this should be based on max possible speed instead of top speed.
//Only ever want the fov change to be a max of 0.2 and for it to have non linear scaling.
@@ -80,16 +80,6 @@ class JetNoRollBehaviour : RidingBehaviour<JetNoRollSettings, JetNoRollState> {
return state.rideVelocity.get().length().toFloat()
}
//TODO: Move these functions to a riding util class.
/*
* Normalizes the current speed between minSpeed and maxSpeed.
* The result is clamped between 0.0 and 1.0, where 0.0 represents minSpeed and 1.0 represents maxSpeed.
*/
private fun normalizeSpeed(currSpeed: Double, minSpeed: Double, maxSpeed: Double): Double {
require(maxSpeed > minSpeed) { "maxSpeed must be greater than minSpeed" }
return ((currSpeed - minSpeed) / (maxSpeed - minSpeed)).coerceIn(0.0, 1.0)
}
override fun rotation(
settings: JetNoRollSettings,
state: JetNoRollState,
@@ -146,7 +136,7 @@ class JetNoRollBehaviour : RidingBehaviour<JetNoRollSettings, JetNoRollState> {
//speed up and slow down based on input
if (driver.zza > 0.0 && speed < topSpeed && state.stamina.get() > 0.0f) {
//modify acceleration to be slower when at closer speeds to top speed
val accelMod = max(-(normalizeSpeed(speed, minSpeed, topSpeed)) + 1, 0.0)
val accelMod = max(-(RidingBehaviour.scaleToRange(speed, minSpeed, topSpeed)) + 1, 0.0)
state.rideVelocity.set(
Vec3(
state.rideVelocity.get().x,
@@ -164,7 +154,7 @@ class JetNoRollBehaviour : RidingBehaviour<JetNoRollSettings, JetNoRollState> {
)
} else if (driver.zza < 0.0 && speed > minSpeed) {
//modify deccel to be slower when at closer speeds to minimum speed
val deccelMod = max((normalizeSpeed(speed, minSpeed, topSpeed) - 1).pow(2) * 4, 0.1)
val deccelMod = max((RidingBehaviour.scaleToRange(speed, minSpeed, topSpeed) - 1).pow(2) * 4, 0.1)
//Decelerate currently always a constant half of max acceleration.
state.rideVelocity.set(
@@ -308,7 +298,7 @@ class JetNoRollBehaviour : RidingBehaviour<JetNoRollSettings, JetNoRollState> {
val minSpeed = vehicle.runtime.resolveDouble(settings.minSpeed)
//Must I ensure that topspeed is greater than minimum?
val normalizedSpeed = normalizeSpeed(state.rideVelocity.get().length(), minSpeed, topSpeed)
val normalizedSpeed = RidingBehaviour.scaleToRange(state.rideVelocity.get().length(), minSpeed, topSpeed)
//TODO: Determine if this should be based on max possible speed instead of top speed.
//Only ever want the fov change to be a max of 0.2 and for it to have non linear scaling.
@@ -285,15 +285,6 @@ class RocketBehaviour : RidingBehaviour<RocketSettings, RocketState> {
return newVelocity
}
/*
* Normalizes the current speed between minSpeed and maxSpeed.
* The result is clamped between 0.0 and 1.0, where 0.0 represents minSpeed and 1.0 represents maxSpeed.
*/
private fun normalizeVal(currSpeed: Double, minSpeed: Double, maxSpeed: Double): Double {
require(maxSpeed > minSpeed) { "maxSpeed must be greater than minSpeed" }
return ((currSpeed - minSpeed) / (maxSpeed - minSpeed)).coerceIn(0.0, 1.0)
}
override fun angRollVel(
settings: RocketSettings,
state: RocketState,
@@ -374,7 +365,7 @@ class RocketBehaviour : RidingBehaviour<RocketSettings, RocketState> {
//val exceededSpeed = max(vehicle.deltaMovement.length() - topSpeed, 0.0)
//TODO: Remove this magic number and get a better comparison for boost top speed
val normalizedBoostSpeed = normalizeVal(state.rideVelocity.get().length(), topSpeed, topSpeed * 3)
val normalizedBoostSpeed = RidingBehaviour.scaleToRange(state.rideVelocity.get().length(), topSpeed, topSpeed * 3)
return 1.0f + normalizedBoostSpeed.pow(2).toFloat() * 0.2f
} else {
return 1.0f
@@ -174,7 +174,7 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
val normSpeed = 1.0f
// TurnRate should always be quick if not sprinting
val invRelSpeed = (inverseLerp(vehicle.deltaMovement.horizontalDistance(), 0.0, topSpeed ).pow(0.5) - 1.0f) * -1.0f
val invRelSpeed = (RidingBehaviour.scaleToRange(vehicle.deltaMovement.horizontalDistance(), 0.0, topSpeed ).pow(0.5) - 1.0f) * -1.0f
val turnRate = ((handling.toFloat() / 20.0f) * max(walkHandlingBoost * invRelSpeed, 1.0)).toFloat()
//Ensure you only ever rotate as much difference as there is between the angles.
@@ -202,19 +202,17 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
vehicle: PokemonEntity,
driver: Player
): Vec3 {
// Check to see if the ride should be walking or sprinting
val walkSpeed = getWalkSpeed(vehicle)
val canSprint = vehicle.runtime.resolveBoolean(settings.canSprint)
val canJump = vehicle.runtime.resolveBoolean(settings.canJump)
val rideTopSpeed = vehicle.runtime.resolveDouble(settings.speedExpr) * 1.3
val topSpeed = if(state.sprinting.get()) rideTopSpeed else walkSpeed
val walkSpeed = getWalkSpeed(vehicle)
val topSpeed = if(canSprint && state.sprinting.get()) rideTopSpeed else walkSpeed
val accel = vehicle.runtime.resolveDouble(settings.accelerationExpr) * 2
//Flag for determining if player is actively inputting
var activeInput = false
var newVelocity = Vec3(state.rideVelocity.get().x, state.rideVelocity.get().y, state.rideVelocity.get().z).normalize().scale(vehicle.deltaMovement.length())
//var newVelocity = vehicle.deltaMovement.normalize()
//speed up and slow down based on input
if (driver.zza != 0.0f && state.stamina.get() > 0.0) {
@@ -237,9 +235,6 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
if (vehicle.onGround()) {
newVelocity = Vec3(newVelocity.x, 0.0, newVelocity.z)
} else {
//TODO: Should we just go back to standard minecraft gravity or do the lerp modifications prevent that?
//I think minecrafts gravity logic is also too harsh and isn't gamefied enough for mounts maybe? Need
//to do some testing and get other's opinions
val gravity = (9.8 / ( 20.0)) * 0.2 * 0.8
val terminalVel = 2.0
@@ -253,18 +248,12 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
}
//TODO: Change this so its tied to a jumping stat and representative of the amount of jumps
val canJump = vehicle.runtime.resolveBoolean(settings.canJump)
//Jump the thang!
if (driver.jumping && vehicle.onGround() && canJump) {
val jumpForce = 1.0
val velMag = newVelocity.length()
newVelocity = newVelocity.add(0.0, jumpForce, 0.0)
val test = 0.0
//Ensure this doesn't add unwanted forward velocity
//val mag = if(newVelocity.length() < rideTopSpeed) newVelocity.length() else rideTopSpeed
//newVelocity = newVelocity.normalize().scale(mag)
}
//Zero out lateral velocity possibly picked up from a controller transition
@@ -273,15 +262,6 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
return newVelocity
}
/*
* lerps the current val between minVal and maxVal.
* The result is clamped between 0.0 and 1.0, where 0.0 represents minVal and 1.0 represents maxVal.
*/
private fun inverseLerp(currVal: Double, minVal: Double, maxVal: Double): Double {
require(maxVal > minVal) { "minVal must be greater than maxVal" }
return ((currVal - minVal) / (maxVal - minVal)).coerceIn(0.0, 1.0)
}
private fun getWalkSpeed( vehicle: PokemonEntity ): Double {
val walkspeed = vehicle.runtime.resolveDouble(vehicle.behaviour.moving.walk.walkSpeed)
val movementSpeed = vehicle.attributes.getValue(Attributes.MOVEMENT_SPEED)
@@ -455,6 +435,9 @@ class HorseSettings : RidingBehaviourSettings {
var canJump = "true".asExpression()
private set
var canSprint = "true".asExpression()
private set
var speedExpr: Expression = "q.get_ride_stats('SPEED', 'LAND', 1.0, 0.3)".asExpression()
private set
@@ -147,7 +147,7 @@ class MinekartBehaviour : RidingBehaviour<MinekartSettings, MinekartState> {
val turnInput = (driver.xxa *-1.0f) * turningAcceleration
val driftInput = turnInput * 0.25f
val lowSpeedTurnBoost = (inverseLerp(vehicle.deltaMovement.horizontalDistance(), 0.0, topSpeed ).pow(0.5) - 2.0f) * -1.0f
val lowSpeedTurnBoost = (RidingBehaviour.scaleToRange(vehicle.deltaMovement.horizontalDistance(), 0.0, topSpeed ).pow(0.5) - 2.0f) * -1.0f
val forcedDriftTurnMomentum = (80.0f / 20.0f) * lowSpeedTurnBoost
val maxTurnMomentum = (60.0f / 20.0f) * lowSpeedTurnBoost
val maxDriftMomentum = forcedDriftTurnMomentum * 0.6f
@@ -293,15 +293,6 @@ class MinekartBehaviour : RidingBehaviour<MinekartSettings, MinekartState> {
return newVelocity
}
/*
* lerps the current val between minVal and maxVal.
* The result is clamped between 0.0 and 1.0, where 0.0 represents minVal and 1.0 represents maxVal.
*/
private fun inverseLerp(currVal: Double, minVal: Double, maxVal: Double): Double {
require(maxVal > minVal) { "minVal must be greater than maxVal" }
return ((currVal - minVal) / (maxVal - minVal)).coerceIn(0.0, 1.0)
}
override fun angRollVel(
settings: MinekartSettings,
state: MinekartState,
@@ -221,9 +221,6 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
if (vehicle.onGround()) {
newVelocity = Vec3(newVelocity.x, 0.0, newVelocity.z)
} else {
//TODO: Should we just go back to standard minecraft gravity or do the lerp modifications prevent that?
//I think minecrafts gravity logic is also too harsh and isn't gamefied enough for mounts maybe? Need
//to do some testing and get other's opinions
val gravity = (9.8 / ( 20.0)) * 0.2 * 0.25 * 3.0
val terminalVel = 2.0
@@ -195,7 +195,7 @@ class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
// Yaw
// TODO:move all magic numbers to handling expression
val yawSpeed = handling * deltaTime * 0.25
val yawForce = sin(controller.roll.toRadians()) * yawSpeed * ( 1.0 - min(sqrt(normalizeVal(state.rideVelocity.get().length(), 0.0, topSpeed)), 0.5))
val yawForce = sin(controller.roll.toRadians()) * yawSpeed * ( 1.0 - min(sqrt(RidingBehaviour.scaleToRange(state.rideVelocity.get().length(), 0.0, topSpeed)), 0.5))
//Apply yaw globally as we don't want roll or pitch changes due to local yaw when looking up or down.
controller.applyGlobalYaw(yawForce.toFloat())
@@ -211,16 +211,6 @@ class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
return Vec3.ZERO
}
/*
* Normalizes the given value between a min and a max.
* The result is clamped between 0.0 and 1.0, where 0.0 represents x is at or below min
* and 1.0 represents x is at or above it.
*/
private fun normalizeVal(x: Double, min: Double, max: Double): Double {
require(max > min) { "max must be greater than min" }
return ((x - min) / (max - min)).coerceIn(0.0, 1.0)
}
override fun canJump(
settings: DolphinSettings,
state: DolphinState,
@@ -25,7 +25,6 @@ import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.DataKeys
import com.cobblemon.mod.common.util.server
import com.google.gson.JsonObject
import java.util.Collections
import java.util.UUID
import net.minecraft.core.RegistryAccess
import net.minecraft.nbt.CompoundTag
@@ -259,9 +258,15 @@ open class PartyStore(override val uuid: UUID) : PokemonStore<PartyPosition>() {
BattlePokemon.playerOwned(it)
}.also { if (healPokemon) it.effectedPokemon.heal() }
}.toMutableList()
if (leadingPokemon != null) {
Collections.rotate(result, result.size - this.indexOfFirst { it.uuid == leadingPokemon })
// reposition lead to front of the party
if (leadingPokemon != null && result.first().uuid != leadingPokemon) {
result.find { it.uuid == leadingPokemon }?.let { lead ->
result.remove(lead)
result.add(0, lead)
}
}
return result
}
fun clearParty() {
@@ -57,7 +57,7 @@ data class BattleFormat(
val GEN_9_SINGLES = BattleFormat(
battleType = BattleTypes.SINGLES,
ruleSet = mutableSetOf(BattleRules.OBTAINABLE, BattleRules.PAST, BattleRules.UNOBTAINABLE)
ruleSet = mutableSetOf("Standard NatDex")
)
val GEN_9_DOUBLES = BattleFormat(
@@ -121,6 +121,8 @@ object BattleRegistry {
packedTeamBuilder.append("${if (pk.dmaxLevel < 10) pk.dmaxLevel else ""},")
// Teratype
packedTeamBuilder.append("${pokemon.effectedPokemon.teraType.name},")
// Original nature
packedTeamBuilder.append("${pk.nature.name.path},")
team.add(packedTeamBuilder.toString())
}
@@ -16,6 +16,9 @@ import com.cobblemon.mod.common.api.battles.interpreter.BattleContext
* @author Segfault Guy
* @since April 10th, 2023
*/
@Deprecated(message =
"This was designed before Doubles and Multi battle formats were introduce and has not been maintained since." +
"Accurate context for formats other than Singles is not guaranteed. This will be replaced in the near future.")
class ContextManager {
/** [BattleContext.Type] buckets containing [BattleContexts] of that type. */
@@ -34,8 +34,9 @@ interface ShowdownService {
fun resetRegistryData(type: String)
fun resetAllRegistries()
fun indicateSpeciesInitialized() {}
fun validateTeam(packedTeam: String, format: String = "cobblemon") {}
companion object {
val service: ShowdownService by lazy { GraalShowdownService() }
val service: ShowdownService by lazy { SocketShowdownService() }
}
}
@@ -167,6 +167,11 @@ class GraalShowdownService : ShowdownService {
func.execute()
}
override fun validateTeam(packedTeam: String, format: String) {
val func = this.context.getBindings("js").getMember("validateTeam")
func.execute(packedTeam, format).asString()
}
private fun sendToShowdown(battleId: UUID, messages: Array<String>) {
sendBattleMessageFunction.execute(battleId.toString(), messages)
}
@@ -9,6 +9,7 @@
package com.cobblemon.mod.common.battles.runner.socket
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.abilities.AbilityTemplate
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
import com.cobblemon.mod.common.battles.ShowdownInterpreter
@@ -141,6 +142,17 @@ class SocketShowdownService(val host: String = "localhost", val port: Int = 1846
acknowledge()
}
override fun validateTeam(packedTeam: String, format: String) {
writer.write(">validator $packedTeam $format")
writer.flush()
val response = readMessage()
val jsonarray = gson.fromJson(response, JsonArray::class.java)
for (i in 0 until jsonarray.size()) {
val msg = jsonarray[i].asString
Cobblemon.LOGGER.error(msg)
}
}
fun acknowledge(ifFails: () -> Unit = {}) {
writer.flush()
val ack = CharArray(3)
@@ -236,8 +236,8 @@ class CookingPotMenu : RecipeBookMenu<CraftingInput, CookingPotRecipeBase>, Cont
slot.onQuickCraft(slotItemStack, itemStack);
} else if (index in CampfireBlockEntity.Companion.PLAYER_INVENTORY_SLOTS || index in CampfireBlockEntity.Companion.PLAYER_HOTBAR_SLOTS) {
if (Seasonings.isSeasoning(slotItemStack)) {
if (!this.moveItemStackTo(slotItemStack, CampfireBlockEntity.Companion.SEASONING_SLOTS.first, CampfireBlockEntity.Companion.SEASONING_SLOTS.last + 1, false) &&
!this.moveItemStackTo(slotItemStack, CampfireBlockEntity.Companion.CRAFTING_GRID_SLOTS.first, CampfireBlockEntity.Companion.CRAFTING_GRID_SLOTS.last + 1, false)
if (!this.moveItemStackTo(slotItemStack, CampfireBlockEntity.Companion.CRAFTING_GRID_SLOTS.first, CampfireBlockEntity.Companion.CRAFTING_GRID_SLOTS.last + 1, false) &&
!this.moveItemStackTo(slotItemStack, CampfireBlockEntity.Companion.SEASONING_SLOTS.first, CampfireBlockEntity.Companion.SEASONING_SLOTS.last + 1, false)
) {
return ItemStack.EMPTY
}
@@ -17,6 +17,7 @@ import com.cobblemon.mod.common.battles.ForcePassActionResponse
import com.cobblemon.mod.common.battles.PassActionResponse
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import java.util.UUID
class ClientBattle(
@@ -32,11 +33,10 @@ class ClientBattle(
set(value) {
field = value
if (value != null) {
val wildMonProps = value.activePokemon[0].battlePokemon?.properties
wildMonProps?.let {props ->
val wildSpecies = PokemonSpecies.getByName(props.species!!)!!
val wildMonSpecies = value.activePokemon[0].battlePokemon?.properties?.species?.asIdentifierDefaultingNamespace()
knowledge = wildMonSpecies?.let {
//FIXME: Better knowledge checking based on aspects/form and such
knowledge = CobblemonClient.clientPokedexData.getKnowledgeForSpecies(wildSpecies.resourceIdentifier)
CobblemonClient.clientPokedexData.getKnowledgeForSpecies(it)
} ?: PokedexEntryProgress.NONE
}
else {
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.cookingpot
import com.cobblemon.mod.common.CobblemonNetwork.sendToServer
import com.cobblemon.mod.common.api.gui.blitk
import com.cobblemon.mod.common.block.campfirepot.CookingPotMenu
import com.cobblemon.mod.common.block.campfirepot.SeasoningSlot
import com.cobblemon.mod.common.block.entity.CampfireBlockEntity.Companion.IS_LID_OPEN_INDEX
import com.cobblemon.mod.common.integration.jei.CobblemonJeiPlugin
import com.cobblemon.mod.common.integration.jei.cooking.CampfirePotRecipeCategory
@@ -197,6 +198,15 @@ class CookingPotScreen(
this.recipeBookComponent.renderTooltip(context, this.leftPos, this.topPos, mouseX, mouseY)
}
override fun renderSlot(guiGraphics: GuiGraphics, slot: Slot) {
if (slot is SeasoningSlot && !menu.carried.isEmpty && !slot.mayPlace(menu.carried)) {
val x = slot.x
val y = slot.y
guiGraphics.fill(x,y,x+16,y+16,822018048)
}
super.renderSlot(guiGraphics, slot)
}
override fun recipesUpdated() {
this.recipeBookComponent.recipesUpdated()
}
@@ -240,7 +240,6 @@ class DialogueScreen(var dialogueDTO: DialogueDTO) : Screen("gui.dialogue".asTra
}
this.dialogueStartTick = minecraft!!.player!!.tickCount
dialogueDTO.currentPageDTO.clientActions.flatMap(String::asExpressions).resolve(runtime)
}
var gibberIndex = 0
@@ -17,6 +17,7 @@ import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.gui.components.Button
import net.minecraft.client.resources.sounds.SimpleSoundInstance
import net.minecraft.client.sounds.SoundManager
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.MutableComponent
import net.minecraft.resources.ResourceLocation
@@ -25,7 +26,7 @@ class SummaryTab(
val label: MutableComponent? = null,
val icon: ResourceLocation? = null,
onPress: OnPress
): Button(pX, pY, WIDTH, HEIGHT, label, onPress, DEFAULT_NARRATION), CobblemonRenderable {
): Button(pX, pY, WIDTH, HEIGHT, label ?: Component.empty(), onPress, DEFAULT_NARRATION), CobblemonRenderable {
companion object {
private const val WIDTH = 39
private const val HEIGHT = 13
@@ -0,0 +1,34 @@
package com.cobblemon.mod.common.command
import com.cobblemon.mod.common.api.permission.CobblemonPermissions
import com.cobblemon.mod.common.battles.BattleFormat
import com.cobblemon.mod.common.battles.BattleRegistry.packTeam
import com.cobblemon.mod.common.battles.runner.ShowdownService
import com.cobblemon.mod.common.util.party
import com.cobblemon.mod.common.util.permission
import com.mojang.brigadier.Command
import com.mojang.brigadier.CommandDispatcher
import com.mojang.brigadier.context.CommandContext
import net.minecraft.commands.CommandSourceStack
import net.minecraft.commands.Commands
object ValidateTeamCommand {
fun register(dispatcher: CommandDispatcher<CommandSourceStack>) {
val command = Commands.literal("validateteam")
.permission(CobblemonPermissions.VALIDATE_TEAM)
// TODO format argument
.executes(::execute)
dispatcher.register(command)
}
private fun execute(context: CommandContext<CommandSourceStack>): Int {
try {
val packedTeam = context.source.playerOrException.party().toBattleTeam().packTeam()
ShowdownService.service.validateTeam(packedTeam, BattleFormat.GEN_9_SINGLES.toFormatJSON())
} catch (e: Exception) {
e.printStackTrace()
}
return Command.SINGLE_SUCCESS
}
}
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.integration.jei.cooking
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.api.berry.Berries
import com.cobblemon.mod.common.api.cooking.Seasonings
import com.cobblemon.mod.common.block.entity.CampfireBlockEntity
import com.cobblemon.mod.common.block.entity.CampfireBlockEntity.Companion.CRAFTING_GRID_WIDTH
import com.cobblemon.mod.common.block.entity.CampfireBlockEntity.Companion.SEASONING_SLOTS
@@ -32,6 +33,7 @@ import mezz.jei.api.recipe.category.IRecipeCategory
import mezz.jei.api.registration.IRecipeCategoryRegistration
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.crafting.Ingredient
@@ -47,7 +49,7 @@ class CampfirePotRecipeCategory(registration: IRecipeCategoryRegistration) : IRe
const val WIDTH = 146
const val HEIGHT = 59
val EXAMPLE_SEASONINGS = Berries.all().map { it.item()?.defaultInstance }
val EXAMPLE_SEASONINGS = BuiltInRegistries.ITEM.map { it.defaultInstance }.filter { Seasonings.isSeasoning(it) }
}
val guiHelper: IGuiHelper = registration.jeiHelpers.guiHelper
@@ -80,11 +82,25 @@ class CampfirePotRecipeCategory(registration: IRecipeCategoryRegistration) : IRe
builder.addSlot(RecipeIngredientRole.INPUT, x, y).addIngredients(ingredient)
}
for ((index, _) in SEASONING_SLOTS.withIndex()) {
val x = 93 + index * 18
val y = 1
if (recipe.seasoningProcessors.isNotEmpty()) {
val processedSeasonings = EXAMPLE_SEASONINGS.filter { item ->
var valid = true
recipe.seasoningProcessors.forEach {
if (!it.consumesItem(item)) {
valid = false
return@forEach
}
}
valid
}
builder.addSlot(RecipeIngredientRole.INPUT, x, y).addIngredients(VanillaTypes.ITEM_STACK, EXAMPLE_SEASONINGS.shuffled())
for ((index, _) in SEASONING_SLOTS.withIndex()) {
val x = 93 + index * 18
val y = 1
builder.addSlot(RecipeIngredientRole.INPUT, x, y)
.addIngredients(VanillaTypes.ITEM_STACK, processedSeasonings.shuffled())
}
}
val registryAccess = Minecraft.getInstance().level?.registryAccess() ?: throw IllegalStateException("Registry access not found")
@@ -36,6 +36,6 @@ object BaitSeasoningProcessor : SeasoningProcessor {
override fun consumesItem(seasoning: ItemStack): Boolean {
val seasoningData = Seasonings.getFromItemStack(seasoning)
return seasoningData != null && !seasoningData.baitEffects.isNullOrEmpty()
return seasoningData != null && (!seasoningData.baitEffects.isNullOrEmpty() || SpawnBaitEffects.getBaitIdentifiersFromItem(seasoning.itemHolder).isNotEmpty())
}
}
@@ -440,6 +440,15 @@
{"origin": [0, 16.4, 2.3], "size": [0, 21, 19], "uv": [84, 24]}
]
},
{
"name": "seat_1_locator",
"parent": "torso",
"pivot": [0, 29, 3],
"rotation": [-30, 0, 0],
"locators": {
"seat_1": [0, 29, 3]
}
},
{
"name": "tail",
"parent": "body",
@@ -469,7 +478,7 @@
"parent": "tail3",
"pivot": [0.5, -1.5, 1.7],
"cubes": [
{"origin": [-2.5, -11.5, -8.3], "size": [5, 10, 10], "inflate": 0.01, "pivot": [0, -6.5, -3.3], "rotation": [0, 0, 0], "uv": [0, 38]}
{"origin": [-2.5, -11.5, -8.3], "size": [5, 10, 10], "inflate": 0.01, "uv": [0, 38]}
]
}
]