版本信息
你使用的IDE:IntelliJ IDEA
你使用的IDE版本:2020.1
Forge版本: 31.1.46
Minecraft版本: 1.15.2
Mapping 文件版本: 20200422-1.15.1
我尝试创建一个c4(ThrowableEntity
)和对应的引爆器(Item
),但是在最后阶段遇到了困难:我不知道如何正确的在拿着引爆器右键时使附近的c4爆炸。我在我的C4Entity的类中写好了与爆炸有关的方法exploder
,并且尝试在c4_exploder
的onItemRightClick
中使用它,就像这样:
c4
实体。我大概意识到了我所犯的错误,但是不知道怎么样去修正它。我尝试了另一种办法:我想要监听事件:玩家拿着物品时右键(
PlayerInteractEvent.RightClickItem
),且拿的是起爆器c4_exploder
时,调用exploder
使其爆炸: 但是我不知道如何正确的注册它(已阅读forge文档,我的问题在于这个监听器是写在c4entity.class
而不是单独的类中的),也不知道是否会出现同第一个方法一样的错误。我该怎么做才能达到我想要的效果?以下是
c4_exploder
和c4entity
的完整代码(在尝试第二种方法时):c4_exploder
:
public class c4_exploder extends Item {
public c4_exploder(){
super(new Properties().group(Utils.ItemGroup));
this.setRegistryName("c4_exploder");
}
@Override
public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) {
ItemStack itemstack = playerIn.getHeldItem(handIn);
return new ActionResult<>(ActionResultType.SUCCESS, itemstack);
}
}
c4entity
:
public class c4entity extends ProjectileItemEntity {
public c4entity(EntityType<? extends c4entity> type, LivingEntity playerIn, World worldIn) {
super(type, playerIn, worldIn);
}
public c4entity(EntityType<c4entity> c4entityEntityType, World world) {
super(c4entityEntityType, world);
}
@Nullable
private BlockState inBlockState;
public c4entity(LivingEntity throwerIn, World worldIn) {
super(ModEntityTypes.c4entitytype,throwerIn, worldIn);
}
@Override
protected Item getDefaultItem() {
return ModItems.c4;
}
@Override
protected void onImpact(RayTraceResult raytraceResultIn) {
if (raytraceResultIn.getType() == RayTraceResult.Type.BLOCK) {
BlockRayTraceResult blockraytraceresult = (BlockRayTraceResult) raytraceResultIn;
BlockState blockstate = this.world.getBlockState(blockraytraceresult.getPos());
this.inBlockState = blockstate;
Vec3d vec3d = blockraytraceresult.getHitVec().subtract(this.getPosX(), this.getPosY(), this.getPosZ());
this.setMotion(vec3d);
Vec3d vec3d1 = vec3d.normalize().scale((double) 0.05F);
this.prevPosX -= vec3d1.x;
this.prevPosY -= vec3d1.y;
this.prevPosZ -= vec3d1.z;
this.playSound(ModSounds.c4_hit, 0.8f, 1.0f);
this.inGround = true;
this.setNoGravity(true);
blockstate.onProjectileCollision(this.world, blockstate, blockraytraceresult, this);
}
}
@Override
public IPacket<?> createSpawnPacket() {
return NetworkHooks.getEntitySpawningPacket(this);
}
private static final DataParameter<Boolean> IGNITED = EntityDataManager.createKey(CreeperEntity.class, DataSerializers.BOOLEAN);
private static final DataParameter<Integer> STATE = EntityDataManager.createKey(CreeperEntity.class, DataSerializers.VARINT);
private int fuseTime = 8;
private int explosionRadius = 2;
private int timeSinceIgnited = 1;
@Override
protected void registerData() {
super.registerData();
this.dataManager.register(STATE, -1);
this.dataManager.register(IGNITED, false);
}
@Override
public void writeAdditional(CompoundNBT compound) {
super.writeAdditional(compound);
compound.putShort("Fuse", (short) this.fuseTime);
compound.putByte("ExplosionRadius", (byte) this.explosionRadius);
compound.putBoolean("ignited", this.hasIgnited());
}
@Override
public void readAdditional(CompoundNBT compound) {
super.readAdditional(compound);
if (compound.contains("Fuse", 99)) {
this.fuseTime = compound.getShort("Fuse");
}
if (compound.contains("ExplosionRadius", 99)) {
this.explosionRadius = compound.getByte("ExplosionRadius");
}
if (compound.getBoolean("ignited")) {
this.ignite();
}
}
public boolean hasIgnited() {
return this.dataManager.get(IGNITED);
}
public void ignite() {
this.dataManager.set(IGNITED, true);
}
public int getc4state() {
return this.dataManager.get(STATE);
}
public void setc4state(int state) {
this.dataManager.set(STATE, state);
}
private void explode() {
if (!this.world.isRemote) {
this.world.createExplosion(this, this.getPosX(), this.getPosY(), this.getPosZ(), (float) this.explosionRadius, Explosion.Mode.DESTROY);
this.remove();
this.spawnLingeringCloud();
}
}
private void spawnLingeringCloud() {
AreaEffectCloudEntity areaeffectcloudentity = new AreaEffectCloudEntity(this.world, this.getPosX(), this.getPosY(), this.getPosZ());
areaeffectcloudentity.setRadius(1.0F);
areaeffectcloudentity.setRadiusOnUse(-0.5F);
areaeffectcloudentity.setWaitTime(10);
areaeffectcloudentity.setDuration(areaeffectcloudentity.getDuration() / 2);
areaeffectcloudentity.setRadiusPerTick(-areaeffectcloudentity.getRadius() / (float) areaeffectcloudentity.getDuration());
this.world.addEntity(areaeffectcloudentity);
}
public void exploder() {
this.ignite();
this.setc4state(1);
int i = this.getc4state();
this.timeSinceIgnited += i;
if (this.timeSinceIgnited < 0) {
this.timeSinceIgnited = 0;
}
if (this.timeSinceIgnited >= this.fuseTime) {
this.timeSinceIgnited = this.fuseTime;
this.explode();
}
}
@SubscribeEvent
public void getexplode(PlayerInteractEvent.RightClickItem event){
if(this.getThrower().getHeldItemMainhand().getItem()==ModItems.c4_exploder){
this.exploder();
}
}
其中的延时爆炸功能还不太能起作用,不过这并不是重点。