From d66ea35d7668737e6755d3d3d334d52cb7c2cee2 Mon Sep 17 00:00:00 2001 From: Atsuishio <842960157@qq.com> Date: Fri, 30 May 2025 17:17:44 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=9D=B4=E8=9D=B6=E9=9B=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../b69ee8a2655365569b979911c0440daa8c470ac2 | 3 +- .../models/item/blu_43_mine.json | 6 + .../client/model/entity/Blu43Model.java | 24 ++ .../client/model/entity/C4Model.java | 2 +- .../client/model/entity/ClaymoreModel.java | 2 +- .../client/renderer/entity/Blu43Renderer.java | 43 +++ .../datagen/ModItemModelProvider.java | 1 + .../superbwarfare/entity/Blu43Entity.java | 245 ++++++++++++++++++ .../superbwarfare/init/ModEntities.java | 3 + .../init/ModEntityRenderers.java | 1 + .../superbwarfare/init/ModItems.java | 2 + .../superbwarfare/item/Blu43Mine.java | 80 ++++++ .../animations/c4.animation.json | 8 - .../animations/claymore.animation.json | 128 --------- .../assets/superbwarfare/geo/blu_43.geo.json | 182 +++++++++++++ .../superbwarfare/geo/claymore.geo.json | 117 ++++++++- .../assets/superbwarfare/lang/en_us.json | 2 + .../assets/superbwarfare/lang/zh_cn.json | 2 + .../superbwarfare/textures/entity/blu_43.png | Bin 0 -> 639 bytes .../textures/item/blu_43_mine.png | Bin 0 -> 406 bytes 20 files changed, 702 insertions(+), 149 deletions(-) create mode 100644 src/generated/resources/assets/superbwarfare/models/item/blu_43_mine.json create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/model/entity/Blu43Model.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/Blu43Renderer.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/entity/Blu43Entity.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/item/Blu43Mine.java delete mode 100644 src/main/resources/assets/superbwarfare/animations/c4.animation.json delete mode 100644 src/main/resources/assets/superbwarfare/animations/claymore.animation.json create mode 100644 src/main/resources/assets/superbwarfare/geo/blu_43.geo.json create mode 100644 src/main/resources/assets/superbwarfare/textures/entity/blu_43.png create mode 100644 src/main/resources/assets/superbwarfare/textures/item/blu_43_mine.png diff --git a/src/generated/resources/.cache/b69ee8a2655365569b979911c0440daa8c470ac2 b/src/generated/resources/.cache/b69ee8a2655365569b979911c0440daa8c470ac2 index db0dafcff..76ed80003 100644 --- a/src/generated/resources/.cache/b69ee8a2655365569b979911c0440daa8c470ac2 +++ b/src/generated/resources/.cache/b69ee8a2655365569b979911c0440daa8c470ac2 @@ -1,4 +1,4 @@ -// 1.21.1 2025-05-29T14:19:09.6790507 Item Models: superbwarfare +// 1.21.1 2025-05-30T19:50:17.18005 Item Models: superbwarfare 06b82c2eb3d0312eaa6085814e1497e61139fc9c assets/superbwarfare/models/item/aa_12.json fb3a995587b2c253571c3160ff02c2ad8c73ecf8 assets/superbwarfare/models/item/aa_12_base.json 13ca8d5676888ff51f3308d88e4bf67691fa34f8 assets/superbwarfare/models/item/aa_12_blueprint.json @@ -23,6 +23,7 @@ a207f0f01b87315d1b85fc3ea69bf52b2bd5c71a assets/superbwarfare/models/item/aureli 984c08ca6f6893a15721a85e30118f9e32c65c7f assets/superbwarfare/models/item/barbed_wire.json e8f16946c6f9429989d05e9ec250a72ffc64f9e1 assets/superbwarfare/models/item/beam_test.json bda38dd5cb3ca4c3e289a012c0529609ac02ded2 assets/superbwarfare/models/item/beast.json +e73a45b6a96cb3c8901fea9365261501d87f85a7 assets/superbwarfare/models/item/blu_43_mine.json 10964037bbbf9325114b0d05c63fb3a8513e05ca assets/superbwarfare/models/item/bocek.json 55698528f99669ec9f28ae9915c26e1a686f642a assets/superbwarfare/models/item/bocek_base.json 13ca8d5676888ff51f3308d88e4bf67691fa34f8 assets/superbwarfare/models/item/bocek_blueprint.json diff --git a/src/generated/resources/assets/superbwarfare/models/item/blu_43_mine.json b/src/generated/resources/assets/superbwarfare/models/item/blu_43_mine.json new file mode 100644 index 000000000..79e6c9fca --- /dev/null +++ b/src/generated/resources/assets/superbwarfare/models/item/blu_43_mine.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "superbwarfare:item/blu_43_mine" + } +} \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/client/model/entity/Blu43Model.java b/src/main/java/com/atsuishio/superbwarfare/client/model/entity/Blu43Model.java new file mode 100644 index 000000000..433654532 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/model/entity/Blu43Model.java @@ -0,0 +1,24 @@ +package com.atsuishio.superbwarfare.client.model.entity; + +import com.atsuishio.superbwarfare.Mod; +import com.atsuishio.superbwarfare.entity.Blu43Entity; +import net.minecraft.resources.ResourceLocation; +import software.bernie.geckolib.model.GeoModel; + +public class Blu43Model extends GeoModel { + + @Override + public ResourceLocation getAnimationResource(Blu43Entity entity) { + return null; + } + + @Override + public ResourceLocation getModelResource(Blu43Entity entity) { + return Mod.loc("geo/blu_43.geo.json"); + } + + @Override + public ResourceLocation getTextureResource(Blu43Entity entity) { + return Mod.loc("textures/entity/blu_43.png"); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/model/entity/C4Model.java b/src/main/java/com/atsuishio/superbwarfare/client/model/entity/C4Model.java index 17b90cfd3..f3930f28e 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/model/entity/C4Model.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/model/entity/C4Model.java @@ -11,7 +11,7 @@ public class C4Model extends GeoModel { @Override public ResourceLocation getAnimationResource(C4Entity entity) { - return Mod.loc("animations/c4.animation.json"); + return null; } @Override diff --git a/src/main/java/com/atsuishio/superbwarfare/client/model/entity/ClaymoreModel.java b/src/main/java/com/atsuishio/superbwarfare/client/model/entity/ClaymoreModel.java index b9656566d..011ea62c9 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/model/entity/ClaymoreModel.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/model/entity/ClaymoreModel.java @@ -11,7 +11,7 @@ public class ClaymoreModel extends GeoModel { @Override public ResourceLocation getAnimationResource(ClaymoreEntity entity) { - return Mod.loc("animations/claymore.animation.json"); + return null; } @Override diff --git a/src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/Blu43Renderer.java b/src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/Blu43Renderer.java new file mode 100644 index 000000000..28612cfc1 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/renderer/entity/Blu43Renderer.java @@ -0,0 +1,43 @@ +package com.atsuishio.superbwarfare.client.renderer.entity; + +import com.atsuishio.superbwarfare.client.model.entity.Blu43Model; +import com.atsuishio.superbwarfare.entity.Blu43Entity; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Axis; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import org.jetbrains.annotations.NotNull; +import software.bernie.geckolib.cache.object.BakedGeoModel; +import software.bernie.geckolib.renderer.GeoEntityRenderer; + +public class Blu43Renderer extends GeoEntityRenderer { + + public Blu43Renderer(EntityRendererProvider.Context renderManager) { + super(renderManager, new Blu43Model()); + } + + @Override + public RenderType getRenderType(Blu43Entity animatable, ResourceLocation texture, MultiBufferSource bufferSource, float partialTick) { + return RenderType.entityTranslucent(getTextureLocation(animatable)); + } + + @Override + public void preRender(PoseStack poseStack, Blu43Entity entity, BakedGeoModel model, MultiBufferSource bufferSource, VertexConsumer buffer, boolean isReRender, float partialTick, int packedLight, int packedOverlay, int color) { + float scale = 1f; + this.scaleHeight = scale; + this.scaleWidth = scale; + super.preRender(poseStack, entity, model, bufferSource, buffer, isReRender, partialTick, packedLight, packedOverlay, color); + } + + @Override + public void render(Blu43Entity entityIn, float entityYaw, float partialTicks, PoseStack poseStack, @NotNull MultiBufferSource bufferIn, int packedLightIn) { + poseStack.pushPose(); + poseStack.mulPose(Axis.YP.rotationDegrees(-Mth.lerp(partialTicks, entityIn.yRotO, entityIn.getYRot()))); + super.render(entityIn, entityYaw, partialTicks, poseStack, bufferIn, packedLightIn); + poseStack.popPose(); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/datagen/ModItemModelProvider.java b/src/main/java/com/atsuishio/superbwarfare/datagen/ModItemModelProvider.java index 21b8ece1f..92bede493 100644 --- a/src/main/java/com/atsuishio/superbwarfare/datagen/ModItemModelProvider.java +++ b/src/main/java/com/atsuishio/superbwarfare/datagen/ModItemModelProvider.java @@ -92,6 +92,7 @@ public class ModItemModelProvider extends ItemModelProvider { simpleItem(ModItems.MISSILE_ENGINE); simpleItem(ModItems.FUSEE); simpleItem(ModItems.PRIMER); + simpleItem(ModItems.BLU_43_MINE); simpleItem(ModItems.AP_HEAD); simpleItem(ModItems.HE_HEAD); simpleItem(ModItems.CANNON_CORE); diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/Blu43Entity.java b/src/main/java/com/atsuishio/superbwarfare/entity/Blu43Entity.java new file mode 100644 index 000000000..66140734e --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/entity/Blu43Entity.java @@ -0,0 +1,245 @@ +package com.atsuishio.superbwarfare.entity; + +import com.atsuishio.superbwarfare.init.ModDamageTypes; +import com.atsuishio.superbwarfare.init.ModEntities; +import com.atsuishio.superbwarfare.init.ModItems; +import com.atsuishio.superbwarfare.tools.CustomExplosion; +import com.atsuishio.superbwarfare.tools.ParticleTool; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.network.syncher.EntityDataSerializers; +import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.players.OldUsersConverter; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.damagesource.DamageTypes; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.*; +import net.minecraft.world.entity.decoration.HangingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.projectile.ThrownPotion; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Explosion; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.entity.EntityTypeTest; +import net.neoforged.neoforge.event.EventHooks; +import net.neoforged.neoforge.items.ItemHandlerHelper; +import org.jetbrains.annotations.NotNull; +import software.bernie.geckolib.animatable.GeoEntity; +import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache; +import software.bernie.geckolib.animation.AnimatableManager; +import software.bernie.geckolib.util.GeckoLibUtil; + +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.Optional; +import java.util.UUID; + +public class Blu43Entity extends Entity implements GeoEntity, OwnableEntity { + + protected static final EntityDataAccessor> OWNER_UUID = SynchedEntityData.defineId(Blu43Entity.class, EntityDataSerializers.OPTIONAL_UUID); + protected static final EntityDataAccessor LAST_ATTACKER_UUID = SynchedEntityData.defineId(Blu43Entity.class, EntityDataSerializers.STRING); + public static final EntityDataAccessor HEALTH = SynchedEntityData.defineId(Blu43Entity.class, EntityDataSerializers.FLOAT); + private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); + + public Blu43Entity(EntityType type, Level world) { + super(type, world); + } + + public Blu43Entity(LivingEntity owner, Level level) { + super(ModEntities.BLU_43.get(), level); + this.setOwnerUUID(owner.getUUID()); + } + + @Override + protected void defineSynchedData(SynchedEntityData.@NotNull Builder builder) { + builder.define(OWNER_UUID, Optional.empty()) + .define(LAST_ATTACKER_UUID, "undefined") + .define(HEALTH, 5f); + } + + @Override + public boolean isPickable() { + return !this.isRemoved(); + } + + @Override + public boolean hurt(DamageSource source, float amount) { + if (source.getDirectEntity() instanceof ThrownPotion || source.getDirectEntity() instanceof AreaEffectCloud) + return false; + if (source.is(DamageTypes.FALL)) + return false; + if (source.is(DamageTypes.CACTUS)) + return false; + if (source.is(DamageTypes.DROWN)) + return false; + if (source.is(DamageTypes.DRAGON_BREATH)) + return false; + if (source.is(DamageTypes.WITHER)) + return false; + if (source.is(DamageTypes.WITHER_SKULL)) + return false; + if (source.is(ModDamageTypes.CUSTOM_EXPLOSION) || source.is(ModDamageTypes.MINE) || source.is(ModDamageTypes.PROJECTILE_BOOM) || source.is(DamageTypes.EXPLOSION)) { + amount *= 0.02f; + } + if (source.getEntity() != null) { + this.entityData.set(LAST_ATTACKER_UUID, source.getEntity().getStringUUID()); + } + this.entityData.set(HEALTH, this.entityData.get(HEALTH) - amount); + return super.hurt(source, amount); + } + + public void setOwnerUUID(@Nullable UUID pUuid) { + this.entityData.set(OWNER_UUID, Optional.ofNullable(pUuid)); + } + + @Nullable + public UUID getOwnerUUID() { + return this.entityData.get(OWNER_UUID).orElse(null); + } + + public boolean isOwnedBy(LivingEntity pEntity) { + return pEntity == this.getOwner(); + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + compound.putFloat("Health", this.entityData.get(HEALTH)); + compound.putString("LastAttacker", this.entityData.get(LAST_ATTACKER_UUID)); + if (this.getOwnerUUID() != null) { + compound.putUUID("Owner", this.getOwnerUUID()); + } + } + + @Override + public void readAdditionalSaveData(CompoundTag compound) { + if (compound.contains("Health")) { + this.entityData.set(HEALTH, compound.getFloat("Health")); + } + + if (compound.contains("LastAttacker")) { + this.entityData.set(LAST_ATTACKER_UUID, compound.getString("LastAttacker")); + } + + UUID uuid; + if (compound.hasUUID("Owner")) { + uuid = compound.getUUID("Owner"); + } else { + String s = compound.getString("Owner"); + + assert this.getServer() != null; + uuid = OldUsersConverter.convertMobOwnerIfNecessary(this.getServer(), s); + } + + if (uuid != null) { + try { + this.setOwnerUUID(uuid); + } catch (Throwable ignored) { + } + } + } + + @Override + @ParametersAreNonnullByDefault + public @NotNull InteractionResult interact(Player player, InteractionHand hand) { + if (this.isOwnedBy(player) && player.isShiftKeyDown()) { + if (!this.level().isClientSide()) { + this.discard(); + } + + if (!player.getAbilities().instabuild) { + ItemHandlerHelper.giveItemToPlayer(player, new ItemStack(ModItems.BLU_43_MINE.get())); + } + } + + return InteractionResult.sidedSuccess(this.level().isClientSide()); + } + + @Override + public void tick() { + super.tick(); + + if (this.tickCount >= 20) { + touchEntity(); + } + + this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.03, 0.0)); + + if (!this.level().noCollision(this.getBoundingBox())) { + this.moveTowardsClosestSpace(this.getX(), (this.getBoundingBox().minY + this.getBoundingBox().maxY) / 2.0, this.getZ()); + } + + this.move(MoverType.SELF, this.getDeltaMovement()); + float f = 0.98F; + if (this.onGround()) { + BlockPos pos = this.getBlockPosBelowThatAffectsMyMovement(); + f = this.level().getBlockState(pos).getFriction(this.level(), pos, this) * 0.98F; + } + + this.setDeltaMovement(this.getDeltaMovement().multiply(f, 0.98, f)); + if (this.onGround()) { + this.setDeltaMovement(this.getDeltaMovement().multiply(1.0, -0.9, 1.0)); + } + + if (this.entityData.get(HEALTH) <= 0) { + triggerExplode(); + } + + this.refreshDimensions(); + } + + public void touchEntity() { + if (level() instanceof ServerLevel) { + var frontBox = getBoundingBox().inflate(0.2); + boolean trigger = false; + + var entities = level().getEntities(EntityTypeTest.forClass(Entity.class), frontBox, entity -> entity != this && !(entity instanceof HangingEntity) && entity.getBoundingBox().getSize() > 0.4).stream().toList(); + + for (var entity : entities) { + if (entity != null) { + trigger = true; + if (!entity.level().isClientSide() && entity instanceof LivingEntity living) { + living.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 200, 3, false, false), this.getOwner()); + living.addEffect(new MobEffectInstance(MobEffects.WEAKNESS, 200, 3, false, false), this.getOwner()); + living.addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 30, 0, false, false), this.getOwner()); + } + break; + } + } + + if (trigger) { + triggerExplode(); + } + + } + } + + private void triggerExplode() { + CustomExplosion explosion = new CustomExplosion(this.level(), this, + ModDamageTypes.causeCustomExplosionDamage(this.level().registryAccess(), this, this.getOwner()), 15f, + this.getX(), this.getEyeY(), this.getZ(), 2f, Explosion.BlockInteraction.KEEP, true); + explosion.explode(); + EventHooks.onExplosionStart(this.level(), explosion); + explosion.finalizeExplosion(false); + ParticleTool.spawnMiniExplosionParticles(this.level(), this.position()); + this.discard(); + } + + @Override + public boolean isPushable() { + return true; + } + + @Override + public void registerControllers(AnimatableManager.ControllerRegistrar data) { + } + + @Override + public AnimatableInstanceCache getAnimatableInstanceCache() { + return this.cache; + } +} \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModEntities.java b/src/main/java/com/atsuishio/superbwarfare/init/ModEntities.java index 6da43c46c..95ebdf735 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModEntities.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModEntities.java @@ -42,6 +42,9 @@ public class ModEntities { EntityType.Builder.of(SmokeDecoyEntity::new, MobCategory.MISC).setTrackingRange(64).setUpdateInterval(1).noSave().sized(3f, 3f)); public static final DeferredHolder, EntityType> CLAYMORE = register("claymore", EntityType.Builder.of(ClaymoreEntity::new, MobCategory.MISC).setTrackingRange(64).setUpdateInterval(1).sized(0.5f, 0.5f)); + + public static final DeferredHolder, EntityType> BLU_43 = register("blu_43", + EntityType.Builder.of(Blu43Entity::new, MobCategory.MISC).setTrackingRange(32).setUpdateInterval(1).sized(0.12f, 0.05f)); public static final DeferredHolder, EntityType> C_4 = register("c4", EntityType.Builder.of(C4Entity::new, MobCategory.MISC).setTrackingRange(64).setUpdateInterval(1).sized(0.5f, 0.5f)); public static final DeferredHolder, EntityType> WATER_MASK = register("water_mask", diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModEntityRenderers.java b/src/main/java/com/atsuishio/superbwarfare/init/ModEntityRenderers.java index 55b603f90..1e77bd625 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModEntityRenderers.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModEntityRenderers.java @@ -53,5 +53,6 @@ public class ModEntityRenderers { event.registerEntityRenderer(ModEntities.A_10A.get(), A10Renderer::new); event.registerEntityRenderer(ModEntities.MK_82.get(), Mk82Renderer::new); event.registerEntityRenderer(ModEntities.AGM_65.get(), Agm65Renderer::new); + event.registerEntityRenderer(ModEntities.BLU_43.get(), Blu43Renderer::new); } } diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModItems.java b/src/main/java/com/atsuishio/superbwarfare/init/ModItems.java index 26f9e3f9a..01b9f8b7c 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModItems.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModItems.java @@ -116,6 +116,7 @@ public class ModItems { public static final DeferredHolder RGO_GRENADE = AMMO.register("rgo_grenade", RgoGrenade::new); public static final DeferredHolder CLAYMORE_MINE = AMMO.register("claymore_mine", ClaymoreMine::new); public static final DeferredHolder C4_BOMB = AMMO.register("c4_bomb", C4Bomb::new); + public static final DeferredHolder BLU_43_MINE = AMMO.register("blu_43_mine", Blu43Mine::new); public static final DeferredHolder SMALL_SHELL = AMMO.register("small_shell", SmallShellItem::new); public static final DeferredHolder ROCKET_70 = AMMO.register("rocket_70", Rocket70::new); public static final DeferredHolder WIRE_GUIDE_MISSILE = AMMO.register("wire_guide_missile", WireGuideMissile::new); @@ -332,6 +333,7 @@ public class ModItems { DispenserBlock.registerBehavior(SWARM_DRONE.get(), new SwarmDrone.SwarmDroneDispenseBehavior()); DispenserBlock.registerBehavior(C4_BOMB.get(), new C4Bomb.C4DispenseItemBehavior()); DispenserBlock.registerBehavior(CLAYMORE_MINE.get(), new ClaymoreMine.ClaymoreDispenseBehavior()); + DispenserBlock.registerBehavior(BLU_43_MINE.get(), new Blu43Mine.Blu43MineDispenseBehavior()); DispenserBlock.registerBehavior(ROCKET.get(), new Rocket.RocketDispenseBehavior()); DispenserBlock.registerBehavior(ROCKET_70.get(), new Rocket70.Rocket70DispenseBehavior()); DispenserBlock.registerBehavior(MEDIUM_AERIAL_BOMB.get(), new MediumAerialBomb.MediumAerialBombDispenseBehavior()); diff --git a/src/main/java/com/atsuishio/superbwarfare/item/Blu43Mine.java b/src/main/java/com/atsuishio/superbwarfare/item/Blu43Mine.java new file mode 100644 index 000000000..891c7c890 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/item/Blu43Mine.java @@ -0,0 +1,80 @@ +package com.atsuishio.superbwarfare.item; + +import com.atsuishio.superbwarfare.entity.Blu43Entity; +import com.atsuishio.superbwarfare.init.ModEntities; +import net.minecraft.core.Direction; +import net.minecraft.core.Position; +import net.minecraft.core.dispenser.BlockSource; +import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.DispenserBlock; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; +import org.joml.Math; + +import javax.annotation.ParametersAreNonnullByDefault; + +public class Blu43Mine extends Item { + public Blu43Mine() { + super(new Properties()); + } + + @Override + public @NotNull InteractionResultHolder use(Level level, Player player, @NotNull InteractionHand hand) { + ItemStack stack = player.getItemInHand(hand); + + if (!level.isClientSide) { + float randomRot = (float) Mth.clamp((2 * Math.random() - 1) * 180, -180, 180); + Blu43Entity entity = new Blu43Entity(player, level); + entity.moveTo(player.getX(), player.getY() + 1.1, player.getZ(), randomRot, 0); + entity.setYBodyRot(randomRot); + entity.setYHeadRot(randomRot); + entity.setDeltaMovement(0.5 * player.getLookAngle().x, 0.5 * player.getLookAngle().y, 0.5 * player.getLookAngle().z); + + level.addFreshEntity(entity); + } + + player.getCooldowns().addCooldown(this, 4); + + if (!player.getAbilities().instabuild) { + stack.shrink(1); + } + + return InteractionResultHolder.consume(stack); + } + + public static class Blu43MineDispenseBehavior extends DefaultDispenseItemBehavior { + @Override + @ParametersAreNonnullByDefault + protected @NotNull ItemStack execute(BlockSource blockSource, ItemStack stack) { + Level level = blockSource.level(); + Position position = DispenserBlock.getDispensePosition(blockSource); + Direction direction = blockSource.state().getValue(DispenserBlock.FACING); + + var blu43 = new Blu43Entity(ModEntities.BLU_43.get(), level); + blu43.setPos(position.x(), position.y(), position.z()); + float randomRot = (float) Mth.clamp((2 * Math.random() - 1) * 180, -180, 180); + + var pX = direction.getStepX(); + var pY = direction.getStepY() + 0.1F; + var pZ = direction.getStepZ(); + Vec3 vec3 = (new Vec3(pX, pY, pZ)).normalize().scale(0.05); + blu43.setDeltaMovement(vec3); + double d0 = vec3.horizontalDistance(); + blu43.setYRot(randomRot); + blu43.setXRot((float) (Mth.atan2(vec3.y, d0) * (double) (180F / (float) Math.PI))); + blu43.yRotO = blu43.getYRot(); + blu43.xRotO = blu43.getXRot(); + + level.addFreshEntity(blu43); + stack.shrink(1); + return stack; + } + } +} diff --git a/src/main/resources/assets/superbwarfare/animations/c4.animation.json b/src/main/resources/assets/superbwarfare/animations/c4.animation.json deleted file mode 100644 index 924c12f6d..000000000 --- a/src/main/resources/assets/superbwarfare/animations/c4.animation.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "format_version": "1.8.0", - "animations": { - "animation.c4.idle": { - "animation_length": 0.5 - } - } -} \ No newline at end of file diff --git a/src/main/resources/assets/superbwarfare/animations/claymore.animation.json b/src/main/resources/assets/superbwarfare/animations/claymore.animation.json deleted file mode 100644 index c84c08d4d..000000000 --- a/src/main/resources/assets/superbwarfare/animations/claymore.animation.json +++ /dev/null @@ -1,128 +0,0 @@ -{ - "format_version": "1.8.0", - "animations": { - "animation.claymore.idle": { - "animation_length": 0.5, - "bones": { - "claymore": { - "rotation": { - "0.0": { - "vector": [0, 0, 0] - }, - "0.5": { - "vector": [0, 0, 0] - } - } - } - } - }, - "animation.claymore.fire": { - "animation_length": 0.6, - "bones": { - "0": { - "rotation": { - "0.0": { - "vector": [0, 0, 0] - }, - "0.2": { - "vector": [-7.5, 0, 0], - "easing": "easeInOutQuad" - }, - "0.4": { - "vector": [22.5, 0, 0], - "easing": "easeInQuint" - }, - "0.6": { - "vector": [0, 0, 0], - "easing": "easeOutQuart" - } - }, - "position": { - "0.0": { - "vector": [0, 0, 0] - }, - "0.2": { - "vector": [0, 1.9, 0], - "easing": "easeInOutQuad" - }, - "0.4": { - "vector": [0, -18.1, 0], - "easing": "easeInQuint" - }, - "0.6": { - "vector": [0, 0, 0], - "easing": "easeOutQuart" - } - } - }, - "Righthand": { - "rotation": { - "0.0": { - "vector": [-74.87647, 7.24305, -178.04845] - }, - "0.6": { - "vector": [-74.87647, 7.24305, -178.04845] - } - }, - "position": { - "0.0": { - "vector": [-1, -10, 6] - }, - "0.6": { - "vector": [-1, -10, 6] - } - } - }, - "Lefthand": { - "rotation": { - "0.0": { - "vector": [-74.87647, -7.24305, 178.04845] - }, - "0.6": { - "vector": [-74.87647, -7.24305, 178.04845] - } - }, - "position": { - "0.0": { - "vector": [1, -9.9813, 6] - }, - "0.6": { - "vector": [1, -9.9813, 6] - } - } - }, - "claymore": { - "rotation": { - "0.0": { - "vector": [0, 0, 0] - }, - "0.2": { - "vector": [0, 0, 0] - }, - "0.4": { - "vector": [20, 0, 0] - }, - "0.6": { - "vector": [0, 0, 0] - } - }, - "position": { - "0.0": { - "vector": [0, 0, 0] - }, - "0.2": { - "vector": [0, 0, 0] - }, - "0.4": { - "vector": [0, -0.25, -1.25] - }, - "0.6": { - "vector": [0, 0, 0] - } - } - } - } - } - }, - "geckolib_format_version": 2 -} \ No newline at end of file diff --git a/src/main/resources/assets/superbwarfare/geo/blu_43.geo.json b/src/main/resources/assets/superbwarfare/geo/blu_43.geo.json new file mode 100644 index 000000000..34d35be4d --- /dev/null +++ b/src/main/resources/assets/superbwarfare/geo/blu_43.geo.json @@ -0,0 +1,182 @@ +{ + "format_version": "1.12.0", + "minecraft:geometry": [ + { + "description": { + "identifier": "geometry.unknown", + "texture_width": 16, + "texture_height": 16, + "visible_bounds_width": 2, + "visible_bounds_height": 2.5, + "visible_bounds_offset": [0, 0.75, 0] + }, + "bones": [ + { + "name": "root", + "pivot": [0, 0, 0], + "cubes": [ + { + "origin": [0.0625, 0, -0.325], + "size": [0.125, 0.25, 0.9], + "uv": { + "north": {"uv": [7, 1], "uv_size": [0.5, 0.5]}, + "south": {"uv": [2, 7], "uv_size": [0.5, 0.5]}, + "west": {"uv": [3, 4], "uv_size": [1.5, 0.5]}, + "down": {"uv": [0, 6.5], "uv_size": [0.5, -1.5]} + } + }, + { + "origin": [0.1875, 0, -0.3], + "size": [0.7, 0.05, 0.825], + "uv": { + "north": {"uv": [3, 5], "uv_size": [1.5, 0.5]}, + "south": {"uv": [5, 4], "uv_size": [1.5, 0.5]}, + "up": {"uv": [0, 0], "uv_size": [1.5, 1.5]}, + "down": {"uv": [0, 3.5], "uv_size": [1.5, -1.5]} + } + }, + { + "origin": [0.20769, 0.27517, -0.3], + "size": [0.125, 0.05, 0.825], + "pivot": [-0.04231, 0.26517, 0.1125], + "rotation": [0, 0, 45], + "uv": { + "north": {"uv": [5, 8], "uv_size": [0.5, 0.5]}, + "south": {"uv": [8, 5], "uv_size": [0.5, 0.5]}, + "up": {"uv": [6, 1], "uv_size": [0.5, 1.5]} + } + }, + { + "origin": [0.71088, 0, -0.52968], + "size": [0.75, 0.05, 0.655], + "pivot": [0.46088, 0, -0.15468], + "rotation": [0, -37.5, 0], + "uv": { + "north": {"uv": [5, 5], "uv_size": [1.5, 0.5]}, + "south": {"uv": [6, 0], "uv_size": [1.5, 0.5]}, + "west": {"uv": [1, 7], "uv_size": [1, 0.5]}, + "up": {"uv": [0, 4], "uv_size": [1.5, 1]}, + "down": {"uv": [4, 1], "uv_size": [1.5, -1]} + } + }, + { + "origin": [-0.00758, 0.16919, -0.325], + "size": [0.125, 0.1775, 0.9], + "pivot": [0.05492, 0.29419, 0.1], + "rotation": [0, 0, -45], + "uv": { + "north": {"uv": [4, 8], "uv_size": [0.5, 0.5]}, + "south": {"uv": [8, 4], "uv_size": [0.5, 0.5]}, + "west": {"uv": [4, 3], "uv_size": [1.5, 0.5]} + } + }, + { + "origin": [-0.1875, 0, -0.325], + "size": [0.25, 0.375, 0.9], + "uv": { + "north": {"uv": [6, 6], "uv_size": [0.5, 1]}, + "east": {"uv": [6, 8], "uv_size": [1.7, 0.75]}, + "south": {"uv": [0, 7], "uv_size": [0.5, 1]}, + "up": {"uv": [1, 5], "uv_size": [0.5, 1.5]}, + "down": {"uv": [5, 2.5], "uv_size": [0.5, -1.5]} + } + }, + { + "origin": [-0.15089, 0, 0.575], + "size": [0.25, 0.25, 0.075], + "pivot": [-0.08839, 0.1875, 0.1], + "rotation": [0, 0, -45], + "uv": { + "east": {"uv": [7, 4], "uv_size": [0.5, 0.5]}, + "west": {"uv": [5, 7], "uv_size": [0.5, 0.5]}, + "up": {"uv": [7, 5], "uv_size": [0.5, 0.5]}, + "down": {"uv": [6, 7.5], "uv_size": [0.5, -0.5]} + } + }, + { + "origin": [-0.15089, 0, 0.65], + "size": [0.25, 0.25, 0.175], + "pivot": [-0.08839, 0.1875, 0.1], + "rotation": [0, 0, -45], + "uv": { + "east": {"uv": [8, 1], "uv_size": [0.5, 0.5]}, + "south": {"uv": [2, 8], "uv_size": [0.5, 0.5]}, + "west": {"uv": [8, 2], "uv_size": [0.5, 0.5]}, + "up": {"uv": [3, 8], "uv_size": [0.5, 0.5]}, + "down": {"uv": [8, 3.5], "uv_size": [0.5, -0.5]} + } + }, + { + "origin": [-0.11125, 0.07625, -0.4], + "size": [0.2225, 0.2225, 0.075], + "pivot": [0, 0.1875, -0.325], + "rotation": [0, 0, -45], + "uv": { + "north": {"uv": [7, 6], "uv_size": [0.5, 0.5]}, + "east": {"uv": [7, 7], "uv_size": [0.5, 0.5]}, + "west": {"uv": [0, 8], "uv_size": [0.5, 0.5]}, + "up": {"uv": [8, 0], "uv_size": [0.5, 0.5]}, + "down": {"uv": [1, 8.5], "uv_size": [0.5, -0.5]} + } + }, + { + "origin": [-0.7968, 0, 0.32549], + "size": [0.7, 0.375, 0.45], + "pivot": [-0.9218, 0, 0.37549], + "rotation": [0, 22.5, 0], + "uv": { + "south": {"uv": [2, 1], "uv_size": [1.5, 1]}, + "up": {"uv": [2, 2], "uv_size": [1.5, 1]}, + "down": {"uv": [2, 4], "uv_size": [1.5, -1]} + } + }, + { + "origin": [-0.81237, 0, 0.16194], + "size": [0.375, 0.375, 0.25], + "pivot": [-1.26237, 0, 0.01194], + "rotation": [0, -22.5, 0], + "uv": { + "south": {"uv": [2, 6], "uv_size": [0.5, 1]}, + "up": {"uv": [7, 2], "uv_size": [0.5, 0.5]}, + "down": {"uv": [3, 7.5], "uv_size": [0.5, -0.5]} + } + }, + { + "origin": [-0.0172, 0, -0.1213], + "size": [0.2425, 0.375, 0.25], + "pivot": [-0.5997, 0, -0.2713], + "rotation": [0, -90, 0], + "uv": { + "south": {"uv": [3, 6], "uv_size": [0.5, 1]}, + "up": {"uv": [7, 3], "uv_size": [0.5, 0.5]}, + "down": {"uv": [4, 7.5], "uv_size": [0.5, -0.5]} + } + }, + { + "origin": [-0.58506, 0, -0.78984], + "size": [0.325, 0.375, 0.9], + "pivot": [-1.03506, 0, -0.28984], + "rotation": [0, -45, 0], + "uv": { + "east": {"uv": [2, 0], "uv_size": [2, 1]}, + "up": {"uv": [4, 1], "uv_size": [0.5, 2]}, + "down": {"uv": [2, 6], "uv_size": [0.5, -2]} + } + }, + { + "origin": [0.4875, 0, -0.55], + "size": [0.4, 0.375, 0.175], + "pivot": [0.0375, 0, -0.775], + "rotation": [0, -90, 0], + "uv": { + "east": {"uv": [6, 3], "uv_size": [0.5, 1]}, + "up": {"uv": [4, 6], "uv_size": [1, 0.5]}, + "down": {"uv": [5, 6.5], "uv_size": [1, -0.5]} + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/superbwarfare/geo/claymore.geo.json b/src/main/resources/assets/superbwarfare/geo/claymore.geo.json index ddc09b324..600dcb704 100644 --- a/src/main/resources/assets/superbwarfare/geo/claymore.geo.json +++ b/src/main/resources/assets/superbwarfare/geo/claymore.geo.json @@ -21,16 +21,113 @@ "pivot": [0, 0, 0], "rotation": [0, 180, 0], "cubes": [ - {"origin": [-3.5, 2.75, -0.5], "size": [7, 5, 2], "uv": [0, 0]}, - {"origin": [-2, 7, 0], "size": [4, 1, 1], "uv": [0, 14]}, - {"origin": [2, 7.75, 0], "size": [1, 1, 1], "uv": [14, 7]}, - {"origin": [-3, 7.75, 0], "size": [1, 1, 1], "uv": [6, 7]}, - {"origin": [3, -0.65, -0.2], "size": [0, 4, 1], "pivot": [3, 2.6, 0.3], "rotation": [-45, 0, 0], "uv": [0, 15]}, - {"origin": [3, -0.9, 0.05], "size": [0, 4, 1], "pivot": [3, 2.6, 0.3], "rotation": [45, 0, 0], "uv": [14, 13]}, - {"origin": [-3, -0.9, 0.05], "size": [0, 4, 1], "pivot": [-3, 2.6, 0.3], "rotation": [45, 0, 0], "uv": [10, 13]}, - {"origin": [-3, -0.65, -0.2], "size": [0, 4, 1], "pivot": [-3, 2.6, 0.3], "rotation": [-45, 0, 0], "uv": [12, 13]}, - {"origin": [-5.11836, 2.75, -1.41865], "size": [2, 5, 2], "pivot": [-5.61836, 1.75, 0.08135], "rotation": [0, -22.5, 0], "uv": [0, 7]}, - {"origin": [2.81179, 2.75, -0.95984], "size": [2, 5, 2], "pivot": [4.31179, 1.75, -0.45984], "rotation": [0, 22.5, 0], "uv": [8, 7]} + { + "origin": [-3.5, 2.75, -0.5], + "size": [7, 5, 2], + "uv": { + "north": {"uv": [2, 2], "uv_size": [7, 5]}, + "south": {"uv": [11, 2], "uv_size": [7, 5]}, + "up": {"uv": [2, 0], "uv_size": [7, 2]}, + "down": {"uv": [9, 2], "uv_size": [7, -2]} + } + }, + { + "origin": [-2, 7.75, 0], + "size": [4, 0.25, 1], + "uv": { + "north": {"uv": [1, 15], "uv_size": [4, 1]}, + "south": {"uv": [6, 15], "uv_size": [4, 1]}, + "up": {"uv": [1, 14], "uv_size": [4, 1]} + } + }, + { + "origin": [2, 7.75, 0], + "size": [1, 1, 1], + "uv": { + "north": {"uv": [15, 8], "uv_size": [1, 1]}, + "east": {"uv": [14, 8], "uv_size": [1, 1]}, + "south": {"uv": [17, 8], "uv_size": [1, 1]}, + "west": {"uv": [16, 8], "uv_size": [1, 1]}, + "up": {"uv": [15, 7], "uv_size": [1, 1]} + } + }, + { + "origin": [-3, 7.75, 0], + "size": [1, 1, 1], + "uv": { + "north": {"uv": [7, 8], "uv_size": [1, 1]}, + "east": {"uv": [6, 8], "uv_size": [1, 1]}, + "south": {"uv": [9, 8], "uv_size": [1, 1]}, + "west": {"uv": [8, 8], "uv_size": [1, 1]}, + "up": {"uv": [7, 7], "uv_size": [1, 1]} + } + }, + { + "origin": [3, -0.65, -0.2], + "size": [0, 4, 1], + "pivot": [3, 2.6, 0.3], + "rotation": [-45, 0, 0], + "uv": { + "east": {"uv": [0, 16], "uv_size": [1, 4]}, + "west": {"uv": [1, 16], "uv_size": [1, 4]} + } + }, + { + "origin": [3, -0.9, 0.05], + "size": [0, 4, 1], + "pivot": [3, 2.6, 0.3], + "rotation": [45, 0, 0], + "uv": { + "east": {"uv": [14, 14], "uv_size": [1, 4]}, + "west": {"uv": [15, 14], "uv_size": [1, 4]} + } + }, + { + "origin": [-3, -0.65, -0.2], + "size": [0, 4, 1], + "pivot": [-3, 2.6, 0.3], + "rotation": [-45, 0, 0], + "uv": { + "east": {"uv": [2, 16], "uv_size": [-1, 4]}, + "west": {"uv": [1, 16], "uv_size": [-1, 4]} + } + }, + { + "origin": [-3, -0.9, 0.05], + "size": [0, 4, 1], + "pivot": [-3, 2.6, 0.3], + "rotation": [45, 0, 0], + "uv": { + "east": {"uv": [16, 14], "uv_size": [-1, 4]}, + "west": {"uv": [15, 14], "uv_size": [-1, 4]} + } + }, + { + "origin": [-5.11836, 2.75, -1.41865], + "size": [2, 5, 2], + "pivot": [-5.61836, 1.75, 0.08135], + "rotation": [0, -22.5, 0], + "uv": { + "north": {"uv": [2, 9], "uv_size": [2, 5]}, + "east": {"uv": [0, 9], "uv_size": [2, 5]}, + "south": {"uv": [6, 9], "uv_size": [2, 5]}, + "up": {"uv": [2, 7], "uv_size": [2, 2]}, + "down": {"uv": [4, 9], "uv_size": [2, -2]} + } + }, + { + "origin": [2.81179, 2.75, -0.95984], + "size": [2, 5, 2], + "pivot": [4.31179, 1.75, -0.45984], + "rotation": [0, 22.5, 0], + "uv": { + "north": {"uv": [10, 9], "uv_size": [2, 5]}, + "south": {"uv": [14, 9], "uv_size": [2, 5]}, + "west": {"uv": [12, 9], "uv_size": [2, 5]}, + "up": {"uv": [10, 7], "uv_size": [2, 2]}, + "down": {"uv": [12, 9], "uv_size": [2, -2]} + } + } ] } ] diff --git a/src/main/resources/assets/superbwarfare/lang/en_us.json b/src/main/resources/assets/superbwarfare/lang/en_us.json index e03b0f06d..e6933d74c 100644 --- a/src/main/resources/assets/superbwarfare/lang/en_us.json +++ b/src/main/resources/assets/superbwarfare/lang/en_us.json @@ -171,6 +171,7 @@ "item.superbwarfare.ap_5_inches": "AP Shell", "item.superbwarfare.javelin_missile": "Javelin Missile", "item.superbwarfare.lunge_mine": "Lunge Mine", + "item.superbwarfare.blu_43_mine": "BLU-43B DragonTooth", "item.superbwarfare.rocket_70": "70mm Rocket", "item.superbwarfare.small_shell": "Small Caliber Shells", "des.superbwarfare.small_shell": "Suitable for 20mm ~ 40mm caliber weapons", @@ -482,6 +483,7 @@ "entity.superbwarfare.mk_82": "MK-82 Aerial Bomb", "entity.superbwarfare.agm_65": "AGM-65 Maverick", "entity.superbwarfare.dps_generator": "DPS Generator", + "entity.superbwarfare.blu_43_mine": "BLU-43B DragonTooth", "key.categories.superbwarfare": "Superb Warfare", "key.superbwarfare.hold_zoom": "Zoom (Hold)", diff --git a/src/main/resources/assets/superbwarfare/lang/zh_cn.json b/src/main/resources/assets/superbwarfare/lang/zh_cn.json index b4c35d3b2..5dd1f620f 100644 --- a/src/main/resources/assets/superbwarfare/lang/zh_cn.json +++ b/src/main/resources/assets/superbwarfare/lang/zh_cn.json @@ -171,6 +171,7 @@ "item.superbwarfare.ap_5_inches": "穿甲弹", "item.superbwarfare.javelin_missile": "标枪导弹", "item.superbwarfare.lunge_mine": "突刺爆雷", + "item.superbwarfare.blu_43_mine": "BLU-43蝴蝶雷", "item.superbwarfare.rocket_70": "70mm火箭弹", "item.superbwarfare.small_shell": "小口径炮弹", "des.superbwarfare.small_shell": "适配20mm ~ 40mm口径武器", @@ -482,6 +483,7 @@ "entity.superbwarfare.mk_82": "MK-82 航空炸弹", "entity.superbwarfare.agm_65": "AGM-65 “小牛”空对地导弹", "entity.superbwarfare.dps_generator": "DPS发电机", + "entity.superbwarfare.blu_43": "BLU-43蝴蝶雷", "key.categories.superbwarfare": "卓越前线", "key.superbwarfare.hold_zoom": "瞄准(按住)", diff --git a/src/main/resources/assets/superbwarfare/textures/entity/blu_43.png b/src/main/resources/assets/superbwarfare/textures/entity/blu_43.png new file mode 100644 index 0000000000000000000000000000000000000000..6ebd124855df920d877806e934893ad0cdb5fb28 GIT binary patch literal 639 zcmV-_0)YLAP)Px%IY~r8R9J=Wlut-hQ51*2`{p_AidHf;4vYv<;V!1Y7#A9$<1jJ`Ga>d5jc_Rh zf!3y_AhnS&B3l>^3~0nype_o67}`m-X<;?yGMimG&(mVOgw+jLm60>MQ%E$QbTEB8_Tlz{PB}E$uH$qG~OxzfrbE?i5WHa;EvoFyruX{ z%q?pR<=Z)5TrXmpCZ$qo*8{Jfy|e{$6CA+sAMoQdeHeyO_DDH%fag!`v2b#;CK7PAWqV0n4jT?Ha-5zz~v z{%AeHaF9SKP~M;`v(4t_1^|i6-2(9X%{zA$a5}7#g~-mGLit;_Vdj2D0X&^5SFYvE zNp}@+I@Z2?Wp$;%>Pi8Crlv+l$46vzd_(~Blq3gwYNCN(aJIyW7GJF}Vtp}*^~EGP zkgQysU&^cSu|`ruY0()+N{C?^_LlfO&DKp2MKE19xNGe|_bM39tlW1)30MG$dwFgWPH zAh?T*W2Hl92L%_mQVInNf)MCd3%S}15X6bM)UQ8~L2z{oHe7w(hzXEIskwwdE z3$^LLd=T}UiUt6>Z3ybnvc8ZKIY5F%? z!hfMh($ literal 0 HcmV?d00001