活塞、粘性活塞推动、拉回以及发射器投掷时复制一个TNT,复制出的TNT带有额外动量。
Java:
package org.bugcraft.tntduper;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Dispenser;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockDispenseEvent;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.bukkit.event.block.BlockPistonRetractEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.util.Vector;
public class TNTDuper extends JavaPlugin implements Listener {
@Override
public void onEnable() {
getServer().getPluginManager().registerEvents(this, this);
getLogger().info("TNTDuper插件已启用!");
}
@Override
public void onDisable() {
getLogger().info("TNTDuper插件已禁用!");
}
@EventHandler
public void onBlockDispense(BlockDispenseEvent event) {
Block block = event.getBlock();
// 检查是否是发射器
if (block.getType() != Material.DISPENSER) {
return;
}
// 检查发射的物品是否是TNT
if (event.getItem().getType() != Material.TNT) {
return;
}
Dispenser dispenser = (Dispenser) block.getState();
Inventory inventory = dispenser.getInventory();
// 检查发射器内是否只有TNT
if (containsOnlyTNT(inventory)) {
// 取消事件,我们自己处理TNT的发射和补充
event.setCancelled(true);
// 创建TNT实体并发射(模拟原版行为)
// 使用正确的实体类型名称
TNTPrimed tnt = (TNTPrimed) block.getWorld().spawnEntity(
block.getLocation().add(0.5, 0.5, 0.5),
EntityType.TNT
);
// 设置TNT的发射方向(根据发射器朝向)
setTNTVelocity(tnt, block);
}
}
@EventHandler
public void onPistonExtend(BlockPistonExtendEvent event) {
// 检查活塞推动的方块中是否有TNT
for (Block block : event.getBlocks()) {
if (block.getType() == Material.TNT) {
handlePistonTNT(block, event.getDirection());
}
}
}
@EventHandler
public void onPistonRetract(BlockPistonRetractEvent event) {
// 检查粘性活塞拉回的方块中是否有TNT
if (event.isSticky()) {
for (Block block : event.getBlocks()) {
if (block.getType() == Material.TNT) {
handlePistonTNT(block, event.getDirection());
}
}
}
}
private void handlePistonTNT(Block tntBlock, BlockFace direction) {
// 在活塞推动TNT的位置生成一个新的TNT实体
TNTPrimed tnt = (TNTPrimed) tntBlock.getWorld().spawnEntity(
tntBlock.getLocation().add(0.5, 0.5, 0.5),
EntityType.TNT
);
// 设置TNT的速度方向与活塞推动方向一致
Vector velocity = new Vector(
direction.getModX() * 0.5,
direction.getModY() * 0.5,
direction.getModZ() * 0.5
);
// 添加一些随机性以防止TNT堆叠
velocity.add(new Vector(
(Math.random() - 0.5) * 0.2,
(Math.random() - 0.5) * 0.2,
(Math.random() - 0.5) * 0.2
));
tnt.setVelocity(velocity);
}
private boolean containsOnlyTNT(Inventory inventory) {
for (ItemStack item : inventory.getContents()) {
if (item != null && item.getType() != Material.AIR && item.getType() != Material.TNT) {
return false;
}
}
return true;
}
private void setTNTVelocity(TNTPrimed tnt, Block dispenser) {
// 获取发射器的朝向
org.bukkit.block.data.type.Dispenser dispenserData =
(org.bukkit.block.data.type.Dispenser) dispenser.getBlockData();
BlockFace facing = dispenserData.getFacing();
// 根据朝向设置速度
Vector velocity = new Vector(
facing.getModX() * 0.5,
facing.getModY() * 0.5,
facing.getModZ() * 0.5
);
// 添加一些随机性以防止TNT堆叠
velocity.add(new Vector(
(Math.random() - 0.5) * 0.2,
(Math.random() - 0.5) * 0.2,
(Math.random() - 0.5) * 0.2
));
tnt.setVelocity(velocity);
}
}