diff --git a/src/main/java/com/atsuishio/superbwarfare/data/gun/DefaultGunData.java b/src/main/java/com/atsuishio/superbwarfare/data/gun/DefaultGunData.java index a2d85c7a4..a56fd615a 100644 --- a/src/main/java/com/atsuishio/superbwarfare/data/gun/DefaultGunData.java +++ b/src/main/java/com/atsuishio/superbwarfare/data/gun/DefaultGunData.java @@ -30,8 +30,8 @@ public class DefaultGunData { @SerializedName("Magazine") public int magazine; - @SerializedName("ProjectileType") - public String projectileType = "superbwarfare:projectile"; + @SerializedName("Projectile") + public ProjectileInfo projectile = new ProjectileInfo(); @SerializedName("ProjectileAmount") public int projectileAmount = 1; diff --git a/src/main/java/com/atsuishio/superbwarfare/data/gun/GunData.java b/src/main/java/com/atsuishio/superbwarfare/data/gun/GunData.java index 31a4f59f1..877355ef0 100644 --- a/src/main/java/com/atsuishio/superbwarfare/data/gun/GunData.java +++ b/src/main/java/com/atsuishio/superbwarfare/data/gun/GunData.java @@ -187,8 +187,12 @@ public class GunData { return magazine() <= 0; } + public ProjectileInfo projectileInfo() { + return defaultGunData().projectile; + } + public String projectileType() { - return defaultGunData().projectileType; + return projectileInfo().type; } public int projectileAmount() { diff --git a/src/main/java/com/atsuishio/superbwarfare/data/gun/ProjectileInfo.java b/src/main/java/com/atsuishio/superbwarfare/data/gun/ProjectileInfo.java new file mode 100644 index 000000000..3ac80a7ff --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/data/gun/ProjectileInfo.java @@ -0,0 +1,13 @@ +package com.atsuishio.superbwarfare.data.gun; + +import com.google.gson.JsonObject; +import com.google.gson.annotations.SerializedName; + +public class ProjectileInfo { + + @SerializedName("Type") + public String type = "superbwarfare:projectile"; + + @SerializedName("Data") + public JsonObject data; +} diff --git a/src/main/java/com/atsuishio/superbwarfare/data/launchable/LaunchableEntityTool.java b/src/main/java/com/atsuishio/superbwarfare/data/launchable/LaunchableEntityTool.java new file mode 100644 index 000000000..0ecd70aa2 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/data/launchable/LaunchableEntityTool.java @@ -0,0 +1,115 @@ +package com.atsuishio.superbwarfare.data.launchable; + +import com.atsuishio.superbwarfare.Mod; +import com.atsuishio.superbwarfare.data.gun.ProjectileInfo; +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import net.minecraft.nbt.*; +import net.minecraft.server.packs.resources.ResourceManager; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.event.OnDatapackSyncEvent; +import net.neoforged.neoforge.event.server.ServerStartedEvent; +import org.jetbrains.annotations.Nullable; + +import java.io.InputStreamReader; +import java.util.HashMap; + +@EventBusSubscriber(modid = Mod.MODID) +public class LaunchableEntityTool { + public static HashMap launchableEntitiesData = new HashMap<>(); + + /** + * 初始化数据,从data中读取数据json文件 + */ + public static void initJsonData(ResourceManager manager) { + launchableEntitiesData.clear(); + for (var entry : manager.listResources("launchable", file -> file.getPath().endsWith(".json")).entrySet()) { + var attribute = entry.getValue(); + try { + Gson gson = new Gson(); + var data = gson.fromJson(new InputStreamReader(attribute.open()), JsonObject.class); + + launchableEntitiesData.put(data.get("Type").getAsString(), data.get("Data").getAsJsonObject()); + } catch (Exception e) { + Mod.LOGGER.error(e.getMessage()); + } + } + } + + public static @Nullable CompoundTag getModifiedTag(ProjectileInfo projectileInfo, ShootData data) { + JsonObject launchableData; + if (projectileInfo.data != null) { + launchableData = projectileInfo.data; + } else if (launchableEntitiesData.containsKey(projectileInfo.type)) { + launchableData = launchableEntitiesData.get(projectileInfo.type); + } else { + return null; + } + + var tag = new CompoundTag(); + + for (var d : launchableData.entrySet()) { + var parsed = parseData(d.getValue(), data); + if (parsed == null) continue; + tag.put(d.getKey(), parsed); + } + + return tag; + } + + private static @Nullable Tag parseData(JsonElement object, ShootData data) { + if (object.isJsonObject()) { + var tag = new CompoundTag(); + for (var d : object.getAsJsonObject().entrySet()) { + var parsed = parseData(d.getValue(), data); + if (parsed == null) continue; + tag.put(d.getKey(), parsed); + } + return tag; + } else if (object.isJsonArray()) { + var tag = new ListTag(); + for (var d : object.getAsJsonArray()) { + tag.add(parseData(d, data)); + } + return tag; + } else if (object.isJsonPrimitive()) { + var prime = object.getAsJsonPrimitive(); + if (prime.isString()) { + return modifyStringTag(prime.getAsString(), data); + } else if (prime.isNumber()) { + return DoubleTag.valueOf(prime.getAsLong()); + } else if (prime.isBoolean()) { + return ByteTag.valueOf(prime.getAsBoolean()); + } + return null; + } + return null; + } + + private static Tag modifyStringTag(String value, ShootData data) { + return switch (value) { + case "@sbw:damage" -> DoubleTag.valueOf(data.damage()); + case "@sbw:owner" -> NbtUtils.createUUID(data.shooter()); + case "@sbw:owner_string_lower" -> + StringTag.valueOf(data.shooter().toString().replace("-", "").toLowerCase()); + case "@sbw:owner_string_upper" -> + StringTag.valueOf(data.shooter().toString().replace("-", "").toUpperCase()); + case "@sbw:explosion_damage" -> DoubleTag.valueOf(data.explosionDamage()); + case "@sbw:explosion_radius" -> DoubleTag.valueOf(data.explosionRadius()); + case "@sbw:spread" -> DoubleTag.valueOf(data.spread()); + default -> StringTag.valueOf(value); + }; + } + + @SubscribeEvent + public static void serverStarted(ServerStartedEvent event) { + initJsonData(event.getServer().getResourceManager()); + } + + @SubscribeEvent + public static void onDataPackSync(OnDatapackSyncEvent event) { + initJsonData(event.getPlayerList().getServer().getResourceManager()); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/data/launchable/ShootData.java b/src/main/java/com/atsuishio/superbwarfare/data/launchable/ShootData.java new file mode 100644 index 000000000..c136a5176 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/data/launchable/ShootData.java @@ -0,0 +1,13 @@ +package com.atsuishio.superbwarfare.data.launchable; + +import java.util.UUID; + +// 开火时的信息 +public record ShootData( + UUID shooter, + double damage, + double explosionDamage, + double explosionRadius, + double spread +) { +} diff --git a/src/main/java/com/atsuishio/superbwarfare/item/gun/GunItem.java b/src/main/java/com/atsuishio/superbwarfare/item/gun/GunItem.java index e77bb7ee3..607aa2271 100644 --- a/src/main/java/com/atsuishio/superbwarfare/item/gun/GunItem.java +++ b/src/main/java/com/atsuishio/superbwarfare/item/gun/GunItem.java @@ -4,7 +4,10 @@ import com.atsuishio.superbwarfare.Mod; import com.atsuishio.superbwarfare.client.PoseTool; import com.atsuishio.superbwarfare.client.tooltip.component.GunImageComponent; import com.atsuishio.superbwarfare.data.gun.GunData; +import com.atsuishio.superbwarfare.data.gun.ProjectileInfo; import com.atsuishio.superbwarfare.data.gun.value.AttachmentType; +import com.atsuishio.superbwarfare.data.launchable.LaunchableEntityTool; +import com.atsuishio.superbwarfare.data.launchable.ShootData; import com.atsuishio.superbwarfare.entity.projectile.ExplosiveProjectile; import com.atsuishio.superbwarfare.entity.projectile.ProjectileEntity; import com.atsuishio.superbwarfare.init.ModAttachments; @@ -575,12 +578,14 @@ public abstract class GunItem extends Item implements CustomRendererItem { float bypassArmorRate = (float) data.bypassArmor(); var projectileType = data.projectileType(); + var projectileInfo = data.projectileInfo(); AtomicReference projectileHolder = new AtomicReference<>(); EntityType.byString(projectileType).ifPresent(entityType -> { var entity = entityType.create(level); if (!(entity instanceof Projectile)) return; ((Projectile) entity).setOwner(player); + // SBW子弹弹射物专属属性 if (entity instanceof ProjectileEntity projectile) { projectile.shooter(player) .damage(damage) @@ -590,12 +595,36 @@ public abstract class GunItem extends Item implements CustomRendererItem { .setGunItemId(stack); } + // SBW爆炸物专属属性 if (entity instanceof ExplosiveProjectile explosive) { explosive.setDamage(damage); explosive.setExplosionDamage((float) data.explosionDamage()); explosive.setExplosionRadius((float) data.explosionRadius()); } + // 填充其他自定义NBT数据 + if (projectileInfo.data != null) { + var tag = LaunchableEntityTool.getModifiedTag(projectileInfo, + new ShootData(player.getUUID(), damage, data.explosionDamage(), data.explosionRadius(), data.spread()) + ); + if (tag != null) { + entity.load(tag); + } + + } else if (LaunchableEntityTool.launchableEntitiesData.containsKey(projectileType)) { + var newInfo = new ProjectileInfo(); + newInfo.data = LaunchableEntityTool.launchableEntitiesData.get(projectileType); + newInfo.type = projectileType; + + var tag = LaunchableEntityTool.getModifiedTag( + newInfo, + new ShootData(player.getUUID(), damage, data.explosionDamage(), data.explosionRadius(), data.spread()) + ); + if (tag != null) { + entity.load(tag); + } + } + projectileHolder.set((Projectile) entity); }); diff --git a/src/main/java/com/atsuishio/superbwarfare/perk/ammo/MicroMissile.java b/src/main/java/com/atsuishio/superbwarfare/perk/ammo/MicroMissile.java index b9efb1729..2fcfa80c7 100644 --- a/src/main/java/com/atsuishio/superbwarfare/perk/ammo/MicroMissile.java +++ b/src/main/java/com/atsuishio/superbwarfare/perk/ammo/MicroMissile.java @@ -1,8 +1,7 @@ package com.atsuishio.superbwarfare.perk.ammo; import com.atsuishio.superbwarfare.data.gun.GunData; -import com.atsuishio.superbwarfare.entity.projectile.GunGrenadeEntity; -import com.atsuishio.superbwarfare.entity.projectile.RpgRocketEntity; +import com.atsuishio.superbwarfare.entity.projectile.ExplosiveProjectile; import com.atsuishio.superbwarfare.perk.AmmoPerk; import com.atsuishio.superbwarfare.perk.Perk; import com.atsuishio.superbwarfare.perk.PerkInstance; @@ -14,15 +13,13 @@ public class MicroMissile extends AmmoPerk { super(new AmmoPerk.Builder("micro_missile", Perk.Type.AMMO).speedRate(1.2f)); } + // TODO 正确设计和实现伤害修改 @Override public void modifyProjectile(GunData data, PerkInstance instance, Entity entity) { float radius = (float) (data.explosionRadius() * 0.5f); float damage = (float) data.explosionDamage() * (1.1f + instance.level() * 0.1f); entity.setNoGravity(true); - if (entity instanceof GunGrenadeEntity projectile) { - projectile.setExplosionRadius(radius); - projectile.setExplosionDamage(damage); - } else if (entity instanceof RpgRocketEntity projectile) { + if (entity instanceof ExplosiveProjectile projectile) { projectile.setExplosionRadius(radius); projectile.setExplosionDamage(damage); } diff --git a/src/main/resources/data/superbwarfare/guns/m_79.json b/src/main/resources/data/superbwarfare/guns/m_79.json index 176e24f1f..b2d754f01 100644 --- a/src/main/resources/data/superbwarfare/guns/m_79.json +++ b/src/main/resources/data/superbwarfare/guns/m_79.json @@ -3,7 +3,9 @@ "RecoilX": 0.004, "RecoilY": 0.023, "Damage": 40, - "ProjectileType": "superbwarfare:gun_grenade", + "Projectile": { + "Type": "superbwarfare:gun_grenade" + }, "ExplosionDamage": 80, "ExplosionRadius": 5, "Velocity": 3.75, diff --git a/src/main/resources/data/superbwarfare/guns/rpg.json b/src/main/resources/data/superbwarfare/guns/rpg.json index bb12eae5b..42ee363f5 100644 --- a/src/main/resources/data/superbwarfare/guns/rpg.json +++ b/src/main/resources/data/superbwarfare/guns/rpg.json @@ -3,7 +3,9 @@ "RecoilX": 0.008, "RecoilY": 0.018, "Damage": 270, - "ProjectileType": "superbwarfare:rpg_rocket", + "Projectile": { + "Type": "superbwarfare:rpg_rocket" + }, "ExplosionDamage": 130, "ExplosionRadius": 10, "Velocity": 4, diff --git a/src/main/resources/data/superbwarfare/launchable/arrow.json b/src/main/resources/data/superbwarfare/launchable/arrow.json new file mode 100644 index 000000000..04a55263e --- /dev/null +++ b/src/main/resources/data/superbwarfare/launchable/arrow.json @@ -0,0 +1,8 @@ +{ + "Type": "minecraft:arrow", + "Data": { + "damage": "@sbw:damage", + "pickup": 2, + "crit": false + } +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/launchable/fireball.json b/src/main/resources/data/superbwarfare/launchable/fireball.json new file mode 100644 index 000000000..234a8ea3a --- /dev/null +++ b/src/main/resources/data/superbwarfare/launchable/fireball.json @@ -0,0 +1,6 @@ +{ + "Type": "minecraft:fireball", + "Data": { + "ExplosionPower": "@sbw:explosion_damage" + } +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/launchable/spectral_arrow.json b/src/main/resources/data/superbwarfare/launchable/spectral_arrow.json new file mode 100644 index 000000000..cb5420035 --- /dev/null +++ b/src/main/resources/data/superbwarfare/launchable/spectral_arrow.json @@ -0,0 +1,8 @@ +{ + "Type": "minecraft:spectral_arrow", + "Data": { + "damage": "@sbw:damage", + "pickup": 2, + "crit": false + } +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/launchable/trident.json b/src/main/resources/data/superbwarfare/launchable/trident.json new file mode 100644 index 000000000..fbd5fd1d3 --- /dev/null +++ b/src/main/resources/data/superbwarfare/launchable/trident.json @@ -0,0 +1,7 @@ +{ + "Type": "minecraft:trident", + "Data": { + "pickup": 2, + "crit": false + } +} \ No newline at end of file