diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModPerks.java b/src/main/java/com/atsuishio/superbwarfare/init/ModPerks.java index 9ed9d1cdc..64cbac8a7 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModPerks.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModPerks.java @@ -6,6 +6,7 @@ import com.atsuishio.superbwarfare.perk.Perk; import com.atsuishio.superbwarfare.perk.ammo.*; import com.atsuishio.superbwarfare.perk.damage.*; import com.atsuishio.superbwarfare.perk.functional.*; +import net.minecraft.core.Registry; import net.minecraft.resources.ResourceKey; import net.minecraft.world.effect.MobEffects; import net.neoforged.bus.api.IEventBus; @@ -20,6 +21,8 @@ import net.neoforged.neoforge.registries.RegistryBuilder; @SuppressWarnings("unused") public class ModPerks { + public static final ResourceKey> PERK_KEY = ResourceKey.createRegistryKey(Mod.loc("perk")); + @SubscribeEvent public static void registry(NewRegistryEvent event) { event.create(new RegistryBuilder(ResourceKey.createRegistryKey(Mod.loc("perk")))); diff --git a/src/main/java/com/atsuishio/superbwarfare/item/gun/data/DefaultGunData.java b/src/main/java/com/atsuishio/superbwarfare/item/gun/data/DefaultGunData.java index 6e6308011..d0ac8f7a8 100644 --- a/src/main/java/com/atsuishio/superbwarfare/item/gun/data/DefaultGunData.java +++ b/src/main/java/com/atsuishio/superbwarfare/item/gun/data/DefaultGunData.java @@ -2,6 +2,8 @@ package com.atsuishio.superbwarfare.item.gun.data; import com.google.gson.annotations.SerializedName; +import java.util.List; + public class DefaultGunData { @SerializedName("RecoilX") @@ -72,4 +74,7 @@ public class DefaultGunData { @SerializedName("HeatPerShoot") public double heatPerShoot = 0; + + @SerializedName("AvailablePerks") + public List availablePerks; } diff --git a/src/main/java/com/atsuishio/superbwarfare/item/gun/data/GunData.java b/src/main/java/com/atsuishio/superbwarfare/item/gun/data/GunData.java index 3a3dafeaf..0cd7c772b 100644 --- a/src/main/java/com/atsuishio/superbwarfare/item/gun/data/GunData.java +++ b/src/main/java/com/atsuishio/superbwarfare/item/gun/data/GunData.java @@ -1,5 +1,7 @@ package com.atsuishio.superbwarfare.item.gun.data; +import com.atsuishio.superbwarfare.Mod; +import com.atsuishio.superbwarfare.init.ModPerks; import com.atsuishio.superbwarfare.item.gun.GunItem; import com.atsuishio.superbwarfare.item.gun.data.subdata.*; import com.atsuishio.superbwarfare.item.gun.data.value.*; @@ -21,13 +23,17 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.CustomData; +import net.neoforged.neoforge.registries.DeferredHolder; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.List; import java.util.Objects; import java.util.UUID; public class GunData { + public final ItemStack stack; public final GunItem item; public final CompoundTag tag; @@ -140,9 +146,7 @@ public class GunData { return GunsTool.gunsData.getOrDefault(id, new DefaultGunData()); } - // 枪械本体属性开始 - public double rawDamage() { return defaultGunData().damage; } @@ -428,8 +432,72 @@ public class GunData { reload.setState(ReloadState.NOT_RELOADING); } - // 可持久化属性开始 + private static int getPriority(String s) { + if (s == null || s.isEmpty()) return 2; + if (s.startsWith("@")) return 0; + else if (s.startsWith("!")) return 2; + else return 1; + } + public List availablePerks() { + List availablePerks = new ArrayList<>(); + var perkNames = defaultGunData().availablePerks; + perkNames.sort((s1, s2) -> { + int p1 = getPriority(s1); + int p2 = getPriority(s2); + + if (p1 != p2) { + return Integer.compare(p1, p2); + } else { + return s1.compareTo(s2); + } + }); + + // TODO 正确实现注册项读取 + var perks = new ArrayList>(); + perks.addAll(ModPerks.AMMO_PERKS.getEntries()); + perks.addAll(ModPerks.DAMAGE_PERKS.getEntries()); + perks.addAll(ModPerks.FUNC_PERKS.getEntries()); + + var perkValues = perks.stream().map(DeferredHolder::get).toList(); + var perkKeys = perks.stream().map(perk -> perk.getKey().location().toString()).toList(); + + for (String name : perkNames) { + if (name.startsWith("@")) { + String type = name.substring(1); + switch (type) { + case "Ammo" -> + availablePerks.addAll(perkValues.stream().filter(perk -> perk.type == Perk.Type.AMMO).toList()); + case "Functional" -> + availablePerks.addAll(perkValues.stream().filter(perk -> perk.type == Perk.Type.FUNCTIONAL).toList()); + case "Damage" -> + availablePerks.addAll(perkValues.stream().filter(perk -> perk.type == Perk.Type.DAMAGE).toList()); + } + } else if (name.startsWith("!")) { + String n = name.substring(1); + var index = perkKeys.indexOf(n); + if (index != -1) { + availablePerks.remove(perkValues.get(index)); + } else { + Mod.LOGGER.warn("Perk {} not found", n); + } + } else { + var index = perkKeys.indexOf(name); + if (index != -1) { + availablePerks.add(perkValues.get(index)); + } else { + Mod.LOGGER.warn("Perk {} not found", name); + } + } + } + return availablePerks; + } + + public boolean canApplyPerk(Perk perk) { + return availablePerks().contains(perk); + } + + // 可持久化属性开始 public final IntValue ammo; public final IntValue fireMode; public final IntValue level; @@ -447,7 +515,6 @@ public class GunData { return item.canSwitchScope(stack); } - public final Reload reload; public boolean reloading() { @@ -472,7 +539,6 @@ public class GunData { public final IntValue sensitivity; // 其他子级属性 - public final Bolt bolt; public final Attachment attachment; public final Perks perk; diff --git a/src/main/java/com/atsuishio/superbwarfare/menu/ReforgingTableMenu.java b/src/main/java/com/atsuishio/superbwarfare/menu/ReforgingTableMenu.java index bc7254e65..c554348b6 100644 --- a/src/main/java/com/atsuishio/superbwarfare/menu/ReforgingTableMenu.java +++ b/src/main/java/com/atsuishio/superbwarfare/menu/ReforgingTableMenu.java @@ -224,7 +224,7 @@ public class ReforgingTableMenu extends AbstractContainerMenu { */ public void generateResult() { ItemStack gun = this.container.getItem(INPUT_SLOT); - if (!(gun.getItem() instanceof GunItem gunItem)) { + if (!(gun.getItem() instanceof GunItem)) { return; } @@ -241,7 +241,7 @@ public class ReforgingTableMenu extends AbstractContainerMenu { List.of(ammo, func, damage).forEach(item -> { if (!item.isEmpty() && item.getItem() instanceof PerkItem perkItem - && gunItem.canApplyPerk(perkItem.getPerk()) + && GunData.from(container.getItem(INPUT_SLOT)).canApplyPerk(perkItem.getPerk()) ) { data.perk.set(new PerkInstance(perkItem.getPerk(), (short) switch (perkItem.getPerk().type) { case AMMO -> this.ammoPerkLevel.get(); @@ -472,10 +472,8 @@ public class ReforgingTableMenu extends AbstractContainerMenu { }; return pStack.getItem() instanceof PerkItem perkItem && perkItem.getPerk().type == type - && !container.getItem(INPUT_SLOT).isEmpty() - && container.getItem(INPUT_SLOT).getItem() instanceof GunItem gunItem - && gunItem.canApplyPerk(perkItem.getPerk()) - && container.getItem(slot).isEmpty(); + && !container.getItem(INPUT_SLOT).isEmpty() && container.getItem(INPUT_SLOT).getItem() instanceof GunItem + && GunData.from(container.getItem(INPUT_SLOT)).canApplyPerk(perkItem.getPerk()) && container.getItem(slot).isEmpty(); } public int getMaxStackSize() { diff --git a/src/main/resources/data/superbwarfare/guns/ak_47.json b/src/main/resources/data/superbwarfare/guns/ak_47.json index 817f19dff..d7d434e82 100644 --- a/src/main/resources/data/superbwarfare/guns/ak_47.json +++ b/src/main/resources/data/superbwarfare/guns/ak_47.json @@ -15,5 +15,12 @@ "BypassesArmor": 0.2, "SoundRadius": 14, "RPM": 600, - "AmmoType": "@RifleAmmo" + "AmmoType": "@RifleAmmo", + "AvailablePerks": [ + "superbwarfare:heal_clip", + "superbwarfare:kill_clip", + "@Ammo", + "!superbwarfare:micro_missile", + "!superbwarfare:longer_wire" + ] } \ No newline at end of file