添加Projectile属性和相关自定义接口

This commit is contained in:
Light_Quanta 2025-05-16 05:52:15 +08:00
parent b5951a237e
commit ebd70d7dfe
No known key found for this signature in database
GPG key ID: 11A39A1B8C890959
13 changed files with 215 additions and 11 deletions

View file

@ -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;

View file

@ -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() {

View file

@ -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;
}

View file

@ -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<String, JsonObject> 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());
}
}

View file

@ -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
) {
}

View file

@ -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<Projectile> 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);
});

View file

@ -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);
}

View file

@ -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,

View file

@ -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,

View file

@ -0,0 +1,8 @@
{
"Type": "minecraft:arrow",
"Data": {
"damage": "@sbw:damage",
"pickup": 2,
"crit": false
}
}

View file

@ -0,0 +1,6 @@
{
"Type": "minecraft:fireball",
"Data": {
"ExplosionPower": "@sbw:explosion_damage"
}
}

View file

@ -0,0 +1,8 @@
{
"Type": "minecraft:spectral_arrow",
"Data": {
"damage": "@sbw:damage",
"pickup": 2,
"crit": false
}
}

View file

@ -0,0 +1,7 @@
{
"Type": "minecraft:trident",
"Data": {
"pickup": 2,
"crit": false
}
}