mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-27 20:46:27 -04:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9309c53a40 |
+1
-2
@@ -39,5 +39,4 @@ common/src/main/resources/assets/cobblemon/showdown
|
||||
common/.fabric
|
||||
|
||||
# MacOS
|
||||
.DS_Store
|
||||
.kotlin/sessions/kotlin-compiler-16609242564043830292.salive
|
||||
.DS_Store
|
||||
@@ -1,3 +0,0 @@
|
||||
### Additions
|
||||
- Added the Poké Dex as a craftable item.
|
||||
- Poké Dexes can be placed on lecterns.
|
||||
+17
-71
@@ -60,16 +60,24 @@
|
||||
- Hidden Power now displays its effective typing.
|
||||
- Moves impacted by the abilities Pixelate, Refrigerate, Aerilate, Galvanize, and Normalize now display as their altered typing.
|
||||
- Added Polished Tumblestone and Tumblestone Brick block sets from Tumblestone, Black Tumblestone, and Sky Tumblestone.
|
||||
- Added Fire, Water, Thunder, Leaf, Ice, Sun, Moon, Shiny, Dawn, and Dusk Stone Storage Blocks.
|
||||
- Added Metronome, Protective Pads, Punching Glove, Room Service, Scope Lens, Shed Shell, Terrain Extender, Throat Spray, Utility Umbrella, Wide Lens, and Zoom Lens held items
|
||||
- Moves can now be benched without specifying a replacement move, allowing for empty move slots.
|
||||
- Moves learned via Sketch now persist after battle.
|
||||
- Added ston_henge_ruins, luna_henge_ruins, and sol_henge_ruins structures.
|
||||
- Added Eject Pack, Metronome, Protective Pads, Punching Glove, Room Service, Scope Lens, Shed Shell, Terrain Extender, Throat Spray, Utility Umbrella, Wide Lens, and Zoom Lens held items
|
||||
- Added a `battleInvulnerability` gamerule to make players invulnerable to any damage during a battle
|
||||
- Added a `mobTargetInBattle` gamerule to exclude players from being targeted by mobs during a battle
|
||||
- Added battle log messages for switching out Pokémon
|
||||
- Added Evolution particles and sounds for Pokemon that are sent out when evolution is started.
|
||||
|
||||
### Added cries to the following Pokémon
|
||||
- Timburr, Gurdurr, Conkeldurr
|
||||
- Golett, Golurk
|
||||
|
||||
### Changes
|
||||
- Altered the item model for Medicinal Leeks and Roasted Leeks to be held like sticks and other rod items.
|
||||
- Adjusted some berry balance values like yield and growth times
|
||||
- Changes to mulch buffs/durations
|
||||
- Dreepy is now shoulder mountable
|
||||
- Link Cable recipe has been redesigned
|
||||
- Updated potion sprites
|
||||
- Weedle, Caterpie, Spearow, Smoochum, Mew, Murkrow, Larvitar, Taillow, Plusle, Minun, Beldum, Starly, Buneary, Combee, Pachirisu, Pidove, Petilil, Hisui Bias Petilil, Zorua, Hisuian Zorua, Elgyem, Fletchling, Skrelp, Klefki, Fomantis, Morelull, Dreepy, Shroodle, Tatsugiri, Glimmet, and Roaming Gimmighoul are now shoulder mountable
|
||||
- Chikorita's ability to look around removed due to the awkwardness of it.
|
||||
- Link Cable recipe has been redesigned
|
||||
- Updated potion sprites
|
||||
- Removed the interchangeable evolution results for the first stage Hisuian starters to prevent confusion. The method still exists for stage 2 to 3, but stage 1 to 2 was not distinguishable enough for many users.
|
||||
|
||||
### Pokémon Added
|
||||
#### Gen 2
|
||||
@@ -86,72 +94,10 @@
|
||||
#### Gen 9
|
||||
- Farigiraf
|
||||
|
||||
### Added cries to the following Pokémon
|
||||
- Timburr, Gurdurr, Conkeldurr
|
||||
- Golett, Golurk
|
||||
|
||||
### Changes
|
||||
- Altered the item model for Medicinal Leeks and Roasted Leeks to be held like sticks and other rod items.
|
||||
- Adjusted some berry balance values like yield and growth times
|
||||
- Adjusted volumes of sounds made by Display Cases, Berry Bushes, Energy Root, Medicinal Leek, Vivichoke, Mints, Revival Herbs and Gilded Chests.
|
||||
- Changes to mulch buffs/durations
|
||||
- Dreepy is now shoulder mountable
|
||||
- Link Cable recipe has been redesigned
|
||||
- Updated potion sprites
|
||||
- Weedle, Caterpie, Spearow, Smoochum, Mew, Murkrow, Larvitar, Taillow, Plusle, Minun, Beldum, Starly, Buneary, Combee, Pachirisu, Pidove, Petilil, Hisui Bias Petilil, Zorua, Hisuian Zorua, Elgyem, Fletchling, Skrelp, Klefki, Fomantis, Morelull, Dreepy, Shroodle, Tatsugiri, Glimmet, and Roaming Gimmighoul are now shoulder mountable
|
||||
- Chikorita's ability to look around removed due to the awkwardness of it.
|
||||
- Link Cable recipe has been redesigned
|
||||
- Updated potion sprites
|
||||
- Updated sounds for Medicinal Leeks, Big Roots, Energy Roots and Revival Herbs
|
||||
- Updated UI sounds for clicking and evolving Pokémon
|
||||
- Removed the interchangeable evolution results for the first stage Hisuian starters to prevent confusion. The method still exists for stage 2 to 3, but stage 1 to 2 was not distinguishable enough for many users.
|
||||
- Kakuna, Beedrill, Snorlax, Munchlax, and Lurantis received model updates
|
||||
|
||||
### Fixes
|
||||
- Fixed trading Pokémon setting their friendsip to 0 instead of the base value.
|
||||
- Fixed a scenario where a Pokémon that rolled to spawn with a special Tera type sometimes has a Tera type that is already a part of their natural typing.
|
||||
- Fixed PokemonProperty argument suggestions for ``tera`` and ``tera_type`` not suggesting ``stellar``.
|
||||
- Fixed being able to stack Relic Coin Pouches on top of each other.
|
||||
- Fixed Model loader generating misleading crash-reports when client is crashing
|
||||
- Scaled down Amaura's fetus model to avoid clipping through the tank while animating
|
||||
- Big Roots and Energy Roots now share the same sounds as intented.
|
||||
- Fixed Cubone's cry not having a sound.
|
||||
- Fixed sounds made by blocks playing at a lower pitch than intended.
|
||||
- Fixed the Seafloor spawning context not being a usable context.
|
||||
- Fixed Pokemon spawning in non-full blocks like slabs.
|
||||
- Fixed Gilded Chests not dropping the chest itself when broken, only the contents.
|
||||
- Fixed Pokémon losing their Hidden Ability through evolution if the middle stage did not have a Hidden Ability.
|
||||
- Hidden Power no longer plays the water type action effect. (It now plays the normal type action effect.)
|
||||
- Fixed Chimchar and Monferno T posing whenever they sleep.
|
||||
- Fixed the Magby line not having any placeholder walk animations.
|
||||
- Fixed Duskull and Dusclops using skylight levels for their nether spawn data. There is no sun in the Nether!
|
||||
- Fixed Hisuian Zoroark using base Zoroark stats.
|
||||
- Fixed Bellossom clipping into the player head when shoulder mounted.
|
||||
- Fixed Shroomish's look range to prevent it from looking higher than it should.
|
||||
- Fixed Crumbling Arch not blending in with the world.
|
||||
- Fixed Energy Root applying being usable on a fainted Pokemon.
|
||||
- Fixed Pokémon entity not spawning when starting a battle while recalling said Pokémon
|
||||
- Fixed species comparison not using namespace for both sides in PokemonProperties.isSubsetOf.
|
||||
- Fixed PokemonProperties#asString prefixing nicknames with a '$'
|
||||
- Fixed reviving items throwing an exception when used in battle
|
||||
- Fixed messages for Focus Sash, Confusion, Mummy, Ice Face, Own Tempo, and Revive
|
||||
- Fixed PC not saving when Pokemon was changed outside.
|
||||
- Fixed shearble Pokemon not dropping correct wool colors.
|
||||
- Fixed pasture spawning Pokemon inside solid blocks when closest spawning position is blocked off.
|
||||
- Fixed Tumbling Down advancement not being granted by tumblestone variants.
|
||||
- Improve error handling when loading spawn-sets to ensure invalid configurations don't crash the server
|
||||
- Fixed empty JsonPlayerData files resulting in players being unable to join server/world
|
||||
- Fixed crumbling_arch_ruins from generating a giant cube of air and removed the chest
|
||||
- Fixed possible crash on large population servers due to concurrent access of data.
|
||||
|
||||
### Developer
|
||||
- SpawnCause is now an implementation of SpawningInfluence.
|
||||
- Added "forcedAspects" to Pokemon to make it easier to easily add basic aspects to a Pokémon in a way that persists. We already know that everyone is going to overuse this.
|
||||
- Made the Pokemon.aspects setter private. This could technically break sidemods but if you are affected by this then you were using it wrong! Use Pokemon.forcedAspects to fix it.
|
||||
- Many types related to ``Pokemon`` including itself now have dedicated ``Codec``, please migrate to them from the NBT/JSON/PacketBuffer write/read methods.
|
||||
- ``TeraTypes`` now implements ``Iterable``.
|
||||
- PokemonBattle now starts on turn 0.
|
||||
- All sounds related to evolving Pokémon have been moved to the "sounds/evolution" folder.
|
||||
|
||||
### Data Pack & Resource Pack Creators
|
||||
- Added support for "shedders" similar to Shedinja's evolution logic.
|
||||
|
||||
@@ -40,7 +40,7 @@ dependencies {
|
||||
modApi(libs.molang)
|
||||
|
||||
// Integrations
|
||||
compileOnlyApi(libs.jei.api)
|
||||
// compileOnlyApi(libs.jei.api)
|
||||
modCompileOnly(libs.bundles.fabric.integrations.compileOnly) {
|
||||
isTransitive = false
|
||||
}
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonBakingOverrides;
|
||||
import com.cobblemon.mod.common.item.PokedexItem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.renderer.ItemModelShaper;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.entity.ItemRenderer;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.world.item.ItemDisplayContext;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/*
|
||||
I think it would be nice to maybe use the existing mixin we have for custom item rendering [BuiltinModelItemRendererMixin]
|
||||
Obviously that would require changes. Potentially each item renderer defines what modes it overrides for?
|
||||
*/
|
||||
@Mixin(ItemRenderer.class)
|
||||
public abstract class ItemRendererMixin {
|
||||
|
||||
@Shadow @Final private ItemModelShaper itemModelShaper;
|
||||
|
||||
@Shadow public abstract void render(ItemStack stack, ItemDisplayContext renderMode, boolean leftHanded, PoseStack matrices, MultiBufferSource vertexConsumers, int light, int overlay, BakedModel model);
|
||||
|
||||
@Inject(
|
||||
method = "Lnet/minecraft/client/renderer/entity/ItemRenderer;render(Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemDisplayContext;ZLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;IILnet/minecraft/client/resources/model/BakedModel;)V",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true
|
||||
)
|
||||
private void cobblemon$overridePokedexModel(ItemStack stack, ItemDisplayContext renderMode, boolean leftHanded, PoseStack matrices, MultiBufferSource multiBufferSource, int i, int j, BakedModel model, CallbackInfo ci) {
|
||||
boolean shouldOverride = renderMode != ItemDisplayContext.GUI && renderMode != ItemDisplayContext.FIXED;
|
||||
if (shouldOverride && stack.getItem() instanceof PokedexItem) {
|
||||
BakedModel replacementModel = CobblemonBakingOverrides.INSTANCE.getPokedexOverride(((PokedexItem) stack.getItem()).getType()).getModel();
|
||||
if (!model.equals(replacementModel)) {
|
||||
ci.cancel();
|
||||
render(stack, renderMode, leftHanded, matrices, multiBufferSource, i, j, replacementModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonBakingOverrides;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import net.minecraft.client.color.block.BlockColors;
|
||||
@@ -19,6 +20,8 @@ import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.client.resources.model.UnbakedModel;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
import org.slf4j.Logger;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -28,10 +31,16 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(ModelBakery.class)
|
||||
public abstract class ModelLoaderMixin {
|
||||
|
||||
@Shadow abstract UnbakedModel getModel(ResourceLocation resourceLocation);
|
||||
|
||||
@Shadow protected abstract void registerModel(ModelResourceLocation modelId, UnbakedModel unbakedModel);
|
||||
|
||||
@Final
|
||||
@Shadow
|
||||
private Map<ResourceLocation, UnbakedModel> unbakedCache;
|
||||
|
||||
@Final
|
||||
@Shadow
|
||||
private static Logger LOGGER;
|
||||
|
||||
@Inject(
|
||||
method = "<init>",
|
||||
at = @At("TAIL")
|
||||
@@ -42,8 +51,19 @@ public abstract class ModelLoaderMixin {
|
||||
Map<ResourceLocation, List<BlockStateModelLoader.LoadedJson>> blockStates,
|
||||
CallbackInfo ci) {
|
||||
CobblemonBakingOverrides.INSTANCE.getModels().forEach(bakingOverride -> {
|
||||
var unbakedModel = this.getModel(bakingOverride.getModelLocation());
|
||||
this.registerModel(bakingOverride.getModelIdentifier(), unbakedModel);
|
||||
try {
|
||||
BlockModel unbakedModel = this.loadBlockModel(bakingOverride.getModelLocation());
|
||||
this.unbakedCache.put(bakingOverride.getModelIdentifier().id(), unbakedModel);
|
||||
this.registerModel(bakingOverride.getModelIdentifier(), unbakedModel);
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Error loading a Cobblemon BakedModel:", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Shadow
|
||||
private BlockModel loadBlockModel(ResourceLocation id) throws IOException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,8 @@ package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding;
|
||||
import com.cobblemon.mod.common.item.PokedexItem;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.MouseHandler;
|
||||
import net.minecraft.util.Mth;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -28,8 +23,6 @@ public class PartyScrollMixin {
|
||||
@Shadow
|
||||
private double accumulatedScrollY;
|
||||
|
||||
@Shadow @Final private Minecraft minecraft;
|
||||
|
||||
@Inject(
|
||||
method = "onScroll",
|
||||
at = @At(
|
||||
@@ -41,7 +34,7 @@ public class PartyScrollMixin {
|
||||
),
|
||||
cancellable = true
|
||||
)
|
||||
public void cobblemon$scrollParty(long window, double horizontal, double vertical, CallbackInfo ci) {
|
||||
public void onMouseScroll(long window, double horizontal, double vertical, CallbackInfo ci) {
|
||||
if (PartySendBinding.INSTANCE.getWasDown()) {
|
||||
int i = (int)accumulatedScrollY;
|
||||
if (i > 0) {
|
||||
@@ -57,21 +50,4 @@ public class PartyScrollMixin {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "onScroll",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/entity/player/Inventory;swapPaint(D)V"
|
||||
),
|
||||
cancellable = true
|
||||
)
|
||||
public void cobblemon$doPokedexZoom(long window, double horizontal, double vertical, CallbackInfo ci) {
|
||||
PokedexUsageContext usageContext = CobblemonClient.INSTANCE.getPokedexUsageContext();
|
||||
if (usageContext.getScanningGuiOpen()) {
|
||||
usageContext.adjustZoom(vertical);
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,18 +18,7 @@ import com.cobblemon.mod.common.api.tags.CobblemonItemTags;
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon;
|
||||
import com.cobblemon.mod.common.util.CompoundTagExtensionsKt;
|
||||
import com.cobblemon.mod.common.util.DataKeys;
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.food.FoodProperties;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
@@ -40,6 +29,15 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.food.FoodProperties;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
@Mixin(Player.class)
|
||||
public abstract class PlayerMixin extends LivingEntity {
|
||||
@@ -65,7 +63,7 @@ public abstract class PlayerMixin extends LivingEntity {
|
||||
super(p_20966_, p_20967_);
|
||||
}
|
||||
|
||||
@Inject(method = "respawnEntityOnShoulder", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntityType;create(Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/world/level/Level;)Ljava/util/Optional;"), cancellable = true)
|
||||
@Inject(method = "respawnEntityOnShoulder", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntityType;create(Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/world/Level;)Ljava/util/Optional;"), cancellable = true)
|
||||
private void cobblemon$removePokemon(CompoundTag nbt, CallbackInfo ci) {
|
||||
if (CompoundTagExtensionsKt.isPokemonEntity(nbt)) {
|
||||
final UUID uuid = this.getPokemonID(nbt);
|
||||
@@ -161,16 +159,4 @@ public abstract class PlayerMixin extends LivingEntity {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "isInvulnerableTo", at = @At("HEAD"), cancellable = true)
|
||||
public void isInvulnerableTo(DamageSource source, CallbackInfoReturnable<Boolean> ci) {
|
||||
if (!level().isClientSide) {
|
||||
ServerPlayer player = (ServerPlayer)(Object)this;
|
||||
boolean invulnerableInBattle = this.level().getGameRules().getBoolean(CobblemonGameRules.BATTLE_INVULNERABILITY);
|
||||
boolean inBattle = Cobblemon.INSTANCE.getBattleRegistry().getBattleByParticipatingPlayer(player) != null;
|
||||
if (invulnerableInBattle && inBattle) {
|
||||
ci.setReturnValue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.ai.targeting.TargetingConditions;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(TargetingConditions.class)
|
||||
public class TargetingConditionsMixin {
|
||||
|
||||
@Inject(method = "test", at = @At("HEAD"), cancellable = true)
|
||||
public void test(@Nullable LivingEntity baseEntity, LivingEntity targetEntity, CallbackInfoReturnable<Boolean> ci) {
|
||||
if (targetEntity instanceof ServerPlayer player) {
|
||||
boolean canTargetInBattle = player.level().getGameRules().getBoolean(CobblemonGameRules.MOB_TARGET_IN_BATTLE);
|
||||
boolean targetInBattle = Cobblemon.INSTANCE.getBattleRegistry().getBattleByParticipatingPlayer(player) != null;
|
||||
if (!canTargetInBattle && targetInBattle) ci.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.accessor;
|
||||
|
||||
import net.minecraft.client.gui.components.AbstractSelectionList;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(AbstractSelectionList.class)
|
||||
public interface EntryListWidgetAccessor {
|
||||
@Accessor("renderHeader")
|
||||
boolean getRenderHeader();
|
||||
}
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(AbstractClientPlayer.class)
|
||||
public class AbstractClientPlayerMixin {
|
||||
@Inject(
|
||||
method = "getFieldOfViewModifier()F",
|
||||
at = @At(
|
||||
value = "HEAD"
|
||||
),
|
||||
cancellable = true
|
||||
)
|
||||
public void cobblemon$getPokedexFovMultiplier(CallbackInfoReturnable<Float> cir) {
|
||||
PokedexUsageContext usageContext = CobblemonClient.INSTANCE.getPokedexUsageContext();
|
||||
if (usageContext.getScanningGuiOpen()) {
|
||||
cir.setReturnValue(usageContext.getFovMultiplier());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.gui.ScrollingWidget;
|
||||
import net.minecraft.client.gui.components.AbstractSelectionList;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.Constant;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyConstant;
|
||||
|
||||
@Mixin(AbstractSelectionList.class)
|
||||
public abstract class EntryListWidgetMixin {
|
||||
|
||||
@SuppressWarnings("ConstantValue")
|
||||
@ModifyConstant(method = "getEntryAtPosition", constant = @Constant(intValue = 4))
|
||||
public int cobblemon$adjustOnlyIfNecessary(int input) {
|
||||
if(ScrollingWidget.class.isInstance(this)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import net.minecraft.client.DeltaTracker;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
/**
|
||||
* Mixin to give us a hook to render the PartyOverlay below the Chat
|
||||
*
|
||||
* @author Qu
|
||||
* @since 2022-02-22
|
||||
*/
|
||||
@Mixin(Gui.class)
|
||||
public class GuiMixin {
|
||||
//This injects into the actual BooleanSupplier lambda for the "this.layers.add(layeredDraw, () -> !minecraft.options.hideGui)" call
|
||||
// sus af. You have to get the method name by looking at the bytecode of the class. Can do in intellij By clicking View -> Show Bytecode (top left)
|
||||
@Inject(method = "method_55797", at = @At("HEAD"), cancellable = true)
|
||||
private static void cobblemon$dontRenderUiInPokedex(Minecraft minecraft, CallbackInfoReturnable<Boolean> cir) {
|
||||
if (CobblemonClient.INSTANCE.getPokedexUsageContext().getScanningGuiOpen()) {
|
||||
cir.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
@Mixin(ItemRenderer.class)
|
||||
public abstract class ItemRendererMixin {
|
||||
|
||||
@Unique private final String MODEL_PATH = Cobblemon.implementation.getModAPI() == ModAPI.FABRIC ? "fabric_resource" : "standalone";
|
||||
@Unique private static final String MODEL_PATH = Cobblemon.implementation.getModAPI() == ModAPI.FABRIC ? "fabric_resource" : "standalone";
|
||||
|
||||
@Shadow @Final private ItemModelShaper itemModelShaper;
|
||||
|
||||
|
||||
@@ -9,9 +9,6 @@
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBuildDetails.smallCommitHash
|
||||
//import com.cobblemon.mod.common.api.storage.player.factory.MongoPlayerDataStoreFactory
|
||||
import com.cobblemon.mod.common.advancement.CobblemonCriteria
|
||||
import com.cobblemon.mod.common.advancement.criterion.EvolvePokemonContext
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
import com.cobblemon.mod.common.api.SeasonResolver
|
||||
import com.cobblemon.mod.common.api.data.DataProvider
|
||||
@@ -19,14 +16,11 @@ import com.cobblemon.mod.common.api.drop.CommandDropEntry
|
||||
import com.cobblemon.mod.common.api.drop.DropEntry
|
||||
import com.cobblemon.mod.common.api.drop.ItemDropEntry
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.BATTLE_STARTED_POST
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.BATTLE_VICTORY
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.DATA_SYNCHRONIZED
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.EVOLUTION_COMPLETE
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.LEVEL_UP_EVENT
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.POKEMON_CAPTURED
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.POKEMON_SCANNED
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.STARTER_CHOSEN
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.TRADE_COMPLETED
|
||||
import com.cobblemon.mod.common.api.permission.PermissionValidator
|
||||
import com.cobblemon.mod.common.api.pokeball.catching.calculators.CaptureCalculator
|
||||
@@ -62,11 +56,9 @@ import com.cobblemon.mod.common.api.storage.factory.FileBackedPokemonStoreFactor
|
||||
import com.cobblemon.mod.common.api.storage.molang.NbtMoLangDataStoreFactory
|
||||
import com.cobblemon.mod.common.api.storage.pc.PCStore
|
||||
import com.cobblemon.mod.common.api.storage.pc.link.PCLinkManager
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreManager
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreType
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.DexDataNbtBackend
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.PlayerDataJsonBackend
|
||||
import com.cobblemon.mod.common.api.storage.player.factory.CachedPlayerDataStoreFactory
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerDataStoreManager
|
||||
import com.cobblemon.mod.common.api.storage.player.factory.JsonPlayerDataStoreFactory
|
||||
import com.cobblemon.mod.common.api.storage.player.factory.MongoPlayerDataStoreFactory
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonEntityTypeTags
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.battles.BagItems
|
||||
@@ -77,12 +69,10 @@ import com.cobblemon.mod.common.battles.ShowdownThread
|
||||
import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.command.argument.DexArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.DialogueArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.FormArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.MoveArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PartySlotArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.SpeciesArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PokemonArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PokemonPropertiesArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PokemonStoreArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.SpawnBucketArgumentType
|
||||
@@ -92,7 +82,6 @@ import com.cobblemon.mod.common.config.constraint.IntConstraint
|
||||
import com.cobblemon.mod.common.config.starter.StarterConfig
|
||||
import com.cobblemon.mod.common.data.CobblemonDataProvider
|
||||
import com.cobblemon.mod.common.events.AdvancementHandler
|
||||
import com.cobblemon.mod.common.events.PokedexHandler
|
||||
import com.cobblemon.mod.common.events.ServerTickHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
|
||||
import com.cobblemon.mod.common.permission.LaxPermissionValidator
|
||||
@@ -115,6 +104,8 @@ import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.world.feature.CobblemonPlacedFeatures
|
||||
import com.cobblemon.mod.common.world.feature.ore.CobblemonOrePlacedFeatures
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
import com.mongodb.ConnectionString
|
||||
import com.mongodb.MongoClientSettings
|
||||
import com.mongodb.client.MongoClient
|
||||
import com.mongodb.client.MongoClients
|
||||
import java.io.File
|
||||
@@ -161,7 +152,7 @@ object Cobblemon {
|
||||
val battleRegistry = BattleRegistry
|
||||
var storage = PokemonStoreManager()
|
||||
var molangData = NbtMoLangDataStoreFactory
|
||||
lateinit var playerDataManager: PlayerInstancedDataStoreManager
|
||||
lateinit var playerData: PlayerDataStoreManager
|
||||
lateinit var starterConfig: StarterConfig
|
||||
val dataProvider: DataProvider = CobblemonDataProvider
|
||||
var permissionValidator: PermissionValidator by Delegates.observable(LaxPermissionValidator().also { it.initialize() }) { _, _, newValue -> newValue.initialize() }
|
||||
@@ -209,7 +200,7 @@ object Cobblemon {
|
||||
|
||||
DATA_SYNCHRONIZED.subscribe {
|
||||
storage.onPlayerDataSync(it)
|
||||
playerDataManager.syncAllToPlayer(it)
|
||||
playerData.get(it).sendToPlayer(it)
|
||||
starterHandler.handleJoin(it)
|
||||
ServerSettingsPacket(this.config.preventCompletePartyDeposit, this.config.displayEntityLevelLabel).sendToPlayer(it)
|
||||
}
|
||||
@@ -217,7 +208,7 @@ object Cobblemon {
|
||||
PCLinkManager.removeLink(it.player.uuid)
|
||||
BattleRegistry.onPlayerDisconnect(it.player)
|
||||
storage.onPlayerDisconnect(it.player)
|
||||
playerDataManager.onPlayerDisconnect(it.player)
|
||||
playerData.onPlayerDisconnect(it.player)
|
||||
TradeManager.onLogoff(it.player)
|
||||
}
|
||||
PlatformEvents.PLAYER_DEATH.subscribe {
|
||||
@@ -242,6 +233,9 @@ object Cobblemon {
|
||||
}
|
||||
}
|
||||
|
||||
// Register the grow_tumblestone advancement
|
||||
PlatformEvents.RIGHT_CLICK_BLOCK.subscribe { AdvancementHandler.onTumbleStonePlaced(it) }
|
||||
|
||||
PlatformEvents.CHANGE_DIMENSION.subscribe {
|
||||
it.player.party().forEach { pokemon -> pokemon.entity?.recallWithAnimation() }
|
||||
}
|
||||
@@ -257,8 +251,6 @@ object Cobblemon {
|
||||
}
|
||||
|
||||
HeldItemProvider.register(CobblemonHeldItemManager, Priority.LOWEST)
|
||||
|
||||
|
||||
}
|
||||
|
||||
fun initialize() {
|
||||
@@ -300,21 +292,16 @@ object Cobblemon {
|
||||
}
|
||||
PlatformEvents.SERVER_STARTING.subscribe { event ->
|
||||
val server = event.server
|
||||
playerDataManager = PlayerInstancedDataStoreManager().also { it.setup(server) }
|
||||
playerData = PlayerDataStoreManager().also { it.setup(server) }
|
||||
|
||||
val mongoClient: MongoClient?
|
||||
|
||||
val pokemonStoreRoot = server.getWorldPath(LevelResource.ROOT).resolve("pokemon").toFile()
|
||||
val storeAdapter = when (config.storageFormat) {
|
||||
"nbt", "json" -> {
|
||||
val generalJsonFactory = CachedPlayerDataStoreFactory(PlayerDataJsonBackend())
|
||||
generalJsonFactory.setup(server)
|
||||
|
||||
val pokedexNbtFactory = CachedPlayerDataStoreFactory(DexDataNbtBackend())
|
||||
pokedexNbtFactory.setup(server)
|
||||
|
||||
playerDataManager.setFactory(generalJsonFactory, PlayerInstancedDataStoreType.GENERAL)
|
||||
playerDataManager.setFactory(pokedexNbtFactory, PlayerInstancedDataStoreType.POKEDEX)
|
||||
val jsonFactory = JsonPlayerDataStoreFactory()
|
||||
jsonFactory.setup(server)
|
||||
playerData.setFactory(jsonFactory)
|
||||
|
||||
if (config.storageFormat == "nbt") {
|
||||
NBTStoreAdapter(pokemonStoreRoot.absolutePath, useNestedFolders = true, folderPerClass = true)
|
||||
@@ -327,9 +314,7 @@ object Cobblemon {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
"mongodb" -> {
|
||||
/*
|
||||
try {
|
||||
Class.forName("com.mongodb.client.MongoClient")
|
||||
|
||||
@@ -338,18 +323,14 @@ object Cobblemon {
|
||||
.build()
|
||||
mongoClient = MongoClients.create(mongoClientSettings)
|
||||
val mongoFactory = MongoPlayerDataStoreFactory(mongoClient, config.mongoDBDatabaseName)
|
||||
playerData.setFactory(mongoFactory, PlayerInstancedDataStoreType.GENERAL)
|
||||
playerData.setFactory(mongoFactory)
|
||||
MongoDBStoreAdapter(mongoClient, config.mongoDBDatabaseName)
|
||||
} catch (e: ClassNotFoundException) {
|
||||
LOGGER.error("MongoDB driver not found.")
|
||||
throw e
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
else -> throw IllegalArgumentException("Unsupported storageFormat: ${config.storageFormat}")
|
||||
}
|
||||
.with(ReforgedConversion(server.getWorldPath(LevelResource.ROOT))) as FileStoreAdapter<*>
|
||||
@@ -366,13 +347,21 @@ object Cobblemon {
|
||||
|
||||
PlatformEvents.SERVER_STOPPED.subscribe {
|
||||
storage.unregisterAll()
|
||||
playerDataManager.saveAllStores()
|
||||
playerData.saveAll()
|
||||
}
|
||||
PlatformEvents.SERVER_STARTED.subscribe {
|
||||
bestSpawner.onServerStarted()
|
||||
battleRegistry.onServerStarted()
|
||||
}
|
||||
PlatformEvents.SERVER_TICK_POST.subscribe { ServerTickHandler.onTick(it.server) }
|
||||
POKEMON_CAPTURED.subscribe { AdvancementHandler.onCapture(it) }
|
||||
// EGG_HATCH.subscribe { AdvancementHandler.onHatch(it) }
|
||||
BATTLE_VICTORY.subscribe { AdvancementHandler.onWinBattle(it) }
|
||||
EVOLUTION_COMPLETE.subscribe(Priority.LOWEST) { event ->
|
||||
AdvancementHandler.onEvolve(event)
|
||||
}
|
||||
LEVEL_UP_EVENT.subscribe { AdvancementHandler.onLevelUp(it) }
|
||||
TRADE_COMPLETED.subscribe { AdvancementHandler.onTradeCompleted(it) }
|
||||
|
||||
BagItems.observable.subscribe {
|
||||
LOGGER.info("Starting dummy Showdown battle to force it to pre-load data.")
|
||||
@@ -384,12 +373,8 @@ object Cobblemon {
|
||||
).ifSuccessful { it.mute = true }
|
||||
}
|
||||
|
||||
registerEventHandlers()
|
||||
}
|
||||
|
||||
fun registerEventHandlers() {
|
||||
AdvancementHandler.registerListeners()
|
||||
PokedexHandler.registerListeners()
|
||||
//To whomever is merging, this is moved out of Cobblemon and into the CobblemonImplementations
|
||||
//CobblemonSherds.registerSherds()
|
||||
}
|
||||
|
||||
fun getLevel(dimension: ResourceKey<Level>): Level? {
|
||||
@@ -487,15 +472,13 @@ object Cobblemon {
|
||||
}
|
||||
|
||||
private fun registerArgumentTypes() {
|
||||
this.implementation.registerCommandArgument(cobblemonResource("pokemon"), SpeciesArgumentType::class, SingletonArgumentInfo.contextFree(SpeciesArgumentType::species))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("pokemon"), PokemonArgumentType::class, SingletonArgumentInfo.contextFree(PokemonArgumentType::pokemon))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("pokemon_properties"), PokemonPropertiesArgumentType::class, SingletonArgumentInfo.contextFree(PokemonPropertiesArgumentType::properties))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("spawn_bucket"), SpawnBucketArgumentType::class, SingletonArgumentInfo.contextFree(SpawnBucketArgumentType::spawnBucket))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("move"), MoveArgumentType::class, SingletonArgumentInfo.contextFree(MoveArgumentType::move))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("party_slot"), PartySlotArgumentType::class, SingletonArgumentInfo.contextFree(PartySlotArgumentType::partySlot))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("pokemon_store"), PokemonStoreArgumentType::class, SingletonArgumentInfo.contextFree(PokemonStoreArgumentType::pokemonStore))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("dialogue"), DialogueArgumentType::class, SingletonArgumentInfo.contextFree(DialogueArgumentType::dialogue))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("form"), FormArgumentType::class, SingletonArgumentInfo.contextFree(FormArgumentType::form))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("dex"), DexArgumentType::class, SingletonArgumentInfo.contextFree (DexArgumentType::dex))
|
||||
}
|
||||
|
||||
}
|
||||
@@ -36,9 +36,6 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
|
||||
@JvmField
|
||||
val PC: BlockEntityType<PCBlockEntity> = this.create("pc", BlockEntityType.Builder.of(::PCBlockEntity, CobblemonBlocks.PC).build(null))
|
||||
|
||||
@JvmField
|
||||
val LECTERN: BlockEntityType<LecternBlockEntity> = this.create("lectern", BlockEntityType.Builder.of(::LecternBlockEntity, CobblemonBlocks.LECTERN).build(null))
|
||||
|
||||
@JvmField
|
||||
val BERRY = this.create("berry", BlockEntityType.Builder.of(::BerryBlockEntity, *CobblemonBlocks.berries().values.toTypedArray()).build(null))
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.api.apricorn.Apricorn
|
||||
import com.cobblemon.mod.common.block.*
|
||||
import com.cobblemon.mod.common.block.LecternBlock
|
||||
import com.cobblemon.mod.common.block.MintBlock.MintType
|
||||
import com.cobblemon.mod.common.block.chest.GildedChestBlock
|
||||
import com.cobblemon.mod.common.block.sign.CobblemonHangingSignBlock
|
||||
@@ -264,27 +263,6 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val SMOOTH_TUMBLESTONE = this.create("smooth_tumblestone",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val SMOOTH_TUMBLESTONE_STAIRS = this.create("smooth_tumblestone_stairs", StairsBlockInvoker.`cobblemon$create`(SMOOTH_TUMBLESTONE.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(SMOOTH_TUMBLESTONE)))
|
||||
@JvmField
|
||||
val SMOOTH_TUMBLESTONE_SLAB = this.create("smooth_tumblestone_slab", SlabBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
@JvmField
|
||||
val TUMBLESTONE_BRICKS = this.create("tumblestone_bricks", Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
@@ -292,7 +270,8 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val TUMBLESTONE_BRICK_STAIRS = this.create("tumblestone_brick_stairs", StairsBlockInvoker.`cobblemon$create`(TUMBLESTONE_BRICKS.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(TUMBLESTONE_BRICKS)))
|
||||
@JvmField
|
||||
@@ -363,27 +342,6 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val SMOOTH_SKY_TUMBLESTONE = this.create("smooth_sky_tumblestone",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.COLOR_LIGHT_BLUE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val SMOOTH_SKY_TUMBLESTONE_STAIRS = this.create("smooth_sky_tumblestone_stairs", StairsBlockInvoker.`cobblemon$create`(SMOOTH_SKY_TUMBLESTONE.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(SMOOTH_SKY_TUMBLESTONE)))
|
||||
@JvmField
|
||||
val SMOOTH_SKY_TUMBLESTONE_SLAB = this.create("smooth_sky_tumblestone_slab", SlabBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.COLOR_LIGHT_BLUE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
@JvmField
|
||||
val SKY_TUMBLESTONE_BRICKS = this.create("sky_tumblestone_bricks",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
@@ -464,28 +422,6 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val SMOOTH_BLACK_TUMBLESTONE = this.create("smooth_black_tumblestone",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_BLACK)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val SMOOTH_BLACK_TUMBLESTONE_STAIRS = this.create("smooth_black_tumblestone_stairs", StairsBlockInvoker.`cobblemon$create`(SMOOTH_BLACK_TUMBLESTONE.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(SMOOTH_BLACK_TUMBLESTONE)))
|
||||
@JvmField
|
||||
val SMOOTH_BLACK_TUMBLESTONE_SLAB = this.create("smooth_black_tumblestone_slab", SlabBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_BLACK)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
@JvmField
|
||||
val BLACK_TUMBLESTONE_BRICKS = this.create("black_tumblestone_bricks",
|
||||
Block(
|
||||
@@ -528,117 +464,6 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val FIRE_STONE_BLOCK = this.create("fire_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.FIRE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val WATER_STONE_BLOCK = this.create("water_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.WATER)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val THUNDER_STONE_BLOCK = this.create("thunder_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.GLOW_LICHEN)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val LEAF_STONE_BLOCK = this.create("leaf_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.COLOR_GREEN)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val ICE_STONE_BLOCK = this.create("ice_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.ICE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val SUN_STONE_BLOCK = this.create("sun_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val MOON_STONE_BLOCK = this.create("moon_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.DEEPSLATE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val SHINY_STONE_BLOCK = this.create("shiny_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.QUARTZ)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val DAWN_STONE_BLOCK = this.create("dawn_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.DIAMOND)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val DUSK_STONE_BLOCK = this.create("dusk_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.WARPED_HYPHAE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val BLACK_APRICORN = apricornBlock("black_apricorn", Apricorn.BLACK)
|
||||
@JvmField
|
||||
@@ -813,19 +638,6 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val LECTERN = create(
|
||||
"lectern",
|
||||
LecternBlock(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.WOOD)
|
||||
.instrument(NoteBlockInstrument.BASS)
|
||||
.sound(SoundType.WOOD)
|
||||
.strength(2.5F)
|
||||
.ignitedByLava()
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val DISPLAY_CASE = create(
|
||||
"display_case",
|
||||
@@ -835,7 +647,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
.noOcclusion()
|
||||
.pushReaction(PushReaction.BLOCK)
|
||||
.mapColor(MapColor.STONE)
|
||||
.strength(0.3F)
|
||||
.strength(0.3f)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ object CobblemonCommands {
|
||||
PcCommand.register(dispatcher)
|
||||
SpawnPokemonFromPool.register(dispatcher)
|
||||
PokeboxCommand.register(dispatcher)
|
||||
PokedexCommand.register(dispatcher)
|
||||
TestStoreCommand.register(dispatcher)
|
||||
QueryLearnsetCommand.register(dispatcher)
|
||||
TestPcSlotCommand.register(dispatcher)
|
||||
|
||||
@@ -19,7 +19,6 @@ import com.cobblemon.mod.common.api.text.gray
|
||||
import com.cobblemon.mod.common.block.BerryBlock
|
||||
import com.cobblemon.mod.common.block.MintBlock
|
||||
import com.cobblemon.mod.common.block.MintBlock.MintType
|
||||
import com.cobblemon.mod.common.client.pokedex.PokedexTypes
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
|
||||
import com.cobblemon.mod.common.item.*
|
||||
import com.cobblemon.mod.common.item.armor.CobblemonArmorTrims
|
||||
@@ -153,21 +152,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val ANCIENT_ORIGIN_BALL = pokeBallItem(PokeBalls.ANCIENT_ORIGIN_BALL)
|
||||
|
||||
@JvmField
|
||||
val POKEDEX_BLACK = create("pokedex_black", PokedexItem(PokedexTypes.BLACK))
|
||||
@JvmField
|
||||
val POKEDEX_BLUE = create("pokedex_blue", PokedexItem(PokedexTypes.BLUE))
|
||||
@JvmField
|
||||
val POKEDEX_GREEN = create("pokedex_green", PokedexItem(PokedexTypes.GREEN))
|
||||
@JvmField
|
||||
val POKEDEX_PINK = create("pokedex_pink", PokedexItem(PokedexTypes.PINK))
|
||||
@JvmField
|
||||
val POKEDEX_RED = create("pokedex_red", PokedexItem(PokedexTypes.RED))
|
||||
@JvmField
|
||||
val POKEDEX_WHITE = create("pokedex_white", PokedexItem(PokedexTypes.WHITE))
|
||||
@JvmField
|
||||
val POKEDEX_YELLOW = create("pokedex_yellow", PokedexItem(PokedexTypes.YELLOW))
|
||||
|
||||
@JvmField
|
||||
val VIVICHOKE = compostableItem("vivichoke")
|
||||
|
||||
@@ -272,8 +256,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
val PASTURE = blockItem("pasture", CobblemonBlocks.PASTURE)
|
||||
@JvmField
|
||||
val DISPLAY_CASE = blockItem("display_case", CobblemonBlocks.DISPLAY_CASE)
|
||||
@JvmField
|
||||
val LECTERN = blockItem("lectern", CobblemonBlocks.LECTERN)
|
||||
|
||||
// Evolution items
|
||||
@JvmField val LINK_CABLE = create("link_cable", LinkCableItem())
|
||||
@@ -980,12 +962,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val CHISELED_POLISHED_TUMBLESTONE = blockItem("chiseled_polished_tumblestone", CobblemonBlocks.CHISELED_POLISHED_TUMBLESTONE)
|
||||
@JvmField
|
||||
val SMOOTH_TUMBLESTONE = blockItem("smooth_tumblestone", CobblemonBlocks.SMOOTH_TUMBLESTONE)
|
||||
@JvmField
|
||||
val SMOOTH_TUMBLESTONE_STAIRS = blockItem("smooth_tumblestone_stairs", CobblemonBlocks.SMOOTH_TUMBLESTONE_STAIRS)
|
||||
@JvmField
|
||||
val SMOOTH_TUMBLESTONE_SLAB = blockItem("smooth_tumblestone_slab", CobblemonBlocks.SMOOTH_TUMBLESTONE_SLAB)
|
||||
@JvmField
|
||||
val TUMBLESTONE_BRICKS = blockItem("tumblestone_bricks", CobblemonBlocks.TUMBLESTONE_BRICKS)
|
||||
@JvmField
|
||||
val TUMBLESTONE_BRICK_STAIRS = blockItem("tumblestone_brick_stairs", CobblemonBlocks.TUMBLESTONE_BRICK_STAIRS)
|
||||
@@ -1006,12 +982,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val CHISELED_POLISHED_SKY_TUMBLESTONE = blockItem("chiseled_polished_sky_tumblestone", CobblemonBlocks.CHISELED_POLISHED_SKY_TUMBLESTONE)
|
||||
@JvmField
|
||||
val SMOOTH_SKY_TUMBLESTONE = blockItem("smooth_sky_tumblestone", CobblemonBlocks.SMOOTH_SKY_TUMBLESTONE)
|
||||
@JvmField
|
||||
val SMOOTH_SKY_TUMBLESTONE_STAIRS = blockItem("smooth_sky_tumblestone_stairs", CobblemonBlocks.SMOOTH_SKY_TUMBLESTONE_STAIRS)
|
||||
@JvmField
|
||||
val SMOOTH_SKY_TUMBLESTONE_SLAB = blockItem("smooth_sky_tumblestone_slab", CobblemonBlocks.SMOOTH_SKY_TUMBLESTONE_SLAB)
|
||||
@JvmField
|
||||
val SKY_TUMBLESTONE_BRICKS = blockItem("sky_tumblestone_bricks", CobblemonBlocks.SKY_TUMBLESTONE_BRICKS)
|
||||
@JvmField
|
||||
val SKY_TUMBLESTONE_BRICK_STAIRS = blockItem("sky_tumblestone_brick_stairs", CobblemonBlocks.SKY_TUMBLESTONE_BRICK_STAIRS)
|
||||
@@ -1032,12 +1002,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val CHISELED_POLISHED_BLACK_TUMBLESTONE = blockItem("chiseled_polished_black_tumblestone", CobblemonBlocks.CHISELED_POLISHED_BLACK_TUMBLESTONE)
|
||||
@JvmField
|
||||
val SMOOTH_BLACK_TUMBLESTONE = blockItem("smooth_black_tumblestone", CobblemonBlocks.SMOOTH_BLACK_TUMBLESTONE)
|
||||
@JvmField
|
||||
val SMOOTH_BLACK_TUMBLESTONE_STAIRS = blockItem("smooth_black_tumblestone_stairs", CobblemonBlocks.SMOOTH_BLACK_TUMBLESTONE_STAIRS)
|
||||
@JvmField
|
||||
val SMOOTH_BLACK_TUMBLESTONE_SLAB = blockItem("smooth_black_tumblestone_slab", CobblemonBlocks.SMOOTH_BLACK_TUMBLESTONE_SLAB)
|
||||
@JvmField
|
||||
val BLACK_TUMBLESTONE_BRICKS = blockItem("black_tumblestone_bricks", CobblemonBlocks.BLACK_TUMBLESTONE_BRICKS)
|
||||
@JvmField
|
||||
val BLACK_TUMBLESTONE_BRICK_STAIRS = blockItem("black_tumblestone_brick_stairs", CobblemonBlocks.BLACK_TUMBLESTONE_BRICK_STAIRS)
|
||||
@@ -1048,27 +1012,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val CHISELED_BLACK_TUMBLESTONE_BRICKS = blockItem("chiseled_black_tumblestone_bricks", CobblemonBlocks.CHISELED_BLACK_TUMBLESTONE_BRICKS)
|
||||
|
||||
@JvmField
|
||||
val FIRE_STONE_BLOCK = blockItem("fire_stone_block", CobblemonBlocks.FIRE_STONE_BLOCK)
|
||||
@JvmField
|
||||
val WATER_STONE_BLOCK = blockItem("water_stone_block", CobblemonBlocks.WATER_STONE_BLOCK)
|
||||
@JvmField
|
||||
val THUNDER_STONE_BLOCK = blockItem("thunder_stone_block", CobblemonBlocks.THUNDER_STONE_BLOCK)
|
||||
@JvmField
|
||||
val LEAF_STONE_BLOCK = blockItem("leaf_stone_block", CobblemonBlocks.LEAF_STONE_BLOCK)
|
||||
@JvmField
|
||||
val ICE_STONE_BLOCK = blockItem("ice_stone_block", CobblemonBlocks.ICE_STONE_BLOCK)
|
||||
@JvmField
|
||||
val SUN_STONE_BLOCK = blockItem("sun_stone_block", CobblemonBlocks.SUN_STONE_BLOCK)
|
||||
@JvmField
|
||||
val MOON_STONE_BLOCK = blockItem("moon_stone_block", CobblemonBlocks.MOON_STONE_BLOCK)
|
||||
@JvmField
|
||||
val SHINY_STONE_BLOCK = blockItem("shiny_stone_block", CobblemonBlocks.SHINY_STONE_BLOCK)
|
||||
@JvmField
|
||||
val DAWN_STONE_BLOCK = blockItem("dawn_stone_block", CobblemonBlocks.DAWN_STONE_BLOCK)
|
||||
@JvmField
|
||||
val DUSK_STONE_BLOCK = blockItem("dusk_stone_block", CobblemonBlocks.DUSK_STONE_BLOCK)
|
||||
|
||||
@JvmField
|
||||
val AUTOMATON_ARMOR_TRIM_SMITHING_TEMPLATE: SmithingTemplateItem = this.create(
|
||||
"automaton_armor_trim_smithing_template",
|
||||
|
||||
@@ -24,7 +24,6 @@ import com.cobblemon.mod.common.client.net.effect.RunPosableMoLangHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormEntityParticleHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormParticleHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.InteractPokemonUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.PokedexUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.SummaryUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.npc.CloseNPCEditorHandler
|
||||
import com.cobblemon.mod.common.client.net.npc.OpenNPCEditorHandler
|
||||
@@ -32,7 +31,6 @@ import com.cobblemon.mod.common.client.net.pasture.ClosePastureHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.OpenPastureHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.PokemonPasturedHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.PokemonUnpasturedHandler
|
||||
import com.cobblemon.mod.common.client.net.pokedex.ServerConfirmedScanHandler
|
||||
import com.cobblemon.mod.common.client.net.pokemon.update.PokemonUpdatePacketHandler
|
||||
import com.cobblemon.mod.common.client.net.settings.ServerSettingsPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.sound.UnvalidatedPlaySoundS2CPacketHandler
|
||||
@@ -90,14 +88,19 @@ import com.cobblemon.mod.common.net.messages.client.spawn.SpawnGenericBedrockPac
|
||||
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokeballPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.starter.OpenStarterUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.SetClientPlayerDataPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.starter.SetClientPlayerDataPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.RemoveClientPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.SwapClientPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.InitializePartyPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.MoveClientPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyReferencePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.ClosePCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.InitializePCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.MoveClientPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.OpenPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.toast.ToastPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeAcceptanceChangedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeCancelledPacket
|
||||
@@ -107,7 +110,6 @@ import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferNotification
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.PokedexUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.*
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
|
||||
@@ -125,7 +127,6 @@ import com.cobblemon.mod.common.net.messages.server.npc.SaveNPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.PasturePokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.UnpastureAllPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.StartScanningPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.interact.InteractPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetNicknamePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.evolution.AcceptEvolutionPacket
|
||||
@@ -184,10 +185,6 @@ import com.cobblemon.mod.common.net.serverhandling.trade.CancelTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.ChangeTradeAcceptanceHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.OfferTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.pokedex.ServerConfirmedScanPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.FinishScanningPacket
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.FinishScanningHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.StartScanningHandler
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
@@ -267,7 +264,6 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(SummaryUIPacket.ID, SummaryUIPacket::decode, SummaryUIPacketHandler))
|
||||
list.add(PacketRegisterInfo(InteractPokemonUIPacket.ID, InteractPokemonUIPacket::decode, InteractPokemonUIPacketHandler))
|
||||
list.add(PacketRegisterInfo(PlayerInteractOptionsPacket.ID, PlayerInteractOptionsPacket::decode, PlayerInteractOptionsHandler))
|
||||
list.add(PacketRegisterInfo(PokedexUIPacket.ID, PokedexUIPacket::decode, PokedexUIPacketHandler))
|
||||
|
||||
// Starter packets
|
||||
list.add(PacketRegisterInfo(OpenStarterUIPacket.ID, OpenStarterUIPacket::decode, StarterUIPacketHandler))
|
||||
@@ -321,7 +317,6 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(NPCRegistrySyncPacket.ID, NPCRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(PokeRodRegistrySyncPacket.ID, PokeRodRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(ScriptRegistrySyncPacket.ID, ScriptRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(PokedexDexSyncPacket.ID, PokedexDexSyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(FishingBaitRegistrySyncPacket.ID, FishingBaitRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
|
||||
// Effects
|
||||
@@ -371,8 +366,6 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(CloseNPCEditorPacket.ID, CloseNPCEditorPacket::decode, CloseNPCEditorHandler))
|
||||
list.add(PacketRegisterInfo(OpenNPCEditorPacket.ID, OpenNPCEditorPacket::decode, OpenNPCEditorHandler))
|
||||
|
||||
//Pokedex scanning
|
||||
list.add(PacketRegisterInfo(ServerConfirmedScanPacket.ID, ServerConfirmedScanPacket::decode, ServerConfirmedScanHandler))
|
||||
return list
|
||||
}
|
||||
|
||||
@@ -428,10 +421,6 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(OfferTradePacket.ID, OfferTradePacket::decode, OfferTradeHandler))
|
||||
list.add(PacketRegisterInfo(UpdateTradeOfferPacket.ID, UpdateTradeOfferPacket::decode, UpdateTradeOfferHandler))
|
||||
|
||||
// Pokedex scanning
|
||||
list.add(PacketRegisterInfo(StartScanningPacket.ID, StartScanningPacket::decode, StartScanningHandler))
|
||||
list.add(PacketRegisterInfo(FinishScanningPacket.ID, FinishScanningPacket::decode, FinishScanningHandler))
|
||||
|
||||
// Pasture
|
||||
list.add(PacketRegisterInfo(PasturePokemonPacket.ID, PasturePokemonPacket::decode, PasturePokemonHandler))
|
||||
list.add(PacketRegisterInfo(UnpasturePokemonPacket.ID, UnpasturePokemonPacket::decode, UnpasturePokemonHandler))
|
||||
|
||||
@@ -61,43 +61,14 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
@JvmField
|
||||
val POKE_BALL_TRAIL = this.create("poke_ball.trail")
|
||||
|
||||
@JvmField
|
||||
val POKEDEX_OPEN = this.create("item.pokedex.open")
|
||||
@JvmField
|
||||
val POKEDEX_CLOSE = this.create("item.pokedex.close")
|
||||
@JvmField
|
||||
val POKEDEX_SCAN_OPEN = this.create("item.pokedex.scan_open")
|
||||
@JvmField
|
||||
val POKEDEX_SCAN_CLOSE = this.create("item.pokedex.scan_close")
|
||||
@JvmField
|
||||
val POKEDEX_SCAN = this.create("item.pokedex.scan")
|
||||
@JvmField
|
||||
val POKEDEX_SCAN_LOOP = this.create("item.pokedex.scan_loop")
|
||||
@JvmField
|
||||
val POKEDEX_SCAN_DETAIL = this.create("item.pokedex.scan_detail")
|
||||
@JvmField
|
||||
val POKEDEX_CLICK = this.create("item.pokedex.click")
|
||||
@JvmField
|
||||
val POKEDEX_CLICK_SHORT = this.create("item.pokedex.click_short")
|
||||
@JvmField
|
||||
val POKEDEX_SNAP_PICTURE = this.create("item.pokedex.snap")
|
||||
@JvmField
|
||||
val POKEDEX_ZOOM_IN = this.create("item.pokedex.zoom_in")
|
||||
@JvmField
|
||||
val POKEDEX_ZOOM_OUT = this.create("item.pokedex.zoom_out")
|
||||
@JvmField
|
||||
val POKEDEX_ZOOM_INCREMENT = this.create("item.pokedex.zoom_increment")
|
||||
|
||||
|
||||
|
||||
@JvmField
|
||||
val ITEM_USE = this.create("item.use")
|
||||
@JvmField
|
||||
val EVOLUTION_NOTIFICATION = this.create("evolution.notification")
|
||||
val CAN_EVOLVE = this.create("pokemon.can_evolve")
|
||||
@JvmField
|
||||
val EVOLUTION_UI = this.create("evolution.ui")
|
||||
val EVOLVING = this.create("pokemon.evolving")
|
||||
@JvmField
|
||||
val EVOLUTION = this.create("evolution")
|
||||
val EVOLVE = this.create("evolution.evolve")
|
||||
|
||||
@JvmField
|
||||
val PVN_BATTLE = this.create("battle.pvn.default")
|
||||
@@ -190,15 +161,6 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
@JvmField
|
||||
val TUMBLESTONE_STEP = this.create("tumblestone.step")
|
||||
|
||||
@JvmField
|
||||
val EVOLUTION_STONE_BLOCK_BREAK = this.create("evolution_stone_block.break")
|
||||
@JvmField
|
||||
val EVOLUTION_STONE_BLOCK_HIT = this.create("evolution_stone_block.hit")
|
||||
@JvmField
|
||||
val EVOLUTION_STONE_BLOCK_PLACE = this.create("evolution_stone_block.place")
|
||||
@JvmField
|
||||
val EVOLUTION_STONE_BLOCK_STEP = this.create("evolution_stone_block.step")
|
||||
|
||||
@JvmField
|
||||
val GIMMIGHOUL_GIVE_ITEM_SMALL = this.create("gimmighoul.give_item_small")
|
||||
@JvmField
|
||||
@@ -248,7 +210,7 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
val GILDED_CHEST_PLACE = this.create("gilded_chest.place")
|
||||
|
||||
@JvmField
|
||||
val RELIC_COIN_SACK_SOUNDS = SoundType(1f, 1.1f,
|
||||
val RELIC_COIN_SACK_SOUNDS = SoundType(1f, 1f,
|
||||
RELIC_COIN_SACK_BREAK,
|
||||
RELIC_COIN_SACK_STEP,
|
||||
RELIC_COIN_SACK_PLACE,
|
||||
@@ -256,7 +218,7 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
RELIC_COIN_SACK_STEP
|
||||
)
|
||||
@JvmField
|
||||
val RELIC_COIN_POUCH_SOUNDS = SoundType(1f, 1.1f,
|
||||
val RELIC_COIN_POUCH_SOUNDS = SoundType(1f, 1f,
|
||||
RELIC_COIN_POUCH_BREAK,
|
||||
RELIC_COIN_SACK_STEP,
|
||||
RELIC_COIN_POUCH_PLACE,
|
||||
@@ -302,7 +264,7 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
val IMPACT_WATER = this.create("impact.water")
|
||||
|
||||
@JvmField
|
||||
val TUMBLESTONE_SOUNDS = SoundType(1f, 1.1f,
|
||||
val TUMBLESTONE_SOUNDS = SoundType(1f, 1f,
|
||||
TUMBLESTONE_BREAK,
|
||||
TUMBLESTONE_STEP,
|
||||
TUMBLESTONE_PLACE,
|
||||
@@ -311,25 +273,16 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val TUMBLESTONE_BLOCK_SOUNDS = SoundType(1f, 1.1f,
|
||||
val TUMBLESTONE_BLOCK_SOUNDS = SoundType(1f, 1f,
|
||||
TUMBLESTONE_BLOCK_BREAK,
|
||||
TUMBLESTONE_STEP,
|
||||
TUMBLESTONE_PLACE,
|
||||
TUMBLESTONE_HIT,
|
||||
TUMBLESTONE_STEP
|
||||
)
|
||||
@JvmField
|
||||
val EVOLUTION_STONE_BLOCK_SOUNDS = SoundType(1f, 1.1f,
|
||||
EVOLUTION_STONE_BLOCK_BREAK,
|
||||
EVOLUTION_STONE_BLOCK_STEP,
|
||||
EVOLUTION_STONE_BLOCK_PLACE,
|
||||
EVOLUTION_STONE_BLOCK_HIT,
|
||||
EVOLUTION_STONE_BLOCK_STEP
|
||||
)
|
||||
|
||||
|
||||
@JvmField
|
||||
val BERRY_BUSH_SOUNDS = SoundType(0.8f, 1.1f,
|
||||
val BERRY_BUSH_SOUNDS = SoundType(1f, 1f,
|
||||
BERRY_BUSH_BREAK,
|
||||
SoundEvents.GRASS_STEP,
|
||||
BERRY_BUSH_PLACE,
|
||||
@@ -338,25 +291,25 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val BIG_ROOT_SOUNDS = SoundType(0.8f, 1.1f,
|
||||
val BIG_ROOT_SOUNDS = SoundType(1f, 1f,
|
||||
BIG_ROOT_BREAK,
|
||||
SoundEvents.ROOTS_STEP,
|
||||
SoundEvents.ROOTS_PLACE,
|
||||
SoundEvents.ROOTS_HIT,
|
||||
SoundEvents.ROOTS_FALL
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val ENERGY_ROOT_SOUNDS = SoundType(1f, 1f,
|
||||
SoundEvents.ROOTS_BREAK,
|
||||
SoundEvents.ROOTS_STEP,
|
||||
ENERGY_ROOT_PLACE,
|
||||
SoundEvents.ROOTS_HIT,
|
||||
SoundEvents.ROOTS_FALL
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val ENERGY_ROOT_SOUNDS = SoundType(0.8f, 1.1f,
|
||||
BIG_ROOT_BREAK,
|
||||
SoundEvents.ROOTS_STEP,
|
||||
ENERGY_ROOT_PLACE,
|
||||
SoundEvents.ROOTS_HIT,
|
||||
SoundEvents.ROOTS_FALL
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val MEDICINAL_LEEK_SOUNDS = SoundType(1f, 1.1f,
|
||||
val MEDICINAL_LEEK_SOUNDS = SoundType(1f, 1f,
|
||||
MEDICINAL_LEEK_BREAK,
|
||||
SoundEvents.GRASS_STEP,
|
||||
MEDICINAL_LEEK_PLACE,
|
||||
@@ -365,7 +318,7 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val VIVICHOKE_SOUNDS = SoundType(0.6f, 1.1f,
|
||||
val VIVICHOKE_SOUNDS = SoundType(1f, 1f,
|
||||
VIVICHOKE_BREAK,
|
||||
SoundEvents.GRASS_STEP,
|
||||
VIVICHOKE_PLACE,
|
||||
@@ -374,7 +327,7 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val MINT_SOUNDS = SoundType(0.6f, 1.1f,
|
||||
val MINT_SOUNDS = SoundType(1f, 1f,
|
||||
MINT_BREAK,
|
||||
SoundEvents.GRASS_STEP,
|
||||
MINT_PLACE,
|
||||
@@ -383,7 +336,7 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val REVIVAL_HERB_SOUNDS = SoundType(0.6f, 1.1f,
|
||||
val REVIVAL_HERB_SOUNDS = SoundType(1f, 1f,
|
||||
REVIVAL_HERB_BREAK,
|
||||
SoundEvents.GRASS_STEP,
|
||||
REVIVAL_HERB_PLACE,
|
||||
@@ -392,7 +345,7 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val GILDED_CHEST_SOUNDS = SoundType(1f, 1.1f,
|
||||
val GILDED_CHEST_SOUNDS = SoundType(1f, 1f,
|
||||
GILDED_CHEST_BREAK,
|
||||
GILDED_CHEST_STEP,
|
||||
GILDED_CHEST_PLACE,
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ class AspectCriterion(
|
||||
// pokemon = json.get("pokemon").asString.asIdentifierDefaultingNamespace()
|
||||
// }
|
||||
//
|
||||
// override fun matches(player: ServerPlayer, context: MutableMap<Identifier, MutableSet<String>>): Boolean {
|
||||
// override fun matches(player: ServerPlayerEntity, context: MutableMap<Identifier, MutableSet<String>>): Boolean {
|
||||
// val caughtAspects = context.getOrDefault(pokemon, mutableSetOf())
|
||||
// return this.aspects.all { it in caughtAspects }
|
||||
// }
|
||||
|
||||
+3
-2
@@ -34,7 +34,8 @@ class BattleCountableCriterion(
|
||||
|
||||
override fun matches(player: ServerPlayer, context: BattleCountableContext): Boolean {
|
||||
var typeCheck = false
|
||||
val advancementData = Cobblemon.playerDataManager.getGenericData(player).advancementData
|
||||
val advancementData = Cobblemon.playerData.get(player).advancementData
|
||||
|
||||
if (battleTypes.isEmpty() || battleTypes.contains("any")) {
|
||||
typeCheck = true
|
||||
}
|
||||
@@ -86,7 +87,7 @@ class BattleCountableCriterion(
|
||||
// json.add("battle_types", battleTypes.toJsonArray())
|
||||
// }
|
||||
//
|
||||
// override fun matches(player: ServerPlayer, context: BattleCountableContext): Boolean {
|
||||
// override fun matches(player: ServerPlayerEntity, context: BattleCountableContext): Boolean {
|
||||
// var typeCheck = false
|
||||
// val advancementData = Cobblemon.playerData.get(player).advancementData
|
||||
// if (battleTypes.isEmpty() || battleTypes.contains("any")) {
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ class CaughtPokemonCriterion(
|
||||
// type = json.get("type")?.asString ?: "any"
|
||||
// }
|
||||
//
|
||||
// override fun matches(player: ServerPlayer, context: CountablePokemonTypeContext): Boolean {
|
||||
// override fun matches(player: ServerPlayerEntity, context: CountablePokemonTypeContext): Boolean {
|
||||
// return super.matches(player, context) && (context.type == type || type == "any")
|
||||
// }
|
||||
//}
|
||||
+2
-2
@@ -50,7 +50,7 @@ open class CountableCriterion<T : CountableContext>(
|
||||
// json.addProperty("count", count)
|
||||
// }
|
||||
//
|
||||
// override fun matches(player: ServerPlayer, context: T) = context.times >= count
|
||||
// override fun matches(player: ServerPlayerEntity, context: T) = context.times >= count
|
||||
//}
|
||||
//
|
||||
///**
|
||||
@@ -64,7 +64,7 @@ open class CountableCriterion<T : CountableContext>(
|
||||
// * @since November 4th, 2022
|
||||
// */
|
||||
//class SimpleCountableCriterionCondition(id: Identifier, predicate: LootContextPredicate) : CountableCriterionCondition<CountableContext>(id, predicate)
|
||||
//fun SimpleCriterionTrigger<CountableContext, SimpleCountableCriterionCondition>.trigger(player: ServerPlayer, times: Int) = trigger(player, CountableContext(times))
|
||||
//fun SimpleCriterionTrigger<CountableContext, SimpleCountableCriterionCondition>.trigger(player: ServerPlayerEntity, times: Int) = trigger(player, CountableContext(times))
|
||||
//
|
||||
///**
|
||||
// * Some type of context that has a count associated with it, representing how many times the trigger has occurred.
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ class EvolvePokemonCriterion(
|
||||
// evolution = json.get("evolution")?.asString ?: "any"
|
||||
// }
|
||||
//
|
||||
// override fun matches(player: ServerPlayer, context: EvolvePokemonContext): Boolean {
|
||||
// override fun matches(player: ServerPlayerEntity, context: EvolvePokemonContext): Boolean {
|
||||
// return context.times >= count && (context.species == species.asIdentifierDefaultingNamespace() || species == "any") &&
|
||||
// (context.evolution == evolution.asIdentifierDefaultingNamespace() || evolution == "any")
|
||||
// }
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ class LevelUpCriterion(
|
||||
evolved = json.get("has_evolved")?.asBoolean ?: true
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: LevelUpContext): Boolean {
|
||||
override fun matches(player: ServerPlayerEntity, context: LevelUpContext): Boolean {
|
||||
val preEvo = context.pokemon.preEvolution == null
|
||||
val hasEvolution = !context.pokemon.evolutions.none()
|
||||
var evolutionCheck = true
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ class PartyCheckCriterion(
|
||||
}
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: PartyCheckContext): Boolean {
|
||||
override fun matches(player: ServerPlayerEntity, context: PartyCheckContext): Boolean {
|
||||
val playerParty = player.party()
|
||||
val matches = mutableListOf<Identifier>()
|
||||
party.forEach {
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ class PlantTumblestoneCriterion(
|
||||
// * @param context The context of the criterion
|
||||
// * @return True if the tumblestone block can grow at the given position, false otherwise
|
||||
// */
|
||||
// override fun matches(player: ServerPlayer, context: PlantTumblestoneContext): Boolean {
|
||||
// override fun matches(player: ServerPlayerEntity, context: PlantTumblestoneContext): Boolean {
|
||||
// return context.tumbleStoneBlock.canGrow(context.pos, player.level())
|
||||
// }
|
||||
//}
|
||||
|
||||
+1
-1
@@ -80,7 +80,7 @@ class TradePokemonCriterion(
|
||||
receivedHeldItem = json.get("received_held_item")?.asString ?: "minecraft:air"
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: TradePokemonContext): Boolean {
|
||||
override fun matches(player: ServerPlayerEntity, context: TradePokemonContext): Boolean {
|
||||
val heldItem1 = context.traded.heldItem().item.registryEntry.ResourceKey().value
|
||||
val heldItem2 = context.received.heldItem().item.registryEntry.ResourceKey().value
|
||||
return (context.traded.species.resourceIdentifier == traded.asIdentifierDefaultingNamespace() || traded == "any") &&
|
||||
|
||||
@@ -33,7 +33,6 @@ import java.io.PrintWriter
|
||||
* @since April 1st, 2022.
|
||||
*/
|
||||
object JsonManifestWalker {
|
||||
// im walkin ere
|
||||
/**
|
||||
* Builds a manifest at [manifestPath] using the files inside the same folder.
|
||||
*
|
||||
|
||||
@@ -21,7 +21,6 @@ import com.cobblemon.mod.common.api.battles.model.actor.EntityBackedBattleActor
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.FleeableBattleActor
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleFledEvent
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
@@ -115,7 +114,7 @@ open class PokemonBattle(
|
||||
var ended = false
|
||||
// TEMP battle showcase stuff
|
||||
var announcingRules = false
|
||||
var turn: Int = 0
|
||||
var turn: Int = 1
|
||||
private set
|
||||
|
||||
private var ticks: Int = 0
|
||||
|
||||
+1
-1
@@ -141,7 +141,7 @@ abstract class BattleActor(
|
||||
* NPC and player actors expect to append their [getName] while wild Pokémon append nothing.
|
||||
*
|
||||
* @param name The name of an object being appended, typically a Pokémon nickname received from showdown.
|
||||
* @return A [MutableComponent] of the [name] append with owner prefix.
|
||||
* @return A [MutableText] of the [name] append with owner prefix.
|
||||
*/
|
||||
abstract fun nameOwned(name: String): MutableComponent
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.cobblemon.mod.common.api.events.item.LeftoversCreatedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokeball.PokeBallCaptureCalculatedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokeball.PokemonCatchRateEvent
|
||||
import com.cobblemon.mod.common.api.events.pokeball.ThrownPokeballHitEvent
|
||||
import com.cobblemon.mod.common.api.events.pokedex.scanning.PokemonScannedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.*
|
||||
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionAcceptedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEvent
|
||||
@@ -41,7 +40,6 @@ import com.cobblemon.mod.common.api.events.storage.ReleasePokemonEvent
|
||||
import com.cobblemon.mod.common.api.events.world.BigRootPropagatedEvent
|
||||
import com.cobblemon.mod.common.api.reactive.CancelableObservable
|
||||
import com.cobblemon.mod.common.api.reactive.EventObservable
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.reactive.Observable.Companion.filter
|
||||
import com.cobblemon.mod.common.api.reactive.Observable.Companion.map
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
@@ -69,6 +67,8 @@ object CobblemonEvents {
|
||||
val EVOLUTION_COMPLETE = EventObservable<EvolutionCompleteEvent>()
|
||||
@JvmField
|
||||
val POKEMON_NICKNAMED = CancelableObservable<PokemonNicknamedEvent>()
|
||||
@JvmField
|
||||
val HELD_ITEM_UPDATED = CancelableObservable<HeldItemUpdatedEvent>()
|
||||
|
||||
@JvmField
|
||||
val THROWN_POKEBALL_HIT = CancelableObservable<ThrownPokeballHitEvent>()
|
||||
@@ -147,9 +147,6 @@ object CobblemonEvents {
|
||||
@JvmField
|
||||
val STARTER_CHOSEN = CancelableObservable<StarterChosenEvent>()
|
||||
|
||||
@JvmField
|
||||
val POKEMON_SCANNED = EventObservable<PokemonScannedEvent>()
|
||||
|
||||
@JvmField
|
||||
val APRICORN_HARVESTED = EventObservable<ApricornHarvestEvent>()
|
||||
// Berries
|
||||
@@ -169,9 +166,4 @@ object CobblemonEvents {
|
||||
val HELD_ITEM_PRE = CancelableObservable<HeldItemEvent.Pre>()
|
||||
@JvmField
|
||||
val HELD_ITEM_POST = EventObservable<HeldItemEvent.Post>()
|
||||
|
||||
@JvmField
|
||||
val POKEMON_GAINED = EventObservable<PokemonGainedEvent>()
|
||||
@JvmField
|
||||
val POKEMON_SEEN = EventObservable<PokemonSeenEvent>()
|
||||
}
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokedex.scanning
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
data class PokemonScannedEvent(val player: ServerPlayer, val scannedEntity: PokemonEntity) {
|
||||
val pokemon: Pokemon
|
||||
get() = scannedEntity.pokemon
|
||||
|
||||
val isOwned: Boolean
|
||||
get() = pokemon.getOwnerPlayer() == player
|
||||
}
|
||||
@@ -10,5 +10,5 @@ package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
//data class HatchEggEvent (
|
||||
// val pokemon: Pokemon,
|
||||
// val player: ServerPlayer
|
||||
// val player: ServerPlayerEntity
|
||||
//)
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import java.util.UUID
|
||||
|
||||
data class PokemonGainedEvent(
|
||||
val playerId: UUID,
|
||||
val pokemon: Pokemon
|
||||
) {
|
||||
}
|
||||
-19
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import java.util.UUID
|
||||
|
||||
data class PokemonSeenEvent(
|
||||
val playerId: UUID,
|
||||
val pokemon: Pokemon
|
||||
) {
|
||||
}
|
||||
@@ -29,7 +29,7 @@ data class PokeRod(
|
||||
val pokeBallId: ResourceLocation,
|
||||
//Hex string of color
|
||||
val lineColor: String,
|
||||
var name: ResourceLocation
|
||||
var name: ResourceLocation// ?// TODO (techdaan) Why was this nullable?
|
||||
) {
|
||||
internal fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeIdentifier(name)
|
||||
|
||||
@@ -10,14 +10,10 @@ package com.cobblemon.mod.common.api.gui
|
||||
|
||||
import com.cobblemon.mod.common.api.text.font
|
||||
import com.cobblemon.mod.common.client.gui.battle.BattleOverlay.Companion.PORTRAIT_DIAMETER
|
||||
import com.cobblemon.mod.common.client.render.SpriteType
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.PokemonModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.util.toHex
|
||||
import com.mojang.authlib.minecraft.client.MinecraftClient
|
||||
import com.mojang.blaze3d.platform.GlStateManager
|
||||
import com.mojang.blaze3d.platform.Lighting
|
||||
import com.mojang.blaze3d.systems.RenderSystem
|
||||
@@ -98,6 +94,8 @@ fun drawRectangle(
|
||||
bufferbuilder.addVertex(matrix, endX, endY, blitOffset).setUv(maxU, maxV)
|
||||
bufferbuilder.addVertex(matrix, endX, y, blitOffset).setUv(maxU, minV)
|
||||
bufferbuilder.addVertex(matrix, x, y, blitOffset).setUv(minU, minV)
|
||||
// TODO: Figure out if this is correct replacement.
|
||||
// OLD: BufferRenderer.draw(bufferbuilder)
|
||||
BufferUploader.drawWithShader(bufferbuilder.buildOrThrow())
|
||||
}
|
||||
|
||||
@@ -116,6 +114,21 @@ fun drawCenteredText(
|
||||
context.drawString(textRenderer, comp, x.toInt() - textRenderer.width(comp) / 2, y.toInt(), colour, shadow)
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun drawTextJustifiedRight(
|
||||
context: GuiGraphics,
|
||||
font: ResourceLocation? = null,
|
||||
text: MutableComponent,
|
||||
x: Number,
|
||||
y: Number,
|
||||
colour: Int,
|
||||
shadow: Boolean = true
|
||||
) {
|
||||
val comp = text.let { if (font != null) it.font(font) else it }
|
||||
val font = Minecraft.getInstance().font
|
||||
context.drawString(font, comp, x.toInt() - font.width(comp), y.toInt(), colour, shadow)
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun drawText(
|
||||
context: GuiGraphics,
|
||||
@@ -148,21 +161,6 @@ fun drawText(
|
||||
return isHovered
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun drawTextJustifiedRight(
|
||||
context: GuiGraphics,
|
||||
font: ResourceLocation? = null,
|
||||
text: MutableComponent,
|
||||
x: Number,
|
||||
y: Number,
|
||||
colour: Int,
|
||||
shadow: Boolean = true
|
||||
) {
|
||||
val comp = text.let { if (font != null) it.font(font) else it }
|
||||
val font = Minecraft.getInstance().font
|
||||
context.drawString(font, comp, x.toInt() - font.width(comp), y.toInt(), colour, shadow)
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun drawText(
|
||||
context: GuiGraphics,
|
||||
@@ -216,77 +214,60 @@ fun drawPosablePortrait(
|
||||
limbSwingAmount: Float = 0F,
|
||||
ageInTicks: Float = 0F,
|
||||
headYaw: Float = 0F,
|
||||
headPitch: Float = 0F,
|
||||
r: Float = 1F,
|
||||
g: Float = 1F,
|
||||
b: Float = 1F,
|
||||
a: Float = 1F
|
||||
headPitch: Float = 0F
|
||||
) {
|
||||
val model = repository.getPoser(identifier, aspects)
|
||||
state.currentAspects = aspects
|
||||
state.currentModel = model
|
||||
val texture = repository.getTexture(identifier, aspects, state.animationSeconds)
|
||||
|
||||
val context = RenderContext()
|
||||
model.context = context
|
||||
repository.getTextureNoSubstitute(identifier, aspects, 0f).let { context.put(RenderContext.TEXTURE, it) }
|
||||
context.put(RenderContext.SCALE, contextScale)
|
||||
context.put(RenderContext.SPECIES, identifier)
|
||||
context.put(RenderContext.ASPECTS, aspects)
|
||||
context.put(RenderContext.POSABLE_STATE, state)
|
||||
|
||||
val renderType = RenderType.entityCutout(texture)
|
||||
|
||||
RenderSystem.applyModelViewMatrix()
|
||||
val quaternion1 = Axis.YP.rotationDegrees(-32F * if (reversed) -1F else 1F)
|
||||
val quaternion2 = Axis.XP.rotationDegrees(5F)
|
||||
|
||||
val originalPose = state.currentPose
|
||||
state.setPoseToFirstSuitable(PoseType.PORTRAIT)
|
||||
state.updatePartialTicks(partialTicks)
|
||||
model.applyAnimations(null, state, limbSwing, limbSwingAmount, ageInTicks, headYaw, headPitch)
|
||||
originalPose?.let { state.setPose(it) }
|
||||
|
||||
matrixStack.pushPose()
|
||||
matrixStack.translate(0.0, PORTRAIT_DIAMETER.toDouble() + 2.0, 0.0)
|
||||
matrixStack.scale(scale, scale, -scale)
|
||||
matrixStack.translate(0.0, -PORTRAIT_DIAMETER / 18.0, 0.0)
|
||||
matrixStack.translate(model.portraitTranslation.x * if (reversed) -1F else 1F, model.portraitTranslation.y, model.portraitTranslation.z - 4)
|
||||
matrixStack.scale(model.portraitScale, model.portraitScale, 1 / model.portraitScale)
|
||||
matrixStack.mulPose(quaternion1) // TODO (techdaan): correct?
|
||||
matrixStack.mulPose(quaternion2)
|
||||
|
||||
val sprite = repository.getSprite(identifier, aspects, SpriteType.PORTRAIT);
|
||||
val light1 = Vector3f(0.2F, 1.0F, -1.0F)
|
||||
val light2 = Vector3f(0.1F, 0.0F, 8.0F)
|
||||
RenderSystem.setShaderLights(light1, light2)
|
||||
quaternion1.conjugate()
|
||||
|
||||
if (sprite == null) {
|
||||
val model = repository.getPoser(identifier, aspects)
|
||||
state.currentAspects = aspects
|
||||
state.currentModel = model
|
||||
val texture = repository.getTexture(identifier, aspects, state.animationSeconds)
|
||||
val immediate = Minecraft.getInstance().renderBuffers().bufferSource()
|
||||
val buffer = immediate.getBuffer(renderType)
|
||||
val packedLight = LightTexture.pack(11, 7)
|
||||
|
||||
val context = RenderContext()
|
||||
model.context = context
|
||||
repository.getTextureNoSubstitute(identifier, aspects, 0f).let { context.put(RenderContext.TEXTURE, it) }
|
||||
context.put(RenderContext.SCALE, contextScale)
|
||||
context.put(RenderContext.SPECIES, identifier)
|
||||
context.put(RenderContext.ASPECTS, aspects)
|
||||
context.put(RenderContext.POSABLE_STATE, state)
|
||||
|
||||
val renderType = RenderType.entityCutout(texture)
|
||||
|
||||
val quaternion1 = Axis.YP.rotationDegrees(-32F * if (reversed) -1F else 1F)
|
||||
val quaternion2 = Axis.XP.rotationDegrees(5F)
|
||||
|
||||
val originalPose = state.currentPose
|
||||
state.setPoseToFirstSuitable(PoseType.PORTRAIT)
|
||||
state.updatePartialTicks(partialTicks)
|
||||
model.applyAnimations(null, state, limbSwing, limbSwingAmount, ageInTicks, headYaw, headPitch)
|
||||
originalPose?.let { state.setPose(it) }
|
||||
|
||||
matrixStack.translate(
|
||||
model.portraitTranslation.x * if (reversed) -1F else 1F,
|
||||
model.portraitTranslation.y,
|
||||
model.portraitTranslation.z - 4
|
||||
)
|
||||
matrixStack.scale(model.portraitScale, model.portraitScale, 1 / model.portraitScale)
|
||||
matrixStack.mulPose(quaternion1)
|
||||
matrixStack.mulPose(quaternion2)
|
||||
|
||||
val light1 = Vector3f(0.2F, 1.0F, -1.0F)
|
||||
val light2 = Vector3f(0.1F, 0.0F, 8.0F)
|
||||
RenderSystem.setShaderLights(light1, light2)
|
||||
quaternion1.conjugate()
|
||||
|
||||
val immediate = Minecraft.getInstance().renderBuffers().bufferSource()
|
||||
val buffer = immediate.getBuffer(renderType)
|
||||
val packedLight = LightTexture.pack(11, 7)
|
||||
|
||||
val colour = toHex(r, g, b, a)
|
||||
model.withLayerContext(immediate, state, repository.getLayers(identifier, aspects)) {
|
||||
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, colour)
|
||||
immediate.endBatch()
|
||||
}
|
||||
|
||||
model.setDefault()
|
||||
|
||||
Lighting.setupFor3DItems()
|
||||
} else {
|
||||
renderSprite(matrixStack, sprite)
|
||||
model.withLayerContext(immediate, state, repository.getLayers(identifier, aspects)) {
|
||||
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
immediate.endBatch()
|
||||
}
|
||||
|
||||
matrixStack.popPose()
|
||||
model.setDefault()
|
||||
|
||||
Lighting.setupFor3DItems()
|
||||
}
|
||||
|
||||
fun drawProfile(
|
||||
@@ -298,75 +279,50 @@ fun drawProfile(
|
||||
partialTicks: Float,
|
||||
scale: Float = 20F
|
||||
) {
|
||||
val model = repository.getPoser(resourceIdentifier, aspects)
|
||||
val texture = repository.getTexture(resourceIdentifier, aspects, state.animationSeconds)
|
||||
|
||||
val context = RenderContext()
|
||||
model.context = context
|
||||
repository.getTextureNoSubstitute(resourceIdentifier, aspects, 0f).let { context.put(RenderContext.TEXTURE, it) }
|
||||
context.put(RenderContext.SCALE, 1F)
|
||||
context.put(RenderContext.SPECIES, resourceIdentifier)
|
||||
context.put(RenderContext.ASPECTS, aspects)
|
||||
context.put(RenderContext.POSABLE_STATE, state)
|
||||
state.currentAspects = aspects
|
||||
state.currentModel = model
|
||||
|
||||
val renderType = RenderType.entityCutout(texture)//model.getLayer(texture)
|
||||
|
||||
RenderSystem.applyModelViewMatrix()
|
||||
matrixStack.scale(scale, scale, -scale)
|
||||
|
||||
val sprite = repository.getSprite(resourceIdentifier, aspects, SpriteType.PROFILE);
|
||||
|
||||
if(sprite == null) {
|
||||
|
||||
val model = repository.getPoser(resourceIdentifier, aspects)
|
||||
val texture = repository.getTexture(resourceIdentifier, aspects, state.animationSeconds)
|
||||
|
||||
val context = RenderContext()
|
||||
model.context = context
|
||||
repository.getTextureNoSubstitute(resourceIdentifier, aspects, 0f)
|
||||
.let { context.put(RenderContext.TEXTURE, it) }
|
||||
context.put(RenderContext.SCALE, 1F)
|
||||
context.put(RenderContext.SPECIES, resourceIdentifier)
|
||||
context.put(RenderContext.ASPECTS, aspects)
|
||||
context.put(RenderContext.POSABLE_STATE, state)
|
||||
state.currentAspects = aspects
|
||||
state.currentModel = model
|
||||
|
||||
val renderType = RenderType.entityCutout(texture)//model.getLayer(texture)
|
||||
|
||||
state.setPoseToFirstSuitable(PoseType.PORTRAIT)
|
||||
state.updatePartialTicks(partialTicks)
|
||||
model.applyAnimations(null, state, 0F, 0F, 0F, 0F, 0F)
|
||||
matrixStack.translate(model.profileTranslation.x, model.profileTranslation.y, model.profileTranslation.z - 4.0)
|
||||
matrixStack.scale(model.profileScale, model.profileScale, 1 / model.profileScale)
|
||||
state.setPoseToFirstSuitable(PoseType.PORTRAIT)
|
||||
state.updatePartialTicks(partialTicks)
|
||||
model.applyAnimations(null, state, 0F, 0F, 0F, 0F, 0F)
|
||||
matrixStack.translate(model.profileTranslation.x, model.profileTranslation.y, model.profileTranslation.z - 4.0)
|
||||
matrixStack.scale(model.profileScale, model.profileScale, 1 / model.profileScale)
|
||||
// matrixStack.multiply(rotation)
|
||||
val quaternion1 = Axis.YP.rotationDegrees(-32F * if (false) -1F else 1F)
|
||||
val quaternion2 = Axis.XP.rotationDegrees(5F)
|
||||
matrixStack.mulPose(quaternion1)
|
||||
matrixStack.mulPose(quaternion2)
|
||||
Lighting.setupForEntityInInventory()
|
||||
val entityRenderDispatcher = Minecraft.getInstance().entityRenderDispatcher
|
||||
entityRenderDispatcher.setRenderShadow(true)
|
||||
val quaternion1 = Axis.YP.rotationDegrees(-32F * if (false) -1F else 1F)
|
||||
val quaternion2 = Axis.XP.rotationDegrees(5F)
|
||||
matrixStack.mulPose(quaternion1)
|
||||
matrixStack.mulPose(quaternion2)
|
||||
Lighting.setupForEntityInInventory() // TODO (techdaan): Does this map correctly?
|
||||
val entityRenderDispatcher = Minecraft.getInstance().entityRenderDispatcher
|
||||
entityRenderDispatcher.setRenderShadow(true)
|
||||
|
||||
val bufferSource = Minecraft.getInstance().renderBuffers().bufferSource()
|
||||
val buffer = bufferSource.getBuffer(renderType)
|
||||
val light1 = Vector3f(-1F, 1F, 1.0F)
|
||||
val light2 = Vector3f(1.3F, -1F, 1.0F)
|
||||
RenderSystem.setShaderLights(light1, light2)
|
||||
val packedLight = LightTexture.pack(11, 7)
|
||||
val bufferSource = Minecraft.getInstance().renderBuffers().bufferSource()
|
||||
val buffer = bufferSource.getBuffer(renderType)
|
||||
val light1 = Vector3f(-1F, 1F, 1.0F)
|
||||
val light2 = Vector3f(1.3F, -1F, 1.0F)
|
||||
RenderSystem.setShaderLights(light1, light2)
|
||||
val packedLight = LightTexture.pack(11, 7)
|
||||
|
||||
model.withLayerContext(bufferSource, state, repository.getLayers(resourceIdentifier, aspects)) {
|
||||
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
bufferSource.endBatch()
|
||||
}
|
||||
model.setDefault()
|
||||
entityRenderDispatcher.setRenderShadow(true)
|
||||
Lighting.setupFor3DItems()
|
||||
} else {
|
||||
renderSprite(matrixStack, sprite)
|
||||
model.withLayerContext(bufferSource, state, repository.getLayers(resourceIdentifier, aspects)) {
|
||||
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
bufferSource.endBatch()
|
||||
}
|
||||
}
|
||||
|
||||
fun renderSprite(matrixStack: PoseStack, sprite: ResourceLocation) {
|
||||
val matrix: PoseStack.Pose = matrixStack.last()
|
||||
matrix.pose().translate(-1f, 0f, 0f)
|
||||
|
||||
RenderSystem.setShaderTexture(0, sprite);
|
||||
RenderSystem.setShader(GameRenderer::getPositionTexShader)
|
||||
|
||||
var buffer = Tesselator.getInstance().begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX)
|
||||
|
||||
buffer.addVertex(matrix, 2f, 0f, 0.0f).setUv(1f, 0f)
|
||||
buffer.addVertex(matrix, 0f, 0f, 0.0f).setUv(0f, 0f)
|
||||
buffer.addVertex(matrix, 0f, 2f, 0.0f).setUv(0f, 1f)
|
||||
buffer.addVertex(matrix, 2f, 2f, 0.0f).setUv(1f, 1f)
|
||||
|
||||
BufferUploader.drawWithShader(buffer.buildOrThrow())
|
||||
model.setDefault()
|
||||
entityRenderDispatcher.setRenderShadow(true)
|
||||
Lighting.setupFor3DItems()
|
||||
}
|
||||
@@ -41,27 +41,20 @@ class MultiLineLabelK(
|
||||
fun renderLeftAligned(
|
||||
context: GuiGraphics,
|
||||
x: Number, y: Number,
|
||||
YStartOffset: Number = 0,
|
||||
ySpacing: Number,
|
||||
colour: Int,
|
||||
scale: Float = 1F,
|
||||
shadow: Boolean = true
|
||||
) {
|
||||
context.pose().pushPose()
|
||||
context.pose().scale(scale, scale, 1F)
|
||||
comps.forEachIndexed { index, textWithWidth ->
|
||||
val yOffset = if (index == 0) YStartOffset else 0
|
||||
drawString(
|
||||
context = context,
|
||||
x = x.toFloat() / scale,
|
||||
y = (y.toFloat() + yOffset.toFloat() + ySpacing.toFloat() * index) / scale,
|
||||
x = x, y = y.toFloat() + ySpacing.toFloat() * index,
|
||||
colour = colour,
|
||||
shadow = shadow,
|
||||
text = textWithWidth.text.string,
|
||||
font = font
|
||||
)
|
||||
}
|
||||
context.pose().popPose()
|
||||
}
|
||||
|
||||
class TextWithWidth internal constructor(val text: FormattedText, val width: Int)
|
||||
|
||||
@@ -99,7 +99,7 @@ interface PokemonSelectingItem {
|
||||
stack.shrink(1)
|
||||
battlePokemon.actor.itemsUsed.add(bagItem)
|
||||
}
|
||||
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(battlePokemon.effectedPokemon.species.resourceIdentifier, BuiltInRegistries.ITEM.getKey(stack.item)))
|
||||
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(battlePokemon.entity!!.pokemon.species.resourceIdentifier, BuiltInRegistries.ITEM.getKey(stack.item)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,6 @@ package com.cobblemon.mod.common.api.molang
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.mojang.serialization.Codec
|
||||
|
||||
/**
|
||||
* An object that can be given a [MoLangRuntime] to produce a single [MoValue]. This abstracts
|
||||
@@ -33,11 +31,4 @@ interface ExpressionLike {
|
||||
fun resolveBoolean(runtime: MoLangRuntime) = resolveDouble(runtime) == 1.0
|
||||
fun resolveObject(runtime: MoLangRuntime) = resolve(runtime) as ObjectValue<*>
|
||||
|
||||
companion object {
|
||||
val CODEC: Codec<ExpressionLike> = Codec.STRING.xmap({
|
||||
it.asExpressionLike()
|
||||
}) {
|
||||
it.getString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,10 @@ class MoveSet : Iterable<Move> {
|
||||
/**
|
||||
* Gets all Moves from the Pokémon but skips null Moves
|
||||
*/
|
||||
fun getMoves() = moves.filterNotNull()
|
||||
fun getMovesWithNulls() = moves.toList()
|
||||
fun getMoves(): List<Move> {
|
||||
return moves.filterNotNull()
|
||||
}
|
||||
|
||||
fun hasSpace() = moves.any { it == null }
|
||||
|
||||
/**
|
||||
@@ -123,7 +125,6 @@ class MoveSet : Iterable<Move> {
|
||||
for (i in 0 until MOVE_COUNT) {
|
||||
if (moves[i] == null) {
|
||||
moves[i] = move
|
||||
move.observable.subscribe { this.update() }
|
||||
update()
|
||||
return
|
||||
}
|
||||
|
||||
+1
-1
@@ -90,7 +90,7 @@ interface EntityProvider {
|
||||
}
|
||||
|
||||
//class MoveAnimationKeyframe(
|
||||
// val sound: ResourceLocation? = null,
|
||||
// val sound: Identifier? = null,
|
||||
// val animation: List<AnimationWithMoments> = listOf(),
|
||||
// val effects: List<ActionEffect> = listOf()
|
||||
//)
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import java.util.concurrent.CompletableFuture
|
||||
|
||||
class CannotInterruptActionEffectKeyframe : ConditionalActionEffectKeyframe() {
|
||||
override fun playWhenTrue(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
context.canBeInterrupted = false
|
||||
context.canBeInterrupted = true
|
||||
return CompletableFuture.completedFuture(Unit)
|
||||
}
|
||||
}
|
||||
@@ -71,7 +71,6 @@ object CobblemonPermissions {
|
||||
|
||||
val CLEAR_PARTY = this.create("${COMMAND_PREFIX}clearparty", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
val CLEAR_PC = this.create("${COMMAND_PREFIX}clearpc", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
val POKEDEX = this.create("${COMMAND_PREFIX}pokedex", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
val NPC_EDIT = this.create("${COMMAND_PREFIX}npcedit", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
|
||||
@@ -163,6 +163,7 @@ object PokeBalls : JsonDataRegistry<PokeBall> {
|
||||
createDefault("safari_ball", CatchRateModifiers.SAFARI)
|
||||
createDefault("fast_ball", BaseStatModifier(Stats.SPEED, { it >= 100 }, 4F))
|
||||
createDefault("level_ball", CatchRateModifiers.LEVEL)
|
||||
// ToDo we will need fishing context here once fishing is implemented for a multiplier
|
||||
createDefault("lure_ball", CatchRateModifiers.LURE)
|
||||
createDefault("heavy_ball", CatchRateModifiers.WEIGHT_BASED)
|
||||
createDefault("love_ball", CatchRateModifiers.LOVE)
|
||||
|
||||
-152
@@ -1,152 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokedex
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addStandardFunctions
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexForm
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
abstract class AbstractPokedexManager {
|
||||
open val speciesRecords: MutableMap<ResourceLocation, SpeciesDexRecord> = mutableMapOf()
|
||||
private val dexCalculatedValues = mutableMapOf<ResourceLocation, MutableMap<PokedexValueCalculator<*>, Any>>()
|
||||
private val globalCalculatedValues = mutableMapOf<GlobalPokedexValueCalculator<*>, Any>()
|
||||
|
||||
@Transient
|
||||
val struct = QueryStruct(hashMapOf()).addStandardFunctions()
|
||||
.addFunction("get_species_record") { params ->
|
||||
val speciesId = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
speciesRecords[speciesId]?.struct ?: QueryStruct(hashMapOf())
|
||||
}
|
||||
|
||||
fun deleteSpeciesRecord(speciesId: ResourceLocation) {
|
||||
speciesRecords.remove(speciesId)
|
||||
markDirty()
|
||||
}
|
||||
|
||||
fun getSpeciesRecord(speciesId: ResourceLocation): SpeciesDexRecord? {
|
||||
return speciesRecords[speciesId]
|
||||
}
|
||||
|
||||
fun getOrCreateSpeciesRecord(speciesId: ResourceLocation): SpeciesDexRecord {
|
||||
return speciesRecords.getOrPut(speciesId) {
|
||||
val record = SpeciesDexRecord()
|
||||
record.initialize(this, speciesId)
|
||||
onSpeciesRecordUpdated(record)
|
||||
record
|
||||
}
|
||||
}
|
||||
|
||||
fun getHighestKnowledgeFor(entry: PokedexEntry): PokedexEntryProgress {
|
||||
val speciesRecord = getSpeciesRecord(entry.speciesId) ?: return PokedexEntryProgress.NONE
|
||||
val hasAllAspects = entry.conditionAspects.all(speciesRecord::hasAspect)
|
||||
if (!hasAllAspects) {
|
||||
return PokedexEntryProgress.NONE
|
||||
}
|
||||
// For each distinct form in this entry, get the highest knowledge level for the unlock forms, then take the highest of those.
|
||||
return entry.forms.maxOfOrNull { form ->
|
||||
form.unlockForms.maxOfOrNull {
|
||||
speciesRecord.getFormRecord(it)?.knowledge ?: PokedexEntryProgress.NONE
|
||||
} ?: PokedexEntryProgress.NONE
|
||||
} ?: PokedexEntryProgress.NONE
|
||||
}
|
||||
|
||||
fun getEncounteredForms(entry: PokedexEntry) : List<PokedexForm> {
|
||||
return getFormsWithKnowledge(entry, PokedexEntryProgress.ENCOUNTERED)
|
||||
}
|
||||
|
||||
fun getCaughtForms(entry: PokedexEntry) : List<PokedexForm> {
|
||||
return getFormsWithKnowledge(entry, PokedexEntryProgress.CAUGHT)
|
||||
}
|
||||
|
||||
fun getFormsWithKnowledge(entry: PokedexEntry, knowledge: PokedexEntryProgress) : List<PokedexForm> {
|
||||
val speciesRecord = getSpeciesRecord(entry.speciesId) ?: return emptyList()
|
||||
val hasAllAspects = entry.conditionAspects.all(speciesRecord::hasAspect)
|
||||
if (!hasAllAspects) {
|
||||
return emptyList()
|
||||
}
|
||||
// For each distinct form in this entry, get the highest knowledge level for the unlock forms, then take the highest of those.
|
||||
return entry.forms.filter { form ->
|
||||
form.unlockForms.any { (speciesRecord.getFormRecord(it)?.knowledge ?: PokedexEntryProgress.NONE) >= knowledge }
|
||||
}
|
||||
}
|
||||
|
||||
fun getSeenShinyStates(entry: PokedexEntry, form: PokedexForm): Set<String> {
|
||||
return getSpeciesRecord(entry.speciesId)?.getFormRecord(form.displayForm)?.getSeenShinyStates() ?: return emptySet()
|
||||
}
|
||||
|
||||
fun getSeenGenders(entry: PokedexEntry, form: PokedexForm): Set<Gender> {
|
||||
return getSpeciesRecord(entry.speciesId)?.getFormRecord(form.displayForm)?.getGenders() ?: emptySet()
|
||||
}
|
||||
|
||||
fun getSeenAspects(entry: PokedexEntry): Set<String> {
|
||||
return getSpeciesRecord(entry.speciesId)?.getAspects() ?: emptySet()
|
||||
}
|
||||
|
||||
fun getKnowledgeForSpecies(speciesId: ResourceLocation): PokedexEntryProgress {
|
||||
return speciesRecords[speciesId]?.getKnowledge() ?: PokedexEntryProgress.NONE
|
||||
}
|
||||
|
||||
open fun onSpeciesRecordUpdated(speciesDexRecord: SpeciesDexRecord) {
|
||||
// Save stuff and packet updates
|
||||
dexCalculatedValues.clear()
|
||||
globalCalculatedValues.clear()
|
||||
}
|
||||
|
||||
fun <T : Any> getDexCalculatedValue(dex: ResourceLocation, calculatedPokedexValue: PokedexValueCalculator<T>): T {
|
||||
val existingValue = dexCalculatedValues[dex]?.get(calculatedPokedexValue) as? T
|
||||
if (existingValue != null) {
|
||||
return existingValue
|
||||
} else {
|
||||
val vals = dexCalculatedValues.getOrPut(dex) { mutableMapOf() }
|
||||
val newValue = calculatedPokedexValue.calculate(this, Dexes.dexEntryMap[dex]!!.getEntries().associateBy { it.id })
|
||||
vals[calculatedPokedexValue] = newValue
|
||||
return newValue
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : Any> getGlobalCalculatedValue(calculatedPokedexValue: GlobalPokedexValueCalculator<T>): T {
|
||||
val existingValue = globalCalculatedValues[calculatedPokedexValue] as? T
|
||||
if (existingValue != null) {
|
||||
return existingValue
|
||||
} else {
|
||||
val newValue = calculatedPokedexValue.calculate(this)
|
||||
globalCalculatedValues[calculatedPokedexValue] = newValue
|
||||
return newValue
|
||||
}
|
||||
}
|
||||
|
||||
open fun markDirty() {
|
||||
// Save stuff
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val NUM_CAUGHT_KEY = "cobblemon.pokedex.entries.caught"
|
||||
const val NUM_SEEN_KEY = "cobblemon.pokedex.entries.seen"
|
||||
|
||||
fun getKeyForSpeciesBase(speciesId: ResourceLocation): String {
|
||||
return "cobblemon.pokedex.${speciesId.path}"
|
||||
}
|
||||
|
||||
fun getKnowledgeKeyForSpecies(speciesId: ResourceLocation): String {
|
||||
return "${getKeyForSpeciesBase(speciesId)}.knowledge"
|
||||
}
|
||||
|
||||
fun getKnowledgeKeyForForm(speciesId: ResourceLocation, formName: String): String {
|
||||
return "${getKnowledgeKeyForSpecies(speciesId)}.${formName.lowercase()}"
|
||||
}
|
||||
|
||||
fun getCaptureMethodKeyForSpecies(speciesId: ResourceLocation): String {
|
||||
return "${getKeyForSpeciesBase(speciesId)}.capturemethod"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokedex
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.pokedex.DexAdditions.DexAddition
|
||||
import com.cobblemon.mod.common.api.pokedex.def.AggregatePokedexDef
|
||||
import com.cobblemon.mod.common.api.pokedex.def.SimplePokedexDef
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.DexEntries
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
|
||||
object DexAdditions : JsonDataRegistry<DexAddition> {
|
||||
override val id = cobblemonResource("dex_additions")
|
||||
override val type = PackType.SERVER_DATA
|
||||
override val observable = SimpleObservable<DexAdditions>()
|
||||
|
||||
override val gson: Gson = GsonBuilder()
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.disableHtmlEscaping()
|
||||
.setPrettyPrinting()
|
||||
.create()
|
||||
|
||||
override val typeToken: TypeToken<DexAddition> = TypeToken.get(DexAddition::class.java)
|
||||
override val resourcePath = "dex_additions"
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, DexAddition>) {
|
||||
data.entries.forEach { (key, value) ->
|
||||
Dexes.dexEntryMap[value.dexId]?.let { dexDef ->
|
||||
if (dexDef is SimplePokedexDef) {
|
||||
var invalid = false
|
||||
value.entries.forEach {
|
||||
if (!DexEntries.entries.containsKey(it)) {
|
||||
invalid = true
|
||||
Cobblemon.LOGGER.error("Unable to apply dex addition {} as the entry {} does not exist", key, it)
|
||||
}
|
||||
}
|
||||
if (invalid) {
|
||||
return@forEach
|
||||
}
|
||||
dexDef.appendEntries(value.entries)
|
||||
} else if (dexDef is AggregatePokedexDef) {
|
||||
var invalid = false
|
||||
value.entries.forEach {
|
||||
if (!Dexes.dexEntryMap.containsKey(it)) {
|
||||
invalid = true
|
||||
Cobblemon.LOGGER.error("Unable to apply dex addition {} as the sub-dex {} does not exist", key, it)
|
||||
}
|
||||
}
|
||||
dexDef.appendSubDexIds(value.entries)
|
||||
}
|
||||
} ?: Cobblemon.LOGGER.error("Unable to apply dex addition {} as the dex {} does not exist", key, value.dexId)
|
||||
}
|
||||
observable.emit(this)
|
||||
}
|
||||
|
||||
override fun sync(player: ServerPlayer) {} // Will be synced as part of the dexes
|
||||
|
||||
class DexAddition {
|
||||
val dexId: ResourceLocation = ResourceLocation.parse("cobblemon:national")
|
||||
/** Could be PokedexEntry locations or PokedexDef locations depending on what type dex the dexId points to. */
|
||||
val entries = mutableListOf<ResourceLocation>()
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokedex
|
||||
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.pokedex.def.PokedexDef
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.DexEntries
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.net.messages.client.data.PokedexDexSyncPacket
|
||||
import com.cobblemon.mod.common.util.adapters.CodecBackedAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
|
||||
object Dexes : JsonDataRegistry<PokedexDef> {
|
||||
override val id = cobblemonResource("dexes")
|
||||
override val type = PackType.SERVER_DATA
|
||||
override val observable = SimpleObservable<Dexes>()
|
||||
|
||||
override val gson: Gson = GsonBuilder()
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.registerTypeAdapter(PokedexDef::class.java, CodecBackedAdapter(PokedexDef.CODEC))
|
||||
.disableHtmlEscaping()
|
||||
.setPrettyPrinting()
|
||||
.create()
|
||||
|
||||
override val typeToken: TypeToken<PokedexDef> = TypeToken.get(PokedexDef::class.java)
|
||||
override val resourcePath = "dexes"
|
||||
|
||||
//Maps a dex id to its PokedexDef
|
||||
val dexEntryMap = linkedMapOf<ResourceLocation, PokedexDef>()
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, PokedexDef>) {
|
||||
dexEntryMap.clear()
|
||||
data.entries.sortedBy { it.value.sortOrder }.forEach { (id, def) -> dexEntryMap[id] = def }
|
||||
observable.emit(this)
|
||||
}
|
||||
|
||||
override fun sync(player: ServerPlayer) {
|
||||
PokedexDexSyncPacket(dexEntryMap.values)
|
||||
}
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokedex
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.struct.VariableStruct
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.readEnumConstant
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeEnumConstant
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import com.google.common.collect.Sets
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.ListCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
/**
|
||||
* A record of a form in the Pokédex. There are a number of tracked properties regarding the form and what
|
||||
* the dex has seen, and adding to it can be done through [encountered] and [caught].
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since August 23rd, 2024
|
||||
*/
|
||||
class FormDexRecord {
|
||||
companion object {
|
||||
val CODEC: Codec<FormDexRecord> = RecordCodecBuilder.create { instance ->
|
||||
instance.group(
|
||||
ListCodec(Codec.STRING, 0, 3).fieldOf("genders").forGetter { it.genders.map { it.name } },
|
||||
ListCodec(Codec.STRING, 0, 2).fieldOf("seenShinyStates").forGetter { it.seenShinyStates.toList() },
|
||||
Codec.STRING.fieldOf("knowledge").forGetter { it.knowledge.name }
|
||||
).apply(instance) { genders, seenShinyStates, knowledge ->
|
||||
FormDexRecord().also {
|
||||
it.genders.addAll(genders.map(Gender::valueOf))
|
||||
it.seenShinyStates.addAll(seenShinyStates)
|
||||
it.knowledge = PokedexEntryProgress.valueOf(knowledge)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** The genders that the dex is aware of. */
|
||||
private val genders: MutableSet<Gender> = mutableSetOf()
|
||||
/** Shiny states could be shiny or non-shiny - on the off chance they only saw the shiny, they shouldn't know what the normal looks like. */
|
||||
private val seenShinyStates = mutableSetOf<String>() // consider: radiants in the future (radiants should just be a resource pack tbh)
|
||||
/** The current awareness of the form that the dex has. */
|
||||
var knowledge = PokedexEntryProgress.NONE
|
||||
private set
|
||||
|
||||
private val data = VariableStruct() // Could use this for various other properties maybe, consider this a draft
|
||||
|
||||
@Transient
|
||||
lateinit var speciesDexRecord: SpeciesDexRecord
|
||||
|
||||
@Transient
|
||||
lateinit var struct: QueryStruct
|
||||
|
||||
fun initialize(speciesDexRecord: SpeciesDexRecord) {
|
||||
this.speciesDexRecord = speciesDexRecord
|
||||
struct = QueryStruct(hashMapOf())
|
||||
.addFunction("data") { data }
|
||||
.addFunction("knowledge") { StringValue(knowledge.name) }
|
||||
.addFunction("has_seen_gender") { params -> genders.contains(Gender.valueOf(params.getString(0).uppercase())) }
|
||||
}
|
||||
|
||||
fun encountered(pokemon: Pokemon) {
|
||||
if (wouldBeDifferent(pokemon, PokedexEntryProgress.ENCOUNTERED)) {
|
||||
addInformation(pokemon, PokedexEntryProgress.ENCOUNTERED)
|
||||
}
|
||||
}
|
||||
|
||||
fun caught(pokemon: Pokemon) {
|
||||
if (wouldBeDifferent(pokemon, PokedexEntryProgress.CAUGHT)) {
|
||||
addInformation(pokemon, PokedexEntryProgress.CAUGHT)
|
||||
}
|
||||
}
|
||||
|
||||
fun getGenders(): Set<Gender> = genders
|
||||
fun hasSeenShinyState(shiny: Boolean): Boolean = seenShinyStates.contains(if (shiny) "shiny" else "normal")
|
||||
fun getSeenShinyStates(): Set<String> = seenShinyStates
|
||||
|
||||
//Used when granting all entries in dex, should figure out better way
|
||||
fun addAllShinyStatesAndGenders() {
|
||||
genders.addAll(listOf(Gender.MALE, Gender.FEMALE))
|
||||
seenShinyStates.addAll(listOf("shiny", "normal"))
|
||||
}
|
||||
|
||||
fun setKnowledgeProgress(newKnowledge: PokedexEntryProgress) {
|
||||
knowledge = newKnowledge
|
||||
speciesDexRecord.onFormRecordUpdated(this)
|
||||
}
|
||||
|
||||
private fun addInformation(pokemon: Pokemon, knowledge: PokedexEntryProgress) {
|
||||
genders.add(pokemon.gender)
|
||||
seenShinyStates.add(if (pokemon.shiny) "shiny" else "normal")
|
||||
if (knowledge.ordinal > this.knowledge.ordinal) {
|
||||
this.knowledge = knowledge
|
||||
}
|
||||
speciesDexRecord.addInformation(pokemon, knowledge)
|
||||
speciesDexRecord.onFormRecordUpdated(this)
|
||||
}
|
||||
|
||||
/** Returns whether the given [Pokemon] and [knowledge] would add new information to the Pokédex.*/
|
||||
fun wouldBeDifferent(pokemon: Pokemon, knowledge: PokedexEntryProgress): Boolean {
|
||||
return pokemon.gender !in genders
|
||||
|| (pokemon.shiny && "shiny" !in seenShinyStates)
|
||||
|| (!pokemon.shiny && "normal" !in seenShinyStates)
|
||||
|| knowledge.ordinal > this.knowledge.ordinal
|
||||
|| speciesDexRecord.wouldBeDifferent(pokemon)
|
||||
}
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeCollection(genders) { _, it -> buffer.writeEnumConstant(it) }
|
||||
buffer.writeCollection(seenShinyStates) { _, it -> buffer.writeString(it) }
|
||||
buffer.writeEnumConstant(knowledge)
|
||||
}
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
genders.clear()
|
||||
seenShinyStates.clear()
|
||||
genders.addAll(buffer.readCollection(Sets::newHashSetWithExpectedSize) { buffer.readEnumConstant(Gender::class.java) })
|
||||
seenShinyStates.addAll(buffer.readCollection(Sets::newHashSetWithExpectedSize) { buffer.readString() })
|
||||
knowledge = buffer.readEnumConstant(PokedexEntryProgress::class.java)
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokedex
|
||||
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.PrimitiveCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.util.StringRepresentable
|
||||
|
||||
/**
|
||||
* Contains stats about a specific pokemon for putting in the pokedex
|
||||
*
|
||||
* @author JPAK, Apion
|
||||
* @since February 21, 2024
|
||||
*/
|
||||
enum class PokedexEntryProgress : StringRepresentable, Comparable<PokedexEntryProgress> {
|
||||
NONE,
|
||||
ENCOUNTERED,
|
||||
CAUGHT;
|
||||
|
||||
override fun getSerializedName() = this.name
|
||||
companion object {
|
||||
val CODEC: Codec<PokedexEntryProgress> = RecordCodecBuilder.create { instance ->
|
||||
instance.map ({
|
||||
PokedexEntryProgress.valueOf(it)
|
||||
}, PrimitiveCodec.STRING.fieldOf("name").forGetter { it.name })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokedex
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.storage.player.InstancedPlayerData
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreType
|
||||
import com.cobblemon.mod.common.api.storage.player.client.ClientPokedexManager
|
||||
import com.cobblemon.mod.common.net.messages.client.SetClientPlayerDataPacket
|
||||
import com.cobblemon.mod.common.pokemon.FormData
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.Species
|
||||
import com.cobblemon.mod.common.util.getPlayer
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.PrimitiveCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import java.util.UUID
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class PokedexManager(
|
||||
override val uuid: UUID,
|
||||
override val speciesRecords: MutableMap<ResourceLocation, SpeciesDexRecord>
|
||||
) : AbstractPokedexManager(), InstancedPlayerData {
|
||||
|
||||
fun encounter(pokemon: Pokemon) {
|
||||
val speciesId = pokemon.species.resourceIdentifier
|
||||
val formName = pokemon.form.name
|
||||
getOrCreateSpeciesRecord(speciesId).getOrCreateFormRecord(formName).encountered(pokemon)
|
||||
}
|
||||
|
||||
fun catch(pokemon: Pokemon) {
|
||||
val speciesId = pokemon.species.resourceIdentifier
|
||||
val formName = pokemon.form.name
|
||||
getOrCreateSpeciesRecord(speciesId).getOrCreateFormRecord(formName).caught(pokemon)
|
||||
}
|
||||
|
||||
override fun markDirty() {
|
||||
}
|
||||
|
||||
override fun initialize() {
|
||||
speciesRecords.entries.forEach { (key, value) -> value.initialize(this, key) }
|
||||
}
|
||||
|
||||
override fun onSpeciesRecordUpdated(speciesDexRecord: SpeciesDexRecord) {
|
||||
uuid.getPlayer()?.sendPacket(
|
||||
SetClientPlayerDataPacket(
|
||||
type = PlayerInstancedDataStoreType.POKEDEX,
|
||||
playerData = ClientPokedexManager(mutableMapOf(speciesDexRecord.id to speciesDexRecord)),
|
||||
isIncremental = true
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CODEC = RecordCodecBuilder.create<PokedexManager> { instance ->
|
||||
instance.group(
|
||||
PrimitiveCodec.STRING.fieldOf("uuid").forGetter { it.uuid.toString() },
|
||||
Codec.unboundedMap(ResourceLocation.CODEC, SpeciesDexRecord.CODEC).fieldOf("speciesRecords").forGetter { it.speciesRecords }
|
||||
).apply(instance) { uuid, map ->
|
||||
//Codec stuff seems to deserialize to an immutable map, so we have to convert it to mutable explicitly
|
||||
PokedexManager(UUID.fromString(uuid), map.toMutableMap()).also { it.initialize() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun toClientData() = ClientPokedexManager(speciesRecords)
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokedex
|
||||
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
interface PokedexValueCalculator<T> {
|
||||
fun calculate(dexManager: AbstractPokedexManager, dex: Map<ResourceLocation, PokedexEntry>): T
|
||||
}
|
||||
|
||||
interface GlobalPokedexValueCalculator<T> {
|
||||
fun calculate(dexManager: AbstractPokedexManager): T
|
||||
}
|
||||
|
||||
object CaughtCount : PokedexValueCalculator<Int> {
|
||||
override fun calculate(dexManager: AbstractPokedexManager, dex: Map<ResourceLocation, PokedexEntry>): Int {
|
||||
return dex.entries.map { it.value }.count { dexManager.getKnowledgeForSpecies(it.speciesId) == PokedexEntryProgress.CAUGHT }
|
||||
}
|
||||
}
|
||||
|
||||
object SeenCount : PokedexValueCalculator<Int> {
|
||||
override fun calculate(dexManager: AbstractPokedexManager, dex: Map<ResourceLocation, PokedexEntry>): Int {
|
||||
return dex.entries.map { it.value }.count { dexManager.getKnowledgeForSpecies(it.speciesId) != PokedexEntryProgress.NONE }
|
||||
}
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokedex
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addStandardFunctions
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import com.google.common.collect.Sets
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.ListCodec
|
||||
import com.mojang.serialization.codecs.PrimitiveCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import java.util.UUID
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
/**
|
||||
* Dex recorded information about a particular Pokémon species. This includes all forms and their information.
|
||||
* Across all forms there is a single list of known aspects which is generally used to track cosmetic variation
|
||||
* though technically things like gender and form-motivating aspects will get collected inadvertently.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since August 23rd, 2024
|
||||
*/
|
||||
class SpeciesDexRecord {
|
||||
companion object {
|
||||
val CODEC: Codec<SpeciesDexRecord> = RecordCodecBuilder.create { instance ->
|
||||
instance.group(
|
||||
ListCodec(PrimitiveCodec.STRING, 0, 512).fieldOf("aspects").forGetter { it.aspects.toList() },
|
||||
Codec.unboundedMap(Codec.STRING, FormDexRecord.CODEC).fieldOf("formRecords").forGetter { it.formRecords }
|
||||
).apply(instance) { aspects, formRecords ->
|
||||
SpeciesDexRecord().also {
|
||||
it.aspects.addAll(aspects)
|
||||
it.formRecords.putAll(formRecords)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Transient
|
||||
lateinit var id: ResourceLocation
|
||||
private val aspects: MutableSet<String> = mutableSetOf()
|
||||
private val formRecords: MutableMap<String, FormDexRecord> = mutableMapOf()
|
||||
|
||||
@Transient
|
||||
val struct = QueryStruct(hashMapOf()).addStandardFunctions()
|
||||
.addFunction("get_form_record") { params ->
|
||||
val formName = params.getString(0)
|
||||
formRecords[formName]?.struct ?: QueryStruct(hashMapOf())
|
||||
}
|
||||
.addFunction("get_or_create_form_record") { params ->
|
||||
getOrCreateFormRecord(params.getString(0)).struct
|
||||
}
|
||||
.addFunction("add_aspect") { params ->
|
||||
val aspect = params.getString(0)
|
||||
aspects.add(aspect)
|
||||
}
|
||||
.addFunction("has_knowledge") { params ->
|
||||
val knowledge = params.getString(0)
|
||||
DoubleValue(formRecords.values.any { it.knowledge.name.equals(knowledge.toString(), ignoreCase = true) })
|
||||
}
|
||||
.addFunction("is_caught") { params ->
|
||||
DoubleValue(formRecords.values.any { it.knowledge.name.equals("CAUGHT", ignoreCase = true) })
|
||||
}
|
||||
// more, also worth moving to something like MoLangFunctions.kt so it's easier to API in more values
|
||||
|
||||
@Transient
|
||||
lateinit var pokedexManager: AbstractPokedexManager
|
||||
|
||||
fun initialize(pokedexManager: AbstractPokedexManager, id: ResourceLocation) {
|
||||
this.id = id
|
||||
this.pokedexManager = pokedexManager
|
||||
this.formRecords.forEach { it.value.initialize(this) }
|
||||
}
|
||||
|
||||
fun onFormRecordUpdated(formDexRecord: FormDexRecord) {
|
||||
pokedexManager.onSpeciesRecordUpdated(this)
|
||||
}
|
||||
|
||||
fun addInformation(pokemon: Pokemon, knowledge: PokedexEntryProgress) {
|
||||
aspects.addAll(pokemon.aspects)
|
||||
}
|
||||
|
||||
fun addAspects(addedAspects: Set<String>) {
|
||||
aspects.addAll(addedAspects)
|
||||
}
|
||||
|
||||
/** Returns true if the given Pokémon contains new information. Internal because it's only to be called from [FormDexRecord.wouldBeDifferent]. */
|
||||
internal fun wouldBeDifferent(pokemon: Pokemon) = pokemon.aspects.any { it !in aspects }
|
||||
|
||||
fun getOrCreateFormRecord(formName: String): FormDexRecord {
|
||||
return formRecords.getOrPut(formName.lowercase()) {
|
||||
val record = FormDexRecord()
|
||||
record.initialize(this)
|
||||
onFormRecordUpdated(record)
|
||||
// Some more stuff eventually
|
||||
record
|
||||
}
|
||||
}
|
||||
|
||||
fun getFormRecord(formName: String): FormDexRecord? {
|
||||
return formRecords[formName.lowercase()]
|
||||
}
|
||||
|
||||
fun deleteFormRecord(formName: String) {
|
||||
formRecords.remove(formName)
|
||||
}
|
||||
|
||||
fun getAspects(): Set<String> = this.aspects
|
||||
fun hasAspect(aspect: String) = aspect in aspects
|
||||
fun getKnowledge() = formRecords.values.maxOfOrNull { it.knowledge } ?: PokedexEntryProgress.NONE
|
||||
fun hasAtLeast(knowledge: PokedexEntryProgress) = getKnowledge().ordinal >= knowledge.ordinal
|
||||
fun hasSeenForm(formName: String) = formRecords.entries.any { it.key.equals(formName, ignoreCase = true) && it.value.knowledge != PokedexEntryProgress.NONE }
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeCollection(aspects) { _, it -> buffer.writeString(it) }
|
||||
buffer.writeInt(formRecords.size)
|
||||
for ((formName, formRecord) in formRecords) {
|
||||
buffer.writeString(formName)
|
||||
formRecord.encode(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
aspects.clear()
|
||||
aspects.addAll(buffer.readCollection(Sets::newHashSetWithExpectedSize) { buffer.readString() })
|
||||
formRecords.clear()
|
||||
val numForms = buffer.readInt()
|
||||
for (i in 0 until numForms) {
|
||||
val formName = buffer.readString()
|
||||
val formRecord = FormDexRecord()
|
||||
formRecord.decode(buffer)
|
||||
formRecords[formName] = formRecord
|
||||
}
|
||||
}
|
||||
}
|
||||
-105
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokedex.def
|
||||
|
||||
import com.cobblemon.mod.common.api.pokedex.Dexes
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry
|
||||
import com.cobblemon.mod.common.net.IntSize
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readIdentifier
|
||||
import com.cobblemon.mod.common.util.readSizedInt
|
||||
import com.cobblemon.mod.common.util.writeIdentifier
|
||||
import com.cobblemon.mod.common.util.writeSizedInt
|
||||
import com.google.common.collect.Lists
|
||||
import com.mojang.serialization.MapCodec
|
||||
import com.mojang.serialization.codecs.PrimitiveCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import io.netty.buffer.ByteBuf
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.network.codec.ByteBufCodecs
|
||||
import net.minecraft.network.codec.StreamCodec
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class AggregatePokedexDef(
|
||||
override val id: ResourceLocation,
|
||||
) : PokedexDef() {
|
||||
override val typeId = ID
|
||||
private val subDexIds = mutableListOf<ResourceLocation>()
|
||||
var squash = true
|
||||
private set
|
||||
|
||||
fun appendSubDexIds(subDexIds: List<ResourceLocation>) {
|
||||
this.subDexIds.addAll(subDexIds)
|
||||
}
|
||||
|
||||
override fun getEntries(): List<PokedexEntry> {
|
||||
if (!squash) {
|
||||
return Dexes.dexEntryMap.values.filter { it.id in subDexIds }.flatMap { it.getEntries() }
|
||||
} else {
|
||||
val speciesToEntry = linkedMapOf<ResourceLocation, PokedexEntry>()
|
||||
subDexIds.forEach { dexId ->
|
||||
Dexes.dexEntryMap[dexId]?.getEntries()?.forEach { entry ->
|
||||
val preExisting = speciesToEntry[entry.speciesId]
|
||||
if (preExisting != null) {
|
||||
speciesToEntry[preExisting.speciesId] = preExisting.combinedWith(entry)
|
||||
} else {
|
||||
speciesToEntry[entry.speciesId] = entry
|
||||
}
|
||||
}
|
||||
}
|
||||
return speciesToEntry.values.toList()
|
||||
}
|
||||
}
|
||||
|
||||
override fun shouldSynchronize(other: PokedexDef) = true
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
sortOrder = buffer.readSizedInt(IntSize.U_BYTE)
|
||||
val size = buffer.readInt()
|
||||
for (i in 0 until size) {
|
||||
subDexIds.add(buffer.readIdentifier())
|
||||
}
|
||||
}
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeSizedInt(IntSize.U_BYTE, sortOrder)
|
||||
buffer.writeInt(subDexIds.size)
|
||||
subDexIds.forEach {
|
||||
buffer.writeIdentifier(it)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("aggregate_pokedex_def")
|
||||
val CODEC: MapCodec<AggregatePokedexDef> = RecordCodecBuilder.mapCodec { instance ->
|
||||
instance.group(
|
||||
ResourceLocation.CODEC.fieldOf("id").forGetter { it.id },
|
||||
PrimitiveCodec.INT.fieldOf("sortOrder").forGetter { it.sortOrder },
|
||||
ResourceLocation.CODEC.listOf().fieldOf("subDexIds").forGetter { it.subDexIds },
|
||||
PrimitiveCodec.BOOL.fieldOf("squash").forGetter { it.squash }
|
||||
).apply(instance) { id, sortOrder, entries, squash ->
|
||||
val result = AggregatePokedexDef(id)
|
||||
result.sortOrder = sortOrder
|
||||
result.subDexIds.addAll(entries)
|
||||
result.squash = squash
|
||||
result
|
||||
}
|
||||
}
|
||||
val PACKET_CODEC: StreamCodec<ByteBuf, AggregatePokedexDef> = StreamCodec.composite(
|
||||
ResourceLocation.STREAM_CODEC, AggregatePokedexDef::id,
|
||||
ByteBufCodecs.INT, AggregatePokedexDef::sortOrder,
|
||||
ByteBufCodecs.collection(Lists::newArrayListWithCapacity, ResourceLocation.STREAM_CODEC), AggregatePokedexDef::subDexIds
|
||||
) { id, sortOrder, entries ->
|
||||
val result = AggregatePokedexDef(id)
|
||||
result.sortOrder = sortOrder
|
||||
//result.subDexIds.addAll(entries)
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokedex.def
|
||||
|
||||
import com.cobblemon.mod.common.api.data.ClientDataSynchronizer
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.DexEntries
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.MapCodec
|
||||
import io.netty.buffer.ByteBuf
|
||||
import net.minecraft.network.codec.StreamCodec
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
/**
|
||||
* A class that defines what entries are in a Pokedex
|
||||
*
|
||||
* @since August 24, 2024
|
||||
* @author Apion
|
||||
*/
|
||||
abstract class PokedexDef: ClientDataSynchronizer<PokedexDef> {
|
||||
//The ID used to find the codecs for this "type" of PokedexDef
|
||||
abstract val typeId: ResourceLocation
|
||||
//The ID of this dex in the Dexes registry
|
||||
abstract val id: ResourceLocation
|
||||
// The sort order for the dex
|
||||
var sortOrder: Int = 0
|
||||
|
||||
abstract fun getEntries(): List<PokedexEntry>
|
||||
|
||||
companion object {
|
||||
val CODEC: Codec<PokedexDef> = ResourceLocation.CODEC.dispatch("type", PokedexDef::typeId, PokedexDef::getCodecById)
|
||||
val PACKET_CODEC: StreamCodec<ByteBuf, PokedexDef> = ResourceLocation.STREAM_CODEC.dispatch({ it.typeId }, ::getPacketCodecById)
|
||||
|
||||
fun getPacketCodecById(id: ResourceLocation): StreamCodec<ByteBuf, out PokedexDef> {
|
||||
return when (id) {
|
||||
SimplePokedexDef.ID -> SimplePokedexDef.PACKET_CODEC
|
||||
AggregatePokedexDef.ID -> AggregatePokedexDef.PACKET_CODEC
|
||||
else -> throw NotImplementedError("Missing pokedex def packet codec for id: $id")
|
||||
}
|
||||
}
|
||||
|
||||
fun getCodecById(id: ResourceLocation): MapCodec<out PokedexDef> {
|
||||
return when (id) {
|
||||
SimplePokedexDef.ID -> SimplePokedexDef.CODEC
|
||||
AggregatePokedexDef.ID -> AggregatePokedexDef.CODEC
|
||||
else -> throw NotImplementedError("Missing pokedex def codec for id: $id")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokedex.def
|
||||
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.DexEntries
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry
|
||||
import com.cobblemon.mod.common.net.IntSize
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readIdentifier
|
||||
import com.cobblemon.mod.common.util.readSizedInt
|
||||
import com.cobblemon.mod.common.util.writeIdentifier
|
||||
import com.cobblemon.mod.common.util.writeSizedInt
|
||||
import com.google.common.collect.Lists
|
||||
import com.mojang.serialization.MapCodec
|
||||
import com.mojang.serialization.codecs.PrimitiveCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import io.netty.buffer.ByteBuf
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.network.codec.ByteBufCodecs
|
||||
import net.minecraft.network.codec.StreamCodec
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
/**
|
||||
* A [PokedexDef] that is just a list of [PokedexEntry]s
|
||||
*
|
||||
* @since August 24, 2024
|
||||
* @author Apion
|
||||
*/
|
||||
class SimplePokedexDef(
|
||||
override val id: ResourceLocation
|
||||
) : PokedexDef() {
|
||||
override val typeId = ID
|
||||
|
||||
private val entries = mutableListOf<ResourceLocation>()
|
||||
|
||||
fun appendEntries(entries: List<ResourceLocation>) {
|
||||
this.entries.addAll(entries)
|
||||
}
|
||||
|
||||
override fun getEntries() = entries.mapNotNull { DexEntries.entries[it] }
|
||||
|
||||
override fun shouldSynchronize(other: PokedexDef) = true
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
sortOrder = buffer.readSizedInt(IntSize.U_BYTE)
|
||||
val size = buffer.readInt()
|
||||
for (i in 0 until size) {
|
||||
entries.add(buffer.readIdentifier())
|
||||
}
|
||||
}
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeSizedInt(IntSize.U_BYTE, sortOrder)
|
||||
buffer.writeInt(entries.size)
|
||||
entries.forEach {
|
||||
buffer.writeIdentifier(it)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("simple_pokedex_def")
|
||||
val CODEC: MapCodec<SimplePokedexDef> = RecordCodecBuilder.mapCodec { instance ->
|
||||
instance.group(
|
||||
ResourceLocation.CODEC.fieldOf("id").forGetter { it.id },
|
||||
PrimitiveCodec.INT.fieldOf("sortOrder").forGetter { it.sortOrder },
|
||||
ResourceLocation.CODEC.listOf().fieldOf("entries").forGetter { it.entries }
|
||||
).apply(instance) { id, sortOrder, entries ->
|
||||
val result = SimplePokedexDef(id)
|
||||
result.sortOrder = sortOrder
|
||||
result.entries.addAll(entries)
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
val PACKET_CODEC: StreamCodec<ByteBuf, SimplePokedexDef> = StreamCodec.composite(
|
||||
ResourceLocation.STREAM_CODEC, SimplePokedexDef::id,
|
||||
ByteBufCodecs.INT, SimplePokedexDef::sortOrder,
|
||||
ByteBufCodecs.collection(Lists::newArrayListWithCapacity, ResourceLocation.STREAM_CODEC), SimplePokedexDef::entries
|
||||
) { id, sortOrder, entries ->
|
||||
val result = SimplePokedexDef(id)
|
||||
result.sortOrder = sortOrder
|
||||
result.entries.addAll(entries)
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokedex.entry
|
||||
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.net.messages.client.data.DexEntrySyncPacket
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
|
||||
object DexEntries : JsonDataRegistry<PokedexEntry> {
|
||||
override val id = cobblemonResource("dex_entries")
|
||||
override val type = PackType.SERVER_DATA
|
||||
|
||||
override val gson: Gson = GsonBuilder()
|
||||
.disableHtmlEscaping()
|
||||
.setPrettyPrinting()
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.create()
|
||||
|
||||
override val typeToken: TypeToken<PokedexEntry> = TypeToken.get(PokedexEntry::class.java)
|
||||
override val resourcePath = "dex_entries"
|
||||
|
||||
val entries = mutableMapOf<ResourceLocation, PokedexEntry>()
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, PokedexEntry>) {
|
||||
data.forEach { _, entry ->
|
||||
entries[entry.id] = entry
|
||||
if (entry.forms.isEmpty()) {
|
||||
entry.forms.add(PokedexForm())
|
||||
}
|
||||
entry.forms.forEach {
|
||||
if (it.unlockForms.isEmpty()) {
|
||||
it.unlockForms = mutableSetOf(it.displayForm)
|
||||
}
|
||||
}
|
||||
}
|
||||
observable.emit(this)
|
||||
}
|
||||
|
||||
override val observable = SimpleObservable<DexEntries>()
|
||||
override fun sync(player: ServerPlayer) {
|
||||
DexEntrySyncPacket(entries.values)
|
||||
}
|
||||
}
|
||||
-58
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokedex.entry
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
|
||||
object DexEntryAdditions : JsonDataRegistry<DexEntryAdditions.DexEntryAddition> {
|
||||
override val id = cobblemonResource("dex_entry_additions")
|
||||
override val type = PackType.SERVER_DATA
|
||||
|
||||
override val gson: Gson = GsonBuilder()
|
||||
.disableHtmlEscaping()
|
||||
.setPrettyPrinting()
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.create()
|
||||
|
||||
override val typeToken: TypeToken<DexEntryAddition> = TypeToken.get(DexEntryAddition::class.java)
|
||||
override val resourcePath = "dex_entry_additions"
|
||||
|
||||
override val observable = SimpleObservable<DexEntryAdditions>()
|
||||
|
||||
val entries = mutableListOf<PokedexEntry>()
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, DexEntryAddition>) {
|
||||
data.entries.forEach { (key, addition) ->
|
||||
DexEntries.entries[addition.entryId]?.add(addition)
|
||||
?: return@forEach Cobblemon.LOGGER.error("Unable to find dex entry {} to add to from dex entry addition {}", addition.entryId, key) // Skip if the entry doesn't exist
|
||||
}
|
||||
observable.emit(this)
|
||||
}
|
||||
|
||||
override fun sync(player: ServerPlayer) {} // It'd be synced as part of the DexEntries
|
||||
|
||||
class DexEntryAddition {
|
||||
val entryId: ResourceLocation = cobblemonResource("some_addition")
|
||||
val forms: List<PokedexForm> = emptyList()
|
||||
val variations: List<PokedexCosmeticVariation> = emptyList()
|
||||
}
|
||||
}
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokedex.entry
|
||||
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
/**
|
||||
* Controls a toggle in the Pokédex GUI that iterates through some set of aspects that
|
||||
* presumably match a species feature or other aspect provider on the server side. This is
|
||||
* used to let the player check out the different variations of a Pokémon.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since August 25th, 2025
|
||||
*/
|
||||
class PokedexCosmeticVariation {
|
||||
var displayName: String = "cobblemon.pokedex.variation.cosmetic"
|
||||
var icon: ResourceLocation = cobblemonResource("textures/gui/pokedex/variation/cosmetic.png")
|
||||
var aspects: Set<String> = emptySet()
|
||||
|
||||
fun clone() = PokedexCosmeticVariation().also {
|
||||
it.displayName = displayName
|
||||
it.icon = icon
|
||||
it.aspects = aspects.toSet()
|
||||
}
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeString(displayName)
|
||||
buffer.writeResourceLocation(icon)
|
||||
buffer.writeCollection(aspects) { _, aspect -> buffer.writeString(aspect) }
|
||||
}
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
displayName = buffer.readString()
|
||||
icon = buffer.readResourceLocation()
|
||||
aspects = buffer.readList { buffer.readString() }.toSet()
|
||||
}
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokedex.entry
|
||||
|
||||
import com.cobblemon.mod.common.util.readIdentifier
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeIdentifier
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class PokedexEntry(
|
||||
val id: ResourceLocation,
|
||||
val speciesId: ResourceLocation,
|
||||
val displayAspects: MutableSet<String> = mutableSetOf(),
|
||||
val conditionAspects: MutableSet<String> = mutableSetOf(),
|
||||
val forms: MutableList<PokedexForm> = mutableListOf(),
|
||||
val variations: MutableList<PokedexCosmeticVariation> = mutableListOf()
|
||||
) {
|
||||
fun clone() = PokedexEntry(
|
||||
id,
|
||||
speciesId,
|
||||
displayAspects,
|
||||
conditionAspects,
|
||||
forms.map { it.clone() }.toMutableList(),
|
||||
variations.map { it.clone() }.toMutableList()
|
||||
)
|
||||
|
||||
fun combinedWith(other: PokedexEntry): PokedexEntry {
|
||||
val copy = clone()
|
||||
other.forms.forEach { form ->
|
||||
if (form.displayForm !in copy.forms.map { it.displayForm }) {
|
||||
copy.forms.add(form.clone())
|
||||
} else {
|
||||
copy.forms.find { it.displayForm == form.displayForm }!!.unlockForms.addAll(form.unlockForms)
|
||||
}
|
||||
}
|
||||
other.variations.forEach { variation ->
|
||||
if (variation.displayName !in copy.variations.map { it.displayName }) {
|
||||
copy.variations.add(variation.clone())
|
||||
}
|
||||
}
|
||||
|
||||
return copy
|
||||
}
|
||||
|
||||
fun add(addition: DexEntryAdditions.DexEntryAddition) {
|
||||
addition.forms.forEach { form ->
|
||||
if (form.displayForm !in forms.map { it.displayForm }) {
|
||||
forms.add(form)
|
||||
} else {
|
||||
forms.find { it.displayForm == form.displayForm }!!.unlockForms.addAll(form.unlockForms)
|
||||
}
|
||||
}
|
||||
addition.variations.forEach { variation ->
|
||||
if (variation.displayName !in variations.map { it.displayName }) {
|
||||
variations.add(variation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun encode(buf: RegistryFriendlyByteBuf) {
|
||||
buf.writeIdentifier(id)
|
||||
buf.writeIdentifier(speciesId)
|
||||
buf.writeCollection(displayAspects) { _, aspect -> buf.writeString(aspect) }
|
||||
buf.writeCollection(conditionAspects) { _, aspect -> buf.writeString(aspect) }
|
||||
buf.writeCollection(forms) { _, form ->
|
||||
buf.writeString(form.displayForm)
|
||||
buf.writeCollection(form.unlockForms) { _, unlockForm -> buf.writeString(unlockForm) }
|
||||
}
|
||||
buf.writeCollection(variations) { _, variation -> variation.encode(buf) }
|
||||
}
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): PokedexEntry {
|
||||
val id = buffer.readIdentifier()
|
||||
val entryId = buffer.readIdentifier()
|
||||
val displayAspects = buffer.readList { buffer.readString() }.toMutableSet()
|
||||
val conditionAspects = buffer.readList { buffer.readString() }.toMutableSet()
|
||||
val forms = buffer.readList {
|
||||
val form = PokedexForm()
|
||||
form.displayForm = buffer.readString()
|
||||
form.unlockForms.addAll(buffer.readList { buffer.readString() })
|
||||
form
|
||||
}
|
||||
val variations = buffer.readList { PokedexCosmeticVariation().also { it.decode(buffer) } }
|
||||
return PokedexEntry(id, entryId, displayAspects, conditionAspects, forms, variations)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PokedexForm {
|
||||
var displayForm: String = "Normal"
|
||||
var unlockForms: MutableSet<String> = mutableSetOf()
|
||||
|
||||
fun clone() = PokedexForm().also {
|
||||
it.displayForm = displayForm
|
||||
it.unlockForms.addAll(unlockForms)
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokedex.filter
|
||||
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
|
||||
/**
|
||||
* A Pokedex [EntryFilter] that filters out entries that do not contain the current search.
|
||||
*
|
||||
* @author whatsy
|
||||
* @since September 4th, 2024
|
||||
* @param searchString The string to use when checking.
|
||||
*/
|
||||
class SearchFilter(val searchString: String) : EntryFilter() {
|
||||
override fun test(entry: PokedexEntry): Boolean {
|
||||
if (searchString == "") return true
|
||||
val species = PokemonSpecies.getByIdentifier(entry.speciesId) ?: return false
|
||||
|
||||
return species.translatedName.string.contains(searchString.trim(), true)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -164,20 +164,6 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
*/
|
||||
fun count() = this.speciesByIdentifier.size
|
||||
|
||||
/**
|
||||
* Gets a map of dex numbers to species.
|
||||
*
|
||||
* @return The dex numbers map to species.
|
||||
*/
|
||||
fun getSpeciesInNamespace(namespace: String = Cobblemon.MODID): MutableMap<Int, Species> = speciesByDex.row(namespace)
|
||||
|
||||
/**
|
||||
* Get a list of loaded namespaces.
|
||||
*
|
||||
* @return The list of loaded namespaces.
|
||||
*/
|
||||
fun getNamespaces() = speciesByDex.rowKeySet().toList()
|
||||
|
||||
/**
|
||||
* Picks a random [Species].
|
||||
*
|
||||
|
||||
+31
-28
@@ -8,7 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.pokemon.evolution
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon.playerDataManager
|
||||
import com.cobblemon.mod.common.Cobblemon.playerData
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.advancement.CobblemonCriteria
|
||||
@@ -20,17 +20,18 @@ 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.api.scheduling.afterOnServer
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.entity.generic.GenericBedrockEntity
|
||||
import com.cobblemon.mod.common.item.PokeBallItem
|
||||
import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimationPacket
|
||||
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.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
/**
|
||||
@@ -121,7 +122,7 @@ interface Evolution : EvolutionLike {
|
||||
if (pokeballStack == null) return false
|
||||
}
|
||||
// If the player has at least one empty spot in their party.
|
||||
owner.party().getFirstAvailablePosition() ?: return false
|
||||
val emptySlot = owner.party().getFirstAvailablePosition() ?: return false
|
||||
|
||||
// Add shed Pokemon to player's party
|
||||
val shedPokemon = pokemon.clone()
|
||||
@@ -129,7 +130,7 @@ interface Evolution : EvolutionLike {
|
||||
innerShedder.apply(shedPokemon)
|
||||
shedPokemon.caughtBall = ((pokeballStack?.item ?: CobblemonItems.POKE_BALL) as PokeBallItem).pokeBall
|
||||
pokemon.storeCoordinates.get()?.store?.add(shedPokemon)
|
||||
CobblemonCriteria.EVOLVE_POKEMON.trigger(owner, EvolvePokemonContext(pokemon.preEvolution!!.species.resourceIdentifier, shedPokemon.species.resourceIdentifier, playerDataManager.getGenericData(owner).advancementData.totalEvolvedCount))
|
||||
CobblemonCriteria.EVOLVE_POKEMON.trigger(owner, EvolvePokemonContext(pokemon.preEvolution!!.species.resourceIdentifier, shedPokemon.species.resourceIdentifier, playerData.get(owner).advancementData.totalEvolvedCount))
|
||||
// Consume one of the balls
|
||||
pokeballStack?.shrink(1)
|
||||
|
||||
@@ -144,7 +145,7 @@ interface Evolution : EvolutionLike {
|
||||
*/
|
||||
fun forceEvolve(pokemon: Pokemon) {
|
||||
// This is a switch to enable/disable the evolution effect while we get particles improved
|
||||
val useEvolutionEffect = true
|
||||
val useEvolutionEffect = false
|
||||
|
||||
if (pokemon.state is ShoulderedState) {
|
||||
pokemon.tryRecallWithAnimation()
|
||||
@@ -154,31 +155,34 @@ interface Evolution : EvolutionLike {
|
||||
if (pokemonEntity == null || !useEvolutionEffect) {
|
||||
evolutionMethod(pokemon)
|
||||
} else {
|
||||
pokemonEntity.busyLocks.add("evolving")
|
||||
pokemonEntity.navigation.stop()
|
||||
pokemonEntity.after(1F) {
|
||||
evolutionAnimation(pokemonEntity)
|
||||
pokemonEntity.evolutionEntity = pokemon.getOwnerPlayer()?.let { GenericBedrockEntity(world = it.level()) }
|
||||
val evolutionEntity = pokemon.entity!!.evolutionEntity
|
||||
evolutionEntity?.apply {
|
||||
category = cobblemonResource("evolution")
|
||||
colliderHeight = pokemonEntity.bbHeight
|
||||
colliderWidth = pokemonEntity.bbWidth
|
||||
scale = pokemonEntity.ageScale
|
||||
syncAge = true // Otherwise particle animation will be starting from zero even if you come along partway through
|
||||
setPos(pokemonEntity.x, pokemonEntity.y, pokemonEntity.z)
|
||||
}
|
||||
pokemonEntity.after(11.2F) {
|
||||
evolutionMethod(pokemon)
|
||||
}
|
||||
pokemonEntity.after( seconds = 12F ) {
|
||||
cryAnimation(pokemonEntity)
|
||||
pokemonEntity.busyLocks.remove("evolving")
|
||||
pokemon.getOwnerPlayer()?.level()?.addFreshEntity(evolutionEntity)
|
||||
afterOnServer(seconds = 9F) {
|
||||
if (!pokemonEntity.isRemoved) {
|
||||
evolutionMethod(pokemon)
|
||||
afterOnServer(seconds = 1.5F) { pokemonEntity.cry() }
|
||||
afterOnServer(seconds = 3F) {
|
||||
if (evolutionEntity != null) {
|
||||
evolutionEntity.kill()
|
||||
if (!pokemonEntity.isRemoved) {
|
||||
pokemonEntity.evolutionEntity = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun evolutionAnimation(pokemon: Entity) {
|
||||
val playPoseableAnimationPacket = PlayPosableAnimationPacket(pokemon.id, setOf("q.bedrock_stateful('evolution', 'evolution', 'endures_primary_animations');"), emptySet())
|
||||
playPoseableAnimationPacket.sendToPlayersAround(pokemon.x, pokemon.y, pokemon.z, 128.0, pokemon.level().dimension())
|
||||
}
|
||||
|
||||
private fun cryAnimation(pokemon: Entity) {
|
||||
val playPoseableAnimationPacket = PlayPosableAnimationPacket(pokemon.id, setOf("cry"), emptySet())
|
||||
playPoseableAnimationPacket.sendToPlayersAround(pokemon.x, pokemon.y, pokemon.z, 128.0, pokemon.level().dimension())
|
||||
}
|
||||
|
||||
fun evolutionMethod(pokemon: Pokemon) {
|
||||
this.result.apply(pokemon)
|
||||
this.learnableMoves.forEach { move ->
|
||||
@@ -190,9 +194,8 @@ interface Evolution : EvolutionLike {
|
||||
pokemon.getOwnerPlayer()?.sendSystemMessage(lang("experience.learned_move", pokemon.getDisplayName(), move.displayName))
|
||||
}
|
||||
// we want to instantly tick for example you might only evolve your Bulbasaur at level 34 so Venusaur should be immediately available
|
||||
pokemon.evolutions.filterIsInstance<PassiveEvolution>().forEach { evolution -> evolution.attemptEvolution(pokemon) }
|
||||
pokemon.lockedEvolutions.filterIsInstance<PassiveEvolution>().forEach { evolution -> evolution.attemptEvolution(pokemon) }
|
||||
pokemon.getOwnerPlayer()?.playSound(CobblemonSounds.EVOLUTION_UI, 1F, 1F)
|
||||
pokemon.getOwnerPlayer()?.playSound(CobblemonSounds.EVOLVING, 1F, 1F)
|
||||
this.shed(pokemon)
|
||||
CobblemonEvents.EVOLUTION_COMPLETE.post(EvolutionCompleteEvent(pokemon, this))
|
||||
}
|
||||
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections
|
||||
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
import com.cobblemon.mod.common.api.reactive.collections.subscriptions.CollectionSubscription
|
||||
|
||||
interface MutableObservableCollection<T, C : Collection<T>> :
|
||||
ObservableCollection<T, C>,
|
||||
MutableCollection<T> {
|
||||
|
||||
fun subscribe(
|
||||
priority: Priority = Priority.NORMAL,
|
||||
anyChangeHandler: (Pair<C, T>) -> Unit,
|
||||
additionHandler: ((Pair<C, T>) -> Unit)? = null,
|
||||
removalHandler: ((Pair<C, T>) -> Unit)? = null,
|
||||
): CollectionSubscription<T, C>
|
||||
|
||||
override fun add(element: T): Boolean
|
||||
|
||||
fun addIf(element: T, predicate: (C) -> Boolean): Boolean
|
||||
|
||||
override fun remove(element: T): Boolean
|
||||
|
||||
fun removeIf(predicate: (T) -> Boolean): Boolean
|
||||
|
||||
override fun addAll(elements: Collection<T>): Boolean
|
||||
|
||||
override fun retainAll(elements: Collection<T>): Boolean
|
||||
|
||||
override fun removeAll(elements: Collection<T>): Boolean
|
||||
|
||||
override fun iterator(): MutableIterator<T>
|
||||
|
||||
override fun clear()
|
||||
|
||||
fun mutableCopy(): MutableObservableCollection<T, C>
|
||||
}
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections
|
||||
|
||||
interface MutableObservableCollectionIterator<T, C : Collection<T>, I : Iterator<T>> :
|
||||
ObservableCollectionIterator<T, I>,
|
||||
MutableIterator<T> {
|
||||
|
||||
override fun remove()
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections
|
||||
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.reactive.ObservableSubscription
|
||||
|
||||
interface ObservableCollection<T, C : Collection<T>> :
|
||||
Collection<T>,
|
||||
Observable<Pair<C, T>> {
|
||||
|
||||
val elements: C
|
||||
override val size: Int
|
||||
|
||||
override fun subscribe(
|
||||
priority: Priority,
|
||||
handler: (Pair<C, T>) -> Unit,
|
||||
): ObservableSubscription<Pair<C, T>>
|
||||
|
||||
override fun unsubscribe(subscription: ObservableSubscription<Pair<C, T>>)
|
||||
|
||||
override fun isEmpty(): Boolean
|
||||
|
||||
fun isNotEmpty(): Boolean
|
||||
|
||||
override fun contains(element: T): Boolean
|
||||
|
||||
override fun containsAll(elements: Collection<T>): Boolean
|
||||
|
||||
override operator fun iterator(): Iterator<T>
|
||||
|
||||
fun copy(): ObservableCollection<T, C>
|
||||
}
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections
|
||||
|
||||
interface ObservableCollectionIterator<T, I : Iterator<T>> : Iterator<T> {
|
||||
|
||||
override fun hasNext(): Boolean
|
||||
override fun next(): T
|
||||
}
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections
|
||||
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
|
||||
|
||||
/**
|
||||
* This attempts to cast [this] value to [Observable].
|
||||
*
|
||||
* @return An observable set with [this] as an [Observable] or an empty set.
|
||||
*/
|
||||
fun <T> T.getElementObservables(): Set<Observable<*>> {
|
||||
this.tryGetObservable()?.let { return setOf(it) }
|
||||
return emptySet()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This attempts to cast [this] value to [Observable].
|
||||
*
|
||||
* @return This value as an [Observable] or null.
|
||||
*/
|
||||
fun <T> T.tryGetObservable(): Observable<*>? = if (this is Observable<*>) this else null
|
||||
|
||||
fun <T> MutableIterator<T>.removeIf(predicate: (T) -> Boolean): Boolean {
|
||||
var removed = false
|
||||
this.forEach { element ->
|
||||
if (predicate(element)) {
|
||||
this.remove()
|
||||
if (!removed) {
|
||||
removed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return removed
|
||||
}
|
||||
-242
@@ -1,242 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.list
|
||||
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.reactive.collections.MutableObservableCollection
|
||||
import com.cobblemon.mod.common.api.reactive.collections.getElementObservables
|
||||
import com.cobblemon.mod.common.api.reactive.collections.subscriptions.IndexedListSubscription
|
||||
import com.cobblemon.mod.common.api.reactive.collections.subscriptions.ListSubscription
|
||||
import com.cobblemon.mod.common.api.reactive.collections.removeIf
|
||||
|
||||
open class MutableObservableList<T>(
|
||||
list: Collection<T> = setOf(),
|
||||
elementHandler: (T) -> Set<Observable<*>> = { it.getElementObservables() },
|
||||
) : MutableObservableCollection<T, List<T>>,
|
||||
ObservableList<T>(list, elementHandler),
|
||||
MutableList<T> {
|
||||
|
||||
private val additionObservable = SimpleObservable<Pair<List<T>, T>>()
|
||||
private val removalObservable = SimpleObservable<Pair<List<T>, T>>()
|
||||
private val setObservable = SimpleObservable<Pair<List<T>, Pair<T, T>>>()
|
||||
private val swapObservable = SimpleObservable<Pair<List<T>, Pair<T, T>>>()
|
||||
private val additionObservableIndexed = SimpleObservable<Triple<List<T>, T, Int>>()
|
||||
private val removalObservableIndexed = SimpleObservable<Triple<List<T>, T, Int>>()
|
||||
private val setObservableIndexed = SimpleObservable<Triple<List<T>, Pair<T, T>, Int>>()
|
||||
private val swapObservableIndexed = SimpleObservable<Triple<List<T>, Pair<T, T>, Pair<Int, Int>>>()
|
||||
|
||||
override fun subscribe(
|
||||
priority: Priority,
|
||||
anyChangeHandler: (Pair<List<T>, T>) -> Unit,
|
||||
additionHandler: ((Pair<List<T>, T>) -> Unit)?,
|
||||
removalHandler: ((Pair<List<T>, T>) -> Unit)?,
|
||||
): ListSubscription<T> {
|
||||
return ListSubscription(
|
||||
anyChange = this.subscribe(priority, anyChangeHandler),
|
||||
addition = additionHandler?.let { additionObservable.subscribe(priority, it) },
|
||||
removal = removalHandler?.let { removalObservable.subscribe(priority, it) },
|
||||
)
|
||||
}
|
||||
|
||||
fun subscribeAndHandle(
|
||||
priority: Priority,
|
||||
anyChangeHandler: (Pair<List<T>, T>) -> Unit,
|
||||
additionHandler: ((Pair<List<T>, T>) -> Unit)?,
|
||||
removalHandler: ((Pair<List<T>, T>) -> Unit)?,
|
||||
): ListSubscription<T> {
|
||||
elements.forEach { anyChangeHandler(this to it) }
|
||||
return subscribe(priority, anyChangeHandler, additionHandler, removalHandler)
|
||||
}
|
||||
|
||||
fun subscribe(
|
||||
priority: Priority,
|
||||
anyChangeHandler: (Pair<List<T>, T>) -> Unit,
|
||||
additionHandler: ((Pair<List<T>, T>) -> Unit)?,
|
||||
removalHandler: ((Pair<List<T>, T>) -> Unit)?,
|
||||
setHandler: ((Pair<List<T>, Pair<T, T>>) -> Unit)?,
|
||||
swapHandler: ((Pair<List<T>, Pair<T, T>>) -> Unit)?,
|
||||
): ListSubscription<T> {
|
||||
@Suppress("DuplicatedCode")
|
||||
return ListSubscription(
|
||||
anyChange = this.subscribe(priority, anyChangeHandler),
|
||||
addition = additionHandler?.let { additionObservable.subscribe(priority, it) },
|
||||
removal = removalHandler?.let { removalObservable.subscribe(priority, it) },
|
||||
set = setHandler?.let { setObservable.subscribe(priority, it) },
|
||||
swap = swapHandler?.let { swapObservable.subscribe(priority, it) },
|
||||
)
|
||||
}
|
||||
|
||||
fun subscribeAndHandle(
|
||||
priority: Priority,
|
||||
anyChangeHandler: (Pair<List<T>, T>) -> Unit,
|
||||
additionHandler: ((Pair<List<T>, T>) -> Unit)?,
|
||||
removalHandler: ((Pair<List<T>, T>) -> Unit)?,
|
||||
setHandler: ((Pair<List<T>, Pair<T, T>>) -> Unit)?,
|
||||
swapHandler: ((Pair<List<T>, Pair<T, T>>) -> Unit)?,
|
||||
): ListSubscription<T> {
|
||||
elements.forEach { anyChangeHandler(this to it) }
|
||||
return subscribe(priority, anyChangeHandler, additionHandler, removalHandler, setHandler, swapHandler)
|
||||
}
|
||||
|
||||
fun subscribeIndexed(
|
||||
priority: Priority,
|
||||
additionHandler: ((Triple<List<T>, T, Int>) -> Unit)?,
|
||||
removalHandler: ((Triple<List<T>, T, Int>) -> Unit)?,
|
||||
setHandler: ((Triple<List<T>, Pair<T, T>, Int>) -> Unit)?,
|
||||
swapHandler: ((Triple<List<T>, Pair<T, T>, Pair<Int, Int>>) -> Unit)?,
|
||||
): IndexedListSubscription<T> {
|
||||
return IndexedListSubscription(
|
||||
addition = additionHandler?.let { additionObservableIndexed.subscribe(priority, it) },
|
||||
removal = removalHandler?.let { removalObservableIndexed.subscribe(priority, it) },
|
||||
set = setHandler?.let { setObservableIndexed.subscribe(priority, it) },
|
||||
swap = swapHandler?.let { swapObservableIndexed.subscribe(priority, it) },
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return `true` after handling [register] & all subscriptions to [additionObservable],
|
||||
* [additionObservableIndexed], & [ObservableList.emitAnyChange].
|
||||
*/
|
||||
private fun emitAddition(element: T, index: Int): Boolean {
|
||||
register(element)
|
||||
additionObservable.emit(list to element)
|
||||
additionObservableIndexed.emit(Triple(list, element, index))
|
||||
return emitAnyChange(element)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return `true` after handling [unregister] & all subscriptions to [removalObservable],
|
||||
* [removalObservableIndexed] & [ObservableList.emitAnyChange].
|
||||
*/
|
||||
private fun emitRemoval(element: T, index: Int): Boolean {
|
||||
unregister(element)
|
||||
removalObservable.emit(list to element)
|
||||
removalObservableIndexed.emit(Triple(list, element, index))
|
||||
return emitAnyChange(element)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return `true` after handling [register], [unregister] & all subscriptions to [setObservable],
|
||||
* [setObservableIndexed], & [ObservableList.emitAnyChange].
|
||||
*/
|
||||
private fun emitSet(elements: Pair<T, T>, index: Int): Boolean {
|
||||
register(elements.first)
|
||||
unregister(elements.second)
|
||||
setObservable.emit(list to elements)
|
||||
setObservableIndexed.emit(Triple(list, elements, index))
|
||||
emitAnyChange(elements.first)
|
||||
emitAnyChange(elements.second)
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* @return `true` after handling all subscriptions to [swapObservable],
|
||||
* [swapObservableIndexed], & [ObservableList.emitAnyChange].
|
||||
*/
|
||||
private fun emitSwap(elements: Pair<T, T>, indices: Pair<Int, Int>): Boolean {
|
||||
swapObservable.emit(list to elements)
|
||||
swapObservableIndexed.emit(Triple(list, elements, indices))
|
||||
emitAnyChange(elements.first)
|
||||
emitAnyChange(elements.second)
|
||||
return true
|
||||
}
|
||||
|
||||
override operator fun iterator() = MutableObservableListIterator(this)
|
||||
|
||||
override fun listIterator() = MutableObservableListIterator(this)
|
||||
|
||||
override fun listIterator(index: Int) = MutableObservableListIterator(this, index)
|
||||
|
||||
override fun subList(fromIndex: Int, toIndex: Int): MutableObservableSubList<T> {
|
||||
return MutableObservableSubList(this, fromIndex, toIndex, elementHandler)
|
||||
}
|
||||
|
||||
override fun addIf(element: T, predicate: (List<T>) -> Boolean): Boolean {
|
||||
return if (predicate(list)) add(element) else false
|
||||
}
|
||||
|
||||
override fun add(element: T): Boolean {
|
||||
list.add(element)
|
||||
return emitAddition(element, lastIndex)
|
||||
}
|
||||
|
||||
fun addAtIf(index: Int, element: T, predicate: (List<T>) -> Boolean): Boolean {
|
||||
return if (predicate(list)) {
|
||||
add(index, element)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
override fun add(index: Int, element: T) {
|
||||
list.add(index, element)
|
||||
emitAddition(element, index)
|
||||
}
|
||||
|
||||
fun setIf(index: Int, element: T, predicate: (T) -> Boolean): T? {
|
||||
return if (predicate(list[index])) set(index, element) else null
|
||||
}
|
||||
|
||||
override operator fun set(index: Int, element: T): T {
|
||||
return list.set(index, element).also { emitSet(element to it, index) }
|
||||
}
|
||||
|
||||
fun swapIf(indexOne: Int, indexTwo: Int, predicate: () -> Boolean): Boolean {
|
||||
return predicate().also { if (it) swap(indexOne, indexTwo) }
|
||||
}
|
||||
|
||||
fun swap(indexOne: Int, indexTwo: Int) {
|
||||
val one = list[indexOne]
|
||||
val two = list.set(indexTwo, one)
|
||||
list[indexOne] = two
|
||||
emitSwap(one to two, indexOne to indexTwo)
|
||||
}
|
||||
|
||||
override fun removeIf(predicate: (T) -> Boolean): Boolean = iterator().removeIf(predicate)
|
||||
|
||||
override fun remove(element: T): Boolean {
|
||||
val indexOf = list.indexOfFirst { it == element }
|
||||
if (indexOf == -1) {
|
||||
return false
|
||||
}
|
||||
list.removeAt(indexOf)
|
||||
return emitRemoval(element, indexOf)
|
||||
}
|
||||
|
||||
override fun removeAt(index: Int): T {
|
||||
val element = list.removeAt(index)
|
||||
emitRemoval(element, index)
|
||||
return element
|
||||
}
|
||||
|
||||
fun removeAtIf(index: Int, predicate: (T) -> Boolean): T? {
|
||||
val element = list[index]
|
||||
if (predicate(element)) {
|
||||
list.removeAt(index)
|
||||
emitRemoval(element, index)
|
||||
}
|
||||
return element
|
||||
}
|
||||
|
||||
override fun addAll(elements: Collection<T>): Boolean {
|
||||
elements.forEach { add(it) }
|
||||
return true
|
||||
}
|
||||
|
||||
override fun addAll(index: Int, elements: Collection<T>): Boolean {
|
||||
var currentIndex = index
|
||||
elements.forEach { add(currentIndex++, it) }
|
||||
return true
|
||||
}
|
||||
|
||||
override fun removeAll(elements: Collection<T>):Boolean = removeIf { elements.contains(it) }
|
||||
|
||||
override fun retainAll(elements: Collection<T>):Boolean = removeIf { !elements.contains(it) }
|
||||
|
||||
override fun clear() {
|
||||
while (isNotEmpty()) {
|
||||
removeAt(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.list
|
||||
|
||||
// the name is not quite long enough yet...
|
||||
import com.cobblemon.mod.common.api.reactive.collections.MutableObservableCollectionIterator
|
||||
|
||||
open class MutableObservableListIterator<T>(
|
||||
observableList: MutableObservableList<T>,
|
||||
index: Int = 0,
|
||||
) : MutableObservableCollectionIterator<T, Set<T>, ListIterator<T>>,
|
||||
ObservableListIterator<T>(observableList, index),
|
||||
MutableListIterator<T> {
|
||||
|
||||
private val mutableList: MutableObservableList<T> = observableList
|
||||
|
||||
private var illegalSetOrRemoveState: Boolean? = null
|
||||
set (value) { if (field != value) field = value }
|
||||
|
||||
override fun next(): T {
|
||||
illegalSetOrRemoveState = false
|
||||
return super.next()
|
||||
}
|
||||
|
||||
override fun previous(): T {
|
||||
illegalSetOrRemoveState = false
|
||||
return super.previous()
|
||||
}
|
||||
|
||||
override fun remove() {
|
||||
throwIfIllegalState("remove")
|
||||
mutableList.removeAt(--index)
|
||||
illegalSetOrRemoveState = true
|
||||
}
|
||||
|
||||
override fun set(element: T) {
|
||||
throwIfIllegalState("set")
|
||||
mutableList[index -1] = element
|
||||
}
|
||||
|
||||
override fun add(element: T) {
|
||||
when {
|
||||
mutableList.isEmpty() -> mutableList.add(element).run { index = 0 }
|
||||
index < mutableList.size -> mutableList.add(index++, element)
|
||||
else -> mutableList.add(element).run { index++ }
|
||||
}
|
||||
illegalSetOrRemoveState = true
|
||||
}
|
||||
|
||||
private fun throwIfIllegalState(function: String) {
|
||||
if (illegalSetOrRemoveState == null) {
|
||||
throw IllegalStateException(
|
||||
"Observable List iterator '$function' was called before 'next' or 'previous'."
|
||||
)
|
||||
} else if (illegalSetOrRemoveState == true) {
|
||||
throw IllegalStateException(
|
||||
"Observable List iterator '$function' was called, " +
|
||||
"but 'remove' or 'add' was already called this iteration."
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
-317
@@ -1,317 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.list
|
||||
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.reactive.collections.MutableObservableCollection
|
||||
import com.cobblemon.mod.common.api.reactive.collections.subscriptions.ListSubscription
|
||||
import com.cobblemon.mod.common.api.reactive.collections.removeIf
|
||||
|
||||
class MutableObservableSubList<T>(
|
||||
private val parentList: MutableObservableList<T>,
|
||||
private val fromIndex: Int,
|
||||
private val toIndex: Int,
|
||||
elementHandler: (T) -> Set<Observable<*>>,
|
||||
) : MutableObservableCollection<T, List<T>>,
|
||||
ObservableSubList<T>(parentList, fromIndex, toIndex, elementHandler),
|
||||
MutableList<T> {
|
||||
|
||||
private val additionObservable = SimpleObservable<Pair<List<T>, T>>()
|
||||
private val removalObservable = SimpleObservable<Pair<List<T>, T>>()
|
||||
private val setObservable = SimpleObservable<Pair<List<T>, Pair<T, T>>>()
|
||||
private val swapObservable = SimpleObservable<Pair<List<T>, Pair<T, T>>>()
|
||||
|
||||
override val elements: List<T>
|
||||
get() = when {
|
||||
isEmpty() -> emptyList()
|
||||
parentList.size < maxSize -> parentList.elements.subList(fromIndex, parentList.size)
|
||||
else -> parentList.elements.subList(fromIndex, currentToIndex)
|
||||
}
|
||||
private val maxLastIndex: Int = toIndex - 1
|
||||
private val maxSize: Int = toIndex - fromIndex
|
||||
override val size: Int get() = when {
|
||||
isEmpty() -> 0
|
||||
parentList.size < toIndex -> parentList.lastIndex - fromIndex
|
||||
else -> maxLastIndex
|
||||
}
|
||||
/** This is the last index in the sublist window, or -1 if the window is empty. */
|
||||
val currentLastIndex: Int get() = size - 1
|
||||
/** This is either [fromIndex] or -1 if the sublist window is empty. */
|
||||
val currentFromIndex: Int get() = if (isEmpty()) -1 else fromIndex
|
||||
/**
|
||||
* If [parentList] size > [toIndex] this is the toIndex,
|
||||
* if the parentList size is > [fromIndex] this is the parentList size,
|
||||
* or this is the [currentFromIndex].
|
||||
*/
|
||||
private val currentToIndex: Int
|
||||
get() = when {
|
||||
toIndex < parentList.size -> toIndex
|
||||
fromIndex < parentList.size -> parentList.size
|
||||
else -> currentFromIndex
|
||||
}
|
||||
private val currentLastIndexInParent: Int
|
||||
get() = when {
|
||||
isEmpty() -> fromIndex
|
||||
parentList.lastIndex < toIndex -> parentList.lastIndex
|
||||
else -> maxLastIndex
|
||||
}
|
||||
|
||||
init {
|
||||
parentList.subscribeIndexed(
|
||||
priority = Priority.NORMAL,
|
||||
additionHandler = { (_, element, index) -> emitAddition(element, index) },
|
||||
removalHandler = { (_, element, index) -> emitRemoval(element, index) },
|
||||
setHandler = { (_, elements, index) -> emitSet(elements, index) },
|
||||
swapHandler = { (_, element, index) -> emitSwap(element, index) },
|
||||
)
|
||||
}
|
||||
|
||||
override fun subscribe(
|
||||
priority: Priority,
|
||||
anyChangeHandler: (Pair<List<T>, T>) -> Unit,
|
||||
additionHandler: ((Pair<List<T>, T>) -> Unit)?,
|
||||
removalHandler: ((Pair<List<T>, T>) -> Unit)?,
|
||||
): ListSubscription<T> {
|
||||
return ListSubscription(
|
||||
anyChange = this.subscribe(priority, anyChangeHandler),
|
||||
addition = additionHandler?.let { additionObservable.subscribe(priority, it) },
|
||||
removal = removalHandler?.let { removalObservable.subscribe(priority, it) },
|
||||
)
|
||||
}
|
||||
|
||||
fun subscribeAndHandle(
|
||||
priority: Priority,
|
||||
anyChangeHandler: (Pair<List<T>, T>) -> Unit,
|
||||
additionHandler: ((Pair<List<T>, T>) -> Unit)?,
|
||||
removalHandler: ((Pair<List<T>, T>) -> Unit)?,
|
||||
): ListSubscription<T> {
|
||||
elements.forEach { anyChangeHandler(this to it) }
|
||||
return subscribe(priority, anyChangeHandler, additionHandler, removalHandler)
|
||||
}
|
||||
|
||||
fun subscribe(
|
||||
priority: Priority,
|
||||
anyChangeHandler: (Pair<List<T>, T>) -> Unit,
|
||||
additionHandler: ((Pair<List<T>, T>) -> Unit)?,
|
||||
removalHandler: ((Pair<List<T>, T>) -> Unit)?,
|
||||
setHandler: ((Pair<List<T>, Pair<T, T>>) -> Unit)?,
|
||||
swapHandler: ((Pair<List<T>, Pair<T, T>>) -> Unit)?,
|
||||
): ListSubscription<T> {
|
||||
@Suppress("DuplicatedCode")
|
||||
return ListSubscription(
|
||||
anyChange = this.subscribe(priority, anyChangeHandler),
|
||||
addition = additionHandler?.let { additionObservable.subscribe(priority, it) },
|
||||
removal = removalHandler?.let { removalObservable.subscribe(priority, it) },
|
||||
set = setHandler?.let { setObservable.subscribe(priority, it) },
|
||||
swap = swapHandler?.let { swapObservable.subscribe(priority, it) },
|
||||
)
|
||||
}
|
||||
|
||||
fun subscribeAndHandle(
|
||||
priority: Priority,
|
||||
anyChangeHandler: (Pair<List<T>, T>) -> Unit,
|
||||
additionHandler: ((Pair<List<T>, T>) -> Unit)?,
|
||||
removalHandler: ((Pair<List<T>, T>) -> Unit)?,
|
||||
setHandler: ((Pair<List<T>, Pair<T, T>>) -> Unit)?,
|
||||
swapHandler: ((Pair<List<T>, Pair<T, T>>) -> Unit)?,
|
||||
): ListSubscription<T> {
|
||||
elements.forEach { anyChangeHandler(this to it) }
|
||||
return subscribe(priority, anyChangeHandler, additionHandler, removalHandler, setHandler, swapHandler)
|
||||
}
|
||||
|
||||
private fun emitAddition(element: T, index: Int) {
|
||||
if (index >= toIndex) {
|
||||
return
|
||||
}
|
||||
val elements = this.elements
|
||||
if (index >= fromIndex) {
|
||||
handleAddition(elements, element)
|
||||
} else if(parentList.lastIndex >= fromIndex) {
|
||||
handleAddition(elements, parentList[fromIndex])
|
||||
}
|
||||
if (parentList.size > toIndex) {
|
||||
handleRemoval(elements, parentList[toIndex])
|
||||
}
|
||||
}
|
||||
|
||||
private fun emitRemoval(element: T, index: Int) {
|
||||
if (index >= toIndex) {
|
||||
return
|
||||
}
|
||||
val elements = this.elements
|
||||
if (index >= fromIndex) {
|
||||
handleRemoval(elements, element)
|
||||
} else if(parentList.lastIndex >= fromIndex - 1) {
|
||||
handleRemoval(elements, parentList[fromIndex - 1])
|
||||
}
|
||||
if (currentLastIndexInParent >= toIndex - 1) {
|
||||
handleAddition(elements, parentList[toIndex - 1])
|
||||
}
|
||||
}
|
||||
|
||||
private fun emitSet(elementPair: Pair<T, T>, index: Int) {
|
||||
if (!index.isInParentRelativeWindow()) {
|
||||
return
|
||||
}
|
||||
register(elementPair.first)
|
||||
unregister(elementPair.second)
|
||||
setObservable.emit(elements to elementPair)
|
||||
emitAnyChange(elementPair.first)
|
||||
emitAnyChange(elementPair.second)
|
||||
}
|
||||
|
||||
private fun emitSwap(elementPair: Pair<T, T>, indices: Pair<Int, Int>) {
|
||||
val firstInWindow = indices.first.isInParentRelativeWindow()
|
||||
val secondInWindow = indices.second.isInParentRelativeWindow()
|
||||
when {
|
||||
firstInWindow && !secondInWindow -> {
|
||||
val elements = this.elements
|
||||
handleRemoval(elements, elementPair.first)
|
||||
handleAddition(elements, elementPair.second)
|
||||
}
|
||||
!firstInWindow && secondInWindow -> {
|
||||
val elements = this.elements
|
||||
handleAddition(elements, elementPair.first)
|
||||
handleRemoval(elements, elementPair.second)
|
||||
}
|
||||
firstInWindow && secondInWindow -> {
|
||||
swapObservable.emit(elements to elementPair)
|
||||
emitAnyChange(elementPair.first)
|
||||
elementPair.second?.let { emitAnyChange(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleAddition(elements: List<T>, element: T) {
|
||||
register(element)
|
||||
additionObservable.emit(elements to element)
|
||||
emitAnyChange(element)
|
||||
}
|
||||
|
||||
private fun handleRemoval(elements: List<T>, element: T) {
|
||||
unregister(element)
|
||||
removalObservable.emit(elements to element)
|
||||
emitAnyChange(element)
|
||||
}
|
||||
|
||||
override operator fun iterator() = MutableObservableSubListIterator(this)
|
||||
|
||||
override fun listIterator() = MutableObservableSubListIterator(this)
|
||||
|
||||
override fun listIterator(index: Int) = MutableObservableSubListIterator(this, index)
|
||||
|
||||
override fun subList(fromIndex: Int, toIndex: Int): MutableObservableSubList<T> {
|
||||
return parentList.subList(parentIndex(fromIndex), parentIndex(toIndex))
|
||||
}
|
||||
|
||||
fun swapIf(indexOne: Int, indexTwo: Int, predicate: () -> Boolean): Boolean {
|
||||
return predicate().also { if (it) swap(indexOne, indexTwo) }
|
||||
}
|
||||
|
||||
fun swap(indexOne: Int, indexTwo: Int) {
|
||||
val parentIndexOne = parentIndex(indexOne)
|
||||
val one = parentList[parentIndexOne]
|
||||
val two = parentList.set(parentIndex(indexTwo), one)
|
||||
parentList[parentIndexOne] = two
|
||||
}
|
||||
|
||||
override fun addIf(element: T, predicate: (List<T>) -> Boolean): Boolean {
|
||||
return if (predicate(this)) add(element) else false
|
||||
}
|
||||
|
||||
override fun add(element: T): Boolean {
|
||||
return if (parentList.lastIndex < toIndex) {
|
||||
parentList.add(element)
|
||||
} else {
|
||||
parentList.add(toIndex, element)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fun addAtIf(index: Int, element: T, predicate: (List<T>) -> Boolean): Boolean {
|
||||
return if (predicate(this)) {
|
||||
add(index, element)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
override fun add(index: Int, element: T) {
|
||||
parentList.add(parentIndex(index), element)
|
||||
}
|
||||
|
||||
override operator fun set(index: Int, element: T): T {
|
||||
return parentList.set(parentIndex(index), element)
|
||||
}
|
||||
|
||||
override fun removeIf(predicate: (T) -> Boolean): Boolean = iterator().removeIf(predicate)
|
||||
|
||||
override fun remove(element: T): Boolean {
|
||||
for (i in fromIndex until parentList.size) {
|
||||
val current = elements[i]
|
||||
if (current == element) {
|
||||
parentList.removeAt(i)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun removeAt(index: Int): T = parentList.removeAt(parentIndex(index))
|
||||
|
||||
override fun addAll(elements: Collection<T>): Boolean {
|
||||
val parentIndex = if (currentLastIndex > -1) currentLastIndex + fromIndex else fromIndex
|
||||
return if (parentIndex > parentList.lastIndex) {
|
||||
parentList.addAll(elements)
|
||||
} else {
|
||||
parentList.addAll(parentIndex, elements)
|
||||
}
|
||||
}
|
||||
|
||||
override fun addAll(index: Int, elements: Collection<T>): Boolean {
|
||||
return parentList.addAll(parentIndex(index), elements)
|
||||
}
|
||||
|
||||
override fun removeAll(elements: Collection<T>): Boolean {
|
||||
return iterator().removeIf { elements.contains(it) }
|
||||
}
|
||||
|
||||
override fun retainAll(elements: Collection<T>): Boolean {
|
||||
return iterator().removeIf { !elements.contains(it) }
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation will remove all elements from the window dynamically. If an element
|
||||
* is removed & an element shifts into the sublist window that meets the predicate, the
|
||||
* new element will also be removed.
|
||||
*
|
||||
* Note: The other iterators including the ObservableSubListIterator will only operate on
|
||||
* the window provided before the iteration, even when the iterator is mutable.
|
||||
*/
|
||||
private fun removeAllIf(predicate: (T) -> Boolean): Boolean {
|
||||
if (isEmpty()) {
|
||||
return false
|
||||
}
|
||||
var mutated = false
|
||||
val outOfParentBounds: (Int) -> Boolean = { it == parentList.size }
|
||||
for (i in fromIndex until currentToIndex) {
|
||||
if (outOfParentBounds(i)) {
|
||||
return mutated
|
||||
}
|
||||
while (predicate(parentList[i])) {
|
||||
parentList.removeAt(i).also { if (!mutated) mutated = true }
|
||||
if (outOfParentBounds(i)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return mutated
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
if (isNotEmpty()) {
|
||||
iterator().removeIf { true }
|
||||
}
|
||||
}
|
||||
}
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.list
|
||||
|
||||
// the name is not quite long enough yet...
|
||||
import com.cobblemon.mod.common.api.reactive.collections.MutableObservableCollectionIterator
|
||||
|
||||
open class MutableObservableSubListIterator<T>(
|
||||
subList: MutableObservableSubList<T>,
|
||||
index: Int = 0,
|
||||
) : MutableObservableCollectionIterator<T, List<T>, ListIterator<T>>,
|
||||
ObservableSubListIterator<T>(subList, index),
|
||||
MutableListIterator<T> {
|
||||
|
||||
private val mutableSubList: MutableObservableSubList<T> = subList
|
||||
|
||||
private var illegalSetOrRemoveState: Boolean? = null
|
||||
set (value) { if (field != value) field = value }
|
||||
|
||||
override fun next(): T {
|
||||
illegalSetOrRemoveState = false
|
||||
return super.next()
|
||||
}
|
||||
|
||||
override fun previous(): T {
|
||||
illegalSetOrRemoveState = false
|
||||
return super.previous()
|
||||
}
|
||||
|
||||
override fun remove() {
|
||||
throwIfIllegalState("remove")
|
||||
mutableSubList.removeAt(--index)
|
||||
illegalSetOrRemoveState = true
|
||||
}
|
||||
|
||||
override fun set(element: T) {
|
||||
throwIfIllegalState("set")
|
||||
mutableSubList[index -1] = element
|
||||
}
|
||||
|
||||
override fun add(element: T) {
|
||||
when {
|
||||
subList.isEmpty() -> {
|
||||
mutableSubList.add(element)
|
||||
index = mutableSubList.currentFromIndex
|
||||
}
|
||||
index < mutableSubList.currentLastIndex -> mutableSubList.add(index++, element)
|
||||
else -> mutableSubList.add(element).run { index++ }
|
||||
}
|
||||
illegalSetOrRemoveState = true
|
||||
}
|
||||
|
||||
private fun throwIfIllegalState(function: String) {
|
||||
if (illegalSetOrRemoveState == null) {
|
||||
throw IllegalStateException(
|
||||
"Observable Sub List iterator '$function' was called before 'next' or 'previous'."
|
||||
)
|
||||
} else if (illegalSetOrRemoveState == true) {
|
||||
throw IllegalStateException(
|
||||
"Observable Sub List iterator '$function' was called, " +
|
||||
"but 'remove' or 'add' was already called this iteration."
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
-93
@@ -1,93 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.list
|
||||
|
||||
import com.cobblemon.mod.common.api.PrioritizedList
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.reactive.ObservableSubscription
|
||||
import com.cobblemon.mod.common.api.reactive.collections.ObservableCollection
|
||||
import com.cobblemon.mod.common.api.reactive.collections.getElementObservables
|
||||
|
||||
open class ObservableList<T>(
|
||||
list: Collection<T>,
|
||||
protected val elementHandler: (T) -> Set<Observable<*>> = { it.getElementObservables() },
|
||||
) : ObservableCollection<T, List<T>>,
|
||||
List<T>,
|
||||
Observable<Pair<List<T>, T>> {
|
||||
|
||||
protected val list: MutableList<T> = list.toMutableList()
|
||||
private val subscriptions = PrioritizedList<ObservableSubscription<Pair<List<T>, T>>>()
|
||||
private val subscriptionMap: MutableMap<Observable<*>, ObservableSubscription<*>> = mutableMapOf()
|
||||
|
||||
override val elements: List<T> get() = list
|
||||
override val size: Int get() = list.size
|
||||
val lastIndex: Int get() = list.lastIndex
|
||||
|
||||
init {
|
||||
list.forEach { register(it) }
|
||||
}
|
||||
|
||||
override fun subscribe(
|
||||
priority: Priority,
|
||||
handler: (Pair<List<T>, T>) -> Unit,
|
||||
): ObservableSubscription<Pair<List<T>, T>> {
|
||||
val subscription = ObservableSubscription(this, handler)
|
||||
subscriptions.add(priority, subscription)
|
||||
return subscription
|
||||
}
|
||||
|
||||
fun subscribeAndHandle(
|
||||
priority: Priority,
|
||||
handler: (Pair<List<T>, T>) -> Unit
|
||||
): ObservableSubscription<Pair<List<T>, T>> {
|
||||
val subscription = ObservableSubscription(this, handler)
|
||||
subscriptions.add(priority, subscription)
|
||||
list.forEach { handler(this to it) }
|
||||
return subscription
|
||||
}
|
||||
|
||||
override fun unsubscribe(subscription: ObservableSubscription<Pair<List<T>, T>>) {
|
||||
subscriptions.remove(subscription)
|
||||
}
|
||||
|
||||
protected fun register(element: T) {
|
||||
elementHandler(element).forEach{ observable ->
|
||||
subscriptionMap[observable] = observable.subscribe { emitAnyChange(element) }
|
||||
}
|
||||
}
|
||||
|
||||
protected fun unregister(element: T) {
|
||||
elementHandler(element).forEach{ subscriptionMap.remove(it)?.unsubscribe() }
|
||||
}
|
||||
|
||||
/** @return true after handling [subscriptions]. */
|
||||
protected fun emitAnyChange(element: T): Boolean {
|
||||
subscriptions.forEach { it.handle(list to element) }
|
||||
return true
|
||||
}
|
||||
|
||||
override fun isEmpty() = list.isEmpty()
|
||||
|
||||
override fun isNotEmpty() = list.isNotEmpty()
|
||||
|
||||
override fun contains(element: T) = list.contains(element)
|
||||
|
||||
override fun containsAll(elements: Collection<T>) = list.containsAll(elements)
|
||||
|
||||
override operator fun get(index: Int): T = list[index]
|
||||
|
||||
override fun indexOf(element: T) = list.indexOf(element)
|
||||
|
||||
override operator fun iterator(): Iterator<T> = list.iterator()
|
||||
|
||||
override fun lastIndexOf(element: T) = list.lastIndexOf(element)
|
||||
|
||||
override fun listIterator(): ListIterator<T> = list.listIterator()
|
||||
|
||||
override fun listIterator(index: Int): ListIterator<T> = list.listIterator(index = index)
|
||||
|
||||
override fun subList(fromIndex: Int, toIndex: Int): List<T> = list.subList(fromIndex, toIndex)
|
||||
|
||||
override fun copy() = ObservableList(this.list, elementHandler)
|
||||
|
||||
open fun mutableCopy() = MutableObservableList(this.list, elementHandler)
|
||||
}
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.list
|
||||
|
||||
open class ObservableListIterator<T>(
|
||||
protected var list: ObservableList<T>,
|
||||
protected var index: Int = 0,
|
||||
) : ListIterator<T> {
|
||||
|
||||
override fun hasNext(): Boolean = index < list.size
|
||||
|
||||
override fun hasPrevious(): Boolean = list.isNotEmpty() && index > 0
|
||||
|
||||
override fun next(): T {
|
||||
if (!hasNext()) {
|
||||
throw NoSuchElementException(
|
||||
"Observable List iterator does not have next element from index $index."
|
||||
)
|
||||
}
|
||||
return list[index++]
|
||||
}
|
||||
|
||||
override fun previous(): T {
|
||||
if (!hasPrevious()) {
|
||||
throw NoSuchElementException(
|
||||
"Observable List iterator does not have a previous element at index ${index -1}."
|
||||
)
|
||||
}
|
||||
return list[--index]
|
||||
}
|
||||
|
||||
override fun nextIndex(): Int = index
|
||||
|
||||
override fun previousIndex(): Int = index -1
|
||||
}
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.list
|
||||
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.reactive.collections.getElementObservables
|
||||
import net.minecraft.nbt.NbtCompound
|
||||
|
||||
|
||||
fun <T> List<T>.saveToNbt(
|
||||
elementKey: String = "element",
|
||||
elementHandler: (T) -> NbtCompound,
|
||||
): NbtCompound {
|
||||
val nbt = NbtCompound()
|
||||
var size = 0
|
||||
this.iterator().forEach { nbt.put(elementKey + size++, elementHandler(it)) }
|
||||
nbt.putInt("size", size)
|
||||
return nbt
|
||||
}
|
||||
|
||||
|
||||
fun <T> NbtCompound.loadObservableListOf(
|
||||
elementKey: String = "element",
|
||||
loadElementHandler: (NbtCompound) -> T,
|
||||
elementObservableHandler: (T) -> Set<Observable<*>> = { it.getElementObservables() },
|
||||
) = ObservableList(this.loadList(elementKey, loadElementHandler), elementObservableHandler)
|
||||
|
||||
|
||||
fun <T> NbtCompound.loadMutableObservableListOf(
|
||||
elementKey: String = "element",
|
||||
loadElementHandler: (NbtCompound) -> T,
|
||||
elementObservableHandler: (T) -> Set<Observable<*>> = { it.getElementObservables() },
|
||||
) = MutableObservableList(this.loadList(elementKey, loadElementHandler), elementObservableHandler)
|
||||
|
||||
|
||||
private fun <T> NbtCompound.loadList(
|
||||
elementKey: String = "element",
|
||||
elementHandler: (NbtCompound) -> T
|
||||
): List<T> {
|
||||
val newList = mutableListOf<T>()
|
||||
if (this.contains("size")) {
|
||||
val size = this.getInt("size")
|
||||
for (i in 0 until size) {
|
||||
newList.add(elementHandler(this.getCompound(elementKey + i)))
|
||||
}
|
||||
}
|
||||
return newList
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.list
|
||||
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.reactive.collections.getElementObservables
|
||||
|
||||
|
||||
fun <T> Collection<T>.toObservableList(
|
||||
elementHandler: (T) -> Set<Observable<*>> = { it.getElementObservables() },
|
||||
) = ObservableList(this, elementHandler)
|
||||
|
||||
|
||||
fun <T> Collection<T>.toMutableObservableList(
|
||||
elementHandler: (T) -> Set<Observable<*>> = { it.getElementObservables() },
|
||||
) = MutableObservableList(this, elementHandler)
|
||||
|
||||
|
||||
fun <T> observableListOf(
|
||||
vararg elements: T,
|
||||
elementHandler: (T) -> Set<Observable<*>> = { it.getElementObservables() },
|
||||
): ObservableList<T> = ObservableList(elements.toList(), elementHandler)
|
||||
|
||||
|
||||
fun <T> mutableObservableListOf(
|
||||
vararg elements: T,
|
||||
elementHandler: (T) -> Set<Observable<*>> = { it.getElementObservables() },
|
||||
): MutableObservableList<T> = MutableObservableList(elements.toList(), elementHandler)
|
||||
|
||||
|
||||
fun <T> observableListOf(
|
||||
elements: Collection<T> = setOf(),
|
||||
elementHandler: (T) -> Set<Observable<*>> = { it.getElementObservables() },
|
||||
): ObservableList<T> = ObservableList(elements, elementHandler)
|
||||
|
||||
|
||||
fun <T> mutableObservableListOf(
|
||||
elements: Collection<T> = setOf(),
|
||||
elementHandler: (T) -> Set<Observable<*>> = { it.getElementObservables() },
|
||||
): MutableObservableList<T> = MutableObservableList(elements, elementHandler)
|
||||
-142
@@ -1,142 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.list
|
||||
|
||||
import com.cobblemon.mod.common.api.PrioritizedList
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.reactive.ObservableSubscription
|
||||
import com.cobblemon.mod.common.api.reactive.collections.ObservableCollection
|
||||
|
||||
open class ObservableSubList<T>(
|
||||
private val parentList: ObservableList<T>,
|
||||
private val fromIndex: Int,
|
||||
private val toIndex: Int,
|
||||
private val elementHandler: (T) -> Set<Observable<*>>,
|
||||
) : ObservableCollection<T, List<T>>,
|
||||
List<T>,
|
||||
Observable<Pair<List<T>, T>> {
|
||||
|
||||
private val subscriptions = PrioritizedList<ObservableSubscription<Pair<List<T>, T>>>()
|
||||
private val subscriptionMap: MutableMap<Observable<*>, ObservableSubscription<*>> = mutableMapOf()
|
||||
|
||||
override val elements: List<T> = parentList.elements.subList(fromIndex, toIndex)
|
||||
override val size: Int = toIndex - fromIndex
|
||||
|
||||
init {
|
||||
for (i in fromIndex until toIndex) {
|
||||
register(parentList[i])
|
||||
}
|
||||
}
|
||||
|
||||
override fun subscribe(
|
||||
priority: Priority,
|
||||
handler: (Pair<List<T>, T>) -> Unit,
|
||||
): ObservableSubscription<Pair<List<T>, T>> {
|
||||
val subscription = ObservableSubscription(this, handler)
|
||||
subscriptions.add(priority, subscription)
|
||||
return subscription
|
||||
}
|
||||
|
||||
fun subscribeAndHandle(
|
||||
priority: Priority,
|
||||
handler: (Pair<List<T>, T>) -> Unit
|
||||
): ObservableSubscription<Pair<List<T>, T>> {
|
||||
val subscription = ObservableSubscription(this, handler)
|
||||
subscriptions.add(priority, subscription)
|
||||
elements.forEach { handler(this to it) }
|
||||
return subscription
|
||||
}
|
||||
|
||||
override fun unsubscribe(subscription: ObservableSubscription<Pair<List<T>, T>>) {
|
||||
subscriptions.remove(subscription)
|
||||
}
|
||||
|
||||
protected fun register(element: T) {
|
||||
elementHandler(element).forEach { observable ->
|
||||
subscriptionMap[observable] = observable.subscribe { emitAnyChange(element) }
|
||||
}
|
||||
}
|
||||
|
||||
protected fun unregister(element: T) {
|
||||
elementHandler(element).forEach { observable ->
|
||||
subscriptionMap.remove(observable)?.unsubscribe()
|
||||
}
|
||||
}
|
||||
|
||||
protected fun emitAnyChange(element: T): Boolean {
|
||||
subscriptions.forEach { it.handle(elements to element) }
|
||||
return true
|
||||
}
|
||||
|
||||
protected fun Int.isInParentRelativeWindow(): Boolean = this in fromIndex until toIndex
|
||||
|
||||
override fun isEmpty() = parentList.lastIndex < fromIndex
|
||||
|
||||
override fun isNotEmpty() = parentList.size > fromIndex
|
||||
|
||||
override fun contains(element: T) = elements.contains(element)
|
||||
|
||||
override fun containsAll(elements: Collection<T>) = this.elements.containsAll(elements)
|
||||
|
||||
/** @throws IndexOutOfBoundsException if sublist does not contain [subListIndex]. */
|
||||
protected fun parentIndex(subListIndex: Int) = throwIfOutOfBounds(subListIndex) + fromIndex
|
||||
/**
|
||||
* @throws IndexOutOfBoundsException [index] is above [currentLastIndex] or below [fromIndex]
|
||||
* @return [index]
|
||||
*/
|
||||
private fun throwIfOutOfBounds(index: Int): Int {
|
||||
return if (index in 0 until size) {
|
||||
index
|
||||
} else {
|
||||
throw IndexOutOfBoundsException("Index $index is outside the sub list window.")
|
||||
}
|
||||
}
|
||||
|
||||
override operator fun get(index: Int): T {
|
||||
return parentList[parentIndex(index)]
|
||||
}
|
||||
|
||||
override fun indexOf(element: T): Int {
|
||||
val endIndex = fromIndex + size
|
||||
for (i in fromIndex until endIndex) {
|
||||
if (elements[i] == element) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
override fun lastIndexOf(element: T): Int {
|
||||
val startIndex = fromIndex + size
|
||||
for (i in startIndex downTo fromIndex) {
|
||||
if (elements[i] == element) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
override operator fun iterator() = ObservableSubListIterator(this)
|
||||
|
||||
override fun listIterator() = ObservableSubListIterator(this)
|
||||
|
||||
override fun listIterator(index: Int) = ObservableSubListIterator(this, index)
|
||||
|
||||
override fun subList(fromIndex: Int, toIndex: Int): List<T> {
|
||||
return parentList.subList(parentIndex(fromIndex), parentIndex(toIndex))
|
||||
}
|
||||
|
||||
/** @return a read-only copy that will NOT mutate if the backing list mutates. */
|
||||
override fun copy() = ObservableList(elements, elementHandler)
|
||||
|
||||
/** @return a mutable copy that will NOT mutate if the backing list mutates. */
|
||||
fun mutableCopy() = MutableObservableList(elements, elementHandler)
|
||||
|
||||
/** @return a read-only version of [parentList] that will NOT mutate if the parent list mutates */
|
||||
fun getParentCopy(): ObservableList<T> = parentList.copy()
|
||||
|
||||
/** @return a read-only version of [parentList] that will NOT mutate if the parent list mutates */
|
||||
fun getParentMutableCopy(): MutableObservableList<T> = parentList.mutableCopy()
|
||||
|
||||
/** @return a read-only version of [parentList] that WILL mutate if the backing list mutates */
|
||||
fun getParent(): ObservableList<T> = parentList
|
||||
}
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.list
|
||||
|
||||
import com.cobblemon.mod.common.api.reactive.collections.ObservableCollectionIterator
|
||||
|
||||
open class ObservableSubListIterator<T>(
|
||||
protected val subList: ObservableSubList<T>,
|
||||
protected var index: Int = 0,
|
||||
) : ObservableCollectionIterator<T, ListIterator<T>>,
|
||||
ListIterator<T> {
|
||||
|
||||
override fun hasNext(): Boolean = index < subList.size
|
||||
|
||||
override fun hasPrevious(): Boolean = subList.isNotEmpty() && index > 0
|
||||
|
||||
override fun next(): T {
|
||||
if (!hasNext()) {
|
||||
throw NoSuchElementException(
|
||||
"Observable Sub List iterator does not have next element from index $index."
|
||||
)
|
||||
}
|
||||
return subList[index++]
|
||||
}
|
||||
|
||||
override fun previous(): T {
|
||||
if (!hasPrevious()) {
|
||||
throw NoSuchElementException(
|
||||
"Observable Sub List iterator does not have previous element from index ${index - 1}."
|
||||
)
|
||||
}
|
||||
return subList[--index]
|
||||
}
|
||||
|
||||
override fun nextIndex(): Int = index
|
||||
|
||||
override fun previousIndex(): Int = index - 1
|
||||
}
|
||||
-101
@@ -1,101 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.map
|
||||
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.reactive.collections.subscriptions.MapSubscription
|
||||
import kotlin.collections.Map.Entry
|
||||
|
||||
class MutableObservableMap<K, V>(
|
||||
map: Map<K, V> = mapOf(),
|
||||
entryHandler: (K, V) -> Set<Observable<*>> = { k, v -> k.getEntryObservables(v) },
|
||||
) : ObservableMap<K, V>(map = map, entryHandler = entryHandler),
|
||||
MutableMap<K, V> {
|
||||
|
||||
private val additionObservable = SimpleObservable<Pair<Map<K, V>, Pair<K, V>>>()
|
||||
private val removalObservable = SimpleObservable<Pair<Map<K, V>, Pair<K, V>>>()
|
||||
|
||||
fun subscribe(
|
||||
priority: Priority = Priority.NORMAL,
|
||||
anyChangeHandler: (Pair<Map<K, V>, Pair<K, V>>) -> Unit,
|
||||
additionHandler: ((Pair<Map<K, V>, Pair<K, V>>) -> Unit)? = null,
|
||||
removalHandler: ((Pair<Map<K, V>, Pair<K, V>>) -> Unit)? = null,
|
||||
): MapSubscription<K, V> {
|
||||
return MapSubscription(
|
||||
anyChange = this.subscribe(priority, anyChangeHandler),
|
||||
addition = additionHandler?.let { additionObservable.subscribe(priority, it) },
|
||||
removal = removalHandler?.let { removalObservable.subscribe(priority, it) },
|
||||
)
|
||||
}
|
||||
|
||||
fun subscribeAndHandle(
|
||||
priority: Priority = Priority.NORMAL,
|
||||
anyChangeHandler: (Pair<Map<K, V>, Pair<K, V>>) -> Unit,
|
||||
additionHandler: ((Pair<Map<K, V>, Pair<K, V>>) -> Unit)? = null,
|
||||
removalHandler: ((Pair<Map<K, V>, Pair<K, V>>) -> Unit)? = null,
|
||||
): MapSubscription<K, V> {
|
||||
entries.forEach { anyChangeHandler(this to it.pair()) }
|
||||
return subscribe(priority, anyChangeHandler, additionHandler, removalHandler)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return `true` after handling [register] & all subscriptions to [additionObservable],
|
||||
* & [ObservableMap.emitAnyChange].
|
||||
*/
|
||||
private fun emitAddition(key: K, value: V): Boolean {
|
||||
register(key, value)
|
||||
additionObservable.emit(map to (key to value))
|
||||
return emitAnyChange(key, value)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return `true` after handling [unregister] & all subscriptions to [removalObservable],
|
||||
* & [ObservableMap.emitAnyChange].
|
||||
*/
|
||||
private fun emitRemoval(key: K, value: V): Boolean {
|
||||
unregister(key, value)
|
||||
removalObservable.emit(map to (key to value))
|
||||
return emitAnyChange(key, value)
|
||||
}
|
||||
|
||||
override operator fun iterator(): MutableObservableMapIterator<K, V> {
|
||||
return MutableObservableMapIterator(this)
|
||||
}
|
||||
|
||||
operator fun set(key: K, value: V): V? = put(key, value)
|
||||
|
||||
fun put(pair: Pair<K, V>): V? = put(pair.first, pair.second)
|
||||
|
||||
fun put(entry: Entry<K, V>): V? = put(entry.key, entry.value)
|
||||
|
||||
override fun put(key: K, value: V): V? {
|
||||
val previous = map.put(key, value)
|
||||
emitAddition(key, value)
|
||||
if (previous != null) {
|
||||
emitRemoval(key, previous)
|
||||
}
|
||||
return previous
|
||||
}
|
||||
|
||||
fun remove(key: K, value: V): Boolean {
|
||||
return if (map[key] == value) (remove(key) != null) else false
|
||||
}
|
||||
|
||||
override fun remove(key: K): V? {
|
||||
val value = map.remove(key) ?: return null
|
||||
emitRemoval(key, value)
|
||||
return value
|
||||
}
|
||||
|
||||
override fun putAll(from: Map<out K, V>) = from.forEach { put(it.key, it.value) }
|
||||
|
||||
fun getOrDefault(key: K, defaultValue: V): V = map[key] ?: defaultValue
|
||||
|
||||
fun getOrPut(key: K, newValue: V) = map[key] ?: newValue.also { put(key, it) }
|
||||
|
||||
override fun clear() {
|
||||
if (map.isNotEmpty()) {
|
||||
keys.toSet().forEach { remove(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.map
|
||||
|
||||
import kotlin.collections.Map.Entry
|
||||
|
||||
open class MutableObservableMapIterator<K, V>(
|
||||
private val observableMap: MutableObservableMap<K, V>,
|
||||
) : ObservableMapIterator<K, V>(observableMap.entries.toSet().iterator()),
|
||||
MutableIterator<Entry<K, V>> {
|
||||
|
||||
private lateinit var currentEntry: Entry<K, V>
|
||||
|
||||
private var removedThisIteration: Boolean? = null
|
||||
set (value) { if (field != value) field = value }
|
||||
|
||||
override fun next(): Entry<K, V> {
|
||||
currentEntry = super.next()
|
||||
removedThisIteration = false
|
||||
return currentEntry
|
||||
}
|
||||
|
||||
override fun remove() {
|
||||
if (removedThisIteration == null) {
|
||||
throw IllegalStateException(
|
||||
"Observable Map iterator 'remove' was called before 'next' or 'previous'."
|
||||
)
|
||||
} else if (removedThisIteration == true) {
|
||||
throw IllegalStateException(
|
||||
"Observable Map iterator 'remove' was called, " +
|
||||
"but 'remove' was already called this iteration."
|
||||
)
|
||||
}
|
||||
observableMap.remove(currentEntry.key)
|
||||
removedThisIteration = true
|
||||
}
|
||||
}
|
||||
-124
@@ -1,124 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.map
|
||||
|
||||
import com.cobblemon.mod.common.api.PrioritizedList
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.reactive.ObservableSubscription
|
||||
import kotlin.Comparator
|
||||
import kotlin.collections.Map.Entry
|
||||
|
||||
open class ObservableMap<K, V>(
|
||||
map: Map<K, V>,
|
||||
protected val entryHandler: (K, V) -> Set<Observable<*>> =
|
||||
{ k: K, v: V -> k.getEntryObservables(v) },
|
||||
) : Map<K, V>,
|
||||
Observable<Pair<Map<K, V>, Pair<K, V>>> {
|
||||
|
||||
protected val map: MutableMap<K, V> = map.toMutableMap()
|
||||
private val subscriptions = PrioritizedList<ObservableSubscription<Pair<Map<K, V>, Pair<K, V>>>>()
|
||||
private val subscriptionMap: MutableMap<Observable<*>, ObservableSubscription<*>> = mutableMapOf()
|
||||
|
||||
override val size get() = map.size
|
||||
override val keys get() = map.keys
|
||||
override val values get() = map.values
|
||||
override val entries get() = map.entries
|
||||
|
||||
init {
|
||||
this.map.forEach { (key, value) ->
|
||||
entryHandler(key, value).forEach{ observable ->
|
||||
subscriptionMap[observable] = observable.subscribe {
|
||||
emitAnyChange(key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun subscribe(
|
||||
priority: Priority,
|
||||
handler: (Pair<Map<K, V>, Pair<K, V>>) -> Unit
|
||||
): ObservableSubscription<Pair<Map<K, V>, Pair<K, V>>> {
|
||||
val subscription = ObservableSubscription(this, handler)
|
||||
subscriptions.add(priority, subscription)
|
||||
return subscription
|
||||
}
|
||||
|
||||
fun subscribeAndHandle(
|
||||
priority: Priority,
|
||||
handler: (Pair<Map<K, V>, Pair<K, V>>) -> Unit
|
||||
): ObservableSubscription<Pair<Map<K, V>, Pair<K, V>>> {
|
||||
val subscription = ObservableSubscription(this, handler)
|
||||
subscriptions.add(priority, subscription)
|
||||
map.forEach { handler(this to (it.pair())) }
|
||||
return subscription
|
||||
}
|
||||
|
||||
override fun unsubscribe(subscription: ObservableSubscription<Pair<Map<K, V>, Pair<K, V>>>) {
|
||||
subscriptions.remove(subscription)
|
||||
}
|
||||
|
||||
protected open fun register(key: K, value: V) {
|
||||
if (contains(key, value)) {
|
||||
entryHandler(key, value).forEach{ observable ->
|
||||
subscriptionMap[observable] = observable.subscribe { emitAnyChange(key, value) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun unregister(key: K, value: V) {
|
||||
entryHandler(key, value).forEach{ subscriptionMap.remove(it)?.unsubscribe() }
|
||||
}
|
||||
|
||||
protected fun emitAnyChange(key: K, value: V): Boolean {
|
||||
subscriptions.forEach { it.handle(map to (key to value)) }
|
||||
return true
|
||||
}
|
||||
|
||||
override fun isEmpty() = map.isEmpty()
|
||||
|
||||
fun isNotEmpty() = map.isNotEmpty()
|
||||
|
||||
override fun containsKey(key: K) = map.containsKey(key)
|
||||
|
||||
override fun containsValue(value: V) = map.containsValue(value)
|
||||
|
||||
fun contains(pair: Pair<K, V>): Boolean = contains(pair.first, pair.second)
|
||||
|
||||
fun contains(entry: Entry<K, V>): Boolean = contains(entry.key, entry.value)
|
||||
|
||||
fun contains(key: K, value: V) = map[key] == value
|
||||
|
||||
fun contains(predicate: (Entry<K, V>) -> Boolean) = map.any(predicate)
|
||||
|
||||
fun containsAll(other: Collection<Entry<K, V>>): Boolean {
|
||||
return map.all { entry -> other.any { it.key == entry.key && it.value == entry.value } }
|
||||
}
|
||||
|
||||
fun containsAll(other: Map<K, V>): Boolean {
|
||||
return map.all { entry -> other.any { it.key == entry.key && it.value == entry.value } }
|
||||
}
|
||||
|
||||
open operator fun iterator(): Iterator<Entry<K, V>> = map.iterator()
|
||||
|
||||
override operator fun get(key: K) = map[key]
|
||||
|
||||
fun toSortedMap(comparator: Comparator<in K>) = map.toMap().toSortedMap(comparator)
|
||||
|
||||
fun firstKeyOrNull(predicate: (Entry<K, V>) -> Boolean = { true }): K? {
|
||||
map.forEach { if (predicate(it)) return it.key }
|
||||
return null
|
||||
}
|
||||
|
||||
fun firstValueOrNull(predicate: (Entry<K, V>) -> Boolean = { true }): V? {
|
||||
map.forEach { if (predicate(it)) return it.value }
|
||||
return null
|
||||
}
|
||||
|
||||
fun firstEntryOrNull(predicate: (Entry<K, V>) -> Boolean = { true }): Entry<K, V>? {
|
||||
map.forEach { if (predicate(it)) return it }
|
||||
return null
|
||||
}
|
||||
|
||||
fun copy() = ObservableMap(this.map, entryHandler)
|
||||
|
||||
fun mutableCopy() = MutableObservableMap(this.map, entryHandler)
|
||||
}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.map
|
||||
|
||||
import kotlin.collections.Map.Entry
|
||||
|
||||
open class ObservableMapIterator<K, V>(
|
||||
protected var iterator: Iterator<Entry<K, V>>
|
||||
) : Iterator<Entry<K, V>> {
|
||||
|
||||
override fun hasNext():Boolean = iterator.hasNext()
|
||||
override fun next(): Entry<K, V> = iterator.next()
|
||||
}
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.map
|
||||
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import net.minecraft.nbt.NbtCompound
|
||||
import kotlin.collections.Map.Entry
|
||||
|
||||
|
||||
fun <K, V> Map<K, V>.saveToNbt(
|
||||
entryKey: String = "entry",
|
||||
entryHandler: (Entry<K, V>) -> NbtCompound,
|
||||
): NbtCompound {
|
||||
val nbt = NbtCompound()
|
||||
var size = 0
|
||||
this.iterator().forEach { nbt.put(entryKey + size++, entryHandler(it)) }
|
||||
nbt.putInt("size", size)
|
||||
return nbt
|
||||
}
|
||||
|
||||
|
||||
fun <K, V> NbtCompound.loadObservableMapOf(
|
||||
entryKey: String = "entry",
|
||||
loadEntryHandler: (NbtCompound) -> Pair<K, V>,
|
||||
entryObservableHandler: (K, V) -> Set<Observable<*>> = { k, v -> k.getEntryObservables(v) },
|
||||
) = ObservableMap(this.loadMap(entryKey, loadEntryHandler), entryObservableHandler)
|
||||
|
||||
|
||||
fun <K, V> NbtCompound.loadMutableObservableMapOf(
|
||||
entryKey: String = "entry",
|
||||
loadEntryHandler: (NbtCompound) -> Pair<K, V>,
|
||||
entryObservableHandler: (K, V) -> Set<Observable<*>> = { k, v -> k.getEntryObservables(v) },
|
||||
) = MutableObservableMap(this.loadMap(entryKey, loadEntryHandler), entryObservableHandler)
|
||||
|
||||
|
||||
private fun <K, V> NbtCompound.loadMap(
|
||||
entryKey: String = "entry",
|
||||
entryHandler: (NbtCompound) -> Pair<K, V>,
|
||||
): MutableMap<K, V> {
|
||||
val newMap: MutableMap<K, V> = mutableMapOf()
|
||||
if (this.contains("size")) {
|
||||
val size = this.getInt("size")
|
||||
for (i in 0 until size) {
|
||||
val (key, value) = entryHandler(this.getCompound(entryKey + i))
|
||||
newMap[key] = value
|
||||
}
|
||||
}
|
||||
return newMap
|
||||
}
|
||||
-113
@@ -1,113 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.map
|
||||
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.reactive.collections.tryGetObservable
|
||||
import kotlin.collections.Map.Entry
|
||||
|
||||
|
||||
fun <K, V> Entry<K, V>.pair() = this.key to this.value
|
||||
|
||||
|
||||
fun <K, V> Collection<Entry<K, V>>.pairs(): Set<Pair<K, V>> {
|
||||
mutableSetOf<Pair<K, V>>().let { set ->
|
||||
this.forEach { set.add(it.key to it.value) }
|
||||
return set
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun <K, V> Map<K, V>.pairs(): Set<Pair<K, V>> {
|
||||
mutableSetOf<Pair<K, V>>().let { set ->
|
||||
this.forEach { set.add(it.key to it.value) }
|
||||
return set
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun <K, V> Collection<Entry<K, V>>.toMap(): Map<K, V> = this.toMutableMap()
|
||||
|
||||
|
||||
fun <K, V> Collection<Entry<K, V>>.toMutableMap(): MutableMap<K, V> {
|
||||
return mutableMapOf<K, V>().putAll(this)
|
||||
}
|
||||
|
||||
|
||||
fun <K, V> MutableMap<K, V>.putAll(entries: Collection<Entry<K, V>>): MutableMap<K, V> {
|
||||
return entries.forEach { this[it.key] = it.value }.let { this }
|
||||
}
|
||||
|
||||
|
||||
fun <K, V> defaultEntryHandler() = { k: K, v: V -> k.getEntryObservables(v) }
|
||||
|
||||
|
||||
fun <K, V> K.getEntryObservables(value: V): Set<Observable<*>> {
|
||||
val observables = mutableSetOf<Observable<*>>()
|
||||
this.tryGetObservable()?.let { observables.add(it) }
|
||||
value.tryGetObservable()?.let { observables.add(it) }
|
||||
return observables
|
||||
}
|
||||
|
||||
|
||||
fun <K, V> Map<K, V>.toObservableMap(
|
||||
entryHandler: (K, V) -> Set<Observable<*>> = defaultEntryHandler(),
|
||||
) = ObservableMap(this, entryHandler)
|
||||
|
||||
fun <K, V> Map<K, V>.toMutableObservableMap(
|
||||
entryHandler: (K, V) -> Set<Observable<*>> = defaultEntryHandler(),
|
||||
) = MutableObservableMap(this, entryHandler)
|
||||
|
||||
fun <K, V> Collection<Pair<K, V>>.toObservableMap(
|
||||
entryHandler: (K, V) -> Set<Observable<*>> = defaultEntryHandler(),
|
||||
) = ObservableMap(this.toMap(), entryHandler)
|
||||
|
||||
fun <K, V> Collection<Pair<K, V>>.toMutableObservableMap(
|
||||
entryHandler: (K, V) -> Set<Observable<*>> = defaultEntryHandler(),
|
||||
) = MutableObservableMap(this.toMap(), entryHandler)
|
||||
|
||||
fun <K, V> observableMapOf(
|
||||
entryHandler: (K, V) -> Set<Observable<*>> = defaultEntryHandler(),
|
||||
) = ObservableMap(mapOf(), entryHandler)
|
||||
|
||||
fun <K, V> mutableObservableMapOf(
|
||||
entryHandler: (K, V) -> Set<Observable<*>> = defaultEntryHandler(),
|
||||
) = MutableObservableMap(mapOf(), entryHandler)
|
||||
|
||||
fun <K, V> observableMapOf(
|
||||
map: Map<K, V> = emptyMap(),
|
||||
entryHandler: (K, V) -> Set<Observable<*>> = defaultEntryHandler(),
|
||||
) = ObservableMap(map, entryHandler)
|
||||
|
||||
fun <K, V> observableMapOf(
|
||||
vararg pairs: Pair<K, V>,
|
||||
entryHandler: (K, V) -> Set<Observable<*>> = defaultEntryHandler(),
|
||||
) = ObservableMap(pairs.toMap(), entryHandler)
|
||||
|
||||
fun <K, V> mutableObservableMapOf(
|
||||
vararg pairs: Pair<K, V>,
|
||||
entryHandler: (K, V) -> Set<Observable<*>> = defaultEntryHandler(),
|
||||
) = MutableObservableMap(pairs.toMap(), entryHandler)
|
||||
|
||||
fun <K, V> mutableObservableMapOf(
|
||||
map: Map<K, V> = emptyMap(),
|
||||
entryHandler: (K, V) -> Set<Observable<*>> = defaultEntryHandler(),
|
||||
) = MutableObservableMap(map, entryHandler)
|
||||
|
||||
fun <K, V> observableMapOf(
|
||||
vararg entries: Entry<K, V>,
|
||||
entryHandler: (K, V) -> Set<Observable<*>> = defaultEntryHandler(),
|
||||
) = ObservableMap(entries.toSet().toMap(), entryHandler)
|
||||
|
||||
fun <K, V> mutableObservableMapOf(
|
||||
vararg entries: Entry<K, V>,
|
||||
entryHandler: (K, V) -> Set<Observable<*>> = defaultEntryHandler(),
|
||||
) = MutableObservableMap(entries.toSet().toMap(), entryHandler)
|
||||
|
||||
fun <K, V> observableMapOf(
|
||||
pairs: Collection<Pair<K, V>> = emptySet(),
|
||||
entryHandler: (K, V) -> Set<Observable<*>> = defaultEntryHandler(),
|
||||
) = ObservableMap(pairs.toMap(), entryHandler)
|
||||
|
||||
fun <K, V> mutableObservableMapOf(
|
||||
pairs: Collection<Pair<K, V>> = emptySet(),
|
||||
entryHandler: (K, V) -> Set<Observable<*>> = defaultEntryHandler(),
|
||||
) = MutableObservableMap(pairs.toMap(), entryHandler)
|
||||
-100
@@ -1,100 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.set
|
||||
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.reactive.collections.MutableObservableCollection
|
||||
import com.cobblemon.mod.common.api.reactive.collections.getElementObservables
|
||||
import com.cobblemon.mod.common.api.reactive.collections.subscriptions.SetSubscription
|
||||
import com.cobblemon.mod.common.api.reactive.collections.removeIf
|
||||
|
||||
class MutableObservableSet<T>(
|
||||
set: Collection<T> = setOf(),
|
||||
elementHandler: (T) -> Set<Observable<*>> = { it.getElementObservables() },
|
||||
) : MutableObservableCollection<T, Set<T>>,
|
||||
ObservableSet<T>(set, elementHandler),
|
||||
MutableSet<T> {
|
||||
|
||||
private val additionObservable = SimpleObservable<Pair<Set<T>, T>>()
|
||||
private val removalObservable = SimpleObservable<Pair<Set<T>, T>>()
|
||||
|
||||
override fun subscribe(
|
||||
priority: Priority,
|
||||
anyChangeHandler: (Pair<Set<T>, T>) -> Unit,
|
||||
additionHandler: ((Pair<Set<T>, T>) -> Unit)?,
|
||||
removalHandler: ((Pair<Set<T>, T>) -> Unit)?,
|
||||
): SetSubscription<T> {
|
||||
return SetSubscription(
|
||||
anyChange = this.subscribe(priority, anyChangeHandler),
|
||||
addition = additionHandler?.let { additionObservable.subscribe(priority, it) },
|
||||
removal = removalHandler?.let { removalObservable.subscribe(priority, it) },
|
||||
)
|
||||
}
|
||||
|
||||
fun subscribeAndHandle(
|
||||
priority: Priority,
|
||||
anyChangeHandler: (Pair<Set<T>, T>) -> Unit,
|
||||
additionHandler: ((Pair<Set<T>, T>) -> Unit)?,
|
||||
removalHandler: ((Pair<Set<T>, T>) -> Unit)?,
|
||||
): SetSubscription<T> {
|
||||
elements.forEach { anyChangeHandler(this to it) }
|
||||
return subscribe(priority, anyChangeHandler, additionHandler, removalHandler)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return `true` after handling [register] & all subscriptions to [additionObservable]
|
||||
* & [ObservableSet.emitAnyChange].
|
||||
*/
|
||||
private fun emitAddition(element: T): Boolean {
|
||||
register(element)
|
||||
additionObservable.emit(set to element)
|
||||
return emitAnyChange(element)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return `true` after handling [unregister] & all subscriptions to [removalObservable]
|
||||
* & [ObservableSet.emitAnyChange].
|
||||
*/
|
||||
private fun emitRemoval(element: T): Boolean {
|
||||
unregister(element)
|
||||
removalObservable.emit(set to element)
|
||||
return emitAnyChange(element)
|
||||
}
|
||||
|
||||
override operator fun iterator() = MutableObservableSetIterator(this)
|
||||
|
||||
override fun addIf(element: T, predicate: (Set<T>) -> Boolean): Boolean {
|
||||
return if (predicate(set)) add(element) else false
|
||||
}
|
||||
|
||||
override fun add(element: T): Boolean {
|
||||
return if (set.add(element)) emitAddition(element) else false
|
||||
}
|
||||
|
||||
override fun removeIf(predicate: (T) -> Boolean): Boolean {
|
||||
return iterator().removeIf(predicate)
|
||||
}
|
||||
|
||||
fun removeIf(element: T, predicate: (Set<T>) -> Boolean): Boolean {
|
||||
return if (predicate(set)) remove(element) else false
|
||||
}
|
||||
|
||||
override fun remove(element: T): Boolean {
|
||||
return if (set.remove(element)) emitRemoval(element) else false
|
||||
}
|
||||
|
||||
override fun addAll(elements: Collection<T>): Boolean {
|
||||
var mutated = false
|
||||
elements.forEach { if (add(it) && !mutated) mutated = true }
|
||||
return mutated
|
||||
}
|
||||
|
||||
override fun removeAll(elements: Collection<T>):Boolean = removeIf { elements.contains(it) }
|
||||
|
||||
override fun retainAll(elements: Collection<T>):Boolean = removeIf { !elements.contains(it) }
|
||||
|
||||
override fun clear() {
|
||||
// just a simpler way to call the mutable iterator & emit with each removal
|
||||
removeIf { true }
|
||||
}
|
||||
}
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.set
|
||||
|
||||
import com.cobblemon.mod.common.api.reactive.collections.MutableObservableCollectionIterator
|
||||
|
||||
open class MutableObservableSetIterator<T>(
|
||||
private val observableSet: MutableObservableSet<T>,
|
||||
) : MutableObservableCollectionIterator<T, Set<T>, Iterator<T>>,
|
||||
ObservableSetIterator<T>(observableSet.elements.toSet().iterator()),
|
||||
MutableIterator<T> {
|
||||
|
||||
private var currentElement: T? = null
|
||||
set (value) { if (field != value) field = value }
|
||||
|
||||
private var removedThisIteration: Boolean = false
|
||||
set (value) { if (field != value) field = value }
|
||||
|
||||
override fun next(): T {
|
||||
currentElement = iterator.next()
|
||||
removedThisIteration = false
|
||||
return currentElement!!
|
||||
}
|
||||
|
||||
override fun remove() {
|
||||
if (currentElement == null) {
|
||||
throw IllegalStateException("Observable Set iterator 'remove' was called before 'next' or 'previous'.")
|
||||
} else if (removedThisIteration) {
|
||||
throw IllegalStateException("Observable Set iterator 'remove' was called, but 'remove' was already called this iteration.")
|
||||
}
|
||||
observableSet.remove(currentElement)
|
||||
currentElement = null
|
||||
removedThisIteration = true
|
||||
}
|
||||
}
|
||||
-86
@@ -1,86 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.set
|
||||
|
||||
import com.cobblemon.mod.common.api.PrioritizedList
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.reactive.ObservableSubscription
|
||||
import com.cobblemon.mod.common.api.reactive.collections.ObservableCollection
|
||||
import com.cobblemon.mod.common.api.reactive.collections.getElementObservables
|
||||
|
||||
open class ObservableSet<T>(
|
||||
set: Collection<T>,
|
||||
protected val elementHandler: (T) -> Set<Observable<*>> = { it.getElementObservables() },
|
||||
) : ObservableCollection<T, Set<T>>,
|
||||
Set<T>,
|
||||
Observable<Pair<Set<T>, T>> {
|
||||
|
||||
protected val set: MutableSet<T> = set.toMutableSet()
|
||||
private val subscriptions = PrioritizedList<ObservableSubscription<Pair<Set<T>, T>>>()
|
||||
private val subscriptionMap: MutableMap<Observable<*>, ObservableSubscription<*>> = mutableMapOf()
|
||||
|
||||
// Keep as 'this.set' & not 'set,' b/c compiler doesn't like it & cries a little.
|
||||
override val elements: Set<T> get() = this.set
|
||||
override val size: Int get() = set.size
|
||||
|
||||
init {
|
||||
set.forEach { register(it) }
|
||||
}
|
||||
|
||||
override fun subscribe(
|
||||
priority: Priority,
|
||||
handler: (Pair<Set<T>, T>) -> Unit,
|
||||
): ObservableSubscription<Pair<Set<T>, T>> {
|
||||
val subscription = ObservableSubscription(this, handler)
|
||||
subscriptions.add(priority, subscription)
|
||||
return subscription
|
||||
}
|
||||
|
||||
fun subscribeAndHandle(
|
||||
priority: Priority,
|
||||
handler: (Pair<Set<T>, T>) -> Unit
|
||||
): ObservableSubscription<Pair<Set<T>, T>> {
|
||||
val subscription = ObservableSubscription(this, handler)
|
||||
subscriptions.add(priority, subscription)
|
||||
set.forEach { handler(this to it) }
|
||||
return subscription
|
||||
}
|
||||
|
||||
/*
|
||||
TODO: fix issue where passing subscription to addition or removal does not unsubscribe
|
||||
Does this issue really matter?
|
||||
Calling unsubscribe from the subscription directly works as intended
|
||||
*/
|
||||
override fun unsubscribe(subscription: ObservableSubscription<Pair<Set<T>, T>>) {
|
||||
subscriptions.remove(subscription)
|
||||
}
|
||||
|
||||
protected fun register(element: T) {
|
||||
elementHandler(element).forEach{ observable ->
|
||||
subscriptionMap[observable] = observable.subscribe { emitAnyChange(element) }
|
||||
}
|
||||
}
|
||||
|
||||
protected fun unregister(element: T) {
|
||||
elementHandler(element).forEach{ subscriptionMap.remove(it)?.unsubscribe() }
|
||||
}
|
||||
|
||||
/** @return true after handling [subscriptions]. */
|
||||
protected fun emitAnyChange(element: T): Boolean {
|
||||
subscriptions.forEach { it.handle(set to element) }
|
||||
return true
|
||||
}
|
||||
|
||||
override fun isEmpty() = set.isEmpty()
|
||||
|
||||
override fun isNotEmpty() = set.isNotEmpty()
|
||||
|
||||
override fun contains(element: T) = set.contains(element)
|
||||
|
||||
override fun containsAll(elements: Collection<T>) = set.containsAll(elements)
|
||||
|
||||
override operator fun iterator(): Iterator<T> = set.iterator()
|
||||
|
||||
override fun copy() = ObservableSet(set, elementHandler)
|
||||
|
||||
fun mutableCopy() = MutableObservableSet(set, elementHandler)
|
||||
}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.set
|
||||
|
||||
import com.cobblemon.mod.common.api.reactive.collections.ObservableCollectionIterator
|
||||
|
||||
open class ObservableSetIterator<T>(
|
||||
protected var iterator: Iterator<T>
|
||||
) : ObservableCollectionIterator<T, Iterator<T>> {
|
||||
|
||||
override fun hasNext():Boolean = iterator.hasNext()
|
||||
override fun next(): T = iterator.next()
|
||||
}
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.set
|
||||
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.reactive.collections.getElementObservables
|
||||
import net.minecraft.nbt.NbtCompound
|
||||
|
||||
|
||||
fun <T> Set<T>.saveToNbt(
|
||||
elementKey: String = "element",
|
||||
elementHandler: (T) -> NbtCompound,
|
||||
): NbtCompound {
|
||||
val nbt = NbtCompound()
|
||||
var size = 0
|
||||
this.iterator().forEach { nbt.put(elementKey + size++, elementHandler(it)) }
|
||||
nbt.putInt("size", size)
|
||||
return nbt
|
||||
}
|
||||
|
||||
|
||||
fun <T> NbtCompound.loadObservableSetOf(
|
||||
elementKey: String = "element",
|
||||
loadElementHandler: (NbtCompound) -> T,
|
||||
elementObservableHandler: (T) -> Set<Observable<*>> = { it.getElementObservables() },
|
||||
) = ObservableSet(this.loadSet(elementKey, loadElementHandler), elementObservableHandler)
|
||||
|
||||
|
||||
fun <T> NbtCompound.loadMutableObservableSetOf(
|
||||
elementKey: String = "element",
|
||||
loadElementHandler: (NbtCompound) -> T,
|
||||
elementObservableHandler: (T) -> Set<Observable<*>> = { it.getElementObservables() },
|
||||
) = MutableObservableSet(this.loadSet(elementKey, loadElementHandler), elementObservableHandler)
|
||||
|
||||
|
||||
private fun <T> NbtCompound.loadSet(
|
||||
elementKey: String = "element",
|
||||
elementHandler: (NbtCompound) -> T,
|
||||
): Set<T> {
|
||||
val newSet = mutableSetOf<T>()
|
||||
if (this.contains("size")) {
|
||||
val size = this.getInt("size")
|
||||
for (i in 0 until size) {
|
||||
newSet.add(elementHandler(this.getCompound(elementKey + i)))
|
||||
}
|
||||
}
|
||||
return newSet
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.set
|
||||
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.reactive.collections.getElementObservables
|
||||
|
||||
|
||||
fun <T> Collection<T>.toObservableSet(
|
||||
elementHandler: (T) -> Set<Observable<*>> = { it.getElementObservables() },
|
||||
) = ObservableSet(this, elementHandler)
|
||||
|
||||
|
||||
fun <T> Collection<T>.toMutableObservableSet(
|
||||
elementHandler: (T) -> Set<Observable<*>> = { it.getElementObservables() },
|
||||
) = MutableObservableSet(this, elementHandler)
|
||||
|
||||
|
||||
fun <T> observableSetOf(
|
||||
vararg elements: T,
|
||||
elementHandler: (T) -> Set<Observable<*>> = { it.getElementObservables() },
|
||||
): ObservableSet<T> = ObservableSet(elements.toSet(), elementHandler)
|
||||
|
||||
|
||||
fun <T> mutableObservableSetOf(
|
||||
vararg elements: T,
|
||||
elementHandler: (T) -> Set<Observable<*>> = { it.getElementObservables() },
|
||||
): MutableObservableSet<T> = MutableObservableSet(elements.toSet(), elementHandler)
|
||||
|
||||
|
||||
fun <T> observableSetOf(
|
||||
elements: Collection<T> = setOf(),
|
||||
elementHandler: (T) -> Set<Observable<*>> = { it.getElementObservables() },
|
||||
): ObservableSet<T> = ObservableSet(elements, elementHandler)
|
||||
|
||||
|
||||
fun <T> mutableObservableSetOf(
|
||||
elements: Collection<T> = setOf(),
|
||||
elementHandler: (T) -> Set<Observable<*>> = { it.getElementObservables() },
|
||||
): MutableObservableSet<T> = MutableObservableSet(elements, elementHandler)
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.subscriptions
|
||||
|
||||
import com.cobblemon.mod.common.api.reactive.ObservableSubscription
|
||||
|
||||
/**
|
||||
* Immutable observable collections implement an [anyChange] observable subscription directly.
|
||||
*
|
||||
* Mutable observable collections implement [anyChange], [addition], & [removal] subscriptions
|
||||
* through a [CollectionSubscription].
|
||||
*
|
||||
* @property anyChange Emits with any mutation of the collection or the collection's observable elements.
|
||||
*
|
||||
* @property addition Emits when any collection mutation results from the addition of an element.
|
||||
*
|
||||
* @property removal Emits when any collection mutation results from the removal of an element.
|
||||
*
|
||||
* @see ListSubscription.set
|
||||
* @see ListSubscription.swap
|
||||
*/
|
||||
interface CollectionSubscription<T, C : Collection<T>> {
|
||||
|
||||
val anyChange: ObservableSubscription<Pair<C, T>>
|
||||
val addition: ObservableSubscription<Pair<C, T>>?
|
||||
val removal: ObservableSubscription<Pair<C, T>>?
|
||||
|
||||
fun unsubscribe()
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.subscriptions
|
||||
|
||||
import com.cobblemon.mod.common.api.reactive.ObservableSubscription
|
||||
|
||||
data class IndexedListSubscription<T>(
|
||||
val addition: ObservableSubscription<Triple<List<T>, T, Int>>? = null,
|
||||
val removal: ObservableSubscription<Triple<List<T>, T, Int>>? = null,
|
||||
val set: ObservableSubscription<Triple<List<T>, Pair<T, T>, Int>>? = null,
|
||||
val swap: ObservableSubscription<Triple<List<T>, Pair<T, T>, Pair<Int, Int>>>? = null,
|
||||
) {
|
||||
|
||||
fun unsubscribe() {
|
||||
addition?.unsubscribe()
|
||||
removal?.unsubscribe()
|
||||
set?.unsubscribe()
|
||||
swap?.unsubscribe()
|
||||
}
|
||||
}
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.subscriptions
|
||||
|
||||
import com.cobblemon.mod.common.api.reactive.ObservableSubscription
|
||||
|
||||
data class ListSubscription<T>(
|
||||
override val anyChange: ObservableSubscription<Pair<List<T>, T>>,
|
||||
override val addition: ObservableSubscription<Pair<List<T>, T>>? = null,
|
||||
override val removal: ObservableSubscription<Pair<List<T>, T>>? = null,
|
||||
val set: ObservableSubscription<Pair<List<T>, Pair<T, T>>>? = null,
|
||||
val swap: ObservableSubscription<Pair<List<T>, Pair<T, T>>>? = null,
|
||||
) : CollectionSubscription<T, List<T>> {
|
||||
|
||||
override fun unsubscribe() {
|
||||
this.anyChange.unsubscribe()
|
||||
addition?.unsubscribe()
|
||||
removal?.unsubscribe()
|
||||
set?.unsubscribe()
|
||||
swap?.unsubscribe()
|
||||
}
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.subscriptions
|
||||
|
||||
import com.cobblemon.mod.common.api.reactive.ObservableSubscription
|
||||
import com.cobblemon.mod.common.api.reactive.collections.map.ObservableMap
|
||||
import com.cobblemon.mod.common.api.reactive.collections.map.MutableObservableMap
|
||||
|
||||
/**
|
||||
* The immutable [ObservableMap] implements an [anyChange] observable subscription directly.
|
||||
*
|
||||
* The [MutableObservableMap] implements [anyChange], [addition], & [removal] subscriptions
|
||||
* through this class.
|
||||
*
|
||||
* @property anyChange Emits with any mutation from removal, addition, or a mutation in place by
|
||||
* an entry extending the observable interface.
|
||||
*
|
||||
* @property addition Emits when any mutation results from the addition of an element.
|
||||
*
|
||||
* @property removal Emits when any mutation results from the removal of an element.
|
||||
*/
|
||||
data class MapSubscription<K, T>(
|
||||
val anyChange: ObservableSubscription<Pair<Map<K, T>, Pair<K, T>>>,
|
||||
val addition: ObservableSubscription<Pair<Map<K, T>, Pair<K, T>>>? = null,
|
||||
val removal: ObservableSubscription<Pair<Map<K, T>, Pair<K, T>>>? = null,
|
||||
) {
|
||||
|
||||
fun unsubscribe() {
|
||||
anyChange.unsubscribe()
|
||||
addition?.unsubscribe()
|
||||
removal?.unsubscribe()
|
||||
}
|
||||
}
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
package com.cobblemon.mod.common.api.reactive.collections.subscriptions
|
||||
|
||||
import com.cobblemon.mod.common.api.reactive.ObservableSubscription
|
||||
|
||||
data class SetSubscription<T>(
|
||||
override val anyChange: ObservableSubscription<Pair<Set<T>, T>>,
|
||||
override val addition: ObservableSubscription<Pair<Set<T>, T>>? = null,
|
||||
override val removal: ObservableSubscription<Pair<Set<T>, T>>? = null,
|
||||
) : CollectionSubscription<T, Set<T>> {
|
||||
|
||||
override fun unsubscribe() {
|
||||
this.anyChange.unsubscribe()
|
||||
addition?.unsubscribe()
|
||||
removal?.unsubscribe()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.reference
|
||||
|
||||
/**
|
||||
* Reference data interface. Reference data is defined as information that applies to Cobblemon structurally,
|
||||
* such as species, stat types, Pokémon types, etc. These do not change during runtime, and are instead used only
|
||||
* referentially.
|
||||
*
|
||||
* A Cobblemon class or interface that implements this interface is capable of being added/modified/deleted
|
||||
* on the server side and this information will reach the client on login.
|
||||
*/
|
||||
interface ReferenceData {
|
||||
/**
|
||||
* A unique identifier for this piece of reference data among this reference collection.
|
||||
* Used to identify when two pieces of reference data are describing the same thing.
|
||||
*/
|
||||
fun id(): String
|
||||
/** Generate a hash to be able to tell if the server and client have a differing version of this. */
|
||||
override fun hashCode(): Int
|
||||
|
||||
// TODO write and read from byte buffer
|
||||
}
|
||||
@@ -78,8 +78,8 @@ class ParticleEvent(
|
||||
particleEffect?.let { effect ->
|
||||
val bedrockParticleOptions = BedrockParticleOptionsRepository.getEffect(effect.effect) ?: return@let
|
||||
val rootMatrix = when (effect.type) {
|
||||
EventParticleOptions.EventParticleType.EMITTER-> MatrixWrapper().updatePosition(storm.matrixWrapper.position).updateMatrix(storm.matrixWrapper.matrix)
|
||||
EventParticleOptions.EventParticleType.EMITTER_BOUND -> storm.matrixWrapper
|
||||
EventParticleOptions.EventParticleType.EMITTER,// -> MatrixWrapper().updatePosition(storm.matrixWrapper.getOrigin())
|
||||
EventParticleOptions.EventParticleType.EMITTER_BOUND,// -> storm.matrixWrapper
|
||||
EventParticleOptions.EventParticleType.PARTICLE,
|
||||
EventParticleOptions.EventParticleType.PARTICLE_WITH_VELOCITY -> (particle?.let {
|
||||
Vec3(
|
||||
@@ -91,8 +91,8 @@ class ParticleEvent(
|
||||
}
|
||||
|
||||
val sourceVelocity = when (effect.type) {
|
||||
EventParticleOptions.EventParticleType.EMITTER -> storm.sourceVelocity().let { { it } }
|
||||
EventParticleOptions.EventParticleType.EMITTER_BOUND -> storm.sourceVelocity
|
||||
EventParticleOptions.EventParticleType.EMITTER,// -> storm.sourceVelocity().let { { it } }
|
||||
EventParticleOptions.EventParticleType.EMITTER_BOUND,// -> storm.sourceVelocity
|
||||
EventParticleOptions.EventParticleType.PARTICLE -> { { Vec3.ZERO } }
|
||||
EventParticleOptions.EventParticleType.PARTICLE_WITH_VELOCITY -> (particle?.let {
|
||||
Vec3(
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user