mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-20 22:26:24 -04:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea99b339ea |
+7
-88
@@ -38,19 +38,17 @@
|
||||
- Lightning is now affected by a Pokemon's ability/typing
|
||||
- Pokémon with the ability Lightning Rod draw in lightning similar to a lightning rod block albeit with a lower priority and range, gain immunity to lightning damage, and receive a temporary damage buff.
|
||||
- Pokémon with the ability Motor Drive are immune to lightning damage and receive a temporary speed buff when struck by lightning
|
||||
- Pokémon with the ability Volt Absorb are immune to lightning damage and receive Instant Health II for a short duration
|
||||
- Pokémon with the ability Volt Absorb are immune to lightning damage and receive Regeneration II for a short duration
|
||||
- Ground type Pokémon are immune to lightning damage
|
||||
- Added functionality to Everstone when held by a Pokémon; suppresses evolution notification and hides evolve button in summary interface.
|
||||
- Added optional `filePath` parameter to MoLang functions to allow for global stores (ex. `../global/`). Path must end in a forward slash.
|
||||
- Added new optional property `attachment_options` for most EmitterShapes to be attached to the locator/entities scale, rotation, and/or position. Position is true by default.
|
||||
- Added Statistics for battles won, fled, and total, Pokémon captured (shiny and total), Pokémon released, dex entries added, trades completed, Pokémon levels gained, Pokémon evolved, fossils revived, PokéRod casts and reel-ins and Pokémon times ridden.
|
||||
- Galarica Nut bushes now generate on beaches.
|
||||
- Some Pokémon now pitch their bodies in the direction they're moving.
|
||||
- Added new advancements Didn't Stop To Think, We Need To Cook, Pokémon Jockey!, Souped-Up Stats, Culinary World Tour, Mochi Mochi!, A Luring Aroma, That's Bait, Star Pokéathlete, Home on the Range, and Just a Smackerel.
|
||||
- Added new advancements Didn't Stop To Think, We Need To Cook, and Pokémon Jockey!.
|
||||
- Berries can now be smelted into their respective dyes.
|
||||
- Added Syrupy Apples.
|
||||
- Added `/runmolang <molang> [<npc>|<player>|<pokemon>]` command that executes a MoLang expression with the provided options as environment variables, as well as the entity (as `q.entity`) that executed the command.
|
||||
- Added new 69th berry, Eggant.
|
||||
- Added bubble quirk to Kingler; like Krabby, Kingler will blows bubbles during dusk.
|
||||
- Added `.Pre` and `.Post` to the following events:
|
||||
- `PokemonRecallEvent`
|
||||
@@ -58,12 +56,6 @@
|
||||
- Added a new gamerule, 'healerHealsPC', when set to true a successful use of a healer will also heal all of the Pokemon in that player's PC.
|
||||
- Mooshtanks will switch between their red and brown variant when hit by lightning
|
||||
- Smeargle spawns with differing tail colour depending on its [Characteristic](https://bulbapedia.bulbagarden.net/wiki/Characteristic) stat
|
||||
- Added smooth level-up animations to the party overlay to replace chat messages.
|
||||
- Added `min_perfect_ivs` property to PokemonProperties to specify the minimum number of perfect IVs of the Pokemon.
|
||||
- Added `defaultKeyItems` config option to specify which key items players always have.
|
||||
- Added `scale_modifier` property to PokemonProperties to modify the scale of the Pokemon.
|
||||
- Added advancement trigger to check riding stat boosts.
|
||||
- Added Tasty Tail which you can get from Slowpokes if you happen to have a pair of shears. They don't mind, we asked.
|
||||
|
||||
### Pokémon Added
|
||||
|
||||
@@ -95,8 +87,6 @@
|
||||
- Altaria
|
||||
- Snorunt
|
||||
- Glalie
|
||||
- Shuppet
|
||||
- Banette
|
||||
- Latias
|
||||
- Latios
|
||||
|
||||
@@ -145,11 +135,6 @@
|
||||
- Swadloon
|
||||
- Leavanny
|
||||
- Druddigon
|
||||
- Minccino
|
||||
- Cinccino
|
||||
- Vanillite
|
||||
- Vanillish
|
||||
- Vanilluxe
|
||||
|
||||
#### Gen 6
|
||||
- Skiddo
|
||||
@@ -311,23 +296,7 @@
|
||||
- Tauros - Paldea Blaze
|
||||
- Tauros - Paldea Combat
|
||||
- Dewgong
|
||||
- Corphish (updated placeholders for crustaceous tripod gait legs)
|
||||
- Crawdaunt (updated placeholders for crustaceous bipedal legs)
|
||||
- Dragapult
|
||||
- Camerupt
|
||||
- Relicanth
|
||||
- Heracross
|
||||
- Salamence
|
||||
- Staraptor
|
||||
- Dusknoir
|
||||
- Arcanine
|
||||
- Carvanha
|
||||
- Sharpedo
|
||||
- Mimikyu
|
||||
- Dewgong
|
||||
- Mime Jr
|
||||
- Gyarados
|
||||
- Lapras
|
||||
- Exeggutor - Kanto
|
||||
|
||||
### Model updates for the following Pokémon
|
||||
- Cleffa
|
||||
@@ -355,8 +324,6 @@
|
||||
- Nosepass
|
||||
- Probopass
|
||||
- Kangaskhan
|
||||
- Scorbunny
|
||||
- Raboot
|
||||
- Cinderace
|
||||
- Magnemite
|
||||
- Magneton
|
||||
@@ -443,18 +410,6 @@
|
||||
- Litwick
|
||||
- Lampent
|
||||
- Chandelure
|
||||
- Rayquaza
|
||||
- Aerodactyl
|
||||
- Basculin
|
||||
- Basculegion
|
||||
- Shroodle
|
||||
- Grafaiai
|
||||
- Steelix
|
||||
- Dratini
|
||||
- Dragonair
|
||||
- Dragonite
|
||||
- Cutiefly
|
||||
- Ribombee
|
||||
|
||||
### Changes
|
||||
- Changed pokemon caught and seen count to update based on the current pokedex being looked
|
||||
@@ -476,7 +431,8 @@
|
||||
- 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.
|
||||
- Improved the performance of saving Pokédex and player data.
|
||||
- Pokémon hitbox now scales with entity attribute `generic.scale`.
|
||||
- Removed Shulker shell Forretress.
|
||||
- Removed Shulker aspect and replaced it with cosmetic_item-shulker_shell.
|
||||
- Shulker shell Forretress is now a cosmetic rather than a special evo and thus all shulker Forretress will revert back to normal until a shulker shell is put in their cosmetic slot.
|
||||
- Updated `doPokemonSpawning` gamerule to support per-dimension configurations.
|
||||
- The Pokedex now displays a form name of a "normal" Pokémon for when the base form is still a named form.
|
||||
- Improved the zoom functionality of the Pokédex Scanner by giving the levels logarithmic scaling.
|
||||
@@ -485,7 +441,7 @@
|
||||
- Quirk animations no longer play in the battle GUI since they were pretty distracting.
|
||||
- A number of Pokemon that float above the ground visually (Gastly, Klingklang, etc.) are no longer considered to be touching the ground
|
||||
- Changed the recipes for Level, Lure, and Moon Balls to be cleaner
|
||||
- Renamed `pokemonId` and `type` to `species` and `evolved` to `has_evolved` in relevant Advancement triggers for conformity, this is a breaking change.
|
||||
- Renamed `pokemonId` and `type` to `species` in relevant Advancement triggers for conformity, this is a breaking change.
|
||||
- Added a separate `species` argument to the `pick_starter`, `pasture_use` and `resurrect_pokemon` Advancement triggers.
|
||||
- Made `CobblemonAgingDespawner` thresholds configurable via the config file.
|
||||
- Tweaked Berry flavor data to balance cooking pot mechanics
|
||||
@@ -520,16 +476,8 @@
|
||||
- Updated `HatchEggEvent.Post` to include the Pokemon that hatched.
|
||||
- Roseli Berry Trees now naturally generate in their preferred biomes.
|
||||
- Refactored dynamic lights compat to be more future proof. The dynamic light support is only tested with LambDynamicLights, on NeoForged use that mod in combination with Sinytra Connector
|
||||
- Renamed Masterful Dedication advancement to This will affect the Whiscash Population
|
||||
- Changed icon for the following advancements: New Angles for Angling, Researcher Recruit, Doing my Part, Reapriforestation
|
||||
- Disabled advancement Mother Nature's Bounty from appearing in chat when obtained, now only appears as a toast and in the advancements menu
|
||||
- Removed Oki-Doki Vivichokey advancement
|
||||
- Shulker Boxes and Traveler's Backpacks can no longer be held by Pokémon. Thanks Monocle ;) You could re-enable this with a datapack but you'd be crazy.
|
||||
- Shulker Boxes and Traveler's Backpacks AND Packed Up backpacks can no longer be held by Pokémon. Thanks Monocle ;) You could re-enable this with our datapack (but you'd be crazy).
|
||||
- Moomoo Milk now clears Pokémon stat changes when used in battle.
|
||||
- Updated Evolution Stone Block light levels
|
||||
- Added light levels to Evolution Stone Ores. These levels are reduced versions of the full blocks light levels
|
||||
- Added a steps counter to the summary screen for Pokémon that require walking a certain number of steps to evolve.
|
||||
|
||||
### Fixes
|
||||
- Fixed game crashing when removing national pokedex using datapacks
|
||||
@@ -614,17 +562,8 @@
|
||||
- Fixed singular Pokémon corruption causing entire storage corruption. Storages will now skip corrupted Pokémon and print an error to console.
|
||||
- Fixed species additions not being able to properly mark a species as implemented.
|
||||
- Fixed Pokémon item models not showing a glint when enchanted.
|
||||
- Fixed the missing Terracotta Sun Stone Ore smelting and blasting recipes
|
||||
- Improved experience gain from smelting evolution stone ores to better match other ore types
|
||||
- Fixed some specific bag items not being dropped when used in battle.
|
||||
- The Corphish line will now sink in water.
|
||||
- Fixed the "use all berry bait" achievement not being progressed
|
||||
- Fixed bobber hook and berry sprouts texture sizes causing mipmap issues.
|
||||
- Fixed head locator not taking into account scale for positioning.
|
||||
- Fixed Pokémon step counts not being saved when recalling them to a Pokéball or reentering the world.
|
||||
- Fixed NPC pokémon not being linked to their NPC, which previously caused NPC pokémon to be catchable.
|
||||
- Fixed an uncommon error caused by scanning a pokémon on a player's shoulder.
|
||||
- Fixed a case where spawning could fail and log warnings when nothing wrong was happening.
|
||||
|
||||
### Developer
|
||||
- A finished battle now has winners and losers set inside of `PokemonBattle` instead of them always being empty.
|
||||
@@ -681,17 +620,6 @@
|
||||
}
|
||||
```
|
||||
This will change the value of `mooshtank` from `red` to `brown` and vice versa when a lightning strikes this Pokémon. Only chains of which a value is the current value will be considered, so multiple entries for the same key with different chains can be added.
|
||||
- Removed Npc interface from NPCEntity, the interface is unused and in vanilla is only implemented by VillagerEntity as a means to disable villagers with the `spawn-npcs` server property.
|
||||
- Added new `Observable#subscribe` methods that take Java Consumers to make usage in Java a little cleaner.
|
||||
- Annotated a bunch of Kotlin methods and fields for cleaner Java names.
|
||||
- Added `PartyStore#isEmpty()`.
|
||||
- Added `ElementalTypes#getRandomType()`.
|
||||
- Added `IVs#getEffectiveBattleTotal()`.
|
||||
- Added `IVs.MAX_TOTAL` constant.
|
||||
- Added `PokemonStats#total()`.
|
||||
- Add `NatureAdapter` for serializing and deserializing Natures using Gson.
|
||||
- Added `Pokemon.getBaseRideStat(RidingStat)` for getting the base value of the given stat.
|
||||
- Fixed `Species#create` using the species name instead of identifier, which had led to certain mismatches generating random pokémon.
|
||||
|
||||
### 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)
|
||||
@@ -732,7 +660,6 @@
|
||||
- Adds Flows for `POKEMON_HEALED`, `POKEMON_SCANNED`, `BERRY_HARVEST`, `LOOT_DROPPED`, `POKEMON_SEEN`, `COLLECT_EGG`, `HATCH_EGG`, and `EXPERIENCE_GAINED`.
|
||||
- Adds Flows for `POKEMON_CATCH_RATE`, `BAIT_SET`, `BAIT_SET_PRE`, `BAIT_CONSUMED`, `POKEROD_CAST_PRE`, `POKEROD_CAST_POST`, `POKEROD_REEL`, and `BOBBER_SPAWN_POKEMON_PRE`.
|
||||
- Adds Flows for `POKEMON_ASPECTS_CHANGED`, `FRIENDSHIP_UPDATED`, `CHANGE_PC_BOX_WALLPAPER_EVENT_PRE`, `CHANGE_PC_BOX_WALLPAPER_EVENT_POST`, and `FULLNESS_UPDATED`.
|
||||
- Added Callback for `SERVER_STOPPING`
|
||||
- MoLang triggered battles may now set the battle format, whether to clone the player's party, set level, or heal prior.
|
||||
- Added Molang function for Player: `inventory`
|
||||
- Adds Flows for `STARTER_CHOSEN`, `EV_GAINED`, `POKEMON_RELEASED`, `POKEMON_NICKNAMED`, `HELD_ITEM`, and `TRADE_COMPLETED` events
|
||||
@@ -800,14 +727,6 @@
|
||||
- Also changed the default from `cobblemon:empty_bait` to `any`
|
||||
- The previous default is still available by using the above as baitId
|
||||
- Added support for species-specific move action effects, using the format `{move_id}_{species}.json`.
|
||||
- Added `look_at_entity_types` variable for look_at_entities to specify what entity type or entity tag to look at.
|
||||
- Added `Looks At Players` behaviour preset that only sets the look target to players.
|
||||
- Added various functions to `q.file` for JSON file handling in MoLang, strictly for `./config` and `./data` folders that have `/molang/` in the path:
|
||||
- `q.file.save(<path>, <struct>)` Saves to the given file path with the given variable struct.
|
||||
- `q.file.load(<path>)` Loads a variable struct from the given path, or gets it from the cache if it's already been loaded.
|
||||
- `q.file.exists(<path>)` Returns 1 if the given file path exists.
|
||||
- `q.file.clear(<path>)` Clears the given file from the cache.
|
||||
- Using `q.run_script` will now allow additional arguments which will be put into `c.arg_1`, `c.arg_2`, etc.
|
||||
|
||||
### Particles
|
||||
Added new/updated particles for the following moves:
|
||||
@@ -3040,4 +2959,4 @@ Thank you so much to all of our community translators that bring the mod to the
|
||||
- Added species, ability, and move translations for `ko_ko`, `jp_jp`, `fr_fr`, `es_es`, `it_it`, and `zh_cn`.
|
||||
|
||||
## [1.0.0 (November 12th, 2022)](#1-0-0)
|
||||
- Initial release.
|
||||
- Initial release.
|
||||
@@ -1,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.duck;
|
||||
|
||||
import com.mongodb.lang.Nullable;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
public interface CameraDuck {
|
||||
BlockGetter cobblemon$getLevel();
|
||||
|
||||
@Nullable
|
||||
Entity cobblemon$getEntity();
|
||||
|
||||
Vector3f cobblemon$getForwards();
|
||||
|
||||
Vector3f cobblemon$getUp();
|
||||
|
||||
Vector3f cobblemon$getLeft();
|
||||
|
||||
float cobblemon$getXRot();
|
||||
void cobblemon$setXRot(float xRot);
|
||||
|
||||
float cobblemon$getYRot();
|
||||
void cobblemon$setYRot(float yRot);
|
||||
}
|
||||
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.OrientationControllable;
|
||||
import com.cobblemon.mod.common.duck.RidePassenger;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.projectile.AbstractArrow;
|
||||
@@ -25,9 +24,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(AbstractArrow.class)
|
||||
public abstract class AbstractArrowMixin {
|
||||
|
||||
// Target the constructor that takes a LivingEntity owner
|
||||
@Inject(
|
||||
method = "<init>(Lnet/minecraft/world/entity/EntityType;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemStack;)V",
|
||||
at = @At("TAIL")
|
||||
at = @At("TAIL") // Inject at the very end of the constructor
|
||||
)
|
||||
private void cobblemon$adjustSpawnPosition(
|
||||
EntityType<? extends AbstractArrow> entityType,
|
||||
@@ -39,12 +39,11 @@ public abstract class AbstractArrowMixin {
|
||||
) {
|
||||
AbstractArrow arrow = (AbstractArrow)(Object)this;
|
||||
if(!(owner.getVehicle() instanceof OrientationControllable vehicle)) return;
|
||||
if(!(vehicle instanceof PokemonEntity)) return;
|
||||
var vehicleController = vehicle.getOrientationController();
|
||||
|
||||
// If this is a pokemon ride passenger then use the rider eye position to set the arrow spawn position.
|
||||
if (owner instanceof RidePassenger ridePassenger && vehicleController != null ) {
|
||||
var eyePos = ridePassenger.cobblemon$getRideEyePos(); //.add(0.0, -2.0, 0.0);
|
||||
// If this is a rolling ride passenger then use the rider eye position to set the arrow spawn position.
|
||||
if (owner instanceof RidePassenger ridePassenger && vehicleController != null && vehicleController.getActive()) {
|
||||
var eyePos = ridePassenger.cobblemon$getRideEyePos().add(0.0, -2.0, 0.0);
|
||||
arrow.setPos(eyePos);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,10 +28,6 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Mixin(BeehiveBlockEntity.Occupant.class)
|
||||
public abstract class BeeOccupantMixin {
|
||||
|
||||
@@ -52,7 +48,7 @@ public abstract class BeeOccupantMixin {
|
||||
var facing = state.getValue(HorizontalDirectionalBlock.FACING);
|
||||
newPos = pos.relative(facing).getCenter();
|
||||
newYaw = facing.toYRot();
|
||||
brain.setMemory(CobblemonMemories.HIVE_LOCATION, pos); // This needs to be set in the case that the hive was picked up and moved.
|
||||
brain.setMemory(CobblemonMemories.INSTANCE.getHIVE_LOCATION(), pos); // This needs to be set in the case that the hive was picked up and moved.
|
||||
} else {
|
||||
// Block has likely been destroyed
|
||||
var center = pos.getCenter();
|
||||
@@ -62,16 +58,16 @@ public abstract class BeeOccupantMixin {
|
||||
center.z + level.random.nextFloat() * 0.6 - 0.3
|
||||
);
|
||||
newYaw = level.random.nextFloat() * 360F;
|
||||
brain.eraseMemory(CobblemonMemories.HIVE_LOCATION);
|
||||
brain.eraseMemory(CobblemonMemories.INSTANCE.getHIVE_LOCATION());
|
||||
}
|
||||
entity.yRotO = newYaw;
|
||||
entity.setPos(newPos);
|
||||
// Do honey logic
|
||||
var hasNectar = brain.getMemory(CobblemonMemories.HAS_NECTAR).orElse(false);
|
||||
var hasNectar = brain.getMemory(CobblemonMemories.INSTANCE.getHAS_NECTAR()).orElse(false);
|
||||
if (hasNectar) {
|
||||
// Remove nectar and reset got to hive cooldown
|
||||
brain.eraseMemory(CobblemonMemories.HAS_NECTAR);
|
||||
brain.setMemoryWithExpiry(CobblemonMemories.HIVE_COOLDOWN, true, PathToBeeHiveTaskConfig.STAY_OUT_OF_HIVE_COOLDOWN);
|
||||
brain.eraseMemory(CobblemonMemories.INSTANCE.getHAS_NECTAR());
|
||||
brain.setMemoryWithExpiry(CobblemonMemories.INSTANCE.getHIVE_COOLDOWN(), true, PathToBeeHiveTaskConfig.STAY_OUT_OF_HIVE_COOLDOWN);
|
||||
// Increment honey level of the hive
|
||||
if (state.is(BlockTags.BEEHIVES, (blockStateBase) -> blockStateBase.hasProperty(BeehiveBlock.HONEY_LEVEL))) {
|
||||
int i = state.getValue(BeehiveBlock.HONEY_LEVEL);
|
||||
@@ -92,15 +88,13 @@ public abstract class BeeOccupantMixin {
|
||||
@Inject(method = "of", at = @At("HEAD"), cancellable = true)
|
||||
private static void cobblemon$of(Entity entity, CallbackInfoReturnable<BeehiveBlockEntity.Occupant> cir) {
|
||||
if (entity instanceof PokemonEntity pokemonEntity) {
|
||||
List<String> IGNORED_BEE_TAGS = Arrays.asList("Air", "ArmorDropChances", "ArmorItems", "Brain", "CanPickUpLoot", "DeathTime", "FallDistance", "FallFlying", "Fire", "HandDropChances", "HandItems", "HurtByTimestamp", "HurtTime", "LeftHanded", "Motion", "NoGravity", "OnGround", "PortalCooldown", "Pos", "Rotation", "Passengers", "leash", "UUID");
|
||||
CompoundTag compoundTag = new CompoundTag();
|
||||
entity.save(compoundTag);
|
||||
Objects.requireNonNull(compoundTag);
|
||||
IGNORED_BEE_TAGS.forEach(compoundTag::remove);
|
||||
Boolean hasNectar = pokemonEntity.getBrain().getMemory(CobblemonMemories.HAS_NECTAR).orElse(false);
|
||||
Boolean hasNectar = pokemonEntity.getBrain().getMemory(CobblemonMemories.INSTANCE.getHAS_NECTAR()).orElse(false);
|
||||
cir.setReturnValue(new BeehiveBlockEntity.Occupant(CustomData.of(compoundTag), 0, hasNectar ? 2400 : 600));
|
||||
cir.cancel();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,6 @@ import com.cobblemon.mod.common.client.entity.PokemonClientDelegate;
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.net.messages.server.orientation.ServerboundUpdateOrientationPacket;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
@@ -63,14 +61,6 @@ public abstract class LivingEntityMixin extends Entity implements OrientationCon
|
||||
}
|
||||
}
|
||||
|
||||
@WrapOperation(method = "baseTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;isInWall()Z"))
|
||||
public boolean cobblemon$preventMountSuffocation(LivingEntity instance, Operation<Boolean> original) {
|
||||
if (instance.getVehicle() instanceof PokemonEntity) {
|
||||
return false;
|
||||
}
|
||||
return original.call(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HitResult pick(double hitDistance, float partialTicks, boolean hitFluids) {
|
||||
Entity vehicle = this.getVehicle();
|
||||
@@ -115,7 +105,7 @@ public abstract class LivingEntityMixin extends Entity implements OrientationCon
|
||||
|
||||
@Inject(method = "tick", at = @At("HEAD"))
|
||||
private void cobblemon$updateRenderOrientation(CallbackInfo ci) {
|
||||
this.cobblemon$orientationController.tick();
|
||||
//this.cobblemon$orientationController.tick();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -38,7 +38,6 @@ import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.EntityDimensions;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
@@ -222,25 +221,24 @@ public abstract class PlayerMixin extends LivingEntity implements ScannableEntit
|
||||
|
||||
@Nullable @Unique
|
||||
private PokedexEntityData getDataFromShoulderPokemon(CompoundTag shoulderTag) {
|
||||
Pokemon pokemon;
|
||||
if (level().isClientSide) {
|
||||
CompoundTag pokemonTag = shoulderTag.getCompound(DataKeys.POKEMON);
|
||||
if (pokemonTag.isEmpty()) return null;
|
||||
Species species = PokemonSpecies.getByIdentifier(ResourceLocation.parse(pokemonTag.getString(DataKeys.POKEMON_SPECIES_IDENTIFIER)));
|
||||
if (species == null) return null;
|
||||
String formId = pokemonTag.getString(DataKeys.POKEMON_FORM_ID);
|
||||
FormData form = species.getStandardForm();
|
||||
List<FormData> formList = species.getForms().stream().filter(it -> it.formOnlyShowdownId().equals(formId)).toList();
|
||||
if (!formList.isEmpty()) form = formList.getFirst();
|
||||
if (form == null) return null;
|
||||
String genderString = pokemonTag.getString(DataKeys.POKEMON_GENDER);
|
||||
if (genderString.isEmpty()) return null;
|
||||
Gender gender = Gender.valueOf(genderString);
|
||||
boolean shiny = pokemonTag.getBoolean(DataKeys.POKEMON_SHINY);
|
||||
int level = pokemonTag.getInt(DataKeys.POKEMON_LEVEL);
|
||||
Set<String> aspects = shoulderTag.getList(DataKeys.SHOULDER_ASPECTS, Tag.TAG_STRING).stream().map(Tag::getAsString).collect(Collectors.toSet());
|
||||
CompoundTag pokemonTag = shoulderTag.getCompound(DataKeys.POKEMON);
|
||||
if (pokemonTag.isEmpty()) return null;
|
||||
Species species = PokemonSpecies.INSTANCE.getByIdentifier(ResourceLocation.parse(pokemonTag.getString(DataKeys.POKEMON_SPECIES_IDENTIFIER)));
|
||||
if (species == null) return null;
|
||||
String formId = pokemonTag.getString(DataKeys.POKEMON_FORM_ID);
|
||||
FormData form = species.getStandardForm();
|
||||
List<FormData> formList = species.getForms().stream().filter(it -> it.formOnlyShowdownId().equals(formId)).toList();
|
||||
if (!formList.isEmpty()) form = formList.getFirst();
|
||||
if (form == null) return null;
|
||||
String genderString = pokemonTag.getString(DataKeys.POKEMON_GENDER);
|
||||
if (genderString.isEmpty()) return null;
|
||||
Gender gender = Gender.valueOf(genderString);
|
||||
boolean shiny = pokemonTag.getBoolean(DataKeys.POKEMON_SHINY);
|
||||
int level = pokemonTag.getInt(DataKeys.POKEMON_LEVEL);
|
||||
Set<String> aspects = shoulderTag.getList(DataKeys.SHOULDER_ASPECTS, Tag.TAG_STRING).stream().map(Tag::getAsString).collect(Collectors.toSet());
|
||||
|
||||
pokemon = new Pokemon();
|
||||
Pokemon pokemon = new Pokemon();
|
||||
if (level().isClientSide) {
|
||||
pokemon.setSpecies(species);
|
||||
pokemon.setForm(form);
|
||||
pokemon.setGender(gender);
|
||||
@@ -251,7 +249,7 @@ public abstract class PlayerMixin extends LivingEntity implements ScannableEntit
|
||||
PlayerPartyStore party = Cobblemon.INSTANCE.getStorage().getParty(this.getUUID(), this.registryAccess());
|
||||
pokemon = party.get(shoulderTag.getUUID(DataKeys.SHOULDER_UUID));
|
||||
}
|
||||
return (pokemon == null) ? null : new PokedexEntityData(pokemon, null);
|
||||
return new PokedexEntityData(pokemon, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -319,7 +317,7 @@ public abstract class PlayerMixin extends LivingEntity implements ScannableEntit
|
||||
|
||||
@Override
|
||||
public void cobblemon$setRideXRot(float rideXRot) {
|
||||
this.cobblemon$rideXRot = Mth.wrapDegrees(rideXRot);
|
||||
this.cobblemon$rideXRot = rideXRot;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -329,7 +327,7 @@ public abstract class PlayerMixin extends LivingEntity implements ScannableEntit
|
||||
|
||||
@Override
|
||||
public void cobblemon$setRideYRot(float rideYRot) {
|
||||
this.cobblemon$rideYRot = Mth.wrapDegrees(rideYRot);
|
||||
this.cobblemon$rideYRot = rideYRot;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -29,4 +29,5 @@ public class RecipeBookSettingsMixin {
|
||||
private void cobblemon$init(CallbackInfo ci) {
|
||||
states.put(RecipeBookType.valueOf("COOKING_POT"), new RecipeBookSettings.TypeSettings(true, true));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -55,6 +55,86 @@ public abstract class SoundEngineMixin implements SoundEngineDuck {
|
||||
@Shadow
|
||||
public abstract boolean isActive(SoundInstance sound);
|
||||
|
||||
@Inject(method = "play",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/sounds/ChannelAccess$ChannelHandle;execute(Ljava/util/function/Consumer;)V"
|
||||
),
|
||||
cancellable = true
|
||||
)
|
||||
private void cobblemon$overrideChannelExecute(
|
||||
SoundInstance sound,
|
||||
CallbackInfo ci,
|
||||
@Local(name = "h") float h,
|
||||
@Local(name = "i") float i,
|
||||
@Local(name = "g") float g,
|
||||
@Local(name = "bl2") boolean bl2,
|
||||
@Local(name = "bl3") boolean bl3,
|
||||
@Local(name = "bl") boolean bl,
|
||||
@Local(name = "vec3") Vec3 vec3,
|
||||
@Local(name = "channelHandle") ChannelAccess.ChannelHandle handle
|
||||
) {
|
||||
if (!(sound instanceof RideLoopSound rideSound)) return;
|
||||
|
||||
if (handle == null) return;
|
||||
|
||||
handle.execute((channel) -> {
|
||||
channel.setPitch(i);
|
||||
channel.setVolume(h);
|
||||
|
||||
if (rideSound.getRideAttenuation() == RideAttenuationModel.LINEAR) {
|
||||
channel.linearAttenuation(g);
|
||||
} else if (rideSound.getRideAttenuation() == RideAttenuationModel.EXPONENTIAL){
|
||||
((ChannelDuck) channel).cobblemon$inverseAttenuation(g);
|
||||
} else {
|
||||
channel.disableAttenuation();
|
||||
}
|
||||
|
||||
// Apply low pass filter if the rideSound dictate that it should be muffled
|
||||
if (rideSound.getShouldMuffle()) {
|
||||
((ChannelDuck) channel).cobblemon$applyLowPassFilter(1.0f, rideSound.getMuffleAmount());
|
||||
} else {
|
||||
((ChannelDuck) channel).cobblemon$clearFilters();
|
||||
}
|
||||
|
||||
channel.setLooping(bl2 && !bl3);
|
||||
channel.setSelfPosition(vec3);
|
||||
channel.setRelative(bl);
|
||||
});
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "tickNonPaused",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/sounds/ChannelAccess$ChannelHandle;execute(Ljava/util/function/Consumer;)V",
|
||||
ordinal = 0
|
||||
)
|
||||
)
|
||||
private void cobblemon$tickableSoundTick(
|
||||
CallbackInfo ci,
|
||||
@Local(name = "tickableSoundInstance") TickableSoundInstance instance,
|
||||
@Local(name = "channelHandle", ordinal = 0) ChannelAccess.ChannelHandle handle,
|
||||
@Local(name = "f", ordinal = 0) float volume,
|
||||
@Local(name = "g", ordinal = 0) float pitch,
|
||||
@Local(name = "vec3", ordinal = 0) Vec3 vec3
|
||||
) {
|
||||
if (!(instance instanceof RideLoopSound rideSound)) return;
|
||||
|
||||
handle.execute(channel -> {
|
||||
channel.setVolume(volume);
|
||||
channel.setPitch(pitch);
|
||||
channel.setSelfPosition(vec3);
|
||||
|
||||
// Apply low pass filter if the rideSound dictate that it should be muffled
|
||||
if (rideSound.getShouldMuffle()) {
|
||||
((ChannelDuck) channel).cobblemon$applyLowPassFilter(1.0f, rideSound.getMuffleAmount());
|
||||
} else {
|
||||
((ChannelDuck) channel).cobblemon$clearFilters();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Resumes the Source belonging to the queried SoundInstance. */
|
||||
private void resume(SoundInstance sound) {
|
||||
ChannelAccess.ChannelHandle sourceManager = this.instanceToChannel.get(sound);
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.accessor;
|
||||
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(Camera.class)
|
||||
public interface CameraAccessor {
|
||||
@Accessor("level")
|
||||
BlockGetter getLevel();
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(BrewingStandMenu.class)
|
||||
public abstract class BrewingStandMenuMixin {
|
||||
|
||||
@Inject(method = "<init>(ILnet/minecraft/world/entity/player/Inventory;Lnet/minecraft/world/Container;Lnet/minecraft/world/inventory/ContainerData;)V", at = @At("TAIL"))
|
||||
private void captureLevel(int containerId, Inventory playerInventory, Container brewingStandContainer, ContainerData brewingStandData, CallbackInfo ci) {
|
||||
var recipeManager = playerInventory.player.level().getRecipeManager();
|
||||
@@ -36,4 +37,9 @@ public abstract class BrewingStandMenuMixin {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@WrapOperation(method = "quickMoveStack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/BrewingStandMenu$PotionSlot;mayPlaceItem(Lnet/minecraft/world/item/ItemStack;)Z"))
|
||||
private boolean cobblemon$isPotionBottle(ItemStack stack, Operation<Boolean> original, @Local(argsOnly = true) Player player) {
|
||||
return BrewingStandRecipe.Companion.isBottle(stack, player.level().getRecipeManager()) || original.call(stack);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,58 +8,89 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.OrientationControllable;
|
||||
import com.cobblemon.mod.common.api.orientation.OrientationController;
|
||||
import com.cobblemon.mod.common.api.riding.Rideable;
|
||||
import com.cobblemon.mod.common.client.MountedPokemonAnimationRenderController;
|
||||
import com.cobblemon.mod.common.client.render.camera.MountedCameraRenderer;
|
||||
import com.cobblemon.mod.common.duck.CameraDuck;
|
||||
import com.cobblemon.mod.common.duck.RidePassenger;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import com.mojang.blaze3d.Blaze3D;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
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 implements CameraDuck {
|
||||
public abstract class CameraMixin {
|
||||
@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 private float eyeHeight;
|
||||
@Shadow private float eyeHeightOld;
|
||||
@Shadow private BlockGetter level;
|
||||
@Shadow private Entity entity;
|
||||
@Final @Shadow private Vector3f forwards;
|
||||
@Final @Shadow private Vector3f up;
|
||||
@Final @Shadow private Vector3f left;
|
||||
@Shadow private float yRot;
|
||||
@Shadow private float xRot;
|
||||
|
||||
@Shadow protected abstract void setPosition(Vec3 pos);
|
||||
|
||||
@Override public BlockGetter cobblemon$getLevel() {
|
||||
return level;
|
||||
@Shadow private float partialTickTime;
|
||||
|
||||
// Used to help in camera rotation rendering when transitioning
|
||||
// from rolled to unrolled.
|
||||
@Unique private float cobblemon$returnTimer = 0;
|
||||
@Unique private float cobblemon$rollAngleStart = 0;
|
||||
|
||||
@Unique private double cobblemon$lastHandledRotationTime = Double.MIN_VALUE;
|
||||
@Unique private double cobblemon$frameTime = 0.0;
|
||||
|
||||
@Inject(method = "setRotation", at = @At("HEAD"), cancellable = true)
|
||||
public void cobblemon$setRotation(float f, float g, CallbackInfo ci) {
|
||||
// Calculate the current frametime
|
||||
double d = Blaze3D.getTime();
|
||||
this.cobblemon$frameTime = (this.cobblemon$lastHandledRotationTime != Double.MIN_VALUE) ? d - this.cobblemon$lastHandledRotationTime : 0.0;
|
||||
this.cobblemon$lastHandledRotationTime = d;
|
||||
|
||||
// Don't assume the camera to be attached to an entity. Ponder Scenes from create et.al. for example aren't.
|
||||
if (this.entity == null) return;
|
||||
var vehicle = this.entity.getVehicle();
|
||||
if (!(vehicle instanceof OrientationControllable controllableVehicle)) return;
|
||||
var instance = (Camera)(Object)this;
|
||||
|
||||
// If the current vehicle has no orientation then return and perform
|
||||
// vanilla camera rotations
|
||||
var vehicleController = controllableVehicle.getOrientationController();
|
||||
if (vehicleController.getOrientation() == null) return;
|
||||
|
||||
// If the controller has been deactivated but the orientation isn't null yet
|
||||
// then perform transition from rolled ride/camera to vanilla
|
||||
if (!vehicleController.isActive() && vehicleController.getOrientation() != null) {
|
||||
cobblemon$applyTransitionRotation(vehicleController, ci);
|
||||
} else { // Otherwise perform cobblemon specific camera rotation and set transition helper variables
|
||||
cobblemon$applyRotation();
|
||||
this.cobblemon$returnTimer = 0;
|
||||
this.cobblemon$rollAngleStart = instance.rotation().getEulerAnglesYXZ(new Vector3f()).z();
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override public Entity cobblemon$getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override public Vector3f cobblemon$getForwards() { return forwards; }
|
||||
|
||||
@Override public Vector3f cobblemon$getUp() { return up; }
|
||||
|
||||
@Override public Vector3f cobblemon$getLeft() { return left; }
|
||||
|
||||
@Override public float cobblemon$getXRot() { return xRot; }
|
||||
@Override public void cobblemon$setXRot(float xRot) { this.xRot = xRot; }
|
||||
|
||||
@Override public float cobblemon$getYRot() { return yRot; }
|
||||
@Override public void cobblemon$setYRot(float yRot) { this.yRot = yRot; }
|
||||
|
||||
@WrapOperation(method = "setup", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Camera;setPosition(DDD)V"))
|
||||
public void cobblemon$positionCamera(Camera instance, double x, double y, double z, Operation<Void> original, @Local(ordinal = 1, argsOnly = true) boolean thirdPersonReverse) {
|
||||
Entity entity = instance.getEntity();
|
||||
@@ -68,22 +99,157 @@ public abstract class CameraMixin implements CameraDuck {
|
||||
|
||||
if(vehicle instanceof Rideable){
|
||||
Vec3 position = MountedCameraRenderer.INSTANCE.getCameraPosition(
|
||||
instance,
|
||||
entity,
|
||||
vehicle,
|
||||
thirdPersonReverse,
|
||||
eyeHeight,
|
||||
eyeHeightOld
|
||||
instance,
|
||||
entity,
|
||||
vehicle,
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
thirdPersonReverse,
|
||||
eyeHeightOld,
|
||||
eyeHeight
|
||||
);
|
||||
|
||||
if(position != null) {
|
||||
if(position != null){
|
||||
setPosition(position);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// reset the rotation values if it is now not being ridden.
|
||||
MountedCameraRenderer.INSTANCE.setSmoothRotation(null);
|
||||
original.call(instance, x, y, z);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void cobblemon$applyRotation(){
|
||||
var driver = this.entity;
|
||||
if (!(driver.getVehicle() instanceof OrientationControllable controllableVehicle) ||
|
||||
controllableVehicle.getOrientationController().getOrientation() == null ||
|
||||
!controllableVehicle.getOrientationController().getActive()
|
||||
) return;
|
||||
|
||||
// Grab the driver and vehicle orientation controllers.
|
||||
var vehicleController = controllableVehicle.getOrientationController();
|
||||
|
||||
var isDriving = driver.getControlledVehicle() != null;
|
||||
|
||||
// Grab the ride orientation
|
||||
var newRotation = new Quaternionf();
|
||||
|
||||
// If the player is driving then use the current orientation since the driver sets it.
|
||||
// If not then use the smoothed render orientation for passengers otherwise the vehicle rotation will be jerky
|
||||
if (isDriving) {
|
||||
newRotation = vehicleController.getOrientation().normal(new Matrix3f()).getNormalizedRotation(new Quaternionf());
|
||||
} else {
|
||||
newRotation = vehicleController.getRenderOrientation(this.partialTickTime);
|
||||
}
|
||||
|
||||
// Unroll the current rotation if no roll is requested
|
||||
if (Cobblemon.config.getDisableRoll()) {
|
||||
var eulerAngs = newRotation.getEulerAnglesYXZ(new Vector3f());
|
||||
var currAngs = this.rotation.getEulerAnglesYXZ(new Vector3f());
|
||||
var vehicle = (PokemonEntity)driver.getVehicle();
|
||||
var vel = vehicle.getRidingAnimationData().getVelocitySpring().getInterpolated(this.partialTickTime, 0);
|
||||
|
||||
// lerp the new rotation towards this y rot at a rate proportional to the horizontal movement speed?
|
||||
var yaw = Mth.wrapDegrees(Math.toDegrees(Mth.atan2(vel.x(), vel.z())) + 180.0f);
|
||||
|
||||
var degDiff = Mth.degreesDifference((float)Math.toDegrees(currAngs.y()), (float)yaw);
|
||||
var pitchDeadzoneDeg = 15.0; // x degrees of deadzone about +-90 degrees of pitch.
|
||||
var pitchDeg = vehicleController.getPitch();
|
||||
// ConsiderPitch to be already 90 if within the deadzone around it.
|
||||
var cutoffPitch = Math.min(1.0,(Mth.abs(pitchDeg) / (90.0f - pitchDeadzoneDeg))) * 90.0f * Math.signum(pitchDeg);
|
||||
var lerpRateMod = Mth.cos((float)Math.toRadians(cutoffPitch));
|
||||
|
||||
// Apply smoothing from the cameras current yaw to the yaw of the velocity vector of the ride.
|
||||
var k = 5.0f; // Some smoothing constant k
|
||||
var smoothingFactor = lerpRateMod * cobblemon$frameTime * k;
|
||||
var newYaw = currAngs.y() + (Math.toRadians(degDiff) * smoothingFactor);
|
||||
|
||||
newRotation.set(new Quaternionf().rotateYXZ((float)newYaw, eulerAngs.x(), 0.0f));
|
||||
}
|
||||
|
||||
var rotationOffset = 0;
|
||||
if (Minecraft.getInstance().options.getCameraType().isMirrored()) {
|
||||
newRotation.rotateY((float)Math.toRadians(180));
|
||||
rotationOffset = 180;
|
||||
}
|
||||
|
||||
// Get the drivers local look angle in relation to the ride and apply it.
|
||||
if (vehicleController.getActive()) {
|
||||
var vehicleMatrix = new Matrix3f().set(newRotation);
|
||||
var driverMatrix = new Matrix3f();// Base the driver
|
||||
var playerRotater = (RidePassenger)driver;
|
||||
newRotation = vehicleMatrix.mul(
|
||||
driverMatrix.rotateYXZ(
|
||||
-Mth.DEG_TO_RAD * (playerRotater.cobblemon$getRideYRot()),
|
||||
-Mth.DEG_TO_RAD * playerRotater.cobblemon$getRideXRot(),
|
||||
0.0f)
|
||||
).normal(new Matrix3f()).getNormalizedRotation(new Quaternionf());
|
||||
}
|
||||
this.rotation.set(newRotation);
|
||||
var eulerAngs = newRotation.getEulerAnglesXYZ(new Vector3f());
|
||||
this.xRot = eulerAngs.x() * Mth.RAD_TO_DEG;
|
||||
this.yRot = eulerAngs.y() * Mth.RAD_TO_DEG;
|
||||
// Set the drivers rotations to match
|
||||
var driverEulerAngs = new Quaternionf(this.rotation).getEulerAnglesYXZ(new Vector3f());
|
||||
driver.setXRot(-driverEulerAngs.x() * Mth.RAD_TO_DEG + rotationOffset);
|
||||
driver.setYRot(180.0f - (driverEulerAngs.y() * Mth.RAD_TO_DEG));
|
||||
|
||||
OrientationController.Companion.getFORWARDS().rotate(this.rotation, this.forwards);
|
||||
OrientationController.Companion.getUP().rotate(this.rotation, this.up);
|
||||
OrientationController.Companion.getLEFT().rotate(this.rotation, this.left);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void cobblemon$applyTransitionRotation(
|
||||
OrientationController vehicleController,
|
||||
CallbackInfo ci
|
||||
) {
|
||||
// If the transition has just started then
|
||||
if (this.cobblemon$returnTimer == 0.0) {
|
||||
MountedCameraRenderer.INSTANCE.resetDriverRotations((Camera)(Object)this, this.entity);
|
||||
}
|
||||
|
||||
if(this.cobblemon$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.
|
||||
float interpolatedRoll = Mth.lerp(this.cobblemon$returnTimer, this.cobblemon$rollAngleStart, 0.0f);
|
||||
float pitch = (float) Math.toRadians(-this.entity.getXRot());
|
||||
float yaw = (float) Math.toRadians(180 - this.entity.getYRot());
|
||||
|
||||
Quaternionf interRot = new Quaternionf();
|
||||
interRot.rotationYXZ(yaw, pitch, interpolatedRoll);
|
||||
|
||||
this.rotation.set(interRot);
|
||||
var eulerAngs = interRot.getEulerAnglesXYZ(new Vector3f());
|
||||
this.xRot = eulerAngs.x() * Mth.RAD_TO_DEG;
|
||||
this.yRot = eulerAngs.y() * Mth.RAD_TO_DEG;
|
||||
OrientationController.Companion.getFORWARDS().rotate(this.rotation, this.forwards);
|
||||
OrientationController.Companion.getUP().rotate(this.rotation, this.up);
|
||||
OrientationController.Companion.getLEFT().rotate(this.rotation, this.left);
|
||||
|
||||
if(cobblemon$rollAngleStart == 0){
|
||||
this.cobblemon$returnTimer = 1;
|
||||
vehicleController.reset();
|
||||
MountedCameraRenderer.INSTANCE.resetDriverRotations((Camera)(Object)this, this.entity);
|
||||
return;
|
||||
}
|
||||
this.cobblemon$returnTimer += (partialTickTime * (1.0f/20.0f));
|
||||
ci.cancel();
|
||||
} else {
|
||||
this.cobblemon$returnTimer = 1;
|
||||
vehicleController.reset();
|
||||
MountedCameraRenderer.INSTANCE.resetDriverRotations((Camera)(Object)this, this.entity);
|
||||
}
|
||||
}
|
||||
|
||||
@WrapOperation(method = "setup", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Camera;move(FFF)V", ordinal = 0))
|
||||
public void stopMoveIfRolling(Camera instance, float zoom, float dy, float dx, Operation<Void> original) {
|
||||
Entity entity = instance.getEntity();
|
||||
Entity vehicle = entity.getVehicle();
|
||||
|
||||
if (!(vehicle instanceof PokemonEntity) || Cobblemon.config.getThirdPersonViewBobbing()) {
|
||||
original.call(instance, zoom, dy, dx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.OrientationControllable;
|
||||
import com.cobblemon.mod.common.client.render.player.MountedPlayerRenderer;
|
||||
import com.cobblemon.mod.common.duck.RidePassenger;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import net.minecraft.client.model.HumanoidModel;
|
||||
import net.minecraft.client.model.geom.ModelPart;
|
||||
@@ -69,18 +68,6 @@ public class HumanoidModelMixin {
|
||||
behaviour.shouldRotateRiderHead(settings, state, pokemonEntity)
|
||||
);
|
||||
|
||||
// If the player is on a rollable ride then use the ride local rotations to rotate the head
|
||||
// This is to allow the player head to face the correct direction when "freelooking"
|
||||
// TODO: find a way for this to work on built jars without borking head rotations.
|
||||
// if (entity instanceof RidePassenger playerRotater &&
|
||||
// vehicle instanceof OrientationControllable controller &&
|
||||
// controller.getOrientationController().isActive()) {
|
||||
// this.head.xRot = playerRotater.cobblemon$getRideXRot();
|
||||
// headPitch = playerRotater.cobblemon$getRideXRot();
|
||||
// this.head.yRot = playerRotater.cobblemon$getRideYRot();
|
||||
// netHeadYaw = playerRotater.cobblemon$getRideYRot();
|
||||
// }
|
||||
|
||||
if (!shouldRotatePlayerHead) {
|
||||
netHeadYaw = 0f;
|
||||
headPitch = 0f;
|
||||
|
||||
+2
-2
@@ -36,9 +36,9 @@ public class ItemInHandRendererMixin {
|
||||
}
|
||||
}
|
||||
|
||||
@Redirect(method = "renderHandsWithItems", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;mulPose(Lorg/joml/Quaternionf;)V"))
|
||||
@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 != null && Minecraft.getInstance().player.getVehicle() instanceof OrientationControllable controllable && controllable.getOrientationController().isActive())) {
|
||||
if (!(Minecraft.getInstance().player instanceof OrientationControllable controllable && controllable.getOrientationController().isActive())) {
|
||||
instance.mulPose(quaternion);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +129,10 @@ public abstract class LocalPlayerMixin extends AbstractClientPlayer implements O
|
||||
if (Minecraft.getInstance().player != (Object)this) return;
|
||||
if (!(this.getVehicle() instanceof PokemonEntity pokemonEntity)) return;
|
||||
|
||||
// Only send rotation updates if the player is riding a vehicle that is currently rollable
|
||||
if (!(this.getVehicle() instanceof OrientationControllable controllableVehicle)) return;
|
||||
if (!controllableVehicle.getOrientationController().getActive()) return;
|
||||
|
||||
var passenger = (LocalPlayer)(Object)this;
|
||||
var playerRotater = (RidePassenger)passenger;
|
||||
|
||||
@@ -200,7 +204,7 @@ public abstract class LocalPlayerMixin extends AbstractClientPlayer implements O
|
||||
this.cobblemon$survivalJumpTriggerTime = 0;
|
||||
}
|
||||
else {
|
||||
this.cobblemon$survivalJumpTriggerTime = 12;
|
||||
this.cobblemon$survivalJumpTriggerTime = 7;
|
||||
}
|
||||
}
|
||||
else if (this.cobblemon$survivalJumpTriggerTime > 0) {
|
||||
@@ -227,17 +231,33 @@ public abstract class LocalPlayerMixin extends AbstractClientPlayer implements O
|
||||
public HitResult pick(double hitDistance, float partialTicks, boolean hitFluids) {
|
||||
Entity vehicle = this.getVehicle();
|
||||
if (vehicle instanceof PokemonEntity pokemonEntity) {
|
||||
PokemonClientDelegate delegate = (PokemonClientDelegate) pokemonEntity.getDelegate();
|
||||
String locatorName = delegate.getSeatLocator(this);
|
||||
MatrixWrapper locator = delegate.getLocatorStates().get(locatorName);
|
||||
|
||||
// Get player object
|
||||
var passenger = (LocalPlayer)(Object)this;
|
||||
var playerRotater = (RidePassenger)passenger;
|
||||
if (locator == null) {
|
||||
return super.pick(hitDistance, partialTicks, hitFluids);
|
||||
}
|
||||
|
||||
// Gather eye position from stored 1st person camera position calculation
|
||||
var eyePosition = playerRotater.cobblemon$getRideEyePos();
|
||||
Vec3 locatorOffset = locator != null ? new Vec3(locator.getMatrix().getTranslation(new Vector3f())) : Vec3.ZERO;
|
||||
|
||||
OrientationController controller = this.getOrientationController();
|
||||
|
||||
float currEyeHeight = this.getEyeHeight();
|
||||
Vector3f offset = new Vector3f(new Vector3f(0f, currEyeHeight - (this.getBbHeight() / 2), 0f));
|
||||
|
||||
if (Minecraft.getInstance().options.getCameraType() == CameraType.FIRST_PERSON) {
|
||||
PosableModel model = VaryingModelRepository.INSTANCE.getPoser(pokemonEntity.getPokemon().getSpecies().getResourceIdentifier(), new FloatingState());
|
||||
offset.add(cobblemon$getFirstPersonOffset(model, locatorName));
|
||||
}
|
||||
|
||||
Matrix3f orientation = controller.isActive() && controller.getOrientation() != null ? controller.getOrientation() : new Matrix3f();
|
||||
Vec3 rotatedEyeHeight = new Vec3(orientation.transform(offset));
|
||||
|
||||
Vec3 eyePosition = locatorOffset.add(pokemonEntity.position()).add(rotatedEyeHeight);
|
||||
|
||||
Vec3 viewVector = this.getViewVector(partialTicks);
|
||||
Vec3 viewDistanceVector = eyePosition.add(viewVector.x * hitDistance, viewVector.y * hitDistance, viewVector.z * hitDistance);
|
||||
|
||||
return this.level()
|
||||
.clip(
|
||||
new ClipContext(
|
||||
|
||||
@@ -122,9 +122,8 @@ public abstract class MouseHandlerMixin {
|
||||
double cursorDeltaY,
|
||||
@Local(argsOnly = true) double d,
|
||||
@Local(argsOnly = true) double movementTime
|
||||
) {
|
||||
) {
|
||||
PokedexUsageContext usageContext = CobblemonClient.INSTANCE.getPokedexUsageContext();
|
||||
boolean returnValue = true;
|
||||
if (usageContext.getScanningGuiOpen()) {
|
||||
this.smoothTurnY.reset();
|
||||
this.smoothTurnX.reset();
|
||||
@@ -134,11 +133,10 @@ public abstract class MouseHandlerMixin {
|
||||
var sensitivity = lerp(usageContext.getFovMultiplier(), spyglassSensitivity, lookSensitivity);
|
||||
var yRotationFlip = this.minecraft.options.invertYMouse().get() ? -1 : 1;
|
||||
player.turn(this.accumulatedDX * sensitivity, (this.accumulatedDY * sensitivity * yRotationFlip));
|
||||
returnValue = false;
|
||||
}
|
||||
|
||||
var vehicle = player.getVehicle();
|
||||
if (!(vehicle instanceof PokemonEntity)) return returnValue;
|
||||
if (!(vehicle instanceof PokemonEntity)) return true;
|
||||
|
||||
// Clamp player rotation if riding and the vehicle demands it
|
||||
if (player.isPassenger() && vehicle instanceof PokemonEntity pokeVehicle) {
|
||||
@@ -152,7 +150,7 @@ public abstract class MouseHandlerMixin {
|
||||
pitchSmoother.reset();
|
||||
rollSmoother.reset();
|
||||
yawSmoother.reset();
|
||||
return returnValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
var vehicleController = controllableVehicle.getOrientationController();
|
||||
@@ -223,7 +221,7 @@ public abstract class MouseHandlerMixin {
|
||||
vehicleController.rotate((float) (angRot.x * 10 * d), (float) (angRot.y * 10 * d), (float) (angRot.z * 10 * d));
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Inject(method = "handleAccumulatedMovement", at = @At("HEAD"))
|
||||
@@ -310,7 +308,6 @@ public abstract class MouseHandlerMixin {
|
||||
playerRotater.cobblemon$setRideXRot(playerRotater.cobblemon$getRideXRot() + f);
|
||||
playerRotater.cobblemon$setRideYRot(playerRotater.cobblemon$getRideYRot() + g);
|
||||
playerRotater.cobblemon$setRideXRot(Mth.clamp(playerRotater.cobblemon$getRideXRot(), -90.0F, 90.0F));
|
||||
playerRotater.cobblemon$setRideYRot(Mth.clamp(playerRotater.cobblemon$getRideYRot(), -105.0F, 105.0F));
|
||||
if (player.getVehicle() != null) {
|
||||
player.getVehicle().onPassengerTurned(player);
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.OrientationControllable;
|
||||
import net.minecraft.client.CameraType;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.Options;
|
||||
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.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(Options.class)
|
||||
public abstract class OptionsMixin {
|
||||
|
||||
/**
|
||||
* Only allow third person on rollables when motion sick cam is enabled
|
||||
*/
|
||||
@Inject(
|
||||
method = "getCameraType",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true
|
||||
)
|
||||
private void cobblemon$forceThirdPerson(CallbackInfoReturnable<CameraType> cir) {
|
||||
var mc = Minecraft.getInstance();
|
||||
if(!(mc.player instanceof Player player)) return;
|
||||
if(!(player.getVehicle() instanceof OrientationControllable vehicle)) return;
|
||||
if(vehicle.getOrientationController() == null) return;
|
||||
|
||||
// Force third person if on an active rollable vehicle and roll is disabled.
|
||||
if (Cobblemon.config.getDisableRoll() && vehicle.getOrientationController().isActive()) {
|
||||
cir.setReturnValue(CameraType.THIRD_PERSON_BACK);
|
||||
cir.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -52,7 +52,7 @@ public class RecipeBookCategoriesMixin {
|
||||
types.add(cobblemon$createCategory("COOKING_POT_SEARCH", $VALUES.length, new ItemStack(Items.COMPASS)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_FOODS", $VALUES.length + 1, new ItemStack(CobblemonItems.LEEK_AND_POTATO_STEW)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_MEDICINES", $VALUES.length + 2, new ItemStack(CobblemonItems.POTION)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_COMPLEX_DISHES", $VALUES.length + 3, new ItemStack(CobblemonItems.APRIJUICE_RED)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_COMPLEX_DISHES", $VALUES.length + 3, new ItemStack(CobblemonItems.POKE_PUFF)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_MISC", $VALUES.length + 4, new ItemStack(CobblemonItems.PROTEIN)));
|
||||
$VALUES = types.toArray(RecipeBookCategories[]::new);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import com.cobblemon.mod.common.duck.RidePassenger;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
@@ -69,17 +68,18 @@ public abstract class EntityMixin {
|
||||
)
|
||||
private void cobblemon$modifyEyePosition_partial(float partialTicks, CallbackInfoReturnable<Vec3> cir) {
|
||||
var entity = (Entity)(Object)this;
|
||||
if (entity.level().isClientSide) return;
|
||||
if (!(entity instanceof Player player)) return;
|
||||
if (!(player instanceof RidePassenger ridePassenger)) return;
|
||||
if (!(player.getVehicle() instanceof OrientationControllable vehicle)) return;
|
||||
var vehicleController = vehicle.getOrientationController();
|
||||
if (vehicleController == null) return;
|
||||
|
||||
|
||||
// TODO: Determine if it needs partialtick involved.
|
||||
Vec3 customEyePos = ridePassenger.cobblemon$getRideEyePos();
|
||||
cir.setReturnValue(customEyePos);
|
||||
// If Orientation is currently being controlled then use the stored eye position from camera positioning.
|
||||
if (vehicleController.getActive() && vehicleController.getOrientation() != null) {
|
||||
// TODO: Determine if it needs partialtick involved.
|
||||
Vec3 customEyePos = ridePassenger.cobblemon$getRideEyePos();
|
||||
cir.setReturnValue(customEyePos);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
@@ -89,16 +89,18 @@ public abstract class EntityMixin {
|
||||
)
|
||||
private void cobblemon$modifyEyePosition_noPartial(CallbackInfoReturnable<Vec3> cir) {
|
||||
var entity = (Entity)(Object)this;
|
||||
if (entity.level().isClientSide) return;
|
||||
if (!(entity instanceof Player player)) return;
|
||||
if (!(player instanceof RidePassenger ridePassenger)) return;
|
||||
if (!(player.getVehicle() instanceof OrientationControllable vehicle)) return;
|
||||
var vehicleController = vehicle.getOrientationController();
|
||||
if (vehicleController == null) return;
|
||||
|
||||
// TODO: Determine if it needs partialtick involved.
|
||||
Vec3 customEyePos = ridePassenger.cobblemon$getRideEyePos();
|
||||
cir.setReturnValue(customEyePos);
|
||||
// If Orientation is currently being controlled then use the stored eye position from camera positioning.
|
||||
if (vehicleController.getActive() && vehicleController.getOrientation() != null) {
|
||||
// TODO: Determine if it needs partialtick involved.
|
||||
Vec3 customEyePos = ridePassenger.cobblemon$getRideEyePos();
|
||||
cir.setReturnValue(customEyePos);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import com.cobblemon.mod.common.api.drop.ItemDropEntry
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.DATA_SYNCHRONIZED
|
||||
import com.cobblemon.mod.common.api.interaction.RequestManager
|
||||
import com.cobblemon.mod.common.api.molang.MoLangLoadedFilesCache
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.permission.PermissionValidator
|
||||
import com.cobblemon.mod.common.api.pokeball.catching.calculators.CaptureCalculator
|
||||
@@ -45,7 +44,6 @@ import com.cobblemon.mod.common.api.spawning.CobblemonSpawningZoneGenerator
|
||||
import com.cobblemon.mod.common.api.spawning.position.AreaSpawnablePositionResolver
|
||||
import com.cobblemon.mod.common.api.spawning.SpawningZoneGenerator
|
||||
import com.cobblemon.mod.common.api.starter.StarterHandler
|
||||
import com.cobblemon.mod.common.api.stats.CobblemonStats
|
||||
import com.cobblemon.mod.common.api.storage.PokemonStoreManager
|
||||
import com.cobblemon.mod.common.api.storage.adapter.conversions.ReforgedConversion
|
||||
import com.cobblemon.mod.common.api.storage.adapter.database.MongoDBStoreAdapter
|
||||
@@ -81,7 +79,6 @@ import com.cobblemon.mod.common.events.EntityCallbackHandler
|
||||
import com.cobblemon.mod.common.events.CallbackHandler
|
||||
import com.cobblemon.mod.common.events.PokedexHandler
|
||||
import com.cobblemon.mod.common.events.ServerTickHandler
|
||||
import com.cobblemon.mod.common.events.StatHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
|
||||
import com.cobblemon.mod.common.permission.LaxPermissionValidator
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
@@ -91,8 +88,6 @@ 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.SlowpokeTailRegrowthSpeciesFeature
|
||||
import com.cobblemon.mod.common.pokemon.feature.SlowpokeTailRegrowthSpeciesFeatureProvider
|
||||
import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.pokemon.properties.*
|
||||
@@ -167,8 +162,6 @@ object Cobblemon {
|
||||
|
||||
val serverPlayerStructs = mutableMapOf<UUID, ObjectValue<Player>>()
|
||||
|
||||
val statistics: CobblemonStats = CobblemonStats
|
||||
|
||||
@JvmStatic
|
||||
val builtinPacks = listOf<CobblemonPack>(
|
||||
CobblemonPack(id = "adorncompatibility", name = "Adorn Compatibility", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.ALWAYS_ENABLED, neededMods = setOf("adorn")),
|
||||
@@ -309,13 +302,7 @@ object Cobblemon {
|
||||
|
||||
SpeciesFeatures.register(
|
||||
DataKeys.HAS_BEEN_SHEARED,
|
||||
FlagSpeciesFeatureProvider(keys = listOf(DataKeys.HAS_BEEN_SHEARED), default = false)
|
||||
)
|
||||
|
||||
SpeciesFeatures.register(
|
||||
SlowpokeTailRegrowthSpeciesFeature.NAME,
|
||||
SlowpokeTailRegrowthSpeciesFeatureProvider
|
||||
)
|
||||
FlagSpeciesFeatureProvider(keys = listOf(DataKeys.HAS_BEEN_SHEARED), default = false))
|
||||
|
||||
CustomPokemonProperty.register(UncatchableProperty)
|
||||
CustomPokemonProperty.register(BattleCloneProperty)
|
||||
@@ -344,7 +331,6 @@ object Cobblemon {
|
||||
}
|
||||
PlatformEvents.SERVER_STARTING.subscribe { event ->
|
||||
val server = event.server
|
||||
MoLangLoadedFilesCache.initialize(server)
|
||||
playerDataManager = PlayerInstancedDataStoreManager().also { it.setup(server) }
|
||||
|
||||
val mongoClient: MongoClient?
|
||||
@@ -447,7 +433,6 @@ object Cobblemon {
|
||||
fun registerEventHandlers() {
|
||||
AdvancementHandler.registerListeners()
|
||||
PokedexHandler.registerListeners()
|
||||
StatHandler.registerListeners()
|
||||
}
|
||||
|
||||
fun getLevel(dimension: ResourceKey<Level>): Level? {
|
||||
|
||||
@@ -11,26 +11,16 @@ package com.cobblemon.mod.common
|
||||
import net.minecraft.world.entity.schedule.Activity
|
||||
|
||||
object CobblemonActivities {
|
||||
@JvmField
|
||||
val activities = mutableListOf<Activity>()
|
||||
@JvmField
|
||||
val BATTLING = register(Activity("battling"))
|
||||
@JvmField
|
||||
val ACTION_EFFECT = register(Activity("action_effect"))
|
||||
@JvmField
|
||||
val NPC_CHATTING = register(Activity("npc_chatting"))
|
||||
@JvmField
|
||||
val POKEMON_SLEEPING_ACTIVITY = register(Activity("pokemon_sleeping"))
|
||||
@JvmField
|
||||
val POKEMON_GROW_CROP = register(Activity("pokemon_grow_crop"))
|
||||
@JvmField
|
||||
val POKEMON_SLEEP_ON_TRAINER_BED = register(Activity("pokemon_sleep_on_trainer_bed"))
|
||||
@JvmField
|
||||
val POKEMON_HERD = register(Activity("pokemon_herd"))
|
||||
@JvmField
|
||||
val POKEMON_POLLINATION = register(Activity("pokemon_pollination"))
|
||||
|
||||
@JvmStatic
|
||||
fun register(activity: Activity): Activity {
|
||||
activities.add(activity)
|
||||
return activity
|
||||
|
||||
@@ -60,13 +60,13 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
|
||||
// Evolution Ores
|
||||
@JvmField
|
||||
val DAWN_STONE_ORE = evolutionStoneOre("dawn_stone_ore", 7)
|
||||
val DAWN_STONE_ORE = evolutionStoneOre("dawn_stone_ore")
|
||||
@JvmField
|
||||
val DUSK_STONE_ORE = evolutionStoneOre("dusk_stone_ore")
|
||||
@JvmField
|
||||
val FIRE_STONE_ORE = evolutionStoneOre("fire_stone_ore", 10)
|
||||
val FIRE_STONE_ORE = evolutionStoneOre("fire_stone_ore")
|
||||
@JvmField
|
||||
val NETHER_FIRE_STONE_ORE = this.create("nether_fire_stone_ore", DropExperienceBlock(UniformInt.of(1, 2), BlockBehaviour.Properties.of().mapColor(MapColor.NETHER).instrument(NoteBlockInstrument.BASEDRUM).requiresCorrectToolForDrops().strength(3.0F, 3.0F).sound(SoundType.NETHER_ORE).lightLevel{10}))
|
||||
val NETHER_FIRE_STONE_ORE = evolutionStoneOre("nether_fire_stone_ore")
|
||||
@JvmField
|
||||
val ICE_STONE_ORE = evolutionStoneOre("ice_stone_ore")
|
||||
@JvmField
|
||||
@@ -74,24 +74,24 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val MOON_STONE_ORE = evolutionStoneOre("moon_stone_ore")
|
||||
@JvmField
|
||||
val DRIPSTONE_MOON_STONE_ORE = this.create("dripstone_moon_stone_ore", DropExperienceBlock(UniformInt.of(1, 2), BlockBehaviour.Properties.of().mapColor(MapColor.TERRACOTTA_BROWN).instrument(NoteBlockInstrument.BASEDRUM).requiresCorrectToolForDrops().strength(3.0F, 3.0F).sound(SoundType.DRIPSTONE_BLOCK)))
|
||||
val DRIPSTONE_MOON_STONE_ORE = evolutionStoneOre("dripstone_moon_stone_ore")
|
||||
@JvmField
|
||||
val SHINY_STONE_ORE = evolutionStoneOre("shiny_stone_ore", 12)
|
||||
val SHINY_STONE_ORE = evolutionStoneOre("shiny_stone_ore")
|
||||
@JvmField
|
||||
val SUN_STONE_ORE = evolutionStoneOre("sun_stone_ore", 2)
|
||||
val SUN_STONE_ORE = evolutionStoneOre("sun_stone_ore")
|
||||
@JvmField
|
||||
val TERRACOTTA_SUN_STONE_ORE = this.create("terracotta_sun_stone_ore", DropExperienceBlock(UniformInt.of(1, 2), BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_ORANGE).instrument(NoteBlockInstrument.BASEDRUM).requiresCorrectToolForDrops().strength(3.0F, 3.0F).lightLevel{2}))
|
||||
val TERRACOTTA_SUN_STONE_ORE = evolutionStoneOre("terracotta_sun_stone_ore")
|
||||
@JvmField
|
||||
val THUNDER_STONE_ORE = evolutionStoneOre("thunder_stone_ore", 6)
|
||||
val THUNDER_STONE_ORE = evolutionStoneOre("thunder_stone_ore")
|
||||
@JvmField
|
||||
val WATER_STONE_ORE = evolutionStoneOre("water_stone_ore")
|
||||
|
||||
@JvmField
|
||||
val DEEPSLATE_DAWN_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_dawn_stone_ore", 7)
|
||||
val DEEPSLATE_DAWN_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_dawn_stone_ore")
|
||||
@JvmField
|
||||
val DEEPSLATE_DUSK_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_dusk_stone_ore")
|
||||
@JvmField
|
||||
val DEEPSLATE_FIRE_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_fire_stone_ore", 10)
|
||||
val DEEPSLATE_FIRE_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_fire_stone_ore")
|
||||
@JvmField
|
||||
val DEEPSLATE_ICE_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_ice_stone_ore")
|
||||
@JvmField
|
||||
@@ -99,11 +99,11 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val DEEPSLATE_MOON_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_moon_stone_ore")
|
||||
@JvmField
|
||||
val DEEPSLATE_SHINY_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_shiny_stone_ore", 12)
|
||||
val DEEPSLATE_SHINY_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_shiny_stone_ore")
|
||||
@JvmField
|
||||
val DEEPSLATE_SUN_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_sun_stone_ore", 2)
|
||||
val DEEPSLATE_SUN_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_sun_stone_ore")
|
||||
@JvmField
|
||||
val DEEPSLATE_THUNDER_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_thunder_stone_ore", 6)
|
||||
val DEEPSLATE_THUNDER_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_thunder_stone_ore")
|
||||
@JvmField
|
||||
val DEEPSLATE_WATER_STONE_ORE = this.deepslateEvolutionStoneOre("deepslate_water_stone_ore")
|
||||
|
||||
@@ -454,7 +454,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
|
||||
@JvmField
|
||||
val SOUL_CAMPFIRE = create("soul_campfire", CampfireBlock(BlockBehaviour.Properties.of().sound(SoundType.WOOD).noOcclusion().pushReaction(PushReaction.BLOCK).mapColor(MapColor.PODZOL).strength(2.0F).lightLevel{9}, true))
|
||||
|
||||
|
||||
@JvmField
|
||||
val RELIC_COIN_POUCH = create("relic_coin_pouch", CoinPouchBlock(BlockBehaviour.Properties.of().sound(CobblemonSounds.RELIC_COIN_POUCH_SOUNDS).pushReaction(PushReaction.DESTROY).noOcclusion(), true))
|
||||
@JvmField
|
||||
@@ -577,145 +577,74 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
|
||||
private val berries = mutableMapOf<ResourceLocation, BerryBlock>()
|
||||
|
||||
@JvmField
|
||||
val AGUAV_BERRY = this.berryBlock("aguav")
|
||||
@JvmField
|
||||
val APICOT_BERRY = this.berryBlock("apicot")
|
||||
@JvmField
|
||||
val ASPEAR_BERRY = this.berryBlock("aspear")
|
||||
@JvmField
|
||||
val BABIRI_BERRY = this.berryBlock("babiri")
|
||||
@JvmField
|
||||
val BELUE_BERRY = this.berryBlock("belue")
|
||||
@JvmField
|
||||
val BLUK_BERRY = this.berryBlock("bluk")
|
||||
@JvmField
|
||||
val CHARTI_BERRY = this.berryBlock("charti")
|
||||
@JvmField
|
||||
val CHERI_BERRY = this.berryBlock("cheri")
|
||||
@JvmField
|
||||
val CHESTO_BERRY = this.berryBlock("chesto")
|
||||
@JvmField
|
||||
val CHILAN_BERRY = this.berryBlock("chilan")
|
||||
@JvmField
|
||||
val CHOPLE_BERRY = this.berryBlock("chople")
|
||||
@JvmField
|
||||
val COBA_BERRY = this.berryBlock("coba")
|
||||
@JvmField
|
||||
val COLBUR_BERRY = this.berryBlock("colbur")
|
||||
@JvmField
|
||||
val CORNN_BERRY = this.berryBlock("cornn")
|
||||
@JvmField
|
||||
val CUSTAP_BERRY = this.berryBlock("custap")
|
||||
@JvmField
|
||||
val DURIN_BERRY = this.berryBlock("durin")
|
||||
@JvmField
|
||||
val EGGANT_BERRY = this.berryBlock("eggant")
|
||||
@JvmField
|
||||
val ENIGMA_BERRY = this.berryBlock("enigma")
|
||||
@JvmField
|
||||
val FIGY_BERRY = this.berryBlock("figy")
|
||||
@JvmField
|
||||
val GANLON_BERRY = this.berryBlock("ganlon")
|
||||
@JvmField
|
||||
val GREPA_BERRY = this.berryBlock("grepa")
|
||||
@JvmField
|
||||
val HABAN_BERRY = this.berryBlock("haban")
|
||||
@JvmField
|
||||
val HONDEW_BERRY = this.berryBlock("hondew")
|
||||
@JvmField
|
||||
val HOPO_BERRY = this.berryBlock("hopo")
|
||||
@JvmField
|
||||
val IAPAPA_BERRY = this.berryBlock("iapapa")
|
||||
@JvmField
|
||||
val JABOCA_BERRY = this.berryBlock("jaboca")
|
||||
@JvmField
|
||||
val KASIB_BERRY = this.berryBlock("kasib")
|
||||
@JvmField
|
||||
val KEBIA_BERRY = this.berryBlock("kebia")
|
||||
@JvmField
|
||||
val KEE_BERRY = this.berryBlock("kee")
|
||||
@JvmField
|
||||
val KELPSY_BERRY = this.berryBlock("kelpsy")
|
||||
@JvmField
|
||||
val LANSAT_BERRY = this.berryBlock("lansat")
|
||||
@JvmField
|
||||
val LEPPA_BERRY = this.berryBlock("leppa")
|
||||
@JvmField
|
||||
val LIECHI_BERRY = this.berryBlock("liechi")
|
||||
@JvmField
|
||||
val LUM_BERRY = this.berryBlock("lum")
|
||||
@JvmField
|
||||
val MAGO_BERRY = this.berryBlock("mago")
|
||||
@JvmField
|
||||
val MAGOST_BERRY = this.berryBlock("magost")
|
||||
@JvmField
|
||||
val MARANGA_BERRY = this.berryBlock("maranga")
|
||||
@JvmField
|
||||
val MICLE_BERRY = this.berryBlock("micle")
|
||||
@JvmField
|
||||
val NANAB_BERRY = this.berryBlock("nanab")
|
||||
@JvmField
|
||||
val NOMEL_BERRY = this.berryBlock("nomel")
|
||||
@JvmField
|
||||
val OCCA_BERRY = this.berryBlock("occa")
|
||||
@JvmField
|
||||
val ORAN_BERRY = this.berryBlock("oran")
|
||||
@JvmField
|
||||
val PAMTRE_BERRY = this.berryBlock("pamtre")
|
||||
@JvmField
|
||||
val PASSHO_BERRY = this.berryBlock("passho")
|
||||
@JvmField
|
||||
val PAYAPA_BERRY = this.berryBlock("payapa")
|
||||
@JvmField
|
||||
val PECHA_BERRY = this.berryBlock("pecha")
|
||||
@JvmField
|
||||
val PERSIM_BERRY = this.berryBlock("persim")
|
||||
@JvmField
|
||||
val PETAYA_BERRY = this.berryBlock("petaya")
|
||||
@JvmField
|
||||
val PINAP_BERRY = this.berryBlock("pinap")
|
||||
@JvmField
|
||||
val POMEG_BERRY = this.berryBlock("pomeg")
|
||||
@JvmField
|
||||
val QUALOT_BERRY = this.berryBlock("qualot")
|
||||
@JvmField
|
||||
val RABUTA_BERRY = this.berryBlock("rabuta")
|
||||
@JvmField
|
||||
val RAWST_BERRY = this.berryBlock("rawst")
|
||||
@JvmField
|
||||
val RAZZ_BERRY = this.berryBlock("razz")
|
||||
@JvmField
|
||||
val RINDO_BERRY = this.berryBlock("rindo")
|
||||
@JvmField
|
||||
val ROSELI_BERRY = this.berryBlock("roseli")
|
||||
@JvmField
|
||||
val ROWAP_BERRY = this.berryBlock("rowap")
|
||||
@JvmField
|
||||
val SALAC_BERRY = this.berryBlock("salac")
|
||||
@JvmField
|
||||
val SHUCA_BERRY = this.berryBlock("shuca")
|
||||
@JvmField
|
||||
val SITRUS_BERRY = this.berryBlock("sitrus")
|
||||
@JvmField
|
||||
val SPELON_BERRY = this.berryBlock("spelon")
|
||||
@JvmField
|
||||
val STARF_BERRY = this.berryBlock("starf")
|
||||
@JvmField
|
||||
val TAMATO_BERRY = this.berryBlock("tamato")
|
||||
@JvmField
|
||||
val TANGA_BERRY = this.berryBlock("tanga")
|
||||
@JvmField
|
||||
val TOUGA_BERRY = this.berryBlock("touga")
|
||||
@JvmField
|
||||
val WACAN_BERRY = this.berryBlock("wacan")
|
||||
@JvmField
|
||||
val WATMEL_BERRY = this.berryBlock("watmel")
|
||||
@JvmField
|
||||
val WEPEAR_BERRY = this.berryBlock("wepear")
|
||||
@JvmField
|
||||
val WIKI_BERRY = this.berryBlock("wiki")
|
||||
@JvmField
|
||||
val YACHE_BERRY = this.berryBlock("yache")
|
||||
//val BINDING_SOIL = this.create("binding_soil", BindingSoilBlock(BlockBehaviour.Properties.of()))
|
||||
|
||||
@@ -783,10 +712,8 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
}
|
||||
|
||||
private fun evolutionStoneOre(name: String) = this.create(name, DropExperienceBlock(UniformInt.of(1, 2), BlockBehaviour.Properties.ofFullCopy(Blocks.IRON_ORE)))
|
||||
private fun evolutionStoneOre(name: String, lightLevel: Int) = this.create(name, DropExperienceBlock(UniformInt.of(1, 2), BlockBehaviour.Properties.ofFullCopy(Blocks.IRON_ORE).lightLevel { lightLevel }))
|
||||
|
||||
private fun deepslateEvolutionStoneOre(name: String) = this.create(name, DropExperienceBlock(UniformInt.of(1, 2), BlockBehaviour.Properties.ofFullCopy(Blocks.DEEPSLATE_IRON_ORE)))
|
||||
private fun deepslateEvolutionStoneOre(name: String, lightLevel: Int) = this.create(name, DropExperienceBlock(UniformInt.of(1, 2), BlockBehaviour.Properties.ofFullCopy(Blocks.DEEPSLATE_IRON_ORE).lightLevel { lightLevel }))
|
||||
|
||||
/**
|
||||
* Helper method for creating leaves
|
||||
|
||||
@@ -43,7 +43,6 @@ object CobblemonCosmeticItems : JsonDataRegistry<CosmeticItemAssignment> {
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.create()
|
||||
|
||||
@JvmField
|
||||
val cosmeticItems = mutableListOf<CosmeticItemAssignment>()
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, CosmeticItemAssignment>) {
|
||||
@@ -56,9 +55,7 @@ object CobblemonCosmeticItems : JsonDataRegistry<CosmeticItemAssignment> {
|
||||
CosmeticItemAssignmentSyncPacket(cosmeticItems).sendToPlayer(player)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun findValidForPokemon(pokemon: Pokemon) = cosmeticItems.filter { it.pokemon.any { it.matches(pokemon) } }
|
||||
@JvmStatic
|
||||
fun findValidCosmeticForPokemonAndItem(registryAccess: RegistryAccess, pokemon: Pokemon, itemStack: ItemStack) = cosmeticItems
|
||||
.filter { it.pokemon.any { it.matches(pokemon) } }
|
||||
.flatMap { it.cosmeticItems }
|
||||
|
||||
@@ -21,73 +21,56 @@ import net.minecraft.resources.ResourceLocation
|
||||
|
||||
object CobblemonItemComponents : PlatformRegistry<Registry<DataComponentType<*>>, ResourceKey<Registry<DataComponentType<*>>>, DataComponentType<*>>() {
|
||||
|
||||
@JvmField
|
||||
val POKEMON_ITEM: DataComponentType<PokemonItemComponent> = create("pokemon_item", DataComponentType.builder<PokemonItemComponent>()
|
||||
.persistent(PokemonItemComponent.CODEC)
|
||||
.networkSynchronized(PokemonItemComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
@JvmField
|
||||
val HELD_ITEM_EFFECT: DataComponentType<HeldItemEffectComponent> = create("held_item_effect", DataComponentType.builder<HeldItemEffectComponent>()
|
||||
.persistent(HeldItemEffectComponent.CODEC)
|
||||
.networkSynchronized(HeldItemEffectComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
@JvmField
|
||||
val BAIT: DataComponentType<RodBaitComponent> = create("bait", DataComponentType.builder<RodBaitComponent>()
|
||||
.persistent(RodBaitComponent.CODEC)
|
||||
.networkSynchronized(RodBaitComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
@JvmField
|
||||
val POT_DATA: DataComponentType<PotComponent> = create("cooking_pot_item", DataComponentType.builder<PotComponent>()
|
||||
.persistent(PotComponent.CODEC)
|
||||
.networkSynchronized(PotComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
@JvmField
|
||||
val BAIT_EFFECTS: DataComponentType<BaitEffectsComponent> = create("bait_effects", DataComponentType.builder<BaitEffectsComponent>()
|
||||
.persistent(BaitEffectsComponent.CODEC)
|
||||
.networkSynchronized(BaitEffectsComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
@JvmField
|
||||
val FLAVOUR: DataComponentType<FlavourComponent> = create("flavour", DataComponentType.builder<FlavourComponent>()
|
||||
.persistent(FlavourComponent.CODEC)
|
||||
.networkSynchronized(FlavourComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
@JvmField
|
||||
val RIDE_BOOST: DataComponentType<RideBoostsComponent> = create("ride_boosts", DataComponentType.builder<RideBoostsComponent>()
|
||||
.persistent(RideBoostsComponent.CODEC)
|
||||
.networkSynchronized(RideBoostsComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
@JvmField
|
||||
val FOOD_COLOUR: DataComponentType<FoodColourComponent> = create("food_colour", DataComponentType.builder<FoodColourComponent>()
|
||||
.persistent(FoodColourComponent.CODEC)
|
||||
.networkSynchronized(FoodColourComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
@JvmField
|
||||
val INGREDIENT: DataComponentType<IngredientComponent> = create("ingredient", DataComponentType.builder<IngredientComponent>()
|
||||
.persistent(IngredientComponent.CODEC)
|
||||
.networkSynchronized(IngredientComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
@JvmField
|
||||
val FOOD: DataComponentType<FoodComponent> = create("food", DataComponentType.builder<FoodComponent>()
|
||||
.persistent(FoodComponent.CODEC)
|
||||
.networkSynchronized(FoodComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
@JvmField
|
||||
val MOB_EFFECTS: DataComponentType<MobEffectsComponent> = create("mob_effects", DataComponentType.builder<MobEffectsComponent>()
|
||||
.persistent(MobEffectsComponent.CODEC)
|
||||
.networkSynchronized(MobEffectsComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
@JvmField
|
||||
val CRAFTED: DataComponentType<Boolean> = create("crafted", DataComponentType.builder<Boolean>()
|
||||
.persistent(Codec.BOOL)
|
||||
.networkSynchronized(ByteBufCodecs.BOOL)
|
||||
@@ -99,7 +82,6 @@ object CobblemonItemComponents : PlatformRegistry<Registry<DataComponentType<*>>
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:cooking_pot_item"), POT_DATA)
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:bait_effects"), BAIT_EFFECTS)
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:flavour"), FLAVOUR)
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:ride_boosts"), RIDE_BOOST)
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:food_colour"), FOOD_COLOUR)
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:ingredient"), INGREDIENT)
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:food"), FOOD)
|
||||
|
||||
@@ -36,7 +36,7 @@ import com.cobblemon.mod.common.item.berry.PPRestoringBerryItem
|
||||
import com.cobblemon.mod.common.item.berry.PortionHealingBerryItem
|
||||
import com.cobblemon.mod.common.item.berry.StatusCuringBerryItem
|
||||
import com.cobblemon.mod.common.item.berry.VolatileCuringBerryItem
|
||||
import com.cobblemon.mod.common.item.interactive.PonigiriItem
|
||||
import com.cobblemon.mod.common.item.food.PonigiriItem
|
||||
import com.cobblemon.mod.common.item.food.SinisterTeaItem
|
||||
import com.cobblemon.mod.common.item.interactive.*
|
||||
import com.cobblemon.mod.common.item.interactive.ability.AbilityChangeItem
|
||||
@@ -382,8 +382,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val SINISTER_TEA = create("sinister_tea", SinisterTeaItem())
|
||||
|
||||
// @JvmField
|
||||
// val POKE_PUFF = pokepuffItem("poke_puff")
|
||||
@JvmField
|
||||
val POKE_PUFF = pokepuffItem("poke_puff")
|
||||
|
||||
// FOODS
|
||||
@JvmField
|
||||
@@ -517,7 +517,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField val RAWST_BERRY = berryItem("rawst", StatusCuringBerryItem(CobblemonBlocks.RAWST_BERRY, Statuses.BURN))
|
||||
@JvmField val ASPEAR_BERRY = berryItem("aspear", StatusCuringBerryItem(CobblemonBlocks.ASPEAR_BERRY, Statuses.FROZEN))
|
||||
@JvmField val PERSIM_BERRY = berryItem("persim", VolatileCuringBerryItem(CobblemonBlocks.PERSIM_BERRY, "confusion"))
|
||||
@JvmField val EGGANT_BERRY = berryItem("eggant", VolatileCuringBerryItem(CobblemonBlocks.EGGANT_BERRY, "attract"))
|
||||
@JvmField val RAZZ_BERRY = berryItem("razz", CobblemonBlocks.RAZZ_BERRY)
|
||||
@JvmField val BLUK_BERRY = berryItem("bluk", CobblemonBlocks.BLUK_BERRY)
|
||||
@JvmField val NANAB_BERRY = berryItem("nanab", CobblemonBlocks.NANAB_BERRY)
|
||||
@@ -683,7 +682,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
}
|
||||
})
|
||||
@JvmField
|
||||
val ENERGY_ROOT = compostableItem("energy_root", EnergyRootItem(CobblemonBlocks.ENERGY_ROOT, Properties()), 0.65f)
|
||||
val ENERGY_ROOT = compostableItem("energy_root", EnergyRootItem(CobblemonBlocks.ENERGY_ROOT, Properties()), 0.60f)
|
||||
@JvmField
|
||||
val REVIVAL_HERB = compostableItem("revival_herb", RevivalHerbItem(CobblemonBlocks.REVIVAL_HERB))
|
||||
@JvmField
|
||||
@@ -693,9 +692,9 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val REMEDY = compostableItem("remedy", RemedyItem(RemedyItem.NORMAL), 0.65f)
|
||||
@JvmField
|
||||
val FINE_REMEDY = compostableItem("fine_remedy", RemedyItem(RemedyItem.FINE), 0.85f)
|
||||
val FINE_REMEDY = compostableItem("fine_remedy", RemedyItem(RemedyItem.FINE), 0.75f)
|
||||
@JvmField
|
||||
val SUPERB_REMEDY = compostableItem("superb_remedy", RemedyItem(RemedyItem.SUPERB), 1f)
|
||||
val SUPERB_REMEDY = compostableItem("superb_remedy", RemedyItem(RemedyItem.SUPERB), 0.85f)
|
||||
@JvmField
|
||||
val MOOMOO_MILK = create("moomoo_milk", MoomooMilk(Item.Properties().craftRemainder(Items.GLASS_BOTTLE).stacksTo((16))))
|
||||
|
||||
@@ -915,7 +914,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val ASSAULT_VEST = heldItem("assault_vest")
|
||||
@JvmField
|
||||
val BIG_ROOT = compostableBlockItem("big_root", CobblemonBlocks.BIG_ROOT, 0.30f)
|
||||
val BIG_ROOT = compostableBlockItem("big_root", CobblemonBlocks.BIG_ROOT, 0.40f)
|
||||
@JvmField
|
||||
val BINDING_BAND = heldItem("binding_band")
|
||||
@JvmField
|
||||
@@ -1063,15 +1062,15 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val ZOOM_LENS = heldItem("zoom_lens")
|
||||
@JvmField
|
||||
val MENTAL_HERB = compostableHeldItem("mental_herb", null, 0.85F)
|
||||
val MENTAL_HERB = compostableHeldItem("mental_herb", null, 1F)
|
||||
@JvmField
|
||||
val MIRROR_HERB = compostableHeldItem("mirror_herb", null, 0.85F)
|
||||
val MIRROR_HERB = compostableHeldItem("mirror_herb", null, 1F)
|
||||
@JvmField
|
||||
val MISTY_SEED = heldItem("misty_seed")
|
||||
@JvmField
|
||||
val POWER_HERB = compostableHeldItem("power_herb", null, 0.85F)
|
||||
val POWER_HERB = compostableHeldItem("power_herb", null, 1F)
|
||||
@JvmField
|
||||
val WHITE_HERB = compostableHeldItem("white_herb", null, 0.85F)
|
||||
val WHITE_HERB = compostableHeldItem("white_herb", null, 1F)
|
||||
@JvmField
|
||||
val BRIGHT_POWDER = heldItem("bright_powder")
|
||||
@JvmField
|
||||
|
||||
@@ -12,12 +12,9 @@ import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.api.data.DataRegistry
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.mechanics.AprijuicesMechanic
|
||||
import com.cobblemon.mod.common.mechanics.BerriesMechanic
|
||||
import com.cobblemon.mod.common.mechanics.PotionsMechanic
|
||||
import com.cobblemon.mod.common.mechanics.RemediesMechanic
|
||||
import com.cobblemon.mod.common.mechanics.SlowpokeTailsMechanic
|
||||
import com.cobblemon.mod.common.net.messages.client.data.CobblemonMechanicsSyncPacket
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
@@ -40,25 +37,13 @@ object CobblemonMechanics : DataRegistry {
|
||||
var remedies = RemediesMechanic()
|
||||
var berries = BerriesMechanic()
|
||||
var potions = PotionsMechanic()
|
||||
var aprijuices = AprijuicesMechanic()
|
||||
var slowpokeTails = SlowpokeTailsMechanic()
|
||||
|
||||
override fun sync(player: ServerPlayer) {
|
||||
CobblemonMechanicsSyncPacket(
|
||||
this.remedies,
|
||||
this.berries,
|
||||
this.potions,
|
||||
this.aprijuices,
|
||||
this.slowpokeTails
|
||||
).sendToPlayer(player)
|
||||
}
|
||||
override fun sync(player: ServerPlayer) {}
|
||||
|
||||
override fun reload(manager: ResourceManager) {
|
||||
remedies = loadMechanic(manager, "remedies", RemediesMechanic::class.java)
|
||||
berries = loadMechanic(manager, "berries", BerriesMechanic::class.java)
|
||||
potions = loadMechanic(manager, "potions", PotionsMechanic::class.java)
|
||||
aprijuices = loadMechanic(manager, "aprijuices", AprijuicesMechanic::class.java)
|
||||
slowpokeTails = loadMechanic(manager, "slowpoke_tails", SlowpokeTailsMechanic::class.java)
|
||||
}
|
||||
|
||||
private fun <T> loadMechanic(manager: ResourceManager, name: String, clazz: Class<T>): T {
|
||||
|
||||
@@ -30,80 +30,49 @@ object CobblemonMemories {
|
||||
* get serialized during relogs. This makes sense for things like battles which
|
||||
* do not survive a relog therefore any memory of it should be temporary.
|
||||
*/
|
||||
@JvmField
|
||||
|
||||
val BATTLING_POKEMON = register("battling_pokemon", ListCodec(UUIDUtil.CODEC, 0, 31))
|
||||
@JvmField
|
||||
val NPC_BATTLING = register("npc_battling", PrimitiveCodec.BOOL)
|
||||
@JvmField
|
||||
val DIALOGUES = register<List<ActiveDialogue>>("npc_dialogues")
|
||||
@JvmField
|
||||
val ACTIVE_ACTION_EFFECT = register<ActionEffectContext>("active_action_effect")
|
||||
@JvmField
|
||||
val POKEMON_FLYING = register("pokemon_flying", PrimitiveCodec.BOOL)
|
||||
@JvmField
|
||||
val POKEMON_DROWSY = register("pokemon_drowsy", PrimitiveCodec.BOOL)
|
||||
@JvmField
|
||||
val POKEMON_SLEEPING = register("pokemon_sleeping", PrimitiveCodec.BOOL)
|
||||
@JvmField
|
||||
val POKEMON_BATTLE = register<UUID>("pokemon_battle")
|
||||
@JvmField
|
||||
val PATH_COOLDOWN = register<Boolean>("path_cooldown")
|
||||
@JvmField
|
||||
val TARGETED_BATTLE_POKEMON = register<UUID>("targeted_battle_pokemon")
|
||||
@JvmField
|
||||
val NEAREST_VISIBLE_ATTACKER = register<LivingEntity>("nearest_visible_attacker")
|
||||
@JvmField
|
||||
val NEARBY_GROWABLE_CROPS = register<BlockPos>("nearby_growable_crops")
|
||||
@JvmField
|
||||
val NEARBY_SWEET_BERRY_BUSH = register<BlockPos>("nearest_sweet_berry_bush")
|
||||
@JvmField
|
||||
val DISABLE_WALK_TO_BERRY_BUSH = register<Boolean>("disable_walk_to_berry_bush")
|
||||
@JvmField
|
||||
val TIME_TRYING_TO_REACH_BERRY_BUSH = register<Int>("time_trying_to_reach_berry_bush")
|
||||
@JvmField
|
||||
val IS_CONSUMING_ITEM = register<Boolean>("is_consuming_item")
|
||||
@JvmField
|
||||
val RECENTLY_ATE_GRASS = register<Boolean>("recently_ate_grass")
|
||||
@JvmField
|
||||
val HIVE_LOCATION = register<BlockPos>("hive_location", BlockPos.CODEC)
|
||||
@JvmField
|
||||
val HIVE_BLACKLIST = register<List<BlockPos>>("hive_blacklist")
|
||||
@JvmField
|
||||
val HIVE_COOLDOWN = register<Boolean>("hive_cooldown")
|
||||
@JvmField
|
||||
val NEARBY_FLOWER = register<BlockPos>("nearby_flower", BlockPos.CODEC)
|
||||
@JvmField
|
||||
val PATH_TO_NEARBY_FLOWER_COOLDOWN = register<Boolean>("path_to_nearby_flower_cooldown")
|
||||
@JvmField
|
||||
val HAS_NECTAR = register<Boolean>("has_nectar", PrimitiveCodec.BOOL)
|
||||
@JvmField
|
||||
val NEARBY_SACC_LEAVES = register<BlockPos>("nearby_sacc_leaves", BlockPos.CODEC)
|
||||
/** who am i following rn? */
|
||||
@JvmField
|
||||
val HERD_LEADER = register<String>("herd_leader", PrimitiveCodec.STRING)
|
||||
/** how many are following me rn? */
|
||||
@JvmField
|
||||
val HERD_SIZE = register<Int>("herd_size") // Don't bother saving it, we'll try to keep count roughly.
|
||||
@JvmField
|
||||
val ATTACK_TARGET_DATA = register<CobblemonAttackTargetData>("attack_target_data") // This is used to store additional information about the attack target, such as when to give up pursuit.
|
||||
@JvmField
|
||||
val WANDER_CONTROL = register<CobblemonWanderControl>("wander_control")
|
||||
@JvmField
|
||||
val DISABLE_WALK_TO_WANTED_ITEM = register<Boolean>("disable_walk_to_wanted_item")
|
||||
@JvmField
|
||||
val TIME_TRYING_TO_REACH_WANTED_ITEM = register<Int>("time_trying_to_wanted_item")
|
||||
|
||||
@JvmStatic
|
||||
fun <U> register(id: String, codec: Codec<U>): MemoryModuleType<U> {
|
||||
val memoryModule = MemoryModuleType(Optional.of(codec))
|
||||
memories[id] = memoryModule
|
||||
return memoryModule
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun <U> register(id: String): MemoryModuleType<U> {
|
||||
val memoryModule = MemoryModuleType<U>(Optional.empty())
|
||||
memories[id] = memoryModule
|
||||
return memoryModule
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,10 +19,8 @@ import com.cobblemon.mod.common.client.net.callback.move.OpenMoveCallbackHandler
|
||||
import com.cobblemon.mod.common.client.net.callback.party.OpenPartyCallbackHandler
|
||||
import com.cobblemon.mod.common.client.net.callback.partymove.OpenPartyMoveCallbackHandler
|
||||
import com.cobblemon.mod.common.client.net.cooking.ToggleCookingPotLidHandler
|
||||
import com.cobblemon.mod.common.client.net.data.CobblemonMechanicsSyncHandler
|
||||
import com.cobblemon.mod.common.client.net.data.DataRegistrySyncPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.data.RideSettingsSyncHandler
|
||||
import com.cobblemon.mod.common.client.net.debug.OpenRidingStatsDebugGUIHandler
|
||||
import com.cobblemon.mod.common.client.net.dialogue.DialogueClosedHandler
|
||||
import com.cobblemon.mod.common.client.net.dialogue.DialogueOpenedHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.PokeSnackBlockParticlesHandler
|
||||
@@ -30,7 +28,6 @@ import com.cobblemon.mod.common.client.net.effect.RunPosableMoLangHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.SaccharineLogBlockParticlesHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormEntityParticleHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormParticleHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.ExpGainedDataPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.InteractPokemonUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.PokedexUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.SummaryUIPacketHandler
|
||||
@@ -80,7 +77,6 @@ import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyMoveCallba
|
||||
import com.cobblemon.mod.common.net.messages.client.cooking.SeasoningRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.cooking.ToggleCookingPotLidPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.data.*
|
||||
import com.cobblemon.mod.common.net.messages.client.debug.RequestOpenRidingStatsDebugGUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueClosedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueOpenedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.PokeSnackBlockParticlesPacket
|
||||
@@ -136,7 +132,6 @@ import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferNotification
|
||||
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.ui.ExpGainedDataPacket
|
||||
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
|
||||
@@ -162,7 +157,6 @@ import com.cobblemon.mod.common.net.messages.server.callback.party.PartyPokemonS
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.party.PartySelectCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.partymove.PartyMoveSelectCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.partymove.PartyPokemonMoveSelectedPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.debug.OpenRidingStatsDebugGUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.debug.ServerboundUpdateRidingSettingsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.debug.ServerboundUpdateRidingStatRangePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.debug.ServerboundUpdateRidingStatsPacket
|
||||
@@ -216,7 +210,6 @@ import com.cobblemon.mod.common.net.serverhandling.callback.party.PartyPokemonSe
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.party.PartySelectCancelledHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.partymove.PartyMoveSelectCancelledHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.partymove.PartyPokemonMoveSelectedHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.debug.RequestOpenRidingStatsDebugGUIHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.debug.ServerboundUpdateRidingSettingsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.debug.ServerboundUpdateRidingStatRangeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.debug.ServerboundUpdateRidingStatsHandler
|
||||
@@ -272,13 +265,10 @@ object CobblemonNetwork {
|
||||
fun ServerPlayer.sendPacket(packet: NetworkPacket<*>) {
|
||||
sendPacketToPlayer(this, packet)
|
||||
}
|
||||
@JvmStatic
|
||||
fun sendToServer(packet: NetworkPacket<*>) {
|
||||
Cobblemon.implementation.networkManager.sendToServer(packet)
|
||||
}
|
||||
@JvmStatic
|
||||
fun sendToAllPlayers(packet: NetworkPacket<*>) = sendPacketToPlayers(server()!!.playerList.players, packet)
|
||||
@JvmStatic
|
||||
fun sendPacketToPlayers(players: Iterable<ServerPlayer>, packet: NetworkPacket<*>) = players.forEach { sendPacketToPlayer(it, packet) }
|
||||
|
||||
val s2cPayloads = generateS2CPacketInfoList()
|
||||
@@ -357,7 +347,6 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(InteractPokemonUIPacket.ID, InteractPokemonUIPacket::decode, InteractPokemonUIPacketHandler))
|
||||
list.add(PacketRegisterInfo(PlayerInteractOptionsPacket.ID, PlayerInteractOptionsPacket::decode, PlayerInteractOptionsHandler))
|
||||
list.add(PacketRegisterInfo(PokedexUIPacket.ID, PokedexUIPacket::decode, PokedexUIPacketHandler))
|
||||
list.add(PacketRegisterInfo(ExpGainedDataPacket.ID, ExpGainedDataPacket::decode, ExpGainedDataPacketHandler))
|
||||
|
||||
// Starter packets
|
||||
list.add(PacketRegisterInfo(OpenStarterUIPacket.ID, OpenStarterUIPacket::decode, StarterUIPacketHandler))
|
||||
@@ -400,7 +389,6 @@ object CobblemonNetwork {
|
||||
|
||||
// Data registries
|
||||
list.add(PacketRegisterInfo(AbilityRegistrySyncPacket.ID, AbilityRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(CobblemonMechanicsSyncPacket.ID, CobblemonMechanicsSyncPacket::decode, CobblemonMechanicsSyncHandler))
|
||||
list.add(PacketRegisterInfo(MovesRegistrySyncPacket.ID, MovesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(BerryRegistrySyncPacket.ID, BerryRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(SpeciesRegistrySyncPacket.ID, SpeciesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
@@ -491,9 +479,6 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(ClientboundUpdateRidingStatePacket.ID, ClientboundUpdateRidingStatePacket::decode, ClientboundUpdateRidingStateHandler))
|
||||
list.add(PacketRegisterInfo(ClientboundUpdateDriverInputPacket.ID, ClientboundUpdateDriverInputPacket::decode, ClientboundUpdateDriverInputHandler))
|
||||
|
||||
// Debug
|
||||
list.add(PacketRegisterInfo(OpenRidingStatsDebugGUIPacket.ID, OpenRidingStatsDebugGUIPacket::decode, OpenRidingStatsDebugGUIHandler))
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
@@ -610,13 +595,10 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(SetEntityBehaviourPacket.ID, SetEntityBehaviourPacket::decode, SetEntityBehaviourHandler))
|
||||
list.add(PacketRegisterInfo(DamageOnCollisionPacket.ID, DamageOnCollisionPacket::decode, DamageOnCollisionPacketHandler))
|
||||
|
||||
// Debug
|
||||
list.add(PacketRegisterInfo(RequestOpenRidingStatsDebugGUIPacket.ID, RequestOpenRidingStatsDebugGUIPacket::decode, RequestOpenRidingStatsDebugGUIHandler))
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
fun sendPacketToPlayer(player: ServerPlayer, packet: NetworkPacket<*>) {
|
||||
Cobblemon.implementation.networkManager.sendPacketToPlayer(player, packet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,45 +20,32 @@ import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
object CobblemonSensors {
|
||||
val sensors = mutableMapOf<String, SensorType<*>>()
|
||||
|
||||
@JvmField
|
||||
val NPC_BATTLING = register("npc_battling", ::NPCBattlingSensor)
|
||||
@JvmField
|
||||
val BATTLING_POKEMON = register("battling_pokemon", ::BattlingPokemonSensor)
|
||||
// val NPC_BATTLING = register("npc_battling", ::NPCBattlingSensor)
|
||||
@JvmField
|
||||
val POKEMON_DROWSY = register("pokemon_drowsy", ::DrowsySensor)
|
||||
|
||||
@JvmField
|
||||
val POKEMON_ADULT = register("pokemon_adult_sensor", ::PokemonAdultSensor)
|
||||
|
||||
@JvmField
|
||||
val POKEMON_DISTURBANCE = register("pokemon_disturbance_sensor", ::PokemonDisturbancesSensor)
|
||||
|
||||
@JvmField
|
||||
val POKEMON_DEFEND_OWNER = register("pokemon_owner_under_attack", ::DefendOwnerSensor)
|
||||
|
||||
@JvmField
|
||||
val NEARBY_GROWABLE_CROPS = register("nearby_growable_crops", ::PokemonGrowableCropSensor)
|
||||
|
||||
@JvmField
|
||||
val NEARBY_BEE_HIVE = register("nearby_bee_hive", ::BeeHiveSensor)
|
||||
|
||||
@JvmField
|
||||
val NEARBY_FLOWER = register("nearby_flower", ::FlowerSensor)
|
||||
|
||||
@JvmField
|
||||
val NEARBY_SWEET_BERRY_BUSH = register("nearby_sweet_berry_bush", ::SweetBerryBushSensor)
|
||||
|
||||
@JvmField
|
||||
val POKEMON_NEARBY_WANTED_ITEM = register("pokemon_nearby_wanted_item", ::PokemonItemSensor)
|
||||
|
||||
@JvmField
|
||||
val NEARBY_SACC_LEAVES = register("nearby_sacc_leaves", ::SacLeavesSensor)
|
||||
|
||||
@JvmStatic
|
||||
fun <E : Entity, U : Sensor<E>> register(id: String, supplier: Supplier<U>): SensorType<U> {
|
||||
val sensor = SensorType(supplier)
|
||||
sensors[id] = sensor
|
||||
return sensor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,11 +103,6 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
@JvmField
|
||||
val EVOLUTION = this.create("evolution.full")
|
||||
|
||||
@JvmField
|
||||
val LEVELUP_START = this.create("gui.levelup_start")
|
||||
@JvmField
|
||||
val LEVELUP = this.create("gui.levelup")
|
||||
|
||||
@JvmField
|
||||
val PVN_BATTLE = this.create("battle.pvn.default")
|
||||
@JvmField
|
||||
|
||||
@@ -23,63 +23,43 @@ import net.minecraft.resources.ResourceKey
|
||||
* @since October 26th, 2022
|
||||
*/
|
||||
object CobblemonCriteria : PlatformRegistry<Registry<CriterionTrigger<*>>, ResourceKey<Registry<CriterionTrigger<*>>>, CriterionTrigger<*>>(){
|
||||
@JvmField
|
||||
val PICK_STARTER = this.create("pick_starter", SimpleCriterionTrigger(PokemonCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val CATCH_POKEMON = this.create("catch_pokemon", SimpleCriterionTrigger(CaughtPokemonCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val CATCH_SHINY_POKEMON = this.create("catch_shiny_pokemon", SimpleCriterionTrigger(CountableCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val EGG_COLLECT = this.create("eggs_collected", SimpleCriterionTrigger(CountableCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val EGG_HATCH = this.create("eggs_hatched", SimpleCriterionTrigger(CountableCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val EVOLVE_POKEMON = this.create("pokemon_evolved", SimpleCriterionTrigger(EvolvePokemonCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val WIN_BATTLE = this.create("battles_won", SimpleCriterionTrigger(BattleCountableCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val DEFEAT_POKEMON = this.create("pokemon_defeated", SimpleCriterionTrigger(CountableCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val COLLECT_ASPECT = this.create("aspects_collected", SimpleCriterionTrigger(AspectCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val POKEMON_INTERACT = this.create("pokemon_interact", SimpleCriterionTrigger(PokemonInteractCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val PARTY_CHECK = this.create("party", SimpleCriterionTrigger(PartyCheckCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val LEVEL_UP = this.create("level_up", SimpleCriterionTrigger(LevelUpCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val PASTURE_USE = this.create("pasture_use", SimpleCriterionTrigger(PokemonCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val RESURRECT_POKEMON = this.create("resurrect_pokemon", SimpleCriterionTrigger(PokemonCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val TRADE_POKEMON = this.create("trade_pokemon", SimpleCriterionTrigger(TradePokemonCriterion.CODEC))
|
||||
|
||||
@JvmField
|
||||
val CAST_POKE_ROD = this.create("cast_poke_rod", SimpleCriterionTrigger(CastPokeRodCriterionCondition.CODEC))
|
||||
|
||||
@JvmField
|
||||
val REEL_IN_POKEMON = this.create("reel_in_pokemon", SimpleCriterionTrigger(ReelInPokemonCriterionCondition.CODEC))
|
||||
|
||||
// Advancement criteria for [grow_tumblestone.json]
|
||||
@JvmField
|
||||
val PLANT_TUMBLESTONE = this.create("plant_tumblestone", SimpleCriterionTrigger(PlantTumblestoneCriterion.CODEC))
|
||||
|
||||
val RIDING_STAT_BOOST = this.create("riding_stat_boost", SimpleCriterionTrigger(RidingStatBoostCriterion.CODEC))
|
||||
|
||||
override val registry = BuiltInRegistries.TRIGGER_TYPES
|
||||
override val resourceKey = Registries.TRIGGER_TYPE
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -32,6 +32,6 @@ class CastPokeRodCriterionCondition(
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: CastPokeRodContext): Boolean {
|
||||
return (context.baitId == this.baitId.asIdentifierDefaultingNamespace() || this.baitId == "empty_bait")
|
||||
return (context.baitId == this.baitId.asIdentifierDefaultingNamespace() || this.baitId.equals("empty_bait"))
|
||||
}
|
||||
}
|
||||
|
||||
+4
-6
@@ -21,25 +21,23 @@ import java.util.Optional
|
||||
* @author Hiroku
|
||||
* @since November 4th, 2022
|
||||
*/
|
||||
open class CountablePokemonTypeContext(times: Int, var type: String/*, var species: String*/) : CountableContext(times)
|
||||
open class CountablePokemonTypeContext(times: Int, var species: String) : CountableContext(times)
|
||||
|
||||
class CaughtPokemonCriterion(
|
||||
playerCtx: Optional<ContextAwarePredicate>,
|
||||
val type : String,
|
||||
//val species: String,
|
||||
val species: String,
|
||||
count: Int
|
||||
): CountableCriterion<CountablePokemonTypeContext>(playerCtx, count) {
|
||||
|
||||
companion object {
|
||||
val CODEC: Codec<CaughtPokemonCriterion> = RecordCodecBuilder.create { it.group(
|
||||
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(CaughtPokemonCriterion::playerCtx),
|
||||
Codec.STRING.optionalFieldOf("type", "any").forGetter(CaughtPokemonCriterion::type),
|
||||
//Codec.STRING.optionalFieldOf("species", "any").forGetter(CaughtPokemonCriterion::species),
|
||||
Codec.STRING.optionalFieldOf("species", "any").forGetter(CaughtPokemonCriterion::species),
|
||||
Codec.INT.optionalFieldOf("count", 0).forGetter(CaughtPokemonCriterion::count)
|
||||
).apply(it, ::CaughtPokemonCriterion) }
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: CountablePokemonTypeContext): Boolean {
|
||||
return super.matches(player, context) && (context.type == type || type == "any")// && (context.species == species || species == "any")
|
||||
return super.matches(player, context) && (context.species == species || species == "any")
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ class LevelUpCriterion(
|
||||
val CODEC: Codec<LevelUpCriterion> = RecordCodecBuilder.create { it.group(
|
||||
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(LevelUpCriterion::playerCtx),
|
||||
Codec.INT.optionalFieldOf("level", 0).forGetter(LevelUpCriterion::level),
|
||||
Codec.BOOL.optionalFieldOf("has_evolved", true).forGetter(LevelUpCriterion::evolved)
|
||||
Codec.BOOL.optionalFieldOf("evolved", true).forGetter(LevelUpCriterion::evolved)
|
||||
).apply(it, ::LevelUpCriterion) }
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -35,6 +35,6 @@ class ReelInPokemonCriterionCondition(
|
||||
|
||||
override fun matches(player: ServerPlayer, context: ReelInPokemonContext): Boolean {
|
||||
return (context.species == this.species.asIdentifierDefaultingNamespace() || this.species == "any")
|
||||
&& (context.baitId == this.baitId.asIdentifierDefaultingNamespace() || this.baitId == "any" || this.baitId == "empty_bait")
|
||||
&& (context.baitId == this.baitId.asIdentifierDefaultingNamespace() || this.baitId == "any")
|
||||
}
|
||||
}
|
||||
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.advancement.criterion
|
||||
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.advancements.critereon.ContextAwarePredicate
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import java.util.Optional
|
||||
|
||||
class RidingStatBoostContext(val pokemon: PokemonEntity)
|
||||
|
||||
class RidingStatBoostCriterion(
|
||||
playerCtx: Optional<ContextAwarePredicate>,
|
||||
val rideStat: String,
|
||||
val statValue : Double,
|
||||
val isMax : Boolean
|
||||
) : SimpleCriterionCondition<RidingStatBoostContext>(playerCtx) {
|
||||
|
||||
companion object {
|
||||
val CODEC: Codec<RidingStatBoostCriterion> = RecordCodecBuilder.create { it.group(
|
||||
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter { it.playerCtx },
|
||||
Codec.STRING.optionalFieldOf("ride_stat", "any").forGetter { it.rideStat },
|
||||
Codec.DOUBLE.optionalFieldOf("stat_value", 0.0).forGetter { it.statValue },
|
||||
Codec.BOOL.optionalFieldOf("is_max", false).forGetter { it.isMax }
|
||||
).apply(it, ::RidingStatBoostCriterion) }
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: RidingStatBoostContext) : Boolean {
|
||||
RidingStyle.entries.forEach { ridingStyle ->
|
||||
RidingStat.entries.forEach { rideStat ->
|
||||
if (rideStat.name.equals(this.rideStat, true) || this.rideStat == "any") {
|
||||
val max = context.pokemon.pokemon.getMaxRideBoost(rideStat).toDouble()
|
||||
val min = context.pokemon.pokemon.getBaseRideStat(rideStat).toDouble()
|
||||
val value = context.pokemon.getRideStat(rideStat, ridingStyle, min, max)
|
||||
if ((value >= this.statValue && this.statValue > 0.0) || value == max || !context.pokemon.pokemon.canAddRideBoost(rideStat)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -70,23 +70,16 @@ object Abilities : DataRegistry {
|
||||
AbilityRegistrySyncPacket(all()).sendToPlayer(player)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun register(ability: AbilityTemplate): AbilityTemplate {
|
||||
this.abilityMap[ability.name.lowercase()] = ability
|
||||
return ability
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun all() = this.abilityMap.values.toList()
|
||||
@JvmStatic
|
||||
fun first() = this.abilityMap.values.first()
|
||||
@JvmStatic
|
||||
fun get(name: String) = abilityMap[name.lowercase()]
|
||||
@JvmStatic
|
||||
fun getOrDummy(name: String) = get(name) ?: DUMMY
|
||||
@JvmStatic
|
||||
fun getOrException(name: String) = get(name) ?: throw IllegalArgumentException("Unable to find ability of name: $name")
|
||||
@JvmStatic
|
||||
fun count() = this.abilityMap.size
|
||||
|
||||
internal fun receiveSyncPacket(abilities: Collection<AbilityTemplate>) {
|
||||
|
||||
@@ -47,23 +47,12 @@ class ApplyBehaviours : BehaviourConfig {
|
||||
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
|
||||
if (!checkCondition(behaviourConfigurationContext, condition)) return
|
||||
|
||||
val applicableBehaviours = behaviours.mapNotNull {
|
||||
val resolvedBehaviour = CobblemonBehaviours.behaviours[it]
|
||||
if (resolvedBehaviour == null) {
|
||||
Cobblemon.LOGGER.warn("Behaviour $it not found while configuring entity of type ${entity.type}")
|
||||
} else if (!resolvedBehaviour.canBeApplied(entity)) {
|
||||
Cobblemon.LOGGER.warn("Behaviour $it cannot be applied to entity ${entity.id}")
|
||||
} else {
|
||||
return@mapNotNull resolvedBehaviour
|
||||
}
|
||||
null
|
||||
}
|
||||
|
||||
val configurations = behaviours.map { CobblemonBehaviours.behaviours[it]?.takeIf { it.canBeApplied(entity) } ?: return Cobblemon.LOGGER.warn("Behaviour $it not found") }
|
||||
// Why not just add the presets to the context directly?
|
||||
// Nested preset application is a thing, and I only want to track the top level presets.
|
||||
// i.e. if a preset applies another preset, I don't want to track the inner preset, since it's redundant if we track the top one.
|
||||
val originalContextBehaviours = behaviourConfigurationContext.appliedBehaviours.toMutableSet()
|
||||
applicableBehaviours.forEach {
|
||||
configurations.forEach {
|
||||
it.configure(entity, behaviourConfigurationContext)
|
||||
}
|
||||
originalContextBehaviours.addAll(behaviours)
|
||||
|
||||
+3
-17
@@ -11,7 +11,8 @@ package com.cobblemon.mod.common.api.ai.config.task
|
||||
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.ai.config.task.SharedEntityVariables.SEE_DISTANCE
|
||||
import com.cobblemon.mod.common.util.resolveEntityTypes
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.SetEntityLookTarget
|
||||
@@ -21,16 +22,13 @@ import net.minecraft.world.entity.ai.sensing.SensorType
|
||||
class LookAtEntitiesTaskConfig : SingleTaskConfig {
|
||||
companion object {
|
||||
const val LOOK_AT_ENTITIES = "look_at_entities"
|
||||
const val LOOK_AT_ENTITY_TYPES = "look_at_entity_types"
|
||||
}
|
||||
|
||||
val condition = booleanVariable(SharedEntityVariables.LOOKING_CATEGORY, LOOK_AT_ENTITIES, true).asExpressible()
|
||||
val maxDistance = numberVariable(SharedEntityVariables.LOOKING_CATEGORY, SEE_DISTANCE, 15).asExpressible()
|
||||
val entityTypes = stringVariable(SharedEntityVariables.LOOKING_CATEGORY, LOOK_AT_ENTITY_TYPES, "").asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
|
||||
condition,
|
||||
entityTypes,
|
||||
maxDistance
|
||||
).asVariables()
|
||||
|
||||
@@ -41,18 +39,6 @@ class LookAtEntitiesTaskConfig : SingleTaskConfig {
|
||||
if (!condition.resolveBoolean(behaviourConfigurationContext.runtime)) return null
|
||||
behaviourConfigurationContext.addMemories(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.LOOK_TARGET)
|
||||
behaviourConfigurationContext.addSensors(SensorType.NEAREST_LIVING_ENTITIES)
|
||||
|
||||
val lookDistance = maxDistance.resolveFloat(behaviourConfigurationContext.runtime)
|
||||
val lookAtTypesText = entityTypes.resolveString(behaviourConfigurationContext.runtime)
|
||||
if (lookAtTypesText.isBlank()) {
|
||||
return SetEntityLookTarget.create(lookDistance)
|
||||
}
|
||||
|
||||
val lookAtTypes = resolveEntityTypes(entity.registryAccess(), lookAtTypesText)
|
||||
return if (lookAtTypes.isNotEmpty()) {
|
||||
SetEntityLookTarget.create({ lookAtTypes.contains(it.type) }, lookDistance)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
return SetEntityLookTarget.create(maxDistance.resolveFloat(behaviourConfigurationContext.runtime))
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -19,7 +19,7 @@ import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
|
||||
class MeleeAttackTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(SharedEntityVariables.ATTACKING_CATEGORY, "attacks_melee", true).asExpressible()
|
||||
val range = numberVariable(SharedEntityVariables.ATTACKING_CATEGORY, "melee_range", 0.75F).asExpressible()
|
||||
val range = numberVariable(SharedEntityVariables.ATTACKING_CATEGORY, "melee_range", 1.5F).asExpressible()
|
||||
val cooldownTicks = numberVariable(SharedEntityVariables.ATTACKING_CATEGORY, "melee_cooldown", 20).asExpressible()
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
|
||||
|
||||
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.api.apricorn
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBlocks
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.cooking.Flavour
|
||||
import com.cobblemon.mod.common.block.ApricornBlock
|
||||
import com.cobblemon.mod.common.block.ApricornSaplingBlock
|
||||
import com.cobblemon.mod.common.item.ApricornItem
|
||||
@@ -27,14 +28,43 @@ import net.minecraft.world.level.material.MapColor
|
||||
* @author Licious
|
||||
* @since October 29th, 2022
|
||||
*/
|
||||
enum class Apricorn : StringRepresentable {
|
||||
enum class Apricorn(
|
||||
/** A value of true means it buffs that flavour, a value of false means it weakens that flavour. */
|
||||
val flavourStrength: Map<Flavour, Boolean> = emptyMap()
|
||||
) : StringRepresentable {
|
||||
|
||||
BLACK,
|
||||
BLUE,
|
||||
GREEN,
|
||||
PINK,
|
||||
RED,
|
||||
BLUE(
|
||||
mapOf(
|
||||
Flavour.DRY to true,
|
||||
Flavour.BITTER to false
|
||||
)
|
||||
),
|
||||
GREEN(
|
||||
mapOf(
|
||||
Flavour.BITTER to true,
|
||||
Flavour.SWEET to false
|
||||
)
|
||||
),
|
||||
PINK(
|
||||
mapOf(
|
||||
Flavour.SWEET to true,
|
||||
Flavour.SPICY to false
|
||||
)
|
||||
),
|
||||
RED(
|
||||
mapOf(
|
||||
Flavour.SPICY to true,
|
||||
Flavour.SOUR to false
|
||||
)
|
||||
),
|
||||
WHITE,
|
||||
YELLOW;
|
||||
YELLOW(
|
||||
mapOf(
|
||||
Flavour.SOUR to true,
|
||||
Flavour.DRY to false
|
||||
)
|
||||
);
|
||||
|
||||
fun item(): ApricornItem = when(this) {
|
||||
BLACK -> CobblemonItems.BLACK_APRICORN
|
||||
@@ -101,4 +131,5 @@ enum class Apricorn : StringRepresentable {
|
||||
companion object {
|
||||
val CODEC: Codec<Apricorn> = StringRepresentable.fromValues(::values)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -85,7 +85,6 @@ object Berries : JsonDataRegistry<Berry> {
|
||||
BerryRegistrySyncPacket(this.all()).sendToPlayer(player)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun all() = this.berries.values.toList()
|
||||
|
||||
/**
|
||||
@@ -94,7 +93,6 @@ object Berries : JsonDataRegistry<Berry> {
|
||||
* @param identifier The identifier of the berry.
|
||||
* @return The [Berry] if loaded otherwise null.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getByIdentifier(identifier: ResourceLocation): Berry? = this.berries[identifier]
|
||||
|
||||
/**
|
||||
@@ -103,7 +101,6 @@ object Berries : JsonDataRegistry<Berry> {
|
||||
* @param name The path of the identifier of the berry under the [Cobblemon.MODID] namespace.
|
||||
* @return The [Berry] if loaded otherwise null.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getByName(name: String): Berry? = this.getByIdentifier(cobblemonResource(name))
|
||||
|
||||
}
|
||||
+25
-105
@@ -8,14 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.cooking
|
||||
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.util.math.geometry.toDegrees
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import net.minecraft.util.FastColor
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import kotlin.math.atan2
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
private val colourMap = mapOf(
|
||||
Flavour.SPICY to 0xFEB37D,
|
||||
@@ -55,111 +49,37 @@ fun getColourMixFromFlavours(dominantFlavours: List<Flavour>, forBubbles: Boolea
|
||||
|
||||
if (colors.isEmpty()) return null
|
||||
|
||||
return getColourMixFromColors(colors)
|
||||
val (alphaSum, redSum, greenSum, blueSum) = colors.fold(IntArray(4)) { acc, color ->
|
||||
acc[0] += FastColor.ARGB32.alpha(color)
|
||||
acc[1] += FastColor.ARGB32.red(color)
|
||||
acc[2] += FastColor.ARGB32.green(color)
|
||||
acc[3] += FastColor.ARGB32.blue(color)
|
||||
acc
|
||||
}
|
||||
|
||||
return FastColor.ARGB32.color(
|
||||
alphaSum / colors.size,
|
||||
redSum / colors.size,
|
||||
greenSum / colors.size,
|
||||
blueSum / colors.size
|
||||
)
|
||||
}
|
||||
|
||||
fun getColourMixFromRideStatBoosts(dominantBoosts: Iterable<RidingStat>, forBubbles: Boolean = false): Int? {
|
||||
return getColourMixFromFlavours(dominantBoosts.map { it.flavour }, forBubbles)
|
||||
}
|
||||
|
||||
// Mixing RGB colors directly often gives poor results
|
||||
// Converting them to HSL and averaging hues circularly produces more natural blends
|
||||
fun getColourMixFromColors(colors: List<Int>): Int? {
|
||||
if (colors.isEmpty()) return null
|
||||
if (colors.size == 1) return colors[0]
|
||||
|
||||
val hslColors = colors.map {
|
||||
val red = FastColor.ARGB32.red(it)
|
||||
val green = FastColor.ARGB32.green(it)
|
||||
val blue = FastColor.ARGB32.blue(it)
|
||||
|
||||
rgbToHsl(red, green, blue)
|
||||
val (alphaSum, redSum, greenSum, blueSum) = colors.fold(IntArray(4)) { acc, color ->
|
||||
acc[0] += FastColor.ARGB32.alpha(color)
|
||||
acc[1] += FastColor.ARGB32.red(color)
|
||||
acc[2] += FastColor.ARGB32.green(color)
|
||||
acc[3] += FastColor.ARGB32.blue(color)
|
||||
acc
|
||||
}
|
||||
|
||||
val hues = hslColors.map { it.h.toDouble() }
|
||||
val huesAverage = hueAverage(hues).toFloat()
|
||||
val saturations = hslColors.map { it.s }
|
||||
val saturationsAverage = average(saturations)
|
||||
val lightness = hslColors.map { it.l }
|
||||
val lightnessAverage = average(lightness)
|
||||
|
||||
val rgbColor = hslToRgb(huesAverage, saturationsAverage, lightnessAverage)
|
||||
|
||||
return FastColor.ARGB32.color(rgbColor.r, rgbColor.g, rgbColor.b)
|
||||
}
|
||||
|
||||
// Based on https://iter.ca/post/hue-avg
|
||||
fun hueAverage(hues: List<Double>): Float {
|
||||
val points = hues.map { hue ->
|
||||
val rad = hue.toRadians()
|
||||
Pair(cos(rad), sin(rad))
|
||||
}
|
||||
|
||||
val avgX = points.sumOf { it.first.toDouble() } / points.size
|
||||
val avgY = points.sumOf { it.second.toDouble() } / points.size
|
||||
|
||||
var degrees = atan2(avgY, avgX).toDegrees()
|
||||
if (degrees < 0) {
|
||||
degrees += 360f
|
||||
} else if (degrees > 360) {
|
||||
degrees -= 360f
|
||||
}
|
||||
|
||||
return degrees
|
||||
}
|
||||
|
||||
fun average(values: List<Float>): Float {
|
||||
if (values.isEmpty()) return 0f
|
||||
return values.sum() / values.size
|
||||
}
|
||||
|
||||
data class HSL(val h: Float, val s: Float, val l: Float)
|
||||
|
||||
fun rgbToHsl(r: Int, g: Int, b: Int): HSL {
|
||||
val rf = r / 255f
|
||||
val gf = g / 255f
|
||||
val bf = b / 255f
|
||||
|
||||
val max = maxOf(rf, gf, bf)
|
||||
val min = minOf(rf, gf, bf)
|
||||
val delta = max - min
|
||||
|
||||
var h = 0f
|
||||
val l = (max + min) / 2f
|
||||
val s = if (delta == 0f) 0f else delta / (1f - kotlin.math.abs(2f * l - 1f))
|
||||
|
||||
if (delta != 0f) {
|
||||
h = when (max) {
|
||||
rf -> ((gf - bf) / delta) % 6f
|
||||
gf -> ((bf - rf) / delta) + 2f
|
||||
else -> ((rf - gf) / delta) + 4f
|
||||
}
|
||||
h *= 60f
|
||||
if (h < 0) h += 360f
|
||||
}
|
||||
|
||||
return HSL(h, s, l)
|
||||
}
|
||||
|
||||
data class RGB(val r: Int, val g: Int, val b: Int)
|
||||
|
||||
fun hslToRgb(h: Float, s: Float, l: Float): RGB {
|
||||
val c = (1f - kotlin.math.abs(2f * l - 1f)) * s
|
||||
val x = c * (1f - kotlin.math.abs((h / 60f) % 2f - 1f))
|
||||
val m = l - c / 2f
|
||||
|
||||
val (rf, gf, bf) = when {
|
||||
h < 60f -> Triple(c, x, 0f)
|
||||
h < 120f -> Triple(x, c, 0f)
|
||||
h < 180f -> Triple(0f, c, x)
|
||||
h < 240f -> Triple(0f, x, c)
|
||||
h < 300f -> Triple(x, 0f, c)
|
||||
else -> Triple(c, 0f, x)
|
||||
}
|
||||
|
||||
return RGB(
|
||||
((rf + m) * 255).toInt().coerceIn(0, 255),
|
||||
((gf + m) * 255).toInt().coerceIn(0, 255),
|
||||
((bf + m) * 255).toInt().coerceIn(0, 255)
|
||||
return FastColor.ARGB32.color(
|
||||
alphaSum / colors.size,
|
||||
redSum / colors.size,
|
||||
greenSum / colors.size,
|
||||
blueSum / colors.size
|
||||
)
|
||||
}
|
||||
@@ -28,14 +28,12 @@ import net.minecraft.server.level.ServerPlayer
|
||||
object DialogueManager {
|
||||
val activeDialogues = mutableMapOf<UUID, ActiveDialogue>()
|
||||
|
||||
@JvmStatic
|
||||
fun startDialogue(playerEntity: ServerPlayer, dialogue: Dialogue): ActiveDialogue {
|
||||
val activeDialogue = ActiveDialogue(playerEntity, dialogue)
|
||||
startDialogue(activeDialogue)
|
||||
return activeDialogue
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun startDialogue(playerEntity: ServerPlayer, npcEntity: NPCEntity, dialogue: Dialogue): ActiveDialogue {
|
||||
val activeDialogue = ActiveDialogue(playerEntity, dialogue)
|
||||
activeDialogue.runtime.withNPCValue("npc", npcEntity)
|
||||
@@ -44,7 +42,6 @@ object DialogueManager {
|
||||
return activeDialogue
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun startDialogue(activeDialogue: ActiveDialogue) {
|
||||
activeDialogue.initialize()
|
||||
if (!activeDialogue.completion.isDone) {
|
||||
@@ -52,7 +49,6 @@ object DialogueManager {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun stopDialogue(playerEntity: ServerPlayer) {
|
||||
val activeDialogue = playerEntity.activeDialogue ?: return
|
||||
DialogueClosedPacket(activeDialogue.dialogueId).sendToPlayer(playerEntity)
|
||||
|
||||
@@ -10,12 +10,14 @@ package com.cobblemon.mod.common.api.drop
|
||||
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.LOOT_DROPPED
|
||||
import com.cobblemon.mod.common.api.events.drops.LootDroppedEvent
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import kotlin.random.Random
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
/**
|
||||
@@ -93,16 +95,6 @@ class DropTable {
|
||||
pokemon: Pokemon? = null,
|
||||
) {
|
||||
val drops = getDrops(amount, pokemon).toMutableList()
|
||||
postLootDroppedEvent(drops, entity, world, pos, player)
|
||||
}
|
||||
|
||||
fun postLootDroppedEvent(
|
||||
drops: MutableList<DropEntry>,
|
||||
entity: LivingEntity?,
|
||||
world: ServerLevel,
|
||||
pos: Vec3,
|
||||
player: ServerPlayer?,
|
||||
) {
|
||||
LOOT_DROPPED.postThen(
|
||||
event = LootDroppedEvent(this, player, entity, drops),
|
||||
ifSucceeded = { it.drops.forEach { it.drop(entity, world, pos, player) } }
|
||||
@@ -118,4 +110,4 @@ class DropTable {
|
||||
val entries = buffer.readInt()
|
||||
repeat(entries) { this.entries.add(ItemDropEntry().decode(buffer)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ import com.cobblemon.mod.common.api.events.berry.BerryHarvestEvent
|
||||
import com.cobblemon.mod.common.api.events.berry.BerryMutationOfferEvent
|
||||
import com.cobblemon.mod.common.api.events.berry.BerryMutationResultEvent
|
||||
import com.cobblemon.mod.common.api.events.berry.BerryYieldCalculationEvent
|
||||
import com.cobblemon.mod.common.api.events.cooking.PokeSnackSpawnPokemonEvent
|
||||
import com.cobblemon.mod.common.api.events.drops.LootDroppedEvent
|
||||
import com.cobblemon.mod.common.api.events.entity.*
|
||||
import com.cobblemon.mod.common.api.events.farming.ApricornHarvestEvent
|
||||
@@ -328,12 +327,6 @@ object CobblemonEvents {
|
||||
@JvmField
|
||||
val BOBBER_SPAWN_POKEMON_POST = EventObservable<BobberSpawnPokemonEvent.Post>()
|
||||
|
||||
@JvmField
|
||||
val POKE_SNACK_SPAWN_POKEMON_PRE = CancelableObservable<PokeSnackSpawnPokemonEvent.Pre>()
|
||||
|
||||
@JvmField
|
||||
val POKE_SNACK_SPAWN_POKEMON_POST = EventObservable<PokeSnackSpawnPokemonEvent.Post>()
|
||||
|
||||
@JvmField
|
||||
val BAIT_EFFECT_REGISTRATION = EventObservable<BaitEffectFunctionRegistryEvent>()
|
||||
|
||||
|
||||
-38
@@ -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.events.cooking
|
||||
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
|
||||
import com.cobblemon.mod.common.api.spawning.detail.SpawnAction
|
||||
import com.cobblemon.mod.common.block.entity.PokeSnackBlockEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
|
||||
interface PokeSnackSpawnPokemonEvent {
|
||||
|
||||
data class Pre(
|
||||
val pokeSnackBlockEntity: PokeSnackBlockEntity,
|
||||
val spawnAction: SpawnAction<*>,
|
||||
) : Cancelable(), PokeSnackSpawnPokemonEvent {
|
||||
val context = mapOf<String, MoValue>()
|
||||
val functions = moLangFunctionMap(
|
||||
cancelFunc
|
||||
)
|
||||
}
|
||||
|
||||
data class Post(
|
||||
val pokeSnackBlockEntity: PokeSnackBlockEntity,
|
||||
val spawnAction: SpawnAction<*>,
|
||||
val pokemonEntity: PokemonEntity,
|
||||
) : PokeSnackSpawnPokemonEvent {
|
||||
val context = mapOf<String, MoValue>()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -57,7 +57,6 @@ object PokeRods : JsonDataRegistry<PokeRod> {
|
||||
* Gets a Pokerod from registry name.
|
||||
* @return the pokerod object if found otherwise null.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getPokeRod(name : ResourceLocation): PokeRod? = rods[name]
|
||||
|
||||
}
|
||||
@@ -68,7 +68,6 @@ class SpawnBait(
|
||||
val TYPING = cobblemonResource("typing")
|
||||
val EGG_GROUP = cobblemonResource("egg_group")
|
||||
val SHINY_REROLL = cobblemonResource("shiny_reroll")
|
||||
val DROPS_REROLL = cobblemonResource("drops_reroll")
|
||||
val HIDDEN_ABILITY_CHANCE = cobblemonResource("ha_chance")
|
||||
val POKEMON_CHANCE = cobblemonResource("pokemon_chance")
|
||||
val FRIENDSHIP = cobblemonResource("friendship")
|
||||
@@ -86,7 +85,6 @@ class SpawnBait(
|
||||
registerEffect(NATURE) { entity, effect -> FishingSpawnCause.alterNatureAttempt(entity, effect) }
|
||||
registerEffect(IV) { entity, effect -> FishingSpawnCause.alterIVAttempt(entity, effect) }
|
||||
registerEffect(SHINY_REROLL) { entity, effect -> FishingSpawnCause.shinyReroll(entity, effect) }
|
||||
registerEffect(DROPS_REROLL) { entity, effect -> FishingSpawnCause.saveDropsReroll(entity, effect) }
|
||||
registerEffect(GENDER_CHANCE) { entity, effect -> FishingSpawnCause.alterGenderAttempt(entity, effect) }
|
||||
registerEffect(LEVEL_RAISE) { entity, effect -> FishingSpawnCause.alterLevelAttempt(entity, effect) }
|
||||
registerEffect(HIDDEN_ABILITY_CHANCE) { entity, _ -> FishingSpawnCause.alterHAAttempt(entity) }
|
||||
|
||||
@@ -53,24 +53,20 @@ object SpawnBaitEffects : JsonDataRegistry<SpawnBait> {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getEffectsFromRodItemStack(stack: ItemStack): List<SpawnBait.Effect> {
|
||||
return getEffectsFromItemStack(stack.components.get(CobblemonItemComponents.BAIT)?.stack ?: ItemStack.EMPTY)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getEffectsFromItemStack(stack: ItemStack): List<SpawnBait.Effect> {
|
||||
val componentEffects = stack.get(CobblemonItemComponents.BAIT_EFFECTS)?.effects ?: emptyList()
|
||||
return componentEffects.mapNotNull(::getFromIdentifier).flatMap { it.effects } +
|
||||
getEffectsFromItem(stack.itemHolder)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getBaitIdentifiersFromItem(holder: Holder<Item>): List<ResourceLocation> {
|
||||
return effectsMap.entries.filter { it.value.item.fits(holder) }.map { it.key }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getBaitFromItemStack(holder: Holder<Item>): List<SpawnBait> {
|
||||
return effectsMap.values.filter { it.item.fits(holder) }
|
||||
}
|
||||
@@ -79,7 +75,6 @@ object SpawnBaitEffects : JsonDataRegistry<SpawnBait> {
|
||||
return getBaitFromItemStack(holder).flatMap { it.effects }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getFromIdentifier(identifier: ResourceLocation): SpawnBait? {
|
||||
// Check normal spawn bait registry
|
||||
effectsMap[identifier]?.let { return it }
|
||||
@@ -103,7 +98,6 @@ object SpawnBaitEffects : JsonDataRegistry<SpawnBait> {
|
||||
}
|
||||
|
||||
// if it has bait effects and is not listed as a seasoning then it is a bait
|
||||
@JvmStatic
|
||||
fun isFishingBait(stack: ItemStack): Boolean {
|
||||
val holder = stack.itemHolder
|
||||
return effectsMap.values.any { it.item.fits(holder) }
|
||||
|
||||
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.api.fishing
|
||||
import kotlin.math.ceil
|
||||
|
||||
object SpawnBaitUtils {
|
||||
@JvmStatic
|
||||
fun mergeEffects(effects: List<SpawnBait.Effect>): List<SpawnBait.Effect> {
|
||||
val grouped = effects.groupBy { Pair(it.type, it.subcategory) }
|
||||
|
||||
|
||||
@@ -69,7 +69,6 @@ object Fossils: JsonDataRegistry<Fossil> {
|
||||
/**
|
||||
* Gets all loaded [Fossil]s.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun all() = this.fossils.values.toList()
|
||||
|
||||
/**
|
||||
@@ -77,7 +76,6 @@ object Fossils: JsonDataRegistry<Fossil> {
|
||||
* @param identifier The identifier of the fossil.
|
||||
* @return The [Fossil] if loaded, otherwise null.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getByIdentifier(identifier: ResourceLocation): Fossil? = this.fossils[identifier]
|
||||
|
||||
/**
|
||||
@@ -85,7 +83,6 @@ object Fossils: JsonDataRegistry<Fossil> {
|
||||
* @param fossilStacks The fossil [ItemStack]'s.
|
||||
* @return The [Fossil] if found, otherwise null.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getFossilByItemStacks(fossilStacks: List<ItemStack>): Fossil? {
|
||||
return this.all().firstOrNull { it.matchesIngredients(fossilStacks) }
|
||||
}
|
||||
@@ -95,7 +92,6 @@ object Fossils: JsonDataRegistry<Fossil> {
|
||||
* @param fossilStacks The fossil [ItemStack]'s.
|
||||
* @return The [Fossil] if found to be a superset, otherwise null.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getSubFossilByItemStacks(fossilStacks: List<ItemStack>): Fossil? {
|
||||
return this.all().firstOrNull { it.matchesIngredientsSubSet(fossilStacks) }
|
||||
}
|
||||
@@ -104,7 +100,6 @@ object Fossils: JsonDataRegistry<Fossil> {
|
||||
* @param itemStack The ingredient [ItemStack].
|
||||
* @return true if it's a fossil ingredient, otherwise false.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun isFossilIngredient(itemStack: ItemStack): Boolean {
|
||||
return this.all().any { it.isIngredient(itemStack) }
|
||||
}
|
||||
|
||||
@@ -57,7 +57,6 @@ object NaturalMaterials : JsonDataRegistry<List<NaturalMaterial>>{
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun isNaturalMaterial(item: ItemStack): Boolean {
|
||||
val itemId = BuiltInRegistries.ITEM.getKey(item.item)
|
||||
return itemId in itemMap.keys || tagMap.keys.any {
|
||||
@@ -65,7 +64,6 @@ object NaturalMaterials : JsonDataRegistry<List<NaturalMaterial>>{
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getContent(item: ItemStack): Int? {
|
||||
val itemId = BuiltInRegistries.ITEM.getKey(item.item)
|
||||
if (itemId in itemMap.keys) {
|
||||
@@ -78,7 +76,6 @@ object NaturalMaterials : JsonDataRegistry<List<NaturalMaterial>>{
|
||||
return null
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getReturnItem(item: ItemStack): ResourceLocation? {
|
||||
val itemId = BuiltInRegistries.ITEM.getKey(item.item)
|
||||
if (itemId in itemMap.keys) {
|
||||
@@ -90,4 +87,4 @@ object NaturalMaterials : JsonDataRegistry<List<NaturalMaterial>>{
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,9 +56,7 @@ object Marks: JsonDataRegistry<Mark> {
|
||||
/**
|
||||
* Gets all loaded [Mark]s.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun all() = this.marks.values.toList()
|
||||
@JvmStatic
|
||||
fun identifiers(): Collection<String> = marks.keys.toSet().map { it.toString() }
|
||||
|
||||
/**
|
||||
@@ -66,6 +64,5 @@ object Marks: JsonDataRegistry<Mark> {
|
||||
* @param identifier The identifier of the mark.
|
||||
* @return The [Mark] if loaded, otherwise null.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getByIdentifier(identifier: ResourceLocation): Mark? = this.marks[identifier]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import com.bedrockk.molang.runtime.MoLangEnvironment
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.struct.ArrayStruct
|
||||
import com.bedrockk.molang.runtime.struct.ContextStruct
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.struct.VariableStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
@@ -180,18 +179,6 @@ object MoLangFunctions {
|
||||
struct.map.clear()
|
||||
DoubleValue.ONE
|
||||
},
|
||||
"get_variable" to java.util.function.Function { params ->
|
||||
val struct = params.get<VariableStruct>(0)
|
||||
val variable = params.getString(1)
|
||||
return@Function struct.map[variable] ?: DoubleValue.ZERO
|
||||
},
|
||||
"set_variable" to java.util.function.Function { params ->
|
||||
val struct = params.get<VariableStruct>(0)
|
||||
val variable = params.getString(1)
|
||||
val value = params.get<MoValue>(2)
|
||||
struct.map[variable] = value
|
||||
return@Function value
|
||||
},
|
||||
"set_query" to java.util.function.Function { params ->
|
||||
val variable = params.getString(0)
|
||||
val value = params.get<MoValue>(1)
|
||||
@@ -309,12 +296,8 @@ object MoLangFunctions {
|
||||
val runtime = MoLangRuntime()
|
||||
runtime.environment.query = params.environment.query
|
||||
runtime.environment.variable = params.environment.variable
|
||||
val args = params.params.subList(1, params.params.size)
|
||||
runtime.environment.context = ContextStruct(
|
||||
params.environment.context.map + args.mapIndexed { index, value -> "arg_${index + 1}" to value }.toMap()
|
||||
)
|
||||
runtime.environment.context = params.environment.context
|
||||
val script = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
// store the args in the
|
||||
CobblemonScripts.run(script, runtime) ?: DoubleValue.ZERO
|
||||
},
|
||||
"run_molang" to java.util.function.Function { params ->
|
||||
@@ -366,8 +349,7 @@ object MoLangFunctions {
|
||||
val pickupPriority = params.getIntOrNull(1) ?: 0
|
||||
val pickupItem = ObtainableItem(item = item, pickupPriority = pickupPriority)
|
||||
return@Function pickupItem.struct
|
||||
},
|
||||
"file" to java.util.function.Function { MoLangLoadedFilesCache.struct }
|
||||
}
|
||||
)
|
||||
val biomeFunctions = mutableListOf<(Holder<Biome>) -> HashMap<String, java.util.function.Function<MoParams, Any>>>()
|
||||
val worldFunctions = mutableListOf<(Holder<Level>) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
|
||||
@@ -608,10 +590,10 @@ object MoLangFunctions {
|
||||
}
|
||||
if (player is ServerPlayer) {
|
||||
map.put("seen_credits") { _ ->
|
||||
DoubleValue(player.seenCredits)
|
||||
DoubleValue( DoubleValue(player.seenCredits) )
|
||||
}
|
||||
map.put("is_in_dialogue") { _ ->
|
||||
DoubleValue(player.isInDialogue)
|
||||
DoubleValue( DoubleValue(player.isInDialogue) )
|
||||
}
|
||||
map.put("active_dialogue") { _ ->
|
||||
if (player.isInDialogue) {
|
||||
@@ -1904,43 +1886,12 @@ object MoLangFunctions {
|
||||
map.put("in_battle") { DoubleValue(pokemonEntity.isBattling) }
|
||||
map.put("is_moving") { DoubleValue((pokemonEntity.moveControl as? PokemonMoveControl)?.hasWanted() == true) }
|
||||
map.put("is_flying") { DoubleValue(pokemonEntity.getBehaviourFlag(PokemonBehaviourFlag.FLYING)) }
|
||||
map.put("get_riding_state") { params ->
|
||||
val name = params.getStringOrNull(0)
|
||||
pokemonEntity.ifRidingAvailableSupply(DoubleValue.ZERO) { behaviour, settings, state ->
|
||||
val moValue = behaviour.asMoLangValue(settings, state, pokemonEntity)
|
||||
return@ifRidingAvailableSupply moValue.functions[name]?.apply(MoParams.EMPTY) as? MoValue ?: moValue
|
||||
}
|
||||
}
|
||||
map.put("is_gliding") {
|
||||
pokemonEntity.ifRidingAvailableSupply(DoubleValue.ZERO) { behaviour, settings, state ->
|
||||
val moValue = behaviour.asMoLangValue(settings, state, pokemonEntity)
|
||||
return@ifRidingAvailableSupply moValue.functions.get("gliding")?.apply(MoParams.EMPTY) as? MoValue ?: DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
map.put("is_sprinting") {
|
||||
pokemonEntity.ifRidingAvailableSupply(DoubleValue.ZERO) { behaviour, settings, state ->
|
||||
val moValue = behaviour.asMoLangValue(settings, state, pokemonEntity)
|
||||
return@ifRidingAvailableSupply moValue.functions.get("sprinting")?.apply(MoParams.EMPTY) as? MoValue ?: DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
map.put("is_drifting") {
|
||||
pokemonEntity.ifRidingAvailableSupply(DoubleValue.ZERO) { behaviour, settings, state ->
|
||||
val moValue = behaviour.asMoLangValue(settings, state, pokemonEntity)
|
||||
return@ifRidingAvailableSupply moValue.functions.get("drifting")?.apply(MoParams.EMPTY) as? MoValue ?: DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
map.put("is_powered_drifting") {
|
||||
pokemonEntity.ifRidingAvailableSupply(DoubleValue.ZERO) { behaviour, settings, state ->
|
||||
val moValue = behaviour.asMoLangValue(settings, state, pokemonEntity)
|
||||
return@ifRidingAvailableSupply moValue.functions.get("powered_drifting")?.apply(MoParams.EMPTY) as? MoValue ?: DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
map.put("in_air") {
|
||||
pokemonEntity.ifRidingAvailableSupply(DoubleValue.ZERO) { behaviour, settings, state ->
|
||||
val moValue = behaviour.asMoLangValue(settings, state, pokemonEntity)
|
||||
return@ifRidingAvailableSupply moValue.functions.get("in_air")?.apply(MoParams.EMPTY) as? MoValue ?: DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
map.put("get_alt_pose") { StringValue(pokemonEntity.getAltPose()) }
|
||||
map.put("is_gliding") { DoubleValue(pokemonEntity.isUsingAltPose(cobblemonResource("gliding"))) }
|
||||
map.put("is_sprinting") { DoubleValue(pokemonEntity.isUsingAltPose(cobblemonResource("sprinting"))) }
|
||||
map.put("is_drifting") { DoubleValue(pokemonEntity.isUsingAltPose(cobblemonResource("drifting"))) }
|
||||
map.put("is_powered_drifting") { DoubleValue(pokemonEntity.isUsingAltPose(cobblemonResource("powered_drifting"))) }
|
||||
map.put("in_air") { DoubleValue(pokemonEntity.isUsingAltPose(cobblemonResource("in_air"))) }
|
||||
map.put("is_wild") { DoubleValue(pokemonEntity.ownerUUID == null) }
|
||||
map.put("is_in_party") { DoubleValue(pokemonEntity.pokemon.storeCoordinates.get()?.store is PartyStore) }
|
||||
map.put("is_ridden") { DoubleValue(pokemonEntity.hasControllingPassenger()) }
|
||||
@@ -2518,17 +2469,6 @@ object MoLangFunctions {
|
||||
return value
|
||||
}
|
||||
|
||||
fun Vec3.asMoLangValue(): ObjectValue<Vec3> {
|
||||
val value = ObjectValue(
|
||||
obj = this
|
||||
)
|
||||
value.addFunction("x") { this.x }
|
||||
value.addFunction("y") { this.y }
|
||||
value.addFunction("z") { this.z }
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
/**
|
||||
* Different functions exist depending on the entity type, this tries to make the struct that's most specific to the type.
|
||||
*/
|
||||
@@ -2715,4 +2655,5 @@ object MoLangFunctions {
|
||||
}
|
||||
}
|
||||
|
||||
fun Either<ResourceLocation, ExpressionLike>.runScript(runtime: MoLangRuntime) = map({ CobblemonScripts.run(it, runtime) }, { it.resolve(runtime) })
|
||||
fun Either<ResourceLocation, ExpressionLike>.runScript(runtime: MoLangRuntime) = map({ CobblemonScripts.run(it, runtime) }, { it.resolve(runtime) })
|
||||
|
||||
|
||||
@@ -1,114 +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.molang
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.struct.VariableStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.JsonElement
|
||||
import java.nio.file.Path
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.world.level.storage.LevelResource
|
||||
|
||||
/**
|
||||
* A cache for loaded MoLang files to avoid redundant file I/O operations.
|
||||
* Provides functions to load, save, check existence, and clear cached files.
|
||||
*
|
||||
* Only files with /molang/ in their path and a .json extension within the config
|
||||
* or data folders can be accessed.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since November 1st, 2025
|
||||
*/
|
||||
object MoLangLoadedFilesCache {
|
||||
private val gson = GsonBuilder().setPrettyPrinting().create()
|
||||
val loadedFiles = ConcurrentHashMap<String, VariableStruct>()
|
||||
|
||||
/** Essentially the server root or world root for singleplayer. */
|
||||
lateinit var baseFolder: Path
|
||||
private lateinit var configFolder: Path
|
||||
private lateinit var dataFolder: Path
|
||||
|
||||
fun initialize(server: MinecraftServer) {
|
||||
baseFolder = server.getWorldPath(LevelResource.ROOT)
|
||||
configFolder = baseFolder.resolve("config").normalize().toAbsolutePath()
|
||||
dataFolder = baseFolder.resolve("data").normalize().toAbsolutePath()
|
||||
}
|
||||
|
||||
val struct = QueryStruct(hashMapOf())
|
||||
.addFunction("load") { params ->
|
||||
val fileName = params.params[0].asString()
|
||||
return@addFunction load(fileName)
|
||||
}
|
||||
.addFunction("save") { params ->
|
||||
val fileName = params.params[0].asString()
|
||||
val data = params.params[1] as VariableStruct
|
||||
save(fileName, data)
|
||||
return@addFunction DoubleValue.ONE
|
||||
}
|
||||
.addFunction("exists") { params ->
|
||||
val fileName = params.params[0].asString()
|
||||
val exists = exists(fileName)
|
||||
return@addFunction if (exists) DoubleValue.ONE else DoubleValue.ZERO
|
||||
}
|
||||
.addFunction("clear") { params ->
|
||||
val fileName = params.params[0].asString()
|
||||
clear(fileName)
|
||||
return@addFunction DoubleValue.ONE
|
||||
}
|
||||
|
||||
private fun validatePath(fileName: String): Path? {
|
||||
val filePath = baseFolder.resolve(fileName).normalize().toAbsolutePath()
|
||||
if (!filePath.startsWith(configFolder) && !filePath.startsWith(dataFolder)) {
|
||||
Cobblemon.LOGGER.error("MoLang attempted to access file outside of config or data folder: $fileName")
|
||||
return null
|
||||
} else if ("/molang/" !in fileName) {
|
||||
Cobblemon.LOGGER.error("MoLang attempted to access file outside of a 'molang' subfolder: $fileName")
|
||||
return null
|
||||
} else if (!fileName.endsWith(".json")) {
|
||||
Cobblemon.LOGGER.error("MoLang attempted to access file without a .json extension: $fileName")
|
||||
return null
|
||||
}
|
||||
return filePath
|
||||
}
|
||||
|
||||
fun exists(fileName: String): Boolean {
|
||||
val filePath = validatePath(fileName) ?: return false
|
||||
return filePath.toFile().exists()
|
||||
}
|
||||
|
||||
fun clear(fileName: String) {
|
||||
loadedFiles.remove(fileName)
|
||||
}
|
||||
|
||||
fun load(fileName: String): VariableStruct {
|
||||
return loadedFiles.getOrPut(fileName) {
|
||||
val filePath = validatePath(fileName) ?: return VariableStruct()
|
||||
val file = filePath.toFile()
|
||||
if (!file.exists()) {
|
||||
return VariableStruct()
|
||||
}
|
||||
val jsonElement = gson.fromJson(file.readText(), JsonElement::class.java)
|
||||
MoValue.of(jsonElement) as VariableStruct
|
||||
}
|
||||
}
|
||||
|
||||
fun save(fileName: String, data: VariableStruct) {
|
||||
loadedFiles[fileName] = data
|
||||
val filePath = validatePath(fileName) ?: return
|
||||
val file = filePath.toFile()
|
||||
file.parentFile?.mkdirs()
|
||||
val jsonElement = MoValue.writeToJson(data)
|
||||
file.writeText(gson.toJson(jsonElement))
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,8 @@
|
||||
package com.cobblemon.mod.common.api.molang
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
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.scripting.CobblemonScripts
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
@@ -23,11 +23,11 @@ import net.minecraft.resources.ResourceLocation
|
||||
*/
|
||||
class ReferenceExpression(val identifier: ResourceLocation) : ExpressionLike {
|
||||
override fun resolve(runtime: MoLangRuntime, context: Map<String, MoValue>): MoValue {
|
||||
return getScript()?.resolve(runtime, context) ?: StringValue(identifier.toString())
|
||||
return getScript()?.resolve(runtime, context) ?: DoubleValue.ZERO
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return getScript()?.getString() ?: identifier.toString()
|
||||
return getScript()?.getString() ?: "0"
|
||||
}
|
||||
|
||||
fun getScript() = CobblemonScripts.scripts[identifier]
|
||||
|
||||
@@ -33,7 +33,6 @@ object HiddenPowerUtil {
|
||||
ElementalTypes.DARK
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
fun getHiddenPowerType(pokemon: Pokemon?): ElementalType {
|
||||
if (pokemon == null) {
|
||||
return ElementalTypes.NORMAL
|
||||
|
||||
@@ -106,19 +106,12 @@ object Moves : DataRegistry {
|
||||
MovesRegistrySyncPacket(all()).sendToPlayer(player)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getByName(name: String) = allMoves[name.lowercase()]
|
||||
@JvmStatic
|
||||
fun getByNumericalId(id: Int) = idMapping[id]
|
||||
@JvmStatic
|
||||
fun getByNameOrDummy(name: String) = allMoves[name.lowercase()] ?: MoveTemplate.dummy(name.lowercase())
|
||||
@JvmStatic
|
||||
fun getExceptional() = getByName("tackle") ?: allMoves.values.random()
|
||||
@JvmStatic
|
||||
fun count() = allMoves.size
|
||||
@JvmStatic
|
||||
fun names(): Collection<String> = this.allMoves.keys.toSet()
|
||||
@JvmStatic
|
||||
fun all() = this.allMoves.values.toList()
|
||||
|
||||
internal fun receiveSyncPacket(moves: Collection<MoveTemplate>) {
|
||||
|
||||
@@ -97,7 +97,6 @@ object NPCClasses : JsonDataRegistry<NPCClass> {
|
||||
override val observable = SimpleObservable<NPCClasses>()
|
||||
private val npcClassesByIdentifier = hashMapOf<ResourceLocation, NPCClass>()
|
||||
|
||||
@JvmStatic
|
||||
val classes: Collection<NPCClass>
|
||||
get() = this.npcClassesByIdentifier.values
|
||||
|
||||
@@ -117,7 +116,6 @@ object NPCClasses : JsonDataRegistry<NPCClass> {
|
||||
* @param identifier The unique [NPCClass.id] of the [NPCClass].
|
||||
* @return The [NPCClass] if existing.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getByIdentifier(identifier: ResourceLocation) = this.npcClassesByIdentifier[identifier]
|
||||
|
||||
/**
|
||||
@@ -125,7 +123,6 @@ object NPCClasses : JsonDataRegistry<NPCClass> {
|
||||
*
|
||||
* @return The loaded NPC class amount.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun count() = this.npcClassesByIdentifier.size
|
||||
|
||||
/**
|
||||
@@ -135,7 +132,6 @@ object NPCClasses : JsonDataRegistry<NPCClass> {
|
||||
*
|
||||
* @return A randomly selected [Species].
|
||||
*/
|
||||
@JvmStatic
|
||||
fun random(): NPCClass = this.npcClassesByIdentifier.values.random()
|
||||
|
||||
fun dummy(): NPCClass {
|
||||
|
||||
@@ -102,7 +102,6 @@ object NPCPresets : JsonDataRegistry<NPCPreset> {
|
||||
observable.emit(this)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getPreset(identifier: ResourceLocation): NPCPreset? {
|
||||
return npcPresetsByIdentifier[identifier]
|
||||
}
|
||||
|
||||
+95
-17
@@ -10,14 +10,17 @@ package com.cobblemon.mod.common.api.orientation
|
||||
|
||||
import com.cobblemon.mod.common.util.math.geometry.toDegrees
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import net.minecraft.client.Minecraft
|
||||
import com.mojang.blaze3d.Blaze3D
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import org.joml.AxisAngle4f
|
||||
import org.joml.Matrix3f
|
||||
import org.joml.Quaternionf
|
||||
import org.joml.Vector3f
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.asin
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.sign
|
||||
|
||||
open class OrientationController(val entity: LivingEntity) {
|
||||
@@ -36,6 +39,11 @@ open class OrientationController(val entity: LivingEntity) {
|
||||
private var renderOrientationO: Matrix3f? = null
|
||||
private var renderOrientation: Matrix3f? = null
|
||||
|
||||
|
||||
private var angularVelocity: Vector3f = Vector3f(0.0f, 0.0f, 0.0f)
|
||||
private var lastHandledRotationTime = Double.MIN_VALUE
|
||||
private var frameTime = 0.0
|
||||
|
||||
/** Adding this simply because it irritates me seeing `getActive` when most of this is Java. */
|
||||
fun isActive() = active
|
||||
|
||||
@@ -64,11 +72,6 @@ open class OrientationController(val entity: LivingEntity) {
|
||||
}
|
||||
|
||||
fun getRenderOrientation(delta: Float): Quaternionf {
|
||||
// Return direct orientation if this is the player that drives this entities orientation.
|
||||
//TODO: Why does this break the render orientation.
|
||||
// if(entity.level().isClientSide && entity.controllingPassenger == Minecraft.getInstance().player) {
|
||||
// return Quaternionf().setFromUnnormalized(orientation)
|
||||
// }
|
||||
val old = renderOrientationO ?: renderOrientation ?: orientation ?: Matrix3f()
|
||||
val new = renderOrientation ?: old
|
||||
val oldQuat = Quaternionf().setFromUnnormalized(old)
|
||||
@@ -78,18 +81,93 @@ open class OrientationController(val entity: LivingEntity) {
|
||||
}
|
||||
|
||||
fun tick() {
|
||||
if (!active || orientation == null) return
|
||||
renderOrientationO = renderOrientation
|
||||
val current = orientation
|
||||
val renderMatrix = this.renderOrientation ?: current
|
||||
val renderQuat = Quaternionf().setFromUnnormalized(renderMatrix)
|
||||
val targetQuat = Quaternionf().setFromUnnormalized(current)
|
||||
val dampingFactor = 0.66f // Smooth interpolation to reduce jitter of orientations recieved from the server.
|
||||
renderQuat.slerp(targetQuat, dampingFactor)
|
||||
// val d = Blaze3D.getTime();
|
||||
// this.frameTime =
|
||||
// if (this.lastHandledRotationTime != Double.MIN_VALUE) d - this.lastHandledRotationTime else 0.0;
|
||||
// this.lastHandledRotationTime = d;
|
||||
//
|
||||
// if (!active || orientation == null) return
|
||||
//
|
||||
// // Find the desired angular velocity
|
||||
// // lerp the current ang vel towards the desired at a set rate (does this need to take into account frametime?
|
||||
// val current = orientation
|
||||
// val renderMatrix = this.renderOrientation ?: Matrix3f()
|
||||
// val renderQuat = Quaternionf().setFromUnnormalized(renderMatrix)
|
||||
// val targetQuat = Quaternionf().setFromUnnormalized(current)
|
||||
//
|
||||
// // Max rate of angular change in radians per second
|
||||
// val maxAngVel = Math.toRadians(180.0).toFloat()
|
||||
//
|
||||
// // Find the difference between the current render orientation and the target orientation
|
||||
// val qDiff: Quaternionf = targetQuat.mul(renderQuat.invert())
|
||||
//
|
||||
// // Construct the target rate of change from the difference quat
|
||||
// val axAng = qDiff.get(AxisAngle4f())
|
||||
// val capdRate = axAng.angle.coerceIn(-maxAngVel, maxAngVel)
|
||||
// val targetAngVel = Vector3f(
|
||||
// axAng.x,
|
||||
// axAng.y,
|
||||
// axAng.z
|
||||
// ).mul(capdRate)
|
||||
//
|
||||
// // lerp the current angular velocity towards the target
|
||||
// val k = 10.0f // Some smoothing constant k
|
||||
// val smoothingFactor = Math.min(1.0f, this.frameTime.toFloat() * k)
|
||||
// angularVelocity = angularVelocity.lerp(targetAngVel, smoothingFactor)
|
||||
//
|
||||
// // Use the angular velocity to slerp the renderQuat toward the targetQuat
|
||||
// val frameDisplacement =
|
||||
// angularVelocity.mul(this.frameTime.toFloat()) // Angular displacement happening on this frame
|
||||
//
|
||||
// val fAng = frameDisplacement.length() // Angle of displacement for this given pass/frame
|
||||
// if (fAng > 0.0001f) { // Ensure that the angle is significant enough that its worth normalizing and carrying out rotation
|
||||
// val fAx = frameDisplacement.normalize()
|
||||
// // Construct a rotation quat from the
|
||||
// val rotQuat = Quaternionf().fromAxisAngleRad(fAx, fAng)
|
||||
//
|
||||
// // Set the new orientation post frame stepped rotation.
|
||||
// renderOrientation = Matrix3f().set(renderQuat.mul(rotQuat))
|
||||
// }
|
||||
//
|
||||
//// this.renderOrientation = orientation
|
||||
//
|
||||
// // apply the new current angular velocity to the current render orientation
|
||||
// // construct a quat out of the angular velocity
|
||||
// // slerp the quat with a value of frametime
|
||||
|
||||
val newRenderOrientation = Matrix3f()
|
||||
renderQuat.get(newRenderOrientation)
|
||||
renderOrientation = newRenderOrientation
|
||||
val d = Blaze3D.getTime();
|
||||
this.frameTime = if (this.lastHandledRotationTime != Double.MIN_VALUE) d - this.lastHandledRotationTime else 0.0;
|
||||
this.lastHandledRotationTime = d;
|
||||
|
||||
if (!active || orientation == null) return
|
||||
|
||||
val current = orientation
|
||||
val renderMatrix = this.renderOrientation ?: Matrix3f()
|
||||
|
||||
// Create mutable copies for manipulation
|
||||
val renderQuat = Quaternionf().setFromUnnormalized(renderMatrix)
|
||||
var targetQuat = Quaternionf().setFromUnnormalized(current)
|
||||
|
||||
// --- Shortest Path Check (Still mandatory for Slerp) ---
|
||||
if (renderQuat.dot(targetQuat) < 0) {
|
||||
targetQuat = targetQuat.invert()
|
||||
}
|
||||
// --------------------------------------------------------
|
||||
|
||||
// K is the speed (rad/s) we want to close the gap at.
|
||||
val k_rate = 10.0f // E.g., target 10 units/second closing rate.
|
||||
|
||||
// Calculate the frame-rate independent alpha (t) for Slerp.
|
||||
// This makes the smoothing constant 'k_rate' a rate of change, not an arbitrary alpha value.
|
||||
val slerpAlpha = 1.0f - Math.exp(-(k_rate * this.frameTime)).toFloat()
|
||||
|
||||
// Use Slerp to interpolate the renderQuat towards the targetQuat
|
||||
val newRenderQuat = renderQuat.slerp(targetQuat, slerpAlpha, Quaternionf())
|
||||
|
||||
// Set the new orientation
|
||||
renderOrientation = Matrix3f().set(newRenderQuat)
|
||||
|
||||
// Angular velocity is now redundant for rendering, but could be used for particle effects, etc.
|
||||
}
|
||||
|
||||
val forwardVector: Vector3f
|
||||
|
||||
@@ -23,14 +23,11 @@ object PastureLinkManager {
|
||||
// Maps player UUID
|
||||
val links = mutableMapOf<UUID, PastureLink>()
|
||||
|
||||
@JvmStatic
|
||||
fun getLinkByPlayerId(playerId: UUID) = links[playerId]
|
||||
@JvmStatic
|
||||
fun createLink(playerId: UUID, link: PastureLink) {
|
||||
links[playerId] = link
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getLinkByPlayer(player: ServerPlayer): PastureLink? {
|
||||
val link = getLinkByPlayerId(player.uuid)
|
||||
if (link != null) {
|
||||
@@ -43,7 +40,6 @@ object PastureLinkManager {
|
||||
return link
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun removeAt(world: ServerLevel, pos: BlockPos) {
|
||||
links.removeIf { (uuid, pastureLink) ->
|
||||
val shouldRemove = world.dimensionTypeRegistration().`is`(pastureLink.dimension) && pastureLink.pos == pos
|
||||
|
||||
-1
@@ -28,7 +28,6 @@ import net.minecraft.server.level.ServerPlayer
|
||||
object PasturePermissionControllers {
|
||||
val controllers = PrioritizedList<PasturePermissionController>()
|
||||
|
||||
@JvmStatic
|
||||
fun permit(player: ServerPlayer, pastureBlockEntity: PokemonPastureBlockEntity): PasturePermissions {
|
||||
return controllers.firstNotNullOfOrNull { it.permit(player, pastureBlockEntity) }
|
||||
?: PasturePermissions(
|
||||
|
||||
@@ -147,10 +147,6 @@ object CobblemonPermissions {
|
||||
@JvmStatic
|
||||
val SEE_HIDDEN_NPCS = this.create("seehiddennpcs", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
@JvmStatic
|
||||
val USE_RIDING_STATS_DEBUG = this.create("useridingstatsdebug", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
@JvmStatic
|
||||
fun all(): Iterable<Permission> = this.permissions
|
||||
|
||||
private fun create(node: String, level: PermissionLevel): Permission {
|
||||
|
||||
@@ -53,196 +53,100 @@ object PokeBalls : JsonDataRegistry<PokeBall> {
|
||||
// ToDo datapack pokeball type here instead
|
||||
private val custom = hashMapOf<ResourceLocation, PokeBall>()
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("getPokeBall")
|
||||
val POKE_BALL
|
||||
get() = this.byName("poke_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getSlateBall")
|
||||
val SLATE_BALL
|
||||
get() = this.byName("slate_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getAzureBall")
|
||||
val AZURE_BALL
|
||||
get() = this.byName("azure_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getVerdantBall")
|
||||
val VERDANT_BALL
|
||||
get() = this.byName("verdant_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getRoseateBall")
|
||||
val ROSEATE_BALL
|
||||
get() = this.byName("roseate_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getCitrineBall")
|
||||
val CITRINE_BALL
|
||||
get() = this.byName("citrine_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getGreatBall")
|
||||
val GREAT_BALL
|
||||
get() = this.byName("great_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getUltraBall")
|
||||
val ULTRA_BALL
|
||||
get() = this.byName("ultra_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getMasterBall")
|
||||
val MASTER_BALL
|
||||
get() = this.byName("master_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getSafariBall")
|
||||
val SAFARI_BALL
|
||||
get() = this.byName("safari_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getFastBall")
|
||||
val FAST_BALL
|
||||
get() = this.byName("fast_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getLevelBall")
|
||||
val LEVEL_BALL
|
||||
get() = this.byName("level_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getLureBall")
|
||||
val LURE_BALL
|
||||
get() = this.byName("lure_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getHeavyBall")
|
||||
val HEAVY_BALL
|
||||
get() = this.byName("heavy_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getLoveBall")
|
||||
val LOVE_BALL
|
||||
get() = this.byName("love_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getFriendBall")
|
||||
val FRIEND_BALL
|
||||
get() = this.byName("friend_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getMoonBall")
|
||||
val MOON_BALL
|
||||
get() = this.byName("moon_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getSportBall")
|
||||
val SPORT_BALL
|
||||
get() = this.byName("sport_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getNetBall")
|
||||
val NET_BALL
|
||||
get() = this.byName("net_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getDiveBall")
|
||||
val DIVE_BALL
|
||||
get() = this.byName("dive_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getNestBall")
|
||||
val NEST_BALL
|
||||
get() = this.byName("nest_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getRepeatBall")
|
||||
val REPEAT_BALL
|
||||
get() = this.byName("repeat_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getTimerBall")
|
||||
val TIMER_BALL
|
||||
get() = this.byName("timer_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getLuxuryBall")
|
||||
val LUXURY_BALL
|
||||
get() = this.byName("luxury_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getPremierBall")
|
||||
val PREMIER_BALL
|
||||
get() = this.byName("premier_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getDuskBall")
|
||||
val DUSK_BALL
|
||||
get() = this.byName("dusk_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getHealBall")
|
||||
val HEAL_BALL
|
||||
get() = this.byName("heal_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getQuickBall")
|
||||
val QUICK_BALL
|
||||
get() = this.byName("quick_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getCherishBall")
|
||||
val CHERISH_BALL
|
||||
get() = this.byName("cherish_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getParkBall")
|
||||
val PARK_BALL
|
||||
get() = this.byName("park_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getDreamBall")
|
||||
val DREAM_BALL
|
||||
get() = this.byName("dream_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getBeastBall")
|
||||
val BEAST_BALL
|
||||
get() = this.byName("beast_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getAncientPokeBall")
|
||||
val ANCIENT_POKE_BALL
|
||||
get() = this.byName("ancient_poke_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getAncientCitrineBall")
|
||||
val ANCIENT_CITRINE_BALL
|
||||
get() = this.byName("ancient_citrine_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getAncientVerdantBall")
|
||||
val ANCIENT_VERDANT_BALL
|
||||
get() = this.byName("ancient_verdant_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getAncientAzureBall")
|
||||
val ANCIENT_AZURE_BALL
|
||||
get() = this.byName("ancient_azure_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getAncientRoseateBall")
|
||||
val ANCIENT_ROSEATE_BALL
|
||||
get() = this.byName("ancient_roseate_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getAncientSlateBall")
|
||||
val ANCIENT_SLATE_BALL
|
||||
get() = this.byName("ancient_slate_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getAncientIvoryBall")
|
||||
val ANCIENT_IVORY_BALL
|
||||
get() = this.byName("ancient_ivory_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getAncientGreatBall")
|
||||
val ANCIENT_GREAT_BALL
|
||||
get() = this.byName("ancient_great_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getAncientUltraBall")
|
||||
val ANCIENT_ULTRA_BALL
|
||||
get() = this.byName("ancient_ultra_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getAncientHeavyBall")
|
||||
val ANCIENT_HEAVY_BALL
|
||||
get() = this.byName("ancient_heavy_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getAncientLeadenBall")
|
||||
val ANCIENT_LEADEN_BALL
|
||||
get() = this.byName("ancient_leaden_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getAncientGigatonBall")
|
||||
val ANCIENT_GIGATON_BALL
|
||||
get() = this.byName("ancient_gigaton_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getAncientFeatherBall")
|
||||
val ANCIENT_FEATHER_BALL
|
||||
get() = this.byName("ancient_feather_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getAncientWingBall")
|
||||
val ANCIENT_WING_BALL
|
||||
get() = this.byName("ancient_wing_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getAncientJetBall")
|
||||
val ANCIENT_JET_BALL
|
||||
get() = this.byName("ancient_jet_ball")
|
||||
@JvmStatic
|
||||
@get:JvmName("getAncientOriginBall")
|
||||
val ANCIENT_ORIGIN_BALL
|
||||
get() = this.byName("ancient_origin_ball")
|
||||
|
||||
@@ -321,10 +225,8 @@ object PokeBalls : JsonDataRegistry<PokeBall> {
|
||||
* Gets a Pokeball from registry name.
|
||||
* @return the pokeball object if found otherwise null.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getPokeBall(name : ResourceLocation): PokeBall? = this.custom[name] ?: this.defaults[name]
|
||||
|
||||
@JvmStatic
|
||||
fun all() = this.defaults.filterKeys { !this.custom.containsKey(it) }.values + this.custom.values
|
||||
|
||||
private fun createDefault(
|
||||
@@ -348,196 +250,4 @@ object PokeBalls : JsonDataRegistry<PokeBall> {
|
||||
val identifier = cobblemonResource(name)
|
||||
return this.custom[identifier] ?: this.defaults[identifier]!!
|
||||
}
|
||||
|
||||
/**
|
||||
* Backwards compatibility getters
|
||||
*/
|
||||
@JvmName("getPOKE_BALL")
|
||||
@Deprecated("Use PokeBalls.getPokeBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getPOKE_BALL() = POKE_BALL
|
||||
|
||||
@JvmName("getSLATE_BALL")
|
||||
@Deprecated("Use PokeBalls.getSlateBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getSLATE_BALL() = SLATE_BALL
|
||||
|
||||
@JvmName("getAZURE_BALL")
|
||||
@Deprecated("Use PokeBalls.getAzureBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getAZURE_BALL() = AZURE_BALL
|
||||
|
||||
@JvmName("getVERDANT_BALL")
|
||||
@Deprecated("Use PokeBalls.getVerdantBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getVERDANT_BALL() = VERDANT_BALL
|
||||
|
||||
@JvmName("getROSEATE_BALL")
|
||||
@Deprecated("Use PokeBalls.getRoseateBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getROSEATE_BALL() = ROSEATE_BALL
|
||||
|
||||
@JvmName("getCITRINE_BALL")
|
||||
@Deprecated("Use PokeBalls.getCitrineBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getCITRINE_BALL() = CITRINE_BALL
|
||||
|
||||
@JvmName("getGREAT_BALL")
|
||||
@Deprecated("Use PokeBalls.getGreatBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getGREAT_BALL() = GREAT_BALL
|
||||
|
||||
@JvmName("getULTRA_BALL")
|
||||
@Deprecated("Use PokeBalls.getUltraBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getULTRA_BALL() = ULTRA_BALL
|
||||
|
||||
@JvmName("getMASTER_BALL")
|
||||
@Deprecated("Use PokeBalls.getMasterBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getMASTER_BALL() = MASTER_BALL
|
||||
|
||||
@JvmName("getSAFARI_BALL")
|
||||
@Deprecated("Use PokeBalls.getSafariBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getSAFARI_BALL() = SAFARI_BALL
|
||||
|
||||
@JvmName("getFAST_BALL")
|
||||
@Deprecated("Use PokeBalls.getFastBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getFAST_BALL() = FAST_BALL
|
||||
|
||||
@JvmName("getLEVEL_BALL")
|
||||
@Deprecated("Use PokeBalls.getLevelBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getLEVEL_BALL() = LEVEL_BALL
|
||||
|
||||
@JvmName("getLURE_BALL")
|
||||
@Deprecated("Use PokeBalls.getLureBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getLURE_BALL() = LURE_BALL
|
||||
|
||||
@JvmName("getHEAVY_BALL")
|
||||
@Deprecated("Use PokeBalls.getHeavyBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getHEAVY_BALL() = HEAVY_BALL
|
||||
|
||||
@JvmName("getLOVE_BALL")
|
||||
@Deprecated("Use PokeBalls.getLoveBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getLOVE_BALL() = LOVE_BALL
|
||||
|
||||
@JvmName("getFRIEND_BALL")
|
||||
@Deprecated("Use PokeBalls.getFriendBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getFRIEND_BALL() = FRIEND_BALL
|
||||
|
||||
@JvmName("getMOON_BALL")
|
||||
@Deprecated("Use PokeBalls.getMoonBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getMOON_BALL() = MOON_BALL
|
||||
|
||||
@JvmName("getSPORT_BALL")
|
||||
@Deprecated("Use PokeBalls.getSportBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getSPORT_BALL() = SPORT_BALL
|
||||
|
||||
@JvmName("getNET_BALL")
|
||||
@Deprecated("Use PokeBalls.getNetBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getNET_BALL() = NET_BALL
|
||||
|
||||
@JvmName("getNEST_BALL")
|
||||
@Deprecated("Use PokeBalls.getNestBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getNEST_BALL() = NEST_BALL
|
||||
|
||||
@JvmName("getREPEAT_BALL")
|
||||
@Deprecated("Use PokeBalls.getRepeatBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getREPEAT_BALL() = REPEAT_BALL
|
||||
|
||||
@JvmName("getTIMER_BALL")
|
||||
@Deprecated("Use PokeBalls.getTimerBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getTIMER_BALL() = TIMER_BALL
|
||||
|
||||
@JvmName("getLUXURY_BALL")
|
||||
@Deprecated("Use PokeBalls.getLuxuryBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getLUXURY_BALL() = LUXURY_BALL
|
||||
|
||||
@JvmName("getPREMIER_BALL")
|
||||
@Deprecated("Use PokeBalls.getPremierBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getPREMIER_BALL() = PREMIER_BALL
|
||||
|
||||
@JvmName("getDUSK_BALL")
|
||||
@Deprecated("Use PokeBalls.getDuskBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getDUSK_BALL() = DUSK_BALL
|
||||
|
||||
@JvmName("getHEAL_BALL")
|
||||
@Deprecated("Use PokeBalls.getHealBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getHEAL_BALL() = HEAL_BALL
|
||||
|
||||
@JvmName("getQUICK_BALL")
|
||||
@Deprecated("Use PokeBalls.getQuickBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getQUICK_BALL() = QUICK_BALL
|
||||
|
||||
@JvmName("getCHERISH_BALL")
|
||||
@Deprecated("Use PokeBalls.getCherishBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getCHERISH_BALL() = CHERISH_BALL
|
||||
|
||||
@JvmName("getPARK_BALL")
|
||||
@Deprecated("Use PokeBalls.getParkBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getPARK_BALL() = PARK_BALL
|
||||
|
||||
@JvmName("getDREAM_BALL")
|
||||
@Deprecated("Use PokeBalls.getDreamBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getDREAM_BALL() = DREAM_BALL
|
||||
|
||||
@JvmName("getBEAST_BALL")
|
||||
@Deprecated("Use PokeBalls.getBeastBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getBEAST_BALL() = BEAST_BALL
|
||||
|
||||
@JvmName("getANCIENT_POKE_BALL")
|
||||
@Deprecated("Use PokeBalls.getAncientPokeBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getANCIENT_POKE_BALL() = ANCIENT_POKE_BALL
|
||||
|
||||
@JvmName("getANCIENT_CITRINE_BALL")
|
||||
@Deprecated("Use PokeBalls.getAncientCitrineBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getANCIENT_CITRINE_BALL() = ANCIENT_CITRINE_BALL
|
||||
|
||||
@JvmName("getANCIENT_VERDANT_BALL")
|
||||
@Deprecated("Use PokeBalls.getAncientVerdantBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getANCIENT_VERDANT_BALL() = ANCIENT_VERDANT_BALL
|
||||
|
||||
@JvmName("getANCIENT_AZURE_BALL")
|
||||
@Deprecated("Use PokeBalls.getAncientAzureBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getANCIENT_AZURE_BALL() = ANCIENT_AZURE_BALL
|
||||
|
||||
@JvmName("getANCIENT_ROSEATE_BALL")
|
||||
@Deprecated("Use PokeBalls.getAncientRoseateBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getANCIENT_ROSEATE_BALL() = ANCIENT_ROSEATE_BALL
|
||||
|
||||
@JvmName("getANCIENT_SLATE_BALL")
|
||||
@Deprecated("Use PokeBalls.getAncientSlateBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getANCIENT_SLATE_BALL() = ANCIENT_SLATE_BALL
|
||||
|
||||
@JvmName("getANCIENT_IVORY_BALL")
|
||||
@Deprecated("Use PokeBalls.getAncientIvoryBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getANCIENT_IVORY_BALL() = ANCIENT_IVORY_BALL
|
||||
|
||||
@JvmName("getANCIENT_GREAT_BALL")
|
||||
@Deprecated("Use PokeBalls.getAncientGreatBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getANCIENT_GREAT_BALL() = ANCIENT_GREAT_BALL
|
||||
|
||||
@JvmName("getANCIENT_ULTRA_BALL")
|
||||
@Deprecated("Use PokeBalls.getAncientUltraBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getANCIENT_ULTRA_BALL() = ANCIENT_ULTRA_BALL
|
||||
|
||||
@JvmName("getANCIENT_HEAVY_BALL")
|
||||
@Deprecated("Use PokeBalls.getAncientHeavyBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getANCIENT_HEAVY_BALL() = ANCIENT_HEAVY_BALL
|
||||
|
||||
@JvmName("getANCIENT_LEADEN_BALL")
|
||||
@Deprecated("Use PokeBalls.getAncientLeadenBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getANCIENT_LEADEN_BALL() = ANCIENT_LEADEN_BALL
|
||||
|
||||
@JvmName("getANCIENT_GIGATON_BALL")
|
||||
@Deprecated("Use PokeBalls.getAncientGigatonBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getANCIENT_GIGATON_BALL() = ANCIENT_GIGATON_BALL
|
||||
|
||||
@JvmName("getANCIENT_FEATHER_BALL")
|
||||
@Deprecated("Use PokeBalls.getAncientFeatherBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getANCIENT_FEATHER_BALL() = ANCIENT_FEATHER_BALL
|
||||
|
||||
@JvmName("getANCIENT_WING_BALL")
|
||||
@Deprecated("Use PokeBalls.getAncientWingBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getANCIENT_WING_BALL() = ANCIENT_WING_BALL
|
||||
|
||||
@JvmName("getANCIENT_JET_BALL")
|
||||
@Deprecated("Use PokeBalls.getAncientJetBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getANCIENT_JET_BALL() = ANCIENT_JET_BALL
|
||||
|
||||
@JvmName("getANCIENT_ORIGIN_BALL")
|
||||
@Deprecated("Use PokeBalls.getAncientOriginBall(), provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getANCIENT_ORIGIN_BALL() = ANCIENT_ORIGIN_BALL
|
||||
|
||||
}
|
||||
@@ -24,151 +24,126 @@ import net.minecraft.resources.ResourceLocation
|
||||
object Natures {
|
||||
private val allNatures = mutableListOf<Nature>()
|
||||
|
||||
@JvmField
|
||||
val HARDY = registerNature(
|
||||
Nature(cobblemonResource("hardy"), "cobblemon.nature.hardy",
|
||||
null, null, null, null)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val LONELY = registerNature(
|
||||
Nature(cobblemonResource("lonely"), "cobblemon.nature.lonely",
|
||||
Stats.ATTACK, Stats.DEFENCE, Flavour.SPICY, Flavour.SOUR)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val BRAVE = registerNature(
|
||||
Nature(cobblemonResource("brave"), "cobblemon.nature.brave",
|
||||
Stats.ATTACK, Stats.SPEED, Flavour.SPICY, Flavour.SWEET)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val ADAMANT = registerNature(
|
||||
Nature(cobblemonResource("adamant"), "cobblemon.nature.adamant",
|
||||
Stats.ATTACK, Stats.SPECIAL_ATTACK, Flavour.SPICY, Flavour.DRY)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val NAUGHTY = registerNature(
|
||||
Nature(cobblemonResource("naughty"), "cobblemon.nature.naughty",
|
||||
Stats.ATTACK, Stats.SPECIAL_DEFENCE, Flavour.SPICY, Flavour.BITTER)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val BOLD = registerNature(
|
||||
Nature(cobblemonResource("bold"), "cobblemon.nature.bold",
|
||||
Stats.DEFENCE, Stats.ATTACK, Flavour.SOUR, Flavour.SPICY)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val DOCILE = registerNature(
|
||||
Nature(cobblemonResource("docile"), "cobblemon.nature.docile",
|
||||
null, null, null, null)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val RELAXED = registerNature(
|
||||
Nature(cobblemonResource("relaxed"), "cobblemon.nature.relaxed",
|
||||
Stats.DEFENCE, Stats.SPEED, Flavour.SOUR, Flavour.SWEET)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val IMPISH = registerNature(
|
||||
Nature(cobblemonResource("impish"), "cobblemon.nature.impish",
|
||||
Stats.DEFENCE, Stats.SPECIAL_ATTACK, Flavour.SOUR, Flavour.DRY)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val LAX = registerNature(
|
||||
Nature(cobblemonResource("lax"), "cobblemon.nature.lax",
|
||||
Stats.DEFENCE, Stats.SPECIAL_DEFENCE, Flavour.SOUR, Flavour.BITTER)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val TIMID = registerNature(
|
||||
Nature(cobblemonResource("timid"), "cobblemon.nature.timid",
|
||||
Stats.SPEED, Stats.ATTACK, Flavour.SWEET, Flavour.SPICY)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val HASTY = registerNature(
|
||||
Nature(cobblemonResource("hasty"), "cobblemon.nature.hasty",
|
||||
Stats.SPEED, Stats.DEFENCE, Flavour.SWEET, Flavour.SOUR)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val SERIOUS = registerNature(
|
||||
Nature(cobblemonResource("serious"), "cobblemon.nature.serious",
|
||||
null, null, null, null)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val JOLLY = registerNature(
|
||||
Nature(cobblemonResource("jolly"), "cobblemon.nature.jolly",
|
||||
Stats.SPEED, Stats.SPECIAL_ATTACK, Flavour.SWEET, Flavour.DRY)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val NAIVE = registerNature(
|
||||
Nature(cobblemonResource("naive"), "cobblemon.nature.naive",
|
||||
Stats.SPEED, Stats.SPECIAL_DEFENCE, Flavour.SWEET, Flavour.BITTER)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val MODEST = registerNature(
|
||||
Nature(cobblemonResource("modest"), "cobblemon.nature.modest",
|
||||
Stats.SPECIAL_ATTACK, Stats.ATTACK, null, null)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val MILD = registerNature(
|
||||
Nature(cobblemonResource("mild"), "cobblemon.nature.mild",
|
||||
Stats.SPECIAL_ATTACK, Stats.DEFENCE, Flavour.DRY, Flavour.SOUR)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val QUIET = registerNature(
|
||||
Nature(cobblemonResource("quiet"), "cobblemon.nature.quiet",
|
||||
Stats.SPECIAL_ATTACK, Stats.SPEED, Flavour.DRY, Flavour.SWEET)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val BASHFUL = registerNature(
|
||||
Nature(cobblemonResource("bashful"), "cobblemon.nature.bashful",
|
||||
null, null, null, null)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val RASH = registerNature(
|
||||
Nature(cobblemonResource("rash"), "cobblemon.nature.rash",
|
||||
Stats.SPECIAL_ATTACK, Stats.SPECIAL_DEFENCE, Flavour.DRY, Flavour.BITTER)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val CALM = registerNature(
|
||||
Nature(cobblemonResource("calm"), "cobblemon.nature.calm",
|
||||
Stats.SPECIAL_DEFENCE, Stats.ATTACK, Flavour.BITTER, Flavour.SPICY)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val GENTLE = registerNature(
|
||||
Nature(cobblemonResource("gentle"), "cobblemon.nature.gentle",
|
||||
Stats.SPECIAL_DEFENCE, Stats.DEFENCE, Flavour.BITTER, Flavour.SOUR)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val SASSY = registerNature(
|
||||
Nature(cobblemonResource("sassy"), "cobblemon.nature.sassy",
|
||||
Stats.SPECIAL_DEFENCE, Stats.SPEED, Flavour.BITTER, Flavour.SWEET)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val CAREFUL = registerNature(
|
||||
Nature(cobblemonResource("careful"), "cobblemon.nature.careful",
|
||||
Stats.SPECIAL_DEFENCE, Stats.SPECIAL_ATTACK, Flavour.BITTER, Flavour.DRY)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val QUIRKY = registerNature(
|
||||
Nature(cobblemonResource("quirky"), "cobblemon.nature.quirky",
|
||||
null, null, null, null)
|
||||
@@ -178,7 +153,6 @@ object Natures {
|
||||
/**
|
||||
* Registers a new nature type
|
||||
*/
|
||||
@JvmStatic
|
||||
fun registerNature(nature: Nature): Nature {
|
||||
allNatures.add(nature)
|
||||
return nature
|
||||
@@ -188,7 +162,6 @@ object Natures {
|
||||
* Gets a nature by registry name
|
||||
* @return a nature type or null
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getNature(name: ResourceLocation): Nature? {
|
||||
return allNatures.find { nature -> nature.name == name }
|
||||
}
|
||||
@@ -197,7 +170,6 @@ object Natures {
|
||||
* Utility method to get a nature by string
|
||||
* @return a nature type or null
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getNature(identifier: String) = getNature(cobblemonResource(identifier))
|
||||
?: getNature(ResourceLocation.parse(identifier))
|
||||
|
||||
@@ -205,114 +177,10 @@ object Natures {
|
||||
* Helper function for a random Nature
|
||||
* @return a random nature type
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getRandomNature(): Nature {
|
||||
return allNatures.random()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun all(): Collection<Nature> = this.allNatures.toList()
|
||||
|
||||
/**
|
||||
* Backwards compatibility getters
|
||||
*/
|
||||
@JvmName("getHARDY")
|
||||
@Deprecated("Use Natures.HARDY, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getHARDY() = HARDY
|
||||
|
||||
@JvmName("getLONELY")
|
||||
@Deprecated("Use Natures.LONELY, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getLONELY() = LONELY
|
||||
|
||||
@JvmName("getBRAVE")
|
||||
@Deprecated("Use Natures.BRAVE, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getBRAVE() = BRAVE
|
||||
|
||||
@JvmName("getADAMANT")
|
||||
@Deprecated("Use Natures.ADAMANT, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getADAMANT() = ADAMANT
|
||||
|
||||
@JvmName("getNAUGHTY")
|
||||
@Deprecated("Use Natures.NAUGHTY, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getNAUGHTY() = NAUGHTY
|
||||
|
||||
@JvmName("getBOLD")
|
||||
@Deprecated("Use Natures.BOLD, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getBOLD() = BOLD
|
||||
|
||||
@JvmName("getDOCILE")
|
||||
@Deprecated("Use Natures.DOCILE, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getDOCILE() = DOCILE
|
||||
|
||||
@JvmName("getRELAXED")
|
||||
@Deprecated("Use Natures.RELAXED, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getRELAXED() = RELAXED
|
||||
|
||||
@JvmName("getIMPISH")
|
||||
@Deprecated("Use Natures.IMPISH, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getIMPISH() = IMPISH
|
||||
|
||||
@JvmName("getLAX")
|
||||
@Deprecated("Use Natures.LAX, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getLAX() = LAX
|
||||
|
||||
@JvmName("getTIMID")
|
||||
@Deprecated("Use Natures.TIMID, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getTIMID() = TIMID
|
||||
|
||||
@JvmName("getHASTY")
|
||||
@Deprecated("Use Natures.HASTY, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getHASTY() = HASTY
|
||||
|
||||
@JvmName("getSERIOUS")
|
||||
@Deprecated("Use Natures.SERIOUS, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getSERIOUS() = SERIOUS
|
||||
|
||||
@JvmName("getJOLLY")
|
||||
@Deprecated("Use Natures.JOLLY, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getJOLLY() = JOLLY
|
||||
|
||||
@JvmName("getNAIVE")
|
||||
@Deprecated("Use Natures.NAIVE, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getNAIVE() = NAIVE
|
||||
|
||||
@JvmName("getMODEST")
|
||||
@Deprecated("Use Natures.MODEST, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getMODEST() = MODEST
|
||||
|
||||
@JvmName("getMILD")
|
||||
@Deprecated("Use Natures.MILD, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getMILD() = MILD
|
||||
|
||||
@JvmName("getQUIET")
|
||||
@Deprecated("Use Natures.QUIET, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getQUIET() = QUIET
|
||||
|
||||
@JvmName("getBASHFUL")
|
||||
@Deprecated("Use Natures.BASHFUL, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getBASHFUL() = BASHFUL
|
||||
|
||||
@JvmName("getRASH")
|
||||
@Deprecated("Use Natures.RASH, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getRASH() = RASH
|
||||
|
||||
@JvmName("getCALM")
|
||||
@Deprecated("Use Natures.CALM, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getCALM() = CALM
|
||||
|
||||
@JvmName("getGENTLE")
|
||||
@Deprecated("Use Natures.GENTLE, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getGENTLE() = GENTLE
|
||||
|
||||
@JvmName("getSASSY")
|
||||
@Deprecated("Use Natures.SASSY, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getSASSY() = SASSY
|
||||
|
||||
@JvmName("getCAREFUL")
|
||||
@Deprecated("Use Natures.CAREFUL, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getCAREFUL() = CAREFUL
|
||||
|
||||
@JvmName("getQUIRKY")
|
||||
@Deprecated("Use Natures.QUIRKY, provided for backwards compatibility until Cobblemon 1.8.")
|
||||
fun getQUIRKY() = QUIRKY
|
||||
}
|
||||
@@ -17,7 +17,6 @@ import com.cobblemon.mod.common.api.events.pokemon.ShinyChanceCalculationEvent
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.api.pokemon.aspect.AspectProvider
|
||||
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.Statuses
|
||||
import com.cobblemon.mod.common.api.properties.CustomPokemonProperty
|
||||
@@ -32,12 +31,10 @@ import com.cobblemon.mod.common.pokemon.IVs
|
||||
import com.cobblemon.mod.common.pokemon.OriginalTrainerType
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.RenderablePokemon
|
||||
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
|
||||
import com.cobblemon.mod.common.pokemon.status.PersistentStatus
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.isDouble
|
||||
import com.cobblemon.mod.common.util.isFloat
|
||||
import com.cobblemon.mod.common.util.isUuid
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import com.cobblemon.mod.common.util.simplify
|
||||
@@ -149,8 +146,6 @@ open class PokemonProperties {
|
||||
props.originalTrainer = parsePlayerProperty(keyPairs, listOf("originaltrainer", "ot"))
|
||||
props.moves = parseString(keyPairs, listOf("moves"))?.split(",")
|
||||
props.heldItem = parseString(keyPairs, listOf("helditem", "held_item"))
|
||||
props.minPerfectIVs = parseIntProperty(keyPairs, listOf("min_perfect_ivs"))?.coerceIn(0, Stats.PERMANENT.size)
|
||||
props.scaleModifier = parseFloatProperty(keyPairs, listOf("scale_modifier"))
|
||||
|
||||
val maybeIVs = IVs()
|
||||
val maybeEVs = EVs()
|
||||
@@ -200,16 +195,6 @@ open class PokemonProperties {
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseFloatProperty(keyPairs: MutableList<Pair<String, String?>>, labels: Iterable<String>): Float? {
|
||||
val matchingKeyPair = getMatchedKeyPair(keyPairs, labels) ?: return null
|
||||
val value = matchingKeyPair.second
|
||||
return if (value == null || !value.isFloat()) {
|
||||
null
|
||||
} else {
|
||||
value.toFloat()
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseIdentifierOfRegistry(keyPairs: MutableList<Pair<String, String?>>, validKeys: List<String>, valueFetcher: (ResourceLocation) -> String?): String? {
|
||||
val matched = getMatchedKeyPair(keyPairs, validKeys) ?: return null
|
||||
val value = matched.second?.lowercase() ?: return null
|
||||
@@ -358,9 +343,7 @@ open class PokemonProperties {
|
||||
var moves: List<String>? = null
|
||||
var heldItem: String? = null
|
||||
var cosmeticItem: String? = null
|
||||
var scaleModifier: Float? = null
|
||||
|
||||
var minPerfectIVs: Int? = null
|
||||
var ivs: IVs? = null
|
||||
var evs: EVs? = null
|
||||
var customProperties = mutableListOf<CustomPokemonProperty>()
|
||||
@@ -430,11 +413,6 @@ open class PokemonProperties {
|
||||
pokemon.hyperTrainIV(stat.key, stat.value)
|
||||
}
|
||||
}
|
||||
minPerfectIVs?.let {
|
||||
CobblemonStatProvider.ofType(Stat.Type.PERMANENT).shuffled().take(it).forEach { stat ->
|
||||
pokemon.setIV(stat, IVs.MAX_VALUE)
|
||||
}
|
||||
}
|
||||
evs?.let { evs ->
|
||||
evs.forEach { stat ->
|
||||
pokemon.setEV(stat.key, stat.value)
|
||||
@@ -491,7 +469,6 @@ open class PokemonProperties {
|
||||
if (stack.isEmpty) return@let
|
||||
pokemon.swapHeldItem(stack, decrement = true, aiCanDrop = false)
|
||||
}
|
||||
scaleModifier?.let { pokemon.scaleModifier = it }
|
||||
pokemon.updateAspects()
|
||||
}
|
||||
|
||||
@@ -535,7 +512,6 @@ open class PokemonProperties {
|
||||
nature?.takeIf { it != pokemon.nature.name.toString() }?.let { return false }
|
||||
ability?.takeIf { it != pokemon.ability.name }?.let { return false }
|
||||
status?.takeIf { it != pokemon.status?.status?.showdownName }?.let { return false }
|
||||
minPerfectIVs?.takeIf { pokemon.ivs.count { stat -> stat.value == IVs.MAX_VALUE } < it }?.let { return false }
|
||||
ivs?.forEach{ stat ->
|
||||
if (stat.value != pokemon.ivs[stat.key]) { return false }
|
||||
}
|
||||
@@ -566,7 +542,6 @@ open class PokemonProperties {
|
||||
|
||||
return@takeIf false
|
||||
}?.let { return false }
|
||||
scaleModifier?.takeIf { it != pokemon.scaleModifier }?.let { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -595,7 +570,6 @@ open class PokemonProperties {
|
||||
nature?.takeIf { it != properties.nature }?.let { return false }
|
||||
ability?.takeIf { it != properties.ability }?.let { return false }
|
||||
status?.takeIf { it != properties.status }?.let { return false }
|
||||
minPerfectIVs?.takeIf { it != properties.minPerfectIVs }?.let { return false }
|
||||
ivs?.let{ ivs ->
|
||||
ivs.forEach{ stat ->
|
||||
//If the potential subset has IV and the main set does not then it cant be a subset
|
||||
@@ -619,7 +593,6 @@ open class PokemonProperties {
|
||||
originalTrainerType?.takeIf { it != properties.originalTrainerType }?.let{ return false }
|
||||
moves?.takeIf { it.any { move -> properties.moves?.none { it == move } == true } }?.let { return false }
|
||||
fullness?.takeIf { it != properties.fullness }?.let { return false }
|
||||
scaleModifier?.takeIf { it != properties.scaleModifier }?.let { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -673,7 +646,6 @@ open class PokemonProperties {
|
||||
nature?.let { nbt.putString(DataKeys.POKEMON_NATURE, it) }
|
||||
ability?.let { nbt.putString(DataKeys.POKEMON_ABILITY, it) }
|
||||
status?.let { nbt.putString(DataKeys.POKEMON_STATUS_NAME, it) }
|
||||
minPerfectIVs?.let { nbt.putInt(DataKeys.POKEMON_MIN_PERFECT_IVS, it) }
|
||||
ivs?.let { nbt.put(DataKeys.POKEMON_IVS, IVs.CODEC.encodeStart(NbtOps.INSTANCE, it).result().get()) }
|
||||
evs?.let { nbt.put(DataKeys.POKEMON_EVS, EVs.CODEC.encodeStart(NbtOps.INSTANCE, it).result().get()) }
|
||||
type?.let { nbt.putString(DataKeys.ELEMENTAL_TYPE, it) }
|
||||
@@ -685,7 +657,6 @@ open class PokemonProperties {
|
||||
originalTrainer?.let { nbt.putString(DataKeys.POKEMON_ORIGINAL_TRAINER, it) }
|
||||
moves?.let { nbt.putString(DataKeys.POKEMON_PROPERTIES_MOVES, it.joinToString(separator = ",")) }
|
||||
heldItem?.let {nbt.putString(DataKeys.POKEMON_PROPERTIES_HELDITEM, it)}
|
||||
scaleModifier?.let { nbt.putFloat(DataKeys.POKEMON_SCALE_MODIFIER, it) }
|
||||
val custom = ListTag()
|
||||
customProperties.map { StringTag.valueOf(it.asString()) }.forEach { custom.add(it) }
|
||||
nbt.put(DataKeys.POKEMON_PROPERTIES_CUSTOM, custom)
|
||||
@@ -707,7 +678,6 @@ open class PokemonProperties {
|
||||
nature = if (tag.contains(DataKeys.POKEMON_NATURE)) tag.getString(DataKeys.POKEMON_NATURE) else null
|
||||
ability = if (tag.contains(DataKeys.POKEMON_ABILITY)) tag.getString(DataKeys.POKEMON_ABILITY) else null
|
||||
status = if (tag.contains(DataKeys.POKEMON_STATUS_NAME)) tag.getString(DataKeys.POKEMON_STATUS_NAME) else null
|
||||
minPerfectIVs = if (tag.contains(DataKeys.POKEMON_MIN_PERFECT_IVS)) tag.getInt(DataKeys.POKEMON_MIN_PERFECT_IVS) else null
|
||||
ivs = if (tag.contains(DataKeys.POKEMON_IVS)) IVs.CODEC.decode(NbtOps.INSTANCE, tag.getCompound(DataKeys.POKEMON_IVS)).result().getOrNull()?.first else null
|
||||
evs = if (tag.contains(DataKeys.POKEMON_EVS)) EVs.CODEC.decode(NbtOps.INSTANCE, tag.getCompound(DataKeys.POKEMON_EVS)).result().getOrNull()?.first else null
|
||||
type = if (tag.contains(DataKeys.ELEMENTAL_TYPE)) tag.getString(DataKeys.ELEMENTAL_TYPE) else null
|
||||
@@ -719,7 +689,6 @@ open class PokemonProperties {
|
||||
originalTrainer = if (tag.contains(DataKeys.POKEMON_ORIGINAL_TRAINER)) tag.getString(DataKeys.POKEMON_ORIGINAL_TRAINER) else null
|
||||
moves = if (tag.contains(DataKeys.POKEMON_PROPERTIES_MOVES)) tag.getString(DataKeys.POKEMON_PROPERTIES_MOVES).split(",") else null
|
||||
heldItem = if (tag.contains(DataKeys.POKEMON_PROPERTIES_HELDITEM)) tag.getString(DataKeys.POKEMON_PROPERTIES_HELDITEM) else null
|
||||
scaleModifier = if (tag.contains(DataKeys.POKEMON_SCALE_MODIFIER)) tag.getFloat(DataKeys.POKEMON_SCALE_MODIFIER) else null
|
||||
val custom = tag.getList(DataKeys.POKEMON_PROPERTIES_CUSTOM, Tag.TAG_STRING.toInt())
|
||||
// This is kinda gross
|
||||
custom.forEach { customProperties.addAll(parse(it.asString).customProperties) }
|
||||
@@ -735,14 +704,14 @@ open class PokemonProperties {
|
||||
shiny?.let { json.addProperty(DataKeys.POKEMON_SHINY, it) }
|
||||
gender?.let { json.addProperty(DataKeys.POKEMON_GENDER, it.name) }
|
||||
species?.let { json.addProperty(DataKeys.POKEMON_SPECIES_TEXT, it) }
|
||||
//nickname?.let { json.addProperty(DataKeys.POKEMON_NICKNAME, Text.Serialization.toJsonString(it)) }
|
||||
form?.let { json.addProperty(DataKeys.POKEMON_FORM_ID, it) }
|
||||
friendship?.let { json.addProperty(DataKeys.POKEMON_FRIENDSHIP, it) }
|
||||
fullness?.let { json.addProperty(DataKeys.POKEMON_FULLNESS, it) }
|
||||
fullness?.let {json.addProperty(DataKeys.POKEMON_FULLNESS, it)}
|
||||
pokeball?.let { json.addProperty(DataKeys.POKEMON_CAUGHT_BALL, it) }
|
||||
nature?.let { json.addProperty(DataKeys.POKEMON_NATURE, it) }
|
||||
ability?.let { json.addProperty(DataKeys.POKEMON_ABILITY, it) }
|
||||
status?.let { json.addProperty(DataKeys.POKEMON_STATUS_NAME, it) }
|
||||
minPerfectIVs?.let { json.addProperty(DataKeys.POKEMON_MIN_PERFECT_IVS, it) }
|
||||
ivs?.let { json.add(DataKeys.POKEMON_IVS, IVs.CODEC.encodeStart(JsonOps.INSTANCE, it).result().get()) }
|
||||
evs?.let { json.add(DataKeys.POKEMON_EVS, EVs.CODEC.encodeStart(JsonOps.INSTANCE, it).result().get()) }
|
||||
type?.let { json.addProperty(DataKeys.ELEMENTAL_TYPE, it) }
|
||||
@@ -754,7 +723,6 @@ open class PokemonProperties {
|
||||
originalTrainer?.let { json.addProperty(DataKeys.POKEMON_ORIGINAL_TRAINER, it) }
|
||||
moves?.let { json.addProperty(DataKeys.POKEMON_PROPERTIES_MOVES, it.joinToString(separator = ",")) }
|
||||
heldItem?.let {json.addProperty(DataKeys.POKEMON_PROPERTIES_HELDITEM, it)}
|
||||
scaleModifier?.let { json.addProperty(DataKeys.POKEMON_SCALE_MODIFIER, it) }
|
||||
val custom = JsonArray()
|
||||
customProperties.map { it.asString() }.forEach { custom.add(it) }
|
||||
json.add(DataKeys.POKEMON_PROPERTIES_CUSTOM, custom)
|
||||
@@ -769,6 +737,7 @@ open class PokemonProperties {
|
||||
shiny = json.get(DataKeys.POKEMON_SHINY)?.asBoolean
|
||||
gender = json.get(DataKeys.POKEMON_GENDER)?.asString?.let { Gender.valueOf(it) }
|
||||
species = json.get(DataKeys.POKEMON_SPECIES_TEXT)?.asString
|
||||
//nickname = json.get(DataKeys.POKEMON_NICKNAME)?.asString?.let { Text.Serialization.fromJson(it) }
|
||||
form = json.get(DataKeys.POKEMON_FORM_ID)?.asString
|
||||
friendship = json.get(DataKeys.POKEMON_FRIENDSHIP)?.asInt
|
||||
fullness = json.get(DataKeys.POKEMON_FULLNESS)?.asInt
|
||||
@@ -776,7 +745,6 @@ open class PokemonProperties {
|
||||
nature = json.get(DataKeys.POKEMON_NATURE)?.asString
|
||||
ability = json.get(DataKeys.POKEMON_ABILITY)?.asString
|
||||
status = json.get(DataKeys.POKEMON_STATUS_NAME)?.asString
|
||||
minPerfectIVs = json.get(DataKeys.POKEMON_MIN_PERFECT_IVS)?.asInt
|
||||
ivs = json.getAsJsonObject(DataKeys.POKEMON_IVS)?.let { IVs.CODEC.decode(JsonOps.INSTANCE, it).result().getOrNull()?.first }
|
||||
evs = json.getAsJsonObject(DataKeys.POKEMON_EVS)?.let { EVs.CODEC.decode(JsonOps.INSTANCE, it).result().getOrNull()?.first }
|
||||
type = json.get(DataKeys.ELEMENTAL_TYPE)?.asString
|
||||
@@ -788,7 +756,6 @@ open class PokemonProperties {
|
||||
originalTrainer = json.get(DataKeys.POKEMON_ORIGINAL_TRAINER)?.asString
|
||||
moves = json.get(DataKeys.POKEMON_PROPERTIES_MOVES)?.asString?.split(",")
|
||||
heldItem = json.get(DataKeys.POKEMON_PROPERTIES_HELDITEM)?.asString
|
||||
scaleModifier = json.get(DataKeys.POKEMON_SCALE_MODIFIER)?.asFloat
|
||||
val custom = json.get(DataKeys.POKEMON_PROPERTIES_CUSTOM)?.asJsonArray
|
||||
// This is still kinda gross
|
||||
custom?.forEach { customProperties.addAll(parse(it.asString).customProperties) }
|
||||
@@ -805,12 +772,11 @@ open class PokemonProperties {
|
||||
shiny?.let { pieces.add("shiny=$it") }
|
||||
gender?.let { pieces.add("gender=$it")}
|
||||
friendship?.let { pieces.add("friendship=$it") }
|
||||
fullness?.let { pieces.add("fullness=$it") }
|
||||
fullness?.let {pieces.add("fullness=$it")}
|
||||
pokeball?.let { pieces.add("pokeball=$it") }
|
||||
nature?.let { pieces.add("nature=$it") }
|
||||
ability?.let { pieces.add("ability=$it") }
|
||||
status?.let { pieces.add("status=$it") }
|
||||
minPerfectIVs?.let { pieces.add("min_perfect_ivs=$it") }
|
||||
ivs?.forEach{ stat ->
|
||||
pieces.add("${stat.key}_iv=${stat.value}")
|
||||
}
|
||||
@@ -827,7 +793,6 @@ open class PokemonProperties {
|
||||
customProperties.forEach { pieces.add(it.asString()) }
|
||||
moves?.let { pieces.add("moves=${it.joinToString(separator = ",")}") }
|
||||
heldItem?.let {pieces.add("helditem=$it")}
|
||||
scaleModifier?.let { pieces.add("scale_modifier=$it") }
|
||||
return pieces.joinToString(separator)
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
|
||||
import com.cobblemon.mod.common.api.riding.sound.RideSoundSettingsList
|
||||
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
|
||||
@@ -128,6 +129,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
.registerTypeAdapter(MobEffect::class.java, RegistryElementAdapter<MobEffect>(BuiltInRegistries::MOB_EFFECT))
|
||||
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter)
|
||||
.registerTypeAdapter(RidingBehaviourSettings::class.java, RidingBehaviourSettingsAdapter)
|
||||
.registerTypeAdapter(RidingStatDefinition::class.java, RidingStatDefinitionAdapter)
|
||||
.registerTypeAdapter(RideSoundSettingsList::class.java, RideSoundSettingsListAdapter)
|
||||
.registerTypeAdapter(ObtainableItemCondition::class.java, ObtainableItemConditionAdapter)
|
||||
.disableHtmlEscaping()
|
||||
@@ -142,10 +144,8 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
private val speciesByIdentifier = hashMapOf<ResourceLocation, Species>()
|
||||
private val speciesByDex = HashBasedTable.create<String, Int, Species>()
|
||||
|
||||
@JvmStatic
|
||||
val species: Collection<Species>
|
||||
get() = this.speciesByIdentifier.values
|
||||
@JvmStatic
|
||||
val implemented: List<Species>
|
||||
get() = this.species.filter { it.implemented }
|
||||
|
||||
@@ -171,7 +171,6 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
* @param name The path of the species asset.
|
||||
* @return The [Species] if existing.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getByName(name: String) = this.getByIdentifier(cobblemonResource(name))
|
||||
|
||||
/**
|
||||
@@ -180,7 +179,6 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
* @param ndex The [Species.nationalPokedexNumber].
|
||||
* @return The [Species] if existing.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getByPokedexNumber(ndex: Int, namespace: String = Cobblemon.MODID) = this.speciesByDex.get(namespace, ndex)
|
||||
|
||||
/**
|
||||
@@ -189,7 +187,6 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
* @param identifier The unique [Species.resourceIdentifier] of the [Species].
|
||||
* @return The [Species] if existing.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getByIdentifier(identifier: ResourceLocation) = this.speciesByIdentifier[identifier]
|
||||
|
||||
/**
|
||||
@@ -197,7 +194,6 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
*
|
||||
* @return The loaded species amount.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun count() = this.speciesByIdentifier.size
|
||||
|
||||
/**
|
||||
@@ -205,7 +201,6 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
*
|
||||
* @return The dex numbers map to species.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getSpeciesInNamespace(namespace: String = Cobblemon.MODID): MutableMap<Int, Species> = speciesByDex.row(namespace)
|
||||
|
||||
/**
|
||||
@@ -213,7 +208,6 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
*
|
||||
* @return The list of loaded namespaces.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getNamespaces() = speciesByDex.rowKeySet().toList()
|
||||
|
||||
/**
|
||||
@@ -223,7 +217,6 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
*
|
||||
* @return A randomly selected [Species].
|
||||
*/
|
||||
@JvmStatic
|
||||
fun random(): Species = this.implemented.random()
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, Species>) {
|
||||
@@ -323,4 +316,4 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-4
@@ -36,16 +36,12 @@ object ShoulderEffectRegistry {
|
||||
PlatformEvents.SERVER_PLAYER_LOGIN.subscribe { this.refreshEffects(it.player) }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun register(name: String, effect: Class<out ShoulderEffect>) = effect.also { effects[name] = it }
|
||||
|
||||
@JvmStatic
|
||||
fun unregister(name: String) = effects.remove(name)
|
||||
|
||||
@JvmStatic
|
||||
fun getName(clazz: Class<out ShoulderEffect>) = effects.firstNotNullOf { if (it.value == clazz) it.key else null }
|
||||
|
||||
@JvmStatic
|
||||
fun get(name: String): Class<out ShoulderEffect>? = effects[name]
|
||||
|
||||
// It was removed by a source such as milk, reapply
|
||||
|
||||
-7
@@ -62,14 +62,10 @@ object GlobalSpeciesFeatures : JsonDataRegistry<SpeciesFeatureProvider<*>> {
|
||||
data.forEach(this::registerFromAssets)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getCodeFeature(name: String) = codeFeatures[name]
|
||||
@JvmStatic
|
||||
fun getResourceFeature(name: String) = resourceFeatures[name]
|
||||
@JvmStatic
|
||||
fun getFeature(name: String) = getCodeFeature(name) ?: getResourceFeature(name)
|
||||
|
||||
@JvmStatic
|
||||
fun getFeatures() = (resourceFeatures.keys + codeFeatures.keys).mapNotNull(this::getFeature)
|
||||
|
||||
fun loadOnClient(entries: Collection<Map.Entry<String, SpeciesFeatureProvider<*>>>) {
|
||||
@@ -87,9 +83,7 @@ object GlobalSpeciesFeatures : JsonDataRegistry<SpeciesFeatureProvider<*>> {
|
||||
mapping[name] = provider
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun register(name: String, provider: SpeciesFeatureProvider<*>) = register(name, provider, isCoded = true)
|
||||
@JvmStatic
|
||||
fun <T : SpeciesFeature> register(name: String, providerLambda: () -> T) {
|
||||
register(name, object : SpeciesFeatureProvider<T> {
|
||||
override fun invoke(pokemon: Pokemon) = providerLambda()
|
||||
@@ -99,7 +93,6 @@ object GlobalSpeciesFeatures : JsonDataRegistry<SpeciesFeatureProvider<*>> {
|
||||
}
|
||||
private fun registerFromAssets(identifier: ResourceLocation, provider: SpeciesFeatureProvider<*>) = register(identifier.path, provider, isCoded = false)
|
||||
|
||||
@JvmStatic
|
||||
fun unregister(name: String) {
|
||||
var coded = true
|
||||
val value = getResourceFeature(name)?.also { coded = false } ?: getCodeFeature(name) ?: return
|
||||
|
||||
+2
-6
@@ -66,16 +66,12 @@ class IntSpeciesFeature(override var name: String) : SynchronizedSpeciesFeature,
|
||||
override fun apply(pokemon: Pokemon) {
|
||||
val featureProvider = SpeciesFeatures.getFeature(name) ?: return
|
||||
if (featureProvider in SpeciesFeatures.getFeaturesFor(pokemon.species)) {
|
||||
var existingFeature = pokemon.getFeature<IntSpeciesFeature>(name)
|
||||
|
||||
val existingFeature = pokemon.getFeature<IntSpeciesFeature>(name)
|
||||
if (existingFeature != null) {
|
||||
existingFeature.value = value
|
||||
} else {
|
||||
existingFeature = IntSpeciesFeature(name, value)
|
||||
pokemon.features.add(existingFeature)
|
||||
pokemon.features.add(IntSpeciesFeature(name, value))
|
||||
}
|
||||
|
||||
pokemon.markFeatureDirty(existingFeature)
|
||||
pokemon.updateAspects()
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -60,6 +60,5 @@ object SpeciesFeatureAssignments : JsonDataRegistry<SpeciesFeatureAssignment> {
|
||||
this.assignments.putAll(data)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getFeatures(species: Species) = assignments[species.resourceIdentifier] ?: emptySet()
|
||||
}
|
||||
@@ -68,19 +68,14 @@ object SpeciesFeatures : JsonDataRegistry<SpeciesFeatureProvider<*>> {
|
||||
data.forEach(this::registerFromAssets)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getCodeFeature(name: String) = codeFeatures[name]
|
||||
@JvmStatic
|
||||
fun getResourceFeature(name: String) = resourceFeatures[name]
|
||||
@JvmStatic
|
||||
fun getFeature(name: String) = getCodeFeature(name) ?: getResourceFeature(name) ?: GlobalSpeciesFeatures.getFeature(name)
|
||||
fun loadOnClient(entries: Collection<Map.Entry<String, SpeciesFeatureProvider<*>>>) {
|
||||
codeFeatures.putAll(entries.map { it.toPair() })
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getFeatures() = (resourceFeatures.keys + codeFeatures.keys).mapNotNull(this::getFeature)
|
||||
@JvmStatic
|
||||
fun getFeaturesFor(species: Species): List<SpeciesFeatureProvider<*>> {
|
||||
val mentionedFeatures = species.features.mapNotNull(this::getFeature)
|
||||
val globalFeatures = GlobalSpeciesFeatures.getFeatures()
|
||||
@@ -100,11 +95,9 @@ object SpeciesFeatures : JsonDataRegistry<SpeciesFeatureProvider<*>> {
|
||||
mapping[name] = provider
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun register(name: String, provider: SpeciesFeatureProvider<*>) = register(name, provider, isCoded = true)
|
||||
private fun registerFromAssets(identifier: ResourceLocation, provider: SpeciesFeatureProvider<*>) = register(identifier.path, provider, isCoded = false)
|
||||
|
||||
@JvmStatic
|
||||
fun unregister(name: String) {
|
||||
var coded = true
|
||||
val value = getResourceFeature(name)?.also { coded = false } ?: getCodeFeature(name) ?: return
|
||||
|
||||
-17
@@ -1,17 +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.pokemon.feature
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
|
||||
interface TickingSpeciesFeature {
|
||||
fun onSecondPassed(world: ServerLevel, pokemon: Pokemon, entity: PokemonEntity?)
|
||||
}
|
||||
-7
@@ -29,7 +29,6 @@ object HeldItemProvider {
|
||||
* @param pokemon The [Pokemon] being queried.
|
||||
* @return The [HeldItemManager] that can provide for the given [pokemon], if non match returns the [HeldItemManager.EMPTY].
|
||||
*/
|
||||
@JvmStatic
|
||||
fun provide(pokemon: BattlePokemon): HeldItemManager = this.managers.firstOrNull { manager -> manager.showdownId(pokemon) != null } ?: HeldItemManager.EMPTY
|
||||
|
||||
/**
|
||||
@@ -38,7 +37,6 @@ object HeldItemProvider {
|
||||
* @param pokemon The [Pokemon] being queried.
|
||||
* @return The showdownId string that [pokemon] is holding, otherwise null.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun provideShowdownId(pokemon: BattlePokemon) = this.managers.firstNotNullOfOrNull { manager -> manager.showdownId(pokemon) }
|
||||
|
||||
/**
|
||||
@@ -47,8 +45,6 @@ object HeldItemProvider {
|
||||
* @param manager The [HeldItemManager] being registered.
|
||||
* @param priority The [Priority] to register it under.
|
||||
*/
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun register(manager: HeldItemManager, priority: Priority = Priority.NORMAL) {
|
||||
this.managers.add(priority, manager)
|
||||
}
|
||||
@@ -60,8 +56,6 @@ object HeldItemProvider {
|
||||
* @param priority The [Priority] to specifically remove the instance from, if null it will remove from all.
|
||||
*/
|
||||
@Suppress("unused")
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun unregister(manager: HeldItemManager, priority: Priority? = null) {
|
||||
if (priority != null) {
|
||||
this.managers.remove(priority, manager)
|
||||
@@ -75,7 +69,6 @@ object HeldItemProvider {
|
||||
*
|
||||
* @return The read-only copy of the registered [HeldItemManager]s.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun managers(): List<HeldItemManager> = this.managers.toList()
|
||||
|
||||
}
|
||||
@@ -34,24 +34,17 @@ object Statuses {
|
||||
private val volatileStatuses = mutableListOf<Status>()
|
||||
private val allStatuses = mutableListOf<Status>()
|
||||
|
||||
@JvmField
|
||||
val POISON = registerStatus(PoisonStatus())
|
||||
@JvmField
|
||||
val POISON_BADLY = registerStatus(PoisonBadlyStatus())
|
||||
@JvmField
|
||||
val PARALYSIS = registerStatus(ParalysisStatus())
|
||||
@JvmField
|
||||
val SLEEP = registerStatus(SleepStatus())
|
||||
@JvmField
|
||||
val FROZEN = registerStatus(FrozenStatus())
|
||||
@JvmField
|
||||
val BURN = registerStatus(BurnStatus())
|
||||
@JvmField
|
||||
val ATTRACT = registerStatus(AttractStatus())
|
||||
@JvmField
|
||||
val CONFUSE = registerStatus(ConfuseStatus())
|
||||
|
||||
@JvmStatic
|
||||
|
||||
|
||||
fun <T: Status> registerStatus(status: T) : T {
|
||||
if (status is PersistentStatus) {
|
||||
persistentStatuses.add(status)
|
||||
@@ -63,10 +56,7 @@ object Statuses {
|
||||
return status
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getStatus(name: ResourceLocation) = allStatuses.find { status -> status.name == name }
|
||||
@JvmStatic
|
||||
fun getStatus(showdownName: String) = allStatuses.find { it.showdownName == showdownName }
|
||||
@JvmStatic
|
||||
fun getPersistentStatuses() = persistentStatuses
|
||||
}
|
||||
@@ -17,7 +17,6 @@ import com.cobblemon.mod.common.api.reactive.pipes.StopAfterTransform
|
||||
import com.cobblemon.mod.common.api.reactive.pipes.TakeFirstTransform
|
||||
import java.lang.Thread.sleep
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import java.util.function.Consumer
|
||||
|
||||
/**
|
||||
* An object that emits values of the generic type. This can be subscribed to and unsubscribed from, as well as
|
||||
@@ -31,8 +30,6 @@ import java.util.function.Consumer
|
||||
*/
|
||||
interface Observable<T> {
|
||||
fun subscribe(priority: Priority = Priority.NORMAL, handler: (T) -> Unit): ObservableSubscription<T>
|
||||
fun subscribe(handler: Consumer<T>): ObservableSubscription<T> = subscribe(Priority.NORMAL) { handler.accept(it) }
|
||||
fun subscribe(priority: Priority, handler: Consumer<T>): ObservableSubscription<T> = subscribe(priority) { handler.accept(it) }
|
||||
fun unsubscribe(subscription: ObservableSubscription<T>)
|
||||
|
||||
// This isn't pretty, ik
|
||||
|
||||
+3
-15
@@ -8,9 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.behaviour
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.sound.RideSoundSettingsList
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
@@ -21,6 +18,7 @@ import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import kotlin.math.abs
|
||||
|
||||
/**
|
||||
* Represents the behaviour of a Pokemon when being ridden.
|
||||
@@ -78,6 +76,8 @@ interface RidingBehaviour<Settings : RidingBehaviourSettings, State : RidingBeha
|
||||
|
||||
fun useAngVelSmoothing(settings: Settings, state: State, vehicle: PokemonEntity): Boolean
|
||||
|
||||
fun useRidingAltPose(settings: Settings, state: State, vehicle: PokemonEntity, driver: Player): ResourceLocation
|
||||
|
||||
fun inertia(settings: Settings, state: State, vehicle: PokemonEntity): Double
|
||||
|
||||
fun shouldRoll(settings: Settings, state: State, vehicle: PokemonEntity): Boolean
|
||||
@@ -116,18 +116,6 @@ interface RidingBehaviour<Settings : RidingBehaviourSettings, State : RidingBeha
|
||||
*/
|
||||
fun mouseModifiesDriverRotation(settings: Settings, state: State, vehicle: PokemonEntity): Pair<Boolean, Boolean> = Pair(false, false)
|
||||
|
||||
/**
|
||||
* Used in MoLang functions for querying states for animations or other magical MoLang effects.
|
||||
*/
|
||||
fun asMoLangValue(settings: Settings, state: State, vehicle: PokemonEntity): ObjectValue<RidingBehaviour<Settings, State>> {
|
||||
val value = ObjectValue(
|
||||
this
|
||||
)
|
||||
value.functions.put("ride_velocity") { state.rideVelocity.get().asMoLangValue() }
|
||||
value.functions.put("stamina") { DoubleValue(state.stamina.get()) }
|
||||
return value
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal helpers to help behaviour specific calculations
|
||||
*/
|
||||
|
||||
+1
@@ -53,6 +53,7 @@ open class RidingBehaviourState {
|
||||
rideVelocity.set(buffer.readVec3(), true)
|
||||
stamina.set(buffer.readFloat(), true)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun <T> ridingState(value: T, side: Side) = SidedRidingState(value, side)
|
||||
|
||||
+1
-3
@@ -39,15 +39,13 @@ object RidingBehaviours {
|
||||
register(CompositeBehaviour.KEY, CompositeBehaviour())
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun register(key: ResourceLocation, behaviour: RidingBehaviour<out RidingBehaviourSettings, out RidingBehaviourState>) {
|
||||
if (behaviours.contains(key)) error("Behaviour already registered to key $key")
|
||||
behaviours[key] = behaviour as RidingBehaviour<RidingBehaviourSettings, RidingBehaviourState>
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun get(key: ResourceLocation): RidingBehaviour<RidingBehaviourSettings, RidingBehaviourState> {
|
||||
if (!behaviours.contains(key)) error("Behaviour not registered to key $key")
|
||||
return behaviours[key]!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-10
@@ -19,9 +19,7 @@ import net.minecraft.world.entity.LivingEntity
|
||||
import kotlin.collections.get
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import kotlin.collections.get
|
||||
import kotlin.math.max
|
||||
|
||||
/**
|
||||
* Small wrapper around a RidingBehaviour to provide sane defaults in the event that the behaviour is not active.
|
||||
@@ -51,11 +49,6 @@ class RidingController(
|
||||
fun tick() {
|
||||
if (entity.ticksLived - lastTransitionAge < 10) return
|
||||
val newTransition = checkForNewTransition(entity.controllingPassenger)
|
||||
// If transitioning to air then give an upward boost
|
||||
if (newTransition == RidingStyle.AIR && context?.style != RidingStyle.AIR && context?.state != null) {
|
||||
val currVel = context!!.state.rideVelocity.get()
|
||||
context!!.state.rideVelocity.set(Vec3(currVel.x, max(0.1, currVel.y), currVel.z))
|
||||
}
|
||||
val behaviourSettings = entity.pokemon.riding.behaviours?.get(newTransition)
|
||||
if (newTransition != context?.style) {
|
||||
if (newTransition != null && behaviourSettings != null) {
|
||||
@@ -118,9 +111,8 @@ class RidingController(
|
||||
|
||||
private fun canTransitionToLand(): Boolean {
|
||||
val hasLandController = entity.pokemon.riding.behaviours?.get(RidingStyle.LAND) != null
|
||||
if (!hasLandController) return false
|
||||
if ((entity.isUnderWater)) return false
|
||||
if ((entity.isEyeInFluid(FluidTags.WATER) || entity.isEyeInFluid(FluidTags.LAVA))) return false
|
||||
if (hasLandController && (entity.isInLiquid || entity.isUnderWater)) return false
|
||||
if (!hasLandController && (entity.isEyeInFluid(FluidTags.WATER) || entity.isEyeInFluid(FluidTags.LAVA))) return false
|
||||
return entity.onGround()
|
||||
}
|
||||
|
||||
|
||||
+17
-16
@@ -10,10 +10,9 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.air
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.MoLangMath.lerp
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.orientation.OrientationController
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.*
|
||||
@@ -34,6 +33,7 @@ import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import org.joml.Vector3f
|
||||
import kotlin.math.*
|
||||
|
||||
@@ -55,7 +55,7 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
get() = CobblemonRideSettings.bird
|
||||
|
||||
override fun isActive(settings: BirdSettings, state: BirdState, vehicle: PokemonEntity): Boolean {
|
||||
return !(vehicle.isUnderWater)
|
||||
return !(vehicle.isInWater || vehicle.isUnderWater)
|
||||
}
|
||||
|
||||
override fun pose(settings: BirdSettings, state: BirdState, vehicle: PokemonEntity): PoseType {
|
||||
@@ -291,10 +291,10 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
val handling = vehicle.runtime.resolveDouble(settings.handlingExpr ?: globalBird.handlingExpr!!)
|
||||
|
||||
val yawDeltaDeg = deltaTime * handling * sin(Math.toRadians(controller.roll.toDouble()))
|
||||
val trueYawDelt = yawDeltaDeg * abs(cos(Math.toRadians(controller.pitch.toDouble()))).coerceIn(-1.0, 1.0)
|
||||
val trueYawDelt = yawDeltaDeg * abs(cos(Math.toRadians(controller.pitch.toDouble()))*2).coerceIn(-1.0, 1.0)
|
||||
|
||||
// Dampen yaw when upside down
|
||||
val yawDampen = (1 - abs(min(cos(controller.roll.toRadians()),0.0f)))
|
||||
val yawDampen = (1 - abs(min(cos(controller.roll.toRadians()),0.0f)).pow(2))
|
||||
controller.applyGlobalYaw(trueYawDelt.toFloat() * yawDampen)
|
||||
|
||||
// Correct orientation when at low speeds
|
||||
@@ -550,6 +550,18 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: BirdSettings,
|
||||
state: BirdState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
if (state.gliding.get()) {
|
||||
return cobblemonResource("gliding")
|
||||
}
|
||||
return cobblemonResource("no_pose")
|
||||
}
|
||||
|
||||
override fun inertia(settings: BirdSettings, state: BirdState, vehicle: PokemonEntity): Double {
|
||||
return 0.5
|
||||
}
|
||||
@@ -602,17 +614,6 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
}
|
||||
|
||||
override fun createDefaultState(settings: BirdSettings) = BirdState()
|
||||
|
||||
override fun asMoLangValue(
|
||||
settings: BirdSettings,
|
||||
state: BirdState,
|
||||
vehicle: PokemonEntity
|
||||
): ObjectValue<RidingBehaviour<BirdSettings, BirdState>> {
|
||||
val value = super.asMoLangValue(settings, state, vehicle)
|
||||
value.functions.put("gliding") { DoubleValue(state.gliding.get()) }
|
||||
value.functions.put("last_glide") { DoubleValue(state.lastGlide.get()) }
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
class BirdSettings : RidingBehaviourSettings {
|
||||
|
||||
+11
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types.air
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
@@ -23,6 +24,7 @@ import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
@@ -153,6 +155,15 @@ class GliderBehaviour : RidingBehaviour<GliderSettings, RidingBehaviourState> {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: GliderSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
return cobblemonResource("no_pose")
|
||||
}
|
||||
|
||||
override fun inertia(settings: GliderSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Double {
|
||||
return 0.5
|
||||
}
|
||||
|
||||
+10
@@ -33,6 +33,7 @@ import kotlin.math.abs
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sin
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
@@ -245,6 +246,15 @@ class HelicopterBehaviour : RidingBehaviour<HelicopterSettings, RidingBehaviourS
|
||||
return true
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: HelicopterSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
return cobblemonResource("no_pose")
|
||||
}
|
||||
|
||||
override fun inertia(settings: HelicopterSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Double {
|
||||
return 0.1
|
||||
}
|
||||
|
||||
+29
-21
@@ -9,9 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types.air
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.*
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseOption
|
||||
@@ -25,6 +23,7 @@ import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@@ -33,6 +32,7 @@ import net.minecraft.world.level.ClipContext
|
||||
import net.minecraft.world.phys.HitResult
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import org.joml.Matrix3f
|
||||
import kotlin.math.*
|
||||
|
||||
@@ -59,8 +59,18 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
|
||||
state: HoverState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
// Hover mounts should be able to go just about anywhere but underwater
|
||||
return !vehicle.isUnderWater
|
||||
return Shapes.create(vehicle.boundingBox).blockPositionsAsListRounded().any {
|
||||
//Need to check other fluids
|
||||
if (vehicle.isInWater || vehicle.isUnderWater) {
|
||||
return@any false
|
||||
}
|
||||
//This might not actually work, depending on what the yPos actually is. yPos of the middle of the entity? the feet?
|
||||
if (it.y.toDouble() == (vehicle.position().y)) {
|
||||
val blockState = vehicle.level().getBlockState(it.below())
|
||||
return@any !blockState.isAir && blockState.fluidState.isEmpty
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override fun pose(
|
||||
@@ -156,7 +166,6 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
|
||||
driver: LivingEntity
|
||||
): Vec2 {
|
||||
val turnAmount = calcRotAmount(settings, state, vehicle, driver)
|
||||
state.rideVelocity.set( state.rideVelocity.get().yRot(turnAmount.toRadians()))
|
||||
return Vec2(driver.xRot, vehicle.yRot + turnAmount )
|
||||
}
|
||||
|
||||
@@ -198,7 +207,6 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
|
||||
input: Vec3
|
||||
): Vec3 {
|
||||
val retVel = calculateRideSpaceVel(settings, state, vehicle, driver)
|
||||
state.rideVelocity.set(retVel)
|
||||
return retVel
|
||||
}
|
||||
|
||||
@@ -220,8 +228,8 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
|
||||
}
|
||||
|
||||
// align the velocity vector to be in local vehicle space
|
||||
// val yawAligned = Matrix3f().rotateY(vehicle.yRot.toRadians())
|
||||
// newVelocity = (newVelocity.toVector3f().mul(yawAligned)).toVec3d()
|
||||
val yawAligned = Matrix3f().rotateY(vehicle.yRot.toRadians())
|
||||
newVelocity = (newVelocity.toVector3f().mul(yawAligned)).toVec3d()
|
||||
|
||||
// Vertical movement based on driver input.
|
||||
val vertInput = when {
|
||||
@@ -267,6 +275,9 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
|
||||
// Check to see if this new velocity will exceed top speed and if it will then cap it
|
||||
newVelocity = if (newVelocity.length() > topSpeed) newVelocity.normalize().scale(topSpeed) else newVelocity
|
||||
|
||||
val revertYawAligned = Matrix3f().rotateY(-vehicle.yRot.toRadians())
|
||||
state.rideVelocity.set((newVelocity.toVector3f().mul(revertYawAligned)).toVec3d())
|
||||
|
||||
return newVelocity
|
||||
}
|
||||
|
||||
@@ -350,6 +361,15 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: HoverSettings,
|
||||
state: HoverState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
return cobblemonResource("no_pose")
|
||||
}
|
||||
|
||||
override fun inertia(
|
||||
settings: HoverSettings,
|
||||
state: HoverState,
|
||||
@@ -395,7 +415,7 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
|
||||
state: HoverState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getRideSounds(
|
||||
@@ -407,18 +427,6 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
|
||||
}
|
||||
|
||||
override fun createDefaultState(settings: HoverSettings) = HoverState()
|
||||
|
||||
override fun asMoLangValue(
|
||||
settings: HoverSettings,
|
||||
state: HoverState,
|
||||
vehicle: PokemonEntity
|
||||
): ObjectValue<RidingBehaviour<HoverSettings, HoverState>> {
|
||||
val value = super.asMoLangValue(settings, state, vehicle)
|
||||
value.functions.put("boosting") { DoubleValue(state.isBoosting.get()) }
|
||||
value.functions.put("boost_ticks") { DoubleValue(state.boostTicks.get()) }
|
||||
value.functions.put("too_high") { DoubleValue(state.tooHigh.get()) }
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
class HoverSettings : RidingBehaviourSettings {
|
||||
|
||||
+19
-34
@@ -10,10 +10,9 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.air
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.MoLangMath.lerp
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
|
||||
@@ -41,6 +40,7 @@ import kotlin.math.min
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
@@ -72,6 +72,7 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
if (vehicle.isInWater || vehicle.isUnderWater) {
|
||||
return@any false
|
||||
}
|
||||
//This might not actually work, depending on what the yPos actually is. yPos of the middle of the entity? the feet?
|
||||
if (it.y.toDouble() == (vehicle.position().y)) {
|
||||
val blockState = vehicle.level().getBlockState(it.below())
|
||||
return@any !(!blockState.isAir && blockState.fluidState.isEmpty)
|
||||
@@ -167,8 +168,8 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
calculateRideSpaceVel(settings, state, vehicle, driver)
|
||||
|
||||
// The downward force used to encourage players to stop flying upside down.
|
||||
val penaltyDeccel = vehicle.runtime.resolveDouble(settings.maxDownwardForceSeconds ?: globalJet.maxDownwardForceSeconds!!).toFloat() * 20.0f
|
||||
val extraDownwardForce = if(state.stamina.get() == 0.0f) -0.3 * (state.noStamTickCnt.get() / penaltyDeccel).coerceIn(0.0f, 1.0f) else 0.0 // 6 blocks a second downward
|
||||
val maxDownwardForceTickCnt = 20.0
|
||||
val extraDownwardForce = if(state.stamina.get() == 0.0f) -0.3 * (state.noStamTickCnt.get() / maxDownwardForceTickCnt).coerceIn(0.0, 1.0) else 0.0 // 6 blocks a second downward
|
||||
|
||||
// Convert the local velocity vector into a world vector
|
||||
val localVelVec = Vector3f(
|
||||
@@ -177,10 +178,7 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
state.rideVelocity.get().z.toFloat() * -1.0f // Flip the z axis to make this left handed? orr.. right handed? idk, flip it though
|
||||
)
|
||||
var worldVelVec = localVelVec.mul(controller.orientation).toVec3d().yRot(vehicle.yRot.toRadians()) // Unrotate preemptively as this vector gets rotate later down the line in MC logic.
|
||||
worldVelVec = Vec3(
|
||||
worldVelVec.x,
|
||||
worldVelVec.y * (1 - (state.noStamTickCnt.get() / penaltyDeccel).coerceIn(0.0f, 1.0f)), // Dampen the upwards movement depending on stamina depletion time
|
||||
worldVelVec.z).add(0.0, extraDownwardForce, 0.0) // Add the stamina depletion force to bring the ride down.
|
||||
worldVelVec = worldVelVec.add(0.0, extraDownwardForce, 0.0) // Add the stamina depletion force to bring the ride down.
|
||||
|
||||
return worldVelVec
|
||||
}
|
||||
@@ -200,8 +198,6 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
val minSpeed = topSpeed * vehicle.runtime.resolveDouble(settings.minSpeedFactor ?: globalJet.minSpeedFactor!!)
|
||||
val speed = state.rideVelocity.get().z
|
||||
val boostMult = vehicle.runtime.resolveDouble(settings.jumpExpr ?: globalJet.jumpExpr!!)
|
||||
val maxNoStamickCnt = vehicle.runtime.resolveDouble(settings.maxDownwardForceSeconds ?: globalJet.maxDownwardForceSeconds!!).toFloat() * 20.0f
|
||||
|
||||
|
||||
val boostTopSpeed = topSpeed * boostMult
|
||||
val boostAccel = accel * boostMult
|
||||
@@ -209,15 +205,11 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
//speed up and slow down based on input
|
||||
if (state.stamina.get() == 0.0f) {
|
||||
// Decelerate currently always a constant half of max acceleration.
|
||||
|
||||
// Increase penalty deccel when stamina has been depleted for a while.
|
||||
val penaltyDeccel = deccel * (state.noStamTickCnt.get() / maxNoStamickCnt).coerceIn(0.0f, 1.0f)
|
||||
val minPenaltySpeed = minSpeed
|
||||
state.rideVelocity.set(
|
||||
Vec3(
|
||||
state.rideVelocity.get().x,
|
||||
state.rideVelocity.get().y,
|
||||
max(state.rideVelocity.get().z - (penaltyDeccel), minPenaltySpeed)
|
||||
max(state.rideVelocity.get().z - (deccel * 1.3), 0.3 * 0.5)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -329,7 +321,7 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
// Have accumulated input begin decay when no input detected
|
||||
if (abs(mouseX) == 0.0) {
|
||||
// Have decay on roll be much stronger.
|
||||
state.currMouseXForce.set(lerp(state.currMouseXForce.get(), 0.0, 0.02))
|
||||
state.currMouseXForce.set(lerp(state.currMouseXForce.get(), 0.0, 0.08))
|
||||
}
|
||||
if (mouseY == 0.0) {
|
||||
state.currMouseYForce.set(lerp(state.currMouseYForce.get(), 0.0, 0.02))
|
||||
@@ -382,9 +374,9 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
val penaltyDeccel = vehicle.runtime.resolveDouble(settings.maxDownwardForceSeconds ?: globalJet.maxDownwardForceSeconds!!).toFloat() * 20.0f
|
||||
val maxDownwardForceTickCnt = 20.0f
|
||||
return when {
|
||||
state.noStamTickCnt.get() != 0 -> 1f - 0.2f*(state.noStamTickCnt.get() / penaltyDeccel).coerceIn(0.0f,1.0f)
|
||||
state.noStamTickCnt.get() != 0 -> 1f - 0.2f*(state.noStamTickCnt.get() / maxDownwardForceTickCnt).coerceIn(0.0f,1.0f)
|
||||
state.boosting.get() -> 1.2f
|
||||
else -> 1.0f
|
||||
}
|
||||
@@ -394,6 +386,15 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: JetSettings,
|
||||
state: JetState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
return cobblemonResource("no_pose")
|
||||
}
|
||||
|
||||
override fun inertia(settings: JetSettings, state: JetState, vehicle: PokemonEntity): Double {
|
||||
return 1.0
|
||||
}
|
||||
@@ -445,17 +446,6 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
val impactSpeed = impactVec.horizontalDistance().toFloat() * 10f
|
||||
return vehicle.causeFallDamage(impactSpeed, 1f, vehicle.damageSources().flyIntoWall())
|
||||
}
|
||||
|
||||
override fun asMoLangValue(
|
||||
settings: JetSettings,
|
||||
state: JetState,
|
||||
vehicle: PokemonEntity
|
||||
): ObjectValue<RidingBehaviour<JetSettings, JetState>> {
|
||||
val value = super.asMoLangValue(settings, state, vehicle)
|
||||
value.functions.put("boosting") { DoubleValue(state.boosting.get()) }
|
||||
value.functions.put("can_speed_burst") { DoubleValue(state.canSpeedBurst.get()) }
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
class JetSettings : RidingBehaviourSettings {
|
||||
@@ -496,9 +486,6 @@ class JetSettings : RidingBehaviourSettings {
|
||||
var staminaExpr: Expression? = null
|
||||
private set
|
||||
|
||||
var maxDownwardForceSeconds: Expression? = null
|
||||
private set
|
||||
|
||||
var rideSounds: RideSoundSettingsList = RideSoundSettingsList()
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
@@ -514,7 +501,6 @@ class JetSettings : RidingBehaviourSettings {
|
||||
buffer.writeNullableExpression(speedExpr)
|
||||
buffer.writeNullableExpression(accelerationExpr)
|
||||
buffer.writeNullableExpression(staminaExpr)
|
||||
buffer.writeNullableExpression(maxDownwardForceSeconds)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
@@ -530,7 +516,6 @@ class JetSettings : RidingBehaviourSettings {
|
||||
speedExpr = buffer.readNullableExpression()
|
||||
accelerationExpr = buffer.readNullableExpression()
|
||||
staminaExpr = buffer.readNullableExpression()
|
||||
maxDownwardForceSeconds = buffer.readNullableExpression()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+24
-15
@@ -10,9 +10,7 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.air
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.MoLangMath.lerp
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.*
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseOption
|
||||
@@ -26,12 +24,14 @@ import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import org.joml.Matrix3f
|
||||
import kotlin.math.*
|
||||
|
||||
@@ -58,7 +58,18 @@ class RocketBehaviour : RidingBehaviour<RocketSettings, RocketState> {
|
||||
state: RocketState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return !((vehicle.isInWater || vehicle.isUnderWater) || vehicle.onGround())
|
||||
return Shapes.create(vehicle.boundingBox).blockPositionsAsListRounded().any {
|
||||
//Need to check other fluids
|
||||
if (vehicle.isInWater || vehicle.isUnderWater) {
|
||||
return@any false
|
||||
}
|
||||
//This might not actually work, depending on what the yPos actually is. yPos of the middle of the entity? the feet?
|
||||
if (it.y.toDouble() == (vehicle.position().y)) {
|
||||
val blockState = vehicle.level().getBlockState(it.below())
|
||||
return@any !blockState.isAir && blockState.fluidState.isEmpty
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override fun pose(
|
||||
@@ -411,6 +422,15 @@ class RocketBehaviour : RidingBehaviour<RocketSettings, RocketState> {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: RocketSettings,
|
||||
state: RocketState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
return cobblemonResource("no_pose")
|
||||
}
|
||||
|
||||
override fun inertia(
|
||||
settings: RocketSettings,
|
||||
state: RocketState,
|
||||
@@ -456,7 +476,7 @@ class RocketBehaviour : RidingBehaviour<RocketSettings, RocketState> {
|
||||
state: RocketState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -480,17 +500,6 @@ class RocketBehaviour : RidingBehaviour<RocketSettings, RocketState> {
|
||||
}
|
||||
|
||||
override fun createDefaultState(settings: RocketSettings) = RocketState()
|
||||
|
||||
override fun asMoLangValue(
|
||||
settings: RocketSettings,
|
||||
state: RocketState,
|
||||
vehicle: PokemonEntity
|
||||
): ObjectValue<RidingBehaviour<RocketSettings, RocketState>> {
|
||||
val value = super.asMoLangValue(settings, state, vehicle)
|
||||
value.functions.put("boosting") { DoubleValue(state.boosting.get()) }
|
||||
value.functions.put("can_speed_burst") { DoubleValue(state.canSpeedBurst.get()) }
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
class RocketSettings : RidingBehaviourSettings {
|
||||
|
||||
+11
@@ -170,6 +170,17 @@ class CompositeBehaviour : RidingBehaviour<CompositeSettings, CompositeState> {
|
||||
}
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: CompositeSettings,
|
||||
state: CompositeState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
return chooseBehaviour(settings, state) { behaviour, behaviourSettings, behaviourState ->
|
||||
behaviour.useRidingAltPose(behaviourSettings, behaviourState, vehicle, driver)
|
||||
}
|
||||
}
|
||||
|
||||
override fun useAngVelSmoothing(
|
||||
settings: CompositeSettings,
|
||||
state: CompositeState,
|
||||
|
||||
+26
-50
@@ -9,9 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types.land
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
|
||||
@@ -33,7 +31,6 @@ import com.cobblemon.mod.common.util.resolveDouble
|
||||
import com.cobblemon.mod.common.util.resolveFloat
|
||||
import com.cobblemon.mod.common.util.writeNullableExpression
|
||||
import com.cobblemon.mod.common.util.writeRidingStats
|
||||
import net.minecraft.client.Minecraft
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
@@ -43,6 +40,7 @@ import kotlin.math.sqrt
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@@ -67,7 +65,7 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
|
||||
val poseProvider = PoseProvider<HorseSettings, HorseState>(PoseType.STAND)
|
||||
.with(PoseOption(PoseType.WALK) { _, state, vehicle ->
|
||||
return@PoseOption state.walking.get()
|
||||
return@PoseOption abs(state.rideVelocity.get().horizontalDistance()) > 0.0
|
||||
})
|
||||
|
||||
override fun isActive(
|
||||
@@ -113,12 +111,9 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
driver: Player,
|
||||
input: Vec3
|
||||
) {
|
||||
if (vehicle.level().isClientSide) {
|
||||
handleSprinting(state)
|
||||
inAirCheck(state, vehicle)
|
||||
tickStamina(settings, state, vehicle)
|
||||
state.walking.set(state.rideVelocity.get().horizontalDistance() > 0.01)
|
||||
}
|
||||
handleSprinting(state, driver)
|
||||
inAirCheck(state, vehicle)
|
||||
tickStamina(settings, state, vehicle)
|
||||
}
|
||||
|
||||
fun inAirCheck(
|
||||
@@ -139,22 +134,15 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
}
|
||||
|
||||
fun handleSprinting(
|
||||
state: HorseState
|
||||
state: HorseState,
|
||||
driver: Player
|
||||
) {
|
||||
val tryingToSprint = Minecraft.getInstance().options.keySprint.isDown() && Minecraft.getInstance().options.keyUp.isDown()
|
||||
|
||||
if (state.stamina.get() <= 0.0f || !Minecraft.getInstance().options.keyUp.isDown()) {
|
||||
// If stamina runs out or the player is not holding forward then stop sprinting
|
||||
state.sprinting.set(false)
|
||||
if (state.stamina.get() <= 0.0f) {
|
||||
state.sprintToggleable.set(false)
|
||||
}
|
||||
} else if (!state.sprinting.get() && !state.sprintToggleable.get() && state.stamina.get() > 0.33f) {
|
||||
// If you are not sprinting and sprint is not toggleable and you're not trying to sprint and stamina is above 0.3 then enable the toggle
|
||||
state.sprintToggleable.set(true)
|
||||
} else if (tryingToSprint && state.sprintToggleable.get()) {
|
||||
// If you are trying to sprint and the toggle allows it then start sprinting and disable toggle
|
||||
state.sprinting.set(true)
|
||||
if (state.sprinting.get()) {
|
||||
state.sprinting.set(driver.isSprinting && state.stamina.get() > 0.0f)
|
||||
} else {
|
||||
// Only allow sprinting to start if over x percentage of stamina left
|
||||
val stamSprintPerc = 25.0f
|
||||
state.sprinting.set(driver.isSprinting && state.stamina.get() > stamSprintPerc / 100.0f)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -472,6 +460,19 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
when {
|
||||
state.inAir.get() -> return cobblemonResource("in_air")
|
||||
state.sprinting.get() -> return cobblemonResource("sprinting")
|
||||
}
|
||||
return cobblemonResource("no_pose")
|
||||
}
|
||||
|
||||
override fun inertia(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
@@ -529,19 +530,6 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
}
|
||||
|
||||
override fun createDefaultState(settings: HorseSettings) = HorseState()
|
||||
|
||||
override fun asMoLangValue(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
vehicle: PokemonEntity
|
||||
): ObjectValue<RidingBehaviour<HorseSettings, HorseState>> {
|
||||
val canJump = vehicle.runtime.resolveBoolean(settings.canJump ?: globalHorse.canJump!!)
|
||||
val value = super.asMoLangValue(settings, state, vehicle)
|
||||
value.functions.put("sprinting") { DoubleValue(state.sprinting.get()) }
|
||||
value.functions.put("walking") { DoubleValue(state.walking.get()) }
|
||||
value.functions.put("in_air") { DoubleValue(state.inAir.get() || (state.rideVelocity.get().y >= 0.0 && (vehicle.controllingPassenger as? Player)?.jumping == true && canJump) || (state.rideVelocity.get().y > 0.0)) }
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
class HorseSettings : RidingBehaviourSettings {
|
||||
@@ -614,16 +602,12 @@ class HorseSettings : RidingBehaviourSettings {
|
||||
|
||||
class HorseState : RidingBehaviourState() {
|
||||
var sprinting = ridingState(false, Side.CLIENT)
|
||||
var walking = ridingState(false, Side.BOTH)
|
||||
var sprintToggleable = ridingState(false, Side.CLIENT)
|
||||
var inAir = ridingState(false, Side.CLIENT)
|
||||
var jumpTicks = ridingState(0, Side.CLIENT)
|
||||
|
||||
override fun encode(buffer: FriendlyByteBuf) {
|
||||
super.encode(buffer)
|
||||
buffer.writeBoolean(sprinting.get())
|
||||
buffer.writeBoolean(walking.get())
|
||||
buffer.writeBoolean(sprintToggleable.get())
|
||||
buffer.writeBoolean(inAir.get())
|
||||
buffer.writeInt(jumpTicks.get())
|
||||
}
|
||||
@@ -631,8 +615,6 @@ class HorseState : RidingBehaviourState() {
|
||||
override fun decode(buffer: FriendlyByteBuf) {
|
||||
super.decode(buffer)
|
||||
sprinting.set(buffer.readBoolean(), forced = true)
|
||||
walking.set(buffer.readBoolean(), forced = true)
|
||||
sprintToggleable.set(buffer.readBoolean(), forced = true)
|
||||
inAir.set(buffer.readBoolean(), forced = true)
|
||||
jumpTicks.set(buffer.readInt(), forced = true)
|
||||
}
|
||||
@@ -640,8 +622,6 @@ class HorseState : RidingBehaviourState() {
|
||||
override fun reset() {
|
||||
super.reset()
|
||||
sprinting.set(false, forced = true)
|
||||
walking.set(false, forced = true)
|
||||
sprintToggleable.set(false, forced = true)
|
||||
inAir.set(false, forced = true)
|
||||
jumpTicks.set(0, forced = true)
|
||||
}
|
||||
@@ -650,8 +630,6 @@ class HorseState : RidingBehaviourState() {
|
||||
it.rideVelocity.set(this.rideVelocity.get(), forced = true)
|
||||
it.stamina.set(this.stamina.get(), forced = true)
|
||||
it.sprinting.set(this.sprinting.get(), forced = true)
|
||||
it.walking.set(this.sprinting.get(), forced = true)
|
||||
it.sprintToggleable.set(this.sprintToggleable.get(), forced = true)
|
||||
it.inAir.set(this.inAir.get(), forced = true)
|
||||
it.jumpTicks.set(this.jumpTicks.get(), forced = true)
|
||||
}
|
||||
@@ -659,8 +637,6 @@ class HorseState : RidingBehaviourState() {
|
||||
override fun shouldSync(previous: RidingBehaviourState): Boolean {
|
||||
if (previous !is HorseState) return false
|
||||
if (previous.sprinting.get() != sprinting.get()) return true
|
||||
if (previous.walking.get() != walking.get()) return true
|
||||
if (previous.sprintToggleable.get() != sprintToggleable.get()) return true
|
||||
if (previous.inAir.get() != inAir.get()) return true
|
||||
return super.shouldSync(previous)
|
||||
}
|
||||
|
||||
+13
-15
@@ -10,10 +10,8 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.land
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.MoLangMath.lerp
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
|
||||
@@ -45,6 +43,7 @@ import kotlin.math.sign
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
@@ -395,6 +394,18 @@ class MinekartBehaviour : RidingBehaviour<MinekartSettings, MinekartState> {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: MinekartSettings,
|
||||
state: MinekartState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
when {
|
||||
state.drifting.get() -> return cobblemonResource("drifting")
|
||||
}
|
||||
return cobblemonResource("no_pose")
|
||||
}
|
||||
|
||||
override fun inertia(settings: MinekartSettings, state: MinekartState, vehicle: PokemonEntity): Double {
|
||||
return 1.0
|
||||
}
|
||||
@@ -444,19 +455,6 @@ class MinekartBehaviour : RidingBehaviour<MinekartSettings, MinekartState> {
|
||||
}
|
||||
|
||||
override fun createDefaultState(settings: MinekartSettings) = MinekartState()
|
||||
|
||||
override fun asMoLangValue(
|
||||
settings: MinekartSettings,
|
||||
state: MinekartState,
|
||||
vehicle: PokemonEntity
|
||||
): ObjectValue<RidingBehaviour<MinekartSettings, MinekartState>> {
|
||||
val value = super.asMoLangValue(settings, state, vehicle)
|
||||
value.functions.put("drifiting") { DoubleValue(state.drifting.get()) }
|
||||
value.functions.put("clockwise_drift") { DoubleValue(state.clockwiseDrift.get()) }
|
||||
value.functions.put("boosting") { DoubleValue(state.boost.get()) }
|
||||
value.functions.put("in_air") { DoubleValue(state.inAir.get()) }
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
class MinekartSettings : RidingBehaviourSettings {
|
||||
|
||||
+14
-13
@@ -10,10 +10,8 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.land
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.MoLangMath.lerp
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
|
||||
@@ -44,6 +42,7 @@ import kotlin.math.sign
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
@@ -360,6 +359,19 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: VehicleSettings,
|
||||
state: VehicleState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
when {
|
||||
state.poweredDrifting.get() -> return cobblemonResource("powered_drifting")
|
||||
state.drifting.get() -> return cobblemonResource("drifting")
|
||||
}
|
||||
return cobblemonResource("no_pose")
|
||||
}
|
||||
|
||||
override fun inertia(settings: VehicleSettings, state: VehicleState, vehicle: PokemonEntity): Double {
|
||||
return 1.0
|
||||
}
|
||||
@@ -409,17 +421,6 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
}
|
||||
|
||||
override fun createDefaultState(settings: VehicleSettings) = VehicleState()
|
||||
override fun asMoLangValue(
|
||||
settings: VehicleSettings,
|
||||
state: VehicleState,
|
||||
vehicle: PokemonEntity
|
||||
): ObjectValue<RidingBehaviour<VehicleSettings, VehicleState>> {
|
||||
val value = super.asMoLangValue(settings, state, vehicle)
|
||||
value.functions.put("drifting") { DoubleValue(state.drifting.get()) }
|
||||
value.functions.put("powered_drifting") { DoubleValue(state.poweredDrifting.get()) }
|
||||
value.functions.put("in_air") { DoubleValue(state.inAir.get()) }
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleSettings : RidingBehaviourSettings {
|
||||
|
||||
+18
-21
@@ -9,10 +9,8 @@
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types.liquid
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
|
||||
@@ -39,6 +37,7 @@ import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@@ -338,6 +337,22 @@ class BoatBehaviour : RidingBehaviour<BoatSettings, BoatState> {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: BoatSettings,
|
||||
state: BoatState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
val isInWater = Shapes.create(vehicle.boundingBox).blockPositionsAsListRounded().any {
|
||||
if (vehicle.isInWater || vehicle.isUnderWater) {
|
||||
return@any true
|
||||
}
|
||||
val blockState = vehicle.level().getBlockState(it)
|
||||
return@any !blockState.fluidState.isEmpty
|
||||
}
|
||||
return if (!isInWater) cobblemonResource("in_air") else cobblemonResource("no_pose")
|
||||
}
|
||||
|
||||
override fun inertia(settings: BoatSettings, state: BoatState, vehicle: PokemonEntity): Double {
|
||||
return 0.5
|
||||
}
|
||||
@@ -382,25 +397,6 @@ class BoatBehaviour : RidingBehaviour<BoatSettings, BoatState> {
|
||||
|
||||
override fun createDefaultState(settings: BoatSettings) = BoatState()
|
||||
|
||||
override fun asMoLangValue(
|
||||
settings: BoatSettings,
|
||||
state: BoatState,
|
||||
vehicle: PokemonEntity
|
||||
): ObjectValue<RidingBehaviour<BoatSettings, BoatState>> {
|
||||
val value = super.asMoLangValue(settings, state, vehicle)
|
||||
value.functions.put("sprinting") { DoubleValue(state.isVehicleSprinting.get()) }
|
||||
value.functions.put("in_air") {
|
||||
val isInWater = Shapes.create(vehicle.boundingBox).blockPositionsAsListRounded().any {
|
||||
if (vehicle.isInWater || vehicle.isUnderWater) {
|
||||
return@any true
|
||||
}
|
||||
val blockState = vehicle.level().getBlockState(it)
|
||||
return@any !blockState.fluidState.isEmpty
|
||||
}
|
||||
DoubleValue(!isInWater)
|
||||
}
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
class BoatSettings : RidingBehaviourSettings {
|
||||
@@ -496,4 +492,5 @@ class BoatState : RidingBehaviourState() {
|
||||
if (previous !is BoatState) return false
|
||||
return super.shouldSync(previous)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
-12
@@ -8,10 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types.liquid
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
|
||||
@@ -27,8 +25,10 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.blockPositionsAsListRounded
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readRidingStats
|
||||
import com.cobblemon.mod.common.util.writeNullable
|
||||
import com.cobblemon.mod.common.util.writeRidingStats
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
@@ -190,6 +190,15 @@ class BurstBehaviour : RidingBehaviour<BurstSettings, BurstState> {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: BurstSettings,
|
||||
state: BurstState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
return cobblemonResource("no_pose")
|
||||
}
|
||||
|
||||
override fun inertia(settings: BurstSettings, state: BurstState, vehicle: PokemonEntity): Double {
|
||||
return 0.5
|
||||
}
|
||||
@@ -231,16 +240,6 @@ class BurstBehaviour : RidingBehaviour<BurstSettings, BurstState> {
|
||||
}
|
||||
|
||||
override fun createDefaultState(settings: BurstSettings) = BurstState()
|
||||
|
||||
override fun asMoLangValue(
|
||||
settings: BurstSettings,
|
||||
state: BurstState,
|
||||
vehicle: PokemonEntity
|
||||
): ObjectValue<RidingBehaviour<BurstSettings, BurstState>> {
|
||||
val value = super.asMoLangValue(settings, state, vehicle)
|
||||
value.functions.put("dashing") { DoubleValue(state.dashing.get()) }
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
class BurstSettings : RidingBehaviourSettings {
|
||||
|
||||
+15
-31
@@ -10,10 +10,9 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.liquid
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.MoLangMath.lerp
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.orientation.OrientationController
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
|
||||
@@ -28,8 +27,8 @@ import com.cobblemon.mod.common.api.riding.sound.RideSoundSettingsList
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.blockPositionsAsListRounded
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.math.geometry.toDegrees
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import com.cobblemon.mod.common.util.readNullableExpression
|
||||
import com.cobblemon.mod.common.util.readRidingStats
|
||||
@@ -42,14 +41,13 @@ import kotlin.math.*
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import org.joml.Vector3f
|
||||
|
||||
class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
|
||||
@@ -69,20 +67,7 @@ class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
|
||||
.with(PoseOption(PoseType.SWIM) { _, state, entity -> abs(state.rideVelocity.get().length()) > 0.05 })
|
||||
|
||||
override fun isActive(settings: DolphinSettings, state: DolphinState, vehicle: PokemonEntity): Boolean {
|
||||
// If its in water then the dolphin should definitely be active
|
||||
if (vehicle.isInWater || vehicle.isUnderWater) {
|
||||
return true
|
||||
}
|
||||
|
||||
val blockPosBelow = vehicle.blockPosition().below()
|
||||
val blockState = vehicle.level().getBlockState(blockPosBelow)
|
||||
|
||||
// Check if the block below is solid AND not a fluid
|
||||
val isOnSolidGround = !blockState.isAir && blockState.fluidState.isEmpty
|
||||
|
||||
// The dolphin is only INACTIVE if it is on solid ground.
|
||||
// Therefore, it is ACTIVE if it is NOT on solid ground
|
||||
return !isOnSolidGround
|
||||
return vehicle.isInWater || !vehicle.onGround()
|
||||
}
|
||||
|
||||
override fun pose(settings: DolphinSettings, state: DolphinState, vehicle: PokemonEntity): PoseType {
|
||||
@@ -403,8 +388,8 @@ class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
|
||||
val hoverSpeed = 0.2
|
||||
val pitchDamping = abs(cos(controller.pitch.toRadians())).pow(2) // Helper value used when wanting to discard the influence of another value at steep pitches
|
||||
|
||||
// Yaw locally when at or below topSpeed but not when pitched up or rolled over
|
||||
val globalYaw = xInput * (1 - sqrt(RidingBehaviour.scaleToRange(currSpeed, 0.0, topSpeed))).coerceIn(0.0, 1.0)
|
||||
// Yaw locally when at or below hoverSpeed but not when pitched up or rolled over
|
||||
val globalYaw = xInput * (1 - sqrt(RidingBehaviour.scaleToRange(currSpeed, 0.0, hoverSpeed))).coerceIn(0.0, 1.0)
|
||||
controller.rotateYaw(pitchDamping*globalYaw.toFloat())
|
||||
controller.rotateRoll((1-pitchDamping)*globalYaw.toFloat())
|
||||
|
||||
@@ -491,6 +476,15 @@ class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: DolphinSettings,
|
||||
state: DolphinState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
return cobblemonResource("no_pose")
|
||||
}
|
||||
|
||||
override fun inertia(settings: DolphinSettings, state: DolphinState, vehicle: PokemonEntity): Double {
|
||||
return if (!vehicle.isInWater && !vehicle.isUnderWater) 1.0 else 0.1
|
||||
}
|
||||
@@ -533,16 +527,6 @@ class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
|
||||
|
||||
override fun createDefaultState(settings: DolphinSettings) = DolphinState()
|
||||
|
||||
override fun asMoLangValue(
|
||||
settings: DolphinSettings,
|
||||
state: DolphinState,
|
||||
vehicle: PokemonEntity
|
||||
): ObjectValue<RidingBehaviour<DolphinSettings, DolphinState>> {
|
||||
val value = super.asMoLangValue(settings, state, vehicle)
|
||||
value.functions.put("boosting") { DoubleValue(state.boosting.get()) }
|
||||
value.functions.put("has_breached") { DoubleValue(state.hasBreached.get()) }
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
class DolphinSettings : RidingBehaviourSettings {
|
||||
|
||||
+13
-14
@@ -10,10 +10,8 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.liquid
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.MoLangMath.lerp
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.orientation.OrientationController
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.*
|
||||
@@ -35,6 +33,7 @@ import com.cobblemon.mod.common.util.writeRidingStats
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.tags.FluidTags
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@@ -58,9 +57,9 @@ class SubmarineBehaviour : RidingBehaviour<SubmarineSettings, SubmarineState> {
|
||||
}
|
||||
|
||||
val poseProvider = PoseProvider<SubmarineSettings, SubmarineState>(PoseType.FLOAT)
|
||||
.with(PoseOption(PoseType.SWIM) { _, state, entity -> state.rideVelocity.get().z > 0.05 && !state.onSurface.get()})
|
||||
.with(PoseOption(PoseType.STAND) { _, state, entity -> state.rideVelocity.get().z <= 0.05 && state.onSurface.get()})
|
||||
.with(PoseOption(PoseType.STAND) { _, state, entity -> state.rideVelocity.get().z > 0.05 && state.onSurface.get()})
|
||||
.with(PoseOption(PoseType.SWIM) { _, state, entity -> abs(state.rideVelocity.get().z) > 0.05 && !state.onSurface.get()})
|
||||
.with(PoseOption(PoseType.STAND) { _, state, entity -> abs(state.rideVelocity.get().z) <= 0.05 && state.onSurface.get()})
|
||||
.with(PoseOption(PoseType.STAND) { _, state, entity -> abs(state.rideVelocity.get().z) > 0.05 && state.onSurface.get()})
|
||||
|
||||
override fun isActive(settings: SubmarineSettings, state: SubmarineState, vehicle: PokemonEntity): Boolean {
|
||||
return vehicle.isInWater || !vehicle.onGround()
|
||||
@@ -493,6 +492,15 @@ class SubmarineBehaviour : RidingBehaviour<SubmarineSettings, SubmarineState> {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: SubmarineSettings,
|
||||
state: SubmarineState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
return cobblemonResource("no_pose")
|
||||
}
|
||||
|
||||
override fun inertia(settings: SubmarineSettings, state: SubmarineState, vehicle: PokemonEntity): Double {
|
||||
return if (!vehicle.isUnderWater) 1.0 else 0.1
|
||||
}
|
||||
@@ -539,15 +547,6 @@ class SubmarineBehaviour : RidingBehaviour<SubmarineSettings, SubmarineState> {
|
||||
|
||||
override fun createDefaultState(settings: SubmarineSettings) = SubmarineState()
|
||||
|
||||
override fun asMoLangValue(
|
||||
settings: SubmarineSettings,
|
||||
state: SubmarineState,
|
||||
vehicle: PokemonEntity
|
||||
): ObjectValue<RidingBehaviour<SubmarineSettings, SubmarineState>> {
|
||||
val value = super.asMoLangValue(settings, state, vehicle)
|
||||
value.functions.put("on_surface") { DoubleValue(state.onSurface.get()) }
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
class SubmarineSettings : RidingBehaviourSettings {
|
||||
|
||||
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.api.riding.stats
|
||||
import com.cobblemon.mod.common.api.cooking.Flavour
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
|
||||
/**
|
||||
* 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].
|
||||
@@ -30,9 +29,10 @@ enum class RidingStat(
|
||||
|
||||
companion object {
|
||||
fun getByName(name: String) = RidingStat.entries.firstOrNull { it.name.equals(name, ignoreCase = true) }
|
||||
fun getByFlavour(flavour: Flavour) = RidingStat.entries.firstOrNull { it.flavour == flavour }
|
||||
}
|
||||
|
||||
val displayName: MutableComponent
|
||||
get() = lang("ui.stats.ride.${name.lowercase()}")
|
||||
val displayName: Component
|
||||
get() = lang("riding.stat.${name.lowercase()}.name")
|
||||
val description: Component
|
||||
get() = lang("riding.stat.${name.lowercase()}.desc")
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,6 @@ object CobblemonScripts : DataRegistry {
|
||||
player.sendPacket(ScriptRegistrySyncPacket(clientScripts.entries))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun run(identifier: ResourceLocation, runtime: MoLangRuntime): MoValue? {
|
||||
return scripts[identifier]?.resolve(runtime, runtime.contextOrEmpty)
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import com.cobblemon.mod.common.api.spawning.detail.PokemonHerdSpawnDetail
|
||||
import com.cobblemon.mod.common.api.spawning.detail.PokemonSpawnDetail
|
||||
import com.cobblemon.mod.common.api.spawning.detail.SpawnAction
|
||||
import com.cobblemon.mod.common.api.spawning.detail.SpawnDetail
|
||||
import com.cobblemon.mod.common.api.spawning.influence.BucketMultiplyingInfluence
|
||||
import com.cobblemon.mod.common.api.spawning.influence.SpawningInfluence
|
||||
import com.cobblemon.mod.common.api.spawning.position.AreaSpawnablePositionResolver
|
||||
import com.cobblemon.mod.common.api.spawning.position.FishingSpawnablePosition
|
||||
@@ -142,16 +141,6 @@ object BestSpawner {
|
||||
fishingSpawner = BasicSpawner(
|
||||
name = "fishing",
|
||||
spawnPool = CobblemonSpawnPools.WORLD_SPAWN_POOL
|
||||
).also {
|
||||
it.influences.add(
|
||||
BucketMultiplyingInfluence(
|
||||
multipliers = mapOf(
|
||||
"uncommon" to 2.25f,
|
||||
"rare" to 5.5f,
|
||||
"ultra-rare" to 5.5f,
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@ import net.minecraft.server.packs.PackType
|
||||
* A single spawn pool may be used for many different [Spawner]s. Note that changing the
|
||||
* [details] list will change the spawns for any [Spawner] sharing this pool. If you want
|
||||
* to make a change for a pool specifically to one spawner, take a copy of the pool using
|
||||
* [copy], and change that spawner's pool using [Spawner.spawnPool] setters.
|
||||
* [copy], and change that spawner's pool using [Spawner.setSpawnPool].
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since February 9th, 2022
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user