mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-27 04:26:27 -04:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4550ea590a |
+4
-227
@@ -1,232 +1,8 @@
|
||||
# Changelog
|
||||
## [1.7.0 (Month xth, 2025)](#1-7-0)
|
||||
## [1.6.1 (Release TBD)](#1-6-1)
|
||||
|
||||
### Fixes
|
||||
- Fixed Particles sometimes facing the wrong direction (looking at you, Swords Dance)
|
||||
- Fixed PCs always opening at box 2 instead of box 1.
|
||||
|
||||
### Developer
|
||||
- A finished battle now has winners and losers set inside of `PokemonBattle` instead of them always being empty.
|
||||
- Dialogues are correctly removed from memory when they are stopped.
|
||||
- Dialogues with variably-set initial pages now properly start timeout tracking.
|
||||
|
||||
## [1.6.1 (January 26th, 2025)](#1-6-1)
|
||||
|
||||
### Additions
|
||||
- Added crossover paintings from Close Combat: Premonition, Altar, Slumber, and Nomad.
|
||||
- Added Galarica Nuts, used for crafting Galarica Cuffs and Wreaths. Dropped from certain Pokémon. Take a wild guess which.
|
||||
- Added compatibility with Repurposed Structures. (Thank you, TelepathicGrunt!)
|
||||
- Added an evolution method for Karrablast to evolve into Escavalier in singleplayer.
|
||||
- Pokédexes can now be placed in Chiseled Bookshelves.
|
||||
- Added optional box argument to the /pc command.
|
||||
- Pokédex and Dialogue screens now close when the inventory keybind is pressed.
|
||||
- Added config setting `maxPokedexScanningDetectionRange` to control from what distance the player can scan Pokémon using the Pokédex.
|
||||
- Added config setting `hideUnimplementedPokemonInThePokedex` which hides unimplemented Pokémon from the Pokédex when set to true.
|
||||
- Added debug renderer for posable entity locators.
|
||||
- Added crossover paintings from Close Combat, Premonition, Altar, Slumber, and Nomad.
|
||||
- Added optional box argument to the /pc command
|
||||
|
||||
### Changes
|
||||
- Pokémon will now be dynamically revealed to the Pokédex as they're seen instead of revealing entire parties at the end of battle regardless.
|
||||
- Unseen wild Pokémon will update their name from '???' to their real name as soon as a battle starts to reflect the battle UI showing the actual species name.
|
||||
- Pokémon under the illusion effect will reveal their disguise to the Pokédex first and then the base Pokémon once the disguise is broken.
|
||||
- Added more support for a variety of Fabric/NeoForge Convention tags.
|
||||
- Reformatted some tags to be more consistent.
|
||||
- Edited some recipes to utilize tags instead of direct item ids, for greater mod compatibility.
|
||||
- Berries will drop if broken at age 0
|
||||
- Improved Fortune drops on Mint Seeds
|
||||
- New Slowpoke shiny texture.
|
||||
- Updated drops for many Pokémon.
|
||||
- Completely resynced Pokémon move and stat data based on later games. Learnsets have changed considerably to maximise available moves.
|
||||
- Cobblemon save data now saves .old files where applicable as a means to recover from file corruption due to crashes or similar abrupt stops
|
||||
|
||||
### Pokémon Added
|
||||
|
||||
#### Gen 5
|
||||
- Ducklett
|
||||
- Swanna
|
||||
- Shelmet
|
||||
- Accelgor
|
||||
- Karrablast
|
||||
- Escavalier
|
||||
- Rufflet
|
||||
- Braviary
|
||||
- Foongus
|
||||
- Amoonguss
|
||||
|
||||
#### Gen 6
|
||||
- Binacle
|
||||
- Barbaracle
|
||||
|
||||
#### Gen 7
|
||||
- Dewpider
|
||||
- Araquanid
|
||||
- Alolan Geodude
|
||||
- Alolan Graveler
|
||||
- Alolan Golem
|
||||
|
||||
#### Gen 8
|
||||
- Galarian Slowpoke
|
||||
- Galarian Slowbro
|
||||
- Galarian Slowking
|
||||
|
||||
#### Gen 9
|
||||
- Paldean Tauros
|
||||
|
||||
### Added cries to the following Pokémon
|
||||
- All Nidorans
|
||||
- Shellder, Cloyster
|
||||
- Pinsir
|
||||
- Tyrogue, Hitmontop
|
||||
- Spinda
|
||||
|
||||
### Animation updates for the following Pokémon
|
||||
- Primeape
|
||||
- Munchlax
|
||||
- Snorlax
|
||||
- Poliwrath
|
||||
- Goldeen
|
||||
- Seaking
|
||||
- Dondozo
|
||||
- Wobbuffet
|
||||
- Charcadet
|
||||
- Armarouge
|
||||
- Ceruledge
|
||||
- Geodude
|
||||
- Graveler
|
||||
- Golem
|
||||
- Sandile
|
||||
- Krokorok
|
||||
- Krookodile
|
||||
|
||||
### Model updates for the following Pokémon
|
||||
- Slowpoke
|
||||
- Slowbro
|
||||
- Slowking
|
||||
- Eiscue
|
||||
- Tauros
|
||||
- Goldeen
|
||||
- Seaking
|
||||
- Charcadet
|
||||
- Armarouge
|
||||
- Ceruledge
|
||||
- Pinsir
|
||||
- Geodude
|
||||
- Graveler
|
||||
- Golem
|
||||
|
||||
### Cry updates for the following Pokémon
|
||||
- Sceptile
|
||||
|
||||
### Changes
|
||||
- Completely re-synced Pokémon move and stat data based on later games. Learnsets have changed considerably to maximise available moves.
|
||||
- Pokémon will now be dynamically revealed to the Pokédex as they're seen in battle instead of revealing entire parties at the end of battle.
|
||||
- Unseen wild Pokémon will update their name from '???' to their real name as soon as a battle starts to match how the battle UI shows the actual species name.
|
||||
- Pokémon under the illusion effect will reveal their disguise to the Pokédex first and then the base Pokémon once the disguise is broken.
|
||||
- Berries will now drop from berry trees if broken at age 0 so you aren't punished for mistaken planting.
|
||||
- Increased Fortune drops on Mint Seeds.
|
||||
- Updated Slowpoke's shiny texture.
|
||||
- Updated drops for many Pokémon.
|
||||
- Adjusted the evolution sound to match the timing of the particle effect.
|
||||
- Made berry trees shear-able by dispenser blocks. I'm sure nobody will make unholy contraptions with this.
|
||||
- Edited some recipes to utilize tags instead of direct item IDs, for better mod compatibility.
|
||||
- Added more support for a variety of Fabric/NeoForge conventional tags.
|
||||
- Reformatted some tags to be more consistent.
|
||||
|
||||
### Fixes
|
||||
- Fixed Pokédex sometimes crashing when switching forms.
|
||||
- Fixed Pokédex interface not transitioning out when closed.
|
||||
- Fixed texture dimensions for the player and Pokémon interact interface.
|
||||
- Fixed crash related to Tom's Simple Storage mod and the Fossil Machine.
|
||||
- Fixed not being able to retrieve a fossil from the Fossil Machine with an empty hand.
|
||||
- Fixed Pokémon being collidable (collidible? collissionable? kaleidoscopable?) while being captured by a Poké Ball.
|
||||
- Fixed `full_party`, `own_zangoose_seviper`, `use_revive` and `use_candy` Advancement triggers.
|
||||
- Fixed `healing_machine` Advancement by using the correct 1.21 trigger.
|
||||
- Fix Display Cases not dropping items if destroyed through explosions.
|
||||
- Fixed an issue where the first Pokémon in the pastured Pokémon list clipped into the interface.
|
||||
- Fixed all Pokémon facing South on spawn.
|
||||
- Fixed bait being consumed even when not reeling in any Pokémon.
|
||||
- Fixed Miltank milk magically disappearing out of your bucket.
|
||||
- Fixed Pokémon nicknames migrating from 1.5.2 not being displayed properly.
|
||||
- Fixed capitalization in one of our config options. It was a very important fix. Very important. Old configs are fine.
|
||||
- Fixed Poké Rods not working if Lure or Luck of the Sea enchantments get removed by other mods.
|
||||
- Fixed crashes related to Pokémon when they are ready to evolve while holding an enchanted item. Very specific.
|
||||
- Fixed a crash that sometimes occurred when evolving Nincada.
|
||||
- Fixed Cobblemon plants not being compostable on NeoForge.
|
||||
- Fixed hide UI (F1 key) not hiding the party overlay.
|
||||
- Fixed NPC MoLang command `player_lose_command` not working.
|
||||
- Fixed misaligned tooltips with edit boxes in the NPC editor screen.
|
||||
- Fixed Pokémon riding two boats when attempting to deploy a platform on water.
|
||||
- Fixed the summary screen showing there's experience to reach the next level when they are at the level cap.
|
||||
- Fixed Pokémon forgetting moves when evolving on specific cases.
|
||||
- Fixed Adorn compatibility, including improvements when using JEI/REI (Apricorn items now show up under the collapsed entries rather than standalone).
|
||||
- Fixed error message appearing on battle log when using Solar Beam with Sunny Day.
|
||||
- Fixed Pokémon Model offsets for larger species.
|
||||
- Fixed `/pokedex grant all` command not giving male/female/shininess completion for some Pokémon.
|
||||
- Fixed `/pokedex grant only` and `/pokedex remove only` not respecting the form parameter passed.
|
||||
- Fixed variant forms appearing incorrectly in the Pokédex when the normal form had not been unlocked.
|
||||
- Fixed Pokémon occasionally being shot into the sky during battle. No Pokémon were harmed by this bug, probably.
|
||||
- Fixed NPC editing GUI not updating aspects until a game restart.
|
||||
- Fixed some users being unable to open their PC if a Pokémon in it had a lot of PP raises beyond normal bounds. How did you get those, anyway? Tell me or the Bellossom gets it.
|
||||
- Fixed some color variants (Dubwool, Conkeldurr and Undyed wooloo) being missing in the Pokédex.
|
||||
- Fixed invalid species or held items causing Players to not be able to load into their world anymore (commonly happening after removing addons/mods).
|
||||
- Fixed Wooloo variants not being automatically registered in the owner's Pokédex when dyed.
|
||||
- Fixed Vivichoke Dip and Leek & Potato Stew not returning a bowl upon consumption.
|
||||
- Fixed Fossil Restoration Tank not accepting Hay Bales as organic material.
|
||||
- Fixed Potion items applying double their intended healing value.
|
||||
- Fixed Fast Ball capture bonuses applying to all Pokémon, making it the Best Ball instead of the Mediocre Edge-Case Ball.
|
||||
- Fixed "learned new move" messages appearing for already-known moves on Pokémon evolutions.
|
||||
- Fixed Pokémon Item Models breaking shadows nearby when being placed in Display Cases or Item Frames.
|
||||
- Fixed berries not giving bonus yields when planted in their preferred biomes. I'm sure we've fixed that 5 times now.
|
||||
- Fixed the NeoForge version not supporting "SodiumDynamicLights".
|
||||
- Fixed players disconnecting from servers if they made changes to certain config options.
|
||||
- Fixed players with shouldered Pokémon not being able to rejoin their 1.5.2 worlds using 1.6.
|
||||
- Fixed `PokemonProperties` utilizing `ability=<some ability>` being treated as a forced ability even when it is a legal ability for the Pokémon.
|
||||
- Fixed type formatting in Pokédex scanner mode when dual types require two lines.
|
||||
- Fixed trading sometimes crashing the game or server.
|
||||
- Fixed Wild shiny sounds not respecting the `shinyNoticeParticlesDistance` config setting.
|
||||
- Fixed Pokémon being able to evolve mid-battle.
|
||||
- Fixed NPC held items being able to be stolen by players. Don't be a thief!
|
||||
- Fixed evolutions that require a held item consuming it as soon as meeting requirements when it should only be consumed upon evolution.
|
||||
- Fixed Pokémon showing only the default form when selecting them as a target in battle.
|
||||
- Fixed a possible error coming out of reeling fishing rods in specific situations.
|
||||
- Fixed incorrect weights being used when Poké Fishing with Luck of the Sea.
|
||||
- Parametric particle motion now works.
|
||||
- Event-spawned particles now work.
|
||||
- Particles can now have independent coordinate spaces.
|
||||
|
||||
### Developer
|
||||
- Updated the Pokédex data updated events to always include a `Pokemon` instance, and optionally a `DisguiseData` instance.
|
||||
- Updated fields in `SpawnNPCPacket` and `SpawnPokemonPacket` to be visible and mutable.
|
||||
- Updated `UnvalidatedPlaySoundS2CPacket` to be public instead of internal and made its fields mutable.
|
||||
- Added `hideNameTag` field and `HideNPCNameTag` nbt tag to `NPCEntity` to allow hiding the name tag of the NPC.
|
||||
- Added the player to `PokerodReelEvent` so you know who is doing the reeling.
|
||||
|
||||
### MoLang & Datapacks
|
||||
- Added flows for:
|
||||
- `forme_change`: Triggered when a Pokémon changes form in battle.
|
||||
- `mega_evolution`: Triggered when a Pokémon mega evolves in battle. (Note: Third-party mods are required for this feature currently)
|
||||
- `zpower_used`: Triggered when a Pokémon uses a Z-Power move in battle. (Note: Third-party mods are required for this feature currently)
|
||||
- `terastallization`: Triggered when a Pokémon terastallizes in battle. (Note: Third-party mods are required for this feature currently)
|
||||
- `battle_fainted`: Triggered when a Pokémon faints in battle.
|
||||
- `battle_fled`: Triggered when a player flees from battle.
|
||||
- `battle_started_pre`: Triggered when a battle starts. Cancelable!
|
||||
- `battle_started_post`: Triggered when a battle starts.
|
||||
- `apricorn_harvested`: Triggered when an Apricorn is harvested.
|
||||
- `thrown_pokeball_hit`: Triggered when a thrown Pokéball hits a Pokémon.
|
||||
- `level_up`: Triggered when a Pokémon levels up.
|
||||
- `pokemon_fainted`: Triggered when a Pokémon faints.
|
||||
- `pokemon_gained`: Triggered when a player gains a Pokémon.
|
||||
- Added MoLang functions:
|
||||
- For Pokémon:
|
||||
- `pokemon.apply(PokemonProperties)`: Applies the given properties to the Pokémon.
|
||||
- `pokemon.owner`: Returns the owner of the Pokémon or 0.0 if there is no owner or they are not online.
|
||||
- For all entities:
|
||||
- `entity.is_standing_on_blocks(depth, blocks...)`: Returns whether the specified entity is standing on a specific block or set of blocks. Example usage: `q.is_standing_on_blocks(2, minecraft:sand)`
|
||||
- Added NPC field:
|
||||
- `hideNameTag`: Hides the name tag of the NPC.
|
||||
- Added `baseScale` property to NPCs.
|
||||
- Added MoLang particle queries for getting distance to targeted entities.
|
||||
- Fix Pokédex sometimes crashing when switching forms
|
||||
|
||||
## [1.6.0 - The Record Catch Update (December 25th, 2024)](#1-6-0)
|
||||
#### "Now that there's a fishing mechanic, the mod is actually good!"
|
||||
@@ -2129,4 +1905,5 @@ 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.
|
||||
|
||||
|
||||
+25
-17
@@ -15,6 +15,8 @@ import utilities.version
|
||||
*/
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.moddev)
|
||||
|
||||
id("cobblemon.base-conventions")
|
||||
id("cobblemon.publish-conventions")
|
||||
|
||||
@@ -23,38 +25,38 @@ plugins {
|
||||
id("net.nemerosa.versioning") version "3.1.0"
|
||||
}
|
||||
|
||||
architectury {
|
||||
common("neoforge", "fabric")
|
||||
neoForge {
|
||||
neoFormVersion = "1.21.1-20240808.144430"
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven(url = "${rootProject.projectDir}/deps")
|
||||
maven(url = "https://api.modrinth.com/maven")
|
||||
maven(url = "https://maven.fabricmc.net/")
|
||||
maven(url = "https://maven.neoforged.net/releases")
|
||||
mavenLocal()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.bundles.kotlin)
|
||||
modImplementation(libs.fabric.loader)
|
||||
modApi(libs.molang)
|
||||
implementation(libs.bundles.mixins)
|
||||
|
||||
api(libs.molang)
|
||||
compileOnly(libs.graal)
|
||||
compileOnly(libs.bundles.mongo)
|
||||
|
||||
// Integrations
|
||||
compileOnlyApi(libs.jei.api)
|
||||
modCompileOnly(libs.bundles.fabric.integrations.compileOnly) {
|
||||
isTransitive = false
|
||||
}
|
||||
// Flywheel has no common dep so just pick one and don't use any platform specific code in common
|
||||
// modCompileOnly(libs.flywheelFabric)
|
||||
// compileOnly(libs.bundles.fabric.integrations.compileOnly) {
|
||||
// isTransitive = false
|
||||
// }
|
||||
|
||||
// Showdown
|
||||
modCompileOnly(libs.graal)
|
||||
|
||||
// Data Storage
|
||||
modCompileOnly(libs.bundles.mongo)
|
||||
|
||||
// Unit Testing
|
||||
testImplementation(libs.bundles.unitTesting)
|
||||
testRuntimeOnly(libs.junit.fabric)
|
||||
|
||||
// // Integrations
|
||||
// modCompileOnly(libs.bundles.fabric.integrations.compileOnly) {
|
||||
// isTransitive = false
|
||||
// }
|
||||
}
|
||||
|
||||
tasks.withType<Test> {
|
||||
@@ -94,4 +96,10 @@ sourceSets {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IDEA no longer automatically downloads sources/javadoc jars for dependencies, so we need to explicitly enable the behavior.
|
||||
idea {
|
||||
module.isDownloadJavadoc = true
|
||||
module.isDownloadSources = true
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common;
|
||||
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface Rollable {
|
||||
|
||||
Vector3f FORWARDS = new Vector3f(0, 0, 1);
|
||||
Vector3f LEFT = new Vector3f(1, 0, 0);
|
||||
Vector3f UP = new Vector3f(0, 1, 0);
|
||||
|
||||
@Nullable Matrix3f getOrientation();
|
||||
|
||||
Rollable updateOrientation(Function<Matrix3f, Matrix3f> update);
|
||||
|
||||
/**
|
||||
* @return The forward vector (0, 0, 1) after the rotation matrix is applied.
|
||||
*/
|
||||
default Vector3f getForwardVector() {
|
||||
if (getOrientation() == null) return new Vector3f(FORWARDS);
|
||||
return getOrientation().transform(FORWARDS, new Vector3f());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The left vector (1, 0, 0) after the rotation matrix is applied.
|
||||
*/
|
||||
default Vector3f getLeftVector() {
|
||||
if (getOrientation() == null) return new Vector3f(LEFT);
|
||||
return getOrientation().transform(LEFT, new Vector3f());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The up vector (0, 1, 0) after the rotation matrix is applied.
|
||||
*/
|
||||
default Vector3f getUpVector() {
|
||||
if (getOrientation() == null) return new Vector3f(UP);
|
||||
return getOrientation().transform(UP, new Vector3f());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param yaw change in degrees
|
||||
* @return The Rollable object this method was called on
|
||||
*/
|
||||
|
||||
default Rollable rotateYaw(float yaw) {
|
||||
return updateOrientation(prev -> prev.rotateY((float) Math.toRadians(-yaw)));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pitch change in degrees
|
||||
* @return The Rollable object this method was called on
|
||||
*/
|
||||
|
||||
default Rollable rotatePitch(float pitch) {
|
||||
return updateOrientation(prev -> prev.rotateX((float) Math.toRadians(-pitch)));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param roll change in degrees
|
||||
* @return The Rollable object this method was called on
|
||||
*/
|
||||
default Rollable rotateRoll(float roll) {
|
||||
return updateOrientation(prev -> prev.rotateZ((float) Math.toRadians(-roll)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Order matters when rotating an object. If you need a different order, individually call rotateYaw, rotatePitch, and rotateRoll
|
||||
*
|
||||
* @param yaw change in degrees
|
||||
* @param pitch change in degrees
|
||||
* @param roll change in degrees
|
||||
* @return The Rollable object this method was called on
|
||||
*/
|
||||
default Rollable rotate(float yaw, float pitch, float roll) {
|
||||
return rotateYaw(yaw).rotatePitch(pitch).rotateRoll(roll);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return The yaw angle in degrees as a float.
|
||||
* Value is between [-90, 90] with 0 being straight forward, 90 being straight down, and -90 being straight up
|
||||
*/
|
||||
default float getYaw() {
|
||||
return (float) (180F - Math.toDegrees(FORWARDS.angleSigned(getForwardVector(), UP)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the pitch angle in degrees as a float.
|
||||
* Value is between [-180, 180] with 0 being South, 90 being West, 180/-180 being North, and -90 being East
|
||||
*/
|
||||
default float getPitch() {
|
||||
return (float) Math.toDegrees(Math.asin(getForwardVector().y));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the roll angle in degrees as a float.
|
||||
* Value is between [-180, 180] with 0 being no roll (normal), 90 being 90 degrees CW, 180/-180 being 180 degrees CW/CCW, and -90 being 90 degrees CCW
|
||||
*/
|
||||
default float getRoll() {
|
||||
var upVector = getUpVector();
|
||||
var forwardVector = getForwardVector();
|
||||
return (float) Math.toDegrees(upVector.angleSigned(UP, forwardVector));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the angular velocity in degrees per second as a Vec3
|
||||
*/
|
||||
Vec3 angRollVel();
|
||||
|
||||
public void rotationOnMouseXY( double yMouse, double xMouse );
|
||||
|
||||
boolean shouldRoll();
|
||||
|
||||
boolean useMouseInputRoll();
|
||||
|
||||
void clearRotation();
|
||||
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(Camera.class)
|
||||
public abstract class CameraMixin {
|
||||
|
||||
@Shadow private Entity entity;
|
||||
@Shadow @Final private Quaternionf rotation;
|
||||
@Shadow @Final private Vector3f forwards;
|
||||
@Shadow @Final private Vector3f up;
|
||||
@Shadow @Final private Vector3f left;
|
||||
@Shadow private float xRot;
|
||||
@Shadow private float yRot;
|
||||
|
||||
@Shadow public abstract float getXRot();
|
||||
|
||||
@Shadow public abstract float getYRot();
|
||||
|
||||
@Unique private float returnTimer = 0;
|
||||
@Unique private float rollAngleStart = 0;
|
||||
@Unique Minecraft minecraft = Minecraft.getInstance();
|
||||
|
||||
@Unique boolean disableRollableCameraDebug = false;
|
||||
|
||||
@Inject(method = "setRotation", at = @At("HEAD"), cancellable = true)
|
||||
public void open_camera$setRotation(float f, float g, CallbackInfo ci) {
|
||||
if (!(this.entity instanceof Rollable rollable) || disableRollableCameraDebug) return;
|
||||
if (!rollable.shouldRoll() && rollable.getOrientation() != null) {
|
||||
if(this.returnTimer < 1) {
|
||||
//Rotation is taken from entity since we no longer handle mouse ourselves
|
||||
//Stops a period of time when you can't input anything.
|
||||
rollable.getOrientation().set(
|
||||
new Matrix3f()
|
||||
.rotateY((float) Math.toRadians(180 - this.entity.getYRot()))
|
||||
.rotateX((float) Math.toRadians(-this.entity.getXRot()))
|
||||
);
|
||||
if(rollAngleStart == 0){
|
||||
this.returnTimer = 1;
|
||||
rollable.clearRotation();
|
||||
return;
|
||||
}
|
||||
rollable.getOrientation().rotateZ((float) Math.toRadians(-rollAngleStart*(1-returnTimer)));
|
||||
applyRotation();
|
||||
this.returnTimer += .05F;
|
||||
ci.cancel();
|
||||
} else {
|
||||
this.returnTimer = 1;
|
||||
rollable.clearRotation();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (rollable.getOrientation() == null) return;
|
||||
applyRotation();
|
||||
|
||||
this.returnTimer = 0;
|
||||
this.rollAngleStart = rollable.getRoll();
|
||||
ci.cancel();
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void applyRotation(){
|
||||
if (!(this.entity instanceof Rollable rollable) || rollable.getOrientation() == null) return;
|
||||
var newRotation = rollable.getOrientation().normal(new Matrix3f()).getNormalizedRotation(new Quaternionf());
|
||||
if (this.minecraft.options.getCameraType().isMirrored()) {
|
||||
newRotation.rotateY((float)Math.toRadians(180));
|
||||
}
|
||||
this.rotation.set(newRotation);
|
||||
this.xRot = rollable.getPitch();
|
||||
this.yRot = rollable.getYaw();
|
||||
this.forwards.set(rollable.getForwardVector());
|
||||
this.up.set(rollable.getUpVector());
|
||||
this.left.set(rollable.getLeftVector());
|
||||
}
|
||||
}
|
||||
@@ -9,20 +9,6 @@
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper;
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel;
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState;
|
||||
import com.cobblemon.mod.common.entity.PosableEntity;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.joml.Vector3f;
|
||||
import org.spongepowered.asm.mixin.Debug;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -48,39 +34,4 @@ public class EntityRenderDispatcherMixin {
|
||||
public void resourceManagerReloadHook(ResourceManager resourceManager, CallbackInfo ci) {
|
||||
CobblemonClient.INSTANCE.onAddLayer(this.playerRenderers);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "renderHitbox(Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;Lnet/minecraft/world/entity/Entity;FFFF)V",
|
||||
at = @At(value = "TAIL")
|
||||
)
|
||||
private static void renderLocators(
|
||||
PoseStack poseStack,
|
||||
VertexConsumer buffer,
|
||||
Entity entity,
|
||||
float red,
|
||||
float green,
|
||||
float blue,
|
||||
float alpha,
|
||||
CallbackInfo ci
|
||||
) {
|
||||
if (entity instanceof PosableEntity posableEntity) {
|
||||
if (posableEntity.getDelegate() instanceof PosableState state) {
|
||||
state.getLocatorStates().forEach((locator, matrix) -> {
|
||||
poseStack.pushPose();
|
||||
Vec3 pos = matrix.getOrigin().subtract(entity.position());
|
||||
LevelRenderer.renderLineBox(
|
||||
poseStack,
|
||||
buffer,
|
||||
AABB.ofSize(pos, 0.25, 0.25, 0.25),
|
||||
0F,
|
||||
1F,
|
||||
0F,
|
||||
1F
|
||||
);
|
||||
poseStack.popPose();
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.render.player.MountedPlayerRenderer;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import net.minecraft.client.model.HumanoidModel;
|
||||
import net.minecraft.client.model.geom.ModelPart;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@Mixin(HumanoidModel.class)
|
||||
public class HumanoidModelMixin {
|
||||
@Unique HashMap<String, ModelPart> relevantPartsByName = new HashMap<>();
|
||||
|
||||
@Shadow @Final
|
||||
public ModelPart head;
|
||||
@Shadow @Final
|
||||
public ModelPart rightArm;
|
||||
@Shadow @Final
|
||||
public ModelPart leftArm;
|
||||
@Shadow @Final
|
||||
public ModelPart rightLeg;
|
||||
@Shadow @Final
|
||||
public ModelPart leftLeg;
|
||||
|
||||
@Inject(method = "setupAnim*", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/model/geom/ModelPart;copyFrom(Lnet/minecraft/client/model/geom/ModelPart;)V", shift = At.Shift.BEFORE))
|
||||
public void cobblemon$animateRiders(
|
||||
LivingEntity entity,
|
||||
float limbSwing,
|
||||
float limbSwingAmount,
|
||||
float ageInTicks,
|
||||
float netHeadYaw,
|
||||
float headPitch,
|
||||
CallbackInfo ci
|
||||
) {
|
||||
if (relevantPartsByName.isEmpty()) {
|
||||
relevantPartsByName.put("arm_left", leftArm);
|
||||
relevantPartsByName.put("arm_right", rightArm);
|
||||
relevantPartsByName.put("leg_left", leftLeg);
|
||||
relevantPartsByName.put("leg_right", rightLeg);
|
||||
relevantPartsByName.put("head", head);
|
||||
}
|
||||
|
||||
Entity vehicle = entity.getVehicle();
|
||||
if (vehicle instanceof PokemonEntity && entity instanceof AbstractClientPlayer) {
|
||||
MountedPlayerRenderer.INSTANCE.animate((PokemonEntity) vehicle, (AbstractClientPlayer) entity, relevantPartsByName, netHeadYaw, headPitch, ageInTicks, limbSwing, limbSwingAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,21 +8,16 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.item.PokedexItem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Axis;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.client.renderer.ItemInHandRenderer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.joml.Quaternionf;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ItemInHandRenderer.class)
|
||||
@@ -32,15 +27,5 @@ public class ItemInHandRendererMixin {
|
||||
if (abstractClientPlayer.isUsingItem() && abstractClientPlayer.getUseItem().getItem() instanceof PokedexItem) {
|
||||
ci.cancel();
|
||||
}
|
||||
else if (abstractClientPlayer instanceof Rollable rollable && rollable.shouldRoll()) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Redirect(method = "renderHandsWithItems", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;mulPose(Lorg/joml/Quaternionf;)V", ordinal = 1))
|
||||
private void cobblemon$renderHandswithItems(PoseStack instance, Quaternionf quaternion) {
|
||||
if (!(Minecraft.getInstance().player instanceof Rollable rollable && rollable.shouldRoll())) {
|
||||
instance.mulPose(quaternion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,15 +12,9 @@ import com.cobblemon.mod.common.api.pokemon.effect.ShoulderEffectRegistry;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Overwrite;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(LivingEntity.class)
|
||||
@@ -34,70 +28,4 @@ public abstract class LivingEntityMixin {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@Inject(method = "travelRidden", at = @At(value = "HEAD"))
|
||||
private void cobblemon$altTravelRidden(Player player, Vec3 travelVector)
|
||||
{
|
||||
this.setSpeed(this.getRiddenSpeed(player));
|
||||
this.travel(vec3);
|
||||
}
|
||||
|
||||
/*
|
||||
// Shadow the original method so we can call it.
|
||||
@Shadow
|
||||
protected abstract boolean isControlledByLocalInstance();
|
||||
|
||||
/**
|
||||
* Redirect the call to isControlledByLocalInstance() within travelRidden.
|
||||
* When travelRidden calls isControlledByLocalInstance(), it will get our modified result.
|
||||
*/
|
||||
|
||||
/*
|
||||
@Redirect(
|
||||
method = "travelRidden(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/phys/Vec3;)V",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/entity/LivingEntity;isControlledByLocalInstance()Z"
|
||||
)
|
||||
)
|
||||
private boolean redirectIsControlledByLocalInstance(LivingEntity instance) {
|
||||
// Return true if either the original method returns true or our custom condition is true.
|
||||
return this.isControlledByLocalInstance() || this.b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Overwrite
|
||||
private void travelRidden(Player player, Vec3 travelVector) {
|
||||
Vec3 vec3 = this.getRiddenInput(player, travelVector);
|
||||
this.tickRidden(player, vec3);
|
||||
if (this.isControlledByLocalInstance()) {
|
||||
this.setSpeed(this.getRiddenSpeed(player));
|
||||
this.travel(vec3);
|
||||
} else {
|
||||
this.calculateEntityAnimation(false);
|
||||
this.setDeltaMovement(Vec3.ZERO);
|
||||
this.tryCheckInsideBlocks();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ModifyArg(
|
||||
method = "travelRidden",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "setDeltaMovement(Lnet/minecraft/world/phys/Vec3;)V"
|
||||
),
|
||||
index = 0 // the first (and only) argument
|
||||
)
|
||||
private Vec3 modifyDeltaMovementArgument(Vec3 original) {
|
||||
// Optionally, check if original is Vec3.ZERO, to only replace that call:
|
||||
if (original.equals(Vec3.ZERO)) {
|
||||
// Return your custom vector instead of Vec3.ZERO
|
||||
return original;
|
||||
}
|
||||
// Otherwise, return the original value
|
||||
return original;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext;
|
||||
@@ -23,21 +22,16 @@ import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(MouseHandler.class)
|
||||
public class MouseHandlerMixin {
|
||||
@Shadow private double accumulatedScrollY;
|
||||
@Shadow @Final private Minecraft minecraft;
|
||||
@Shadow
|
||||
private double accumulatedScrollY;
|
||||
|
||||
@Unique SmoothDouble xMouseSmoother = new SmoothDouble();
|
||||
@Unique SmoothDouble yMouseSmoother = new SmoothDouble();
|
||||
@Unique SmoothDouble pitchSmoother = new SmoothDouble();
|
||||
@Unique SmoothDouble rollSmoother = new SmoothDouble();
|
||||
@Unique SmoothDouble yawSmoother = new SmoothDouble();
|
||||
@Shadow @Final private Minecraft minecraft;
|
||||
|
||||
@Shadow @Final private SmoothDouble smoothTurnY;
|
||||
|
||||
@@ -99,6 +93,7 @@ public class MouseHandlerMixin {
|
||||
)
|
||||
)
|
||||
public boolean cobblemon$modifyRotation(LocalPlayer player, double cursorDeltaX, double cursorDeltaY, @Local(argsOnly = true) double d) {
|
||||
// I know this technically doesn't need to be a WrapWithCondition, but it'll make things easier later for riding.
|
||||
PokedexUsageContext usageContext = CobblemonClient.INSTANCE.getPokedexUsageContext();
|
||||
if (usageContext.getScanningGuiOpen()) {
|
||||
this.smoothTurnY.reset();
|
||||
@@ -110,62 +105,7 @@ public class MouseHandlerMixin {
|
||||
player.turn(this.accumulatedDX * sensitivity, (this.accumulatedDY * sensitivity));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(player instanceof Rollable rollable)) return true;
|
||||
|
||||
if (!rollable.shouldRoll()) {
|
||||
xMouseSmoother.reset();
|
||||
yMouseSmoother.reset();
|
||||
pitchSmoother.reset();
|
||||
rollSmoother.reset();
|
||||
yawSmoother.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
//maybe have a rollable x mouse and rollable y mouse that take the xmousesmoother
|
||||
//and y mouse smoother ( which are right now named pichsmoother and roll smoother)
|
||||
// values and feed it to those rollable functions which will be called by the
|
||||
//specific ride controller where rollable.rotate can then be called and used
|
||||
//controller specific.
|
||||
var yMouse = yMouseSmoother.getNewDeltaValue(cursorDeltaY * 0.15f, d);
|
||||
var xMouse = xMouseSmoother.getNewDeltaValue(cursorDeltaX * 0.15f, d);
|
||||
rollable.rotationOnMouseXY( yMouse, xMouse );
|
||||
|
||||
//get the current angular velocity requested to be applied
|
||||
//by the ride controller
|
||||
var angRot = rollable.angRollVel();
|
||||
//Multiply against deltatime to get a consistent turn
|
||||
//independent of framerate
|
||||
if( angRot != null ) {
|
||||
//var yaw = angRot.x * d;
|
||||
//Add the yaw to the mouse here... this all needs changed. It should
|
||||
//just map which 0 1 or 2 of the three it is going to modulate with
|
||||
//what
|
||||
|
||||
var yaw = yawSmoother.getNewDeltaValue(angRot.x * 0.5f, d);
|
||||
//yaw += yawSmoother.getNewDeltaValue(cursorDeltaX * 0.15f, d);
|
||||
//var pitch = angRot.y * d;
|
||||
var pitch = pitchSmoother.getNewDeltaValue(angRot.y * 0.5f, d);
|
||||
//pitch += pitchSmoother.getNewDeltaValue(cursorDeltaY * 0.15f, d);
|
||||
//var roll = angRot.z * d;
|
||||
var roll = rollSmoother.getNewDeltaValue(angRot.z * 0.5f, d);
|
||||
rollable.rotate((float) yaw, (float) pitch, (float) roll);
|
||||
}
|
||||
return false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Inject(method = "handleAccumulatedMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MouseHandler;isMouseGrabbed()Z", ordinal = 0))
|
||||
private void cobblemon$maintainMovementWhenInScreens(CallbackInfo ci, @Local(ordinal = 1) double e) {
|
||||
if (minecraft.player == null) return;
|
||||
if (!(minecraft.player instanceof Rollable rollable)) return;
|
||||
if (!rollable.shouldRoll()) return;
|
||||
if (minecraft.isPaused()) return;
|
||||
|
||||
var pitch = pitchSmoother.getNewDeltaValue(0, e);
|
||||
var roll = rollSmoother.getNewDeltaValue(0, e);
|
||||
rollable.rotate(0.0F, (float)pitch, (float)roll);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,15 +10,11 @@ package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.CobblemonItems;
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents;
|
||||
import com.cobblemon.mod.common.api.events.item.LeftoversCreatedEvent;
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies;
|
||||
import com.cobblemon.mod.common.api.riding.Rideable;
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore;
|
||||
import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore;
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.ScannableEntity;
|
||||
import com.cobblemon.mod.common.pokemon.FormData;
|
||||
@@ -29,10 +25,6 @@ import com.cobblemon.mod.common.util.CompoundTagExtensionsKt;
|
||||
import com.cobblemon.mod.common.util.CompoundTagUtilities;
|
||||
import com.cobblemon.mod.common.util.DataKeys;
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
@@ -45,18 +37,14 @@ import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.food.FoodProperties;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix3f;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@@ -64,11 +52,10 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Mixin(Player.class)
|
||||
public abstract class PlayerMixin extends LivingEntity implements Rollable, ScannableEntity {
|
||||
public abstract class PlayerMixin extends LivingEntity implements ScannableEntity {
|
||||
|
||||
@Shadow public abstract CompoundTag getShoulderEntityLeft();
|
||||
|
||||
@@ -86,7 +73,6 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
|
||||
|
||||
@Shadow public abstract void displayClientMessage(Component message, boolean overlay);
|
||||
|
||||
@Unique private Matrix3f orientation = null;
|
||||
|
||||
protected PlayerMixin(EntityType<? extends LivingEntity> p_20966_, Level p_20967_) {
|
||||
super(p_20966_, p_20967_);
|
||||
@@ -192,10 +178,10 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
|
||||
|
||||
@Override @Nullable
|
||||
public PokedexEntityData resolvePokemonScan() {
|
||||
if (CompoundTagUtilities.isShoulderPokemon(this.getShoulderEntityRight())){
|
||||
if(CompoundTagUtilities.isShoulderPokemon(this.getShoulderEntityRight())){
|
||||
return getDataFromShoulderPokemon(this.getShoulderEntityRight());
|
||||
}
|
||||
if (CompoundTagUtilities.isShoulderPokemon(this.getShoulderEntityLeft())){
|
||||
if(CompoundTagUtilities.isShoulderPokemon(this.getShoulderEntityLeft())){
|
||||
return getDataFromShoulderPokemon(this.getShoulderEntityLeft());
|
||||
}
|
||||
return null;
|
||||
@@ -204,157 +190,34 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
|
||||
@Nullable @Unique
|
||||
private PokedexEntityData getDataFromShoulderPokemon(CompoundTag shoulderTag) {
|
||||
CompoundTag pokemonTag = shoulderTag.getCompound(DataKeys.POKEMON);
|
||||
if (pokemonTag.isEmpty()) return null;
|
||||
if(pokemonTag.isEmpty()) return null;
|
||||
Species species = PokemonSpecies.INSTANCE.getByIdentifier(ResourceLocation.parse(pokemonTag.getString(DataKeys.POKEMON_SPECIES_IDENTIFIER)));
|
||||
if (species == null) return null;
|
||||
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;
|
||||
if(!formList.isEmpty()) form = formList.getFirst();
|
||||
if(form == null) return null;
|
||||
String genderString = pokemonTag.getString(DataKeys.POKEMON_GENDER);
|
||||
if (genderString.isEmpty()) return null;
|
||||
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 pokemon = new Pokemon();
|
||||
if (level().isClientSide) {
|
||||
pokemon.setSpecies(species);
|
||||
pokemon.setForm(form);
|
||||
pokemon.setGender(gender);
|
||||
pokemon.setShiny(shiny);
|
||||
pokemon.setLevel(level);
|
||||
pokemon.setForcedAspects(aspects);
|
||||
} else {
|
||||
PlayerPartyStore party = Cobblemon.INSTANCE.getStorage().getParty(this.getUUID(), this.registryAccess());
|
||||
pokemon = party.get(shoulderTag.getUUID(DataKeys.SHOULDER_UUID));
|
||||
}
|
||||
return new PokedexEntityData(pokemon, null);
|
||||
return new PokedexEntityData(
|
||||
species,
|
||||
form,
|
||||
gender,
|
||||
aspects,
|
||||
shiny,
|
||||
level,
|
||||
this.getUUID()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LivingEntity resolveEntityScan() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void absMoveTo(double x, double y, double z, float yaw, float pitch) {
|
||||
if (shouldRoll()) {
|
||||
this.absMoveTo(x, y, z);
|
||||
this.setYRot(yaw % 360.0f);
|
||||
this.setXRot(pitch % 360.0f);
|
||||
this.yRotO = this.getYRot();
|
||||
this.xRotO = this.getXRot();
|
||||
}
|
||||
else {
|
||||
this.absMoveTo(x, y, z);
|
||||
this.absRotateTo(yaw, pitch);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "tick", at = @At("HEAD"))
|
||||
public void tick(CallbackInfo ci) {
|
||||
if (this.shouldRoll()) {
|
||||
// Proof of concept for yaw movement
|
||||
if (this.getMainHandItem().is(Items.STICK)) {
|
||||
this.rotateYaw(2);
|
||||
}
|
||||
else if (this.getMainHandItem().is(Items.BLAZE_ROD)) {
|
||||
this.rotateYaw(-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Matrix3f getOrientation() {
|
||||
return orientation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rollable updateOrientation(Function<Matrix3f, Matrix3f> update) {
|
||||
//Disabled to allow non mouse inputs to modify roll
|
||||
if (!shouldRoll()) return this;
|
||||
|
||||
if (this.orientation == null) {
|
||||
this.orientation = new Matrix3f();
|
||||
this.rotate(getYRot() - 180, getXRot(), 0);
|
||||
}
|
||||
this.orientation = update.apply(this.orientation);
|
||||
setYRot(this.getYaw());
|
||||
setXRot(this.getPitch());
|
||||
this.yRotO = this.getYRot();
|
||||
this.xRotO = this.getXRot();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRoll() {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (!this.equals(player)) return false;
|
||||
if (player.isHolding(Items.DIAMOND)) return true;
|
||||
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return false;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return false;
|
||||
|
||||
return pokemonEntity.getRiding().shouldRoll(pokemonEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rotationOnMouseXY( double yMouse, double xMouse ) {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (!this.equals(player)) return;
|
||||
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return;
|
||||
|
||||
pokemonEntity.getRiding().rotationOnMouseXY(pokemonEntity, player, yMouse, xMouse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useMouseInputRoll() {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (!this.equals(player)) return true;
|
||||
if (player.isHolding(Items.DIAMOND)) return false;
|
||||
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return true;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return true;
|
||||
|
||||
return pokemonEntity.getRiding().useMouseInputRoll(pokemonEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3 angRollVel() {
|
||||
var ret = new Vec3(0.0, 0.0, 0.0);
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (!this.equals(player)) return ret;
|
||||
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return ret;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return ret;
|
||||
|
||||
return pokemonEntity.getRiding().angRollVel(pokemonEntity, player);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void clearRotation() {
|
||||
this.orientation = null;
|
||||
}
|
||||
|
||||
@WrapOperation(
|
||||
method = "rideTick()V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;wantsToStopRiding()Z")
|
||||
)
|
||||
public boolean delegateDismountToController(Player instance, Operation<Boolean> original) {
|
||||
if (this.getVehicle() instanceof Rideable vehicle) {
|
||||
return vehicle.getRiding().dismountOnShift() && original.call(instance);
|
||||
}
|
||||
return original.call(instance);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -8,14 +8,11 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.client.render.ClientPlayerIcon;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
@@ -23,33 +20,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(PlayerRenderer.class)
|
||||
public class PlayerRendererMixin {
|
||||
private static boolean disableRollableRenderDebug = false;
|
||||
|
||||
@Inject(method = "render", at = @At(value = "HEAD"))
|
||||
public void renderPlayer$head(AbstractClientPlayer player, float f, float g, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, CallbackInfo ci) {
|
||||
if(player instanceof Rollable && !disableRollableRenderDebug) {
|
||||
Rollable rollable = (Rollable) player;
|
||||
if(rollable.shouldRoll()){
|
||||
poseStack.pushPose();
|
||||
Matrix4f transformationMatrix = new Matrix4f();
|
||||
Vector3f center = new Vector3f(0, player.getBbHeight()/2, 0);
|
||||
transformationMatrix.translate(center);
|
||||
|
||||
//transformationMatrix.rotate(180f.toRadians() - (rollable.getYaw()).toRadians(), rollable.getUpVector(), transformationMatrix);
|
||||
transformationMatrix.rotate((float) Math.toRadians(-rollable.getPitch()), rollable.getLeftVector(), transformationMatrix);
|
||||
transformationMatrix.rotate((float) Math.toRadians(-rollable.getRoll()), rollable.getForwardVector(), transformationMatrix);
|
||||
|
||||
transformationMatrix.translate(center.negate(new Vector3f()));
|
||||
poseStack.mulPose(transformationMatrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "render", at = @At(value = "TAIL"))
|
||||
public void renderPlayer$tail(AbstractClientPlayer player, float f, float g, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, CallbackInfo ci) {
|
||||
@Inject(method = "render", at = @At(value = "TAIL"))
|
||||
public void renderPlayer(AbstractClientPlayer player, float f, float g, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, CallbackInfo ci) {
|
||||
ClientPlayerIcon.Companion.onRenderPlayer(player);
|
||||
if(player instanceof Rollable && !disableRollableRenderDebug && ((Rollable) player).shouldRoll()){
|
||||
poseStack.popPose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork;
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.net.messages.server.orientation.C2SUpdateOrientationPacket;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import org.joml.Matrix3f;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(LocalPlayer.class)
|
||||
public class LocalPlayerMixin {
|
||||
|
||||
@Unique Matrix3f cobblemon$lastOrientation;
|
||||
|
||||
@Inject(method = "sendPosition", at = @At("TAIL"))
|
||||
private void cobblemon_updateRotationMatrix(CallbackInfo ci) {
|
||||
if (!(this instanceof Rollable rollable)) return;
|
||||
if (rollable.getOrientation() == cobblemon$lastOrientation) return;
|
||||
cobblemon$lastOrientation = rollable.getOrientation() != null ? new Matrix3f(rollable.getOrientation()) : null;
|
||||
CobblemonNetwork.INSTANCE.sendToServer(new C2SUpdateOrientationPacket(rollable.getOrientation()));
|
||||
}
|
||||
|
||||
@Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientPacketListener;send(Lnet/minecraft/network/protocol/Packet;)V"))
|
||||
private void cobblemon_updateRotationMatrixPassenger(CallbackInfo ci) {
|
||||
if (!(this instanceof Rollable rollable)) return;
|
||||
if (rollable.getOrientation() == cobblemon$lastOrientation) return;
|
||||
cobblemon$lastOrientation = rollable.getOrientation() != null ? new Matrix3f(rollable.getOrientation()) : null;
|
||||
CobblemonNetwork.INSTANCE.sendToServer(new C2SUpdateOrientationPacket(rollable.getOrientation()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.entity;
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(Entity.class)
|
||||
public abstract class EntityMixin {
|
||||
|
||||
@Shadow @Nullable public abstract Entity getVehicle();
|
||||
|
||||
@Inject(method = "updateInWaterStateAndDoWaterCurrentPushing", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/Entity;wasTouchingWater:Z", ordinal = 1), cancellable = true)
|
||||
public void cobblemon$verifyActuallyTouchingWater(CallbackInfo ci) {
|
||||
if(this.getVehicle() instanceof PokemonEntity) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.renderer;
|
||||
|
||||
import net.minecraft.client.renderer.entity.LivingEntityRenderer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
||||
/**
|
||||
* @author landonjw
|
||||
*/
|
||||
@Mixin(LivingEntityRenderer.class)
|
||||
public abstract class LivingEntityRendererMixin {
|
||||
// @Redirect(
|
||||
// method = "render(Lnet/minecraft/entity/LivingEntity;FFLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V",
|
||||
// at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;hasVehicle()Z"),
|
||||
// slice = @Slice(
|
||||
// from = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;lerpAngleDegrees(FFF)F"),
|
||||
// to = @At(value = "TAIL")
|
||||
// )
|
||||
// )
|
||||
// private boolean dodgeRenderer(LivingEntity instance) {
|
||||
// return false;
|
||||
// }
|
||||
}
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.renderer;
|
||||
|
||||
|
||||
import com.cobblemon.mod.common.client.render.player.MountedPlayerRenderer;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* @author landonjw
|
||||
*/
|
||||
@Mixin(PlayerRenderer.class)
|
||||
public class PlayerEntityRendererMixin {
|
||||
@Inject(
|
||||
method = "setupRotations(Lnet/minecraft/client/player/AbstractClientPlayer;Lcom/mojang/blaze3d/vertex/PoseStack;FFFF)V",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void doABibarelRoll$modifyRoll(AbstractClientPlayer player, PoseStack poseStack, float a, float b, float partialTicks, float i, CallbackInfo ci) {
|
||||
if (player.isPassenger()) {
|
||||
var vehicle = player.getVehicle();
|
||||
if (vehicle instanceof PokemonEntity entity) {
|
||||
MountedPlayerRenderer.INSTANCE.render(player, entity, poseStack);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.riding;
|
||||
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(LocalPlayer.class)
|
||||
public class JetMixin {
|
||||
|
||||
@Shadow private int jumpRidingTicks;
|
||||
@Shadow private float jumpRidingScale;
|
||||
|
||||
private float jetStrength;
|
||||
|
||||
// @Redirect(method = "tickMovement", at = @At(target = "Lnet/minecraft/entity/JumpingMount;getJumpCooldown()I", value = "INVOKE"))
|
||||
// public int cobblemon$tryHandlingJet(JumpingMount mount) {
|
||||
// if(mount instanceof PokemonEntity pokemon) {
|
||||
//// if(pokemon.getDataTracker().get(PokemonEntity.MOVING)) {
|
||||
//// ++this.field_3938;
|
||||
//// if (this.field_3938 < 11) {
|
||||
//// this.jetStrength = (float) this.field_3938 * 0.1F;
|
||||
//// } else {
|
||||
// this.mountJumpStrength = 0.8F + 2.0F / (float) (this.field_3938 - 9) * 0.1F;
|
||||
//// }
|
||||
//// } else {
|
||||
//// this.field_3938 = 0;
|
||||
//// this.jetStrength = 0;
|
||||
//// }
|
||||
//
|
||||
//// return -1;
|
||||
// }
|
||||
//
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
@Inject(
|
||||
method = "aiStep",
|
||||
at = @At(
|
||||
target = "Lnet/minecraft/client/player/LocalPlayer;jumpRidingScale:F",
|
||||
value = "FIELD",
|
||||
ordinal = 4,
|
||||
shift = At.Shift.AFTER
|
||||
),
|
||||
locals = LocalCapture.CAPTURE_FAILSOFT
|
||||
)
|
||||
public void cobblemon$applyCachedJumpStrength(CallbackInfo ci) {
|
||||
this.jumpRidingScale = this.jetStrength;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,14 +12,6 @@ object CobblemonBuildDetails {
|
||||
const val BRANCH = "{{ branch | default("Not Specified") }}"
|
||||
|
||||
fun smallCommitHash(): String {
|
||||
if(this.GIT_COMMIT.equals("Not Specified")) {
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
return this.GIT_COMMIT.substring(0, 7)
|
||||
}
|
||||
|
||||
fun version(): String {
|
||||
return this.VERSION + if(this.SNAPSHOT) "+${this.smallCommitHash()}" else ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import com.cobblemon.mod.common.api.SeasonResolver
|
||||
import com.cobblemon.mod.common.api.data.DataProvider
|
||||
import com.cobblemon.mod.common.api.drop.CommandDropEntry
|
||||
import com.cobblemon.mod.common.api.drop.DropEntry
|
||||
import com.cobblemon.mod.common.api.drop.EvolutionItemDropEntry
|
||||
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
|
||||
@@ -69,7 +68,6 @@ import com.cobblemon.mod.common.battles.BattleSide
|
||||
import com.cobblemon.mod.common.battles.ShowdownThread
|
||||
import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.client.CobblemonPack
|
||||
import com.cobblemon.mod.common.command.argument.*
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import com.cobblemon.mod.common.config.LastChangedVersion
|
||||
@@ -125,7 +123,6 @@ import kotlin.reflect.jvm.javaField
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.commands.synchronization.SingletonArgumentInfo
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.world.item.NameTagItem
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.storage.LevelResource
|
||||
@@ -165,16 +162,6 @@ object Cobblemon {
|
||||
var statProvider: StatProvider = CobblemonStatProvider
|
||||
var seasonResolver: SeasonResolver = TagSeasonResolver
|
||||
|
||||
@JvmStatic
|
||||
val builtinPacks = listOf<CobblemonPack>(
|
||||
CobblemonPack(id = "adorncompatibility", name = "Adorn Compatibility", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.ALWAYS_ENABLED, neededMods = setOf("adorn")),
|
||||
CobblemonPack(id = "gyaradosjump", name = "Gyarados Jump Patterns", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED),
|
||||
CobblemonPack(id = "regionbiasforms", name = "Region Bias Forms", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED),
|
||||
CobblemonPack(id = "uniqueshinyforms", name = "Shinies for Magikarp Jump", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.NORMAL),
|
||||
|
||||
CobblemonPack(id = "repurposedstructurescobblemon", name = "Repurposed Structures Cobblemon", packType = PackType.SERVER_DATA, activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED, neededMods = setOf("repurposed_structures")),
|
||||
)
|
||||
|
||||
fun preInitialize(implementation: CobblemonImplementation) {
|
||||
this.implementation = implementation
|
||||
|
||||
@@ -201,7 +188,6 @@ object Cobblemon {
|
||||
|
||||
DropEntry.register("command", CommandDropEntry::class.java)
|
||||
DropEntry.register("item", ItemDropEntry::class.java, isDefault = true)
|
||||
DropEntry.register("evolution", EvolutionItemDropEntry::class.java)
|
||||
|
||||
ExperienceGroups.registerDefaults()
|
||||
CaptureCalculators.registerDefaults()
|
||||
@@ -220,7 +206,7 @@ object Cobblemon {
|
||||
storage.onPlayerDataSync(it)
|
||||
playerDataManager.syncAllToPlayer(it)
|
||||
starterHandler.handleJoin(it)
|
||||
ServerSettingsPacket(this.config.preventCompletePartyDeposit, this.config.displayEntityLevelLabel, this.config.displayEntityNameLabel, this.config.maxPokemonLevel, this.config.maxPokemonFriendship, this.config.maxDynamaxLevel).sendToPlayer(it)
|
||||
ServerSettingsPacket(this.config.preventCompletePartyDeposit, this.config.displayEntityLevelLabel, this.config.displayEntityNameLabel).sendToPlayer(it)
|
||||
}
|
||||
PlatformEvents.SERVER_PLAYER_LOGOUT.subscribe {
|
||||
PCLinkManager.removeLink(it.player.uuid)
|
||||
@@ -258,8 +244,6 @@ object Cobblemon {
|
||||
// Lowest priority because this applies after luxury ball bonus as of gen 4
|
||||
CobblemonEvents.FRIENDSHIP_UPDATED.subscribe(Priority.LOWEST) { event ->
|
||||
var increment = (event.newFriendship - event.pokemon.friendship).toFloat()
|
||||
if (increment <= 0) //these affects are only meant to affect positive gains
|
||||
return@subscribe
|
||||
// Our Luxury ball spec is diff from official, but we will still assume these stack
|
||||
if (event.pokemon.heldItemNoCopy().`is`(CobblemonItemTags.IS_FRIENDSHIP_BOOSTER)) {
|
||||
increment += increment * 0.5F
|
||||
|
||||
@@ -317,7 +317,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField val RAZOR_FANG = noSettingsItem("razor_fang")
|
||||
@JvmField val AUSPICIOUS_ARMOR = heldItem("auspicious_armor")
|
||||
@JvmField val MALICIOUS_ARMOR = heldItem("malicious_armor")
|
||||
@JvmField val SHELL_HELMET = heldItem("shell_helmet")
|
||||
|
||||
private val berries = mutableMapOf<ResourceLocation, BerryItem>()
|
||||
// Plants
|
||||
@@ -393,9 +392,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
|
||||
@JvmField val BERRY_JUICE = this.create("berry_juice", BerryJuiceItem())
|
||||
|
||||
@JvmField
|
||||
val GALARICA_NUTS = create("galarica_nuts", GalaricaNutItem())
|
||||
|
||||
// Medicine
|
||||
@JvmField
|
||||
val RARE_CANDY = candyItem("rare_candy") { _, pokemon -> pokemon.getExperienceToNextLevel() }
|
||||
@@ -446,7 +442,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
.saturationModifier(1.2F)
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
|
||||
.alwaysEdible()
|
||||
.usingConvertsTo(Items.BOWL)
|
||||
.build())) {
|
||||
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
|
||||
user.removeAllEffects()
|
||||
@@ -482,7 +477,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val HEAL_POWDER = create("heal_powder", HealPowderItem())
|
||||
@JvmField
|
||||
val LEEK_AND_POTATO_STEW = create("leek_and_potato_stew", Item(Item.Properties().food(FoodProperties.Builder().nutrition(8).saturationModifier(0.6f).usingConvertsTo(Items.BOWL).build()).stacksTo(1)))
|
||||
val LEEK_AND_POTATO_STEW = create("leek_and_potato_stew", Item(Item.Properties().food(FoodProperties.Builder().nutrition(8).saturationModifier(0.6f).build()).stacksTo(1)))
|
||||
@JvmField
|
||||
val REVIVE = create("revive", ReviveItem(max = false))
|
||||
@JvmField
|
||||
|
||||
@@ -51,14 +51,7 @@ import com.cobblemon.mod.common.client.net.storage.pc.OpenPCHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.pc.SetPCBoxPokemonHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.pc.SetPCPokemonHandler
|
||||
import com.cobblemon.mod.common.client.net.toast.ToastPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeAcceptanceChangedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeCancelledHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeCompletedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeOfferExpiredHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeOfferNotificationHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeProcessStartedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeStartedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeUpdatedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.*
|
||||
import com.cobblemon.mod.common.net.PacketRegisterInfo
|
||||
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.SetClientPlayerDataPacket
|
||||
@@ -100,37 +93,14 @@ import com.cobblemon.mod.common.net.messages.client.storage.party.InitializePart
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.MoveClientPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyReferencePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.ClosePCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.InitializePCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.MoveClientPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.OpenPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.messages.client.toast.ToastPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeAcceptanceChangedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeCompletedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferExpiredPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferNotificationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeProcessStartedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.*
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.PokedexUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BattleChallengeResponsePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BenchMovePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.RequestMoveSwapPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.RequestPlayerInteractionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamLeavePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamRequestPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamResponsePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.*
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.*
|
||||
import com.cobblemon.mod.common.net.messages.server.block.AdjustBlockEntityViewerCountPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectedPacket
|
||||
@@ -141,7 +111,6 @@ import com.cobblemon.mod.common.net.messages.server.callback.partymove.PartyPoke
|
||||
import com.cobblemon.mod.common.net.messages.server.dialogue.EscapeDialoguePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.dialogue.InputToDialoguePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.npc.SaveNPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.orientation.C2SUpdateOrientationPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.PasturePokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.UnpastureAllPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPacket
|
||||
@@ -161,21 +130,9 @@ import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePartyPokemonT
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.ReleasePCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.SwapPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.UnlinkPlayerFromPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.AcceptTradeRequestPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.CancelTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.ChangeTradeAcceptancePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.PerformTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket
|
||||
import com.cobblemon.mod.common.net.serverhandling.ChallengeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.ChallengeResponseHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.RequestInteractionsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.BattleSelectActionsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.RemoveSpectatorHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamLeaveHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestResponseHandler
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.block.AdjustBlockEntityViewerCountHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectCancelledHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectedHandler
|
||||
@@ -187,7 +144,6 @@ import com.cobblemon.mod.common.net.serverhandling.dialogue.EscapeDialogueHandle
|
||||
import com.cobblemon.mod.common.net.serverhandling.dialogue.InputToDialogueHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.evolution.AcceptEvolutionHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.npc.SaveNPCHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.orientation.OrientationPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.PasturePokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpastureAllPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpasturePokemonHandler
|
||||
@@ -210,12 +166,7 @@ import com.cobblemon.mod.common.net.serverhandling.storage.pc.MovePartyPokemonTo
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.pc.ReleasePartyPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.pc.SwapPCPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.pc.UnlinkPlayerFromPCHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.AcceptTradeRequestHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.CancelTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.ChangeTradeAcceptanceHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.OfferTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.PerformTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.*
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
@@ -492,9 +443,6 @@ object CobblemonNetwork {
|
||||
// NPC packets
|
||||
list.add(PacketRegisterInfo(SaveNPCPacket.ID, SaveNPCPacket::decode, SaveNPCHandler))
|
||||
|
||||
// Orientation packet(s)
|
||||
list.add(PacketRegisterInfo(C2SUpdateOrientationPacket.ID, C2SUpdateOrientationPacket::decode, OrientationPacketHandler))
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
@@ -502,4 +450,4 @@ object CobblemonNetwork {
|
||||
//logger.info("[S->C] ${packet.type()}")
|
||||
Cobblemon.implementation.networkManager.sendPacketToPlayer(player, packet)
|
||||
}
|
||||
}
|
||||
}
|
||||
+53
-2
@@ -33,13 +33,12 @@ class PartyCheckCriterion(
|
||||
override fun matches(player: ServerPlayer, context: PlayerPartyStore): Boolean {
|
||||
val matches = mutableListOf<ResourceLocation>()
|
||||
party.forEach {
|
||||
if (it == "any".asIdentifierDefaultingNamespace("minecraft") || it == "any".asIdentifierDefaultingNamespace()) {
|
||||
if (it == "any".asIdentifierDefaultingNamespace()) {
|
||||
matches.add(it)
|
||||
}
|
||||
}
|
||||
val partyCount = context.count()
|
||||
if (matches.containsAll(party) && party.size == partyCount && matches.size == partyCount) return true
|
||||
matches.clear()
|
||||
context.iterator().forEach {
|
||||
if (party.contains(it.species.resourceIdentifier)) {
|
||||
matches.add(it.species.resourceIdentifier)
|
||||
@@ -48,3 +47,55 @@ class PartyCheckCriterion(
|
||||
return matches.containsAll(party) && matches.size == party.size
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*class PartyCheckCriterion(id: Identifier, entity: LootContextPredicate) : SimpleCriterionCondition<PartyCheckContext>(id, entity){
|
||||
val party = mutableListOf<Identifier>()
|
||||
override fun toJson(json: JsonObject) {
|
||||
json.add("party", JsonArray(party.size).also {
|
||||
party.forEach { pokemon -> it.add(pokemon.toString()) }
|
||||
})
|
||||
}
|
||||
|
||||
override fun fromJson(json: JsonObject) {
|
||||
party.clear()
|
||||
json.getAsJsonArray("party").forEach { element ->
|
||||
party.add(element.asString.asIdentifierDefaultingNamespace())
|
||||
}
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: PartyCheckContext): Boolean {
|
||||
val playerParty = player.party()
|
||||
val matches = mutableListOf<Identifier>()
|
||||
party.forEach {
|
||||
if (it == "any".asIdentifierDefaultingNamespace()) {
|
||||
matches.add(it)
|
||||
}
|
||||
}
|
||||
val partyCount = playerParty.count()
|
||||
if (matches.containsAll(party) && party.size == partyCount && matches.size == partyCount) return true
|
||||
playerParty.iterator().forEach {
|
||||
if (party.contains(it.species.resourceIdentifier)) {
|
||||
matches.add(it.species.resourceIdentifier)
|
||||
}
|
||||
}
|
||||
return matches.containsAll(party) && matches.size == partyCount
|
||||
}
|
||||
}
|
||||
|
||||
open class PartyCheckContext(val party : PlayerPartyStore)*/
|
||||
@@ -55,7 +55,6 @@ class ActiveDialogue(var playerEntity: ServerPlayer, var dialogueReference: Dial
|
||||
)
|
||||
|
||||
dialogueReference.initializationAction.invoke(this)
|
||||
setPage(currentPage)
|
||||
|
||||
if (!completion.isDone) {
|
||||
val packet = DialogueOpenedPacket(this, true)
|
||||
|
||||
@@ -52,6 +52,6 @@ object DialogueManager {
|
||||
fun stopDialogue(playerEntity: ServerPlayer) {
|
||||
val activeDialogue = playerEntity.activeDialogue ?: return
|
||||
DialogueClosedPacket(activeDialogue.dialogueId).sendToPlayer(playerEntity)
|
||||
activeDialogues.remove(playerEntity.uuid)
|
||||
activeDialogues.remove(activeDialogue.dialogueId)
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.drop
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@@ -41,23 +40,17 @@ interface DropEntry {
|
||||
* to be dropped.
|
||||
*/
|
||||
val percentage: Float
|
||||
|
||||
/**
|
||||
* The drop's quantity when doing selection from the [DropTable]. See the drop table documentation for more on how
|
||||
* this works.
|
||||
*/
|
||||
val quantity: Int
|
||||
|
||||
/**
|
||||
* The maximum number of times the item can be selected drop the [DropTable]. In most cases this will just be 1,
|
||||
* meaning that the item, once picked, cannot be picked again. A larger value will allow the same [DropEntry] from
|
||||
* appearing multiple times in a drop action.
|
||||
*/
|
||||
val maxSelectableTimes: Int
|
||||
|
||||
/** Whether this is considered a possible drop at the moment or not */
|
||||
fun canDrop(pokemon: Pokemon?): Boolean = true
|
||||
|
||||
/** The logic to use to actually drop the thing. */
|
||||
fun drop(entity: LivingEntity?, world: ServerLevel, pos: Vec3, player: ServerPlayer?)
|
||||
}
|
||||
@@ -11,13 +11,11 @@ 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
|
||||
|
||||
/**
|
||||
@@ -47,11 +45,9 @@ class DropTable {
|
||||
* Gets a drop list from this table as a list of [DropEntry]. You can specify the range of drop quantity totals
|
||||
* that will be possible, or if you leave it blank it will use [DropTable.amount].
|
||||
*/
|
||||
fun getDrops(amount: IntRange = this.amount, pokemon: Pokemon? = null): List<DropEntry> {
|
||||
fun getDrops(amount: IntRange = this.amount): List<DropEntry> {
|
||||
val chosenAmount = amount.random()
|
||||
val possibleDrops = entries.filter {
|
||||
it.quantity <= chosenAmount && it.canDrop(pokemon)
|
||||
}.toMutableList()
|
||||
val possibleDrops = entries.filter { it.quantity <= chosenAmount }.toMutableList()
|
||||
|
||||
if (possibleDrops.isEmpty()) {
|
||||
return emptyList()
|
||||
@@ -91,10 +87,11 @@ class DropTable {
|
||||
world: ServerLevel,
|
||||
pos: Vec3,
|
||||
player: ServerPlayer?,
|
||||
amount: IntRange = this.amount,
|
||||
pokemon: Pokemon? = null,
|
||||
amount: IntRange = this.amount
|
||||
) {
|
||||
val drops = getDrops(amount, pokemon).toMutableList()
|
||||
val drops = getDrops(amount).toMutableList()
|
||||
val heldItem = (entity as PokemonEntity).pokemon.heldItemNoCopy()
|
||||
if (!heldItem.isEmpty) entity.spawnAtLocation(heldItem.item)
|
||||
LOOT_DROPPED.postThen(
|
||||
event = LootDroppedEvent(this, player, entity, drops),
|
||||
ifSucceeded = { it.drops.forEach { it.drop(entity, world, pos, player) } }
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.drop
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.requirement.EvolutionRequirement
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
class EvolutionItemDropEntry : ItemDropEntry() {
|
||||
val requirements: MutableSet<EvolutionRequirement> = mutableSetOf()
|
||||
|
||||
override fun canDrop(pokemon: Pokemon?): Boolean = pokemon != null && requirements.all { it.check(pokemon) }
|
||||
}
|
||||
@@ -13,7 +13,6 @@ import com.cobblemon.mod.common.api.events.battles.BattleFledEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleStartedPostEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleStartedPreEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleVictoryEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.instruction.FormeChangeEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.instruction.MegaEvolutionEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.instruction.TerastallizationEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.instruction.ZMoveUsedEvent
|
||||
@@ -49,7 +48,6 @@ import com.cobblemon.mod.common.api.reactive.EventObservable
|
||||
import com.cobblemon.mod.common.api.reactive.Observable.Companion.filter
|
||||
import com.cobblemon.mod.common.api.reactive.Observable.Companion.map
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.riding.events.SelectDriverEvent
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
@@ -107,8 +105,6 @@ object CobblemonEvents {
|
||||
val TERASTALLIZATION = EventObservable<TerastallizationEvent>()
|
||||
@JvmField
|
||||
val ZPOWER_USED = EventObservable<ZMoveUsedEvent>()
|
||||
@JvmField
|
||||
val FORME_CHANGE = EventObservable<FormeChangeEvent>()
|
||||
|
||||
@JvmField
|
||||
val POKEMON_SENT_PRE = CancelableObservable<PokemonSentPreEvent>()
|
||||
@@ -197,8 +193,6 @@ object CobblemonEvents {
|
||||
@JvmField
|
||||
val POKEMON_SEEN = EventObservable<PokemonSeenEvent>()
|
||||
@JvmField
|
||||
val POKEMON_ASPECTS_CHANGED = EventObservable<PokemonAspectsChangedEvent>()
|
||||
@JvmField
|
||||
val POKEDEX_DATA_CHANGED_PRE = CancelableObservable<PokedexDataChangedEvent.Pre>()
|
||||
@JvmField
|
||||
val POKEDEX_DATA_CHANGED_POST = EventObservable<PokedexDataChangedEvent.Post>()
|
||||
@@ -233,12 +227,4 @@ object CobblemonEvents {
|
||||
val HATCH_EGG_PRE = CancelableObservable<HatchEggEvent.Pre>()
|
||||
@JvmField
|
||||
val HATCH_EGG_POST = EventObservable<HatchEggEvent.Post>()
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
//
|
||||
// Riding
|
||||
//
|
||||
// -------------------------------------------------------------------------------------
|
||||
@JvmField
|
||||
val SELECT_DRIVER = EventObservable<SelectDriverEvent>()
|
||||
}
|
||||
|
||||
+1
-24
@@ -8,16 +8,9 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.battles
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleContext
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
import java.util.function.Function
|
||||
|
||||
/**
|
||||
* Event fired when a [BattlePokemon] faints. Exposes the [BattlePokemon] that fainted and the [BattleContext]
|
||||
@@ -30,20 +23,4 @@ data class BattleFaintedEvent(
|
||||
override val battle: PokemonBattle,
|
||||
val killed: BattlePokemon,
|
||||
val context: BattleContext
|
||||
) : BattleEvent {
|
||||
val structContext = mutableMapOf<String, MoValue>(
|
||||
"battle" to battle.struct,
|
||||
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
|
||||
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
|
||||
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct },
|
||||
"pokemon" to killed.struct,
|
||||
"context" to QueryStruct(
|
||||
hashMapOf(
|
||||
"type" to Function { StringValue(context.type.name) },
|
||||
"origin" to Function { context.origin?.struct ?: DoubleValue(0.0) },
|
||||
"id" to Function { StringValue(context.id) },
|
||||
"turn_created" to Function { DoubleValue(context.turn.toDouble()) },
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
) : BattleEvent
|
||||
|
||||
+1
-12
@@ -8,12 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.battles
|
||||
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
|
||||
/**
|
||||
* Event fired when a [PokemonBattle] is fled by a [PlayerBattleActor].
|
||||
@@ -24,11 +20,4 @@ import com.cobblemon.mod.common.util.asArrayValue
|
||||
data class BattleFledEvent (
|
||||
override val battle: PokemonBattle,
|
||||
val player: PlayerBattleActor
|
||||
) : BattleEvent {
|
||||
val context = mutableMapOf<String, MoValue>(
|
||||
"battle" to battle.struct,
|
||||
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
|
||||
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
|
||||
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct }
|
||||
)
|
||||
}
|
||||
) : BattleEvent
|
||||
+2
-18
@@ -9,9 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.events.battles
|
||||
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
|
||||
/**
|
||||
@@ -23,14 +21,7 @@ import net.minecraft.network.chat.MutableComponent
|
||||
* @author Segfault Guy
|
||||
* @since March 26th 2023
|
||||
*/
|
||||
data class BattleStartedPreEvent (override val battle: PokemonBattle, var reason: MutableComponent? = null) : BattleEvent, Cancelable() {
|
||||
val context = mutableMapOf(
|
||||
"battle" to battle.struct,
|
||||
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
|
||||
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
|
||||
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct }
|
||||
)
|
||||
}
|
||||
data class BattleStartedPreEvent (override val battle: PokemonBattle, var reason: MutableComponent? = null) : BattleEvent, Cancelable()
|
||||
|
||||
/**
|
||||
* Event fired after a [PokemonBattle] starts.
|
||||
@@ -38,11 +29,4 @@ data class BattleStartedPreEvent (override val battle: PokemonBattle, var reason
|
||||
* @author Segfault Guy
|
||||
* @since March 26th 2023
|
||||
*/
|
||||
data class BattleStartedPostEvent (override val battle: PokemonBattle) : BattleEvent {
|
||||
val context = mutableMapOf(
|
||||
"battle" to battle.struct,
|
||||
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
|
||||
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
|
||||
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct }
|
||||
)
|
||||
}
|
||||
data class BattleStartedPostEvent (override val battle: PokemonBattle) : BattleEvent
|
||||
-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.battles.instruction
|
||||
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleEvent
|
||||
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
|
||||
/**
|
||||
* Event that is fired when a Pokemon changes Forme in battle.
|
||||
* @param battle The battle where the change occurred.
|
||||
* @param pokemon The Pokemon that changed Forme.
|
||||
*/
|
||||
data class FormeChangeEvent(
|
||||
override val battle: PokemonBattle,
|
||||
val pokemon: BattlePokemon,
|
||||
val formeName: String
|
||||
) : BattleEvent {
|
||||
val context = mutableMapOf(
|
||||
"battle" to battle.struct,
|
||||
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
|
||||
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
|
||||
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct },
|
||||
"pokemon" to pokemon.struct,
|
||||
"forme" to StringValue(formeName)
|
||||
)
|
||||
}
|
||||
+1
-13
@@ -8,25 +8,13 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.battles.instruction
|
||||
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
|
||||
/**
|
||||
* Event that is fired when a Pokemon Mega Evolves.
|
||||
* @param battle The Pokemon Battle.
|
||||
* @param pokemon The Pokemon that Mega Evolves.
|
||||
*/
|
||||
data class MegaEvolutionEvent(val battle: PokemonBattle, val pokemon: BattlePokemon) {
|
||||
val context = mutableMapOf<String, MoValue>(
|
||||
"battle" to battle.struct,
|
||||
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
|
||||
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
|
||||
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct },
|
||||
"pokemon" to pokemon.struct
|
||||
)
|
||||
}
|
||||
data class MegaEvolutionEvent(val battle: PokemonBattle, val pokemon: BattlePokemon)
|
||||
|
||||
+1
-14
@@ -8,13 +8,9 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.battles.instruction
|
||||
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.api.types.tera.TeraType
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
|
||||
/**
|
||||
* Event that is fired when a Pokemon Terastallizes.
|
||||
@@ -26,13 +22,4 @@ data class TerastallizationEvent(
|
||||
val battle: PokemonBattle,
|
||||
val pokemon: BattlePokemon,
|
||||
val teraType: TeraType
|
||||
) {
|
||||
val context = mutableMapOf<String, MoValue>(
|
||||
"battle" to battle.struct,
|
||||
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
|
||||
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
|
||||
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct },
|
||||
"pokemon" to pokemon.struct,
|
||||
"tera_type" to StringValue(teraType.id.toString())
|
||||
)
|
||||
}
|
||||
)
|
||||
+1
-13
@@ -8,24 +8,12 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.battles.instruction
|
||||
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
|
||||
/**
|
||||
* Event that is fired when a Pokemon uses a Z-Move.
|
||||
* @param battle The Pokemon Battle.
|
||||
* @param pokemon The Pokemon that uses the Z-Move.
|
||||
*/
|
||||
data class ZMoveUsedEvent(val battle: PokemonBattle, val pokemon: BattlePokemon) {
|
||||
val context = mutableMapOf<String, MoValue>(
|
||||
"battle" to battle.struct,
|
||||
"players" to battle.actors.filter { it.type == ActorType.PLAYER }.asArrayValue { it.struct },
|
||||
"npcs" to battle.actors.filter { it.type == ActorType.NPC }.asArrayValue { it.struct },
|
||||
"wild_pokemon" to battle.actors.filter { it.type == ActorType.WILD }.asArrayValue { it.struct },
|
||||
"pokemon" to pokemon.struct
|
||||
)
|
||||
}
|
||||
data class ZMoveUsedEvent(val battle: PokemonBattle, val pokemon: BattlePokemon)
|
||||
-12
@@ -8,13 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.farming
|
||||
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.apricorn.Apricorn
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.util.toArrayStruct
|
||||
import com.cobblemon.mod.common.util.worldRegistry
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
@@ -31,11 +26,4 @@ class ApricornHarvestEvent(
|
||||
fun getBlock(): BlockState {
|
||||
return world.getBlockState(pos)
|
||||
}
|
||||
|
||||
val context = mutableMapOf(
|
||||
"player" to player.asMoLangValue(),
|
||||
"apricorn" to StringValue(apricorn.name),
|
||||
"world" to world.worldRegistry.wrapAsHolder(world).asMoLangValue(Registries.DIMENSION),
|
||||
"pos" to pos.toArrayStruct()
|
||||
)
|
||||
}
|
||||
+1
-2
@@ -9,11 +9,10 @@
|
||||
package com.cobblemon.mod.common.api.events.fishing
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
/**
|
||||
* Event that is fired when a fishing rod is reeled.
|
||||
* @param rod The ItemStack of the rod that is being reeled.
|
||||
*/
|
||||
class PokerodReelEvent(val player: Player, val rod: ItemStack) : Cancelable()
|
||||
class PokerodReelEvent(val rod: ItemStack) : Cancelable()
|
||||
+1
-7
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common.api.events.pokeball
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
|
||||
@@ -19,9 +18,4 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
class ThrownPokeballHitEvent(
|
||||
val pokeBall : EmptyPokeBallEntity,
|
||||
val pokemon : PokemonEntity
|
||||
) : Cancelable() {
|
||||
val context = mutableMapOf(
|
||||
"pokeball" to pokeBall.struct,
|
||||
"pokemon" to pokemon.asMoLangValue()
|
||||
)
|
||||
}
|
||||
) : Cancelable()
|
||||
+4
-18
@@ -8,28 +8,14 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokedex.scanning
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData
|
||||
import com.cobblemon.mod.common.pokedex.scanner.ScannableEntity
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
data class PokemonScannedEvent(val player: ServerPlayer, val scannedPokemonEntityData: PokedexEntityData, val scannedEntity: ScannableEntity) {
|
||||
val isOwned: Boolean
|
||||
get() = scannedPokemonEntityData.pokemon.getOwnerUUID() == player.uuid
|
||||
val pokedexEntityData: PokedexEntityData
|
||||
get() = scannedPokemonEntityData
|
||||
|
||||
val context = mutableMapOf(
|
||||
"player" to player.asMoLangValue(),
|
||||
"pokemon" to scannedPokemonEntityData.pokemon.struct,
|
||||
"disguise" to (scannedPokemonEntityData.disguise?.struct ?: DoubleValue.ZERO),
|
||||
"entity" to {
|
||||
when (scannedEntity) {
|
||||
is LivingEntity -> scannedEntity.asMostSpecificMoLangValue()
|
||||
else -> DoubleValue.ZERO
|
||||
}
|
||||
},
|
||||
)
|
||||
val isOwned: Boolean
|
||||
get() = scannedPokemonEntityData.ownerUUID == player.uuid
|
||||
}
|
||||
+2
-9
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
/**
|
||||
@@ -19,11 +18,5 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
*/
|
||||
data class FriendshipUpdatedEvent(
|
||||
val pokemon: Pokemon,
|
||||
val newFriendshipInitial: Int
|
||||
)
|
||||
{
|
||||
var newFriendship: Int = newFriendshipInitial
|
||||
set(value) {
|
||||
field = value.coerceIn(0, Cobblemon.config.maxPokemonFriendship)
|
||||
}
|
||||
}
|
||||
var newFriendship: Int
|
||||
)
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
/**
|
||||
@@ -17,10 +16,4 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
* @author Hiroku
|
||||
* @since August 5th, 2022
|
||||
*/
|
||||
class LevelUpEvent(val pokemon: Pokemon, val oldLevel: Int, var newLevel: Int) {
|
||||
val context = mutableMapOf(
|
||||
"pokemon" to pokemon.struct,
|
||||
"old_level" to DoubleValue(oldLevel.toDouble()),
|
||||
"new_level" to DoubleValue(newLevel.toDouble())
|
||||
)
|
||||
}
|
||||
class LevelUpEvent(val pokemon: Pokemon, val oldLevel: Int, var newLevel: Int)
|
||||
+7
-5
@@ -17,14 +17,16 @@ import com.cobblemon.mod.common.api.pokedex.AbstractPokedexManager
|
||||
import com.cobblemon.mod.common.api.pokedex.FormDexRecord
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.getPlayer
|
||||
import com.mojang.datafixers.util.Either
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* Event that fires when a Pokémon's information is gained or updated in the Pokédex.
|
||||
*/
|
||||
sealed interface PokedexDataChangedEvent {
|
||||
val dataSource: PokedexEntityData
|
||||
val dataSource: Either<PokedexEntityData, Pokemon>
|
||||
val knowledge: PokedexEntryProgress
|
||||
val playerUUID: UUID
|
||||
val record: FormDexRecord
|
||||
@@ -35,22 +37,22 @@ sealed interface PokedexDataChangedEvent {
|
||||
fun getContext(): MutableMap<String, MoValue> {
|
||||
return mutableMapOf(
|
||||
"player" to (playerUUID.getPlayer()?.asMoLangValue() ?: DoubleValue.ZERO),
|
||||
"pokemon" to dataSource.pokemon.struct,
|
||||
"disguise" to (dataSource.disguise?.struct ?: DoubleValue.ZERO),
|
||||
"pokemon" to dataSource.map({ DoubleValue.ZERO }, { it.struct }),
|
||||
"data" to dataSource.map({ it.struct }, { DoubleValue.ZERO }),
|
||||
"knowledge" to StringValue(knowledge.name.lowercase()),
|
||||
"pokedex" to pokedexManager.struct
|
||||
)
|
||||
}
|
||||
|
||||
class Pre(
|
||||
override val dataSource: PokedexEntityData,
|
||||
override val dataSource: Either<PokedexEntityData, Pokemon>,
|
||||
override val knowledge: PokedexEntryProgress,
|
||||
override val playerUUID: UUID,
|
||||
override val record: FormDexRecord
|
||||
) : PokedexDataChangedEvent, Cancelable()
|
||||
|
||||
class Post(
|
||||
override val dataSource: PokedexEntityData,
|
||||
override val dataSource: Either<PokedexEntityData, Pokemon>,
|
||||
override val knowledge: PokedexEntryProgress,
|
||||
override val playerUUID: UUID,
|
||||
override val record: FormDexRecord
|
||||
|
||||
-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.events.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import java.util.*
|
||||
|
||||
data class PokemonAspectsChangedEvent(
|
||||
val ownerId: UUID?,
|
||||
val pokemon: Pokemon,
|
||||
)
|
||||
+1
-7
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
/**
|
||||
@@ -17,9 +16,4 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
data class PokemonFaintedEvent(
|
||||
val pokemon: Pokemon,
|
||||
var faintedTimer: Int
|
||||
) {
|
||||
val context = mutableMapOf(
|
||||
"pokemon" to pokemon.struct,
|
||||
"fainted_timer" to DoubleValue(faintedTimer)
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
+1
-7
@@ -8,16 +8,10 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import java.util.UUID
|
||||
|
||||
data class PokemonGainedEvent(
|
||||
val playerId: UUID,
|
||||
val pokemon: Pokemon
|
||||
) {
|
||||
val context = mutableMapOf(
|
||||
"player_id" to StringValue(playerId.toString()),
|
||||
"pokemon" to pokemon.struct
|
||||
)
|
||||
}
|
||||
)
|
||||
@@ -96,12 +96,11 @@ interface PokemonSelectingItem {
|
||||
player.sendSystemMessage(battleLang("bagitem.invalid").red())
|
||||
} else {
|
||||
battlePokemon.actor.forceChoose(BagItemActionResponse(bagItem, battlePokemon))
|
||||
val stackName = BuiltInRegistries.ITEM.getKey(stack.item)
|
||||
if (!player.isCreative) {
|
||||
stack.shrink(1)
|
||||
battlePokemon.actor.itemsUsed.add(bagItem)
|
||||
}
|
||||
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(battlePokemon.effectedPokemon.species.resourceIdentifier, stackName))
|
||||
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(battlePokemon.effectedPokemon.species.resourceIdentifier, BuiltInRegistries.ITEM.getKey(stack.item)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,4 +148,4 @@ interface PokemonSelectingItem {
|
||||
|
||||
return InteractionResultHolder.success(stack)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -514,17 +514,6 @@ object MoLangFunctions {
|
||||
.map { it.asMostSpecificMoLangValue() }
|
||||
.asArrayValue()
|
||||
}
|
||||
map.put("is_standing_on_blocks") { params ->
|
||||
val depth = params.getDouble(0).toInt()
|
||||
val blocks: MutableSet<Block> = mutableSetOf()
|
||||
for (blockIndex in 1..<params.params.size) {
|
||||
val blockString = params.getString(blockIndex)
|
||||
val block = BuiltInRegistries.BLOCK.get(blockString.asIdentifierDefaultingNamespace("minecraft"))
|
||||
blocks.add(block)
|
||||
}
|
||||
|
||||
return@put if (entity.isStandingOn(blocks, depth)) DoubleValue.ONE else DoubleValue.ZERO
|
||||
}
|
||||
if (entity is PosableEntity) {
|
||||
map.put("play_animation") { params ->
|
||||
val animation = params.getString(0)
|
||||
@@ -614,8 +603,7 @@ object MoLangFunctions {
|
||||
val context = ActionEffectContext(
|
||||
actionEffect = actionEffect,
|
||||
providers = mutableListOf(NPCProvider(npc)),
|
||||
runtime = runtime,
|
||||
level = npc.level()
|
||||
runtime = runtime
|
||||
)
|
||||
npc.actionEffect = context
|
||||
npc.brain.setMemory(CobblemonMemories.ACTIVE_ACTION_EFFECT, context)
|
||||
@@ -718,11 +706,6 @@ object MoLangFunctions {
|
||||
map.put("form") { StringValue(pokemon.form.name) }
|
||||
map.put("weight") { DoubleValue(pokemon.species.weight.toDouble()) }
|
||||
map.put("matches") { params -> DoubleValue(params.getString(0).toProperties().matches(pokemon)) }
|
||||
map.put("apply") { params ->
|
||||
params.getString(0).toProperties().apply(pokemon)
|
||||
DoubleValue.ONE
|
||||
}
|
||||
map.put("owner") { pokemon.getOwnerPlayer()?.asMoLangValue() ?: DoubleValue.ZERO }
|
||||
map
|
||||
}
|
||||
)
|
||||
|
||||
@@ -54,15 +54,7 @@ class BenchedMoves : Iterable<BenchedMove> {
|
||||
}
|
||||
}
|
||||
|
||||
fun add(benchedMove: BenchedMove): Boolean {
|
||||
if (any { it.moveTemplate == benchedMove.moveTemplate }) {
|
||||
return false
|
||||
}
|
||||
|
||||
doThenEmit { benchedMoves.add(benchedMove) }
|
||||
return true
|
||||
}
|
||||
|
||||
fun add(benchedMove: BenchedMove) = doThenEmit { benchedMoves.add(benchedMove) }
|
||||
fun addAll(benchedMoves: Iterable<BenchedMove>) = doThenEmit { this.benchedMoves.addAll(benchedMoves) }
|
||||
fun clear() = doThenEmit { benchedMoves.clear() }
|
||||
fun remove(benchedMove: BenchedMove) = doThenEmit { benchedMoves.remove(benchedMove) }
|
||||
|
||||
@@ -8,12 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.moves
|
||||
|
||||
import com.bedrockk.molang.runtime.MoParams
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunctions
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.moves.categories.DamageCategory
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
@@ -31,7 +25,6 @@ import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import kotlin.math.ceil
|
||||
import kotlin.properties.Delegates
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import java.util.function.Function
|
||||
|
||||
/**
|
||||
* Representing a Move based on some template and with current PP and the number of raised PP stages.
|
||||
@@ -97,21 +90,6 @@ open class Move(
|
||||
val maxPp: Int
|
||||
get() = template.pp + raisedPpStages * template.pp / 5
|
||||
|
||||
val struct: QueryStruct = ObjectValue(this).also {
|
||||
it.addFunctions(
|
||||
hashMapOf(
|
||||
"name" to Function { StringValue(name) },
|
||||
"display_name" to Function { StringValue(displayName.string) },
|
||||
"description" to Function { StringValue(description.string) },
|
||||
"type" to Function { StringValue(type.name) },
|
||||
"damage_category" to Function { StringValue(damageCategory.name) },
|
||||
"power" to Function { DoubleValue(power) },
|
||||
"accuracy" to Function { DoubleValue(accuracy) },
|
||||
"max_pp" to Function { DoubleValue(maxPp.toDouble()) }
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** Raises the max PP and rescales the current PP value. Returns false if it was already maxed out. */
|
||||
fun raiseMaxPP(amount: Int): Boolean {
|
||||
val oldPp = maxPp
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.moves
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.net.IntSize
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
@@ -29,22 +27,6 @@ class MoveSet : Iterable<Move> {
|
||||
|
||||
private val moves = arrayOfNulls<Move>(MOVE_COUNT)
|
||||
|
||||
fun toStruct(): QueryStruct {
|
||||
val struct = QueryStruct(hashMapOf())
|
||||
struct.addFunction("move") { params ->
|
||||
val index = params.getInt(0) as? Int ?: return@addFunction null
|
||||
return@addFunction get(index)?.struct
|
||||
}
|
||||
struct.addFunction("has_move") { params ->
|
||||
val moveID = params.getString(0) ?: return@addFunction null
|
||||
return@addFunction if(moves.any { it?.template?.name == moveID }) DoubleValue(1.0) else DoubleValue(0.0)
|
||||
}
|
||||
struct.addFunction("get_move") { params ->
|
||||
val moveID = params.getString(0) ?: return@addFunction null
|
||||
return@addFunction moves.firstOrNull { it?.template?.name == moveID }?.struct
|
||||
}
|
||||
return struct
|
||||
}
|
||||
|
||||
override fun iterator() = moves.filterNotNull().iterator()
|
||||
|
||||
@@ -134,21 +116,18 @@ class MoveSet : Iterable<Move> {
|
||||
return json
|
||||
}
|
||||
|
||||
fun add(move: Move): Boolean {
|
||||
fun add(move: Move) {
|
||||
if (any { it.template == move.template }) {
|
||||
return false
|
||||
return
|
||||
}
|
||||
|
||||
for (i in 0 until MOVE_COUNT) {
|
||||
if (moves[i] == null) {
|
||||
moves[i] = move
|
||||
move.observable.subscribe { this.update() }
|
||||
update()
|
||||
return true
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
fun update() {
|
||||
|
||||
+1
-3
@@ -15,7 +15,6 @@ import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.level.Level
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
/**
|
||||
@@ -70,8 +69,7 @@ class ActionEffectContext(
|
||||
val runtime: MoLangRuntime,
|
||||
var canBeInterrupted: Boolean = false,
|
||||
var interrupted: Boolean = false,
|
||||
var currentKeyframes: MutableList<ActionEffectKeyframe> = mutableListOf(),
|
||||
var level: Level? = null
|
||||
var currentKeyframes: MutableList<ActionEffectKeyframe> = mutableListOf()
|
||||
) {
|
||||
inline fun <reified T> findOneProvider() = providers.filterIsInstance<T>().firstOrNull()
|
||||
}
|
||||
|
||||
+6
-32
@@ -24,7 +24,6 @@ import net.minecraft.server.level.ServerLevel
|
||||
|
||||
/**
|
||||
* Spawns particles on the entity based on the given particle effect and locator.
|
||||
* Optionally, you can specify target that ends up setting the destination pos on the spawned ParticleStorm
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since January 21st, 2024
|
||||
@@ -33,25 +32,14 @@ class EntityParticlesActionEffectKeyframe : ConditionalActionEffectKeyframe(), E
|
||||
override val entityCondition = "q.entity.is_user".asExpressionLike()
|
||||
var effect: String? = null
|
||||
var locators: List<String> = listOf("target")
|
||||
var targetLocators: Set<String>? = null
|
||||
|
||||
val delay: ExpressionLike = "0".asExpressionLike()
|
||||
val visibilityRange = 200
|
||||
|
||||
override fun playWhenTrue(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
val allEntities = context.providers
|
||||
val entities = context.providers
|
||||
.filterIsInstance<EntityProvider>()
|
||||
.flatMap { prov -> prov.entities }
|
||||
|
||||
val userEntities = context.providers
|
||||
.filterIsInstance<UsersProvider>()
|
||||
.flatMap { prov -> prov.entities }
|
||||
|
||||
val targetEntities = context.providers
|
||||
.filterIsInstance<TargetsProvider>()
|
||||
.flatMap { prov -> prov.entities}
|
||||
|
||||
val sourceEntities = allEntities.filter { test(context, it, it in userEntities) }
|
||||
.flatMap { prov -> prov.entities.filter { test(context, it, isUser = prov is UsersProvider) } }
|
||||
|
||||
val effectIdentifier = try {
|
||||
effect?.asExpressionLike()?.resolveString(context.runtime)?.takeIf { it != "0" } ?: effect
|
||||
@@ -59,24 +47,10 @@ class EntityParticlesActionEffectKeyframe : ConditionalActionEffectKeyframe(), E
|
||||
effect
|
||||
}?.asIdentifierDefaultingNamespace() ?: return skip()
|
||||
|
||||
//Things could be a little weird here since TECHNICALLY it might be possible for a battle to be happening across dimensions
|
||||
val calcedLevel = (context.level as? ServerLevel) ?: allEntities.first().level() as ServerLevel
|
||||
val players = calcedLevel.getPlayers { player ->
|
||||
allEntities.any { player.distanceTo(it) <= visibilityRange }
|
||||
}
|
||||
|
||||
|
||||
sourceEntities.filter { it is PosableEntity }.forEach { entity ->
|
||||
if (targetLocators == null) {
|
||||
val packet = SpawnSnowstormEntityParticlePacket(effectIdentifier, entity.id, locators)
|
||||
packet.sendToPlayers(players)
|
||||
}
|
||||
else {
|
||||
targetEntities.forEach { targetEntity ->
|
||||
val packet = SpawnSnowstormEntityParticlePacket(effectIdentifier, entity.id, locators, targetEntity.id, targetLocators!!.toList())
|
||||
packet.sendToPlayers(players)
|
||||
}
|
||||
}
|
||||
entities.filter { it is PosableEntity }.forEach { entity ->
|
||||
val packet = SpawnSnowstormEntityParticlePacket(effectIdentifier, entity.id, (locators).toList())
|
||||
val players = (entity.level() as ServerLevel).getPlayers { it.distanceTo(entity) <= visibilityRange }
|
||||
packet.sendToPlayers(players)
|
||||
}
|
||||
|
||||
return delayedFuture(seconds = delay.resolveFloat(context.runtime))
|
||||
|
||||
@@ -38,9 +38,8 @@ class NPCClass {
|
||||
var resourceIdentifier: ResourceLocation = cobblemonResource("dummy")
|
||||
var names: MutableList<Component> = mutableListOf()
|
||||
var aspects: MutableSet<String> = mutableSetOf() // These only make sense when applied via presets
|
||||
var baseScale: Float = 1F
|
||||
var hitbox = EntityDimensions.scalable(0.6F, 1.8F).withEyeHeight(1.62F)
|
||||
var modelScale: Float = 0.9375F
|
||||
var modelScale: Float = 0.94F
|
||||
var battleConfiguration = NPCBattleConfiguration()
|
||||
var interaction: NPCInteractConfiguration? = null
|
||||
var canDespawn = true
|
||||
@@ -57,14 +56,12 @@ class NPCClass {
|
||||
var isInvulnerable = false
|
||||
var isLeashable = true
|
||||
var allowProjectileHits = true
|
||||
var hideNameTag = false
|
||||
|
||||
// If you're adding stuff here, add it to NPCPreset and NPCClassAdapter too
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeString(resourceIdentifier.toString())
|
||||
buffer.writeCollection(names) { _, v -> buffer.writeText(v) }
|
||||
buffer.writeFloat(baseScale)
|
||||
buffer.writeFloat(hitbox.width)
|
||||
buffer.writeFloat(hitbox.height)
|
||||
buffer.writeBoolean(hitbox.fixed)
|
||||
@@ -98,13 +95,11 @@ class NPCClass {
|
||||
buffer.writeBoolean(isInvulnerable)
|
||||
buffer.writeBoolean(isLeashable)
|
||||
buffer.writeBoolean(allowProjectileHits)
|
||||
buffer.writeBoolean(hideNameTag)
|
||||
}
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
resourceIdentifier = ResourceLocation.parse(buffer.readString().toString())
|
||||
names = buffer.readList { buffer.readText().copy() }.toMutableList()
|
||||
baseScale = buffer.readFloat()
|
||||
val length = buffer.readFloat()
|
||||
val width = buffer.readFloat()
|
||||
val fixed = buffer.readBoolean()
|
||||
@@ -150,6 +145,5 @@ class NPCClass {
|
||||
isInvulnerable = buffer.readBoolean()
|
||||
isLeashable = buffer.readBoolean()
|
||||
allowProjectileHits = buffer.readBoolean()
|
||||
hideNameTag = buffer.readBoolean()
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,6 @@ class NPCPreset {
|
||||
var canDespawn: Boolean? = null
|
||||
var interaction: NPCInteractConfiguration? = null
|
||||
var names: MutableSet<Component>? = null
|
||||
var baseScale: Float? = null
|
||||
var hitbox: EntityDimensions? = null
|
||||
var ai: List<BrainConfig>? = null
|
||||
var skill: Int? = null
|
||||
@@ -37,7 +36,6 @@ class NPCPreset {
|
||||
var isInvulnerable: Boolean? = null
|
||||
var isLeashable: Boolean? = null
|
||||
var allowProjectileHits: Boolean? = null
|
||||
var hideNameTag: Boolean? = null
|
||||
|
||||
fun applyTo(npcClass: NPCClass) {
|
||||
resourceIdentifier?.let { npcClass.resourceIdentifier = it }
|
||||
@@ -53,7 +51,6 @@ class NPCPreset {
|
||||
// aiScripts?.let { npcClass.aiScripts.addAll(it) }
|
||||
interaction?.let { npcClass.interaction = it }
|
||||
names?.let { npcClass.names.addAll(it) }
|
||||
baseScale?.let { npcClass.baseScale = it }
|
||||
hitbox?.let { npcClass.hitbox = it }
|
||||
skill?.let { npcClass.skill = it }
|
||||
autoHealParty?.let { npcClass.autoHealParty = it }
|
||||
@@ -64,6 +61,5 @@ class NPCPreset {
|
||||
isInvulnerable?.let { npcClass.isInvulnerable = it }
|
||||
isLeashable?.let { npcClass.isLeashable = it }
|
||||
allowProjectileHits?.let { npcClass.allowProjectileHits = it }
|
||||
hideNameTag?.let { npcClass.hideNameTag = it }
|
||||
}
|
||||
}
|
||||
@@ -78,7 +78,6 @@ any number of presets and the properties of those presets will be merged into th
|
||||
"skill": 5,
|
||||
"autoHealParty": true,
|
||||
"randomizePartyOrder": true,
|
||||
"hideNameTag": false,
|
||||
"party": {
|
||||
"type": "simple",
|
||||
"pokemon": [
|
||||
@@ -412,7 +411,4 @@ Pokémon in the party.
|
||||
|
||||
### ai
|
||||
The AI property is an array of brain configurations. This is used to configure the behaviours of the NPC. See
|
||||
the documentation for brain configurations at [AI Configuration](../ai/config/README.md).
|
||||
|
||||
### hideNameTag
|
||||
Whether the NPC's nametag should be hidden or not. Defaults to false.
|
||||
the documentation for brain configurations at [AI Configuration](../ai/config/README.md).
|
||||
@@ -202,8 +202,6 @@ object PokeBalls : JsonDataRegistry<PokeBall> {
|
||||
// Luxury ball effect, low priority as it must be triggered before soothe bell as of gen 4
|
||||
CobblemonEvents.FRIENDSHIP_UPDATED.subscribe(priority = Priority.LOW) { event ->
|
||||
var increment = (event.newFriendship - event.pokemon.friendship).toFloat()
|
||||
if (increment <= 0) //these affects are only meant to affect positive gains
|
||||
return@subscribe
|
||||
if (increment <= 1F) {
|
||||
event.pokemon.caughtBall.effects.filterIsInstance<FriendshipEarningBoostEffect>()
|
||||
.forEach { increment *= it.multiplier }
|
||||
|
||||
+1
-4
@@ -42,10 +42,7 @@ class BaseStatModifier(
|
||||
|
||||
override fun behavior(thrower: LivingEntity, pokemon: Pokemon): CatchRateModifier.Behavior = CatchRateModifier.Behavior.MULTIPLY
|
||||
|
||||
override fun isValid(thrower: LivingEntity, pokemon: Pokemon): Boolean {
|
||||
val valStat = pokemon.form.baseStats[this.stat] ?: return false
|
||||
return comparator(valStat)
|
||||
}
|
||||
override fun isValid(thrower: LivingEntity, pokemon: Pokemon): Boolean = pokemon.form.baseStats[this.stat] != null
|
||||
|
||||
override fun modifyCatchRate(currentCatchRate: Float, thrower: LivingEntity, pokemon: Pokemon): Float = this.behavior(thrower, pokemon).mutator(currentCatchRate, this.value(thrower, pokemon))
|
||||
|
||||
|
||||
+3
-21
@@ -32,18 +32,6 @@ abstract class AbstractPokedexManager {
|
||||
markDirty()
|
||||
}
|
||||
|
||||
fun deleteFormRecord(speciesId: ResourceLocation, formName: String) {
|
||||
val speciesRecord = speciesRecords[speciesId] ?: return
|
||||
speciesRecord.deleteFormRecord(formName)
|
||||
|
||||
if (speciesRecord.isFormRecordsEmpty) {
|
||||
deleteSpeciesRecord(speciesId)
|
||||
return
|
||||
}
|
||||
|
||||
markDirty()
|
||||
}
|
||||
|
||||
fun getSpeciesRecord(speciesId: ResourceLocation): SpeciesDexRecord? {
|
||||
return speciesRecords[speciesId]
|
||||
}
|
||||
@@ -96,21 +84,15 @@ abstract class AbstractPokedexManager {
|
||||
}
|
||||
|
||||
fun getNewInformation(pokedexEntityData: PokedexEntityData): PokedexLearnedInformation {
|
||||
val speciesRecord = getSpeciesRecord(pokedexEntityData.getApparentSpecies().resourceIdentifier)
|
||||
val speciesRecord = getSpeciesRecord(pokedexEntityData.species.resourceIdentifier)
|
||||
if (speciesRecord == null || speciesRecord.getKnowledge() == PokedexEntryProgress.NONE) {
|
||||
return PokedexLearnedInformation.SPECIES
|
||||
}
|
||||
val formRecord = speciesRecord.getFormRecord(pokedexEntityData.getApparentForm().name)
|
||||
val formRecord = speciesRecord.getFormRecord(pokedexEntityData.form.name)
|
||||
if (formRecord == null || formRecord.knowledge == PokedexEntryProgress.NONE) {
|
||||
return PokedexLearnedInformation.FORM
|
||||
}
|
||||
|
||||
// Can't update aspects on a disguise
|
||||
if (pokedexEntityData.disguise != null) {
|
||||
return PokedexLearnedInformation.NONE
|
||||
}
|
||||
|
||||
if (pokedexEntityData.pokemon.aspects.any { !speciesRecord.hasAspect(it) } || pokedexEntityData.pokemon.gender !in formRecord.getGenders() || !formRecord.hasSeenShinyState(pokedexEntityData.pokemon.shiny)) {
|
||||
if (pokedexEntityData.aspects.any{ !speciesRecord.hasAspect(it) } || pokedexEntityData.gender !in formRecord.getGenders() || !formRecord.hasSeenShinyState(pokedexEntityData.shiny)) {
|
||||
return PokedexLearnedInformation.VARIATION
|
||||
}
|
||||
return PokedexLearnedInformation.NONE
|
||||
|
||||
@@ -13,7 +13,6 @@ import com.bedrockk.molang.runtime.struct.VariableStruct
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.pokemon.PokedexDataChangedEvent
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
@@ -89,15 +88,21 @@ class FormDexRecord {
|
||||
it.knowledge = knowledge
|
||||
}
|
||||
|
||||
fun encountered(pokemon: Pokemon) {
|
||||
if (wouldBeDifferent(pokemon, PokedexEntryProgress.ENCOUNTERED)) {
|
||||
addInformation(pokemon, PokedexEntryProgress.ENCOUNTERED)
|
||||
}
|
||||
}
|
||||
|
||||
fun encountered(pokedexEntityData: PokedexEntityData) {
|
||||
if (wouldBeDifferent(pokedexEntityData, PokedexEntryProgress.ENCOUNTERED)) {
|
||||
addInformation(pokedexEntityData, PokedexEntryProgress.ENCOUNTERED)
|
||||
}
|
||||
}
|
||||
|
||||
fun caught(pokedexEntityData: PokedexEntityData) {
|
||||
if (wouldBeDifferent(pokedexEntityData, PokedexEntryProgress.CAUGHT)) {
|
||||
addInformation(pokedexEntityData, PokedexEntryProgress.CAUGHT)
|
||||
fun caught(pokemon: Pokemon) {
|
||||
if (wouldBeDifferent(pokemon, PokedexEntryProgress.CAUGHT)) {
|
||||
addInformation(pokemon, PokedexEntryProgress.CAUGHT)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,11 +112,8 @@ class FormDexRecord {
|
||||
|
||||
//Used when granting all entries in dex, should figure out better way
|
||||
fun addAllShinyStatesAndGenders() {
|
||||
val form = PokemonSpecies.getByIdentifier(speciesDexRecord.id)?.getFormByName(formName)
|
||||
genders.addAll(form?.possibleGenders ?: listOf(Gender.MALE, Gender.FEMALE))
|
||||
|
||||
genders.addAll(listOf(Gender.MALE, Gender.FEMALE))
|
||||
seenShinyStates.addAll(listOf("shiny", "normal"))
|
||||
speciesDexRecord.onFormRecordUpdated(this)
|
||||
}
|
||||
|
||||
fun setKnowledgeProgress(newKnowledge: PokedexEntryProgress) {
|
||||
@@ -119,18 +121,47 @@ class FormDexRecord {
|
||||
speciesDexRecord.onFormRecordUpdated(this)
|
||||
}
|
||||
|
||||
private fun addInformation(pokemon: Pokemon, knowledge: PokedexEntryProgress) {
|
||||
(speciesDexRecord.pokedexManager as? PokedexManager)?.let { pokedexManager ->
|
||||
CobblemonEvents.POKEDEX_DATA_CHANGED_PRE.postThen(
|
||||
PokedexDataChangedEvent.Pre(
|
||||
Either.right(pokemon),
|
||||
knowledge,
|
||||
pokedexManager.uuid,
|
||||
this
|
||||
),
|
||||
ifSucceeded = {
|
||||
genders.add(pokemon.gender)
|
||||
seenShinyStates.add(if (pokemon.shiny) "shiny" else "normal")
|
||||
if (knowledge.ordinal > this.knowledge.ordinal) {
|
||||
this.knowledge = knowledge
|
||||
}
|
||||
speciesDexRecord.addInformation(pokemon, knowledge)
|
||||
speciesDexRecord.onFormRecordUpdated(this)
|
||||
CobblemonEvents.POKEDEX_DATA_CHANGED_POST.post(
|
||||
PokedexDataChangedEvent.Post(
|
||||
Either.right(pokemon),
|
||||
knowledge,
|
||||
pokedexManager.uuid,
|
||||
this
|
||||
)
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun addInformation(pokedexEntityData: PokedexEntityData, knowledge: PokedexEntryProgress) {
|
||||
(speciesDexRecord.pokedexManager as? PokedexManager)?.let { pokedexManager ->
|
||||
CobblemonEvents.POKEDEX_DATA_CHANGED_PRE.postThen(
|
||||
PokedexDataChangedEvent.Pre(
|
||||
pokedexEntityData,
|
||||
knowledge,
|
||||
pokedexManager.uuid,
|
||||
this
|
||||
Either.left(pokedexEntityData),
|
||||
knowledge,
|
||||
pokedexManager.uuid,
|
||||
this
|
||||
),
|
||||
ifSucceeded = {
|
||||
genders.add(pokedexEntityData.pokemon.gender)
|
||||
seenShinyStates.add(if (pokedexEntityData.pokemon.shiny) "shiny" else "normal")
|
||||
genders.add(pokedexEntityData.gender)
|
||||
seenShinyStates.add(if (pokedexEntityData.shiny) "shiny" else "normal")
|
||||
if (knowledge.ordinal > this.knowledge.ordinal) {
|
||||
this.knowledge = knowledge
|
||||
}
|
||||
@@ -138,10 +169,10 @@ class FormDexRecord {
|
||||
speciesDexRecord.onFormRecordUpdated(this)
|
||||
CobblemonEvents.POKEDEX_DATA_CHANGED_POST.post(
|
||||
PokedexDataChangedEvent.Post(
|
||||
pokedexEntityData,
|
||||
knowledge,
|
||||
pokedexManager.uuid,
|
||||
this
|
||||
Either.left(pokedexEntityData),
|
||||
knowledge,
|
||||
pokedexManager.uuid,
|
||||
this
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -149,10 +180,19 @@ class FormDexRecord {
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns whether the given [Pokemon] and [knowledge] would add new information to the Pokédex.*/
|
||||
fun wouldBeDifferent(pokemon: Pokemon, knowledge: PokedexEntryProgress): Boolean {
|
||||
return pokemon.gender !in genders
|
||||
|| (pokemon.shiny && "shiny" !in seenShinyStates)
|
||||
|| (!pokemon.shiny && "normal" !in seenShinyStates)
|
||||
|| knowledge.ordinal > this.knowledge.ordinal
|
||||
|| speciesDexRecord.wouldBeDifferent(pokemon)
|
||||
}
|
||||
|
||||
fun wouldBeDifferent(pokedexEntityData: PokedexEntityData, knowledge: PokedexEntryProgress): Boolean {
|
||||
return pokedexEntityData.pokemon.gender !in genders
|
||||
|| (pokedexEntityData.pokemon.shiny && "shiny" !in seenShinyStates)
|
||||
|| (!pokedexEntityData.pokemon.shiny && "normal" !in seenShinyStates)
|
||||
return pokedexEntityData.gender !in genders
|
||||
|| (pokedexEntityData.shiny && "shiny" !in seenShinyStates)
|
||||
|| (!pokedexEntityData.shiny && "normal" !in seenShinyStates)
|
||||
|| knowledge.ordinal > this.knowledge.ordinal
|
||||
|| speciesDexRecord.wouldBeDifferent(pokedexEntityData)
|
||||
}
|
||||
|
||||
@@ -30,19 +30,19 @@ class PokedexManager(
|
||||
fun encounter(pokemon: Pokemon) {
|
||||
val speciesId = pokemon.species.resourceIdentifier
|
||||
val formName = pokemon.form.name
|
||||
getOrCreateSpeciesRecord(speciesId).getOrCreateFormRecord(formName).encountered(PokedexEntityData(pokemon = pokemon, disguise = null))
|
||||
getOrCreateSpeciesRecord(speciesId).getOrCreateFormRecord(formName).encountered(pokemon)
|
||||
}
|
||||
|
||||
fun encounter(pokedexEntityData: PokedexEntityData) {
|
||||
val speciesId = pokedexEntityData.getApparentSpecies().resourceIdentifier
|
||||
val formName = pokedexEntityData.getApparentForm().name
|
||||
val speciesId = pokedexEntityData.species.resourceIdentifier
|
||||
val formName = pokedexEntityData.form.name
|
||||
getOrCreateSpeciesRecord(speciesId).getOrCreateFormRecord(formName).encountered(pokedexEntityData)
|
||||
}
|
||||
|
||||
fun catch(pokemon: Pokemon) {
|
||||
val speciesId = pokemon.species.resourceIdentifier
|
||||
val formName = pokemon.form.name
|
||||
getOrCreateSpeciesRecord(speciesId).getOrCreateFormRecord(formName).caught(PokedexEntityData(pokemon = pokemon, disguise = null))
|
||||
getOrCreateSpeciesRecord(speciesId).getOrCreateFormRecord(formName).caught(pokemon)
|
||||
}
|
||||
|
||||
override fun markDirty() {
|
||||
|
||||
@@ -50,8 +50,6 @@ class SpeciesDexRecord {
|
||||
lateinit var id: ResourceLocation
|
||||
private val aspects: MutableSet<String> = mutableSetOf()
|
||||
private val formRecords: MutableMap<String, FormDexRecord> = mutableMapOf()
|
||||
val isFormRecordsEmpty: Boolean
|
||||
get() = formRecords.isEmpty()
|
||||
|
||||
fun describe(): String {
|
||||
return "SpeciesDexRecord(aspects=$aspects, formRecords=$formRecords)"
|
||||
@@ -97,7 +95,7 @@ class SpeciesDexRecord {
|
||||
}
|
||||
|
||||
fun addInformation(pokedexEntityData: PokedexEntityData, knowledge: PokedexEntryProgress) {
|
||||
aspects.addAll(pokedexEntityData.pokemon.aspects)
|
||||
aspects.addAll(pokedexEntityData.aspects)
|
||||
}
|
||||
|
||||
fun addAspects(addedAspects: Set<String>) {
|
||||
@@ -107,7 +105,7 @@ class SpeciesDexRecord {
|
||||
/** Returns true if the given Pokémon contains new information. Internal because it's only to be called from [FormDexRecord.wouldBeDifferent]. */
|
||||
internal fun wouldBeDifferent(pokemon: Pokemon) = pokemon.aspects.any { it !in aspects }
|
||||
|
||||
internal fun wouldBeDifferent(pokedexEntityData: PokedexEntityData) = pokedexEntityData.pokemon.aspects.any { it !in aspects }
|
||||
internal fun wouldBeDifferent(pokedexEntityData: PokedexEntityData) = pokedexEntityData.aspects.any { it !in aspects }
|
||||
|
||||
fun getOrCreateFormRecord(formName: String): FormDexRecord {
|
||||
return formRecords.getOrPut(formName.lowercase()) {
|
||||
|
||||
@@ -32,10 +32,9 @@ class SearchFilter(val pokedexManager: AbstractPokedexManager, val searchString:
|
||||
if (searchString == "") return true
|
||||
|
||||
val species = PokemonSpecies.getByIdentifier(entry.speciesId) ?: return false
|
||||
val highestKnowledgeForEntry = pokedexManager.getHighestKnowledgeFor(entry)
|
||||
if (highestKnowledgeForEntry == PokedexEntryProgress.NONE) return false
|
||||
if (pokedexManager.getHighestKnowledgeFor(entry) == PokedexEntryProgress.NONE) return false
|
||||
|
||||
when (searchByType) {
|
||||
when(searchByType) {
|
||||
SearchByType.ABILITIES -> {
|
||||
if (pokedexManager.getHighestKnowledgeFor(entry) !== PokedexEntryProgress.CAUGHT) return false
|
||||
val abilityList = mutableListOf<String>()
|
||||
|
||||
@@ -468,10 +468,6 @@ open class PokemonProperties {
|
||||
return this.commonMatches(pokemonEntity.pokemon) && this.customProperties.none { !it.matches(pokemonEntity) }
|
||||
}
|
||||
|
||||
fun matches(properties: PokemonProperties): Boolean {
|
||||
return properties.asString() == this.asString()
|
||||
}
|
||||
|
||||
private fun commonMatches(pokemon: Pokemon): Boolean {
|
||||
level?.takeIf { it != pokemon.level }?.let { return false }
|
||||
shiny?.takeIf { it != pokemon.shiny }?.let { return false }
|
||||
@@ -809,7 +805,7 @@ open class PokemonProperties {
|
||||
private fun createAbility(id: String, form: FormData): Ability? {
|
||||
val ability = Abilities.get(id) ?: return null
|
||||
val potentialAbility = form.abilities.firstOrNull { potential -> potential.template == ability } ?: return ability.create(true)
|
||||
return potentialAbility.template.create(false, potentialAbility.priority)
|
||||
return potentialAbility.template.create(false)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.pokemon
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.abilities.AbilityPool
|
||||
import com.cobblemon.mod.common.api.abilities.AbilityTemplate
|
||||
@@ -33,7 +32,6 @@ import com.cobblemon.mod.common.api.pokemon.moves.Learnset
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.spawning.TimeRange
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.api.types.adapters.ElementalTypeAdapter
|
||||
@@ -48,7 +46,6 @@ import com.cobblemon.mod.common.pokemon.evolution.adapters.NbtItemPredicateAdapt
|
||||
import com.cobblemon.mod.common.pokemon.evolution.predicate.NbtItemPredicate
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.util.adapters.*
|
||||
import com.cobblemon.mod.common.util.adapters.riding.RideControllerAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.common.collect.HashBasedTable
|
||||
import com.google.gson.Gson
|
||||
@@ -103,8 +100,6 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
.registerTypeAdapter(EggGroup::class.java, EggGroupAdapter)
|
||||
.registerTypeAdapter(MobEffect::class.java, RegistryElementAdapter<MobEffect>(BuiltInRegistries::MOB_EFFECT))
|
||||
.registerTypeAdapter(NbtItemPredicate::class.java, NbtItemPredicateAdapter)
|
||||
.registerTypeAdapter(RideController::class.java, RideControllerAdapter)
|
||||
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
|
||||
.disableHtmlEscaping()
|
||||
.enableComplexMapKeySerialization()
|
||||
.create()
|
||||
|
||||
+14
-46
@@ -13,7 +13,6 @@ import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.advancement.CobblemonCriteria
|
||||
import com.cobblemon.mod.common.advancement.criterion.EvolvePokemonContext
|
||||
import com.cobblemon.mod.common.api.drop.DropTable
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.pokemon.PokemonGainedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEvent
|
||||
@@ -33,8 +32,9 @@ import com.cobblemon.mod.common.pokemon.evolution.variants.LevelUpEvolution
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.TradeEvolution
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.network.protocol.game.ClientboundSoundPacket
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.item.ItemStack
|
||||
@@ -80,11 +80,6 @@ interface Evolution : EvolutionLike {
|
||||
*/
|
||||
val learnableMoves: MutableSet<MoveTemplate>
|
||||
|
||||
/**
|
||||
* The items that will drop once the evolution finishes.
|
||||
*/
|
||||
val drops: DropTable
|
||||
|
||||
/**
|
||||
* Checks if the given [Pokemon] passes all the conditions and is ready to evolve.
|
||||
*
|
||||
@@ -105,6 +100,9 @@ interface Evolution : EvolutionLike {
|
||||
* @param pokemon The [Pokemon] being evolved.
|
||||
*/
|
||||
fun evolve(pokemon: Pokemon): Boolean {
|
||||
if (this.consumeHeldItem) {
|
||||
pokemon.swapHeldItem(ItemStack.EMPTY)
|
||||
}
|
||||
if (this.optional) {
|
||||
// All the networking is handled under the hood, see EvolutionController.
|
||||
return pokemon.evolutionProxy.server().add(this)
|
||||
@@ -132,7 +130,7 @@ interface Evolution : EvolutionLike {
|
||||
owner.party().getFirstAvailablePosition() ?: return false
|
||||
|
||||
// Add shed Pokemon to player's party
|
||||
val shedPokemon = pokemon.clone(registryAccess = owner.registryAccess())
|
||||
val shedPokemon = pokemon.clone()
|
||||
shedPokemon.removeHeldItem()
|
||||
innerShedder.apply(shedPokemon)
|
||||
shedPokemon.caughtBall = ((pokeballStack?.item ?: CobblemonItems.POKE_BALL) as PokeBallItem).pokeBall
|
||||
@@ -192,49 +190,19 @@ interface Evolution : EvolutionLike {
|
||||
}
|
||||
|
||||
fun evolutionMethod(pokemon: Pokemon) {
|
||||
// This ensures the Pokémon doesn't lose moves during evolution
|
||||
// (e.g., Oshawott evolving at level 17 knowing Razor Shell, while Dewott only learns it at level 18).
|
||||
val previousSpeciesLearnableMoves = pokemon.relearnableMoves
|
||||
|
||||
this.result.apply(pokemon)
|
||||
|
||||
val movesToLearn = previousSpeciesLearnableMoves + this.learnableMoves
|
||||
movesToLearn.forEach { move ->
|
||||
val couldAddMove =
|
||||
if (pokemon.moveSet.hasSpace()) {
|
||||
pokemon.moveSet.add(move.create())
|
||||
} else {
|
||||
pokemon.benchedMoves.add(BenchedMove(move, 0))
|
||||
}
|
||||
|
||||
val previousSpeciesKnewMove = previousSpeciesLearnableMoves.any { move.name == it.name }
|
||||
|
||||
if (couldAddMove && !previousSpeciesKnewMove) {
|
||||
pokemon.getOwnerPlayer()?.sendSystemMessage(lang("experience.learned_move", pokemon.getDisplayName(), move.displayName))
|
||||
this.learnableMoves.forEach { move ->
|
||||
if (pokemon.moveSet.hasSpace()) {
|
||||
pokemon.moveSet.add(move.create())
|
||||
} else {
|
||||
pokemon.benchedMoves.add(BenchedMove(move, 0))
|
||||
}
|
||||
pokemon.getOwnerPlayer()?.sendSystemMessage(lang("experience.learned_move", pokemon.getDisplayName(), move.displayName))
|
||||
}
|
||||
|
||||
// we want to instantly tick for example you might only evolve your Bulbasaur at level 34 so Venusaur should be immediately available
|
||||
pokemon.evolutions.filterIsInstance<PassiveEvolution>().forEach { evolution -> evolution.attemptEvolution(pokemon) }
|
||||
pokemon.lockedEvolutions.filterIsInstance<PassiveEvolution>().forEach { evolution -> evolution.attemptEvolution(pokemon) }
|
||||
|
||||
this.shed(pokemon)
|
||||
|
||||
if (this.consumeHeldItem) {
|
||||
pokemon.swapHeldItem(ItemStack.EMPTY)
|
||||
}
|
||||
|
||||
val ownerPlayer = pokemon.getOwnerPlayer()
|
||||
if (ownerPlayer != null && ownerPlayer.level().gameRules.getBoolean(CobblemonGameRules.DO_POKEMON_LOOT)) {
|
||||
drops.drop(
|
||||
pokemon.entity,
|
||||
ownerPlayer.level() as ServerLevel,
|
||||
pokemon.entity?.position() ?: ownerPlayer.position(),
|
||||
ownerPlayer,
|
||||
pokemon = pokemon
|
||||
)
|
||||
}
|
||||
|
||||
CobblemonEvents.EVOLUTION_COMPLETE.post(EvolutionCompleteEvent(pokemon, this))
|
||||
CobblemonEvents.POKEMON_GAINED.post(PokemonGainedEvent(pokemon.getOwnerUUID()!!, pokemon))
|
||||
}
|
||||
@@ -242,4 +210,4 @@ interface Evolution : EvolutionLike {
|
||||
fun applyTo(pokemon: Pokemon) {
|
||||
result.apply(pokemon)
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
-54
@@ -21,12 +21,6 @@ object CobblemonPokemonLabels {
|
||||
*/
|
||||
const val LEGENDARY = "legendary"
|
||||
|
||||
/**
|
||||
* Represents a Pokémon who is typically banned or has restricted usage in competitive sanctions.
|
||||
* For example usage see this [VGC](https://www.pokemon.com/us/pokemon-news/trainers-can-once-again-use-a-restricted-pokemon-in-ranked-battles-series-10-starting-august-1-2021) page.
|
||||
*/
|
||||
const val RESTRICTED = "restricted"
|
||||
|
||||
/**
|
||||
* Represents a mythical Pokémon.
|
||||
* In Cobblemon terms they do not exist since we do not share the concept of timed event only Pokémon but the official ones are still tagged.
|
||||
@@ -34,21 +28,14 @@ object CobblemonPokemonLabels {
|
||||
const val MYTHICAL = "mythical"
|
||||
|
||||
/**
|
||||
* Represents Pokémon that receive a boosted catch rate from the Beast Ball. (Due to Beast Boost)
|
||||
* Does not include [thematically related](https://bulbapedia.bulbagarden.net/wiki/Ultra_Beast#Related_Pok%C3%A9mon) beasts.
|
||||
* Represents Pokémon that originate from Ultra Space.
|
||||
*/
|
||||
const val ULTRA_BEAST = "ultra_beast"
|
||||
|
||||
/**
|
||||
* Represents a Pokémon whose family could be derived from resurrecting a fossil.
|
||||
* Represents the pseudo legendary Pokémon.
|
||||
*/
|
||||
const val FOSSIL = "fossil"
|
||||
|
||||
/**
|
||||
* Represents the "pseudo-legendary" Pokémon. (Slow-rate three-stage lines with a base stat total of 600)
|
||||
* Term reference on this [Pokémon Center](https://www.pokemoncenter.com/search/powerhouse) page.
|
||||
*/
|
||||
const val POWERHOUSE = "powerhouse"
|
||||
const val PSEUDO_LEGENDARY = "pseudo_legendary"
|
||||
|
||||
/**
|
||||
* Represents a baby Pokémon, this is not just a first stage Pokémon species, it is also unable to breed.
|
||||
@@ -65,55 +52,52 @@ object CobblemonPokemonLabels {
|
||||
/**
|
||||
* See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region.
|
||||
*/
|
||||
const val KANTONIAN_FORM = "kantonian_form"
|
||||
|
||||
/**
|
||||
* See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region.
|
||||
* Source for adjectival form: [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Johto#Trivia)
|
||||
*/
|
||||
const val JOHTONIAN_FORM = "johtonian_form"
|
||||
|
||||
/**
|
||||
* See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region.
|
||||
* Source for adjectival form:[Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Hoenn#Trivia)
|
||||
*/
|
||||
const val HOENNIAN_FORM = "hoennian_form"
|
||||
|
||||
/**
|
||||
* See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region.
|
||||
* Source for adjectival form:[Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Sinnoh#Trivia)
|
||||
*/
|
||||
const val SINNOHAN_FORM = "sinnohan_form"
|
||||
const val REGIONAL_OF_KANTO = "kanto_regional"
|
||||
|
||||
/**
|
||||
* See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region.
|
||||
*/
|
||||
const val UNOVAN_FORM = "unovan_form"
|
||||
const val REGIONAL_OF_JOHTO = "johto_regional"
|
||||
|
||||
/**
|
||||
* See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region.
|
||||
*/
|
||||
const val KALOSIAN_FORM = "kalosian_form"
|
||||
const val REGIONAL_OF_HOENN = "hoenn_regional"
|
||||
|
||||
/**
|
||||
* See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region.
|
||||
*/
|
||||
const val REGIONAL_OF_SINNOH = "sinnoh_regional"
|
||||
|
||||
/**
|
||||
* See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region.
|
||||
*/
|
||||
const val REGIONAL_OF_UNOVA = "unova_regional"
|
||||
|
||||
/**
|
||||
* See [REGIONAL], this has no official regionals but it consists of the "base" form that comes from the region.
|
||||
*/
|
||||
const val REGIONAL_OF_KALOS = "kalos_regional"
|
||||
|
||||
/**
|
||||
* See [REGIONAL] and this [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Regional_form#Alolan_Form) page.
|
||||
*/
|
||||
const val ALOLAN_FORM = "alolan_form"
|
||||
const val REGIONAL_OF_ALOLA = "alola_regional"
|
||||
|
||||
/**
|
||||
* See [REGIONAL] and this [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Regional_form#Galarian_Form) page.
|
||||
*/
|
||||
const val GALARIAN_FORM = "galarian_form"
|
||||
const val REGIONAL_OF_GALAR = "galar_regional"
|
||||
|
||||
/**
|
||||
* See [REGIONAL] and this [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Regional_form#Hisuian_Form) page.
|
||||
*/
|
||||
const val HISUIAN_FORM = "hisuian_form"
|
||||
const val REGIONAL_OF_HISUI = "hisui_regional"
|
||||
|
||||
/**
|
||||
* See [REGIONAL] and this [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Regional_form#Paldean_Form) page.
|
||||
*/
|
||||
const val PALDEAN_FORM = "paldean_form"
|
||||
const val REGIONAL_OF_PALDEA = "paldea_regional"
|
||||
|
||||
/**
|
||||
* Represents a mega evolution.
|
||||
@@ -140,7 +124,7 @@ object CobblemonPokemonLabels {
|
||||
const val TOTEM = "totem"
|
||||
|
||||
/**
|
||||
* Represents Pokémon that trigger the Booster Energy item (due to Protosynthesis/Quark Drive)
|
||||
* Represents a Paradox species.
|
||||
* For more information see the [Bulbapedia](https://bulbapedia.bulbagarden.net/wiki/Paradox_Pok%C3%A9mon) page.
|
||||
*/
|
||||
const val PARADOX = "paradox"
|
||||
@@ -187,24 +171,12 @@ object CobblemonPokemonLabels {
|
||||
*/
|
||||
const val GENERATION_7 = "gen7"
|
||||
|
||||
/**
|
||||
* The "official" designation for Pokémon from Gen 7 (Unknown) and not the Alola region
|
||||
* This may also include forms of Pokémon that had been previously introduced
|
||||
*/
|
||||
const val GENERATION_7B = "gen7b"
|
||||
|
||||
/**
|
||||
* Pokémon from the national Pokédex of 810 to 905
|
||||
* This may also include forms of Pokémon that had been previously introduced
|
||||
*/
|
||||
const val GENERATION_8 = "gen8"
|
||||
|
||||
/**
|
||||
* The "official" designation for Pokémon from Gen 8 (Hisui) and not the Galar region
|
||||
* This may also include forms of Pokémon that had been previously introduced
|
||||
*/
|
||||
const val GENERATION_8A = "gen8a"
|
||||
|
||||
/**
|
||||
* Pokémon from the national Pokédex from 906 to 1008
|
||||
* This may also include forms of Pokémon that had been previously introduced
|
||||
|
||||
@@ -53,7 +53,7 @@ enum class Stats(override val identifier: ResourceLocation, override val display
|
||||
fun getStat(statKey: String) = when(statKey.lowercase()) {
|
||||
"hp" -> HP
|
||||
"atk", "attack" -> ATTACK // Hyper Cutter states the full stat name "Attack"
|
||||
"def", "defense", "defence" -> DEFENCE // Big Pecks states the full stat name "Defense"
|
||||
"def", "defense" -> DEFENCE // Big Pecks states the full stat name "Defense"
|
||||
"spa" -> SPECIAL_ATTACK
|
||||
"spd" -> SPECIAL_DEFENCE
|
||||
"spe", "speed" -> SPEED
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding
|
||||
|
||||
import net.minecraft.world.entity.PlayerRideableJumping
|
||||
|
||||
/**
|
||||
* Represents an entity that supports riding.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
interface Rideable : PlayerRideableJumping {
|
||||
|
||||
/**
|
||||
* Denotes the manager responsible for handling any instance of riding taking place on an entity
|
||||
*/
|
||||
val riding: RidingManager
|
||||
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import kotlin.math.sin
|
||||
|
||||
data class RidingManager(val entity: PokemonEntity) {
|
||||
var lastSpeed = 0F
|
||||
var states: MutableMap<ResourceLocation, RidingState> = mutableMapOf()
|
||||
var deltaRotation = Vec2.ZERO
|
||||
|
||||
val runtime: MoLangRuntime by lazy {
|
||||
MoLangRuntime()
|
||||
.setup()
|
||||
.withQueryValue("entity", entity.struct)
|
||||
.also {
|
||||
it.environment.query.addFunction("passenger_count") { DoubleValue(entity.passengers.size.toDouble()) }
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : RidingState> getState(id: ResourceLocation, constructor: (PokemonEntity) -> T): T {
|
||||
val storedState = states[id]
|
||||
if (storedState == null) {
|
||||
val newState = constructor(entity)
|
||||
states[id] = newState
|
||||
return newState
|
||||
}
|
||||
|
||||
return storedState as T
|
||||
}
|
||||
|
||||
fun getController(entity: PokemonEntity): RideController? {
|
||||
return entity.pokemon.riding.controller?.takeIf { it.condition.invoke(entity) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Responsible for handling riding conditions and transitions amongst controllers. This will tick
|
||||
* whenever the entity receives a tickControlled interaction.
|
||||
*/
|
||||
fun tick(entity: PokemonEntity, driver: Player, input: Vec3) {
|
||||
val controller = getController(entity) ?: return
|
||||
|
||||
val pose = controller.pose(entity)
|
||||
entity.entityData.set(PokemonEntity.POSE_TYPE, pose)
|
||||
//val speedPlayer = driver.deltaMovement.horizontalDistance()
|
||||
//driver.displayClientMessage(Component.literal("Speed player: ").withStyle { it.withColor(ChatFormatting.GREEN) }.append(Component.literal("$speedPlayer b/t")), true)
|
||||
val speedEntity = entity.deltaMovement.horizontalDistance()
|
||||
driver.displayClientMessage(Component.literal("Speed Entity: ").withStyle { it.withColor(ChatFormatting.GREEN) }.append(Component.literal("${String.format("%.2f", speedEntity)} b/t")), true)
|
||||
|
||||
}
|
||||
|
||||
fun speed(entity: PokemonEntity, driver: Player): Float {
|
||||
val controller = getController(entity) ?: return 0.05F
|
||||
this.lastSpeed = controller.speed(entity, driver)
|
||||
return this.lastSpeed
|
||||
}
|
||||
|
||||
fun controlledRotation(entity: PokemonEntity, driver: Player): Vec2 {
|
||||
val controller = getController(entity) ?: return entity.rotationVector
|
||||
val previousRotation = entity.rotationVector
|
||||
val rotation = controller.rotation(entity, driver)
|
||||
this.deltaRotation = Vec2(rotation.x - previousRotation.x, rotation.y - previousRotation.y)
|
||||
return rotation
|
||||
}
|
||||
|
||||
fun clampPassengerRotation(entity: PokemonEntity, driver: LivingEntity) {
|
||||
val controller = getController(entity) ?: return
|
||||
return controller.clampPassengerRotation(entity, driver)
|
||||
}
|
||||
|
||||
fun updatePassengerRotation(entity: PokemonEntity, driver: LivingEntity) {
|
||||
val controller = getController(entity) ?: return
|
||||
return controller.updatePassengerRotation(entity, driver)
|
||||
}
|
||||
|
||||
fun velocity(entity: PokemonEntity, driver: Player, input: Vec3): Vec3 {
|
||||
val controller = getController(entity) ?: return Vec3.ZERO
|
||||
return controller.velocity(entity, driver, input)
|
||||
}
|
||||
|
||||
fun canJump(entity: PokemonEntity, driver: Player): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.canJump(entity, driver)
|
||||
}
|
||||
|
||||
fun jumpVelocity(entity: PokemonEntity, driver: Player, jumpStrength: Int): Vec3 {
|
||||
val controller = getController(entity) ?: return Vec3.ZERO
|
||||
return controller.jumpForce(entity, driver, jumpStrength)
|
||||
}
|
||||
|
||||
fun gravity(entity: PokemonEntity, regularGravity: Double): Double? {
|
||||
val controller = getController(entity) ?: return null
|
||||
return controller.gravity(entity, regularGravity)
|
||||
}
|
||||
|
||||
fun shouldRoll(entity: PokemonEntity): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.shouldRoll(entity)
|
||||
}
|
||||
|
||||
fun rotationOnMouseXY( entity: PokemonEntity, driver: Player, yMouse: Double, xMouse: Double ){
|
||||
val controller = getController(entity) ?: return
|
||||
controller.rotationOnMouseXY( entity, driver, yMouse, xMouse )
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether mouse input will affect the rotation of
|
||||
* the rollable object
|
||||
*/
|
||||
fun useMouseInputRoll(entity: PokemonEntity): Boolean {
|
||||
val controller = getController(entity) ?: return true
|
||||
return controller.useMouseInputRoll(entity)
|
||||
}
|
||||
|
||||
fun turnOffOnGround(entity: PokemonEntity): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.turnOffOnGround(entity)
|
||||
}
|
||||
|
||||
fun angRollVel(entity: PokemonEntity, driver: Player): Vec3 {
|
||||
val controller = getController(entity) ?: return Vec3(0.0, 0.0, 0.0)
|
||||
return controller.angRollVel(entity, driver)
|
||||
}
|
||||
|
||||
fun dismountOnShift(): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.dismountOnShift(entity)
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.util.adapters.riding.RideControllerAdapter
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.getString
|
||||
import com.cobblemon.mod.common.util.readIdentifier
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class RidingProperties(
|
||||
val seats: List<Seat> = listOf(),
|
||||
val conditions: List<Expression> = listOf(),
|
||||
val controller: RideController? = null
|
||||
) {
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): RidingProperties {
|
||||
val seats: List<Seat> = buffer.readList { _ -> Seat.decode(buffer) }
|
||||
val conditions = buffer.readList { buffer.readString().asExpression() }
|
||||
val controller = buffer.readNullable { _ ->
|
||||
val key = buffer.readIdentifier()
|
||||
val controller = RideControllerAdapter.types[key]?.getConstructor()?.newInstance() ?: error("Unknown controller key: $key")
|
||||
controller.decode(buffer)
|
||||
return@readNullable controller
|
||||
}
|
||||
|
||||
return RidingProperties(seats = seats, conditions = conditions, controller = controller)
|
||||
}
|
||||
}
|
||||
|
||||
val canRide: Boolean
|
||||
get() = seats.isNotEmpty() && controller != null
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeCollection(seats) { _, seat -> seat.encode(buffer) }
|
||||
buffer.writeCollection(conditions) { _, condition -> buffer.writeString(condition.getString()) }
|
||||
buffer.writeNullable(controller) { _, controller -> controller.encode(buffer) }
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding
|
||||
|
||||
/**
|
||||
* Honestly having a base interface is probably unnecessary I'm just considering whether there's going to be some
|
||||
* kind of shared state later.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 6th, 2024
|
||||
*/
|
||||
interface RidingState
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding
|
||||
|
||||
import com.cobblemon.mod.common.api.net.Encodable
|
||||
import com.cobblemon.mod.common.api.riding.controller.RidingAnimation
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
/**
|
||||
* Seat Properties are responsible for the base information that would then be used to construct a Seat on an entity.
|
||||
*/
|
||||
data class Seat(
|
||||
val locator: String = "seat1",
|
||||
val offset: Vec3 = Vec3.ZERO,
|
||||
val poseOffsets: MutableList<SeatPoseOffset> = mutableListOf(),
|
||||
val poseAnimations: MutableList<SeatPoseAnimations> = mutableListOf()
|
||||
) : Encodable {
|
||||
fun getOffset(poseType: PoseType) : Vec3 {
|
||||
return poseOffsets.firstOrNull { poseType in it.poseTypes }?.offset ?: offset
|
||||
}
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeString(locator)
|
||||
buffer.writeDouble(offset.x)
|
||||
buffer.writeDouble(offset.y)
|
||||
buffer.writeDouble(offset.z)
|
||||
buffer.writeCollection(poseOffsets) { _, offset -> offset.encode(buffer) }
|
||||
buffer.writeCollection(poseAnimations) { _, animations -> animations.encode(buffer) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) : Seat {
|
||||
return Seat(
|
||||
buffer.readString(),
|
||||
Vec3(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()),
|
||||
buffer.readList { SeatPoseOffset.decode(buffer) },
|
||||
buffer.readList { SeatPoseAnimations.decode(buffer) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SeatPoseOffset {
|
||||
val poseTypes = mutableSetOf<PoseType>()
|
||||
var offset = Vec3.ZERO
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeCollection(poseTypes) { _, poseType -> buffer.writeString(poseType.name) }
|
||||
buffer.writeDouble(offset.x)
|
||||
buffer.writeDouble(offset.y)
|
||||
buffer.writeDouble(offset.z)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) : SeatPoseOffset {
|
||||
val offset = SeatPoseOffset()
|
||||
offset.poseTypes.addAll(buffer.readList { buffer.readString().let { PoseType.valueOf(it) } })
|
||||
offset.offset = Vec3(buffer.readDouble(), buffer.readDouble(), buffer.readDouble())
|
||||
return offset
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SeatPoseAnimations {
|
||||
val poseTypes = mutableSetOf<PoseType>()
|
||||
var animations = mutableListOf<RidingAnimation>()
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeCollection(poseTypes) { _, poseType -> buffer.writeString(poseType.name) }
|
||||
buffer.writeCollection(animations) { _, animation -> animation.encode(buffer) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) : SeatPoseAnimations {
|
||||
val animations = SeatPoseAnimations()
|
||||
animations.poseTypes.addAll(buffer.readList { buffer.readString().let { PoseType.valueOf(it) } })
|
||||
animations.animations = buffer.readList { RidingAnimation.decode(buffer) }
|
||||
return animations
|
||||
}
|
||||
}
|
||||
}
|
||||
-127
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.controller
|
||||
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.net.Decodable
|
||||
import com.cobblemon.mod.common.api.net.Encodable
|
||||
import com.cobblemon.mod.common.api.riding.RidingState
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.writeIdentifier
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
/**
|
||||
* A riding controller is the internal control mechanism for determining how a pokemon
|
||||
* handles during riding. Controllers come into play once the pokemon being ridden has
|
||||
* established the path it's capable of. For instance, a land based controller could have
|
||||
* the pokemon experience drifting after movement, or generic movement. It's up to the
|
||||
* controller to decide how the pokemon behaves.
|
||||
*
|
||||
* @since x.x.x
|
||||
*/
|
||||
interface RideController : Encodable, Decodable {
|
||||
|
||||
/** A reference key used to denote the individual controller */
|
||||
val key: ResourceLocation
|
||||
|
||||
/**
|
||||
* Specifies the provider of poses which helps control updating the current pose on the pokemon
|
||||
* being ridden. Controllers are expected to define the pose types responsible for posing the entity
|
||||
* through all expected conditions. It should define a default pose, that will be used in all cases
|
||||
* where a pose does not meet the current conditions for the current mount. Typically, this will be
|
||||
* an idle pose.
|
||||
*/
|
||||
val poseProvider: PoseProvider
|
||||
|
||||
/**
|
||||
* Represents a condition that must be met for this controller to be active. For instance, this can be used
|
||||
* to evaluate things such as current velocity or block state of the entity.
|
||||
*/
|
||||
val condition: (PokemonEntity) -> Boolean
|
||||
|
||||
/**
|
||||
* Specifies the pose the ridden mount should be positioned in. This queries the pose provider using
|
||||
* the entity as a means of determining the conditions the entity is currently under. This allows for
|
||||
* dynamic pose updates.
|
||||
*/
|
||||
fun pose(entity: PokemonEntity) : PoseType {
|
||||
return this.poseProvider.select(entity)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the current speed of the mount.
|
||||
*/
|
||||
fun speed(entity: PokemonEntity, driver: Player) : Float
|
||||
|
||||
/**
|
||||
* Sets the rotation of the mount. This is typically based on the controlling driver and is manipulated as
|
||||
* necessary.
|
||||
*/
|
||||
fun rotation(entity: PokemonEntity, driver: LivingEntity) : Vec2
|
||||
|
||||
/**
|
||||
* Sets the change current change in rotation for that tick in three
|
||||
* dimensions
|
||||
*/
|
||||
fun angRollVel(entity: PokemonEntity, driver: Player): Vec3 {
|
||||
return Vec3(0.0, 0.0, 0.0)
|
||||
}
|
||||
|
||||
fun clampPassengerRotation(entity: PokemonEntity, driver: LivingEntity) {}
|
||||
|
||||
fun updatePassengerRotation(entity: PokemonEntity, driver: LivingEntity) {
|
||||
driver.yRot = entity.yRot
|
||||
}
|
||||
|
||||
/**
|
||||
* Manipulates the movement input as necessary by the controller. This is primarily used to apply limits
|
||||
* to the types of movements. For instance, we can apply limits to any sort of sideways movement input, so that
|
||||
* it would otherwise be slower than normal forward movement.
|
||||
*/
|
||||
fun velocity(entity: PokemonEntity, driver: Player, input: Vec3) : Vec3
|
||||
|
||||
fun canJump(entity: PokemonEntity, driver: Player) : Boolean
|
||||
fun jumpForce(entity: PokemonEntity, driver: Player, jumpStrength: Int) : Vec3
|
||||
|
||||
fun gravity(entity: PokemonEntity, regularGravity: Double) : Double? = null
|
||||
|
||||
fun shouldRoll(entity: PokemonEntity): Boolean = false
|
||||
|
||||
fun useMouseInputRoll(entity: PokemonEntity): Boolean = false
|
||||
|
||||
//If function is not overwritten by controllers then just perform the defualt
|
||||
//rolling function
|
||||
fun rotationOnMouseXY( entity: PokemonEntity, driver: Player, yMouse: Double, xMouse: Double ){
|
||||
if(driver !is Rollable) return
|
||||
|
||||
val rollable = driver as Rollable
|
||||
rollable.rotate(0.0f, yMouse.toFloat(), xMouse.toFloat())
|
||||
}
|
||||
|
||||
fun turnOffOnGround(entity: PokemonEntity): Boolean = false
|
||||
|
||||
fun dismountOnShift(entity: PokemonEntity): Boolean = false
|
||||
|
||||
fun getRuntime(entity: PokemonEntity) = entity.riding.runtime
|
||||
|
||||
fun <T : RidingState> getState(entity: PokemonEntity, constructor: (PokemonEntity) -> T): T {
|
||||
return entity.riding.getState(key, constructor)
|
||||
}
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeIdentifier(this.key)
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.controller
|
||||
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class RidingAnimation(
|
||||
val fileName: String,
|
||||
val animationName: String
|
||||
) {
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeString(fileName)
|
||||
buffer.writeString(animationName)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) : RidingAnimation {
|
||||
return RidingAnimation(
|
||||
buffer.readString(),
|
||||
buffer.readString()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.controller.posing
|
||||
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import java.util.function.Predicate
|
||||
|
||||
data class PoseOption(val pose: PoseType, val condition: Predicate<PokemonEntity>)
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.controller.posing
|
||||
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
|
||||
class PoseProvider(private val fallback: PoseType) {
|
||||
|
||||
private val options = mutableListOf<PoseOption>()
|
||||
|
||||
fun select(entity: PokemonEntity) : PoseType {
|
||||
return this.options.stream()
|
||||
.filter { it.condition.test(entity) }
|
||||
.map { it.pose }
|
||||
.findFirst()
|
||||
.orElse(this.fallback)
|
||||
}
|
||||
|
||||
fun with(option: PoseOption) : PoseProvider {
|
||||
this.options.add(option)
|
||||
return this
|
||||
}
|
||||
|
||||
}
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.events
|
||||
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
data class SelectDriverEvent(val options: Set<LivingEntity>) {
|
||||
|
||||
private var result: DriverSuggestion? = null
|
||||
|
||||
fun result(): LivingEntity? {
|
||||
return this.result?.entity
|
||||
}
|
||||
|
||||
/**
|
||||
* Suggests a particular living entity as a potential driver. Only non-negative
|
||||
* values are permitted by this function. All priority values with lesser priorities
|
||||
* will be outright ignored.
|
||||
*/
|
||||
fun suggest(target: LivingEntity, priority: Int) {
|
||||
if (priority >= 0 && priority > (this.result?.priority ?: -1)) {
|
||||
this.result = DriverSuggestion(target, priority)
|
||||
}
|
||||
}
|
||||
|
||||
data class DriverSuggestion(val entity: LivingEntity, val priority: Int)
|
||||
}
|
||||
+1
-4
@@ -31,7 +31,6 @@ class BedrockParticleEmitter(
|
||||
var rate: ParticleEmitterRate = InstantParticleEmitterRate(),
|
||||
var shape: ParticleEmitterShape = SphereParticleEmitterShape(),
|
||||
var lifetime: ParticleEmitterLifetime = OnceEmitterLifetime(NumberExpression(1.0)),
|
||||
var space: EmitterSpace = EmitterSpace(),
|
||||
var eventTimeline: EventTriggerTimeline = EventTriggerTimeline(mutableMapOf()),
|
||||
var creationEvents: MutableList<SimpleEventTrigger> = mutableListOf(),
|
||||
var expirationEvents: MutableList<SimpleEventTrigger> = mutableListOf(),
|
||||
@@ -46,20 +45,18 @@ class BedrockParticleEmitter(
|
||||
ParticleEmitterRate.codec.fieldOf("rate").forGetter { it.rate },
|
||||
ParticleEmitterShape.codec.fieldOf("shape").forGetter { it.shape },
|
||||
ParticleEmitterLifetime.codec.fieldOf("lifetime").forGetter { it.lifetime },
|
||||
EmitterSpace.CODEC.fieldOf("space").forGetter { it.space },
|
||||
EventTriggerTimeline.CODEC.fieldOf("eventTimeline").forGetter { it.eventTimeline },
|
||||
SimpleEventTrigger.CODEC.listOf().fieldOf("creationEvents").forGetter { it.creationEvents },
|
||||
SimpleEventTrigger.CODEC.listOf().fieldOf("expirationEvents").forGetter { it.expirationEvents },
|
||||
EventTriggerTimeline.CODEC.fieldOf("travelDistanceEvents").forGetter { it.travelDistanceEvents },
|
||||
LoopingTravelDistanceEventTrigger.CODEC.listOf().fieldOf("loopingTravelDistanceEvents").forGetter { it.loopingTravelDistanceEvents }
|
||||
).apply(instance) { startExpressions, updateExpressions, rate, shape, lifetime, space, eventTimeline, creationEvents, expirationEvents, travelDistanceEvents, loopingTravelDistanceEvents ->
|
||||
).apply(instance) { startExpressions, updateExpressions, rate, shape, lifetime, eventTimeline, creationEvents, expirationEvents, travelDistanceEvents, loopingTravelDistanceEvents ->
|
||||
BedrockParticleEmitter(
|
||||
startExpressions = startExpressions,
|
||||
updateExpressions = updateExpressions,
|
||||
shape = shape,
|
||||
rate = rate,
|
||||
lifetime = lifetime,
|
||||
space = space,
|
||||
eventTimeline = eventTimeline,
|
||||
creationEvents = creationEvents,
|
||||
expirationEvents = expirationEvents,
|
||||
|
||||
@@ -1,61 +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.snowstorm
|
||||
|
||||
import com.cobblemon.mod.common.api.data.ArbitrarilyMappedSerializableCompanion
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper
|
||||
import com.cobblemon.mod.common.util.codec.CodecUtils
|
||||
import com.cobblemon.mod.common.util.codec.optionalFieldOfWithDefault
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import org.joml.AxisAngle4f
|
||||
import org.joml.Matrix4f
|
||||
import org.joml.Vector3f
|
||||
|
||||
class EmitterSpace(
|
||||
var scaling: ScalingMode = ScalingMode.WORLD
|
||||
) {
|
||||
companion object {
|
||||
val CODEC: Codec<EmitterSpace> = RecordCodecBuilder.create { instance ->
|
||||
instance.group(
|
||||
Codec.STRING.optionalFieldOfWithDefault("scaling", "world").forGetter { it.scaling.toString() }
|
||||
).apply(instance) { scaling ->
|
||||
EmitterSpace(
|
||||
ScalingMode.valueOf(scaling.uppercase())
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun initializeEmitterMatrix(rootMatrix: MatrixWrapper, locatorMatrix: MatrixWrapper): MatrixWrapper {
|
||||
val rootRotation = rootMatrix.matrix.getRotation(AxisAngle4f())
|
||||
val scale = Vector3f()
|
||||
|
||||
if (scaling == ScalingMode.ENTITY) {
|
||||
locatorMatrix.matrix.getScale(scale)
|
||||
}
|
||||
else {
|
||||
rootMatrix.matrix.getScale(scale)
|
||||
//Incase they are multiplying some axis by -1 to rotate
|
||||
scale.x = Math.signum(scale.x)
|
||||
scale.y = Math.signum(scale.y)
|
||||
scale.z = Math.signum(scale.z)
|
||||
}
|
||||
|
||||
val particleScale = Vector3f(scale.x, scale.y, scale.z)
|
||||
//Presumably we will want to make the initial rotation configurable instead of always using root
|
||||
val particleRawMatrix = Matrix4f().scale(particleScale).rotate(rootRotation)
|
||||
return MatrixWrapper().updateMatrix(particleRawMatrix).updatePosition(locatorMatrix.getOrigin())
|
||||
}
|
||||
|
||||
enum class ScalingMode {
|
||||
WORLD,
|
||||
ENTITY
|
||||
}
|
||||
}
|
||||
@@ -498,7 +498,7 @@ class LookAtDirection : ParticleCameraMode {
|
||||
rotation.hamiltonProduct(Axis.ZP.rotationDegrees(particleAngle))
|
||||
|
||||
// Minecraft in 1.21 or 1.20.4 or something fucked with vertex draw order, and it flipped everything.
|
||||
rotation.hamiltonProduct(Axis.XP.rotationDegrees(180F))
|
||||
rotation.hamiltonProduct(Axis.YP.rotationDegrees(180F))
|
||||
|
||||
return rotation
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Matrix4f
|
||||
|
||||
/**
|
||||
* An event that can be referenced from various particle event triggers. The events are not necessarily particles,
|
||||
@@ -78,11 +77,9 @@ class ParticleEvent(
|
||||
fun run(storm: ParticleStorm, particle: SnowstormParticle?) {
|
||||
particleEffect?.let { effect ->
|
||||
val bedrockParticleOptions = BedrockParticleOptionsRepository.getEffect(effect.effect) ?: return@let
|
||||
val particleMatrix = when (effect.type) {
|
||||
//It may seem incorrect to clone for both of these, but the locator matrix determines whether the
|
||||
//emitter follows the locator. We don't want the child emitter to affect the parent emitter so we make a copy
|
||||
EventParticleOptions.EventParticleType.EMITTER,
|
||||
EventParticleOptions.EventParticleType.EMITTER_BOUND -> storm.emitterSpaceMatrix.clone()
|
||||
val rootMatrix = when (effect.type) {
|
||||
EventParticleOptions.EventParticleType.EMITTER-> MatrixWrapper().updatePosition(storm.matrixWrapper.position).updateMatrix(storm.matrixWrapper.matrix)
|
||||
EventParticleOptions.EventParticleType.EMITTER_BOUND -> storm.matrixWrapper
|
||||
EventParticleOptions.EventParticleType.PARTICLE,
|
||||
EventParticleOptions.EventParticleType.PARTICLE_WITH_VELOCITY -> (particle?.let {
|
||||
Vec3(
|
||||
@@ -90,19 +87,7 @@ class ParticleEvent(
|
||||
it.getY(),
|
||||
it.getZ()
|
||||
)
|
||||
} ?: Vec3(storm.getX(), storm.getY(), storm.getZ())).let {
|
||||
val matrixWrapper = MatrixWrapper()
|
||||
matrixWrapper.updatePosition(it)
|
||||
//We only want the orientation of the original matrix, not position/translation
|
||||
matrixWrapper.updateMatrix(Matrix4f(storm.emitterSpaceMatrix.matrix).setTranslation(0F, 0F, 0F))
|
||||
}
|
||||
}
|
||||
|
||||
val locatorMatrix = when (effect.type) {
|
||||
EventParticleOptions.EventParticleType.EMITTER -> particleMatrix
|
||||
EventParticleOptions.EventParticleType.EMITTER_BOUND -> storm.locatorSpaceMatrix
|
||||
EventParticleOptions.EventParticleType.PARTICLE,
|
||||
EventParticleOptions.EventParticleType.PARTICLE_WITH_VELOCITY -> particleMatrix
|
||||
} ?: Vec3(storm.getX(), storm.getY(), storm.getZ())).let { MatrixWrapper().updatePosition(it) }
|
||||
}
|
||||
|
||||
val sourceVelocity = when (effect.type) {
|
||||
@@ -120,24 +105,17 @@ class ParticleEvent(
|
||||
|
||||
val newStorm = ParticleStorm(
|
||||
effect = bedrockParticleOptions,
|
||||
emitterSpaceMatrix = particleMatrix,
|
||||
locatorSpaceMatrix = locatorMatrix,
|
||||
matrixWrapper = rootMatrix,
|
||||
world = storm.world,
|
||||
sourceVelocity = sourceVelocity,
|
||||
sourceAlive = storm.sourceAlive,
|
||||
sourceVisible = storm.sourceVisible,
|
||||
onDespawn = {},
|
||||
targetPos = storm.targetPos,
|
||||
runtime = MoLangRuntime().setup(),
|
||||
runtime = MoLangRuntime().setup().also { it.environment.query = storm.runtime.environment.query },
|
||||
entity = storm.entity
|
||||
)
|
||||
//The reason this doesn't use the newStorms runtime is that the parent storm can add queries AFTER
|
||||
//the child storm spawns in. Say a parent storm has a creation event. The child spawns before the parent
|
||||
//When the parent tries to add its queries, it overwrites the child's
|
||||
val tempRuntime = MoLangRuntime().setup().also {
|
||||
it.environment.query = storm.runtime.environment.query
|
||||
}
|
||||
effect.expression?.resolve(tempRuntime)
|
||||
|
||||
effect.expression?.resolve(newStorm.runtime)
|
||||
|
||||
newStorm.spawn()
|
||||
}
|
||||
|
||||
@@ -77,17 +77,16 @@ class ParametricParticleMotion(
|
||||
|
||||
override fun getInitialVelocity(runtime: MoLangRuntime, storm: ParticleStorm, particlePos: Vec3, emitterPos: Vec3) = Vec3.ZERO
|
||||
override fun getVelocity(runtime: MoLangRuntime, particle: SnowstormParticle, velocity: Vec3): Vec3 {
|
||||
val particlePositionWS = Vec3(
|
||||
particle.getX(),
|
||||
particle.getY(),
|
||||
particle.getZ()
|
||||
val stormPosition = Vec3(
|
||||
particle.storm.getX(),
|
||||
particle.storm.getY(),
|
||||
particle.storm.getZ()
|
||||
)
|
||||
val matrix = particle.matrixWrapper
|
||||
|
||||
val targetPosPS = runtime.resolveVec3d(offset)
|
||||
val targetPosWS = matrix.transformPosition(targetPosPS)
|
||||
|
||||
return targetPosWS.subtract(particlePositionWS)
|
||||
val offset = runtime.resolveVec3d(this.offset)
|
||||
val particlePosition =
|
||||
Vec3(particle.getX(), particle.getY(), particle.getZ())
|
||||
val desiredPosition = stormPosition.add(offset)
|
||||
return desiredPosition.subtract(particlePosition)
|
||||
}
|
||||
|
||||
override fun getParticleDirection(runtime: MoLangRuntime, storm: ParticleStorm, velocity: Vec3, minSpeed: Float) = runtime.resolveVec3d(direction).normalize()
|
||||
@@ -278,7 +277,7 @@ class CustomMotionDirection(
|
||||
runtime.resolveDouble(direction.second),
|
||||
runtime.resolveDouble(direction.third)
|
||||
)
|
||||
return storm.emitterSpaceMatrix.matrix.transformDirection(v)
|
||||
return storm.matrixWrapper.matrix.transformDirection(v)
|
||||
}
|
||||
|
||||
override fun <T> encode(ops: DynamicOps<T>) = CODEC.encodeStart(ops, this)
|
||||
|
||||
-5
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.api.spawning.condition
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
|
||||
import com.cobblemon.mod.common.api.spawning.context.FishingSpawningContext
|
||||
import com.cobblemon.mod.common.util.itemRegistry
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper
|
||||
import net.minecraft.world.item.enchantment.Enchantments
|
||||
@@ -28,10 +27,6 @@ class FishingSpawningCondition: SpawningCondition<FishingSpawningContext>() {
|
||||
|
||||
var rod: RegistryLikeCondition<Item>? = null
|
||||
var neededNearbyBlocks: MutableList<RegistryLikeCondition<Block>>? = null
|
||||
var minLureLevel: Int? = null
|
||||
var maxLureLevel: Int? = null
|
||||
var bait: ResourceLocation? = null
|
||||
var rodType: ResourceLocation? = null
|
||||
|
||||
override fun fits(ctx: FishingSpawningContext): Boolean {
|
||||
if (!super.fits(ctx)) {
|
||||
|
||||
+4
@@ -59,6 +59,10 @@ abstract class SpawningCondition<T : SpawningContext> {
|
||||
var isThundering: Boolean? = null
|
||||
var timeRange: TimeRange? = null
|
||||
var structures: MutableList<Either<ResourceLocation, TagKey<Structure>>>? = null
|
||||
var minLureLevel: Int? = null
|
||||
var maxLureLevel: Int? = null
|
||||
var bait: ResourceLocation? = null
|
||||
var rodType: ResourceLocation? = null
|
||||
var isSlimeChunk: Boolean? = null
|
||||
|
||||
@Transient
|
||||
|
||||
+6
-2
@@ -10,12 +10,15 @@ package com.cobblemon.mod.common.api.spawning.fishing
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
import com.cobblemon.mod.common.api.abilities.Abilities
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.fishing.BobberSpawnPokemonEvent
|
||||
import com.cobblemon.mod.common.api.fishing.FishingBait
|
||||
import com.cobblemon.mod.common.api.pokemon.Natures
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.api.pokemon.egg.EggGroup
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnBucket
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnCause
|
||||
@@ -24,6 +27,7 @@ import com.cobblemon.mod.common.api.spawning.detail.PokemonSpawnDetail
|
||||
import com.cobblemon.mod.common.api.spawning.detail.SpawnDetail
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.Spawner
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.api.types.tera.TeraTypes
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.item.interactive.PokerodItem
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
@@ -125,8 +129,8 @@ class FishingSpawnCause(
|
||||
}
|
||||
|
||||
fun alterFriendshipAttempt(pokemonEntity: PokemonEntity, effect: FishingBait.Effect) {
|
||||
if (pokemonEntity.pokemon.friendship + effect.value > Cobblemon.config.maxPokemonFriendship)
|
||||
pokemonEntity.pokemon.setFriendship(Cobblemon.config.maxPokemonFriendship)
|
||||
if (pokemonEntity.pokemon.friendship + effect.value > 255)
|
||||
pokemonEntity.pokemon.setFriendship(255)
|
||||
else
|
||||
pokemonEntity.pokemon.setFriendship(pokemonEntity.pokemon.friendship + effect.value.toInt())
|
||||
}
|
||||
|
||||
+1
-2
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.api.spawning.rules.component
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.ast.BooleanExpression
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
|
||||
import com.cobblemon.mod.common.api.spawning.detail.SpawnDetail
|
||||
@@ -34,7 +33,7 @@ class FilterRuleComponent : SpawnRuleComponent {
|
||||
|
||||
val spawnSelector: SpawnDetailSelector = AllSpawnDetailSelector
|
||||
val contextSelector: SpawningContextSelector = AllSpawningContextSelector
|
||||
val allow: Expression = BooleanExpression(false)
|
||||
val allow: Expression = BooleanExpression(true)
|
||||
|
||||
override fun affectSpawnable(detail: SpawnDetail, ctx: SpawningContext): Boolean {
|
||||
return if (spawnSelector.selects(detail) && contextSelector.selects(ctx)) {
|
||||
|
||||
@@ -8,14 +8,12 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.storage
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.storage.factory.FileBackedPokemonStoreFactory
|
||||
import com.cobblemon.mod.common.api.storage.factory.PokemonStoreFactory
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.google.gson.JsonObject
|
||||
import java.util.UUID
|
||||
import net.minecraft.core.RegistryAccess
|
||||
@@ -149,14 +147,10 @@ abstract class PokemonStore<T : StorePosition> : Iterable<Pokemon> {
|
||||
|
||||
operator fun get(uuid: UUID) = find { it.uuid == uuid }
|
||||
|
||||
open fun handleInvalidSpeciesNBT(nbt: CompoundTag) {
|
||||
Cobblemon.LOGGER.error("Failed to read unknown species: ${nbt.getString(DataKeys.POKEMON_SPECIES_IDENTIFIER)}")
|
||||
}
|
||||
open fun handleInvalidSpeciesNBT(nbt: CompoundTag) {}
|
||||
abstract fun saveToNBT(nbt: CompoundTag, registryAccess: RegistryAccess): CompoundTag
|
||||
abstract fun loadFromNBT(nbt: CompoundTag, registryAccess: RegistryAccess): PokemonStore<T>
|
||||
open fun handleInvalidSpeciesJSON(json: JsonObject) {
|
||||
Cobblemon.LOGGER.error("Failed to read unknown species: ${json.get(DataKeys.POKEMON_SPECIES_IDENTIFIER).asString}")
|
||||
}
|
||||
open fun handleInvalidSpeciesJSON(json: JsonObject) {}
|
||||
abstract fun saveToJSON(json: JsonObject, registryAccess: RegistryAccess): JsonObject
|
||||
abstract fun loadFromJSON(json: JsonObject, registryAccess: RegistryAccess): PokemonStore<T>
|
||||
abstract fun savePositionToNBT(position: T, nbt: CompoundTag)
|
||||
|
||||
+9
-9
@@ -46,16 +46,16 @@ open class JSONStoreAdapter(
|
||||
|
||||
override fun <E, T : PokemonStore<E>> load(file: File, storeClass: Class<out T>, uuid: UUID, registryAccess: RegistryAccess): T? {
|
||||
return try {
|
||||
file.reader().use {
|
||||
val json = gson.fromJson<JsonObject>(it)
|
||||
val store = try {
|
||||
storeClass.getConstructor(UUID::class.java, UUID::class.java).newInstance(uuid, uuid)
|
||||
} catch (exception: NoSuchMethodException) {
|
||||
storeClass.getConstructor(UUID::class.java).newInstance(uuid)
|
||||
}
|
||||
store.loadFromJSON(json, registryAccess)
|
||||
store
|
||||
val br = BufferedReader(FileReader(file))
|
||||
val json = gson.fromJson<JsonObject>(br)
|
||||
br.close()
|
||||
val store = try {
|
||||
storeClass.getConstructor(UUID::class.java, UUID::class.java).newInstance(uuid, uuid)
|
||||
} catch (exception: NoSuchMethodException) {
|
||||
storeClass.getConstructor(UUID::class.java).newInstance(uuid)
|
||||
}
|
||||
store.loadFromJSON(json, registryAccess)
|
||||
store
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
|
||||
+15
-36
@@ -42,7 +42,6 @@ abstract class OneToOneFileStoreAdapter<S>(
|
||||
) : FileStoreAdapter<S>, CobblemonAdapterParent<S>() {
|
||||
abstract fun save(file: File, serialized: S)
|
||||
abstract fun <E, T : PokemonStore<E>> load(file: File, storeClass: Class<out T>, uuid: UUID, registryAccess: RegistryAccess): T?
|
||||
|
||||
fun getFile(storeClass: Class<out PokemonStore<*>>, uuid: UUID): File {
|
||||
val className = storeClass.simpleName.lowercase()
|
||||
val subfolder1 = if (folderPerClass) "$className/" else ""
|
||||
@@ -57,54 +56,34 @@ abstract class OneToOneFileStoreAdapter<S>(
|
||||
override fun save(storeClass: Class<out PokemonStore<*>>, uuid: UUID, serialized: S) {
|
||||
val file = getFile(storeClass, uuid)
|
||||
val tempFile = File(file.absolutePath + ".temp")
|
||||
val oldFile = File(file.absolutePath + ".old")
|
||||
tempFile.createNewFile()
|
||||
save(tempFile, serialized)
|
||||
if (file.exists()) {
|
||||
file.copyTo(oldFile, overwrite = true)
|
||||
}
|
||||
tempFile.copyTo(file, overwrite = true)
|
||||
tempFile.delete()
|
||||
}
|
||||
|
||||
override fun <E : StorePosition, T : PokemonStore<E>> provide(storeClass: Class<T>, uuid: UUID, registryAccess: RegistryAccess): T? {
|
||||
val file = getFile(storeClass, uuid)
|
||||
val oldFile = File(file.absolutePath + ".old")
|
||||
val tempFile = File(file.absolutePath + ".temp")
|
||||
if (tempFile.exists()) {
|
||||
try {
|
||||
val tempLoaded = load(tempFile, storeClass, uuid, registryAccess)
|
||||
if (tempLoaded != null) {
|
||||
save(file, serialize(tempLoaded, registryAccess))
|
||||
return tempLoaded
|
||||
}
|
||||
} finally {
|
||||
tempFile.delete()
|
||||
}
|
||||
}
|
||||
|
||||
return if (file.exists() && file.length() > 0L) {
|
||||
return if (file.exists()) {
|
||||
load(file, storeClass, uuid, registryAccess)
|
||||
?: let {
|
||||
file.delete()
|
||||
if (oldFile.exists() && oldFile.length() > 0L) {
|
||||
var result = load(oldFile, storeClass, uuid, registryAccess) ?: let {
|
||||
LOGGER.error("Pokémon save file for ${storeClass.simpleName} ($uuid) was corrupted. A fresh file will be created.")
|
||||
var result = storeClass.getConstructor(UUID::class.java).newInstance(uuid)
|
||||
save(storeClass, uuid, serialize(result, registryAccess))
|
||||
oldFile.delete()
|
||||
return result
|
||||
}
|
||||
LOGGER.warn("Loading old Pokémon save file for ${storeClass.simpleName} ($uuid) due to corruption of current file.")
|
||||
oldFile.copyTo(file, overwrite = true)
|
||||
result
|
||||
}
|
||||
else {
|
||||
storeClass.getConstructor(UUID::class.java).newInstance(uuid)
|
||||
var result = storeClass.getConstructor(UUID::class.java).newInstance(uuid)
|
||||
save(storeClass, uuid, serialize(result, registryAccess))
|
||||
oldFile.delete()
|
||||
result
|
||||
}
|
||||
LOGGER.error("Pokémon save file for ${storeClass.simpleName} ($uuid) was corrupted. A fresh file will be created.")
|
||||
storeClass.getConstructor(UUID::class.java).newInstance(uuid)
|
||||
}
|
||||
} else {
|
||||
file.delete()
|
||||
if (oldFile.exists() && oldFile.length() > 0L) {
|
||||
var result = load(oldFile, storeClass, uuid, registryAccess) ?: let {
|
||||
oldFile.delete()
|
||||
return null
|
||||
}
|
||||
oldFile.copyTo(file, overwrite = true)
|
||||
result
|
||||
}
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
+14
-14
@@ -27,15 +27,15 @@ import net.minecraft.world.entity.player.Player
|
||||
* @since February 21, 2024
|
||||
*/
|
||||
|
||||
open class PlayerInstancedDataStoreManager {
|
||||
class PlayerInstancedDataStoreManager {
|
||||
val factories = mutableMapOf<PlayerInstancedDataStoreType, PlayerInstancedDataFactory<*>>()
|
||||
val saveTasks = mutableMapOf<PlayerInstancedDataStoreType, ScheduledTask>()
|
||||
open fun setFactory(factory: PlayerInstancedDataFactory<*>, dataType: PlayerInstancedDataStoreType) {
|
||||
fun setFactory(factory: PlayerInstancedDataFactory<*>, dataType: PlayerInstancedDataStoreType) {
|
||||
factories[dataType] = factory
|
||||
}
|
||||
|
||||
|
||||
open fun setup(server: MinecraftServer) {
|
||||
fun setup(server: MinecraftServer) {
|
||||
factories.values.forEach {
|
||||
it.setup(server)
|
||||
}
|
||||
@@ -57,62 +57,62 @@ open class PlayerInstancedDataStoreManager {
|
||||
.build()
|
||||
}
|
||||
|
||||
open fun get(playerId: UUID, dataType: PlayerInstancedDataStoreType): InstancedPlayerData {
|
||||
fun get(playerId: UUID, dataType: PlayerInstancedDataStoreType): InstancedPlayerData {
|
||||
if (!factories.contains(dataType)) {
|
||||
throw UnsupportedOperationException("No factory registered for $dataType")
|
||||
}
|
||||
return factories[dataType]!!.getForPlayer(playerId)
|
||||
}
|
||||
|
||||
open fun get(player: Player, dataType: PlayerInstancedDataStoreType): InstancedPlayerData {
|
||||
fun get(player: Player, dataType: PlayerInstancedDataStoreType): InstancedPlayerData {
|
||||
return get(player.uuid, dataType)
|
||||
}
|
||||
|
||||
open fun saveAllOfOneType(dataType: PlayerInstancedDataStoreType) {
|
||||
fun saveAllOfOneType(dataType: PlayerInstancedDataStoreType) {
|
||||
if (!factories.contains(dataType)) {
|
||||
throw UnsupportedOperationException("No factory registered for $dataType")
|
||||
}
|
||||
return factories[dataType]!!.saveAll()
|
||||
}
|
||||
|
||||
open fun saveSingle(playerData: InstancedPlayerData, dataType: PlayerInstancedDataStoreType) {
|
||||
fun saveSingle(playerData: InstancedPlayerData, dataType: PlayerInstancedDataStoreType) {
|
||||
if (!factories.contains(dataType)) {
|
||||
throw UnsupportedOperationException("No factory registered for $dataType")
|
||||
}
|
||||
return factories[dataType]!!.saveSingle(playerData.uuid)
|
||||
}
|
||||
|
||||
open fun onPlayerDisconnect(player: ServerPlayer) {
|
||||
fun onPlayerDisconnect(player: ServerPlayer) {
|
||||
factories.values.forEach {
|
||||
it.onPlayerDisconnect(player)
|
||||
}
|
||||
}
|
||||
|
||||
open fun syncAllToPlayer(player: ServerPlayer) {
|
||||
fun syncAllToPlayer(player: ServerPlayer) {
|
||||
factories.values.forEach {
|
||||
it.sendToPlayer(player)
|
||||
}
|
||||
}
|
||||
|
||||
open fun saveAllStores() {
|
||||
fun saveAllStores() {
|
||||
factories.values.forEach {
|
||||
it.saveAll()
|
||||
}
|
||||
}
|
||||
|
||||
open fun getGenericData(player: ServerPlayer): GeneralPlayerData {
|
||||
fun getGenericData(player: ServerPlayer): GeneralPlayerData {
|
||||
return getGenericData(player.uuid)
|
||||
}
|
||||
|
||||
open fun getGenericData(playerId: UUID): GeneralPlayerData {
|
||||
fun getGenericData(playerId: UUID): GeneralPlayerData {
|
||||
return get(playerId, PlayerInstancedDataStoreTypes.GENERAL) as GeneralPlayerData
|
||||
}
|
||||
|
||||
open fun getPokedexData(player: ServerPlayer): PokedexManager {
|
||||
fun getPokedexData(player: ServerPlayer): PokedexManager {
|
||||
return getPokedexData(player.uuid)
|
||||
}
|
||||
|
||||
open fun getPokedexData(playerId: UUID): PokedexManager {
|
||||
fun getPokedexData(playerId: UUID): PokedexManager {
|
||||
return get(playerId, PlayerInstancedDataStoreTypes.POKEDEX) as PokedexManager
|
||||
}
|
||||
}
|
||||
+5
-62
@@ -8,12 +8,10 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.storage.player.adapter
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.storage.player.InstancedPlayerData
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreType
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.world.level.storage.LevelResource
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
import java.util.UUID
|
||||
|
||||
@@ -37,70 +35,15 @@ abstract class FileBasedPlayerDataStoreBackend<T : InstancedPlayerData>(
|
||||
savePath = server.getWorldPath(LevelResource.PLAYER_DATA_DIR).parent
|
||||
}
|
||||
|
||||
protected fun postSaveFileMoving(playerData: T) {
|
||||
val tempFile = filePath(playerData.uuid, TEMPORARY_FILE_EXTENSION)
|
||||
val oldFile = filePath(playerData.uuid, OLD_FILE_EXTENSION)
|
||||
val file = filePath(playerData.uuid)
|
||||
if (file.exists()) {
|
||||
file.copyTo(oldFile, overwrite = true)
|
||||
}
|
||||
tempFile.copyTo(file, overwrite = true)
|
||||
tempFile.delete()
|
||||
}
|
||||
|
||||
protected fun loadWithFallback(uuid: UUID, loadFunction: (File) -> T): T {
|
||||
val playerFile = filePath(uuid)
|
||||
val playerFileOld = filePath(uuid, OLD_FILE_EXTENSION)
|
||||
playerFile.parentFile.mkdirs()
|
||||
val loadFallback: () -> T = {
|
||||
playerFile.delete()
|
||||
if (playerFileOld.exists() && playerFileOld.length() > 0L) {
|
||||
try {
|
||||
var result = loadFunction(playerFileOld)
|
||||
playerFileOld.copyTo(playerFile)
|
||||
Cobblemon.LOGGER.debug("Loaded .old {} for {}", subfolder, uuid)
|
||||
result
|
||||
} catch (e: Exception) {
|
||||
Cobblemon.LOGGER.error("Failed to load .old $subfolder for $uuid due to ${e.message}. Data is lost")
|
||||
Cobblemon.LOGGER.error(e)
|
||||
playerFileOld.delete()
|
||||
defaultData.invoke(uuid).also(::save)
|
||||
}
|
||||
}
|
||||
else {
|
||||
Cobblemon.LOGGER.error(".old File $subfolder for $uuid is corrupt or missing. Data is lost")
|
||||
playerFileOld.delete()
|
||||
defaultData.invoke(uuid).also(::save)
|
||||
}
|
||||
}
|
||||
return if (playerFile.exists() && playerFile.length() > 0L) {
|
||||
try {
|
||||
loadFunction(playerFile)
|
||||
}
|
||||
catch (e: Exception) {
|
||||
Cobblemon.LOGGER.warn("Failed to load $subfolder for $uuid due to ${e.message}")
|
||||
Cobblemon.LOGGER.warn(e)
|
||||
loadFallback()
|
||||
}
|
||||
} else {
|
||||
loadFallback()
|
||||
}.also { it.initialize() }
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun getSubFile(uuid: UUID, extension: String? = null): String {
|
||||
//TODO: Set file extension to be a field
|
||||
fun getSubFile(uuid: UUID): String {
|
||||
return if (useNestedStructure) {
|
||||
"${uuid.toString().substring(0, 2)}/$uuid.$fileExt${if (extension != null) ".$extension" else ""}"
|
||||
"${uuid.toString().substring(0, 2)}/$uuid.$fileExt"
|
||||
} else {
|
||||
"$uuid.$fileExt.${if (extension != null) ".$extension" else ""}"
|
||||
"$uuid.$fileExt"
|
||||
}
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun filePath(uuid: UUID, extension: String? = null): File = savePath.resolve("$subfolder/${getSubFile(uuid, extension)}").toFile()
|
||||
fun filePath(uuid: UUID) = savePath.resolve("$subfolder/${getSubFile(uuid)}").toFile()
|
||||
|
||||
companion object {
|
||||
const val OLD_FILE_EXTENSION = "old"
|
||||
const val TEMPORARY_FILE_EXTENSION = "tmp"
|
||||
}
|
||||
}
|
||||
+19
-16
@@ -28,26 +28,29 @@ abstract class JsonBackedPlayerDataStoreBackend<T : InstancedPlayerData>(
|
||||
abstract val classToken: TypeToken<T>
|
||||
|
||||
override fun save(playerData: T) {
|
||||
val fileTmp = filePath(playerData.uuid, TEMPORARY_FILE_EXTENSION)
|
||||
fileTmp.parentFile.mkdirs()
|
||||
fileTmp.printWriter().use { pw ->
|
||||
pw.write(gson.toJson(playerData))
|
||||
}
|
||||
postSaveFileMoving(playerData)
|
||||
val file = filePath(playerData.uuid)
|
||||
file.parentFile.mkdirs()
|
||||
val pw = PrintWriter(filePath(playerData.uuid))
|
||||
pw.write(gson.toJson(playerData))
|
||||
pw.flush()
|
||||
pw.close()
|
||||
}
|
||||
|
||||
override fun load(uuid: UUID): T {
|
||||
return loadWithFallback(uuid) {
|
||||
it.reader().use { reader ->
|
||||
gson.fromJson(reader, classToken).also {
|
||||
// Resolves old data that's missing new properties
|
||||
val newProps = it::class.memberProperties.filterIsInstance<KMutableProperty<*>>().filter { member -> member.getter.call(it) == null }
|
||||
if (newProps.isNotEmpty()) {
|
||||
val defaultData = defaultData(uuid)
|
||||
newProps.forEach { member -> member.setter.call(it, member.getter.call(defaultData)) }
|
||||
}
|
||||
val playerFile = filePath(uuid)
|
||||
playerFile.parentFile.mkdirs()
|
||||
return if (playerFile.exists()) {
|
||||
gson.fromJson(BufferedReader(FileReader(playerFile)), classToken).also {
|
||||
// Resolves old data that's missing new properties
|
||||
val newProps = it::class.memberProperties.filterIsInstance<KMutableProperty<*>>().filter { member -> member.getter.call(it) == null }
|
||||
if (newProps.isNotEmpty()) {
|
||||
val defaultData = defaultData(uuid)
|
||||
newProps.forEach { member -> member.setter.call(it, member.getter.call(defaultData)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
defaultData.invoke(uuid).also(::save)
|
||||
}.also { it.initialize() }
|
||||
}
|
||||
|
||||
}
|
||||
+17
-12
@@ -24,24 +24,29 @@ abstract class NbtBackedPlayerData<T : InstancedPlayerData>(
|
||||
type: PlayerInstancedDataStoreType
|
||||
) : FileBasedPlayerDataStoreBackend<T>(subfolder, type, "nbt") {
|
||||
abstract val codec: Codec<T>
|
||||
|
||||
override fun save(playerData: T) {
|
||||
val fileTmp = filePath(playerData.uuid, TEMPORARY_FILE_EXTENSION)
|
||||
fileTmp.parentFile.mkdirs()
|
||||
val encodeResult = codec.encodeStart(NbtOps.INSTANCE, playerData)
|
||||
NbtIo.write(encodeResult.result().get() as CompoundTag, fileTmp.toPath())
|
||||
postSaveFileMoving(playerData)
|
||||
val file = filePath(playerData.uuid)
|
||||
file.parentFile.mkdirs()
|
||||
val os = DataOutputStream(FileOutputStream(filePath(playerData.uuid)))
|
||||
val encodeResult = NbtOps.INSTANCE.withEncoder(codec).apply(playerData)
|
||||
NbtIo.write(encodeResult.result().get() as CompoundTag, os)
|
||||
os.flush()
|
||||
os.close()
|
||||
}
|
||||
|
||||
override fun load(uuid: UUID): T {
|
||||
return loadWithFallback(uuid) {
|
||||
val input = NbtIo.read(it.toPath())
|
||||
val decodeResult = codec.decode(NbtOps.INSTANCE, input)
|
||||
decodeResult.getOrThrow {
|
||||
Cobblemon.LOGGER.error("Error decoding $subfolder for player uuid $uuid")
|
||||
val playerFile = filePath(uuid)
|
||||
playerFile.parentFile.mkdirs()
|
||||
return if (playerFile.exists()) {
|
||||
val input = NbtIo.read(playerFile.toPath())
|
||||
val decodeResult = NbtOps.INSTANCE.withDecoder(codec).apply(input)
|
||||
decodeResult.getPartialOrThrow {
|
||||
Cobblemon.LOGGER.error("Error decoding pokedex for player uuid ${uuid}")
|
||||
Cobblemon.LOGGER.error(it)
|
||||
throw UnsupportedOperationException()
|
||||
}.first
|
||||
}
|
||||
} else {
|
||||
defaultData.invoke(uuid).also(::save)
|
||||
}.also { it.initialize() }
|
||||
}
|
||||
}
|
||||
@@ -23,72 +23,30 @@ object CobblemonBlockTags {
|
||||
|
||||
@JvmField val ALL_HANGING_SIGNS = createTag("all_hanging_signs")
|
||||
@JvmField val ALL_SIGNS = createTag("all_signs")
|
||||
@JvmField val ANCIENT_CITY_BLOCKS = createTag("ancient_city_blocks")
|
||||
@JvmField val APRICORN_LEAVES = createTag("apricorn_leaves")
|
||||
@JvmField val APRICORN_LOGS = createTag("apricorn_logs")
|
||||
@JvmField val APRICORN_SAPLINGS = createTag("apricorn_saplings")
|
||||
@JvmField val APRICORNS = createTag("apricorns")
|
||||
@JvmField val BERRIES = createTag("berries")
|
||||
@JvmField val BERRY_REPLACEABLE = createTag("berry_replaceable")
|
||||
@JvmField val BERRY_SOIL = createTag("berry_soil")
|
||||
@JvmField val BERRY_WILD_SOIL = createTag("berry_wild_soil")
|
||||
@JvmField val BLACK_TUMBLESTONE_BRICKS = createTag("black_tumblestone_bricks")
|
||||
@JvmField val BLACK_TUMBLESTONES = createTag("black_tumblestones")
|
||||
@JvmField val BLUE_FLOWERS = createTag("blue_flowers")
|
||||
@JvmField val BERRY_SOIL = createTag("berry_soil")
|
||||
@JvmField val BERRY_REPLACEABLE = createTag("berry_replaceable")
|
||||
@JvmField val CEILING_HANGING_SIGNS = createTag("ceiling_hanging_signs")
|
||||
@JvmField val CROPS = createTag("crops")
|
||||
@JvmField val DAWN_STONE_ORES = createTag("dawn_stone_ores")
|
||||
@JvmField val DESERT_PYRAMID_BLOCKS = createTag("desert_pyramid_blocks")
|
||||
@JvmField val DRIPSTONE_GROWABLE = createTag("dripstone_growable")
|
||||
@JvmField val DRIPSTONE_REPLACEABLES = createTag("dripstone_replaceables")
|
||||
@JvmField val DUSK_STONE_ORES = createTag("dusk_stone_ores")
|
||||
@JvmField val END_CITY_BLOCKS = createTag("end_city_blocks")
|
||||
@JvmField val EVOLUTION_STONE_BLOCKS = createTag("evolution_stone_blocks")
|
||||
@JvmField val FIRE_STONE_ORES = createTag("fire_stone_ores")
|
||||
@JvmField val FLOWERS = createTag("flowers")
|
||||
@JvmField val FOSSIL_MACHINE_PARTS = createTag("fossil_machine_parts")
|
||||
@JvmField val GEMSTONES = createTag("gemstones")
|
||||
@JvmField val GILDED_CHESTS = createTag("gilded_chests")
|
||||
@JvmField val GLAZED_TERRACOTTA_BLOCKS = createTag("glazed_terracotta_blocks")
|
||||
@JvmField val ICE_STONE_ORES = createTag("ice_stone_ores")
|
||||
@JvmField val JUNGLE_PYRAMID_BLOCKS = createTag("jungle_pyramid_blocks")
|
||||
@JvmField val LEAF_STONE_ORES = createTag("leaf_stone_ores")
|
||||
@JvmField val MACHINES = createTag("machines")
|
||||
@JvmField val MANSION_BLOCKS = createTag("mansion_blocks")
|
||||
@JvmField val MEDICINAL_LEEK_PLANTABLE = createTag("medicinal_leek_plantable")
|
||||
@JvmField val MINTS = createTag("mints")
|
||||
@JvmField val MOON_STONE_ORES = createTag("moon_stone_ores")
|
||||
@JvmField val NATURAL = createTag("natural")
|
||||
@JvmField val NETHER_STRUCTURE_BLOCKS = createTag("nether_structure_blocks")
|
||||
@JvmField val PINK_FLOWERS = createTag("pink_flowers")
|
||||
@JvmField val RED_FLOWERS = createTag("red_flowers")
|
||||
@JvmField val RED_TUMBLESTONE_BRICKS = createTag("red_tumblestone_bricks")
|
||||
@JvmField val RED_TUMBLESTONES = createTag("red_tumblestones")
|
||||
@JvmField val REDSTONE_BLOCKS = createTag("redstone_blocks")
|
||||
@JvmField val ROOTS = createTag("roots")
|
||||
@JvmField val ROOTS_SPREADABLE = createTag("roots_spreadable")
|
||||
@JvmField val RUINED_PORTAL_BLOCKS = createTag("ruined_portal_blocks")
|
||||
@JvmField val SEES_SKY = createTag("sees_sky")
|
||||
@JvmField val SHINY_STONE_ORES = createTag("shiny_stone_ores")
|
||||
@JvmField val SIGNS = createTag("signs")
|
||||
@JvmField val SKY_TUMBLESTONE_BRICKS = createTag("sky_tumblestone_bricks")
|
||||
@JvmField val SKY_TUMBLESTONES = createTag("sky_tumblestones")
|
||||
@JvmField val SMALL_FLOWERS = createTag("small_flowers")
|
||||
@JvmField val SEES_SKY = createTag("sees_sky")
|
||||
@JvmField val SNOW_BLOCK = createTag("snow_block")
|
||||
@JvmField val ROOTS = createTag("roots")
|
||||
@JvmField val STANDING_SIGNS = createTag("standing_signs")
|
||||
@JvmField val SUN_STONE_ORES = createTag("sun_stone_ores")
|
||||
@JvmField val THUNDER_STONE_ORES = createTag("thunder_stone_ores")
|
||||
@JvmField val TRAIL_RUINS_BLOCKS = createTag("trail_ruins_blocks")
|
||||
@JvmField val TRASH = createTag("trash")
|
||||
@JvmField val TREES = createTag("trees")
|
||||
@JvmField val TUMBLESTONE_BRICKS = createTag("tumblestone_bricks")
|
||||
@JvmField val TUMBLESTONES = createTag("tumblestones")
|
||||
@JvmField val TUMBLESTONE_HEAT_SOURCE = createTag("tumblestone_heat_source")
|
||||
@JvmField val WALL_HANGING_SIGNS = createTag("wall_hanging_signs")
|
||||
@JvmField val WALL_SIGNS = createTag("wall_signs")
|
||||
@JvmField val WATER_STONE_ORES = createTag("water_stone_ores")
|
||||
@JvmField val WHITE_FLOWERS = createTag("white_flowers")
|
||||
@JvmField val YELLOW_FLOWERS = createTag("yellow_flowers")
|
||||
|
||||
private fun createTag(name: String) = TagKey.create(Registries.BLOCK, cobblemonResource(name))
|
||||
|
||||
|
||||
@@ -21,108 +21,137 @@ import net.minecraft.tags.TagKey
|
||||
*/
|
||||
@Suppress("unused", "HasPlatformType")
|
||||
object CobblemonItemTags {
|
||||
@JvmField val ABILITY_CHANGERS = create("ability_changers")
|
||||
@JvmField val ANCIENT_POKE_BALLS = create("ancient_poke_balls")
|
||||
@JvmField val APPLES = create("apples")
|
||||
@JvmField val APRICORN_LOGS = create("apricorn_logs")
|
||||
@JvmField val APRICORN_POKE_BALLS = create("apricorn_poke_balls")
|
||||
@JvmField val APRICORN_SPROUTS = create("apricorn_sprouts")
|
||||
@JvmField val APRICORNS = create("apricorns")
|
||||
/** This tag is only used for a Torterra aspect based easter egg evolution at the moment.
|
||||
* It simply includes the 'minecraft:azalea' and 'minecraft:flowering_azalea' items by default. */
|
||||
@JvmField val AZALEA_TREE = create("azalea_tree")
|
||||
@JvmField val BATTLE_ITEMS = create("battle_items")
|
||||
@JvmField val BERRIES = create("berries")
|
||||
@JvmField val BLACK_TUMBLESTONE_BRICKS = create("black_tumblestone_bricks")
|
||||
@JvmField val BLACK_TUMBLESTONES = create("black_tumblestones")
|
||||
@JvmField val BOATS = create("boats")
|
||||
/** This tag is used for Fossil Machine natural materials */
|
||||
@JvmField val COOKED_MEAT = create("cooked_meat")
|
||||
@JvmField val DAWN_STONE_ORES = create("dawn_stone_ores")
|
||||
@JvmField val POTTERY_SHERDS = create("decorated_pot_sherds")
|
||||
@JvmField val DEEP_SEAS = create("deep_seas")
|
||||
@JvmField val DUSK_STONE_ORES = create("dusk_stone_ores")
|
||||
@JvmField val ETHERS = create("ethers")
|
||||
@JvmField val EVOLUTION_ITEMS = create("evolution_items")
|
||||
@JvmField val EVOLUTION_STONE_BLOCKS = create("evolution_stone_blocks")
|
||||
@JvmField val EVOLUTION_STONES = create("evolution_stones")
|
||||
@JvmField val EXPERIENCE_CANDIES = create("experience_candies")
|
||||
@JvmField val FEATHERS = create("feathers")
|
||||
@JvmField val FIRE_STONE_ORES = create("fire_stone_ores")
|
||||
@JvmField val FOSSIL_MACHINE_PARTS = create("fossil_machine_parts")
|
||||
@JvmField val FOSSILS = create("fossils")
|
||||
@JvmField val GILDED_CHESTS = create("gilded_chests")
|
||||
@JvmField val HANGING_SIGNS = create("hanging_signs")
|
||||
@JvmField val HERBS = create("herbs")
|
||||
@JvmField val ICE_STONE_ORES = create("ice_stone_ores")
|
||||
@JvmField val LEAF_STONE_ORES = create("leaf_stone_ores")
|
||||
@JvmField val MACHINES = create("machines")
|
||||
@JvmField val MINT_LEAF = create("mint_leaf")
|
||||
@JvmField val MINT_SEEDS = create("mint_seeds")
|
||||
@JvmField val MINTS = create("mints")
|
||||
@JvmField val MOON_STONE_ORES = create("moon_stone_ores")
|
||||
@JvmField val MUTATED_BERRIES = create("mutated_berries")
|
||||
@JvmField val PLANTS = create("plants")
|
||||
@JvmField val POKE_BALLS = create("poke_balls")
|
||||
@JvmField val POKE_RODS = create("poke_rods")
|
||||
@JvmField val POKEDEX = create("pokedex")
|
||||
@JvmField val POKEDEX_SCREEN = create("pokedex_screen")
|
||||
@JvmField val POTIONS = create("potions")
|
||||
@JvmField val PROTEIN_INGREDIENTS = create("protein_ingredients")
|
||||
@JvmField
|
||||
val ANCIENT_POKE_BALLS = create("ancient_poke_balls")
|
||||
@JvmField
|
||||
val APRICORN_LOGS = create("apricorn_logs")
|
||||
@JvmField
|
||||
val APRICORN_SPROUTS = create("apricorn_sprouts")
|
||||
@JvmField
|
||||
val APRICORNS = create("apricorns")
|
||||
@JvmField
|
||||
val POKEDEX = create("pokedex")
|
||||
/**
|
||||
* This tag is only used for a Torterra aspect based easter egg evolution at the moment.
|
||||
* It simply includes the 'minecraft:azalea' and 'minecraft:flowering_azalea' items by default.
|
||||
*/
|
||||
@JvmField
|
||||
val AZALEA_TREE = create("azalea_tree")
|
||||
@JvmField
|
||||
val BERRIES = create("berries")
|
||||
@JvmField
|
||||
val BOATS = create("boats")
|
||||
@JvmField
|
||||
val COBBLEMON_SEEDS = create("cobblemon_seeds")
|
||||
/**
|
||||
* This tag is used for Fossil Machine natural materials
|
||||
*/
|
||||
@JvmField
|
||||
val COOKED_MEAT = create("cooked_meat")
|
||||
@JvmField
|
||||
val DAWN_STONE_ORES = create("dawn_stone_ores")
|
||||
@JvmField
|
||||
val DUSK_STONE_ORES = create("dusk_stone_ores")
|
||||
@JvmField
|
||||
val EVOLUTION_ITEMS = create("evolution_items")
|
||||
@JvmField
|
||||
val EVOLUTION_STONES = create("evolution_stones")
|
||||
@JvmField
|
||||
val EXPERIENCE_CANDIES = create("experience_candies")
|
||||
@JvmField
|
||||
val FIRE_STONE_ORES = create("fire_stone_ores")
|
||||
@JvmField
|
||||
val FOSSILS = create("fossils")
|
||||
@JvmField
|
||||
val HANGING_SIGNS = create("hanging_signs")
|
||||
@JvmField
|
||||
val HERBS = create("herbs")
|
||||
@JvmField
|
||||
val ICE_STONE_ORES = create("ice_stone_ores")
|
||||
@JvmField
|
||||
val LEAF_STONE_ORES = create("leaf_stone_ores")
|
||||
@JvmField
|
||||
val MINT_LEAF = create("mint_leaf")
|
||||
@JvmField
|
||||
val MINT_SEEDS = create("mint_seeds")
|
||||
@JvmField
|
||||
val MINTS = create("mints")
|
||||
@JvmField
|
||||
val MOON_STONE_ORES = create("moon_stone_ores")
|
||||
@JvmField
|
||||
val MUTATED_BERRIES = create("mutated_berries")
|
||||
@JvmField
|
||||
val PLANTS = create("plants")
|
||||
@JvmField
|
||||
val POKE_BALLS = create("poke_balls")
|
||||
@JvmField
|
||||
val PROTEIN_INGREDIENTS = create("protein_ingredients")
|
||||
/** See [COOKED_MEAT] */
|
||||
@JvmField val RAW_MEAT = create("raw_meat")
|
||||
@JvmField val RED_TUMBLESTONE_BRICKS = create("red_tumblestone_bricks")
|
||||
@JvmField val RED_TUMBLESTONES = create("red_tumblestones")
|
||||
@JvmField val REMEDIES = create("remedies")
|
||||
@JvmField val RESTORES = create("restores")
|
||||
@JvmField val REVIVES = create("revives")
|
||||
@JvmField val SEEDS = create("seeds")
|
||||
@JvmField val SHINY_STONE_ORES = create("shiny_stone_ores")
|
||||
@JvmField val SIGNS = create("signs")
|
||||
@JvmField val SKY_TUMBLESTONE_BRICKS = create("sky_tumblestone_bricks")
|
||||
@JvmField val SKY_TUMBLESTONES = create("sky_tumblestones")
|
||||
@JvmField val SUN_STONE_ORES = create("sun_stone_ores")
|
||||
@JvmField val SWEETS = create("sweets")
|
||||
@JvmField val TEACUPS = create("teacups")
|
||||
@JvmField val TEAPOTS = create("teapots")
|
||||
@JvmField val THUNDER_STONE_ORES = create("thunder_stone_ores")
|
||||
@JvmField val TIER_1_POKE_BALL_MATERIALS = create("tier_1_poke_ball_materials")
|
||||
@JvmField val TIER_1_POKE_BALLS = create("tier_1_poke_balls")
|
||||
@JvmField val TIER_2_POKE_BALL_MATERIALS = create("tier_2_poke_ball_materials")
|
||||
@JvmField val TIER_2_POKE_BALLS = create("tier_2_poke_balls")
|
||||
@JvmField val TIER_3_POKE_BALL_MATERIALS = create("tier_3_poke_ball_materials")
|
||||
@JvmField val TIER_3_POKE_BALLS = create("tier_3_poke_balls")
|
||||
@JvmField val TIER_4_POKE_BALL_MATERIALS = create("tier_4_poke_ball_materials")
|
||||
@JvmField val TIER_4_POKE_BALLS = create("tier_4_poke_balls")
|
||||
@JvmField val TIER_5_POKE_BALLS = create("tier_5_poke_balls")
|
||||
@JvmField val TUMBLESTONE_BRICKS = create("tumblestone_bricks")
|
||||
@JvmField val TUMBLESTONES = create("tumblestones")
|
||||
@JvmField val TYPE_GEMS = create("type_gems")
|
||||
@JvmField val VITAMINS = create("vitamins")
|
||||
@JvmField val WATER_STONE_ORES = create("water_stone_ores")
|
||||
@JvmField val ZINC_INGREDIENTS = create("zinc_ingredients")
|
||||
@JvmField
|
||||
val RAW_MEAT = create("raw_meat")
|
||||
@JvmField
|
||||
val SEEDS = create("seeds")
|
||||
@JvmField
|
||||
val SHINY_STONE_ORES = create("shiny_stone_ores")
|
||||
@JvmField
|
||||
val SIGNS = create("signs")
|
||||
@JvmField
|
||||
val SUN_STONE_ORES = create("sun_stone_ores")
|
||||
@JvmField
|
||||
val THUNDER_STONE_ORES = create("thunder_stone_ores")
|
||||
@JvmField
|
||||
val TUMBLESTONES = create("tumblestones")
|
||||
@JvmField
|
||||
val WATER_STONE_ORES = create("water_stone_ores")
|
||||
@JvmField
|
||||
val ZINC_INGREDIENTS = create("zinc_ingredients")
|
||||
|
||||
// Held Item Tags
|
||||
@JvmField val CONSUMED_IN_NPC_BATTLE = create("held/consumed_in_npc_battle")
|
||||
@JvmField val CONSUMED_IN_PVP_BATTLE = create("held/consumed_in_pvp_battle")
|
||||
@JvmField val CONSUMED_IN_WILD_BATTLE = create("held/consumed_in_wild_battle")
|
||||
@JvmField val DESTINY_KNOT = create("held/destiny_knot")
|
||||
@JvmField val EVERSTONE = create("held/everstone")
|
||||
@JvmField val EXPERIENCE_SHARE = create("held/experience_share")
|
||||
@JvmField val IS_FRIENDSHIP_BOOSTER = create("is_friendship_booster")
|
||||
@JvmField val ANY_HELD_ITEM = create("held/is_held_item")
|
||||
/** Tag that flags items as being able to "create" [CobblemonItems.LEFTOVERS]. */
|
||||
@JvmField val LEAVES_LEFTOVERS = create("held/leaves_leftovers")
|
||||
@JvmField val LUCKY_EGG = create("held/lucky_egg")
|
||||
@JvmField val POWER_ANKLET = create("held/power_anklet")
|
||||
@JvmField val POWER_BAND = create("held/power_band")
|
||||
@JvmField val POWER_BELT = create("held/power_belt")
|
||||
@JvmField val POWER_BRACER = create("held/power_bracer")
|
||||
@JvmField val POWER_LENS = create("held/power_lens")
|
||||
@JvmField val POWER_WEIGHT = create("held/power_weight")
|
||||
@JvmField val TERRAIN_SEEDS = create("held/terrain_seeds")
|
||||
@JvmField
|
||||
val ANY_HELD_ITEM = create("held/is_held_item")
|
||||
@JvmField
|
||||
val EXPERIENCE_SHARE = create("held/experience_share")
|
||||
@JvmField
|
||||
val LUCKY_EGG = create("held/lucky_egg")
|
||||
@JvmField
|
||||
val DESTINY_KNOT = create("held/destiny_knot")
|
||||
@JvmField
|
||||
val EVERSTONE = create("held/everstone")
|
||||
@JvmField
|
||||
val POWER_ANKLET = create("held/power_anklet")
|
||||
@JvmField
|
||||
val POWER_BAND = create("held/power_band")
|
||||
@JvmField
|
||||
val POWER_BELT = create("held/power_belt")
|
||||
@JvmField
|
||||
val POWER_BRACER = create("held/power_bracer")
|
||||
@JvmField
|
||||
val POWER_LENS = create("held/power_lens")
|
||||
@JvmField
|
||||
val POWER_WEIGHT = create("held/power_weight")
|
||||
@JvmField
|
||||
val CONSUMED_IN_NPC_BATTLE = create("held/consumed_in_npc_battle")
|
||||
@JvmField
|
||||
val CONSUMED_IN_PVP_BATTLE = create("held/consumed_in_pvp_battle")
|
||||
@JvmField
|
||||
val CONSUMED_IN_WILD_BATTLE = create("held/consumed_in_wild_battle")
|
||||
@JvmField
|
||||
val TERRAIN_SEEDS = create("held/terrain_seeds")
|
||||
|
||||
/**
|
||||
* Tag that flags items as being able to "create" [CobblemonItems.LEFTOVERS].
|
||||
*/
|
||||
@JvmField
|
||||
val LEAVES_LEFTOVERS = create("held/leaves_leftovers")
|
||||
|
||||
@JvmField
|
||||
val POTTERY_SHERDS = create("decorated_pot_sherds")
|
||||
|
||||
@JvmField
|
||||
val ABILITY_CHANGERS = create("ability_changers")
|
||||
|
||||
@JvmField
|
||||
val IS_FRIENDSHIP_BOOSTER = create("is_friendship_booster")
|
||||
|
||||
private fun create(path: String) = TagKey.create(Registries.ITEM, cobblemonResource(path))
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import net.minecraft.world.phys.Vec3
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Responsible for managing [BattleChallenge]s and initiating PVP [com.cobblemon.mod.common.api.battles.model.PokemonBattle]s.
|
||||
* Responsible for managing [BattleChallenge]s and initiating PVP [PokemonBattle]s.
|
||||
*
|
||||
* @author Segfault Guy, JazzMcNade
|
||||
* @since October 28th, 2024
|
||||
@@ -122,7 +122,7 @@ object ChallengeManager : RequestManager<ChallengeManager.BattleChallenge>() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun isValidInteraction(player: ServerPlayer, target: ServerPlayer) = player.canInteractWith(target, Cobblemon.config.battlePvPMaxDistance)
|
||||
override fun isValidInteraction(player: ServerPlayer, target: ServerPlayer) = player.canInteractWith(target, Cobblemon.config.BattlePvPMaxDistance)
|
||||
|
||||
override fun canAccept(request: BattleChallenge): Boolean {
|
||||
if (request is MultiBattleChallenge) {
|
||||
@@ -132,7 +132,7 @@ object ChallengeManager : RequestManager<ChallengeManager.BattleChallenge>() {
|
||||
if (existingReceiverTeam == null || existingSenderTeam == null) {
|
||||
request.notifySender(true, "error.missing_team")
|
||||
request.notifyReceiver(true, "error.missing_team")
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
val players = existingReceiverTeam.teamPlayers + existingSenderTeam.teamPlayers
|
||||
|
||||
@@ -54,7 +54,7 @@ object ShowdownInterpreter {
|
||||
}
|
||||
|
||||
listOf(
|
||||
"player", "teamsize", "gametype", "gen", "tier", "rated", "clearpoke", "poke", "teampreview", "start", "rule", "t:", "", "capture", "-anim"
|
||||
"player", "teamsize", "gametype", "gen", "tier", "rated", "clearpoke", "poke", "teampreview", "start", "rule", "t:", "", "capture"
|
||||
).forEach { updateInstructionParser[it] = { _, _, _, _ -> IgnoredInstruction() } }
|
||||
|
||||
updateInstructionParser["-ability"] = { _, instructionSet, message, _ -> AbilityInstruction(instructionSet, message) }
|
||||
|
||||
+1
-2
@@ -63,8 +63,7 @@ class ActivateInstruction(val instructionSet: InstructionSet, val message: Battl
|
||||
val context = ActionEffectContext(
|
||||
actionEffect = actionEffect,
|
||||
runtime = runtime,
|
||||
providers = providers,
|
||||
level = battle.players.firstOrNull()?.level()
|
||||
providers = providers
|
||||
)
|
||||
this.future = actionEffect.run(context)
|
||||
holds = context.holds // Reference so future things can check on this action effect's holds
|
||||
|
||||
+1
-2
@@ -56,8 +56,7 @@ class BoostInstruction(battle: PokemonBattle, val message: BattleMessage, val is
|
||||
val context = ActionEffectContext(
|
||||
actionEffect = actionEffect,
|
||||
runtime = runtime,
|
||||
providers = providers,
|
||||
level = battle.players.firstOrNull()?.level()
|
||||
providers = providers
|
||||
)
|
||||
this.future = actionEffect.run(context)
|
||||
holds = context.holds // Reference so future things can check on this action effect's holds
|
||||
|
||||
+1
-2
@@ -52,8 +52,7 @@ class CantInstruction(val message: BattleMessage): ActionEffectInstruction {
|
||||
val context = ActionEffectContext(
|
||||
actionEffect = actionEffect,
|
||||
runtime = runtime,
|
||||
providers = providers,
|
||||
level = battle.players.firstOrNull()?.level()
|
||||
providers = providers
|
||||
)
|
||||
this.future = actionEffect.run(context)
|
||||
holds = context.holds // Reference so future things can check on this action effect's holds
|
||||
|
||||
+1
-2
@@ -114,8 +114,7 @@ class DamageInstruction(
|
||||
val context = ActionEffectContext(
|
||||
actionEffect = actionEffect,
|
||||
runtime = runtime,
|
||||
providers = providers,
|
||||
level = battle.players.firstOrNull()?.level()
|
||||
providers = providers
|
||||
)
|
||||
this.future = actionEffect.run(context)
|
||||
holds = context.holds // Reference so future things can check on this action effect's holds
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user