实现无人机自定义投弹

This commit is contained in:
Light_Quanta 2025-07-03 15:06:50 +08:00
parent 5fc159ee3f
commit bf5900d1e0
No known key found for this signature in database
GPG key ID: 11A39A1B8C890959
8 changed files with 68 additions and 23 deletions

View file

@ -5,7 +5,7 @@ import com.google.gson.JsonObject;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
public class DroneAttachmentData implements IDBasedData { public class DroneAttachmentData implements IDBasedData {
@SerializedName("ItemID") @SerializedName("Item")
public String itemID = ""; public String itemID = "";
@SerializedName("Entity") @SerializedName("Entity")
@ -31,6 +31,14 @@ public class DroneAttachmentData implements IDBasedData {
} }
@SerializedName("DropPosition")
private float[] dropPosition = new float[]{0, -0.09f, 0};
public float[] dropPosition() {
return (this.dropPosition != null && this.dropPosition.length < 3) ? new float[]{0, -0.09f, 0} : this.dropPosition;
}
/** /**
* 无人机显示的挂载实体的实体数据 * 无人机显示的挂载实体的实体数据
*/ */

View file

@ -56,14 +56,15 @@ public class RgoGrenadeEntity extends FastThrowableProjectile implements GeoEnti
} }
@Override @Override
public void addAdditionalSaveData(CompoundTag pCompound) { public void addAdditionalSaveData(@NotNull CompoundTag pCompound) {
super.addAdditionalSaveData(pCompound); super.addAdditionalSaveData(pCompound);
pCompound.putFloat("ExplosionDamage", this.explosionDamage); pCompound.putFloat("ExplosionDamage", this.explosionDamage);
pCompound.putFloat("Radius", this.explosionRadius); pCompound.putFloat("Radius", this.explosionRadius);
pCompound.putFloat("Fuse", this.fuse);
} }
@Override @Override
public void readAdditionalSaveData(CompoundTag pCompound) { public void readAdditionalSaveData(@NotNull CompoundTag pCompound) {
super.readAdditionalSaveData(pCompound); super.readAdditionalSaveData(pCompound);
if (pCompound.contains("ExplosionDamage")) { if (pCompound.contains("ExplosionDamage")) {
this.explosionDamage = pCompound.getFloat("ExplosionDamage"); this.explosionDamage = pCompound.getFloat("ExplosionDamage");
@ -71,6 +72,9 @@ public class RgoGrenadeEntity extends FastThrowableProjectile implements GeoEnti
if (pCompound.contains("Radius")) { if (pCompound.contains("Radius")) {
this.explosionRadius = pCompound.getFloat("Radius"); this.explosionRadius = pCompound.getFloat("Radius");
} }
if (pCompound.contains("Fuse")) {
this.fuse = pCompound.getInt("Fuse");
}
} }
@Override @Override

View file

@ -6,7 +6,6 @@ import com.atsuishio.superbwarfare.data.drone_attachment.DroneAttachmentData;
import com.atsuishio.superbwarfare.entity.projectile.C4Entity; import com.atsuishio.superbwarfare.entity.projectile.C4Entity;
import com.atsuishio.superbwarfare.entity.projectile.LaserEntity; import com.atsuishio.superbwarfare.entity.projectile.LaserEntity;
import com.atsuishio.superbwarfare.entity.projectile.ProjectileEntity; import com.atsuishio.superbwarfare.entity.projectile.ProjectileEntity;
import com.atsuishio.superbwarfare.entity.projectile.RgoGrenadeEntity;
import com.atsuishio.superbwarfare.entity.vehicle.base.MobileVehicleEntity; import com.atsuishio.superbwarfare.entity.vehicle.base.MobileVehicleEntity;
import com.atsuishio.superbwarfare.init.*; import com.atsuishio.superbwarfare.init.*;
import com.atsuishio.superbwarfare.item.Monitor; import com.atsuishio.superbwarfare.item.Monitor;
@ -14,6 +13,8 @@ import com.atsuishio.superbwarfare.tools.*;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.StringTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.EntityDataSerializers;
@ -53,10 +54,7 @@ import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
import software.bernie.geckolib.animation.AnimatableManager; import software.bernie.geckolib.animation.AnimatableManager;
import software.bernie.geckolib.util.GeckoLibUtil; import software.bernie.geckolib.util.GeckoLibUtil;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
public class DroneEntity extends MobileVehicleEntity implements GeoEntity { public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
@ -224,7 +222,7 @@ public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
if (this.fire) { if (this.fire) {
if (this.entityData.get(AMMO) > 0) { if (this.entityData.get(AMMO) > 0) {
this.entityData.set(AMMO, this.entityData.get(AMMO) - 1); this.entityData.set(AMMO, this.entityData.get(AMMO) - 1);
if (controller != null) { if (controller != null && this.level() instanceof ServerLevel) {
droneDrop(controller); droneDrop(controller);
} }
} }
@ -247,12 +245,44 @@ public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
} }
private void droneDrop(@Nullable Player player) { private void droneDrop(@Nullable Player player) {
if (!this.level().isClientSide()) { var data = CustomData.DRONE_ATTACHMENT.get(getItemId(this.currentItem));
RgoGrenadeEntity rgoGrenadeEntity = new RgoGrenadeEntity(player, this.level(), 160); if (data == null) return;
rgoGrenadeEntity.setPos(this.getX(), this.getEyeY() - 0.09, this.getZ()); var dropEntity = EntityType.byString(data.dropEntity())
rgoGrenadeEntity.droneShoot(this); .map(type -> type.create(this.level()))
this.level().addFreshEntity(rgoGrenadeEntity); .orElse(null);
if (dropEntity == null) return;
if (player != null && dropEntity instanceof Projectile projectile) {
projectile.setOwner(player);
} }
var tag = TagDataParser.parse(data.dropData, name -> {
if (player == null) return StringTag.valueOf(name);
var uuid = player.getUUID();
return switch (name) {
case "@sbw:owner" -> NbtUtils.createUUID(uuid);
case "@sbw:owner_string_lower" ->
StringTag.valueOf(uuid.toString().replace("-", "").toLowerCase(Locale.ENGLISH));
case "@sbw:owner_string_upper" ->
StringTag.valueOf(uuid.toString().replace("-", "").toUpperCase(Locale.ENGLISH));
default -> StringTag.valueOf(name);
};
});
dropEntity.load(tag);
var dropPos = data.dropPosition();
dropEntity.setPos(this.getX() + dropPos[0], this.getY() + dropPos[1], this.getZ() + dropPos[2]);
var vec3 = (new Vec3(0.2 * this.getDeltaMovement().x, 0.2 * this.getDeltaMovement().y, 0.2 * this.getDeltaMovement().z));
dropEntity.setDeltaMovement(vec3);
double d0 = vec3.horizontalDistance();
dropEntity.setYRot((float) (Mth.atan2(vec3.x, vec3.z) * (double) (180F / (float) java.lang.Math.PI)));
dropEntity.setXRot((float) (Mth.atan2(vec3.y, d0) * (double) (180F / (float) java.lang.Math.PI)));
dropEntity.yRotO = dropEntity.getYRot();
dropEntity.xRotO = dropEntity.getXRot();
this.level().addFreshEntity(dropEntity);
} }
@Override @Override
@ -355,7 +385,6 @@ public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
// 不同种物品挂载 // 不同种物品挂载
this.currentItem = stack.copyWithCount(1); this.currentItem = stack.copyWithCount(1);
this.entityData.set(DISPLAY_ENTITY, attachmentData.displayEntity()); this.entityData.set(DISPLAY_ENTITY, attachmentData.displayEntity());
// TODO 正确处理和渲染AMMO
this.entityData.set(AMMO, this.entityData.get(AMMO) + 1); this.entityData.set(AMMO, this.entityData.get(AMMO) + 1);
if (!player.isCreative()) { if (!player.isCreative()) {
@ -370,7 +399,6 @@ public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
var rotation = attachmentData.rotation(); var rotation = attachmentData.rotation();
if (attachmentData.displayData != null) { if (attachmentData.displayData != null) {
// TODO 数据替换
this.entityData.set(DISPLAY_ENTITY_TAG, TagDataParser.parse(attachmentData.displayData)); this.entityData.set(DISPLAY_ENTITY_TAG, TagDataParser.parse(attachmentData.displayData));
} }

View file

@ -3,6 +3,7 @@ package com.atsuishio.superbwarfare.tools;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import net.minecraft.nbt.*; import net.minecraft.nbt.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.function.Function; import java.util.function.Function;
@ -11,7 +12,7 @@ public class TagDataParser {
/** /**
* 将JsonObject转换为NBT Tag * 将JsonObject转换为NBT Tag
*/ */
public static CompoundTag parse(JsonObject object) { public static CompoundTag parse(@Nullable JsonObject object) {
return parse(object, null); return parse(object, null);
} }
@ -22,8 +23,9 @@ public class TagDataParser {
* @param tagModifier 替换函数 * @param tagModifier 替换函数
* @return 替换后的NBT Tag * @return 替换后的NBT Tag
*/ */
public static CompoundTag parse(JsonObject object, @Nullable Function<String, Tag> tagModifier) { public static CompoundTag parse(@Nullable JsonObject object, @Nullable Function<String, Tag> tagModifier) {
var tag = new CompoundTag(); var tag = new CompoundTag();
if (object == null) return tag;
for (var d : object.entrySet()) { for (var d : object.entrySet()) {
var parsed = parse(d.getValue(), tagModifier); var parsed = parse(d.getValue(), tagModifier);
@ -41,7 +43,7 @@ public class TagDataParser {
* @param tagModifier 替换函数 * @param tagModifier 替换函数
* @return 替换后的NBT Tag * @return 替换后的NBT Tag
*/ */
public static @Nullable Tag parse(JsonElement object, @Nullable Function<String, Tag> tagModifier) { public static @Nullable Tag parse(@NotNull JsonElement object, @Nullable Function<String, Tag> tagModifier) {
if (object.isJsonObject()) { if (object.isJsonObject()) {
// 递归处理嵌套内容 // 递归处理嵌套内容
var tag = new CompoundTag(); var tag = new CompoundTag();

View file

@ -1,5 +1,5 @@
{ {
"ItemID": "superbwarfare:c4_bomb", "Item": "superbwarfare:c4_bomb",
"Entity": "superbwarfare:c4", "Entity": "superbwarfare:c4",
"HitDamage": 150, "HitDamage": 150,
"ExplosionDamage": 300, "ExplosionDamage": 300,

View file

@ -1,5 +1,5 @@
{ {
"ItemID": "superbwarfare:mortar_shell", "Item": "superbwarfare:mortar_shell",
"Entity": "superbwarfare:mortar_shell", "Entity": "superbwarfare:mortar_shell",
"HitDamage": 200, "HitDamage": 200,
"ExplosionDamage": 160, "ExplosionDamage": 160,

View file

@ -1,11 +1,14 @@
{ {
"ItemID": "superbwarfare:rgo_grenade", "Item": "superbwarfare:rgo_grenade",
"Entity": "superbwarfare:rgo_grenade", "Entity": "superbwarfare:rgo_grenade",
"IsKamikaze": false, "IsKamikaze": false,
"Count": 6, "Count": 6,
"HitDamage": 270, "HitDamage": 270,
"ExplosionDamage": 130, "ExplosionDamage": 130,
"ExplosionRadius": 10, "ExplosionRadius": 10,
"DropData": {
"Fuse": 160
},
"Offset": [ "Offset": [
0, 0,
-0.04, -0.04,

View file

@ -1,5 +1,5 @@
{ {
"ItemID": "superbwarfare:rocket", "Item": "superbwarfare:rocket",
"Entity": "superbwarfare:rpg_rocket", "Entity": "superbwarfare:rpg_rocket",
"HitDamage": 270, "HitDamage": 270,
"ExplosionDamage": 130, "ExplosionDamage": 130,