mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-26 09:06:26 -04:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fead7cc367 | ||
|
|
622b06b68b | ||
|
|
af7645feb4 | ||
|
|
ccf7218cfc | ||
|
|
9b767f5170 | ||
|
|
fcb4861e94 | ||
|
|
aa8b0d3fbb | ||
|
|
d4fa5255ec | ||
|
|
4f3e874e70 | ||
|
|
6df0f17798 | ||
|
|
a9e3115b46 | ||
|
|
bef8e064f1 | ||
|
|
79873c44e7 | ||
|
|
d4abf9f2b5 | ||
|
|
fd8b6c50a5 | ||
|
|
2b872d85cf | ||
|
|
d98908b91d | ||
|
|
f592e6bc05 | ||
|
|
dad86f3692 | ||
|
|
817b55407c | ||
|
|
b2167a9902 | ||
|
|
d3f5ce42a8 | ||
|
|
0eababd67a | ||
|
|
103f65800f | ||
|
|
55925fc4a4 | ||
|
|
63d4176e86 | ||
|
|
4709d0f766 | ||
|
|
e1ef1d9bb0 | ||
|
|
5745b394b5 | ||
|
|
335f6f7104 | ||
|
|
2de001f61c | ||
|
|
9739ed917a | ||
|
|
e9e699c60b | ||
|
|
4dd78d5755 | ||
|
|
1e67385f15 | ||
|
|
f29a26869b | ||
|
|
aefdbfcce3 | ||
|
|
05bce3c058 | ||
|
|
8ba622a635 | ||
|
|
3b1e8f1624 | ||
|
|
eae49b0f7e | ||
|
|
9af141e9cd | ||
|
|
061a418c90 | ||
|
|
bb52d55c80 | ||
|
|
416affb1c3 | ||
|
|
7061d58333 | ||
|
|
b59aab557f | ||
|
|
1f98355bec | ||
|
|
ad6b63055c | ||
|
|
96611b04dc | ||
|
|
49d1015104 | ||
|
|
0eeb992724 | ||
|
|
9e9921098a | ||
|
|
0b23e68786 | ||
|
|
0ce309c37c | ||
|
|
75527fdf40 | ||
|
|
2389bdf25d | ||
|
|
24c9073c4c | ||
|
|
b33e2118b4 | ||
|
|
993ca68a5a | ||
|
|
f0d47055c4 | ||
|
|
bf331a7471 | ||
|
|
f74ba3dc77 | ||
|
|
063b627043 | ||
|
|
85335d14ed | ||
|
|
358b544583 | ||
|
|
ac945b4597 | ||
|
|
8733085232 | ||
|
|
cbc484a611 | ||
|
|
e5412a9c3b | ||
|
|
3ac325a22e | ||
|
|
6775e30f87 | ||
|
|
5d30990eb6 | ||
|
|
c8917ff02e | ||
|
|
de151442cd | ||
|
|
b09e553557 | ||
|
|
11e150e6aa | ||
|
|
85afe85150 | ||
|
|
4f73361565 | ||
|
|
34d2de0319 | ||
|
|
e8be1c9ccf | ||
|
|
9c36b9449c | ||
|
|
1a7695f844 | ||
|
|
134ebe1c2f | ||
|
|
923ef08db4 | ||
|
|
c962aceed2 | ||
|
|
ebeebeeee7 | ||
|
|
6d6867fb09 | ||
|
|
e98084343d | ||
|
|
19dad2daa7 | ||
|
|
f513475267 | ||
|
|
80fbf4a300 | ||
|
|
6904e302ff | ||
|
|
faf3858a5e | ||
|
|
501dd51e29 | ||
|
|
7b23ce055c | ||
|
|
ec8b9be4f6 | ||
|
|
e62e08aafb | ||
|
|
db6a60d3cb | ||
|
|
94ca3808ed | ||
|
|
9eec283036 | ||
|
|
3a0c801ffd | ||
|
|
ab795a4c6c | ||
|
|
0db41c1f9b | ||
|
|
2d315920f8 | ||
|
|
7449bc2377 | ||
|
|
15065e621f | ||
|
|
59fdd41c46 | ||
|
|
fa04e168ac | ||
|
|
94b28c025a | ||
|
|
6ed4938028 | ||
|
|
99d03b16b2 | ||
|
|
f70f7fe354 | ||
|
|
878c31fac7 | ||
|
|
9945143dd9 | ||
|
|
770d248b3a | ||
|
|
345dd60e11 | ||
|
|
7b48ddf418 | ||
|
|
e8ea697caa | ||
|
|
33021e2cb8 | ||
|
|
d577687a87 | ||
|
|
e603238339 | ||
|
|
a62f1fe560 | ||
|
|
96dd007db9 | ||
|
|
c339e36f9a | ||
|
|
2798487106 | ||
|
|
252139d07f | ||
|
|
e55c54fb24 | ||
|
|
74c4e2ae04 |
@@ -1,4 +1,97 @@
|
||||
# Changelog
|
||||
## [1.3.1 (March 31st, 2023)](#1-3-1)
|
||||
|
||||
### Additions
|
||||
- Added Slugma, Magcargo, Nosepass, and Probopass.
|
||||
- Elgyem family now drops Chorus Fruit, Geodude family now drops Black Augurite.
|
||||
- Added missing spawn files for Golett and Bergmite family.
|
||||
- Apricorns can now be smelted into dyes.
|
||||
- Added animations to Staryu line and Porygon line.
|
||||
- Added faint animations to Klink line.
|
||||
- Add lava surface spawn preset.
|
||||
- Added an ``any`` evolution requirement allowing you to define ``possibilities`` of other evolution requirements, for example, this allows you to create an evolution that requires the Pokémon to be shiny or a female.
|
||||
- Added the `/spawnpokemonfrompool [amount]` or `/forcespawn [amount]` command to spawn Pokémon(s) in the surrounding area using the natural spawn rates/pool of that area, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.spawnpokemon` if a permission mod is present. On a successful execution of the command, the amount of Pokémon spawned will be the output.
|
||||
- Added the `/pokebox` and `/pokeboxall` commands to move Pokemon(s) to the PC from a Player's party, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.pokebox` if a permission mod is present. On a successful execution of the command the output will be the number of pokemon moved to the Player's PC.
|
||||
- Added the `/pc` command which opens up the PC UI the same way interacting with the block would, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.pc` if a permission mod is present.
|
||||
|
||||
### Changes
|
||||
- You can now click the portraits of other Pokémon in the starter selection screen to navigate directly to them.
|
||||
- You can now click the right and left arrow keys to navigate PC boxes.
|
||||
- Link Cables will now require Pokémon to hold any held item normally required for their evolution.
|
||||
- After a battle, the last Pokémon used now becomes the selected one in your party.
|
||||
- The `/teach` command can now only allow the Pokémon to be given moves in their learnset, this can be controlled with the permission `cobblemon.command.teach.bypass`, to account for that change the base command now requires the permission `cobblemon.command.teach.base`, this change is meant only for people using a mod capable of providing permissions such as [LuckPerms](https://luckperms.net/).
|
||||
- Apricorns will no longer collide with their block form when picked, this should improve the experience in automatic farms.
|
||||
- Increased spawn chances for many Pokémon requiring specific blocks to be nearby.
|
||||
- Put Cryogonal in more snowy biomes.
|
||||
- Ditto as well as the Eevee, Gible, and Riolu families have been made more common.
|
||||
- Lowered spawn rate of Gyarados on the surface of water.
|
||||
- Apricorn leaves can now be used in the [Composter](https://minecraft.fandom.com/wiki/Composter) block, these have the same chance to raise the compost pile the Minecraft leaves do.
|
||||
- Updated Gengar's model and texture.
|
||||
- Updated Swinub line model and animations.
|
||||
- Tweaked portrait frames for the Pidgey line and for Walking Wake.
|
||||
- Changed all buff shoulder effects to only give a level 1 buff instead of level 2.
|
||||
- Made Weavile a little bigger.
|
||||
- Changed the recipes for Mystic Water, Miracle Seed, and Charcoal Stick to utilise the evolution stones, as well as Never-Melt Ice having an alternate recipe using the Ice Stone.
|
||||
- Replaced the `Failed to handle` battle messages to `Missing interpretation` to make it more clear that mechanics do work just still pending dedicated messages.
|
||||
|
||||
### Fixes
|
||||
- Fixed killing a Dodrio killing your game. Dodrio will never look the same to us.
|
||||
- Fixed non-Fire-type Pokémon being immune to lava.
|
||||
- Fixed custom Pokémon not being usable in battle, properly. A last minute fix caused this to break again; what are these devs not paid for?
|
||||
- Fixed being locked in an endless healing queue if you broke the healing machine during use.
|
||||
- Fixed an issue with the experience calculation when the Exp. Share is held.
|
||||
- Fixed Friendship-based attacks not using friendship values from your Pokémon.
|
||||
- Fixed Link Cables consuming held items they shouldn't due to not validating the held item of a Pokémon.
|
||||
- Fixed a crash when Aromatherapy cured the status of party members.
|
||||
- Fixed moves learnt on evolution not being given when said evolution happens. If you were affected by this issue your existing Pokémon will now be able to relearn those moves.
|
||||
- Fixed console spam when rendering Pokémon model items.
|
||||
- Fixed battle messages for 50+ moves and abilities and items.
|
||||
- Fixed the possible duplicate when capturing Pokémon (probably, this one's hard to reproduce to confirm it's fixed).
|
||||
- Previously duplicated Pokémon are cleaned from PCs and parties on restart.
|
||||
- Fixed an issue with some particle effects applying after a Pokémon has died or on top of the wrong Pokémon when using specific mods.
|
||||
- Fixed Pokémon not looking at each other in battle.
|
||||
- Fixed Experience Candy and Experience Share attempting to bring Pokémon above level cap causing crashes.
|
||||
- Fixed level 100 Pokémon having experience go over the cap total amount they should have.
|
||||
- Fixed `/pokemonspawnat` having the argument positions reverted making it impossible for Brigadier to understand when to suggest coordinates. It is now the intended `/spawnpokemonat <pos> <properties>`.
|
||||
- Fixed performance issues with shouldered Pokémon in certain systems.
|
||||
- Fixed learnset issues for Pokémon whose only modern debut was LGPE/BDSP/LA.
|
||||
- Fixed shiny Zubat, Grimer, Omanyte, Elgyem, Delphox and Aegislash displaying their normal texture.
|
||||
- Fixed sleeping in beds allowing fainted Pokémon to receive experience after a battle ends somehow.
|
||||
- Fixed an issue where a Pokémon will claim to have learnt a new move they already have in their moveset when learnt at an earlier level in their previous evolution. I realize that's confusing.
|
||||
- Fixed Dispensers not being able to shear Wooloo. This will also extend to other mods that check if an entity is valid to shear.
|
||||
- Fixed the currently held item of your Pokémon not dropping to the ground when removing it if your inventory was full.
|
||||
- Fixed creative mode allowing you to make your Pokémon hold more than 1 of the same item.
|
||||
- Fixed a Pokémon duplication glitch when teleporting between worlds.
|
||||
- Fixed dedicated servers being able to reload Cobblemon data with the vanilla `/reload` command causing unintended behavior for clients.
|
||||
- Fixed underground Pokémon spawning above ground.
|
||||
- Fixed Pokémon portrait not reverting back to the Pokémon after a failed capture during battle.
|
||||
- Fixed edge texture artifacts on pane elements for Tentacool and Tentacruel models.
|
||||
- Fixed crash caused by Pokémon pathing
|
||||
- Fixed Pokémon not returning to their balls when being healed in a healing machine
|
||||
- Fixed all Gen IX Pokémon as well as forms added in PLA and Wyrdeer, Kleavor, Ursaluna, Basculegion, Sneasler, Overqwil, and Enamorus having 0 exp yields.
|
||||
- Fixed Irons Leaves having bluetooth back legs. If you saw it, you know what I mean.
|
||||
- Fixed Golurk not having shoulder plates on its shoulders.
|
||||
- Fixed some water Pokémon walking onto land from the water even though they are fish.
|
||||
- Fixed Porygon2 and PorygonZ being too small.
|
||||
- Fixed Snivy line head look animation.
|
||||
- Fixed Staryu line not being able to swim.
|
||||
- Fixed an incompatibility with [Thorium](https://modrinth.com/mod/thorium) patch for [MC-84873](https://bugs.mojang.com/browse/MC-84873).
|
||||
- Fixed Pidgeotto wings when walking.
|
||||
- Fixed Delphox walk animation.
|
||||
- Fixed Froakie line sleep animations in battle.
|
||||
- Fixed Pokémon missing the non-level up moves they could relearn when rejoining a world until a new move was added to their relearn list.
|
||||
- Fixed instantly fleeing from Pokémon set to be unfleeable.
|
||||
- Fixed Pumpkaboo line forms not working. (Currently sizes aren't visual but check base stats to see which size you have.)
|
||||
- Fixed a bug that caused already interpreted messages for moves to be mistaken as uninterpreted.
|
||||
|
||||
### Developer
|
||||
- Add events that are fired just before and after a Pokémon is released (ReleasePokemonEvent.Pre and .Post)
|
||||
|
||||
### Localization
|
||||
- Added complete translations for Japanese, Thai, and Canadian French.
|
||||
- Added partial translations for Russian, Ukrainian, Mexican Spanish, and Korean.
|
||||
- Updated every existing language's translation.
|
||||
- All the translators that contributed are amazing.
|
||||
|
||||
## [1.3.0 - The Foundation Update (March 17th, 2023)](#1-3-0)
|
||||
|
||||
@@ -135,6 +228,7 @@
|
||||
- Fixed ambient sound file path for Porygon2.
|
||||
- Fixed forms not being able to unset the secondary type of a Pokémon in the stat JSON.
|
||||
- Fixed moves that haven't carried over from generation 8 onwards having the description they did in the generation 8 games instead of their last valid one.
|
||||
- Fixed shoulder mounted pokemon not returning to party on healer use and on evolution
|
||||
|
||||
### Developer
|
||||
- Reworked CatchRateModifier, as such, existing implementations need to be updated.
|
||||
|
||||
@@ -106,6 +106,7 @@ import com.cobblemon.mod.common.world.placement.CobblemonPlacementTypes
|
||||
import dev.architectury.event.EventResult
|
||||
import dev.architectury.event.events.common.CommandRegistrationEvent
|
||||
import dev.architectury.event.events.common.InteractionEvent
|
||||
import dev.architectury.event.events.common.PlayerEvent
|
||||
import dev.architectury.hooks.item.tool.AxeItemHooks
|
||||
import java.io.File
|
||||
import java.io.FileReader
|
||||
@@ -127,7 +128,7 @@ import org.apache.logging.log4j.LogManager
|
||||
|
||||
object Cobblemon {
|
||||
const val MODID = "cobblemon"
|
||||
const val VERSION = "1.3.0"
|
||||
const val VERSION = "1.3.1"
|
||||
const val CONFIG_PATH = "config/$MODID/main.json"
|
||||
val LOGGER = LogManager.getLogger()
|
||||
|
||||
@@ -212,6 +213,11 @@ object Cobblemon {
|
||||
}
|
||||
return@RightClickBlock EventResult.pass()
|
||||
})
|
||||
|
||||
PlayerEvent.CHANGE_DIMENSION.register(PlayerEvent.ChangeDimension{ player, _, _ ->
|
||||
player.party().forEach { pokemon -> pokemon.entity?.recallWithAnimation() }
|
||||
})
|
||||
|
||||
TrackedDataHandlerRegistry.register(Vec3DataSerializer)
|
||||
TrackedDataHandlerRegistry.register(StringSetDataSerializer)
|
||||
TrackedDataHandlerRegistry.register(PoseTypeDataSerializer)
|
||||
@@ -312,8 +318,6 @@ object Cobblemon {
|
||||
}
|
||||
|
||||
PokemonSpecies.observable.subscribe {
|
||||
ShowdownService.get().closeConnection()
|
||||
ShowdownService.get().openConnection()
|
||||
LOGGER.info("Starting dummy Showdown battle to force it to pre-load data.")
|
||||
battleRegistry.startBattle(
|
||||
BattleFormat.GEN_9_SINGLES,
|
||||
|
||||
@@ -35,5 +35,8 @@ object CobblemonCommands {
|
||||
FriendshipCommand.register(dispatcher)
|
||||
GiveAllPokemon.register(dispatcher)
|
||||
HeldItemCommand.register(dispatcher, registry)
|
||||
PcCommand.register(dispatcher)
|
||||
SpawnPokemonFromPool.register(dispatcher)
|
||||
PokeboxCommand.register(dispatcher)
|
||||
}
|
||||
}
|
||||
@@ -20,14 +20,22 @@ import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.registry.CompletableRegistry
|
||||
import dev.architectury.registry.registries.RegistrySupplier
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.item.AliasedBlockItem
|
||||
import net.minecraft.item.BlockItem
|
||||
import net.minecraft.item.Item
|
||||
import net.minecraft.item.ItemGroup
|
||||
import net.minecraft.block.ComposterBlock
|
||||
import net.minecraft.item.*
|
||||
import net.minecraft.util.registry.Registry
|
||||
|
||||
object CobblemonItems : CompletableRegistry<Item>(Registry.ITEM_KEY) {
|
||||
|
||||
init {
|
||||
this.completed.thenRun {
|
||||
val compostChance = ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE.getFloat(Items.OAK_LEAVES)
|
||||
// Should always pass unless Mojang reworks leaves to no longer work in the Composter, in that case we already updated w.o doing anything
|
||||
if (compostChance != ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE.defaultReturnValue()) {
|
||||
ComposterBlock.ITEM_TO_LEVEL_INCREASE_CHANCE[APRICORN_LEAVES.get()] = compostChance
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val pokeballs = mutableListOf<RegistrySupplier<PokeBallItem>>()
|
||||
|
||||
@JvmField
|
||||
|
||||
@@ -28,10 +28,8 @@ import com.cobblemon.mod.common.net.messages.client.battle.BattleSetTeamPokemonP
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleSwitchPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleUpdateTeamPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.ChallengeNotificationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.data.AbilityRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.data.MovesRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.data.*
|
||||
import com.cobblemon.mod.common.net.messages.client.data.PropertiesCompletionRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.data.SpeciesRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.*
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.AddEvolutionPacket
|
||||
@@ -189,6 +187,7 @@ object CobblemonNetwork {
|
||||
buildClientMessage<ServerSettingsPacket>()
|
||||
|
||||
// Data registries
|
||||
buildClientMessage<UnlockReloadPacket>()
|
||||
buildClientMessage<AbilityRegistrySyncPacket>()
|
||||
buildClientMessage<MovesRegistrySyncPacket>()
|
||||
buildClientMessage<SpeciesRegistrySyncPacket>()
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ class BattleMessage(rawMessage: String) {
|
||||
* @return A pair of [BattleActor] and [ActiveBattlePokemon] if the argument exists and successfully parses them otherwise null.
|
||||
*/
|
||||
fun actorAndActivePokemon(index: Int, battle: PokemonBattle): Pair<BattleActor, ActiveBattlePokemon>? {
|
||||
val pnx = this.argumentAt(index)?.substring(0, 3) ?: return null
|
||||
val pnx = this.argumentAt(index)?.takeIf { it.length >= 3 }?.substring(0, 3) ?: return null
|
||||
return this.actorAndActivePokemon(pnx, battle)
|
||||
}
|
||||
|
||||
|
||||
+20
-14
@@ -25,6 +25,7 @@ import com.cobblemon.mod.common.battles.BattleCaptureAction
|
||||
import com.cobblemon.mod.common.battles.BattleFormat
|
||||
import com.cobblemon.mod.common.battles.BattleRegistry
|
||||
import com.cobblemon.mod.common.battles.BattleSide
|
||||
import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
|
||||
import com.cobblemon.mod.common.battles.dispatch.BattleDispatch
|
||||
import com.cobblemon.mod.common.battles.dispatch.DispatchResult
|
||||
import com.cobblemon.mod.common.battles.dispatch.GO
|
||||
@@ -34,6 +35,8 @@ import com.cobblemon.mod.common.net.messages.client.battle.BattleEndPacket
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.DefeatEvolutionProgress
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.getPlayer
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import net.minecraft.text.Text
|
||||
@@ -191,7 +194,7 @@ open class PokemonBattle(
|
||||
}
|
||||
val experience = Cobblemon.experienceCalculator.calculate(opponentPokemon, faintedPokemon, multiplier)
|
||||
if (experience > 0) {
|
||||
opponent.awardExperience(opponentPokemon, (experience * Cobblemon.config.experienceMultiplier).toInt())
|
||||
opponent.awardExperience(opponentPokemon, experience)
|
||||
}
|
||||
Cobblemon.evYieldCalculator.calculate(opponentPokemon).forEach { (stat, amount) ->
|
||||
pokemon.evs.add(stat, amount)
|
||||
@@ -258,7 +261,7 @@ open class PokemonBattle(
|
||||
}
|
||||
}
|
||||
|
||||
fun dispatchWaiting(dispatcher: () -> Unit, delaySeconds: Float = 1F) {
|
||||
fun dispatchWaiting(delaySeconds: Float = 1F, dispatcher: () -> Unit) {
|
||||
dispatch {
|
||||
dispatcher()
|
||||
WaitDispatch(delaySeconds)
|
||||
@@ -306,15 +309,18 @@ open class PokemonBattle(
|
||||
.filterIsInstance<FleeableBattleActor>()
|
||||
.filter { it.getWorldAndPosition() != null }
|
||||
.none { pokemonActor ->
|
||||
val (world, pos) = pokemonActor.getWorldAndPosition()!!
|
||||
val nearestPlayerActorDistance = actors.asSequence()
|
||||
.filter { it.type == ActorType.PLAYER }
|
||||
.filterIsInstance<EntityBackedBattleActor<*>>()
|
||||
.mapNotNull { it.entity }
|
||||
.filter { it.world == world }
|
||||
.minOfOrNull { pos.distanceTo(it.pos) }
|
||||
if (pokemonActor.fleeDistance == -1F) true
|
||||
else {
|
||||
val (world, pos) = pokemonActor.getWorldAndPosition()!!
|
||||
val nearestPlayerActorDistance = actors.asSequence()
|
||||
.filter { it.type == ActorType.PLAYER }
|
||||
.filterIsInstance<EntityBackedBattleActor<*>>()
|
||||
.mapNotNull { it.entity }
|
||||
.filter { it.world == world }
|
||||
.minOfOrNull { pos.distanceTo(it.pos) }
|
||||
|
||||
nearestPlayerActorDistance != null && nearestPlayerActorDistance < pokemonActor.fleeDistance
|
||||
nearestPlayerActorDistance != null && nearestPlayerActorDistance < pokemonActor.fleeDistance
|
||||
}
|
||||
}
|
||||
|
||||
if (wildPokemonOutOfRange) {
|
||||
@@ -345,8 +351,8 @@ open class PokemonBattle(
|
||||
* @return The generated [Text] meant to notify the client.
|
||||
*/
|
||||
internal fun createUnimplemented(message: BattleMessage): Text {
|
||||
LOGGER.error("Failed to handle '{}' action {}", message.id, message.rawMessage)
|
||||
return Text.literal("Failed to handle '${message.id}' action ${message.rawMessage}").red()
|
||||
LOGGER.error("Missing interpretation on '{}' action {}", message.id, message.rawMessage)
|
||||
return Text.literal("Missing interpretation on '${message.id}' action ${message.rawMessage}").red()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -363,8 +369,8 @@ open class PokemonBattle(
|
||||
if (publicMessage.id != privateMessage.id) {
|
||||
throw IllegalArgumentException("Messages do not match")
|
||||
}
|
||||
LOGGER.error("Failed to handle '{}' action: \nPublic » {}\nPrivate » {}", publicMessage.id, publicMessage.rawMessage, privateMessage.rawMessage)
|
||||
return Text.literal("Failed to handle '${publicMessage.id}' action please report to the developers").red()
|
||||
LOGGER.error("Missing interpretation on '{}' action: \nPublic » {}\nPrivate » {}", publicMessage.id, publicMessage.rawMessage, privateMessage.rawMessage)
|
||||
return Text.literal("Missing interpretation on '${publicMessage.id}' action please report to the developers").red()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEv
|
||||
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionDisplayEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.interaction.ExperienceCandyUseEvent
|
||||
import com.cobblemon.mod.common.api.events.starter.StarterChosenEvent
|
||||
import com.cobblemon.mod.common.api.events.storage.ReleasePokemonEvent
|
||||
import com.cobblemon.mod.common.api.reactive.CancelableObservable
|
||||
import com.cobblemon.mod.common.api.reactive.EventObservable
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
@@ -92,6 +93,11 @@ object CobblemonEvents {
|
||||
@JvmField
|
||||
val EXPERIENCE_CANDY_USE_POST = EventObservable<ExperienceCandyUseEvent.Post>()
|
||||
|
||||
@JvmField
|
||||
val POKEMON_RELEASED_EVENT_PRE = CancelableObservable<ReleasePokemonEvent.Pre>()
|
||||
@JvmField
|
||||
val POKEMON_RELEASED_EVENT_POST = EventObservable<ReleasePokemonEvent.Post>()
|
||||
|
||||
@JvmField
|
||||
val LOOT_DROPPED = CancelableObservable<LootDroppedEvent>()
|
||||
@JvmField
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.storage
|
||||
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.storage.PokemonStore
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
|
||||
/**
|
||||
* The base of the events around the release of Pokémon from pc or party.
|
||||
* For the generic experience gain event see [CobblemonEvents.POKEMON_RELEASED_EVENT_PRE] and [CobblemonEvents.POKEMON_RELEASED_EVENT_POST]
|
||||
*
|
||||
* @author Polymeta
|
||||
* @since March 22nd, 2023
|
||||
*/
|
||||
interface ReleasePokemonEvent {
|
||||
|
||||
/**
|
||||
* The [ServerPlayerEntity] that is releasing the Pokémon.
|
||||
*/
|
||||
val player: ServerPlayerEntity
|
||||
|
||||
/**
|
||||
* The [Pokemon] being released.
|
||||
*/
|
||||
val pokemon: Pokemon
|
||||
|
||||
/**
|
||||
* The [PokemonStore] from which the Pokémon is being released from.
|
||||
*/
|
||||
val storage: PokemonStore<*>
|
||||
|
||||
/**
|
||||
* Fired when a player attempts to release a Pokémon from their pc or party.
|
||||
* Canceling this event will prevent the Pokémon from being released.
|
||||
* Users of this event are advised to send the player a message to let them know that they can't release that Pokémon and why.
|
||||
* For the event that is fired after all the calculations took place see [ReleasePokemonEvent.Post].
|
||||
*/
|
||||
class Pre(
|
||||
override val player: ServerPlayerEntity,
|
||||
override val pokemon: Pokemon,
|
||||
override val storage: PokemonStore<*>
|
||||
) : ReleasePokemonEvent, Cancelable()
|
||||
|
||||
/**
|
||||
* Fired after a player released a Pokémon from their pc or party.
|
||||
*/
|
||||
class Post(
|
||||
override val player: ServerPlayerEntity,
|
||||
override val pokemon: Pokemon,
|
||||
override val storage: PokemonStore<*>
|
||||
) : ReleasePokemonEvent
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import net.minecraft.text.MutableText
|
||||
* To build a Move you need to use its template
|
||||
*
|
||||
* @param name The name in Showdown ID form.
|
||||
* @param num The numerical ID of this move on Showdown.
|
||||
* @param elementalType The [ElementalType] of this move.
|
||||
* @param damageCategory The [DamageCategory] of this move.
|
||||
* @param power The base power of this move.
|
||||
@@ -34,6 +35,7 @@ import net.minecraft.text.MutableText
|
||||
*/
|
||||
open class MoveTemplate(
|
||||
val name: String,
|
||||
val num: Int,
|
||||
@SerializedName("type")
|
||||
val elementalType: ElementalType,
|
||||
val damageCategory: DamageCategory,
|
||||
@@ -45,8 +47,7 @@ open class MoveTemplate(
|
||||
val critRatio: Double,
|
||||
val effectChances: Array<Double>
|
||||
) {
|
||||
/** Don't change this from 0. It was -1, but then the data JSON reader was making this 0 instead of -1, ignoring our original video. */
|
||||
var id = 0
|
||||
|
||||
val displayName: MutableText
|
||||
get() = lang("move.$name")
|
||||
val description: MutableText
|
||||
@@ -55,6 +56,7 @@ open class MoveTemplate(
|
||||
get() = 8 * pp / 5
|
||||
class Dummy(name: String) : MoveTemplate(
|
||||
name = name,
|
||||
num = -1,
|
||||
elementalType = ElementalTypes.NORMAL,
|
||||
damageCategory = DamageCategories.STATUS,
|
||||
power = 0.0,
|
||||
|
||||
@@ -43,6 +43,7 @@ object Moves : DataRegistry {
|
||||
val jsMove = movesJson[i].asJsonObject
|
||||
val id = jsMove.get("id").asString
|
||||
try {
|
||||
val num = jsMove.get("num").asInt
|
||||
val elementalType = ElementalTypes.getOrException(jsMove.get("type").asString)
|
||||
val damageCategory = DamageCategories.getOrException(jsMove.get("category").asString)
|
||||
val power = jsMove.get("basePower").asDouble
|
||||
@@ -71,13 +72,12 @@ object Moves : DataRegistry {
|
||||
effectChances += secondaryMember.get("chance").asDouble
|
||||
}
|
||||
}
|
||||
val move = MoveTemplate(id, elementalType, damageCategory, power, target, accuracy, pp, priority, critRatio, effectChances.toTypedArray())
|
||||
val move = MoveTemplate(id, num, elementalType, damageCategory, power, target, accuracy, pp, priority, critRatio, effectChances.toTypedArray())
|
||||
this.register(move)
|
||||
} catch (e: Exception) {
|
||||
Cobblemon.LOGGER.error("Caught exception trying to resolve the move '{}'", id, e)
|
||||
}
|
||||
}
|
||||
this.applyIDs()
|
||||
Cobblemon.LOGGER.info("Loaded {} moves", this.allMoves.size)
|
||||
this.observable.emit(this)
|
||||
}
|
||||
@@ -87,7 +87,7 @@ object Moves : DataRegistry {
|
||||
}
|
||||
|
||||
fun getByName(name: String) = allMoves[name.lowercase()]
|
||||
fun getByNumericalId(id: Int) = idMapping[id]!!
|
||||
fun getByNumericalId(id: Int) = idMapping[id]
|
||||
fun getByNameOrDummy(name: String) = allMoves[name.lowercase()] ?: MoveTemplate.dummy(name.lowercase())
|
||||
fun getExceptional() = getByName("tackle") ?: allMoves.values.random()
|
||||
fun count() = allMoves.size
|
||||
@@ -95,24 +95,12 @@ object Moves : DataRegistry {
|
||||
fun all() = this.allMoves.values.toList()
|
||||
|
||||
internal fun receiveSyncPacket(moves: Collection<MoveTemplate>) {
|
||||
moves.forEach { move ->
|
||||
this.register(move)
|
||||
this.idMapping[move.id] = move
|
||||
}
|
||||
moves.forEach(this::register)
|
||||
}
|
||||
|
||||
private fun register(move: MoveTemplate) {
|
||||
this.allMoves[move.name] = move
|
||||
}
|
||||
|
||||
private fun applyIDs() {
|
||||
var id = 1
|
||||
this.allMoves.values
|
||||
.sortedBy { it.name }
|
||||
.forEach {
|
||||
it.id = id++
|
||||
idMapping[it.id] = it
|
||||
}
|
||||
this.idMapping[move.num] = move
|
||||
}
|
||||
|
||||
}
|
||||
+6
-1
@@ -46,12 +46,17 @@ object CobblemonPermissions {
|
||||
|
||||
val TAKE_POKEMON = this.create("${COMMAND_PREFIX}takepokemon", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
val TEACH = this.create("${COMMAND_PREFIX}teach", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
val TEACH = this.create("${COMMAND_PREFIX}teach.base", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
val TEACH_BYPASS_LEARNSET = this.create("${COMMAND_PREFIX}teach.bypass", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
val FRIENDSHIP = this.create("${COMMAND_PREFIX}friendship", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
val HELD_ITEM = this.create("${COMMAND_PREFIX}helditem", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
val PC = this.create("${COMMAND_PREFIX}pc", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
val POKEBOX = this.create("${COMMAND_PREFIX}pokebox", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
fun all(): Iterable<Permission> = this.permissions
|
||||
|
||||
private fun create(node: String, level: PermissionLevel): Permission {
|
||||
|
||||
+6
@@ -21,11 +21,17 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
fun interface PokemonPropertyExtractor {
|
||||
companion object {
|
||||
val SPECIES = PokemonPropertyExtractor { pokemon, properties -> properties.species = pokemon.species.resourceIdentifier.toString() }
|
||||
val FORM = PokemonPropertyExtractor { pokemon, properties -> properties.form = pokemon.form.formOnlyShowdownId() }
|
||||
val SHINY = PokemonPropertyExtractor { pokemon, properties -> properties.shiny = pokemon.shiny }
|
||||
val ASPECTS = PokemonPropertyExtractor { pokemon, properties -> properties.aspects = pokemon.aspects }
|
||||
val LEVEL = PokemonPropertyExtractor { pokemon, properties -> properties.level = pokemon.level }
|
||||
val GENDER = PokemonPropertyExtractor { pokemon, properties -> properties.gender = pokemon.gender }
|
||||
val FRIENDSHIP = PokemonPropertyExtractor { pokemon, properties -> properties.friendship = pokemon.friendship }
|
||||
val POKEBALL = PokemonPropertyExtractor { pokemon, properties -> properties.pokeball = pokemon.caughtBall.name.toString() }
|
||||
val NATURE = PokemonPropertyExtractor { pokemon, properties -> properties.nature = pokemon.nature.name.toString() }
|
||||
val ABILITY = PokemonPropertyExtractor { pokemon, properties -> properties.ability = pokemon.ability.name }
|
||||
|
||||
val ALL = arrayOf(SPECIES, FORM, SHINY, ASPECTS, LEVEL, GENDER, FRIENDSHIP, POKEBALL, NATURE, ABILITY)
|
||||
}
|
||||
|
||||
operator fun invoke(pokemon: Pokemon, properties: PokemonProperties)
|
||||
|
||||
@@ -112,6 +112,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
init {
|
||||
SpeciesAdditions.observable.subscribe {
|
||||
this.species.forEach(Species::initialize)
|
||||
this.species.forEach(Species::resolveEvolutionMoves)
|
||||
Cobblemon.showdownThread.queue { ShowdownService.get().registerSpecies() }
|
||||
// Reload this with the mod
|
||||
CobblemonEmptyHeldItemManager.load()
|
||||
@@ -204,7 +205,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
"H" to "No Ability",
|
||||
"S" to "No Ability"
|
||||
)
|
||||
val types = (form?.types ?: species.types).map { it.name }
|
||||
val types = (form?.types ?: species.types).map { it.name.replaceFirstChar(Char::uppercase) }
|
||||
val preevo: String? = (form?.preEvolution ?: species.preEvolution)?.let { if (it.form == it.species.standardForm) createShowdownName(it.species) else "${createShowdownName(it.species)}-${it.form.name}" }
|
||||
// For the context of battles the content here doesn't matter whatsoever and due to how PokemonProperties work we can't guarantee an actual specific species is defined.
|
||||
val evos = if ((form?.evolutions ?: species.evolutions).isEmpty()) emptyList() else arrayListOf("")
|
||||
|
||||
@@ -12,13 +12,16 @@ import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.abilities.AbilityPool
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEvent
|
||||
import com.cobblemon.mod.common.api.moves.BenchedMove
|
||||
import com.cobblemon.mod.common.api.moves.MoveTemplate
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.requirement.EvolutionRequirement
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.activestate.ShoulderedState
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.ItemInteractionEvolution
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.LevelUpEvolution
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.TradeEvolution
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.sound.SoundCategory
|
||||
|
||||
@@ -91,8 +94,20 @@ interface Evolution : EvolutionLike {
|
||||
* @param pokemon The [Pokemon] being evolved.
|
||||
*/
|
||||
fun forceEvolve(pokemon: Pokemon) {
|
||||
if (pokemon.state is ShoulderedState) {
|
||||
pokemon.tryRecallWithAnimation()
|
||||
}
|
||||
// ToDo Once implemented queue evolution for a pokemon state that is not in battle, start animation instead of instantly doing all of this
|
||||
this.result.apply(pokemon)
|
||||
this.learnableMoves.forEach { move ->
|
||||
if (pokemon.moveSet.hasSpace()) {
|
||||
pokemon.moveSet.add(move.create())
|
||||
}
|
||||
else {
|
||||
pokemon.benchedMoves.add(BenchedMove(move, 0))
|
||||
}
|
||||
pokemon.getOwnerPlayer()?.sendMessage(lang("experience.learned_move", pokemon.species.translatedName, 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 ->
|
||||
|
||||
+19
-15
@@ -9,10 +9,11 @@
|
||||
package com.cobblemon.mod.common.api.pokemon.experience
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.pokemon.evolution.requirements.LevelRequirement
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
fun interface ExperienceCalculator {
|
||||
fun calculate(battlePokemon: BattlePokemon, opponentPokemon: BattlePokemon, participationMultiplier: Double): Int
|
||||
@@ -20,22 +21,25 @@ fun interface ExperienceCalculator {
|
||||
|
||||
object StandardExperienceCalculator : ExperienceCalculator {
|
||||
override fun calculate(battlePokemon: BattlePokemon, opponentPokemon: BattlePokemon, participationMultiplier: Double): Int {
|
||||
val trainerMultiplier = if (opponentPokemon.effectedPokemon.isWild()) 1.0 else 1.5 /* Not used in modern formulas */
|
||||
val baseExp = opponentPokemon.originalPokemon.form.baseExperienceYield
|
||||
val opponentLevel = opponentPokemon.effectedPokemon.level
|
||||
val term1 = (baseExp * opponentLevel) / 5.0
|
||||
// This is meant to be a division but this is due to the intended behavior of handling the 2.0 sent over from Exp. All in modern Pokémon
|
||||
val term2 = 1 * participationMultiplier
|
||||
val victorPokemon = battlePokemon.effectedPokemon
|
||||
val victorLevel = victorPokemon.level
|
||||
val term3 = (((2.0 * opponentLevel) + 10) / (opponentLevel + victorLevel + 10)).pow(2.5)
|
||||
// ToDo when OT is implemented 1.5 if traded with someone from the same locale, 1.7 otherwise, 1.0 if OT
|
||||
val nonOtBonus = 1.0
|
||||
val luckyEggMultiplier = if (battlePokemon.effectedPokemon.heldItemNoCopy().isIn(CobblemonItemTags.LUCKY_EGG)) Cobblemon.config.luckyEggMultiplier else 1.0
|
||||
val evolutionMultiplier = if (battlePokemon.effectedPokemon.evolutionProxy.server().any { evolution ->
|
||||
val requirements = evolution.requirements.asSequence()
|
||||
requirements.any { it is LevelRequirement } && requirements.all { it.check(battlePokemon.effectedPokemon) }
|
||||
}) 1.2 else 1.0
|
||||
val affectionMultiplier = if (battlePokemon.effectedPokemon.friendship >= 220) 1.2 else 1.0
|
||||
val level = opponentPokemon.originalPokemon.level
|
||||
val levelVictor = battlePokemon.originalPokemon.level
|
||||
val pointPowerMultiplier = 1.0
|
||||
val originalTrainerMultiplier = 1.0
|
||||
val evolutionMultiplier =
|
||||
if (battlePokemon.effectedPokemon.evolutionProxy.server().any { evolution ->
|
||||
val requirements = evolution.requirements.asSequence()
|
||||
requirements.any { it is LevelRequirement } && requirements.all { it.check(battlePokemon.effectedPokemon) }
|
||||
}) 1.2 else 1.0
|
||||
val term1 = (baseExp * level * affectionMultiplier * evolutionMultiplier) / (5 * participationMultiplier)
|
||||
val term2 = ((2.0 * level + 10) / (level + levelVictor + 10)).pow(2.5)
|
||||
val term3 = originalTrainerMultiplier * luckyEggMultiplier * pointPowerMultiplier
|
||||
return (term1 * term2 * term3).toInt()
|
||||
// that's us!
|
||||
val gimmickBoost = Cobblemon.config.experienceMultiplier
|
||||
val term4 = term1 * term2 * term3 + 1
|
||||
return (term4 * nonOtBonus * luckyEggMultiplier * evolutionMultiplier * affectionMultiplier * gimmickBoost).roundToInt()
|
||||
}
|
||||
}
|
||||
@@ -79,6 +79,11 @@ open class Learnset : ClientDataSynchronizer<Learnset> {
|
||||
val eggMoves = mutableListOf<MoveTemplate>()
|
||||
val tutorMoves = mutableListOf<MoveTemplate>()
|
||||
val tmMoves = mutableListOf<MoveTemplate>()
|
||||
/**
|
||||
* Moves the species/form will have learnt when evolving into itself.
|
||||
* These are dynamically resolved each boot.
|
||||
*/
|
||||
val evolutionMoves = mutableSetOf<MoveTemplate>()
|
||||
val formChangeMoves = mutableListOf<MoveTemplate>()
|
||||
|
||||
fun getLevelUpMovesUpTo(level: Int) = levelUpMoves
|
||||
@@ -97,8 +102,7 @@ open class Learnset : ClientDataSynchronizer<Learnset> {
|
||||
val level = buffer.readSizedInt(IntSize.U_SHORT)
|
||||
val moves = mutableListOf<MoveTemplate>()
|
||||
repeat(times = buffer.readSizedInt(IntSize.U_BYTE)) {
|
||||
val move = Moves.getByNumericalId(buffer.readSizedInt(IntSize.U_SHORT))
|
||||
moves.add(move)
|
||||
Moves.getByNumericalId(buffer.readInt())?.let(moves::add)
|
||||
}
|
||||
levelUpMoves[level] = moves
|
||||
}
|
||||
@@ -110,7 +114,7 @@ open class Learnset : ClientDataSynchronizer<Learnset> {
|
||||
buffer.writeSizedInt(IntSize.U_SHORT, level)
|
||||
buffer.writeSizedInt(IntSize.U_BYTE, moves.size)
|
||||
for (move in moves) {
|
||||
buffer.writeSizedInt(IntSize.U_SHORT, move.id)
|
||||
buffer.writeInt(move.num)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,8 +46,9 @@ open class SpawnerManager {
|
||||
open fun onServerTick() {
|
||||
// Disables spawning
|
||||
if (!Cobblemon.config.enableSpawning) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
influences.removeIf { it.isExpired() }
|
||||
getSpawnersOfType<TickingSpawner>().forEach(TickingSpawner::tick)
|
||||
}
|
||||
}
|
||||
+3
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.spawning.influence
|
||||
|
||||
import com.cobblemon.mod.common.api.spawning.BestSpawner
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnBucket
|
||||
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
|
||||
import com.cobblemon.mod.common.api.spawning.detail.SpawnAction
|
||||
import com.cobblemon.mod.common.api.spawning.detail.SpawnDetail
|
||||
@@ -32,4 +33,6 @@ interface SpawningInfluence {
|
||||
fun affectAction(action: SpawnAction<*>) {}
|
||||
/** Applies some influence over the entity that's been spawned. */
|
||||
fun affectSpawn(entity: Entity) {}
|
||||
/** Applies some influence over the weight of spawn buckets. */
|
||||
fun affectBucketWeight(bucket: SpawnBucket, weight: Float): Float = weight
|
||||
}
|
||||
+7
-7
@@ -37,10 +37,10 @@ class BestSpawnerConfig {
|
||||
"surface" to 0.01F
|
||||
)
|
||||
val buckets = mutableListOf(
|
||||
SpawnBucket("common", 94.4F),
|
||||
SpawnBucket("common", 93.8F),
|
||||
SpawnBucket("uncommon", 5F),
|
||||
SpawnBucket("rare", 0.5F),
|
||||
SpawnBucket("ultra-rare", 0.1F)
|
||||
SpawnBucket("rare", 1.0F),
|
||||
SpawnBucket("ultra-rare", 0.2F)
|
||||
)
|
||||
|
||||
companion object {
|
||||
@@ -51,7 +51,7 @@ class BestSpawnerConfig {
|
||||
.disableHtmlEscaping()
|
||||
.create()
|
||||
|
||||
const val CONFIG_NAME = "best-spawner-config.json"
|
||||
const val CONFIG_NAME = "best-spawner-config"
|
||||
|
||||
fun load(): BestSpawnerConfig {
|
||||
val internal = loadInternal()
|
||||
@@ -74,7 +74,7 @@ class BestSpawnerConfig {
|
||||
}
|
||||
|
||||
private fun loadInternal(): BestSpawnerConfig {
|
||||
val reader = InputStreamReader(Cobblemon::class.java.getResourceAsStream("/assets/${Cobblemon.MODID}/spawning/$CONFIG_NAME")!!)
|
||||
val reader = InputStreamReader(Cobblemon::class.java.getResourceAsStream("/assets/${Cobblemon.MODID}/spawning/$CONFIG_NAME.json")!!)
|
||||
val config = GSON.fromJson(reader, BestSpawnerConfig::class.java)
|
||||
reader.close()
|
||||
return config
|
||||
@@ -99,7 +99,7 @@ class BestSpawnerConfig {
|
||||
}
|
||||
|
||||
fun saveExternal() {
|
||||
val stream = Cobblemon::class.java.getResourceAsStream("/assets/${Cobblemon.MODID}/spawning/$CONFIG_NAME")!!
|
||||
val stream = Cobblemon::class.java.getResourceAsStream("/assets/${Cobblemon.MODID}/spawning/$CONFIG_NAME.json")!!
|
||||
val bytes = stream.readAllBytes()
|
||||
stream.close()
|
||||
val configFile = File("config/${Cobblemon.MODID}/spawning/$CONFIG_NAME.json")
|
||||
@@ -110,4 +110,4 @@ class BestSpawnerConfig {
|
||||
outputStream.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ abstract class AreaSpawner(
|
||||
return true
|
||||
}
|
||||
|
||||
private fun constrainArea(area: SpawningArea): SpawningArea? {
|
||||
fun constrainArea(area: SpawningArea): SpawningArea? {
|
||||
val basePos = BlockPos.Mutable(area.baseX, area.baseY, area.baseZ)
|
||||
val originalY = area.baseY
|
||||
|
||||
|
||||
@@ -43,12 +43,24 @@ interface Spawner {
|
||||
fun copyInfluences() = influences.filter { !it.isExpired() }.toMutableList()
|
||||
fun chooseBucket(): SpawnBucket {
|
||||
val buckets = Cobblemon.bestSpawner.config.buckets
|
||||
val weightSum = buckets.sumOf { it.weight.toDouble() }.toFloat()
|
||||
val influences = this.copyInfluences()
|
||||
val weightMap = mutableMapOf<SpawnBucket, Float>()
|
||||
|
||||
for (bucket in buckets) {
|
||||
var weight = bucket.weight
|
||||
for (influence in influences) {
|
||||
weight = influence.affectBucketWeight(bucket, weight)
|
||||
}
|
||||
weightMap[bucket] = weight
|
||||
}
|
||||
|
||||
val weightSum = weightMap.values.sum()
|
||||
|
||||
// Make the 0 exclusive and the weightSum inclusive on the random
|
||||
val chosenSum = weightSum - Random().nextFloat(weightSum)
|
||||
var sum = 0F
|
||||
for (bucket in buckets) {
|
||||
sum += bucket.weight
|
||||
sum += weightMap[bucket]!!
|
||||
if (sum >= chosenSum) {
|
||||
return bucket
|
||||
}
|
||||
|
||||
+5
-1
@@ -72,6 +72,7 @@ abstract class TickingSpawner(
|
||||
val scheduledSpawn = scheduledSpawn
|
||||
if (scheduledSpawn != null) {
|
||||
performSpawn(scheduledSpawn)
|
||||
this.scheduledSpawn = null
|
||||
}
|
||||
|
||||
ticksUntilNextSpawn -= tickTimerMultiplier
|
||||
@@ -97,8 +98,11 @@ abstract class TickingSpawner(
|
||||
fun performSpawn(spawnAction: SpawnAction<*>) {
|
||||
spawnAction.entity.subscribe { afterSpawn(it) }
|
||||
spawnAction.run()
|
||||
this.scheduledSpawn = null
|
||||
}
|
||||
|
||||
open fun getCauseEntity(): Entity? = null
|
||||
|
||||
fun getAllInfluences() = this.influences + manager.influences
|
||||
|
||||
override fun copyInfluences() = this.getAllInfluences().toMutableList()
|
||||
}
|
||||
|
||||
@@ -87,8 +87,13 @@ open class PartyStore(override val uuid: UUID) : PokemonStore<PartyPosition>() {
|
||||
}
|
||||
|
||||
override fun getObservingPlayers() = getServer()?.playerManager?.playerList?.filter { it.uuid in observerUUIDs } ?: emptyList()
|
||||
|
||||
/** The total amount of slots in the party. */
|
||||
fun size() = slots.size
|
||||
|
||||
/** The amount of party slots that are occupied by a [Pokemon]. */
|
||||
fun occupied() = slots.filterNotNull().count()
|
||||
|
||||
override fun sendTo(player: ServerPlayerEntity) {
|
||||
player.sendPacket(InitializePartyPacket(false, uuid, slots.size))
|
||||
slots.forEachIndexed { index, pokemon ->
|
||||
@@ -162,6 +167,9 @@ open class PartyStore(override val uuid: UUID) : PokemonStore<PartyPosition>() {
|
||||
slots[slot] = Pokemon().loadFromNBT(pokemonNBT)
|
||||
}
|
||||
}
|
||||
|
||||
removeDuplicates()
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
@@ -186,9 +194,25 @@ open class PartyStore(override val uuid: UUID) : PokemonStore<PartyPosition>() {
|
||||
slots[slot] = Pokemon().loadFromJSON(json.get(key).asJsonObject)
|
||||
}
|
||||
}
|
||||
|
||||
removeDuplicates()
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
fun removeDuplicates() {
|
||||
val knownUUIDs = mutableListOf<UUID>()
|
||||
for (slot in 0 until this.slots.size) {
|
||||
val pokemon = get(slot) ?: continue
|
||||
if (pokemon.uuid !in knownUUIDs) {
|
||||
knownUUIDs.add(pokemon.uuid)
|
||||
} else {
|
||||
slots[slot] = null
|
||||
anyChangeObservable.emit(Unit)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun loadPositionFromNBT(nbt: NbtCompound): StoreCoordinates<PartyPosition> {
|
||||
val slot = nbt.getByte(DataKeys.STORE_SLOT).toInt()
|
||||
return StoreCoordinates(this, PartyPosition(slot))
|
||||
|
||||
@@ -62,6 +62,9 @@ open class PCBox(val pc: PCStore) : Iterable<Pokemon> {
|
||||
val boxNumber: Int
|
||||
get() = this.pc.boxes.indexOf(this)
|
||||
|
||||
val unoccupiedSlots: Int
|
||||
get() = POKEMON_PER_BOX - this.pokemon.filterNotNull().count()
|
||||
|
||||
fun getFirstAvailablePosition(): PCPosition? {
|
||||
for (index in 0 until POKEMON_PER_BOX) {
|
||||
if (this.pokemon[index] == null) {
|
||||
|
||||
@@ -144,9 +144,27 @@ open class PCStore(
|
||||
} else {
|
||||
tryRestoreBackedUpPokemon()
|
||||
}
|
||||
|
||||
removeDuplicates()
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
fun removeDuplicates() {
|
||||
val knownUUIDs = mutableListOf<UUID>()
|
||||
for (box in boxes) {
|
||||
for (i in 0 until POKEMON_PER_BOX) {
|
||||
val pokemon = box[i] ?: continue
|
||||
if (pokemon.uuid !in knownUUIDs) {
|
||||
knownUUIDs.add(pokemon.uuid)
|
||||
} else {
|
||||
box[i] = null
|
||||
pcChangeObservable.emit(Unit)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun saveToJSON(json: JsonObject): JsonObject {
|
||||
json.addProperty(DataKeys.STORE_BOX_COUNT, boxes.size.toShort())
|
||||
json.addProperty(DataKeys.STORE_BOX_COUNT_LOCKED, lockedSize)
|
||||
@@ -195,6 +213,9 @@ open class PCStore(
|
||||
} else {
|
||||
tryRestoreBackedUpPokemon()
|
||||
}
|
||||
|
||||
removeDuplicates()
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.storage.pc.link
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.permission.Permission
|
||||
import com.cobblemon.mod.common.api.storage.pc.PCStore
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
|
||||
/**
|
||||
* A [PCLink] tied to a player that must have a permission.
|
||||
*
|
||||
* @param pc The [PCStore] being opened.
|
||||
* @param player The [ServerPlayerEntity] opening the PC.
|
||||
* @param permission The [Permission] required for this link to work.
|
||||
*/
|
||||
class PermissiblePcLink(pc: PCStore, player: ServerPlayerEntity, private val permission: Permission) : PCLink(pc, player.uuid) {
|
||||
|
||||
override fun isPermitted(player: ServerPlayerEntity): Boolean {
|
||||
val result = Cobblemon.permissionValidator.hasPermission(player, this.permission)
|
||||
if (!result) {
|
||||
PCLinkManager.removeLink(player.uuid)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
@@ -68,7 +68,8 @@ data class BattleFormat(
|
||||
"mod": "$mod",
|
||||
"gameType": "${battleType.name}",
|
||||
"gen": $gen,
|
||||
"ruleset": [${ruleSet.joinToString { "\"$it\"" }}]
|
||||
"ruleset": [${ruleSet.joinToString { "\"$it\"" }}],
|
||||
"effectType": "Format"
|
||||
}
|
||||
""".trimIndent().replace("\n", "")
|
||||
}
|
||||
|
||||
@@ -43,6 +43,10 @@ object BattleRegistry {
|
||||
|
||||
/**
|
||||
* Packs a team into the showdown format
|
||||
*
|
||||
* Example from https://gitlab.com/cable-mc/cobblemon-showdown/-/blob/master/sim/TEAMS.md#packed-format
|
||||
* NICKNAME|SPECIES|ITEM|ABILITY|MOVES|NATURE|EVS|GENDER|IVS|SHINY|LEVEL|HAPPINESS,POKEBALL,HIDDENPOWERTYPE,GIGANTAMAX,DYNAMAXLEVEL,TERATYPE
|
||||
*
|
||||
* @return a string of the packed team
|
||||
*/
|
||||
fun List<BattlePokemon>.packTeam() : String {
|
||||
@@ -98,14 +102,22 @@ object BattleRegistry {
|
||||
packedTeamBuilder.append("${if (pk.shiny) "S" else ""}|")
|
||||
// Level
|
||||
packedTeamBuilder.append("${pk.level}|")
|
||||
|
||||
// Misc
|
||||
// Happiness
|
||||
packedTeamBuilder.append("${pk.friendship}|")
|
||||
packedTeamBuilder.append("${pk.friendship},")
|
||||
// Caught Ball
|
||||
// This is safe to do as all our pokeballs that have showdown item equivalents are the same IDs they use for the pokeball attribute
|
||||
val pokeball = pokemon.effectedPokemon.caughtBall.name.path.replace("_", "")
|
||||
packedTeamBuilder.append("$pokeball|")
|
||||
packedTeamBuilder.append("$pokeball,")
|
||||
// Hidden Power Type
|
||||
packedTeamBuilder.append("|")
|
||||
packedTeamBuilder.append(",")
|
||||
// Gigantamax
|
||||
packedTeamBuilder.append(",")
|
||||
// DynamaxLevel
|
||||
packedTeamBuilder.append(",")
|
||||
// Teratype
|
||||
packedTeamBuilder.append(",")
|
||||
|
||||
team.add(packedTeamBuilder.toString())
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.battles
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleMessage
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.Effect
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.EntityBackedBattleActor
|
||||
@@ -94,12 +95,18 @@ object ShowdownInterpreter {
|
||||
updateInstructions["|-fieldstart|"] = this::handleFieldStartInstructions
|
||||
updateInstructions["|-fieldend|"] = this::handleFieldEndInstructions
|
||||
updateInstructions["|-ability|"] = this::handleAbilityInstructions
|
||||
//To-Do updateInstructions["|-endability|"] = this::handleEndAbilityInstruction
|
||||
updateInstructions["|-nothing"] = { battle, _, _ ->
|
||||
battle.dispatchGo { battle.broadcastChatMessage(battleLang("nothing")) }
|
||||
}
|
||||
updateInstructions["|-clearallboost"] = { battle, _, _ ->
|
||||
battle.dispatchGo { battle.broadcastChatMessage(battleLang("clearallboost")) }
|
||||
}
|
||||
updateInstructions["|-singleturn|"] = this::handleSingleTurnInstruction
|
||||
updateInstructions["|-singlemove|"] = this::handleSingleMoveInstruction
|
||||
updateInstructions["|-prepare|"] = this::handlePrepareInstruction
|
||||
updateInstructions["|-swapboost"] = this::handleSwapBoostInstruction
|
||||
updateInstructions["|-swapsideconditions|"] = this::handleSilently
|
||||
updateInstructions["|-unboost|"] = { battle, line, remainingLines -> boostInstruction(battle, line, remainingLines, false) }
|
||||
updateInstructions["|-boost|"] = { battle, line, remainingLines -> boostInstruction(battle, line, remainingLines, true) }
|
||||
updateInstructions["|-setboost|"] = this::handleSetBoostInstruction
|
||||
@@ -554,49 +561,39 @@ object ShowdownInterpreter {
|
||||
}
|
||||
|
||||
// |move|p1a: Charizard|Tackle|p2a: Magikarp
|
||||
private fun handleMoveInstruction(battle: PokemonBattle, message: String, remainingLines: MutableList<String>) {
|
||||
battle.dispatch {
|
||||
val editMessaged = message.replace("|move|", "")
|
||||
this.lastMover[battle.battleId] = message
|
||||
val userPNX = editMessaged.split("|")[0].split(":")[0].trim()
|
||||
val (_, userPokemon) = battle.getActorAndActiveSlotFromPNX(userPNX)
|
||||
val moveName = editMessaged.split("|")[1].split("|")[0]
|
||||
.replace(" ", "")
|
||||
.lowercase()
|
||||
.replace("[^A-z0-9]".toRegex(), "")
|
||||
private fun handleMoveInstruction(battle: PokemonBattle, rawMessage: String, remainingLines: MutableList<String>) {
|
||||
battle.dispatchGo {
|
||||
this.lastMover[battle.battleId] = rawMessage
|
||||
val message = BattleMessage(rawMessage)
|
||||
|
||||
val userPokemon = message.actorAndActivePokemon(0, battle)?.second ?: return@dispatchGo
|
||||
val targetPokemon = message.actorAndActivePokemon(2, battle)?.second
|
||||
|
||||
val effect = message.effectAt(1) ?: return@dispatchGo
|
||||
val move = Moves.getByNameOrDummy(effect.id)
|
||||
|
||||
val moveTemplate = Moves.getByName(moveName) ?: return@dispatch GO.also { battle.broadcastChatMessage("UNRECOGNIZED MOVE: $moveName".text()) }
|
||||
val hasTarget = editMessaged.split("|").size == 3 && editMessaged.split("|")[2].isNotEmpty()
|
||||
val targetPokemon = if (hasTarget) {
|
||||
val targetPNX = editMessaged.split("|")[2].split(":")[0]
|
||||
battle.getActorAndActiveSlotFromPNX(targetPNX)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
userPokemon.battlePokemon?.effectedPokemon?.let { pokemon ->
|
||||
val progress = UseMoveEvolutionProgress()
|
||||
if (progress.shouldKeep(pokemon)) {
|
||||
val created = pokemon.evolutionProxy.current().progressFirstOrCreate({ it is UseMoveEvolutionProgress && it.currentProgress().move == moveTemplate }) { progress }
|
||||
val created = pokemon.evolutionProxy.current().progressFirstOrCreate({ it is UseMoveEvolutionProgress && it.currentProgress().move == move }) { progress }
|
||||
created.updateProgress(UseMoveEvolutionProgress.Progress(created.currentProgress().move, created.currentProgress().amount + 1))
|
||||
}
|
||||
}
|
||||
if (targetPokemon != null && targetPokemon.second != userPokemon) {
|
||||
val targetPNX = editMessaged.split("|")[2].split(":")[0]
|
||||
val (_, targetPokemon) = battle.getActorAndActiveSlotFromPNX(targetPNX)
|
||||
|
||||
if (targetPokemon != null && targetPokemon != userPokemon) {
|
||||
battle.broadcastChatMessage(battleLang(
|
||||
key = "used_move_on",
|
||||
userPokemon.battlePokemon?.getName() ?: "ERROR".red(),
|
||||
moveTemplate.displayName,
|
||||
move.displayName,
|
||||
targetPokemon.battlePokemon?.getName() ?: "ERROR".red()
|
||||
))
|
||||
} else {
|
||||
battle.broadcastChatMessage(battleLang(
|
||||
key = "used_move",
|
||||
userPokemon.battlePokemon?.getName() ?: "ERROR".red(),
|
||||
moveTemplate.displayName
|
||||
move.displayName
|
||||
))
|
||||
}
|
||||
GO
|
||||
}
|
||||
}
|
||||
|
||||
@@ -730,22 +727,20 @@ object ShowdownInterpreter {
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleCureStatusInstruction(battle: PokemonBattle, message: String, remainingLines: MutableList<String>) {
|
||||
battle.dispatch {
|
||||
val pnx = message.split("|-curestatus|")[1].substring(0, 3)
|
||||
val remaining = message.substringAfter("|-curestatus|")
|
||||
val (_, pokemon) = battle.getActorAndActiveSlotFromPNX(pnx)
|
||||
val status = Statuses.getStatus(remaining.split("|")[1])
|
||||
val battlePokemon = pokemon.battlePokemon ?: return@dispatch GO
|
||||
if (status is PersistentStatus) {
|
||||
battlePokemon.effectedPokemon.status = null
|
||||
battle.sendUpdate(BattlePersistentStatusPacket(pnx, null))
|
||||
private fun handleCureStatusInstruction(battle: PokemonBattle, rawMessage: String, remainingLines: MutableList<String>) {
|
||||
battle.dispatchWaiting {
|
||||
val message = BattleMessage(rawMessage)
|
||||
val pokemon = message.actorAndActivePokemon(0, battle)?.second?.battlePokemon ?: return@dispatchWaiting
|
||||
val status = message.argumentAt(1)?.let(Statuses::getStatus) ?: return@dispatchWaiting
|
||||
val effect = message.effect()
|
||||
val lang = when {
|
||||
effect?.type == Effect.Type.ABILITY -> battleLang("cure_status.ability.${effect.id}", pokemon.getName())
|
||||
// Lang related to move stuff is tied to the status as a generic message such as fire moves defrosting Pokémon
|
||||
effect?.type == Effect.Type.MOVE -> battleLang("cure_status.move.${status.name}", pokemon.getName(), Moves.getByNameOrDummy(effect.id).displayName)
|
||||
message.hasOptionalArgument("msg") -> status.removeMessage?.asTranslated(pokemon.getName()) ?: return@dispatchWaiting
|
||||
else -> return@dispatchWaiting
|
||||
}
|
||||
val showMessage = "[msg]" in remaining
|
||||
if (status != null && showMessage) {
|
||||
status.removeMessage?.let { battle.broadcastChatMessage(it.asTranslated(battlePokemon.getName())) }
|
||||
}
|
||||
WaitDispatch(1F)
|
||||
battle.broadcastChatMessage(lang)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -762,10 +757,63 @@ object ShowdownInterpreter {
|
||||
if (message.contains("move: Bide")){
|
||||
battle.broadcastChatMessage(battleLang("bide_start",pokemon.battlePokemon?.getName() ?: ""))
|
||||
}
|
||||
if (message.contains("move: Yawn")){
|
||||
battle.broadcastChatMessage(battleLang("yawn_start",pokemon.battlePokemon?.getName() ?: ""))
|
||||
}
|
||||
WaitDispatch(2F)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSingleTurnInstruction(battle: PokemonBattle, rawMessage: String, remainingLines: MutableList<String>) {
|
||||
battle.dispatchGo{
|
||||
val message = BattleMessage(rawMessage)
|
||||
val pokemon = message.actorAndActivePokemon(0, battle)?.second ?: return@dispatchGo
|
||||
val pokemonName = pokemon.battlePokemon?.getName() ?: return@dispatchGo
|
||||
val effect = message.effectAt(1) ?: return@dispatchGo
|
||||
val lang = when(effect.id) {
|
||||
"protect" -> battleLang("singleturn.protect", pokemonName)
|
||||
"endure" -> battleLang("singleturn.endure", pokemonName)
|
||||
"craftyshield" -> battleLang("singleturn.crafty_shield", pokemonName)
|
||||
"powder" -> battleLang("singleturn.powder", pokemonName)
|
||||
"followme" -> battleLang("singleturn.follow_me", pokemonName)
|
||||
"snatch" -> battleLang("singleturn.snatch", pokemonName)
|
||||
"quickguard" -> battleLang("singleturn.quick_guard", pokemonName)
|
||||
"wideguard" -> battleLang("singleturn.wide_guard", pokemonName)
|
||||
"roost" -> battleLang("singleturn.roost", pokemonName)
|
||||
"matblock" -> battleLang("singleturn.mat_block", pokemonName)
|
||||
"maxguard" -> battleLang("singleturn.max_guard", pokemonName)
|
||||
"instruct" -> battleLang("singleturn.instruct", pokemonName, message.actorAndActivePokemonFromOptional(battle)?.second?.battlePokemon?.getName() ?: return@dispatchGo)
|
||||
"focuspunch" -> battleLang("singleturn.focus_punch", pokemonName)
|
||||
"electrify" -> battleLang("singleturn.electrify", pokemonName)
|
||||
"beakblast" -> battleLang("singleturn.beak_blast", pokemonName)
|
||||
"helpinghand" -> battleLang("singleturn.helping_hand", pokemonName, message.actorAndActivePokemonFromOptional(battle)?.second?.battlePokemon?.getName() ?: return@dispatchGo)
|
||||
"magiccoat" -> battleLang("singleturn.magic_coat", pokemonName)
|
||||
"ragepowder" -> battleLang("singleturn.rage_powder", pokemonName)
|
||||
"shelltrap" -> battleLang("singleturn.shell_trap", pokemonName)
|
||||
"spotlight" -> battleLang("singleturn.spotlight", pokemonName)
|
||||
else -> battle.createUnimplemented(message)
|
||||
}
|
||||
battle.broadcastChatMessage(lang)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSingleMoveInstruction(battle: PokemonBattle, rawMessage: String, remainingLines: MutableList<String>) {
|
||||
battle.dispatchGo {
|
||||
val message = BattleMessage(rawMessage)
|
||||
val pokemon = message.actorAndActivePokemon(0, battle)?.second ?: return@dispatchGo
|
||||
val pokemonName = pokemon.battlePokemon?.getName() ?: return@dispatchGo
|
||||
val effect = message.effectAt(1) ?: return@dispatchGo
|
||||
val lang = when (effect.id) {
|
||||
"destinybond" -> battleLang("singlemove.destiny_bond", pokemonName)
|
||||
"glaiverush" -> battleLang("singlemove.glaive_rush", pokemonName)
|
||||
"grudge" -> battleLang("singlemove.grudge", pokemonName)
|
||||
"rage" -> battleLang("singlemove.rage", pokemonName)
|
||||
else -> battle.createUnimplemented(message)
|
||||
}
|
||||
battle.broadcastChatMessage(lang)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleActivateInstructions(battle: PokemonBattle, rawMessage: String, remainingLines: MutableList<String>){
|
||||
battle.dispatchGo{
|
||||
val message = BattleMessage(rawMessage)
|
||||
@@ -790,6 +838,11 @@ object ShowdownInterpreter {
|
||||
"aromatherapy" -> battleLang("activate.aromatherapy")
|
||||
"trapped" -> battleLang("activate.trapped")
|
||||
"quickclaw" -> battleLang("item.quick_claw.end", pokemonName)
|
||||
"bind" -> battleLang("activate.bind", pokemonName, message.actorAndActivePokemonFromOptional(battle)?.second?.battlePokemon?.getName() ?: return@dispatchGo)
|
||||
"courtchange" -> battleLang("activate.court_change", pokemonName)
|
||||
"guardsplit" -> battleLang("activate.guard_split", pokemonName)
|
||||
"spite" -> battleLang("activate.spite", pokemonName, message.argumentAt(2)!!, message.argumentAt(3)!!)
|
||||
"wrap" -> battleLang("activate.wrap", pokemonName, message.actorAndActivePokemonFromOptional(battle)?.second?.battlePokemon?.getName() ?: return@dispatchGo)
|
||||
else -> battle.createUnimplemented(message)
|
||||
}
|
||||
battle.broadcastChatMessage(lang)
|
||||
@@ -797,7 +850,7 @@ object ShowdownInterpreter {
|
||||
}
|
||||
|
||||
private fun handleFieldStartInstructions(battle: PokemonBattle, rawMessage: String, remainingLines: MutableList<String>){
|
||||
battle.dispatchWaiting({
|
||||
battle.dispatchWaiting {
|
||||
val message = BattleMessage(rawMessage)
|
||||
// Note persistent is a CAP ability only we can ignore the flag
|
||||
val lang: Text = when (message.argumentAt(0)) {
|
||||
@@ -818,11 +871,11 @@ object ShowdownInterpreter {
|
||||
else -> battle.createUnimplemented(message)
|
||||
}
|
||||
battle.broadcastChatMessage(lang)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleFieldEndInstructions(battle: PokemonBattle, rawMessage: String, remainingLines: MutableList<String>){
|
||||
battle.dispatchWaiting({
|
||||
battle.dispatchWaiting {
|
||||
val message = BattleMessage(rawMessage)
|
||||
// Note persistent is a CAP ability only we can ignore the flag
|
||||
val lang: Text = when (message.argumentAt(0)) {
|
||||
@@ -843,37 +896,97 @@ object ShowdownInterpreter {
|
||||
else -> battle.createUnimplemented(message)
|
||||
}
|
||||
battle.broadcastChatMessage(lang)
|
||||
})
|
||||
}
|
||||
|
||||
private fun handleAbilityInstructions(battle: PokemonBattle, message: String, remainingLines: MutableList<String>) {
|
||||
battle.dispatch {
|
||||
val editedMessage = message.split("|-ability|")[1]
|
||||
val pnx = editedMessage.substring(0, 3)
|
||||
val (_, pokemon) = battle.getActorAndActiveSlotFromPNX(pnx)
|
||||
val fromWhat = editedMessage.split("|")[1]
|
||||
when (fromWhat) {
|
||||
"Speed Boost" -> battle.broadcastChatMessage(battleLang("speed_boost_ability", pokemon.battlePokemon!!.getName()))
|
||||
else -> battle.broadcastChatMessage(editedMessage.text())
|
||||
}
|
||||
WaitDispatch(1F)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleEndInstruction(battle: PokemonBattle, message: String, remainingLines: MutableList<String>) {
|
||||
battle.dispatch {
|
||||
val editedMessage = message.split("|-end|")[1]
|
||||
val pnx = editedMessage.substring(0, 3)
|
||||
val (_, pokemon) = battle.getActorAndActiveSlotFromPNX(pnx)
|
||||
val fromWhat = editedMessage.split("|")[1]
|
||||
|
||||
when (fromWhat) {
|
||||
"confusion" -> battle.broadcastChatMessage(battleLang("confusion_snapped", pokemon.battlePokemon!!.getName()))
|
||||
"move: Bide" -> battle.broadcastChatMessage(battleLang("bide_end", pokemon.battlePokemon!!.getName()))
|
||||
else -> battle.broadcastChatMessage(editedMessage.text())
|
||||
private fun handleAbilityInstructions(battle: PokemonBattle, rawMessage: String, remainingLines: MutableList<String>) {
|
||||
battle.dispatchGo {
|
||||
val message = BattleMessage(rawMessage)
|
||||
val pokemon = message.actorAndActivePokemon(0, battle)?.second ?: return@dispatchGo
|
||||
val pokemonName = pokemon.battlePokemon?.getName() ?: return@dispatchGo
|
||||
val effect = message.effectAt(1) ?: return@dispatchGo
|
||||
//val abilityId = message.argumentAt(1) ?: return@dispatchWaiting
|
||||
//val effect = message.effect() ?: return@dispatchWaiting
|
||||
val feedback = when (effect.id) {
|
||||
"speedboost" -> battleLang("ability.speed_boost", pokemonName)
|
||||
"sturdy" -> battleLang("ability.sturdy", pokemonName)
|
||||
"intimidate" -> battleLang("ability.intimidate", pokemonName)
|
||||
"unnerve" -> battleLang("ability.unnerve", pokemonName)
|
||||
"anticipation" -> battleLang("ability.anticipation", pokemonName)
|
||||
"airlock" -> battleLang("ability.air_lock")
|
||||
"cloudnine" -> battleLang("ability.air_lock") //Cloud Nine shares the same text as Air Lock
|
||||
else -> battleLang("ability.generic", pokemonName, message.argumentAt(1)!!)
|
||||
}
|
||||
battle.broadcastChatMessage(feedback)
|
||||
}
|
||||
}
|
||||
|
||||
WaitDispatch(1F)
|
||||
private fun handlePrepareInstruction(battle: PokemonBattle, rawMessage: String, remainingLines: MutableList<String>) {
|
||||
battle.dispatchGo {
|
||||
val message = BattleMessage(rawMessage)
|
||||
val pokemon = message.actorAndActivePokemon(0, battle)?.second ?: return@dispatchGo
|
||||
val pokemonName = pokemon.battlePokemon?.getName() ?: return@dispatchGo
|
||||
val effect = message.effectAt(1) ?: return@dispatchGo
|
||||
//Prevents spam when the move Role Play is used
|
||||
val lang = when(effect.id) {
|
||||
"bounce" -> battleLang("prepare.bounce", pokemonName)
|
||||
"dig" -> battleLang("prepare.dig", pokemonName)
|
||||
"dive" -> battleLang("prepare.dive", pokemonName)
|
||||
"fly" -> battleLang("prepare.fly", pokemonName)
|
||||
"freezeshock" -> battleLang("prepare.freeze_shock", pokemonName)
|
||||
"geomancy" -> battleLang("prepare.geomancy", pokemonName)
|
||||
"iceburn" -> battleLang("prepare.ice_burn", pokemonName)
|
||||
"meteorbeam" -> battleLang("prepare.meteor_beam", pokemonName)
|
||||
"phantomforce" -> battleLang("prepare.phantom_force", pokemonName)
|
||||
"razorwind" -> battleLang("prepare.razor_wind", pokemonName)
|
||||
"shadowforce" -> battleLang("prepare.phantom_force", pokemonName) //Phantom Force and Shadow Force share the same text
|
||||
"skullbash" -> battleLang("prepare.skull_bash", pokemonName)
|
||||
"skyattack" -> battleLang("prepare.sky_attack", pokemonName)
|
||||
"skydrop" -> battleLang("prepare.sky_drop", pokemonName)
|
||||
"solarbeam" -> battleLang("prepare.solar_beam", pokemonName)
|
||||
"solarblade" -> battleLang("prepare.solar_beam", pokemonName) //Solar Beam and Solar Blade share the same text
|
||||
else -> battle.createUnimplemented(message)
|
||||
}
|
||||
battle.broadcastChatMessage(lang)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSwapBoostInstruction(battle: PokemonBattle, rawMessage: String, remainingLines: MutableList<String>) {
|
||||
battle.dispatchGo {
|
||||
val message = BattleMessage(rawMessage)
|
||||
val pokemon = message.actorAndActivePokemon(0, battle)?.second ?: return@dispatchGo
|
||||
val pokemonName = pokemon.battlePokemon?.getName() ?: return@dispatchGo
|
||||
val targetPokemonName = message.actorAndActivePokemonFromOptional(battle)?.second?.battlePokemon?.getName() ?: return@dispatchGo
|
||||
val effect = message.effectAt(1) ?: return@dispatchGo
|
||||
val lang = when(effect.id) {
|
||||
"guardswap" -> battleLang("swapboost.generic", pokemonName, targetPokemonName)
|
||||
"heartswap" -> battleLang("swapboost.generic", pokemonName, targetPokemonName)
|
||||
"powerswap" -> battleLang("swapboost.generic", pokemonName, targetPokemonName)
|
||||
else -> battle.createUnimplemented(message)
|
||||
}
|
||||
battle.broadcastChatMessage(lang)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleEndInstruction(battle: PokemonBattle, rawMessage: String, remainingLines: MutableList<String>) {
|
||||
battle.dispatchWaiting {
|
||||
val message = BattleMessage(rawMessage)
|
||||
val battlePokemon = message.actorAndActivePokemon(0, battle)?.second?.battlePokemon ?: return@dispatchWaiting
|
||||
val pokemonName = battlePokemon.getName()
|
||||
val effect = message.effectAt(1) ?: return@dispatchWaiting
|
||||
if (message.hasOptionalArgument("silent")) {
|
||||
LOGGER.debug("Received silent: {}", message.rawMessage)
|
||||
}
|
||||
else {
|
||||
val feedback = when (effect.id) {
|
||||
"confusion" -> battleLang("confusion_snapped", pokemonName)
|
||||
"bide" -> battleLang("bide_end", pokemonName)
|
||||
"bind" -> battleLang("end.bide", pokemonName)
|
||||
"wrap" -> battleLang("end.wrap", pokemonName)
|
||||
else -> battle.createUnimplemented(message)
|
||||
}
|
||||
battle.broadcastChatMessage(feedback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1018,6 +1131,11 @@ object ShowdownInterpreter {
|
||||
battle.dispatch {
|
||||
val newHealthRatio: Float
|
||||
val remainingHealth = newHealth.split("/")[0].toInt()
|
||||
|
||||
if (battleMessage.optionalArgument("from")?.equals("move: Wrap") == true) {
|
||||
battle.broadcastChatMessage(battleLang("hurt.wrap", activePokemon.battlePokemon?.getName()!!))
|
||||
}
|
||||
|
||||
if (newHealth == "0") {
|
||||
newHealthRatio = 0F
|
||||
battle.dispatch {
|
||||
@@ -1101,7 +1219,7 @@ object ShowdownInterpreter {
|
||||
}
|
||||
|
||||
private fun handleHealInstruction(battle: PokemonBattle, actor: BattleActor, rawPublic: String, rawPrivate: String) {
|
||||
battle.dispatchWaiting({
|
||||
battle.dispatchWaiting {
|
||||
val publicMessage = BattleMessage(rawPublic)
|
||||
val privateMessage = BattleMessage(rawPrivate)
|
||||
val pnx = privateMessage.argumentAt(0)?.substring(0, 3) ?: return@dispatchWaiting
|
||||
@@ -1136,6 +1254,7 @@ object ShowdownInterpreter {
|
||||
"ingrain" -> battleLang("heal.ingrain", battlePokemon.getName())
|
||||
"grassyterrain" -> battleLang("heal.grassy_terrain", battlePokemon.getName())
|
||||
"leftovers" -> battleLang("heal.leftovers", battlePokemon.getName())
|
||||
"raindish" -> battleLang("heal.rain_dish", battlePokemon.getName())
|
||||
else -> battle.createUnimplementedSplit(publicMessage, privateMessage)
|
||||
}
|
||||
}
|
||||
@@ -1154,11 +1273,11 @@ object ShowdownInterpreter {
|
||||
status.applyMessage.let { battle.broadcastChatMessage(it.asTranslated(battlePokemon.getName())) }
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSetHpInstructions(battle: PokemonBattle, actor: BattleActor, rawPublic: String, rawPrivate: String){
|
||||
battle.dispatchWaiting({
|
||||
battle.dispatchWaiting {
|
||||
val publicMessage = BattleMessage(rawPublic)
|
||||
val privateMessage = BattleMessage(rawPrivate)
|
||||
val pnx = privateMessage.argumentAt(0)?.substring(0, 3) ?: return@dispatchWaiting
|
||||
@@ -1177,7 +1296,13 @@ object ShowdownInterpreter {
|
||||
else -> battle.createUnimplemented(publicMessage)
|
||||
}
|
||||
battle.broadcastChatMessage(lang)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Used for things that are only meant for visual information we don't have
|
||||
private fun handleSilently(battle: PokemonBattle, baseMessage: String, remainingLines: MutableList<String>) {
|
||||
battle.dispatchGo { }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+4
-4
@@ -33,13 +33,14 @@ class GraalShowdownUnbundler {
|
||||
.create()
|
||||
|
||||
fun attemptUnbundle() {
|
||||
var showdownDir = File("showdown")
|
||||
val showdownDir = File("showdown")
|
||||
val metadata = loadShowdownMetadata()
|
||||
|
||||
// Check if showdown needs to be installed
|
||||
if (!showdownDir.exists() || Cobblemon.config.autoUpdateShowdown) {
|
||||
showdownDir.mkdirs()
|
||||
|
||||
val showdownZip = File(showdownDir, "showdown.zip")
|
||||
showdownZip.mkdirs()
|
||||
val showdownMetadataFile = File(showdownDir, "showdown.json")
|
||||
|
||||
var extract = true
|
||||
@@ -56,12 +57,11 @@ class GraalShowdownUnbundler {
|
||||
backupDir.deleteRecursively()
|
||||
}
|
||||
|
||||
showdownDir.copyTo(File("showdown-backup"))
|
||||
showdownDir.copyTo(backupDir)
|
||||
}
|
||||
}
|
||||
|
||||
if (extract) {
|
||||
showdownDir = showdownZip.parentFile
|
||||
Identifier(Cobblemon.MODID, "showdown.zip").extractTo(showdownZip)
|
||||
Identifier(Cobblemon.MODID, "showdown.json").extractTo(showdownMetadataFile)
|
||||
FileUtils.unzipFile(showdownZip.toPath(), showdownDir.toPath())
|
||||
|
||||
@@ -12,9 +12,11 @@ import com.cobblemon.mod.common.api.apricorn.Apricorn
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.farming.ApricornHarvestEvent
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonBlockTags
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.util.playSoundServer
|
||||
import com.cobblemon.mod.common.util.toVec3d
|
||||
import net.minecraft.block.*
|
||||
import net.minecraft.entity.ItemEntity
|
||||
import net.minecraft.entity.ai.pathing.NavigationType
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.item.ItemPlacementContext
|
||||
@@ -79,6 +81,14 @@ class ApricornBlock(settings: Settings, val apricorn: Apricorn) : HorizontalFaci
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun getCollisionShape(state: BlockState, world: BlockView, pos: BlockPos, context: ShapeContext): VoxelShape {
|
||||
if (context is EntityShapeContext && (context.entity as? ItemEntity)?.stack?.isIn(CobblemonItemTags.APRICORNS) == true) {
|
||||
return VoxelShapes.empty()
|
||||
}
|
||||
return super.getCollisionShape(state, world, pos, context)
|
||||
}
|
||||
|
||||
override fun getPlacementState(ctx: ItemPlacementContext): BlockState? {
|
||||
var blockState = defaultState
|
||||
val worldView = ctx.world
|
||||
|
||||
@@ -149,7 +149,7 @@ class HealingMachineBlock(properties: Settings) : BlockWithEntity(properties) {
|
||||
return ActionResult.SUCCESS
|
||||
}
|
||||
|
||||
if (player.uuid in HealingMachineBlockEntity.alreadyHealing) {
|
||||
if (HealingMachineBlockEntity.isUsingHealer(player)) {
|
||||
player.sendMessage(lang("healingmachine.alreadyhealing").red())
|
||||
return ActionResult.SUCCESS
|
||||
}
|
||||
@@ -161,6 +161,7 @@ class HealingMachineBlock(properties: Settings) : BlockWithEntity(properties) {
|
||||
val neededCharge = player.party().getHealingRemainderPercent() - blockEntity.healingCharge
|
||||
player.sendMessage(lang("healingmachine.notenoughcharge", "${((neededCharge/party.count())*100f).toInt()}%").red())
|
||||
}
|
||||
party.forEach { it.tryRecallWithAnimation() }
|
||||
return ActionResult.CONSUME
|
||||
}
|
||||
|
||||
@@ -176,6 +177,14 @@ class HealingMachineBlock(properties: Settings) : BlockWithEntity(properties) {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBreak(world: World, pos: BlockPos, state: BlockState, player: PlayerEntity) {
|
||||
val blockEntity = world.getBlockEntity(pos)
|
||||
if (blockEntity is HealingMachineBlockEntity) {
|
||||
blockEntity.clearData()
|
||||
}
|
||||
super.onBreak(world, pos, state, player)
|
||||
}
|
||||
|
||||
override fun randomDisplayTick(state: BlockState, world: World, pos: BlockPos, random: Random) {
|
||||
val blockEntity = world.getBlockEntity(pos)
|
||||
if (blockEntity !is HealingMachineBlockEntity) return
|
||||
@@ -205,4 +214,4 @@ class HealingMachineBlock(properties: Settings) : BlockWithEntity(properties) {
|
||||
tooltip.add("block.${Cobblemon.MODID}.healing_machine.tooltip1".asTranslated().gray())
|
||||
tooltip.add("block.${Cobblemon.MODID}.healing_machine.tooltip2".asTranslated().gray())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-3
@@ -20,6 +20,7 @@ import java.util.UUID
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.entity.BlockEntity
|
||||
import net.minecraft.block.entity.BlockEntityTicker
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.nbt.NbtCompound
|
||||
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
@@ -90,14 +91,14 @@ class HealingMachineBlockEntity(
|
||||
val player = this.currentUser?.getPlayer() ?: return clearData()
|
||||
val party = player.party()
|
||||
|
||||
alreadyHealing.remove(player.uuid)
|
||||
party.heal()
|
||||
player.sendMessage(lang("healingmachine.healed").green())
|
||||
updateBlockChargeLevel()
|
||||
clearData()
|
||||
}
|
||||
|
||||
private fun clearData() {
|
||||
internal fun clearData() {
|
||||
this.currentUser?.let(alreadyHealing::remove)
|
||||
this.currentUser = null
|
||||
this.pokeBalls.clear()
|
||||
this.healTimeLeft = 0
|
||||
@@ -198,7 +199,7 @@ class HealingMachineBlockEntity(
|
||||
}
|
||||
|
||||
companion object {
|
||||
val alreadyHealing = mutableListOf<UUID>()
|
||||
private val alreadyHealing = hashSetOf<UUID>()
|
||||
const val MAX_REDSTONE_SIGNAL = 10
|
||||
|
||||
internal val TICKER = BlockEntityTicker<HealingMachineBlockEntity> { world, _, _, blockEntity ->
|
||||
@@ -222,5 +223,8 @@ class HealingMachineBlockEntity(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun isUsingHealer(player: PlayerEntity) = this.alreadyHealing.contains(player.uuid)
|
||||
|
||||
}
|
||||
}
|
||||
+5
@@ -28,4 +28,9 @@ class EmptyPokeBallClientDelegate : PokeBallPoseableState(), EntitySideDelegate<
|
||||
}
|
||||
entity.shakeEmitter.subscribe { shakeEmitter.emit(Unit) }
|
||||
}
|
||||
|
||||
override fun tick(entity: EmptyPokeBallEntity) {
|
||||
super.tick(entity)
|
||||
updateLocatorPosition(entity.pos)
|
||||
}
|
||||
}
|
||||
+5
-7
@@ -113,13 +113,7 @@ class PokemonClientDelegate : PoseableEntityState<PokemonEntity>(), PokemonSideD
|
||||
}
|
||||
}
|
||||
|
||||
val model = currentModel
|
||||
if (model != null) {
|
||||
val curState = model.currentState
|
||||
model.currentState = this
|
||||
model.updateLocators()
|
||||
model.currentState = curState
|
||||
}
|
||||
updateLocatorPosition(entity.pos)
|
||||
|
||||
previousVerticalVelocity = entity.velocity.y.toFloat()
|
||||
}
|
||||
@@ -135,4 +129,8 @@ class PokemonClientDelegate : PoseableEntityState<PokemonEntity>(), PokemonSideD
|
||||
statefulAnimations.add(animation)
|
||||
}
|
||||
}
|
||||
|
||||
override fun updatePostDeath() {
|
||||
++entity.deathTime
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.client.gui.screen.Screen
|
||||
import net.minecraft.client.sound.PositionedSoundInstance
|
||||
import net.minecraft.client.util.InputUtil
|
||||
import net.minecraft.client.util.math.MatrixStack
|
||||
import net.minecraft.sound.SoundEvent
|
||||
import net.minecraft.text.Text
|
||||
@@ -408,9 +409,19 @@ class PCGUI(
|
||||
}
|
||||
|
||||
override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
|
||||
if (keyCode == 256) {
|
||||
playSound(CobblemonSounds.PC_OFF.get())
|
||||
UnlinkPlayerFromPCPacket().sendToServer()
|
||||
when (keyCode) {
|
||||
InputUtil.GLFW_KEY_ESCAPE -> {
|
||||
playSound(CobblemonSounds.PC_OFF.get())
|
||||
UnlinkPlayerFromPCPacket().sendToServer()
|
||||
}
|
||||
InputUtil.GLFW_KEY_RIGHT -> {
|
||||
playSound(CobblemonSounds.GUI_CLICK.get())
|
||||
this.storageWidget.box += 1
|
||||
}
|
||||
InputUtil.GLFW_KEY_LEFT -> {
|
||||
playSound(CobblemonSounds.GUI_CLICK.get())
|
||||
this.storageWidget.box -= 1
|
||||
}
|
||||
}
|
||||
return super.keyPressed(keyCode, scanCode, modifiers)
|
||||
}
|
||||
|
||||
+4
-2
@@ -157,13 +157,15 @@ class StarterSelectionScreen private constructor(): Screen("cobblemon.ui.starter
|
||||
starterRoundaboutLeft = StarterRoundabout(
|
||||
pX = x + 89, pY = height / 2 + 84,
|
||||
pWidth = StarterRoundabout.MODEL_WIDTH, pHeight = StarterRoundabout.MODEL_HEIGHT,
|
||||
pokemon = currentCategory.pokemon[leftOfCurrentSelection()]
|
||||
pokemon = currentCategory.pokemon[leftOfCurrentSelection()],
|
||||
clickAction = { _, _ -> this.left() }
|
||||
)
|
||||
|
||||
starterRoundaboutRight = StarterRoundabout(
|
||||
pX = x + 149, pY = height / 2 + 84,
|
||||
pWidth = StarterRoundabout.MODEL_WIDTH, pHeight = StarterRoundabout.MODEL_HEIGHT,
|
||||
pokemon = currentCategory.pokemon[rightOfCurrentSelection()]
|
||||
pokemon = currentCategory.pokemon[rightOfCurrentSelection()],
|
||||
clickAction = { _, _ -> this.right() }
|
||||
)
|
||||
|
||||
addDrawableChild(starterRoundaboutLeft)
|
||||
|
||||
+21
-1
@@ -29,7 +29,8 @@ import net.minecraft.util.math.Vec3f
|
||||
class StarterRoundabout(
|
||||
pX: Int, pY: Int,
|
||||
pWidth: Int, pHeight: Int,
|
||||
var pokemon: RenderablePokemon
|
||||
var pokemon: RenderablePokemon,
|
||||
private val clickAction: (mouseX: Double, mouseY: Double) -> Unit = { _, _ -> }
|
||||
): SoundlessWidget(pX, pY, pWidth, pHeight, Text.literal("StarterRoundabout")) {
|
||||
|
||||
companion object {
|
||||
@@ -44,6 +45,10 @@ class StarterRoundabout(
|
||||
}
|
||||
|
||||
override fun render(matrices: MatrixStack, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
if (!this.visible) {
|
||||
return
|
||||
}
|
||||
this.hovered = mouseX >= this.x && mouseX < this.x + this.width && mouseY >= (this.y - MODEL_HEIGHT) && mouseY < this.y
|
||||
matrices.push()
|
||||
/*
|
||||
* This correction term is due to where scaling comes from in a render. We are giving the drawProfilePokemon
|
||||
@@ -76,4 +81,19 @@ class StarterRoundabout(
|
||||
|
||||
matrices.pop()
|
||||
}
|
||||
|
||||
override fun mouseClicked(pMouseX: Double, pMouseY: Double, pButton: Int): Boolean {
|
||||
if (this.clicked(pMouseX, pMouseY) && this.isValidClickButton(pButton)) {
|
||||
this.onClick(pMouseX, pMouseY)
|
||||
}
|
||||
return super.mouseClicked(pMouseX, pMouseY, pButton)
|
||||
}
|
||||
|
||||
override fun clicked(mouseX: Double, mouseY: Double): Boolean {
|
||||
return this.active && this.visible && this.hovered
|
||||
}
|
||||
|
||||
override fun onClick(mouseX: Double, mouseY: Double) {
|
||||
this.clickAction(mouseX, mouseY)
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import com.cobblemon.mod.common.client.net.battle.BattleSwitchPokemonHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.BattleUpdateTeamPokemonHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.ChallengeNotificationHandler
|
||||
import com.cobblemon.mod.common.client.net.data.DataRegistrySyncPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.data.UnlockReloadPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormParticleHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.InteractPokemonUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.SummaryUIPacketHandler
|
||||
@@ -141,6 +142,7 @@ object ClientPacketRegistrar : SidedPacketRegistrar() {
|
||||
|
||||
|
||||
// Data registries
|
||||
registerHandler(UnlockReloadPacketHandler)
|
||||
registerHandler(DataRegistrySyncPacketHandler<AbilityTemplate, AbilityRegistrySyncPacket>())
|
||||
registerHandler(DataRegistrySyncPacketHandler<MoveTemplate, MovesRegistrySyncPacket>())
|
||||
registerHandler(DataRegistrySyncPacketHandler<Species, SpeciesRegistrySyncPacket>())
|
||||
|
||||
+1
@@ -24,5 +24,6 @@ object BattleCaptureEndHandler : ClientPacketHandler<BattleCaptureEndPacket> {
|
||||
} else {
|
||||
activeBattlePokemon.ballCapturing?.finish()
|
||||
}
|
||||
activeBattlePokemon.ballCapturing = null
|
||||
}
|
||||
}
|
||||
+2
@@ -46,5 +46,7 @@ object BattleSwitchPokemonHandler : ClientPacketHandler<BattleSwitchPokemonPacke
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
CobblemonClient.storage.switchToPokemon(packet.newPokemon.uuid)
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.net.data
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork
|
||||
import com.cobblemon.mod.common.data.CobblemonDataProvider
|
||||
import com.cobblemon.mod.common.net.PacketHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.data.UnlockReloadPacket
|
||||
|
||||
internal object UnlockReloadPacketHandler : PacketHandler<UnlockReloadPacket> {
|
||||
override fun invoke(packet: UnlockReloadPacket, ctx: CobblemonNetwork.NetworkContext) {
|
||||
CobblemonDataProvider.canReload = true
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -25,7 +25,7 @@ object SpawnSnowstormParticleHandler : ClientPacketHandler<SpawnSnowstormParticl
|
||||
matrix.translate(packet.position.x, packet.position.y, packet.position.z)
|
||||
matrix.multiply(POSITIVE_Y.getDegreesQuaternion(packet.yawDegrees))
|
||||
matrix.multiply(POSITIVE_X.getDegreesQuaternion(packet.pitchDegrees))
|
||||
wrapper.update(matrix.peek().positionMatrix)
|
||||
wrapper.updateMatrix(matrix.peek().positionMatrix)
|
||||
val world = MinecraftClient.getInstance().world ?: return
|
||||
ParticleStorm(packet.effect, wrapper, world).spawn()
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ class ParticleStorm(
|
||||
val sourceAlive: () -> Boolean = { true },
|
||||
val sourceVisible: () -> Boolean = { true },
|
||||
val runtime: MoLangRuntime = MoLangRuntime()
|
||||
): NoRenderParticle(world, matrixWrapper.matrix.getOrigin().x, matrixWrapper.matrix.getOrigin().y, matrixWrapper.matrix.getOrigin().z) {
|
||||
): NoRenderParticle(world, matrixWrapper.getOrigin().x, matrixWrapper.getOrigin().y, matrixWrapper.getOrigin().z) {
|
||||
fun spawn() {
|
||||
MinecraftClient.getInstance().particleManager.addParticle(this)
|
||||
}
|
||||
@@ -85,7 +85,7 @@ class ParticleStorm(
|
||||
return
|
||||
}
|
||||
|
||||
val pos = matrixWrapper.matrix.getOrigin()
|
||||
val pos = matrixWrapper.getOrigin()
|
||||
prevPosX = x
|
||||
prevPosY = y
|
||||
prevPosZ = z
|
||||
@@ -134,6 +134,6 @@ class ParticleStorm(
|
||||
contextStorm = null
|
||||
}
|
||||
|
||||
fun transformPosition(position: Vec3d): Vec3d = matrixWrapper.matrix.transformPosition(position)
|
||||
fun transformPosition(position: Vec3d): Vec3d = matrixWrapper.transformPosition(position)
|
||||
fun transformDirection(direction: Vec3d): Vec3d = matrixWrapper.matrix.transformDirection(direction)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,10 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render
|
||||
|
||||
import com.cobblemon.mod.common.util.math.geometry.getOrigin
|
||||
import com.cobblemon.mod.common.util.math.geometry.transformPosition
|
||||
import net.minecraft.util.math.Matrix4f
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
/**
|
||||
* Holds onto a space matrix for quick access, exposes the matrix to mutation.
|
||||
@@ -17,10 +20,17 @@ import net.minecraft.util.math.Matrix4f
|
||||
* @since February 10th, 2023
|
||||
*/
|
||||
class MatrixWrapper {
|
||||
var position: Vec3d = Vec3d.ZERO
|
||||
var matrix: Matrix4f = Matrix4f()
|
||||
|
||||
fun update(rotationMatrix: Matrix4f): MatrixWrapper {
|
||||
fun updateMatrix(rotationMatrix: Matrix4f) = apply {
|
||||
this.matrix = rotationMatrix.copy()
|
||||
return this
|
||||
}
|
||||
|
||||
fun updatePosition(position: Vec3d) = apply {
|
||||
this.position = position
|
||||
}
|
||||
|
||||
fun getOrigin() = position.add(matrix.getOrigin())
|
||||
fun transformPosition(position: Vec3d) = this.position.add(matrix.transformPosition(position))
|
||||
}
|
||||
+4
-4
@@ -26,11 +26,11 @@ import net.minecraft.util.math.Vec3f
|
||||
class PokemonItemRenderer : CobblemonBuiltinItemRenderer {
|
||||
override fun render(stack: ItemStack, mode: ModelTransformation.Mode, matrices: MatrixStack, vertexConsumers: VertexConsumerProvider, light: Int, overlay: Int) {
|
||||
val pokemonItem = stack.item as? PokemonItem ?: return
|
||||
val pokemon = pokemonItem.asPokemon(stack) ?: return
|
||||
val (species, aspects) = pokemonItem.getSpeciesAndAspects(stack) ?: return
|
||||
|
||||
matrices.push()
|
||||
val model = PokemonModelRepository.getPoser(pokemon.species.resourceIdentifier, pokemon.aspects)
|
||||
val renderLayer = model.getLayer(PokemonModelRepository.getTexture(pokemon.species.resourceIdentifier, pokemon.aspects, null))
|
||||
val model = PokemonModelRepository.getPoser(species.resourceIdentifier, aspects)
|
||||
val renderLayer = model.getLayer(PokemonModelRepository.getTexture(species.resourceIdentifier, aspects, null))
|
||||
|
||||
val transformations = positions[mode]!!
|
||||
|
||||
@@ -54,7 +54,7 @@ class PokemonItemRenderer : CobblemonBuiltinItemRenderer {
|
||||
matrices.push()
|
||||
|
||||
val packedLight = LightmapTextureManager.pack(11, 7)
|
||||
model.withLayerContext(vertexConsumers, null, PokemonModelRepository.getLayers(pokemon.species.resourceIdentifier, pokemon.aspects)) {
|
||||
model.withLayerContext(vertexConsumers, null, PokemonModelRepository.getLayers(species.resourceIdentifier, aspects)) {
|
||||
model.render(matrices, vertexConsumer, packedLight, OverlayTexture.DEFAULT_UV, 1F, 1F, 1F, 1F)
|
||||
}
|
||||
|
||||
|
||||
+23
-1
@@ -22,7 +22,12 @@ import net.minecraft.client.render.entity.feature.FeatureRendererContext
|
||||
import net.minecraft.client.render.entity.model.PlayerEntityModel
|
||||
import net.minecraft.client.util.math.MatrixStack
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import java.util.*
|
||||
|
||||
class PokemonOnShoulderRenderer<T : PlayerEntity>(renderLayerParent: FeatureRendererContext<T, PlayerEntityModel<T>>) : FeatureRenderer<T, PlayerEntityModel<T>>(renderLayerParent) {
|
||||
|
||||
private val playerCache = hashMapOf<UUID, ShoulderCache>()
|
||||
|
||||
override fun render(
|
||||
pMatrixStack: MatrixStack,
|
||||
pBuffer: VertexConsumerProvider,
|
||||
@@ -53,7 +58,21 @@ class PokemonOnShoulderRenderer<T : PlayerEntity>(renderLayerParent: FeatureRend
|
||||
val compoundTag = if (pLeftShoulder) pLivingEntity.shoulderEntityLeft else pLivingEntity.shoulderEntityRight
|
||||
if (compoundTag.isPokemonEntity()) {
|
||||
pMatrixStack.push()
|
||||
val pokemon = Pokemon().loadFromNBT(compoundTag.getCompound(DataKeys.POKEMON))
|
||||
val uuid = compoundTag.getCompound(DataKeys.POKEMON).getUuid(DataKeys.POKEMON_UUID)
|
||||
val cache = this.playerCache.getOrPut(pLivingEntity.uuid) { ShoulderCache() }
|
||||
val pokemon: Pokemon
|
||||
if (pLeftShoulder && cache.lastKnownLeft?.uuid != uuid) {
|
||||
pokemon = Pokemon().loadFromNBT(compoundTag.getCompound(DataKeys.POKEMON))
|
||||
cache.lastKnownLeft = pokemon
|
||||
}
|
||||
else if (!pLeftShoulder && cache.lastKnownRight?.uuid != uuid) {
|
||||
pokemon = Pokemon().loadFromNBT(compoundTag.getCompound(DataKeys.POKEMON))
|
||||
cache.lastKnownRight = pokemon
|
||||
}
|
||||
else {
|
||||
// should never be null but might as well be safe
|
||||
pokemon = (if (pLeftShoulder) cache.lastKnownLeft else cache.lastKnownRight) ?: Pokemon()
|
||||
}
|
||||
val scale = pokemon.form.baseScale * pokemon.scaleModifier
|
||||
val width = pokemon.form.hitbox.width
|
||||
val offset = width / 2 - 0.7
|
||||
@@ -90,4 +109,7 @@ class PokemonOnShoulderRenderer<T : PlayerEntity>(renderLayerParent: FeatureRend
|
||||
pMatrixStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
private data class ShoulderCache(var lastKnownLeft: Pokemon? = null, var lastKnownRight: Pokemon? = null)
|
||||
|
||||
}
|
||||
+1
-1
@@ -75,7 +75,7 @@ class LocatorAccess(
|
||||
for ((name, locator) in locators) {
|
||||
matrixStack.push()
|
||||
locator.rotate(matrixStack)
|
||||
state.getOrPut(name) { MatrixWrapper() }.update(matrixStack.peek().positionMatrix)
|
||||
state.getOrPut(name) { MatrixWrapper() }.updateMatrix(matrixStack.peek().positionMatrix)
|
||||
matrixStack.pop()
|
||||
}
|
||||
|
||||
|
||||
+20
-24
@@ -293,7 +293,7 @@ abstract class PoseableEntityModel<T : Entity>(
|
||||
state.currentModel = this
|
||||
setDefault()
|
||||
state.preRender()
|
||||
updateLocators()
|
||||
updateLocators(state)
|
||||
var poseName = state.getPose()
|
||||
var pose = poseName?.let { getPose(it) }
|
||||
val entityPoseType = if (entity is Poseable) entity.getPoseType() else null
|
||||
@@ -328,7 +328,7 @@ abstract class PoseableEntityModel<T : Entity>(
|
||||
state.currentPose?.let { getPose(it) }?.idleStateful(entity, this, state, limbSwing, limbSwingAmount, ageInTicks, headYaw, headPitch)
|
||||
state.applyAdditives(entity, this, state)
|
||||
relevantParts.forEach { it.changeFactor = 1F }
|
||||
updateLocators()
|
||||
updateLocators(state)
|
||||
}
|
||||
|
||||
override fun setAngles(entity: T, limbSwing: Float, limbSwingAmount: Float, ageInTicks: Float, headYaw: Float, headPitch: Float) {
|
||||
@@ -364,30 +364,26 @@ abstract class PoseableEntityModel<T : Entity>(
|
||||
* Figures out where all of this model's locators are in real space, so that they can be
|
||||
* found and used from other client-side systems.
|
||||
*/
|
||||
fun updateLocators() {
|
||||
currentState?.let {
|
||||
val entity = currentEntity ?: return
|
||||
val matrixStack = MatrixStack()
|
||||
matrixStack.translate(entity.x, entity.y, entity.z)
|
||||
fun updateLocators(state: PoseableEntityState<T>) {
|
||||
val entity = currentEntity ?: return
|
||||
val matrixStack = MatrixStack()
|
||||
// We could improve this to be generalized for other entities
|
||||
if (entity is PokemonEntity) {
|
||||
matrixStack.multiply(Vec3f.POSITIVE_Y.getDegreesQuaternion(180 - entity.bodyYaw))
|
||||
matrixStack.push()
|
||||
// We could improve this to be generalized for other entities
|
||||
if (entity is PokemonEntity) {
|
||||
matrixStack.multiply(Vec3f.POSITIVE_Y.getDegreesQuaternion(180 - entity.bodyYaw))
|
||||
matrixStack.push()
|
||||
matrixStack.scale(-1F, -1F, 1F)
|
||||
val scale = entity.pokemon.form.baseScale * entity.pokemon.scaleModifier * (entity.delegate as PokemonClientDelegate).entityScaleModifier
|
||||
matrixStack.scale(scale, scale, scale)
|
||||
} else if (entity is EmptyPokeBallEntity) {
|
||||
matrixStack.multiply(Vec3f.POSITIVE_Y.getDegreesQuaternion(entity.yaw))
|
||||
matrixStack.push()
|
||||
matrixStack.scale(1F, -1F, -1F)
|
||||
matrixStack.scale(0.7F, 0.7F, 0.7F)
|
||||
}
|
||||
// Standard living entity offset, only God knows why Mojang did this.
|
||||
matrixStack.translate(0.0, -1.5, 0.0)
|
||||
|
||||
locatorAccess.update(matrixStack, it.locatorStates)
|
||||
matrixStack.scale(-1F, -1F, 1F)
|
||||
val scale = entity.pokemon.form.baseScale * entity.pokemon.scaleModifier * (entity.delegate as PokemonClientDelegate).entityScaleModifier
|
||||
matrixStack.scale(scale, scale, scale)
|
||||
} else if (entity is EmptyPokeBallEntity) {
|
||||
matrixStack.multiply(Vec3f.POSITIVE_Y.getDegreesQuaternion(entity.yaw))
|
||||
matrixStack.push()
|
||||
matrixStack.scale(1F, -1F, -1F)
|
||||
matrixStack.scale(0.7F, 0.7F, 0.7F)
|
||||
}
|
||||
// Standard living entity offset, only God knows why Mojang did this.
|
||||
matrixStack.translate(0.0, -1.5, 0.0)
|
||||
|
||||
locatorAccess.update(matrixStack, state.locatorStates)
|
||||
}
|
||||
|
||||
fun ModelPart.translation(
|
||||
|
||||
+5
@@ -21,6 +21,7 @@ import com.cobblemon.mod.common.client.render.models.blockbench.quirk.QuirkData
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import net.minecraft.client.MinecraftClient
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
/**
|
||||
* Represents the entity-specific state for a poseable model. The implementation is responsible for
|
||||
@@ -108,4 +109,8 @@ abstract class PoseableEntityState<T : Entity> {
|
||||
statefulAnimations.clear()
|
||||
statefulAnimations.addAll(animations)
|
||||
}
|
||||
|
||||
fun updateLocatorPosition(position: Vec3d) {
|
||||
locatorStates.values.toList().forEach { it.updatePosition(position) }
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -32,8 +32,8 @@ class PidgeotModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Biped
|
||||
override val head = getPart("head")
|
||||
private val tail = getPart("tail")
|
||||
|
||||
override val portraitScale = 2.3F
|
||||
override val portraitTranslation = Vec3d(-0.15, -0.4, 0.0)
|
||||
override val portraitScale = 2.8F
|
||||
override val portraitTranslation = Vec3d(-0.15, -0.8, 0.0)
|
||||
override val profileScale = 1.2F
|
||||
override val profileTranslation = Vec3d(0.0, -0.05, 0.0)
|
||||
|
||||
|
||||
+3
-2
@@ -34,8 +34,8 @@ class PidgeottoModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bip
|
||||
override val head = getPart("head")
|
||||
private val tail = getPart("tail")
|
||||
|
||||
override val portraitScale = 2.3F
|
||||
override val portraitTranslation = Vec3d(-0.1, -0.55, 0.0)
|
||||
override val portraitScale = 2.8F
|
||||
override val portraitTranslation = Vec3d(-0.1, -0.8, 0.0)
|
||||
override val profileScale = 1.1F
|
||||
override val profileTranslation = Vec3d(0.0, 0.1, 0.0)
|
||||
|
||||
@@ -82,6 +82,7 @@ class PidgeottoModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bip
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("pidgeotto", "ground_idle"),
|
||||
rootPart.translation(
|
||||
function = parabolaFunction(
|
||||
peak = -4F,
|
||||
|
||||
+2
-2
@@ -32,8 +32,8 @@ class PidgeyModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, BipedF
|
||||
override val head = getPart("head")
|
||||
private val tail = getPart("tail")
|
||||
|
||||
override val portraitScale = 2.5F
|
||||
override val portraitTranslation = Vec3d(0.0, -1.3, 0.0)
|
||||
override val portraitScale = 3.5F
|
||||
override val portraitTranslation = Vec3d(-0.1, -2.1, 0.0)
|
||||
|
||||
override val profileScale = 1.2F
|
||||
override val profileTranslation = Vec3d(0.0, -0.01, 0.0)
|
||||
|
||||
+17
-5
@@ -8,14 +8,17 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen1
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BipedWalkAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
class PorygonModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, BipedFrame {
|
||||
@@ -30,13 +33,21 @@ class PorygonModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Biped
|
||||
override val profileScale = 1.0F
|
||||
override val profileTranslation = Vec3d(0.0, 0.8, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk("blink") { bedrockStateful("porygonz", "blink").setPreventsIdle(false) }
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
idleAnimations = arrayOf(bedrock("porygon", "sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = STATIONARY_POSES + UI_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
transformTicks = 10,
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
@@ -47,16 +58,17 @@ class PorygonModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Biped
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = MOVING_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
transformTicks = 10,
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("porygon", "ground_idle")
|
||||
bedrock("porygon", "ground_walk")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PoseableEntityState<PokemonEntity>
|
||||
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("porygon", "faint") else null
|
||||
override fun getFaintAnimation(
|
||||
pokemonEntity: PokemonEntity,
|
||||
state: PoseableEntityState<PokemonEntity>
|
||||
) = if (state.isPosedIn(standing, walk)) bedrockStateful("porygon", "faint2") else null
|
||||
}
|
||||
+48
-6
@@ -8,8 +8,10 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen1
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.asTransformed
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
@@ -24,27 +26,67 @@ class StarmieModel(root: ModelPart) : PokemonPoseableModel() {
|
||||
override val profileScale = 1.4F
|
||||
override val profileTranslation = Vec3d(0.0, -0.24, 0.0)
|
||||
|
||||
lateinit var battleidle: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
lateinit var swim: PokemonPose
|
||||
lateinit var float: PokemonPose
|
||||
lateinit var sleep: PokemonPose
|
||||
|
||||
override fun registerPoses() {
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = STATIONARY_POSES + UI_POSES,
|
||||
transformTicks = 10,
|
||||
poseType = PoseType.STAND,
|
||||
condition = { !it.isBattling },
|
||||
idleAnimations = arrayOf(
|
||||
//bedrock("starmie", "ground_idle")
|
||||
bedrock("starmie", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = MOVING_POSES,
|
||||
transformTicks = 10,
|
||||
poseType = PoseType.WALK,
|
||||
condition = { !it.isBattling },
|
||||
idleAnimations = arrayOf(
|
||||
//bedrock("starmie", "ground_walk")
|
||||
bedrock("starmie", "ground_walk")
|
||||
)
|
||||
)
|
||||
|
||||
float = registerPose(
|
||||
poseName = "float",
|
||||
poseTypes = UI_POSES + PoseType.FLOAT,
|
||||
condition = { !it.isBattling },
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("starmie", "water_idle")
|
||||
)
|
||||
)
|
||||
|
||||
swim = registerPose(
|
||||
poseName = "swim",
|
||||
poseType = PoseType.SWIM,
|
||||
condition = { !it.isBattling },
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("starmie", "water_swim")
|
||||
)
|
||||
)
|
||||
|
||||
sleep = registerPose(
|
||||
poseName = "sleep",
|
||||
poseType = PoseType.SLEEP,
|
||||
idleAnimations = arrayOf(bedrock("starmie", "sleep"))
|
||||
)
|
||||
|
||||
battleidle = registerPose(
|
||||
poseName = "battle_idle",
|
||||
poseTypes = PoseType.STATIONARY_POSES,
|
||||
transformTicks = 10,
|
||||
condition = { it.isBattling },
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("starmie", "battle_idle")
|
||||
)
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
|
||||
+31
-6
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen1
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
@@ -26,25 +27,49 @@ class StaryuModel(root: ModelPart) : PokemonPoseableModel() {
|
||||
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
lateinit var swim: PokemonPose
|
||||
lateinit var float: PokemonPose
|
||||
lateinit var sleep: PokemonPose
|
||||
|
||||
override fun registerPoses() {
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = STATIONARY_POSES + UI_POSES,
|
||||
transformTicks = 10,
|
||||
poseType = PoseType.STAND,
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("staryu", "idle")
|
||||
bedrock("staryu", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = MOVING_POSES,
|
||||
transformTicks = 10,
|
||||
poseType = PoseType.WALK,
|
||||
idleAnimations = arrayOf(
|
||||
//bedrock("staryu", "ground_walk")
|
||||
bedrock("staryu", "ground_walk")
|
||||
)
|
||||
)
|
||||
|
||||
float = registerPose(
|
||||
poseName = "float",
|
||||
poseTypes = UI_POSES + PoseType.FLOAT,
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("staryu", "water_idle")
|
||||
)
|
||||
)
|
||||
|
||||
swim = registerPose(
|
||||
poseName = "swim",
|
||||
poseType = PoseType.SWIM,
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("staryu", "water_swim")
|
||||
)
|
||||
)
|
||||
|
||||
sleep = registerPose(
|
||||
poseName = "sleep",
|
||||
poseType = PoseType.SLEEP,
|
||||
idleAnimations = arrayOf(bedrock("staryu", "sleep"))
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.client.render.models.blockbench.pokemon.gen2
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BipedWalkAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
class MagcargoModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("magcargo")
|
||||
override val head = getPart("head")
|
||||
|
||||
override val portraitScale = 1.8F
|
||||
override val portraitTranslation = Vec3d(-0.55, 0.1, 0.0)
|
||||
|
||||
override val profileScale = 0.8F
|
||||
override val profileTranslation = Vec3d(0.0, 0.5, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk("blink") { bedrockStateful("magcargo", "blink").setPreventsIdle(false) }
|
||||
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
idleAnimations = arrayOf(bedrock("magcargo", "ground_sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = STATIONARY_POSES + UI_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("magcargo", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = MOVING_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("magcargo", "ground_walk")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PoseableEntityState<PokemonEntity>
|
||||
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("magcargo", "faint") else null
|
||||
}
|
||||
+1
-1
@@ -18,7 +18,7 @@ import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class PiloswineModel(root: ModelPart) : PokemonPoseableModel() {
|
||||
override val rootPart = root.registerChildWithAllChildren("piloswine_male")
|
||||
override val rootPart = root.registerChildWithAllChildren("piloswine")
|
||||
|
||||
override val portraitScale = 3.0F
|
||||
override val portraitTranslation = Vec3d(-0.6, -3.0, 0.0)
|
||||
|
||||
+21
-8
@@ -8,14 +8,17 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen2
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BipedWalkAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
class Porygon2Model(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, BipedFrame {
|
||||
@@ -25,18 +28,27 @@ class Porygon2Model(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bipe
|
||||
override val rightLeg = getPart("leg_right")
|
||||
|
||||
override val portraitScale = 2.5F
|
||||
override val portraitTranslation = Vec3d(-0.45, -0.8, 0.0)
|
||||
override val portraitTranslation = Vec3d(-0.45, 0.5, 0.0)
|
||||
|
||||
override val profileScale = 1.1F
|
||||
override val profileTranslation = Vec3d(0.0, 0.0, 0.0)
|
||||
override val profileTranslation = Vec3d(0.0, 0.55, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk("blink") { bedrockStateful("porygon2", "blink").setPreventsIdle(false) }
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
idleAnimations = arrayOf(bedrock("porygon2", "sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = STATIONARY_POSES + UI_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
transformTicks = 10,
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("porygon2", "ground_idle")
|
||||
@@ -46,16 +58,17 @@ class Porygon2Model(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bipe
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = MOVING_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
transformTicks = 10,
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("porygon2", "ground_idle"),
|
||||
BipedWalkAnimation(this, periodMultiplier = 0.6F, amplitudeMultiplier = 0.9F),
|
||||
bedrock("porygon2", "ground_walk")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PoseableEntityState<PokemonEntity>
|
||||
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("porygon2", "faint") else null
|
||||
override fun getFaintAnimation(
|
||||
pokemonEntity: PokemonEntity,
|
||||
state: PoseableEntityState<PokemonEntity>
|
||||
) = if (state.isPosedIn(standing, walk)) bedrockStateful("porygon2", "faint") else null
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.client.render.models.blockbench.pokemon.gen2
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BipedWalkAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
class SlugmaModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("slugma")
|
||||
override val head = getPart("head")
|
||||
|
||||
override val portraitScale = 1.7F
|
||||
override val portraitTranslation = Vec3d(-0.35, -0.3, 0.0)
|
||||
|
||||
override val profileScale = 0.75F
|
||||
override val profileTranslation = Vec3d(0.0, 0.575, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk("blink") { bedrockStateful("slugma", "blink").setPreventsIdle(false) }
|
||||
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
idleAnimations = arrayOf(bedrock("slugma", "ground_sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = STATIONARY_POSES + UI_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("slugma", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = MOVING_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("slugma", "ground_walk")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PoseableEntityState<PokemonEntity>
|
||||
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("slugma", "faint") else null
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.client.render.models.blockbench.pokemon.gen3
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BipedWalkAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class NosepassModel(root: ModelPart) : PokemonPoseableModel(), BipedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("nosepass")
|
||||
|
||||
override val leftLeg = getPart("leg_left")
|
||||
override val rightLeg = getPart("leg_right")
|
||||
|
||||
override val portraitScale = 1.5F
|
||||
override val portraitTranslation = Vec3d(-0.1, -0.1, 0.0)
|
||||
|
||||
override val profileScale = 0.75F
|
||||
override val profileTranslation = Vec3d(0.0, 0.65, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
|
||||
override fun registerPoses() {
|
||||
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
idleAnimations = arrayOf(bedrock("nosepass", "ground_sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = STATIONARY_POSES + UI_POSES,
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("nosepass", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("nosepass", "ground_walk"),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun getFaintAnimation(
|
||||
pokemonEntity: PokemonEntity,
|
||||
state: PoseableEntityState<PokemonEntity>
|
||||
) = if (state.isNotPosedIn(sleep)) bedrockStateful("nosepass", "faint") else null
|
||||
}
|
||||
+10
-5
@@ -8,7 +8,9 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen4
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BimanualSwingAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BipedWalkAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BimanualFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
@@ -19,12 +21,14 @@ import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class InfernapeModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, BipedFrame {
|
||||
class InfernapeModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, BipedFrame, BimanualFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("infernape")
|
||||
override val head = getPart("head")
|
||||
override val head = getPart("head_ai")
|
||||
|
||||
override val leftLeg = getPart("leg_left")
|
||||
override val rightLeg = getPart("leg_right")
|
||||
override val leftArm = getPart("arm_left")
|
||||
override val rightArm = getPart("arm_right")
|
||||
|
||||
override val portraitScale = 1.8F
|
||||
override val portraitTranslation = Vec3d(-0.65, 1.55, 0.0)
|
||||
@@ -42,7 +46,7 @@ class InfernapeModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bip
|
||||
poseTypes = STATIONARY_POSES + UI_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
//singleBoneLook(),
|
||||
bedrock("infernape", "idle")
|
||||
)
|
||||
)
|
||||
@@ -52,9 +56,10 @@ class InfernapeModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bip
|
||||
poseTypes = MOVING_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
//singleBoneLook(),
|
||||
bedrock("infernape", "idle"),
|
||||
BipedWalkAnimation(this, periodMultiplier = 0.75F, amplitudeMultiplier = 0.8F)
|
||||
BipedWalkAnimation(this, periodMultiplier = 0.75F, amplitudeMultiplier = 0.8F),
|
||||
BimanualSwingAnimation(this, swingPeriodMultiplier = 0.6F, amplitudeMultiplier = 0.9F)
|
||||
//bedrock("infernape", "ground_walk")
|
||||
)
|
||||
)
|
||||
|
||||
+28
-5
@@ -8,12 +8,15 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen4
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
class PorygonzModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
@@ -21,20 +24,34 @@ class PorygonzModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
override val head = getPart("head")
|
||||
|
||||
override val portraitScale = 2.4F
|
||||
override val portraitTranslation = Vec3d(-0.1, 0.75, 0.0)
|
||||
override val portraitTranslation = Vec3d(-0.1, 1.1, 0.0)
|
||||
|
||||
override val profileScale = 0.85F
|
||||
override val profileTranslation = Vec3d(0.0, 0.6, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk("blink") { bedrockStateful("porygonz", "blink").setPreventsIdle(false) }
|
||||
val twitch1 = quirk("twitch1") { bedrockStateful("porygonz", "twitch1").setPreventsIdle(false) }
|
||||
val twitch2 = quirk("twitch2") { bedrockStateful("porygonz", "twitch2").setPreventsIdle(false) }
|
||||
val twitch3 = quirk("twitch3") { bedrockStateful("porygonz", "twitch3").setPreventsIdle(false) }
|
||||
val twitch4 = quirk("twitch4") { bedrockStateful("porygonz", "twitch4").setPreventsIdle(false) }
|
||||
val twitch5 = quirk("twitch5") { bedrockStateful("porygonz", "twitch5").setPreventsIdle(false) }
|
||||
val twitch6 = quirk("twitch6") { bedrockStateful("porygonz", "twitch6").setPreventsIdle(false) }
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
quirks = arrayOf(twitch1, twitch2, twitch3, twitch4, twitch5, twitch6),
|
||||
idleAnimations = arrayOf(bedrock("porygonz", "sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = UI_POSES + STATIONARY_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
poseTypes = STATIONARY_POSES + UI_POSES,
|
||||
quirks = arrayOf(blink, twitch1, twitch2, twitch3, twitch4, twitch5, twitch6),
|
||||
transformTicks = 10,
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("porygonz", "ground_idle")
|
||||
@@ -44,11 +61,17 @@ class PorygonzModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = MOVING_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
quirks = arrayOf(blink, twitch1, twitch2, twitch3, twitch4, twitch5, twitch6),
|
||||
transformTicks = 10,
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("porygonz", "ground_idle")
|
||||
bedrock("porygonz", "ground_walk")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun getFaintAnimation(
|
||||
pokemonEntity: PokemonEntity,
|
||||
state: PoseableEntityState<PokemonEntity>
|
||||
) = if (state.isPosedIn(standing, walk)) bedrockStateful("porygonz", "faint") else null
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.client.render.models.blockbench.pokemon.gen4
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BipedWalkAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class ProbopassModel(root: ModelPart) : PokemonPoseableModel() {
|
||||
override val rootPart = root.registerChildWithAllChildren("probopass")
|
||||
|
||||
override val portraitScale = 1F
|
||||
override val portraitTranslation = Vec3d(0.0, 0.425, 0.0)
|
||||
|
||||
override val profileScale = 0.75F
|
||||
override val profileTranslation = Vec3d(0.0, 0.7, 0.0)
|
||||
|
||||
lateinit var sleep: PokemonPose
|
||||
lateinit var standing: PokemonPose
|
||||
lateinit var walk: PokemonPose
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk("blink") { bedrockStateful("probopass", "blink").setPreventsIdle(false) }
|
||||
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
idleAnimations = arrayOf(bedrock("probopass", "ground_sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = STATIONARY_POSES + UI_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("probopass", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = MOVING_POSES,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
bedrock("probopass", "ground_walk"),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun getFaintAnimation(
|
||||
pokemonEntity: PokemonEntity,
|
||||
state: PoseableEntityState<PokemonEntity>
|
||||
) = if (state.isNotPosedIn(sleep)) bedrockStateful("probopass", "faint") else null
|
||||
}
|
||||
+1
-6
@@ -23,15 +23,10 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class GolurkModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame, BipedFrame, BimanualFrame {
|
||||
class GolurkModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("golurk")
|
||||
override val head = getPart("head")
|
||||
|
||||
override val leftArm = getPart("arm_left")
|
||||
override val rightArm = getPart("arm_right")
|
||||
override val leftLeg = getPart("leg_left")
|
||||
override val rightLeg = getPart("leg_right")
|
||||
|
||||
override val portraitScale = 3.0F
|
||||
override val portraitTranslation = Vec3d(-0.3, 5.4, 0.0)
|
||||
|
||||
|
||||
+6
@@ -8,9 +8,11 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen5
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
@@ -45,4 +47,8 @@ class KlangModel(root: ModelPart) : PokemonPoseableModel() {
|
||||
)
|
||||
)
|
||||
}
|
||||
override fun getFaintAnimation(
|
||||
pokemonEntity: PokemonEntity,
|
||||
state: PoseableEntityState<PokemonEntity>
|
||||
) = if (state.isPosedIn(standing, walk)) bedrockStateful("klang", "faint") else null
|
||||
}
|
||||
+6
@@ -8,9 +8,11 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen5
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
@@ -45,4 +47,8 @@ class KlinkModel(root: ModelPart) : PokemonPoseableModel() {
|
||||
)
|
||||
)
|
||||
}
|
||||
override fun getFaintAnimation(
|
||||
pokemonEntity: PokemonEntity,
|
||||
state: PoseableEntityState<PokemonEntity>
|
||||
) = if (state.isPosedIn(standing, walk)) bedrockStateful("klink", "faint") else null
|
||||
}
|
||||
+6
@@ -8,9 +8,11 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen5
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PoseableEntityState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPoseableModel
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
@@ -45,4 +47,8 @@ class KlinklangModel(root: ModelPart) : PokemonPoseableModel() {
|
||||
)
|
||||
)
|
||||
}
|
||||
override fun getFaintAnimation(
|
||||
pokemonEntity: PokemonEntity,
|
||||
state: PoseableEntityState<PokemonEntity>
|
||||
) = if (state.isPosedIn(standing, walk)) bedrockStateful("klinklang", "faint") else null
|
||||
}
|
||||
+3
-3
@@ -17,7 +17,7 @@ import net.minecraft.util.math.Vec3d
|
||||
|
||||
class SerperiorModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("serperior")
|
||||
override val head = getPart("head")
|
||||
override val head = getPart("head_ai")
|
||||
|
||||
override val portraitScale = 2.5F
|
||||
override val portraitTranslation = Vec3d(-0.3, 1.25, 0.0)
|
||||
@@ -33,7 +33,7 @@ class SerperiorModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
poseName = "standing",
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
idleAnimations = arrayOf(
|
||||
// singleBoneLook(),
|
||||
singleBoneLook(),
|
||||
bedrock("serperior", "ground_idle")
|
||||
)
|
||||
)
|
||||
@@ -42,7 +42,7 @@ class SerperiorModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
poseName = "walk",
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
idleAnimations = arrayOf(
|
||||
// singleBoneLook(),
|
||||
singleBoneLook(),
|
||||
bedrock("serperior", "ground_walk")
|
||||
)
|
||||
)
|
||||
|
||||
+3
-3
@@ -19,7 +19,7 @@ import net.minecraft.util.math.Vec3d
|
||||
|
||||
class ServineModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame, BipedFrame, BimanualFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("servine")
|
||||
override val head = getPart("head")
|
||||
override val head = getPart("head_ai")
|
||||
override val rightArm = getPart("arm_right")
|
||||
override val leftArm = getPart("arm_left")
|
||||
override val rightLeg = getPart("leg_right")
|
||||
@@ -48,7 +48,7 @@ class ServineModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bipe
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
// singleBoneLook(),
|
||||
singleBoneLook(),
|
||||
bedrock("servine", "ground_idle")
|
||||
)
|
||||
)
|
||||
@@ -59,7 +59,7 @@ class ServineModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bipe
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
// singleBoneLook(),
|
||||
singleBoneLook(),
|
||||
bedrock("servine", "ground_walk")
|
||||
)
|
||||
)
|
||||
|
||||
+3
-3
@@ -19,7 +19,7 @@ import net.minecraft.util.math.Vec3d
|
||||
|
||||
class SnivyModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame, BipedFrame, BimanualFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("snivy")
|
||||
override val head = getPart("head")
|
||||
override val head = getPart("head_ai")
|
||||
override val rightArm = getPart("arm_right")
|
||||
override val leftArm = getPart("arm_left")
|
||||
override val rightLeg = getPart("leg_right")
|
||||
@@ -48,7 +48,7 @@ class SnivyModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame, BipedF
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
// singleBoneLook(),
|
||||
singleBoneLook(),
|
||||
bedrock("snivy", "ground_idle")
|
||||
)
|
||||
)
|
||||
@@ -59,7 +59,7 @@ class SnivyModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame, BipedF
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
idleAnimations = arrayOf(
|
||||
// singleBoneLook(),
|
||||
singleBoneLook(),
|
||||
bedrock("snivy", "ground_walk")
|
||||
)
|
||||
)
|
||||
|
||||
-1
@@ -46,7 +46,6 @@ class FroakieModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Biped
|
||||
poseType = PoseType.SLEEP,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
condition = { !it.isBattling },
|
||||
idleAnimations = arrayOf(bedrock("froakie", "sleep"))
|
||||
)
|
||||
|
||||
|
||||
-1
@@ -46,7 +46,6 @@ class FrogadierModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bip
|
||||
poseType = PoseType.SLEEP,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
condition = { !it.isBattling },
|
||||
idleAnimations = arrayOf(bedrock("frogadier", "sleep"))
|
||||
)
|
||||
|
||||
|
||||
-1
@@ -49,7 +49,6 @@ class GreninjaModel(root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Bipe
|
||||
poseType = PoseType.SLEEP,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
condition = { !it.isBattling },
|
||||
transformedParts = arrayOf(
|
||||
shurikenleft.asTransformed().withVisibility(visibility = false),
|
||||
shurikenright.asTransformed().withVisibility(visibility = false)
|
||||
|
||||
+20
-6
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen9
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.asTransformed
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.QuadrupedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPose
|
||||
@@ -16,14 +17,12 @@ import com.cobblemon.mod.common.entity.PoseType
|
||||
import net.minecraft.client.model.ModelPart
|
||||
import net.minecraft.util.math.Vec3d
|
||||
|
||||
class IronleavesModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame, QuadrupedFrame {
|
||||
class IronleavesModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("ironleaves")
|
||||
override val head = getPart("head")
|
||||
|
||||
override val foreLeftLeg = getPart("leg_front_left")
|
||||
override val foreRightLeg = getPart("leg_front_right")
|
||||
override val hindLeftLeg = getPart("leg_back_left")
|
||||
override val hindRightLeg = getPart("leg_back_right")
|
||||
val neck_sword_left = getPart("neck_sword_left")
|
||||
val neck_sword_right = getPart("neck_sword_right")
|
||||
val sword_head = getPart("sword_head")
|
||||
|
||||
override val portraitScale = 3.0F
|
||||
override val portraitTranslation = Vec3d(-0.9, 2.2, 0.0)
|
||||
@@ -43,6 +42,11 @@ class IronleavesModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Q
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
transformedParts = arrayOf(
|
||||
neck_sword_left.asTransformed().withVisibility(visibility = false),
|
||||
neck_sword_right.asTransformed().withVisibility(visibility = false),
|
||||
sword_head.asTransformed().withVisibility(visibility = false)
|
||||
),
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("ironleaves", "ground_idle")
|
||||
@@ -51,6 +55,11 @@ class IronleavesModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Q
|
||||
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
transformedParts = arrayOf(
|
||||
neck_sword_left.asTransformed().withVisibility(visibility = false),
|
||||
neck_sword_right.asTransformed().withVisibility(visibility = false),
|
||||
sword_head.asTransformed().withVisibility(visibility = false)
|
||||
),
|
||||
idleAnimations = arrayOf(bedrock("ironleaves", "sleep"))
|
||||
)
|
||||
|
||||
@@ -59,6 +68,11 @@ class IronleavesModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame, Q
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
transformedParts = arrayOf(
|
||||
neck_sword_left.asTransformed().withVisibility(visibility = false),
|
||||
neck_sword_right.asTransformed().withVisibility(visibility = false),
|
||||
sword_head.asTransformed().withVisibility(visibility = false)
|
||||
),
|
||||
idleAnimations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("ironleaves", "ground_walk")
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ class WalkingwakeModel (root: ModelPart) : PokemonPoseableModel(), HeadedFrame,
|
||||
override val rightLeg = getPart("leg_right")
|
||||
|
||||
override val portraitScale = 2.2F
|
||||
override val portraitTranslation = Vec3d(-2.35, 2.4, 0.0)
|
||||
override val portraitTranslation = Vec3d(-2.5, 2.4, 0.0)
|
||||
|
||||
override val profileScale = 0.35F
|
||||
override val profileTranslation = Vec3d(0.0, 1.2, 0.0)
|
||||
|
||||
+4
-2
@@ -379,8 +379,10 @@ object PokemonModelRepository : VaryingModelRepository<PokemonEntity, PokemonPos
|
||||
inbuilt("snivy", ::SnivyModel)
|
||||
inbuilt("servine", ::ServineModel)
|
||||
inbuilt("serperior", ::SerperiorModel)
|
||||
|
||||
|
||||
inbuilt("slugma", ::SlugmaModel)
|
||||
inbuilt("magcargo", ::MagcargoModel)
|
||||
inbuilt("nosepass", ::NosepassModel)
|
||||
inbuilt("probopass", ::ProbopassModel)
|
||||
|
||||
// Unhooked because the families are not completed
|
||||
// inbuilt("sprigatito", ::SprigatitoModel)
|
||||
|
||||
+1
-3
@@ -27,10 +27,8 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.isLookingAt
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.util.math.DoubleRange
|
||||
import com.cobblemon.mod.common.util.math.geometry.getOrigin
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import com.cobblemon.mod.common.util.math.remap
|
||||
import java.util.Vector
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.tan
|
||||
@@ -151,7 +149,7 @@ class PokemonRenderer(
|
||||
val clientDelegate = entity.delegate as PokemonClientDelegate
|
||||
val pokemonPosition = entity.pos.add(0.0, entity.height / 2.0 * clientDelegate.entityScaleModifier.toDouble(), 0.0)
|
||||
val beamSourcePosition = if (beamTarget is EmptyPokeBallEntity) {
|
||||
(beamTarget.delegate as PokeBallPoseableState).locatorStates["beam"]?.matrix?.getOrigin() ?: beamTarget.pos
|
||||
(beamTarget.delegate as PokeBallPoseableState).locatorStates["beam"]?.getOrigin() ?: beamTarget.pos
|
||||
// beamTarget.pos.let { it.add(pokemonPosition.subtract(it).normalize().multiply(0.4, 0.0, 0.4)) }
|
||||
} else {
|
||||
beamTarget as PlayerEntity
|
||||
|
||||
+7
-2
@@ -51,6 +51,11 @@ class ClientStorageManager {
|
||||
}
|
||||
}
|
||||
|
||||
fun switchToPokemon(pokemon: UUID) {
|
||||
selectedPokemon = pokemon
|
||||
selectedSlot = myParty.indexOf(myParty.findByUUID(pokemon))
|
||||
}
|
||||
|
||||
fun checkSelectedPokemon() {
|
||||
if (selectedSlot == -1) {
|
||||
val pokemon = myParty.firstOrNull { it != null } ?: return
|
||||
@@ -77,7 +82,7 @@ class ClientStorageManager {
|
||||
}
|
||||
|
||||
fun locatePokemon(storeID: UUID, pokemonID: UUID): Pokemon? {
|
||||
partyStores[storeID]?.let { return it.findByUUID(pokemonID) } ?: return pcStores[storeID]?.findByUUID(pokemonID)
|
||||
return partyStores[storeID]?.findByUUID(pokemonID) ?: pcStores[storeID]?.findByUUID(pokemonID)
|
||||
}
|
||||
|
||||
fun createParty(mine: Boolean, uuid: UUID, slots: Int) {
|
||||
@@ -144,4 +149,4 @@ class ClientStorageManager {
|
||||
partyStores.clear()
|
||||
pcStores.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.command
|
||||
|
||||
import com.cobblemon.mod.common.api.permission.CobblemonPermissions
|
||||
import com.cobblemon.mod.common.api.storage.pc.link.PCLinkManager
|
||||
import com.cobblemon.mod.common.api.storage.pc.link.PermissiblePcLink
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.OpenPCPacket
|
||||
import com.cobblemon.mod.common.util.isInBattle
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.util.pc
|
||||
import com.cobblemon.mod.common.util.permission
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.CommandDispatcher
|
||||
import com.mojang.brigadier.context.CommandContext
|
||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType
|
||||
import net.minecraft.server.command.CommandManager.*
|
||||
import net.minecraft.server.command.ServerCommandSource
|
||||
|
||||
object PcCommand {
|
||||
|
||||
private const val NAME = "pc"
|
||||
private val IN_BATTLE_EXCEPTION = SimpleCommandExceptionType(lang("pc.inbattle").red())
|
||||
|
||||
fun register(dispatcher : CommandDispatcher<ServerCommandSource>) {
|
||||
dispatcher.register(literal(NAME)
|
||||
.permission(CobblemonPermissions.PC)
|
||||
.executes(this::execute)
|
||||
)
|
||||
}
|
||||
|
||||
private fun execute(context: CommandContext<ServerCommandSource>): Int {
|
||||
val player = context.source.playerOrThrow
|
||||
val pc = player.pc()
|
||||
if (player.isInBattle()) {
|
||||
throw IN_BATTLE_EXCEPTION.create()
|
||||
}
|
||||
PCLinkManager.addLink(PermissiblePcLink(pc, player, CobblemonPermissions.PC))
|
||||
OpenPCPacket(pc.uuid).sendToPlayer(player)
|
||||
return Command.SINGLE_SUCCESS
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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.command
|
||||
|
||||
import com.cobblemon.mod.common.api.permission.CobblemonPermissions
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.client.settings.ServerSettings
|
||||
import com.cobblemon.mod.common.command.argument.PartySlotArgumentType
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.RemoveClientPokemonPacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.mojang.brigadier.CommandDispatcher
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType
|
||||
import com.mojang.brigadier.context.CommandContext
|
||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType
|
||||
import net.minecraft.command.argument.EntityArgumentType
|
||||
import net.minecraft.server.command.CommandManager
|
||||
import net.minecraft.server.command.CommandManager.literal
|
||||
import net.minecraft.server.command.ServerCommandSource
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
|
||||
/**
|
||||
* Send Pokemon to the PC.
|
||||
*
|
||||
* Two similar commands with the syntax:
|
||||
*
|
||||
* `/pokebox <player> <slot> [box]` Sends a single Pokemon to the PC, allowing for a specific box to be selected.
|
||||
* If a box is selected and is full, no action will take place.
|
||||
*
|
||||
* `/pokeboxall <player> [box]` Sends all party pokemon to the PC, allowing for a specific box to be selected.
|
||||
* If a box is selected and would not beable to house all of the party Pokemon, no action will take place.
|
||||
*/
|
||||
object PokeboxCommand {
|
||||
private val BOX_DOES_NOT_EXIST = { boxNo: Int -> commandLang("pokebox.box_does_not_exist", boxNo) }
|
||||
private val BOX_IS_FULL_EXCEPTION = { boxNo: Int -> commandLang("pokebox.box_is_full", boxNo) }
|
||||
private val STORAGE_IS_FULL_EXCEPTION = commandLang("pokebox.storage_is_full")
|
||||
private val LAST_POKE_MESSAGE = commandLang("pokebox.last_pokemon")
|
||||
|
||||
fun register(dispatcher: CommandDispatcher<ServerCommandSource>) {
|
||||
dispatcher.register(literal("pokebox")
|
||||
.permission(CobblemonPermissions.POKEBOX)
|
||||
.then(CommandManager.argument("player", EntityArgumentType.player())
|
||||
.then(CommandManager.argument("slot", PartySlotArgumentType.partySlot())
|
||||
.then(CommandManager.argument("box", IntegerArgumentType.integer(1))
|
||||
.executes { context ->
|
||||
val player = context.player()
|
||||
val pokemon = PartySlotArgumentType.getPokemonOf(context, "slot", player)
|
||||
val box = IntegerArgumentType.getInteger(context, "box")
|
||||
execute(context, player, listOf(pokemon), box)
|
||||
})
|
||||
.executes { context ->
|
||||
val player = context.player()
|
||||
val pokemon = PartySlotArgumentType.getPokemonOf(context, "slot", player)
|
||||
execute(context, player, listOf(pokemon))
|
||||
})
|
||||
)
|
||||
)
|
||||
|
||||
dispatcher.register(literal("pokeboxall")
|
||||
.permission(CobblemonPermissions.POKEBOX)
|
||||
.then(CommandManager.argument("player", EntityArgumentType.player())
|
||||
.then(CommandManager.argument("box", IntegerArgumentType.integer(1))
|
||||
.executes { context ->
|
||||
val player = context.player()
|
||||
val box = IntegerArgumentType.getInteger(context, "box")
|
||||
execute(context, player, player.party().toList(), box)
|
||||
})
|
||||
.executes { context ->
|
||||
val player = context.player()
|
||||
execute(context, player, player.party().toList())
|
||||
}))
|
||||
}
|
||||
|
||||
private fun execute(
|
||||
context: CommandContext<ServerCommandSource>,
|
||||
player: ServerPlayerEntity,
|
||||
pokemons: Collection<Pokemon>,
|
||||
box: Int? = null,
|
||||
): Int {
|
||||
val playerPc = player.pc()
|
||||
val playerParty = player.party()
|
||||
|
||||
// If specifying a box, first check that the box exists and can sufficiently hold all the pokemon to be moved.
|
||||
if (box != null) {
|
||||
if (playerPc.boxes.size < box) {
|
||||
throw SimpleCommandExceptionType(BOX_DOES_NOT_EXIST(box).red()).create()
|
||||
}
|
||||
|
||||
val pcBox = playerPc.boxes.get(box - 1)
|
||||
|
||||
if (pcBox.unoccupiedSlots < pokemons.size) {
|
||||
throw SimpleCommandExceptionType(BOX_IS_FULL_EXCEPTION(box).red()).create()
|
||||
}
|
||||
}
|
||||
|
||||
// Operate in reverse so that the party "lead" pokemon would be kept
|
||||
pokemons.reversed().forEach { pokemon ->
|
||||
if (ServerSettings.preventCompletePartyDeposit && playerParty.occupied() == 1) {
|
||||
context.source.sendFeedback(LAST_POKE_MESSAGE.red(), false)
|
||||
return pokemons.size - 1
|
||||
}
|
||||
|
||||
// If PCStore and PCBox both implemented PokemonStore we could make this code a lot cleaner via the same interface
|
||||
val pcPosition = if (box == null) {
|
||||
playerPc.getFirstAvailablePosition()
|
||||
?: throw SimpleCommandExceptionType(STORAGE_IS_FULL_EXCEPTION.red()).create()
|
||||
|
||||
} else {
|
||||
val pcBox = playerPc.boxes.get(box - 1)
|
||||
pcBox.getFirstAvailablePosition()
|
||||
?: throw SimpleCommandExceptionType(BOX_IS_FULL_EXCEPTION(box).red()).create()
|
||||
|
||||
}
|
||||
|
||||
playerParty.remove(pokemon)
|
||||
playerPc[pcPosition] = pokemon
|
||||
|
||||
// Let the client(s) know about the change to party
|
||||
playerParty.sendPacketToObservers(
|
||||
RemoveClientPokemonPacket(player.party(), pokemon.uuid)
|
||||
)
|
||||
}
|
||||
|
||||
// Let the call know how many Pokemon were moved to the PC
|
||||
return pokemons.size
|
||||
}
|
||||
}
|
||||
@@ -50,8 +50,8 @@ object SpawnPokemon {
|
||||
dispatcher.register(contextPositionCommand.alias(ALIAS))
|
||||
val argumentPositionCommand = dispatcher.register(literal(AT_NAME)
|
||||
.permission(CobblemonPermissions.SPAWN_POKEMON)
|
||||
.then(argument(PROPERTIES, PokemonPropertiesArgumentType.properties())
|
||||
.then(argument(POSITION, Vec3ArgumentType.vec3())
|
||||
.then(argument(POSITION, Vec3ArgumentType.vec3())
|
||||
.then(argument(PROPERTIES, PokemonPropertiesArgumentType.properties())
|
||||
.executes { context -> execute(context, Vec3ArgumentType.getVec3(context, POSITION)) }
|
||||
)
|
||||
)
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.command
|
||||
|
||||
import com.cobblemon.mod.common.api.permission.CobblemonPermissions
|
||||
import com.cobblemon.mod.common.api.spawning.CobblemonWorldSpawnerManager
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnCause
|
||||
import com.cobblemon.mod.common.api.spawning.context.AreaSpawningContext
|
||||
import com.cobblemon.mod.common.api.text.green
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.util.alias
|
||||
import com.cobblemon.mod.common.util.commandLang
|
||||
import com.cobblemon.mod.common.util.permission
|
||||
import com.mojang.brigadier.CommandDispatcher
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType
|
||||
import com.mojang.brigadier.context.CommandContext
|
||||
import net.minecraft.server.command.CommandManager
|
||||
import net.minecraft.server.command.CommandManager.literal
|
||||
import net.minecraft.server.command.ServerCommandSource
|
||||
import net.minecraft.text.Text
|
||||
|
||||
/**
|
||||
* Spawn Pokemon From Surrounding Pool
|
||||
*
|
||||
* `/spawnpokemonfrompool [amount]` or the alias `/forcespawn [amount]`
|
||||
*
|
||||
* This command can fail if the randomly selection spawn region has no possible [AreaSpawningContext]. For example if
|
||||
* you are flying in the air
|
||||
*/
|
||||
object SpawnPokemonFromPool {
|
||||
const val NAME = "spawnpokemonfrompool"
|
||||
const val ALIAS = "forcespawn"
|
||||
|
||||
private val UNABLE_TO_SPAWN = commandLang("spawnpokemonfrompool.unable_to_spawn")
|
||||
|
||||
fun register(dispatcher: CommandDispatcher<ServerCommandSource>) {
|
||||
val spawnPokemonFromPoolCommand = dispatcher.register(literal(NAME)
|
||||
.permission(CobblemonPermissions.SPAWN_POKEMON)
|
||||
.then(CommandManager.argument("amount", IntegerArgumentType.integer(1))
|
||||
.executes { context -> execute(context, IntegerArgumentType.getInteger(context, "amount")) }
|
||||
)
|
||||
.executes { context -> execute(context, 1) }
|
||||
)
|
||||
|
||||
dispatcher.register(spawnPokemonFromPoolCommand.alias(ALIAS))
|
||||
}
|
||||
|
||||
private fun execute(context: CommandContext<ServerCommandSource>, amount: Int): Int {
|
||||
val player = context.source.playerOrThrow
|
||||
val spawner = CobblemonWorldSpawnerManager.spawnersForPlayers.getValue(player.uuid)
|
||||
|
||||
var spawnsTriggered = 0
|
||||
|
||||
// This could instead directly use a [Spawner] method if refactored, as it is currently it has
|
||||
// entity counting coupled to the generation of a entity to spawn. Might be a good future change?
|
||||
for (i in 1..amount) {
|
||||
val spawnCause = SpawnCause(spawner = spawner, bucket = spawner.chooseBucket(), entity = spawner.getCauseEntity())
|
||||
|
||||
val area = spawner.getArea(spawnCause) ?: continue
|
||||
val slice = spawner.prospector.prospect(spawner, area)
|
||||
val contexts = spawner.resolver.resolve(spawner, spawner.contextCalculators, slice)
|
||||
|
||||
// This has a chance to fail, if you get a "slice" that has no associated contexts.
|
||||
// but as it was selected at random by the Prospector, it could just be a miss which
|
||||
// means two attempts to spawn in the same location can have differing results (which is expected for
|
||||
// randomness).
|
||||
if (contexts.isEmpty()) {
|
||||
player.sendMessage(UNABLE_TO_SPAWN.red())
|
||||
continue
|
||||
}
|
||||
|
||||
val result = spawner.getSpawningSelector().select(spawner, contexts)
|
||||
if (result == null) {
|
||||
player.sendMessage(UNABLE_TO_SPAWN.red())
|
||||
continue
|
||||
}
|
||||
|
||||
val spawnAction = result.second.doSpawn(ctx = result.first)
|
||||
|
||||
spawnAction.entity.subscribe {
|
||||
player.sendMessage(commandLang("spawnpokemonfrompool", it.displayName).green())
|
||||
}
|
||||
|
||||
spawner.performSpawn(spawnAction)
|
||||
spawnsTriggered++
|
||||
}
|
||||
|
||||
return spawnsTriggered
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,10 @@
|
||||
|
||||
package com.cobblemon.mod.common.command
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.moves.BenchedMove
|
||||
import com.cobblemon.mod.common.api.permission.CobblemonPermissions
|
||||
import com.cobblemon.mod.common.api.pokemon.moves.LearnsetQuery
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.command.argument.MoveArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PartySlotArgumentType
|
||||
@@ -31,7 +33,8 @@ object TeachCommand {
|
||||
private const val PLAYER = "player"
|
||||
private const val SLOT = "slot"
|
||||
private const val MOVE = "move"
|
||||
private val ALREAD_KNOWS_EXCEPTION = Dynamic2CommandExceptionType { a, b -> commandLang("$NAME.already_knows", a, b).red() }
|
||||
private val ALREADY_KNOWS_EXCEPTION = Dynamic2CommandExceptionType { a, b -> commandLang("$NAME.already_knows", a, b).red() }
|
||||
private val CANT_LEARN_EXCEPTION = Dynamic2CommandExceptionType { a, b -> commandLang("$NAME.cant_learn", a, b).red() }
|
||||
|
||||
fun register(dispatcher : CommandDispatcher<ServerCommandSource>) {
|
||||
val command = CommandManager.literal(NAME)
|
||||
@@ -46,18 +49,31 @@ object TeachCommand {
|
||||
}
|
||||
|
||||
private fun execute(context: CommandContext<ServerCommandSource>, player: ServerPlayerEntity) : Int {
|
||||
val pokemon = PartySlotArgumentType.getPokemon(context, SLOT)
|
||||
val pokemon = PartySlotArgumentType.getPokemonOf(context, SLOT, player)
|
||||
val move = MoveArgumentType.getMove(context, MOVE)
|
||||
if (pokemon.moveSet.getMoves().any { it.template == move } || pokemon.benchedMoves.any { it.moveTemplate == move }) {
|
||||
throw ALREAD_KNOWS_EXCEPTION.create(pokemon.displayName, move.displayName)
|
||||
|
||||
if (!Cobblemon.permissionValidator.hasPermission(context.source, CobblemonPermissions.TEACH_BYPASS_LEARNSET) && !LearnsetQuery.ANY.canLearn(move, pokemon.form.moves)) {
|
||||
throw CANT_LEARN_EXCEPTION.create(pokemon.displayName, move.displayName)
|
||||
}
|
||||
|
||||
if (pokemon.moveSet.getMoves().any { it.template == move } || pokemon.benchedMoves.any { it.moveTemplate == move }) {
|
||||
throw ALREADY_KNOWS_EXCEPTION.create(pokemon.displayName, move.displayName)
|
||||
}
|
||||
|
||||
if (pokemon.moveSet.hasSpace()) {
|
||||
pokemon.moveSet.add(move.create())
|
||||
}
|
||||
else {
|
||||
pokemon.benchedMoves.add(BenchedMove(move, 0))
|
||||
}
|
||||
context.source.sendFeedback(commandLang(NAME, pokemon.species.translatedName, player.name, move.displayName), true)
|
||||
|
||||
val pokemonLearntMessage = commandLang(NAME, pokemon.species.translatedName, player.name, move.displayName)
|
||||
context.source.sendFeedback(pokemonLearntMessage, true)
|
||||
|
||||
if (context.source.player?.equals(player) != true) {
|
||||
player.sendMessage(pokemonLearntMessage)
|
||||
}
|
||||
|
||||
return Command.SINGLE_SUCCESS
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ import java.util.concurrent.CompletableFuture
|
||||
import net.minecraft.command.CommandSource
|
||||
import net.minecraft.server.command.ServerCommandSource
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.text.Text
|
||||
|
||||
class PartySlotArgumentType : ArgumentType<Int> {
|
||||
|
||||
override fun parse(reader: StringReader): Int {
|
||||
|
||||
@@ -21,11 +21,15 @@ import com.cobblemon.mod.common.api.pokemon.feature.SpeciesFeatureAssignments
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.SpeciesFeatures
|
||||
import com.cobblemon.mod.common.api.spawning.CobblemonSpawnPools
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnDetailPresets
|
||||
import com.cobblemon.mod.common.net.messages.client.data.UnlockReloadPacket
|
||||
import com.cobblemon.mod.common.pokemon.SpeciesAdditions
|
||||
import com.cobblemon.mod.common.pokemon.properties.PropertiesCompletionProvider
|
||||
import com.cobblemon.mod.common.util.getServer
|
||||
import com.cobblemon.mod.common.util.ifClient
|
||||
import dev.architectury.registry.ReloadListenerRegistry
|
||||
import java.util.UUID
|
||||
import net.minecraft.resource.ResourceManager
|
||||
import net.minecraft.resource.ResourceType
|
||||
import net.minecraft.resource.SynchronousResourceReloader
|
||||
import net.minecraft.server.network.ServerPlayerEntity
|
||||
import net.minecraft.util.Identifier
|
||||
@@ -33,7 +37,8 @@ import net.minecraft.util.Identifier
|
||||
object CobblemonDataProvider : DataProvider {
|
||||
|
||||
// Both Forge n Fabric keep insertion order so if a registry depends on another simply register it after
|
||||
var canReload = true
|
||||
internal var canReload = true
|
||||
// Both Forge n Fabric keep insertion order so if a registry depends on another simply register it after
|
||||
private val registries = mutableListOf<DataRegistry>()
|
||||
private val synchronizedPlayerIds = mutableListOf<UUID>()
|
||||
|
||||
@@ -53,7 +58,15 @@ object CobblemonDataProvider : DataProvider {
|
||||
|
||||
CobblemonSpawnPools.load()
|
||||
|
||||
CobblemonEvents.PLAYER_QUIT.subscribe { synchronizedPlayerIds.remove(it.uuid) }
|
||||
ifClient(){
|
||||
ReloadListenerRegistry.register(ResourceType.CLIENT_RESOURCES, SimpleResourceReloader(ResourceType.CLIENT_RESOURCES))
|
||||
}
|
||||
ReloadListenerRegistry.register(ResourceType.SERVER_DATA, SimpleResourceReloader(ResourceType.SERVER_DATA))
|
||||
|
||||
CobblemonEvents.PLAYER_QUIT.subscribe {
|
||||
UnlockReloadPacket().sendToPlayer(it)
|
||||
synchronizedPlayerIds.remove(it.uuid)
|
||||
}
|
||||
}
|
||||
|
||||
override fun <T : DataRegistry> register(registry: T): T {
|
||||
@@ -61,7 +74,6 @@ object CobblemonDataProvider : DataProvider {
|
||||
if (this.registries.isEmpty()) {
|
||||
LOGGER.info("Note: Cobblemon data registries are only loaded once per server instance as Pokémon species are not safe to reload.")
|
||||
}
|
||||
ReloadListenerRegistry.register(registry.type, SimpleResourceReloader(registry))
|
||||
this.registries.add(registry)
|
||||
LOGGER.info("Registered the {} registry", registry.id.toString())
|
||||
LOGGER.debug("Registered the {} registry of class {}", registry.id.toString(), registry::class.qualifiedName)
|
||||
@@ -88,11 +100,18 @@ object CobblemonDataProvider : DataProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private class SimpleResourceReloader(private val registry: DataRegistry) : SynchronousResourceReloader {
|
||||
private class SimpleResourceReloader(private val type: ResourceType) : SynchronousResourceReloader {
|
||||
override fun reload(manager: ResourceManager) {
|
||||
if (canReload) {
|
||||
this.registry.reload(manager)
|
||||
// Check for a server running, this is due to the create a world screen triggering datapack reloads, these are fine to happen as many times as needed as players may be in the process of adding their datapacks.
|
||||
val isInGame = getServer() != null
|
||||
if (isInGame && this.type == ResourceType.SERVER_DATA && !canReload) {
|
||||
return
|
||||
}
|
||||
registries.filter { it.type == this.type }
|
||||
.forEach { it.reload(manager) }
|
||||
if (isInGame && this.type == ResourceType.SERVER_DATA) {
|
||||
canReload = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+19
-14
@@ -43,7 +43,6 @@ import com.cobblemon.mod.common.util.setPositionSafely
|
||||
import dev.architectury.extensions.network.EntitySpawnExtension
|
||||
import dev.architectury.networking.NetworkManager
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import net.minecraft.entity.EntityDimensions
|
||||
import net.minecraft.entity.EntityPose
|
||||
import net.minecraft.entity.EntityType
|
||||
@@ -293,11 +292,11 @@ class EmptyPokeBallEntity : ThrownItemEntity, Poseable, EntitySpawnExtension {
|
||||
}
|
||||
|
||||
private fun shakeBall(task: ScheduledTask, rollsRemaining: Int, captureResult: CaptureContext) {
|
||||
if (capturingPokemon?.isAlive != true) {
|
||||
discard()
|
||||
}
|
||||
|
||||
if (!isAlive) {
|
||||
if (this.capturingPokemon?.isAlive != true || !this.isAlive || this.owner == null|| owner?.isAlive != true) {
|
||||
if (this.capturingPokemon?.isAlive == true) {
|
||||
this.breakFree()
|
||||
}
|
||||
this.discard()
|
||||
task.expire()
|
||||
return
|
||||
}
|
||||
@@ -312,14 +311,17 @@ class EmptyPokeBallEntity : ThrownItemEntity, Poseable, EntitySpawnExtension {
|
||||
val player = this.owner as? ServerPlayerEntity ?: return
|
||||
|
||||
afterOnMain(seconds = 1F) {
|
||||
pokemon.discard()
|
||||
discard()
|
||||
captureFuture.complete(true)
|
||||
val party = Cobblemon.storage.getParty(player.uuid)
|
||||
pokemon.pokemon.caughtBall = pokeBall
|
||||
pokeBall.effects.forEach { effect -> effect.apply(player, pokemon.pokemon) }
|
||||
party.add(pokemon.pokemon)
|
||||
CobblemonEvents.POKEMON_CAPTURED.post(PokemonCapturedEvent(pokemon.pokemon, player))
|
||||
// Dupes occurred by double-adding Pokémon, this hopefully prevents it triple-condom style
|
||||
if (pokemon.pokemon.isWild() && pokemon.isAlive && !captureFuture.isDone) {
|
||||
pokemon.discard()
|
||||
discard()
|
||||
captureFuture.complete(true)
|
||||
val party = Cobblemon.storage.getParty(player.uuid)
|
||||
pokemon.pokemon.caughtBall = pokeBall
|
||||
pokeBall.effects.forEach { effect -> effect.apply(player, pokemon.pokemon) }
|
||||
party.add(pokemon.pokemon)
|
||||
CobblemonEvents.POKEMON_CAPTURED.post(PokemonCapturedEvent(pokemon.pokemon, player))
|
||||
}
|
||||
}
|
||||
return
|
||||
} else {
|
||||
@@ -415,4 +417,7 @@ class EmptyPokeBallEntity : ThrownItemEntity, Poseable, EntitySpawnExtension {
|
||||
override fun getPoseType(): PoseType {
|
||||
return PoseType.NONE
|
||||
}
|
||||
|
||||
override fun canUsePortals() = false
|
||||
|
||||
}
|
||||
@@ -53,9 +53,7 @@ import com.cobblemon.mod.common.util.*
|
||||
import dev.architectury.extensions.network.EntitySpawnExtension
|
||||
import dev.architectury.networking.NetworkManager
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.entity.EntityDimensions
|
||||
import net.minecraft.entity.EntityPose
|
||||
import net.minecraft.entity.EntityType
|
||||
import net.minecraft.entity.*
|
||||
import net.minecraft.entity.ai.control.MoveControl
|
||||
import net.minecraft.entity.ai.goal.EatGrassGoal
|
||||
import net.minecraft.entity.ai.goal.Goal
|
||||
@@ -98,7 +96,7 @@ class PokemonEntity(
|
||||
world: World,
|
||||
pokemon: Pokemon = Pokemon(),
|
||||
type: EntityType<out PokemonEntity> = CobblemonEntities.POKEMON.get(),
|
||||
) : TameableShoulderEntity(type, world), EntitySpawnExtension, Poseable {
|
||||
) : TameableShoulderEntity(type, world), EntitySpawnExtension, Poseable, Shearable {
|
||||
val removalObservable = SimpleObservable<RemovalReason?>()
|
||||
/** A list of observable subscriptions related to this entity that need to be cleaned up when the entity is removed. */
|
||||
val subscriptions = mutableListOf<ObservableSubscription<*>>()
|
||||
@@ -270,7 +268,7 @@ class PokemonEntity(
|
||||
* Prevents fire type Pokémon from taking fire damage.
|
||||
*/
|
||||
override fun isFireImmune(): Boolean {
|
||||
return FIRE in pokemon.types || behaviour.moving.swim.canSwimInLava
|
||||
return FIRE in pokemon.types || !behaviour.moving.swim.hurtByLava
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -419,40 +417,13 @@ class PokemonEntity(
|
||||
override fun interactMob(player: PlayerEntity, hand: Hand) : ActionResult {
|
||||
val itemStack = player.getStackInHand(hand)
|
||||
if (player is ServerPlayerEntity) {
|
||||
if (itemStack.isOf(Items.SHEARS)) {
|
||||
val feature = pokemon.getFeature<FlagSpeciesFeature>(DataKeys.HAS_BEEN_SHEARED)
|
||||
val isShearable = feature?.enabled == false
|
||||
if (isShearable) {
|
||||
feature!!
|
||||
world.playSoundFromEntity(
|
||||
null,
|
||||
this,
|
||||
SoundEvents.ENTITY_SHEEP_SHEAR,
|
||||
SoundCategory.PLAYERS,
|
||||
1.0F,
|
||||
1.0F
|
||||
)
|
||||
val i = 1 + random.nextInt(3)
|
||||
|
||||
for (j in 0 until i) {
|
||||
val itemEntity = this.dropItem(Items.WHITE_WOOL, 1)
|
||||
if (itemEntity != null) {
|
||||
itemEntity.velocity = itemEntity.velocity.add(
|
||||
((random.nextFloat() - random.nextFloat()) * 0.1f).toDouble(),
|
||||
(random.nextFloat() * 0.05f).toDouble(),
|
||||
((random.nextFloat() - random.nextFloat()) * 0.1f).toDouble()
|
||||
)
|
||||
}
|
||||
}
|
||||
this.emitGameEvent(GameEvent.SHEAR, player)
|
||||
itemStack.damage(1, player) { it.sendToolBreakStatus(hand) }
|
||||
feature.enabled = true
|
||||
pokemon.markFeatureDirty(feature)
|
||||
pokemon.updateAspects()
|
||||
return ActionResult.SUCCESS
|
||||
}
|
||||
if (itemStack.isOf(Items.SHEARS) && this.isShearable) {
|
||||
this.sheared(SoundCategory.PLAYERS)
|
||||
this.emitGameEvent(GameEvent.SHEAR, player)
|
||||
itemStack.damage(1, player) { it.sendToolBreakStatus(hand) }
|
||||
return ActionResult.SUCCESS
|
||||
}
|
||||
if (itemStack.isOf(Items.BUCKET)) {
|
||||
else if (itemStack.isOf(Items.BUCKET)) {
|
||||
if (pokemon.getFeature<FlagSpeciesFeature>(DataKeys.CAN_BE_MILKED) != null) {
|
||||
world.playSoundFromEntity(
|
||||
null,
|
||||
@@ -646,9 +617,8 @@ class PokemonEntity(
|
||||
returned.isEmpty -> lang("held_item.give", this.pokemon.displayName, giving.name)
|
||||
else -> lang("held_item.replace", returned.name, this.pokemon.displayName, giving.name)
|
||||
}
|
||||
player.giveItemStack(returned)
|
||||
player.giveOrDropItemStack(returned)
|
||||
player.sendMessage(text)
|
||||
this.world.playSoundServer(position = this.pos, sound = SoundEvents.ENTITY_ITEM_PICKUP, volume = 0.7F, pitch = 1.4F)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -704,7 +674,8 @@ class PokemonEntity(
|
||||
}
|
||||
|
||||
override fun updatePostDeath() {
|
||||
super.updatePostDeath()
|
||||
// Do not invoke super we need to keep a tight lid on this due to the Thorium mod forcing the ticks to a max of 20 on server side if we invoke a field update here
|
||||
// Client delegate is mimicking expected behavior on client end.
|
||||
delegate.updatePostDeath()
|
||||
}
|
||||
|
||||
@@ -860,4 +831,27 @@ class PokemonEntity(
|
||||
|
||||
override fun breed(world: ServerWorld, other: AnimalEntity) {}
|
||||
|
||||
override fun sheared(shearedSoundCategory: SoundCategory) {
|
||||
this.world.playSoundFromEntity(null, this,SoundEvents.ENTITY_SHEEP_SHEAR, shearedSoundCategory, 1.0F, 1.0F)
|
||||
val feature = this.pokemon.getFeature<FlagSpeciesFeature>(DataKeys.HAS_BEEN_SHEARED) ?: return
|
||||
feature.enabled = true
|
||||
this.pokemon.markFeatureDirty(feature)
|
||||
this.pokemon.updateAspects()
|
||||
val i = this.random.nextInt(3)
|
||||
for (j in 0 until i) {
|
||||
val itemEntity = this.dropItem(Items.WHITE_WOOL, 1) ?: return
|
||||
itemEntity.velocity = itemEntity.velocity.add(
|
||||
((this.random.nextFloat() - this.random.nextFloat()) * 0.1f).toDouble(),
|
||||
(this.random.nextFloat() * 0.05f).toDouble(),
|
||||
((this.random.nextFloat() - this.random.nextFloat()) * 0.1f).toDouble()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun isShearable(): Boolean {
|
||||
val feature = this.pokemon.getFeature<FlagSpeciesFeature>(DataKeys.HAS_BEEN_SHEARED) ?: return false
|
||||
return !this.isBusy && !this.pokemon.isFainted() && !feature.enabled
|
||||
}
|
||||
|
||||
override fun canUsePortals() = false
|
||||
}
|
||||
+2
-2
@@ -176,7 +176,7 @@ class PokemonServerDelegate : PokemonSideDelegate {
|
||||
}
|
||||
++entity.deathTime
|
||||
|
||||
if (entity.deathTime == 60) {
|
||||
if (entity.deathTime == 30) {
|
||||
val owner = entity.owner
|
||||
if (owner != null) {
|
||||
entity.world.playSoundServer(owner.pos, CobblemonSounds.POKE_BALL_RECALL.get(), volume = 0.2F)
|
||||
@@ -185,7 +185,7 @@ class PokemonServerDelegate : PokemonSideDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
if (entity.deathTime == 120) {
|
||||
if (entity.deathTime == 60) {
|
||||
if (entity.owner == null) {
|
||||
entity.world.sendEntityStatus(entity, 60.toByte()) // Sends smoke effect
|
||||
(entity.drops ?: entity.pokemon.form.drops).drop(entity, entity.world as ServerWorld, entity.pos, entity.killer)
|
||||
|
||||
+2
-1
@@ -77,7 +77,8 @@ class PokemonNavigation(val world: World, val pokemonEntity: PokemonEntity) : Mo
|
||||
|
||||
override fun tick() {
|
||||
super.tick()
|
||||
val node = getCurrentPath()?.lastNode
|
||||
val currentPath = getCurrentPath()
|
||||
val node = if (currentPath == null || currentPath.isFinished) null else currentPath.lastNode
|
||||
|
||||
val isFlying = pokemonEntity.getBehaviourFlag(PokemonBehaviourFlag.FLYING)
|
||||
val canWalk = pokemonEntity.behaviour.moving.walk.canWalk
|
||||
|
||||
+1
-3
@@ -35,9 +35,7 @@ class PokemonInBattleMovementGoal(val entity: PokemonEntity, val range: Int) : G
|
||||
val closestPokemonEntity = getClosestPokemonEntity()
|
||||
if (closestPokemonEntity != null) {
|
||||
entity.navigation.stop()
|
||||
// entity.lookAt(EntityAnchorArgumentType.EntityAnchor.EYES, closestPokemonEntity.eyePos)
|
||||
entity.lookAtEntity(closestPokemonEntity, 30.0f, 30.0f)
|
||||
// entity.lookControl.lookAt(closestPokemonEntity.x, closestPokemonEntity.y, closestPokemonEntity.z)
|
||||
entity.lookControl.lookAt(closestPokemonEntity.x, closestPokemonEntity.eyeY, closestPokemonEntity.z)
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -45,7 +45,7 @@ class PokemonMoveIntoFluidGoal(private val mob: PokemonEntity) : Goal() {
|
||||
override fun start() {
|
||||
val appropriateFluids = mutableListOf<TagKey<Fluid>>()
|
||||
val swim = mob.behaviour.moving.swim
|
||||
if (swim.canSwimInLava) {
|
||||
if (swim.canSwimInLava && !swim.hurtByLava) {
|
||||
appropriateFluids.add(FluidTags.LAVA)
|
||||
}
|
||||
if (swim.canSwimInWater) {
|
||||
|
||||
@@ -36,6 +36,10 @@ class PokemonItem : CobblemonItem(Settings().maxCount(1)) {
|
||||
}
|
||||
}
|
||||
|
||||
fun getSpeciesAndAspects(stack: ItemStack): Pair<Species, Set<String>>? {
|
||||
return (species(stack) ?: return null) to (aspects(stack) ?: return null)
|
||||
}
|
||||
|
||||
fun asRenderablePokemon(stack: ItemStack): RenderablePokemon? = this.asPokemon(stack)?.asRenderablePokemon()
|
||||
|
||||
private fun species(stack: ItemStack): Species? {
|
||||
|
||||
@@ -20,7 +20,8 @@ class LinkCableItem : PokemonInteractiveItem(Settings().group(CobblemonItemGroup
|
||||
val pokemon = entity.pokemon
|
||||
pokemon.evolutions.filterIsInstance<TradeEvolution>().forEach { evolution ->
|
||||
// If an evolution is possible non-optional or has been successfully queued we will consume the item and stop
|
||||
if (evolution.evolve(pokemon)) {
|
||||
// validate requirements to respect required held items and such.
|
||||
if (evolution.requirements.all { it.check(pokemon) } && evolution.evolve(pokemon)) {
|
||||
this.consumeItem(player, stack)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ class PokemonDTO : Encodable, Decodable {
|
||||
this.status = pokemon.status?.status?.name
|
||||
this.state = pokemon.state
|
||||
this.caughtBall = pokemon.caughtBall.name
|
||||
this.benchedMoves = pokemon.benchedMoves
|
||||
this.aspects = pokemon.aspects
|
||||
evolutionBuffer = PacketByteBuf(Unpooled.buffer())
|
||||
pokemon.evolutionProxy.saveToBuffer(evolutionBuffer, toClient)
|
||||
|
||||
+3
-7
@@ -13,10 +13,6 @@ import com.cobblemon.mod.common.api.moves.Moves
|
||||
import com.cobblemon.mod.common.api.moves.categories.DamageCategories
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.battles.MoveTarget
|
||||
import com.cobblemon.mod.common.net.IntSize
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readSizedInt
|
||||
import com.cobblemon.mod.common.util.writeSizedInt
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
|
||||
class MovesRegistrySyncPacket : DataRegistrySyncPacket<MoveTemplate> {
|
||||
@@ -24,8 +20,8 @@ class MovesRegistrySyncPacket : DataRegistrySyncPacket<MoveTemplate> {
|
||||
constructor(moves: List<MoveTemplate>): super(moves)
|
||||
|
||||
override fun encodeEntry(buffer: PacketByteBuf, entry: MoveTemplate) {
|
||||
buffer.writeSizedInt(IntSize.U_SHORT, entry.id)
|
||||
buffer.writeString(entry.name)
|
||||
buffer.writeInt(entry.num)
|
||||
buffer.writeString(entry.elementalType.name)
|
||||
buffer.writeString(entry.damageCategory.name)
|
||||
buffer.writeDouble(entry.power)
|
||||
@@ -39,8 +35,8 @@ class MovesRegistrySyncPacket : DataRegistrySyncPacket<MoveTemplate> {
|
||||
}
|
||||
|
||||
override fun decodeEntry(buffer: PacketByteBuf): MoveTemplate {
|
||||
val id = buffer.readSizedInt(IntSize.U_SHORT)
|
||||
val name = buffer.readString()
|
||||
val num = buffer.readInt()
|
||||
val type = ElementalTypes.getOrException(buffer.readString())
|
||||
val damageCategory = DamageCategories.getOrException(buffer.readString())
|
||||
val power = buffer.readDouble()
|
||||
@@ -53,7 +49,7 @@ class MovesRegistrySyncPacket : DataRegistrySyncPacket<MoveTemplate> {
|
||||
repeat(buffer.readVarInt()) {
|
||||
effectChances += buffer.readDouble()
|
||||
}
|
||||
return MoveTemplate(name, type, damageCategory, power, target, accuracy, pp, priority, critRatio, effectChances.toTypedArray()).apply { this.id = id }
|
||||
return MoveTemplate(name, num, type, damageCategory, power, target, accuracy, pp, priority, critRatio, effectChances.toTypedArray())
|
||||
}
|
||||
|
||||
override fun synchronizeDecoded(entries: Collection<MoveTemplate>) {
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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.net.messages.client.data
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import net.minecraft.network.PacketByteBuf
|
||||
|
||||
internal class UnlockReloadPacket : NetworkPacket {
|
||||
override fun encode(buffer: PacketByteBuf) {}
|
||||
override fun decode(buffer: PacketByteBuf) {}
|
||||
}
|
||||
+12
-1
@@ -9,6 +9,8 @@
|
||||
package com.cobblemon.mod.common.net.serverhandling.storage.party
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.storage.ReleasePokemonEvent
|
||||
import com.cobblemon.mod.common.api.storage.pc.link.PCLinkManager
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.ReleasePCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.serverhandling.ServerPacketHandler
|
||||
@@ -22,6 +24,15 @@ object ReleasePCPokemonHandler : ServerPacketHandler<ReleasePCPokemonPacket> {
|
||||
return // Not what we expected
|
||||
}
|
||||
|
||||
pc.remove(packet.position)
|
||||
CobblemonEvents.POKEMON_RELEASED_EVENT_PRE.postThen(
|
||||
event = ReleasePokemonEvent.Pre(player, pokemon, pc),
|
||||
ifSucceeded = { preEvent ->
|
||||
pc.remove(packet.position)
|
||||
CobblemonEvents.POKEMON_RELEASED_EVENT_POST.post(ReleasePokemonEvent.Post(player, pokemon, pc))
|
||||
},
|
||||
ifCanceled = { preEvent ->
|
||||
pc[packet.position] = pokemon
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
+15
-4
@@ -9,6 +9,8 @@
|
||||
package com.cobblemon.mod.common.net.serverhandling.storage.pc
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.storage.ReleasePokemonEvent
|
||||
import com.cobblemon.mod.common.client.settings.ServerSettings
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.ReleasePartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.serverhandling.ServerPacketHandler
|
||||
@@ -23,10 +25,19 @@ object ReleasePartyPokemonHandler : ServerPacketHandler<ReleasePartyPokemonPacke
|
||||
return // Desync
|
||||
}
|
||||
|
||||
if (ServerSettings.preventCompletePartyDeposit && party.filterNotNull().size <= 1) {
|
||||
return // Don't allow empty party
|
||||
}
|
||||
CobblemonEvents.POKEMON_RELEASED_EVENT_PRE.postThen(
|
||||
event = ReleasePokemonEvent.Pre(player, pokemon, party),
|
||||
ifSucceeded = { preEvent ->
|
||||
if (ServerSettings.preventCompletePartyDeposit && party.filterNotNull().size <= 1) {
|
||||
return // Don't allow empty party
|
||||
}
|
||||
|
||||
party.remove(pokemon)
|
||||
party.remove(pokemon)
|
||||
CobblemonEvents.POKEMON_RELEASED_EVENT_POST.post(ReleasePokemonEvent.Post(player, pokemon, party))
|
||||
},
|
||||
ifCanceled = { preEvent ->
|
||||
party[packet.position] = pokemon
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user