package com.tiedup.remake.entities; import com.tiedup.remake.blocks.entity.KidnapBombBlockEntity; import com.tiedup.remake.core.SettingsAccessor; import com.tiedup.remake.util.KidnapExplosion; import javax.annotation.Nullable; import net.minecraft.core.BlockPos; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.MoverType; import net.minecraft.world.entity.item.PrimedTnt; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; /** * Kidnap Bomb Entity - Primed TNT that applies bondage on explosion. * * * When the fuse runs out, instead of a destructive explosion, * it applies stored bondage items to all entities in radius. * * Based on original EntityKidnapBomb from 1.12.2 */ public class EntityKidnapBomb extends PrimedTnt { // Stored bondage items private ItemStack bind = ItemStack.EMPTY; private ItemStack gag = ItemStack.EMPTY; private ItemStack blindfold = ItemStack.EMPTY; private ItemStack earplugs = ItemStack.EMPTY; private ItemStack collar = ItemStack.EMPTY; private ItemStack clothes = ItemStack.EMPTY; public EntityKidnapBomb( EntityType type, Level level ) { super(type, level); } /** * Create from a placed bomb block. */ public EntityKidnapBomb( Level level, double x, double y, double z, @Nullable LivingEntity igniter, @Nullable KidnapBombBlockEntity bombTile ) { super(ModEntities.KIDNAP_BOMB_ENTITY.get(), level); this.setPos(x, y, z); double d0 = level.random.nextDouble() * (Math.PI * 2); this.setDeltaMovement(-Math.sin(d0) * 0.02, 0.2, -Math.cos(d0) * 0.02); this.setFuse(SettingsAccessor.getKidnapBombFuse()); this.xo = x; this.yo = y; this.zo = z; // Copy bondage items from tile entity if (bombTile != null) { this.bind = bombTile.getBind().copy(); this.gag = bombTile.getGag().copy(); this.blindfold = bombTile.getBlindfold().copy(); this.earplugs = bombTile.getEarplugs().copy(); this.collar = bombTile.getCollar().copy(); this.clothes = bombTile.getClothes().copy(); } } @Override public void tick() { // Store previous position this.xo = this.getX(); this.yo = this.getY(); this.zo = this.getZ(); // Apply gravity if (!this.isNoGravity()) { this.setDeltaMovement(this.getDeltaMovement().add(0, -0.04, 0)); } // Move this.move(MoverType.SELF, this.getDeltaMovement()); // Apply friction this.setDeltaMovement(this.getDeltaMovement().scale(0.98)); if (this.onGround()) { this.setDeltaMovement( this.getDeltaMovement().multiply(0.7, -0.5, 0.7) ); } // Handle fuse int fuse = this.getFuse() - 1; this.setFuse(fuse); if (fuse <= 0) { this.discard(); if (!this.level().isClientSide) { this.explode(); } } else { // Spawn smoke particles (client-side only) this.updateInWaterStateAndDoFluidPushing(); if (this.level().isClientSide) { this.level().addParticle( ParticleTypes.SMOKE, this.getX(), this.getY() + 0.5, this.getZ(), 0, 0, 0 ); } } } /** * Perform the kidnap explosion (no block damage). */ protected void explode() { int radius = getExplosionRadius(); BlockPos pos = this.blockPosition(); KidnapExplosion explosion = new KidnapExplosion( this.level(), pos, radius, bind, gag, blindfold, earplugs, collar, clothes ); explosion.explode(); } /** * Get the explosion radius from game rules. */ private int getExplosionRadius() { // Default radius of 5 blocks return SettingsAccessor.getKidnapBombRadius( this.level().getGameRules() ); } // NBT SERIALIZATION @Override protected void addAdditionalSaveData(CompoundTag tag) { super.addAdditionalSaveData(tag); if (!bind.isEmpty()) { tag.put("bind", bind.save(new CompoundTag())); } if (!gag.isEmpty()) { tag.put("gag", gag.save(new CompoundTag())); } if (!blindfold.isEmpty()) { tag.put("blindfold", blindfold.save(new CompoundTag())); } if (!earplugs.isEmpty()) { tag.put("earplugs", earplugs.save(new CompoundTag())); } if (!collar.isEmpty()) { tag.put("collar", collar.save(new CompoundTag())); } if (!clothes.isEmpty()) { tag.put("clothes", clothes.save(new CompoundTag())); } } @Override protected void readAdditionalSaveData(CompoundTag tag) { super.readAdditionalSaveData(tag); if (tag.contains("bind")) { bind = ItemStack.of(tag.getCompound("bind")); } if (tag.contains("gag")) { gag = ItemStack.of(tag.getCompound("gag")); } if (tag.contains("blindfold")) { blindfold = ItemStack.of(tag.getCompound("blindfold")); } if (tag.contains("earplugs")) { earplugs = ItemStack.of(tag.getCompound("earplugs")); } if (tag.contains("collar")) { collar = ItemStack.of(tag.getCompound("collar")); } if (tag.contains("clothes")) { clothes = ItemStack.of(tag.getCompound("clothes")); } } }