119 new translation keys across 3 domains: - Items/Blocks/Misc (46 keys): tooltips, action messages, trap states - Entities/AI Goals (55 keys): NPC speech, maid/master/guard messages - Client GUI (18 keys): widget labels, screen buttons, merchant display Remaining 119 Component.literal() are all intentional: - Debug/Admin/Command wands (47) — dev tools, not player-facing - Entity display names (~25) — dynamic getNpcName() calls - Empty string roots (~15) — .append() chain bases - User-typed text (~10) — /me, /pm, /norp chat content - Runtime data (~12) — StringBuilder, gag muffling, MCA compat
295 lines
8.7 KiB
Java
295 lines
8.7 KiB
Java
package com.tiedup.remake.blocks;
|
|
|
|
import com.tiedup.remake.blocks.entity.KidnapBombBlockEntity;
|
|
import com.tiedup.remake.core.SystemMessageManager;
|
|
import com.tiedup.remake.core.TiedUpMod;
|
|
import com.tiedup.remake.entities.EntityKidnapBomb;
|
|
import com.tiedup.remake.util.BondageItemLoaderUtility;
|
|
import java.util.List;
|
|
import javax.annotation.Nullable;
|
|
import net.minecraft.ChatFormatting;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.sounds.SoundEvents;
|
|
import net.minecraft.sounds.SoundSource;
|
|
import net.minecraft.world.InteractionHand;
|
|
import net.minecraft.world.InteractionResult;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.Items;
|
|
import net.minecraft.world.item.TooltipFlag;
|
|
import net.minecraft.world.level.BlockGetter;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.block.Block;
|
|
import net.minecraft.world.level.block.EntityBlock;
|
|
import net.minecraft.world.level.block.SoundType;
|
|
import net.minecraft.world.level.block.TntBlock;
|
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
import net.minecraft.world.level.block.state.BlockBehaviour;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.gameevent.GameEvent;
|
|
import net.minecraft.world.level.storage.loot.LootParams;
|
|
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
|
|
import net.minecraft.world.phys.BlockHitResult;
|
|
|
|
/**
|
|
* Kidnap Bomb Block - TNT that applies bondage on explosion.
|
|
*
|
|
*
|
|
* Features:
|
|
* - TNT-like block that can be ignited
|
|
* - Stores bondage items via BlockEntity
|
|
* - On explosion, applies items to entities in radius (no block damage)
|
|
* - Can be loaded by right-clicking with bondage items
|
|
*
|
|
* Based on original BlockKidnapBomb from 1.12.2
|
|
*/
|
|
public class BlockKidnapBomb
|
|
extends TntBlock
|
|
implements EntityBlock, ICanBeLoaded
|
|
{
|
|
|
|
public BlockKidnapBomb() {
|
|
super(
|
|
BlockBehaviour.Properties.of()
|
|
.strength(0.0f)
|
|
.sound(SoundType.GRASS)
|
|
.ignitedByLava()
|
|
);
|
|
}
|
|
|
|
// BLOCK ENTITY
|
|
|
|
@Nullable
|
|
@Override
|
|
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
|
|
return new KidnapBombBlockEntity(pos, state);
|
|
}
|
|
|
|
@Nullable
|
|
public KidnapBombBlockEntity getBombEntity(
|
|
BlockGetter level,
|
|
BlockPos pos
|
|
) {
|
|
BlockEntity be = level.getBlockEntity(pos);
|
|
return be instanceof KidnapBombBlockEntity
|
|
? (KidnapBombBlockEntity) be
|
|
: null;
|
|
}
|
|
|
|
// EXPLOSION HANDLING
|
|
|
|
@Override
|
|
public void onCaughtFire(
|
|
BlockState state,
|
|
Level level,
|
|
BlockPos pos,
|
|
@Nullable net.minecraft.core.Direction face,
|
|
@Nullable LivingEntity igniter
|
|
) {
|
|
if (!level.isClientSide) {
|
|
KidnapBombBlockEntity bombTile = getBombEntity(level, pos);
|
|
explode(level, pos, bombTile, igniter);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Spawn the primed kidnap bomb entity.
|
|
*/
|
|
public void explode(
|
|
Level level,
|
|
BlockPos pos,
|
|
@Nullable KidnapBombBlockEntity bombTile,
|
|
@Nullable LivingEntity igniter
|
|
) {
|
|
if (!level.isClientSide) {
|
|
EntityKidnapBomb entity = new EntityKidnapBomb(
|
|
level,
|
|
pos.getX() + 0.5,
|
|
pos.getY(),
|
|
pos.getZ() + 0.5,
|
|
igniter,
|
|
bombTile
|
|
);
|
|
level.addFreshEntity(entity);
|
|
level.playSound(
|
|
null,
|
|
entity.getX(),
|
|
entity.getY(),
|
|
entity.getZ(),
|
|
SoundEvents.TNT_PRIMED,
|
|
SoundSource.BLOCKS,
|
|
1.0f,
|
|
1.0f
|
|
);
|
|
level.gameEvent(igniter, GameEvent.PRIME_FUSE, pos);
|
|
|
|
TiedUpMod.LOGGER.info(
|
|
"[BlockKidnapBomb] Bomb primed at {} by {}",
|
|
pos,
|
|
igniter != null ? igniter.getName().getString() : "unknown"
|
|
);
|
|
}
|
|
}
|
|
|
|
// LOADING ITEMS
|
|
|
|
@Override
|
|
public InteractionResult use(
|
|
BlockState state,
|
|
Level level,
|
|
BlockPos pos,
|
|
Player player,
|
|
InteractionHand hand,
|
|
BlockHitResult hit
|
|
) {
|
|
ItemStack heldItem = player.getItemInHand(hand);
|
|
|
|
// First check if it's flint and steel (default TNT behavior)
|
|
if (
|
|
heldItem.is(Items.FLINT_AND_STEEL) || heldItem.is(Items.FIRE_CHARGE)
|
|
) {
|
|
return super.use(state, level, pos, player, hand, hit);
|
|
}
|
|
|
|
if (hand != InteractionHand.MAIN_HAND) {
|
|
return InteractionResult.PASS;
|
|
}
|
|
|
|
if (heldItem.isEmpty()) {
|
|
return InteractionResult.PASS;
|
|
}
|
|
|
|
// Check if it's a bondage item
|
|
if (!BondageItemLoaderUtility.isLoadableBondageItem(heldItem)) {
|
|
return InteractionResult.PASS;
|
|
}
|
|
|
|
// Server-side only
|
|
if (level.isClientSide) {
|
|
return InteractionResult.SUCCESS;
|
|
}
|
|
|
|
KidnapBombBlockEntity bomb = getBombEntity(level, pos);
|
|
if (bomb == null) {
|
|
return InteractionResult.PASS;
|
|
}
|
|
|
|
// Try to load the held item into the appropriate slot
|
|
if (
|
|
BondageItemLoaderUtility.loadItemIntoHolder(bomb, heldItem, player)
|
|
) {
|
|
SystemMessageManager.sendToPlayer(
|
|
player,
|
|
"Item loaded into bomb",
|
|
ChatFormatting.YELLOW
|
|
);
|
|
return InteractionResult.SUCCESS;
|
|
}
|
|
|
|
return InteractionResult.PASS;
|
|
}
|
|
|
|
// DROPS WITH NBT
|
|
|
|
@Override
|
|
public List<ItemStack> getDrops(
|
|
BlockState state,
|
|
LootParams.Builder params
|
|
) {
|
|
BlockEntity be = params.getOptionalParameter(
|
|
LootContextParams.BLOCK_ENTITY
|
|
);
|
|
ItemStack stack = new ItemStack(this);
|
|
|
|
if (be instanceof KidnapBombBlockEntity bomb) {
|
|
CompoundTag beTag = new CompoundTag();
|
|
bomb.writeBondageData(beTag);
|
|
|
|
if (!beTag.isEmpty()) {
|
|
stack.addTagElement("BlockEntityTag", beTag);
|
|
}
|
|
}
|
|
|
|
return List.of(stack);
|
|
}
|
|
|
|
// TOOLTIP
|
|
|
|
@Override
|
|
public void appendHoverText(
|
|
ItemStack stack,
|
|
@Nullable BlockGetter level,
|
|
List<Component> tooltip,
|
|
TooltipFlag flag
|
|
) {
|
|
tooltip.add(
|
|
Component.translatable("block.tiedup.kidnap_bomb.desc").withStyle(
|
|
ChatFormatting.GRAY
|
|
)
|
|
);
|
|
|
|
CompoundTag nbt = stack.getTag();
|
|
if (nbt != null && nbt.contains("BlockEntityTag")) {
|
|
CompoundTag beTag = nbt.getCompound("BlockEntityTag");
|
|
|
|
// Check if loaded with any items
|
|
if (
|
|
beTag.contains("bind") ||
|
|
beTag.contains("gag") ||
|
|
beTag.contains("blindfold") ||
|
|
beTag.contains("earplugs") ||
|
|
beTag.contains("collar")
|
|
) {
|
|
tooltip.add(
|
|
Component.translatable("block.tiedup.kidnap_bomb.loaded").withStyle(
|
|
ChatFormatting.YELLOW
|
|
)
|
|
);
|
|
|
|
// List loaded items
|
|
BondageItemLoaderUtility.addItemToTooltip(
|
|
tooltip,
|
|
beTag,
|
|
"bind"
|
|
);
|
|
BondageItemLoaderUtility.addItemToTooltip(
|
|
tooltip,
|
|
beTag,
|
|
"gag"
|
|
);
|
|
BondageItemLoaderUtility.addItemToTooltip(
|
|
tooltip,
|
|
beTag,
|
|
"blindfold"
|
|
);
|
|
BondageItemLoaderUtility.addItemToTooltip(
|
|
tooltip,
|
|
beTag,
|
|
"earplugs"
|
|
);
|
|
BondageItemLoaderUtility.addItemToTooltip(
|
|
tooltip,
|
|
beTag,
|
|
"collar"
|
|
);
|
|
BondageItemLoaderUtility.addItemToTooltip(
|
|
tooltip,
|
|
beTag,
|
|
"clothes"
|
|
);
|
|
} else {
|
|
tooltip.add(
|
|
Component.translatable("block.tiedup.kidnap_bomb.empty").withStyle(ChatFormatting.GREEN)
|
|
);
|
|
}
|
|
} else {
|
|
tooltip.add(
|
|
Component.translatable("block.tiedup.kidnap_bomb.empty").withStyle(ChatFormatting.GREEN)
|
|
);
|
|
}
|
|
}
|
|
}
|