From b4990a6664e0a9c9e66c5856f15cd5126fa9c8c3 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Wed, 20 May 2020 14:55:59 +0200 Subject: [PATCH] eyes of the shulker and blaze --- build.gradle | 2 +- .../models/item/end_city_finder.json | 6 + .../models/item/fortress_finder.json | 6 + .../enchantibility/EnchantibilityCompat.java | 5 +- .../entities/EntityStructureFinder.java | 144 ++++++++++++++++++ .../naturesaura/entities/ModEntities.java | 1 + .../items/ItemStructureFinder.java | 42 +++++ .../ellpeck/naturesaura/items/ModItems.java | 2 + .../naturesaura/packet/PacketParticles.java | 21 +++ .../ellpeck/naturesaura/reg/ModRegistry.java | 18 ++- .../assets/naturesaura/lang/en_us.json | 2 + .../textures/item/end_city_finder.png | Bin 0 -> 458 bytes .../textures/item/fortress_finder.png | Bin 0 -> 484 bytes .../en_us/entries/items/end_city_finder.json | 17 +++ .../en_us/entries/items/fortress_finder.json | 17 +++ .../naturesaura/recipes/end_city_finder.json | 26 ++++ .../naturesaura/recipes/fortress_finder.json | 26 ++++ 17 files changed, 325 insertions(+), 10 deletions(-) create mode 100644 src/generated/resources/assets/naturesaura/models/item/end_city_finder.json create mode 100644 src/generated/resources/assets/naturesaura/models/item/fortress_finder.json create mode 100644 src/main/java/de/ellpeck/naturesaura/entities/EntityStructureFinder.java create mode 100644 src/main/java/de/ellpeck/naturesaura/items/ItemStructureFinder.java create mode 100644 src/main/resources/assets/naturesaura/textures/item/end_city_finder.png create mode 100644 src/main/resources/assets/naturesaura/textures/item/fortress_finder.png create mode 100644 src/main/resources/data/naturesaura/patchouli_books/book/en_us/entries/items/end_city_finder.json create mode 100644 src/main/resources/data/naturesaura/patchouli_books/book/en_us/entries/items/fortress_finder.json create mode 100644 src/main/resources/data/naturesaura/recipes/end_city_finder.json create mode 100644 src/main/resources/data/naturesaura/recipes/fortress_finder.json diff --git a/build.gradle b/build.gradle index 857b1b3a..10cb3916 100644 --- a/build.gradle +++ b/build.gradle @@ -110,7 +110,7 @@ dependencies { compileOnly fg.deobf("top.theillusivec4.curios:curios:FORGE-1.15.2-2.0-beta2:api") compile fg.deobf("com.blamejared.crafttweaker:CraftTweaker-1.15.1:6.0.0.4") - compile fg.deobf("quarris.enchantability:enchantability:5.0.1") + compile fg.deobf("quarris.enchantability:enchantability:8.1.15") } // Example for how to get properties into the manifest for reading by the runtime.. diff --git a/src/generated/resources/assets/naturesaura/models/item/end_city_finder.json b/src/generated/resources/assets/naturesaura/models/item/end_city_finder.json new file mode 100644 index 00000000..775acad6 --- /dev/null +++ b/src/generated/resources/assets/naturesaura/models/item/end_city_finder.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "naturesaura:item/end_city_finder" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/naturesaura/models/item/fortress_finder.json b/src/generated/resources/assets/naturesaura/models/item/fortress_finder.json new file mode 100644 index 00000000..ac07dcbc --- /dev/null +++ b/src/generated/resources/assets/naturesaura/models/item/fortress_finder.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "naturesaura:item/fortress_finder" + } +} \ No newline at end of file diff --git a/src/main/java/de/ellpeck/naturesaura/compat/enchantibility/EnchantibilityCompat.java b/src/main/java/de/ellpeck/naturesaura/compat/enchantibility/EnchantibilityCompat.java index 06c0c5d3..4cd98638 100644 --- a/src/main/java/de/ellpeck/naturesaura/compat/enchantibility/EnchantibilityCompat.java +++ b/src/main/java/de/ellpeck/naturesaura/compat/enchantibility/EnchantibilityCompat.java @@ -14,9 +14,8 @@ public class EnchantibilityCompat implements ICompat { @Override public void setup() { DeferredWorkQueue.runLater(() -> { - IInternals api = EnchantabilityApi.getInstance(); - api.registerEnchantEffect(EnchantibilityAuraMending.RES, ModEnchantments.AURA_MENDING, EnchantibilityAuraMending::new); - api.registerEffectComponent(EnchantibilityAuraMending.RES, TickEvent.PlayerTickEvent.class, EnchantibilityAuraMending::onPlayerTick, e -> Collections.singletonList(e.player)); + EnchantabilityApi.registerEnchantEffect(EnchantibilityAuraMending.RES, ModEnchantments.AURA_MENDING, EnchantibilityAuraMending::new); + EnchantabilityApi.registerEffectComponent(EnchantibilityAuraMending.RES, TickEvent.PlayerTickEvent.class, EnchantibilityAuraMending::onPlayerTick, e -> Collections.singletonList(e.player)); }); } diff --git a/src/main/java/de/ellpeck/naturesaura/entities/EntityStructureFinder.java b/src/main/java/de/ellpeck/naturesaura/entities/EntityStructureFinder.java new file mode 100644 index 00000000..ef2c0588 --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/entities/EntityStructureFinder.java @@ -0,0 +1,144 @@ +package de.ellpeck.naturesaura.entities; + +import de.ellpeck.naturesaura.api.NaturesAuraAPI; +import de.ellpeck.naturesaura.packet.PacketHandler; +import de.ellpeck.naturesaura.packet.PacketParticles; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.item.EyeOfEnderEntity; +import net.minecraft.entity.item.ItemEntity; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.network.IPacket; +import net.minecraft.network.datasync.DataParameter; +import net.minecraft.network.datasync.DataSerializers; +import net.minecraft.network.datasync.EntityDataManager; +import net.minecraft.particles.ParticleTypes; +import net.minecraft.util.SoundEvents; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeHooks; +import net.minecraftforge.fml.network.NetworkHooks; + +public class EntityStructureFinder extends EyeOfEnderEntity { + + public static final DataParameter COLOR = EntityDataManager.createKey(EntityStructureFinder.class, DataSerializers.VARINT); + + private double targetX; + private double targetY; + private double targetZ; + private int despawnTimer; + private boolean shatterOrDrop; + + public EntityStructureFinder(EntityType type, World world) { + super(type, world); + } + + @Override + protected void registerData() { + super.registerData(); + this.dataManager.register(COLOR, 0); + } + + @Override + public void writeAdditional(CompoundNBT compound) { + super.writeAdditional(compound); + compound.putInt("color", this.dataManager.get(COLOR)); + } + + @Override + public void readAdditional(CompoundNBT compound) { + super.readAdditional(compound); + this.dataManager.set(COLOR, compound.getInt("color")); + } + + @Override + public void moveTowards(BlockPos pos) { + double d0 = pos.getX(); + int i = pos.getY(); + double d1 = pos.getZ(); + double d2 = d0 - this.getPosX(); + double d3 = d1 - this.getPosZ(); + float f = MathHelper.sqrt(d2 * d2 + d3 * d3); + if (f > 12.0F) { + this.targetX = this.getPosX() + d2 / (double) f * 12.0D; + this.targetZ = this.getPosZ() + d3 / (double) f * 12.0D; + this.targetY = this.getPosY() + 8.0D; + } else { + this.targetX = d0; + this.targetY = i; + this.targetZ = d1; + } + + this.despawnTimer = 0; + this.shatterOrDrop = this.rand.nextInt(4) > 0; + } + + @Override + public void tick() { + this.baseTick(); + + Vec3d vec3d = this.getMotion(); + double d0 = this.getPosX() + vec3d.x; + double d1 = this.getPosY() + vec3d.y; + double d2 = this.getPosZ() + vec3d.z; + float f = MathHelper.sqrt(horizontalMag(vec3d)); + this.rotationYaw = (float) (MathHelper.atan2(vec3d.x, vec3d.z) * (double) (180F / (float) Math.PI)); + this.rotationPitch = (float) (MathHelper.atan2(vec3d.y, f) * (double) (180F / (float) Math.PI)); + while (this.rotationPitch - this.prevRotationPitch < -180.0F) + this.prevRotationPitch -= 360.0F; + while (this.rotationPitch - this.prevRotationPitch >= 180.0F) + this.prevRotationPitch += 360.0F; + while (this.rotationYaw - this.prevRotationYaw < -180.0F) + this.prevRotationYaw -= 360.0F; + while (this.rotationYaw - this.prevRotationYaw >= 180.0F) + this.prevRotationYaw += 360.0F; + this.rotationPitch = MathHelper.lerp(0.2F, this.prevRotationPitch, this.rotationPitch); + this.rotationYaw = MathHelper.lerp(0.2F, this.prevRotationYaw, this.rotationYaw); + if (!this.world.isRemote) { + double d3 = this.targetX - d0; + double d4 = this.targetZ - d2; + float f1 = (float) Math.sqrt(d3 * d3 + d4 * d4); + float f2 = (float) MathHelper.atan2(d4, d3); + double d5 = MathHelper.lerp(0.0025D, f, f1); + double d6 = vec3d.y; + if (f1 < 1.0F) { + d5 *= 0.8D; + d6 *= 0.8D; + } + + int j = this.getPosY() < this.targetY ? 1 : -1; + vec3d = new Vec3d(Math.cos(f2) * d5, d6 + ((double) j - d6) * (double) 0.015F, Math.sin(f2) * d5); + this.setMotion(vec3d); + } + + if (this.isInWater()) { + for (int i = 0; i < 4; ++i) + this.world.addParticle(ParticleTypes.BUBBLE, d0 - vec3d.x * 0.25D, d1 - vec3d.y * 0.25D, d2 - vec3d.z * 0.25D, vec3d.x, vec3d.y, vec3d.z); + } else if (this.world.isRemote) { + NaturesAuraAPI.instance().spawnMagicParticle(d0 - vec3d.x * 0.25D + this.rand.nextDouble() * 0.6D - 0.3D, d1 - vec3d.y * 0.25D - 0.5D, d2 - vec3d.z * 0.25D + this.rand.nextDouble() * 0.6D - 0.3D, vec3d.x * 0.25F, vec3d.y * 0.25F, vec3d.z * 0.25F, this.dataManager.get(COLOR), 1, 50, 0, false, true); + } + + if (!this.world.isRemote) { + this.setPosition(d0, d1, d2); + ++this.despawnTimer; + if (this.despawnTimer > 80 && !this.world.isRemote) { + this.playSound(SoundEvents.ENTITY_ENDER_EYE_DEATH, 1.0F, 1.0F); + this.remove(); + if (this.shatterOrDrop) { + this.world.addEntity(new ItemEntity(this.world, this.getPosX(), this.getPosY(), this.getPosZ(), this.getItem())); + } else { + PacketHandler.sendToAllAround(this.world, this.getPosition(), 32, new PacketParticles((float) this.getPosX(), (float) this.getPosY(), (float) this.getPosZ(), PacketParticles.Type.STRUCTURE_FINDER, this.getEntityId())); + } + } + } else { + this.setRawPosition(d0, d1, d2); + } + + } + + @Override + public IPacket createSpawnPacket() { + return NetworkHooks.getEntitySpawningPacket(this); + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/entities/ModEntities.java b/src/main/java/de/ellpeck/naturesaura/entities/ModEntities.java index 61945b48..fae14d11 100644 --- a/src/main/java/de/ellpeck/naturesaura/entities/ModEntities.java +++ b/src/main/java/de/ellpeck/naturesaura/entities/ModEntities.java @@ -7,4 +7,5 @@ public final class ModEntities { public static EntityType MOVER_CART; public static EntityType EFFECT_INHIBITOR; public static EntityType LIGHT_PROJECTILE; + public static EntityType STRUCTURE_FINDER; } diff --git a/src/main/java/de/ellpeck/naturesaura/items/ItemStructureFinder.java b/src/main/java/de/ellpeck/naturesaura/items/ItemStructureFinder.java new file mode 100644 index 00000000..95ecde7b --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/items/ItemStructureFinder.java @@ -0,0 +1,42 @@ +package de.ellpeck.naturesaura.items; + +import de.ellpeck.naturesaura.entities.EntityStructureFinder; +import de.ellpeck.naturesaura.entities.ModEntities; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.ActionResultType; +import net.minecraft.util.Hand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.server.ServerWorld; + +public class ItemStructureFinder extends ItemImpl { + private final String structureName; + private final int color; + + public ItemStructureFinder(String baseName, String structureName, int color) { + super(baseName); + this.structureName = structureName; + this.color = color; + } + + @Override + public ActionResult onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) { + ItemStack stack = playerIn.getHeldItem(handIn); + if (!worldIn.isRemote) { + BlockPos pos = ((ServerWorld) worldIn).getChunkProvider().getChunkGenerator().findNearestStructure(worldIn, this.structureName, playerIn.getPosition(), 1024, false); + if (pos != null) { + EntityStructureFinder entity = new EntityStructureFinder(ModEntities.STRUCTURE_FINDER, worldIn); + entity.setPosition(playerIn.getPosX(), playerIn.getPosYHeight(0.5D), playerIn.getPosZ()); + entity.func_213863_b(stack); + entity.getDataManager().set(EntityStructureFinder.COLOR, this.color); + entity.moveTowards(pos.up(64)); + worldIn.addEntity(entity); + + stack.shrink(1); + } + } + return new ActionResult<>(ActionResultType.SUCCESS, stack); + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/items/ModItems.java b/src/main/java/de/ellpeck/naturesaura/items/ModItems.java index 9334c0ff..2e2044e7 100644 --- a/src/main/java/de/ellpeck/naturesaura/items/ModItems.java +++ b/src/main/java/de/ellpeck/naturesaura/items/ModItems.java @@ -58,4 +58,6 @@ public final class ModItems { public static Item SKY_CHEST; public static Item SKY_PANTS; public static Item SKY_SHOES; + public static Item FORTRESS_FINDER; + public static Item END_CITY_FINDER; } diff --git a/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java b/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java index 4fcac6c5..6092d2d3 100644 --- a/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java +++ b/src/main/java/de/ellpeck/naturesaura/packet/PacketParticles.java @@ -4,9 +4,14 @@ import de.ellpeck.naturesaura.api.NaturesAuraAPI; import de.ellpeck.naturesaura.api.aura.chunk.IAuraChunk; import de.ellpeck.naturesaura.api.aura.type.IAuraType; import de.ellpeck.naturesaura.blocks.multi.Multiblocks; +import de.ellpeck.naturesaura.entities.EntityStructureFinder; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; import net.minecraft.network.PacketBuffer; +import net.minecraft.particles.ItemParticleData; import net.minecraft.particles.ParticleTypes; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; @@ -513,6 +518,22 @@ public class PacketParticles { message.posY + 2 / 16F + world.rand.nextFloat() * 8 / 16F, message.posZ + 5 / 16F + world.rand.nextFloat() * 6 / 16F, 0, 0, 0, color, 2, 40 + world.rand.nextInt(20), 0, false, true); + }), + STRUCTURE_FINDER((message, world) -> { + EntityStructureFinder entity = (EntityStructureFinder) world.getEntityByID(message.data[0]); + WorldRenderer renderer = Minecraft.getInstance().worldRenderer; + + double d0 = message.posX + 0.5D; + double d13 = message.posY; + double d18 = message.posZ + 0.5D; + for (int j2 = 0; j2 < 8; ++j2) + renderer.addParticle(new ItemParticleData(ParticleTypes.ITEM, entity.getItem()), false, d0, d13, d18, world.rand.nextGaussian() * 0.15D, world.rand.nextDouble() * 0.2D, world.rand.nextGaussian() * 0.15D); + + int color = entity.getDataManager().get(EntityStructureFinder.COLOR); + for (double d24 = 0.0D; d24 < (Math.PI * 2D); d24 += 0.15707963267948966D) { + NaturesAuraAPI.instance().spawnMagicParticle(d0 + Math.cos(d24) * 5.0D, d13 - 0.4D, d18 + Math.sin(d24) * 5.0D, Math.cos(d24) * -2, 0.0D, Math.sin(d24) * -2, color, 2, 60, 0, false, true); + NaturesAuraAPI.instance().spawnMagicParticle(d0 + Math.cos(d24) * 5.0D, d13 - 0.4D, d18 + Math.sin(d24) * 5.0D, Math.cos(d24) * -2.5, 0.0D, Math.sin(d24) * -2.5, color, 2, 60, 0, false, true); + } }); public final BiConsumer action; diff --git a/src/main/java/de/ellpeck/naturesaura/reg/ModRegistry.java b/src/main/java/de/ellpeck/naturesaura/reg/ModRegistry.java index 61e0b149..58c9683e 100644 --- a/src/main/java/de/ellpeck/naturesaura/reg/ModRegistry.java +++ b/src/main/java/de/ellpeck/naturesaura/reg/ModRegistry.java @@ -11,10 +11,7 @@ import de.ellpeck.naturesaura.blocks.tiles.TileEntityAuraBloom.TileEntityAuraCac import de.ellpeck.naturesaura.blocks.tiles.TileEntityEnderCrate; import de.ellpeck.naturesaura.enchant.AuraMendingEnchantment; import de.ellpeck.naturesaura.enchant.ModEnchantments; -import de.ellpeck.naturesaura.entities.EntityEffectInhibitor; -import de.ellpeck.naturesaura.entities.EntityLightProjectile; -import de.ellpeck.naturesaura.entities.EntityMoverMinecart; -import de.ellpeck.naturesaura.entities.ModEntities; +import de.ellpeck.naturesaura.entities.*; import de.ellpeck.naturesaura.entities.render.RenderEffectInhibitor; import de.ellpeck.naturesaura.entities.render.RenderMoverMinecart; import de.ellpeck.naturesaura.entities.render.RenderStub; @@ -34,6 +31,8 @@ import net.minecraft.block.Blocks; import net.minecraft.block.FlowerPotBlock; import net.minecraft.block.SoundType; import net.minecraft.block.material.Material; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.entity.SpriteRenderer; import net.minecraft.enchantment.Enchantment; import net.minecraft.entity.EntityClassification; import net.minecraft.entity.EntityType; @@ -214,7 +213,9 @@ public final class ModRegistry { new ItemArmor("sky_helmet", ModArmorMaterial.SKY, EquipmentSlotType.HEAD), new ItemArmor("sky_chest", ModArmorMaterial.SKY, EquipmentSlotType.CHEST), new ItemArmor("sky_pants", ModArmorMaterial.SKY, EquipmentSlotType.LEGS), - new ItemArmor("sky_shoes", ModArmorMaterial.SKY, EquipmentSlotType.FEET) + new ItemArmor("sky_shoes", ModArmorMaterial.SKY, EquipmentSlotType.FEET), + new ItemStructureFinder("fortress_finder", "Fortress", 0xba2800), + new ItemStructureFinder("end_city_finder", "EndCity", 0xca5cd6) ); Helper.populateObjectHolders(ModItems.class, event.getRegistry()); } @@ -275,13 +276,18 @@ public final class ModRegistry { EntityType.Builder.create(EntityLightProjectile::new, EntityClassification.MISC) .size(0.5F, 0.5F).setShouldReceiveVelocityUpdates(true) .setTrackingRange(64).setUpdateInterval(3).immuneToFire().build(NaturesAura.MOD_ID + ":light_projectile") - .setRegistryName("light_projectile") + .setRegistryName("light_projectile"), + EntityType.Builder.create(EntityStructureFinder::new, EntityClassification.MISC) + .size(0.5F, 0.5F).setShouldReceiveVelocityUpdates(true) + .setTrackingRange(64).setUpdateInterval(2).immuneToFire().build(NaturesAura.MOD_ID + ":structure_finder") + .setRegistryName("structure_finder") ); Helper.populateObjectHolders(ModEntities.class, event.getRegistry()); NaturesAura.proxy.registerEntityRenderer(ModEntities.MOVER_CART, () -> RenderMoverMinecart::new); NaturesAura.proxy.registerEntityRenderer(ModEntities.EFFECT_INHIBITOR, () -> RenderEffectInhibitor::new); NaturesAura.proxy.registerEntityRenderer(ModEntities.LIGHT_PROJECTILE, () -> RenderStub::new); + NaturesAura.proxy.registerEntityRenderer(ModEntities.STRUCTURE_FINDER, () -> m -> new SpriteRenderer<>(m, Minecraft.getInstance().getItemRenderer())); } @SubscribeEvent diff --git a/src/main/resources/assets/naturesaura/lang/en_us.json b/src/main/resources/assets/naturesaura/lang/en_us.json index ba65c2b9..3df7bc15 100644 --- a/src/main/resources/assets/naturesaura/lang/en_us.json +++ b/src/main/resources/assets/naturesaura/lang/en_us.json @@ -127,6 +127,8 @@ "item.naturesaura.tainted_gold": "Tainted Gold", "item.naturesaura.loot_finder": "Staff of Riches", "item.naturesaura.light_staff": "Staff of Baldur", + "item.naturesaura.fortress_finder": "Eye of the Blaze", + "item.naturesaura.end_city_finder": "Eye of the Shulker", "container.naturesaura:tree_ritual.name": "Ritual of the Forest", "container.naturesaura:altar.name": "Natural Altar Infusion", "container.naturesaura:offering.name": "Offering to the Gods", diff --git a/src/main/resources/assets/naturesaura/textures/item/end_city_finder.png b/src/main/resources/assets/naturesaura/textures/item/end_city_finder.png new file mode 100644 index 0000000000000000000000000000000000000000..f319d25e6abc37988d570b834e80202e24f7115f GIT binary patch literal 458 zcmV;*0X6=KP)G# zg1ZQU;3Ra?MFckyTv80Jf|QC4g5R`*qUd#yToW4w@l4^|_dNH#C-6@xza2VuLmc0n z0?=u#$Iix@j@=Ldx~fWV`|L0lGy-t!h6sYL?@8a%Ob*U>xP4P2kVH6KD%XUrs<^(# z(uRYjnJlK}u{0Cc_sAr5vSas@$~6%S2-MtLVY#}AF)RRJ3=3GADbL5Rdh%NWO68i! zj@`?(gYeet8WUPVLNZC6bUwvw&K5szuw31Yvttzt_=_TcA$Ue6sbgs-#<0MImf*#I zr#*Fv>w7#r^?2+LIJw?etQW A=l}o! literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/naturesaura/textures/item/fortress_finder.png b/src/main/resources/assets/naturesaura/textures/item/fortress_finder.png new file mode 100644 index 0000000000000000000000000000000000000000..d3bf94b38929889c84959bf22b8e6fa349df6b04 GIT binary patch literal 484 zcmVAs=6#mY1(5Tp3L?VK?m@&}7PVM3kaOn@oA8_fA)z!hV z^L6X$56C2490Z}1hJq3**b=0t(Aq#N*CE^)V>S;A$ONXGxl zog@n;qfp(uW>dVp=Kui1U`k}pWtM2$Qvv`aNp_e=x@J=VK(Sg>Vvi3$N~mv};_M=e zwml^zjVy_CpDTezo#KAB0^Ob-h-74e!#vU{TcTJkV(xQX_u6RGDK5_=^4#YzG!0x| zqf@qo!#n~Y5{UmB0B&xtFzC6cRU!wq3P+<(RsQw+8IqTYzs~iwvMtGXPX*-i1tnr= z8nUG_T2vPf^GF6M81&q