From 43df61a9dd3ebd014dbb020c28100f4b71b78a5d Mon Sep 17 00:00:00 2001 From: Light_Quanta Date: Thu, 27 Mar 2025 04:59:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E6=B7=BB=E5=8A=A0Vector?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/data/c/tags/item/dusts.json | 6 + .../data/c/tags/item/dusts/coal_coke.json | 5 + .../data/c/tags/item/dusts/iron.json | 5 + .../data/c/tags/item/dusts/tungsten.json | 5 + .../resources/data/c/tags/item/ingots.json | 8 + .../data/c/tags/item/ingots/lead.json | 5 + .../data/c/tags/item/ingots/silver.json | 5 + .../data/c/tags/item/ingots/steel.json | 5 + .../data/c/tags/item/ingots/tungsten.json | 5 + .../data/c/tags/item/ore_rates/singular.json | 10 + .../resources/data/c/tags/item/ores.json | 7 + .../resources/data/c/tags/item/ores/lead.json | 6 + .../data/c/tags/item/ores/silver.json | 0 .../data/c/tags/item/ores/tungsten.json | 6 + .../data/c/tags/item/raw_materials.json | 0 .../data/c/tags/item/raw_materials/lead.json | 0 .../c/tags/item/raw_materials/silver.json | 5 + .../c/tags/item/raw_materials/tungsten.json | 0 .../data/c/tags/item/storage_blocks.json | 8 + .../data/c/tags/item/storage_blocks/lead.json | 5 + .../c/tags/item/storage_blocks/silver.json | 5 + .../c/tags/item/storage_blocks/steel.json | 5 + .../c/tags/item/storage_blocks/tungsten.json | 5 + .../minecraft/tags/block/mineable/axe.json | 5 + .../tags/block/mineable/pickaxe.json | 21 + .../minecraft/tags/block/mineable/shovel.json | 5 + .../minecraft/tags/block/needs_iron_tool.json | 11 + .../tags/block/hard_collision.json | 14 + .../tags/block/soft_collision.json | 22 + .../tags/item/ingots/cemented_carbide.json | 9 + .../superbwarfare/tags/item/ingots/steel.json | 9 + .../item/storage_blocks/cemented_carbide.json | 9 + .../tags/item/storage_blocks/steel.json | 0 .../superbwarfare/client/AnimationHelper.java | 73 + .../superbwarfare/client/PoseTool.java | 28 + .../client/layer/VectorLayer.java | 27 + .../client/model/item/VectorItemModel.java | 163 ++ .../renderer/item/VectorItemRenderer.java | 158 ++ .../component/ModDataComponents.java | 6 + .../superbwarfare/datagen/DataGenerators.java | 33 + .../datagen/ModBlockTagProvider.java | 48 + .../datagen/ModItemTagProvider.java | 146 ++ .../event/ClientEventHandler.java | 1513 +++++++++++++++++ .../superbwarfare/event/GunEventHandler.java | 942 ++++++++++ .../superbwarfare/init/ModItems.java | 3 +- .../superbwarfare/init/ModProperties.java | 6 +- .../atsuishio/superbwarfare/init/ModTabs.java | 22 +- .../superbwarfare/item/gun/GunEvents.java | 20 + .../superbwarfare/item/gun/GunItem.java | 440 +++++ .../item/gun/smg/VectorItem.java | 231 +++ .../network/NetworkRegistry.java | 2 + .../network/message/GunsDataMessage.java | 41 + .../network/message/ShootMessage.java | 129 ++ .../superbwarfare/tools/GunsTool.java | 265 +++ .../superbwarfare/tools/InventoryTool.java | 25 +- .../superbwarfare/tools/NBTTool.java | 62 + .../data/superbwarfare/guns/aa_12.json | 17 + .../data/superbwarfare/guns/ak_12.json | 18 + .../data/superbwarfare/guns/ak_47.json | 18 + .../data/superbwarfare/guns/bocek.json | 8 + .../data/superbwarfare/guns/devotion.json | 17 + .../data/superbwarfare/guns/glock_17.json | 15 + .../data/superbwarfare/guns/glock_18.json | 16 + .../data/superbwarfare/guns/hk_416.json | 18 + .../superbwarfare/guns/homemade_shotgun.json | 16 + .../superbwarfare/guns/hunting_rifle.json | 13 + .../data/superbwarfare/guns/javelin.json | 10 + .../data/superbwarfare/guns/k_98.json | 18 + .../data/superbwarfare/guns/m_1911.json | 15 + .../data/superbwarfare/guns/m_4.json | 18 + .../data/superbwarfare/guns/m_60.json | 16 + .../data/superbwarfare/guns/m_79.json | 12 + .../data/superbwarfare/guns/m_870.json | 18 + .../data/superbwarfare/guns/m_98b.json | 18 + .../data/superbwarfare/guns/marlin.json | 16 + .../data/superbwarfare/guns/minigun.json | 12 + .../data/superbwarfare/guns/mk_14.json | 18 + .../data/superbwarfare/guns/mosin_nagant.json | 18 + .../data/superbwarfare/guns/mp_443.json | 15 + .../data/superbwarfare/guns/ntw_20.json | 17 + .../data/superbwarfare/guns/qbz_95.json | 18 + .../data/superbwarfare/guns/rpg.json | 10 + .../data/superbwarfare/guns/rpk.json | 16 + .../guns/secondary_cataclysm.json | 15 + .../data/superbwarfare/guns/sentinel.json | 16 + .../data/superbwarfare/guns/sks.json | 15 + .../data/superbwarfare/guns/svd.json | 17 + .../data/superbwarfare/guns/taser.json | 10 + .../data/superbwarfare/guns/trachelium.json | 14 + .../data/superbwarfare/guns/vector.json | 17 + 90 files changed, 5097 insertions(+), 27 deletions(-) create mode 100644 src/generated/resources/data/c/tags/item/dusts.json create mode 100644 src/generated/resources/data/c/tags/item/dusts/coal_coke.json create mode 100644 src/generated/resources/data/c/tags/item/dusts/iron.json create mode 100644 src/generated/resources/data/c/tags/item/dusts/tungsten.json create mode 100644 src/generated/resources/data/c/tags/item/ingots.json create mode 100644 src/generated/resources/data/c/tags/item/ingots/lead.json create mode 100644 src/generated/resources/data/c/tags/item/ingots/silver.json create mode 100644 src/generated/resources/data/c/tags/item/ingots/steel.json create mode 100644 src/generated/resources/data/c/tags/item/ingots/tungsten.json create mode 100644 src/generated/resources/data/c/tags/item/ore_rates/singular.json create mode 100644 src/generated/resources/data/c/tags/item/ores.json create mode 100644 src/generated/resources/data/c/tags/item/ores/lead.json create mode 100644 src/generated/resources/data/c/tags/item/ores/silver.json create mode 100644 src/generated/resources/data/c/tags/item/ores/tungsten.json create mode 100644 src/generated/resources/data/c/tags/item/raw_materials.json create mode 100644 src/generated/resources/data/c/tags/item/raw_materials/lead.json create mode 100644 src/generated/resources/data/c/tags/item/raw_materials/silver.json create mode 100644 src/generated/resources/data/c/tags/item/raw_materials/tungsten.json create mode 100644 src/generated/resources/data/c/tags/item/storage_blocks.json create mode 100644 src/generated/resources/data/c/tags/item/storage_blocks/lead.json create mode 100644 src/generated/resources/data/c/tags/item/storage_blocks/silver.json create mode 100644 src/generated/resources/data/c/tags/item/storage_blocks/steel.json create mode 100644 src/generated/resources/data/c/tags/item/storage_blocks/tungsten.json create mode 100644 src/generated/resources/data/minecraft/tags/block/mineable/axe.json create mode 100644 src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json create mode 100644 src/generated/resources/data/minecraft/tags/block/mineable/shovel.json create mode 100644 src/generated/resources/data/minecraft/tags/block/needs_iron_tool.json create mode 100644 src/generated/resources/data/superbwarfare/tags/block/hard_collision.json create mode 100644 src/generated/resources/data/superbwarfare/tags/block/soft_collision.json create mode 100644 src/generated/resources/data/superbwarfare/tags/item/ingots/cemented_carbide.json create mode 100644 src/generated/resources/data/superbwarfare/tags/item/ingots/steel.json create mode 100644 src/generated/resources/data/superbwarfare/tags/item/storage_blocks/cemented_carbide.json create mode 100644 src/generated/resources/data/superbwarfare/tags/item/storage_blocks/steel.json create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/AnimationHelper.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/PoseTool.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/layer/VectorLayer.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/model/item/VectorItemModel.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/client/renderer/item/VectorItemRenderer.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/datagen/DataGenerators.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/datagen/ModBlockTagProvider.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/datagen/ModItemTagProvider.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/event/ClientEventHandler.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/event/GunEventHandler.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/item/gun/GunEvents.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/item/gun/GunItem.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/item/gun/smg/VectorItem.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/network/message/GunsDataMessage.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/network/message/ShootMessage.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/tools/GunsTool.java create mode 100644 src/main/java/com/atsuishio/superbwarfare/tools/NBTTool.java create mode 100644 src/main/resources/data/superbwarfare/guns/aa_12.json create mode 100644 src/main/resources/data/superbwarfare/guns/ak_12.json create mode 100644 src/main/resources/data/superbwarfare/guns/ak_47.json create mode 100644 src/main/resources/data/superbwarfare/guns/bocek.json create mode 100644 src/main/resources/data/superbwarfare/guns/devotion.json create mode 100644 src/main/resources/data/superbwarfare/guns/glock_17.json create mode 100644 src/main/resources/data/superbwarfare/guns/glock_18.json create mode 100644 src/main/resources/data/superbwarfare/guns/hk_416.json create mode 100644 src/main/resources/data/superbwarfare/guns/homemade_shotgun.json create mode 100644 src/main/resources/data/superbwarfare/guns/hunting_rifle.json create mode 100644 src/main/resources/data/superbwarfare/guns/javelin.json create mode 100644 src/main/resources/data/superbwarfare/guns/k_98.json create mode 100644 src/main/resources/data/superbwarfare/guns/m_1911.json create mode 100644 src/main/resources/data/superbwarfare/guns/m_4.json create mode 100644 src/main/resources/data/superbwarfare/guns/m_60.json create mode 100644 src/main/resources/data/superbwarfare/guns/m_79.json create mode 100644 src/main/resources/data/superbwarfare/guns/m_870.json create mode 100644 src/main/resources/data/superbwarfare/guns/m_98b.json create mode 100644 src/main/resources/data/superbwarfare/guns/marlin.json create mode 100644 src/main/resources/data/superbwarfare/guns/minigun.json create mode 100644 src/main/resources/data/superbwarfare/guns/mk_14.json create mode 100644 src/main/resources/data/superbwarfare/guns/mosin_nagant.json create mode 100644 src/main/resources/data/superbwarfare/guns/mp_443.json create mode 100644 src/main/resources/data/superbwarfare/guns/ntw_20.json create mode 100644 src/main/resources/data/superbwarfare/guns/qbz_95.json create mode 100644 src/main/resources/data/superbwarfare/guns/rpg.json create mode 100644 src/main/resources/data/superbwarfare/guns/rpk.json create mode 100644 src/main/resources/data/superbwarfare/guns/secondary_cataclysm.json create mode 100644 src/main/resources/data/superbwarfare/guns/sentinel.json create mode 100644 src/main/resources/data/superbwarfare/guns/sks.json create mode 100644 src/main/resources/data/superbwarfare/guns/svd.json create mode 100644 src/main/resources/data/superbwarfare/guns/taser.json create mode 100644 src/main/resources/data/superbwarfare/guns/trachelium.json create mode 100644 src/main/resources/data/superbwarfare/guns/vector.json diff --git a/src/generated/resources/data/c/tags/item/dusts.json b/src/generated/resources/data/c/tags/item/dusts.json new file mode 100644 index 000000000..8cb21df14 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/dusts.json @@ -0,0 +1,6 @@ +{ + "values": [ + "#c:dusts/coal_coke", + "#c:dusts/tungsten" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/dusts/coal_coke.json b/src/generated/resources/data/c/tags/item/dusts/coal_coke.json new file mode 100644 index 000000000..383ee00b8 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/dusts/coal_coke.json @@ -0,0 +1,5 @@ +{ + "values": [ + "superbwarfare:coal_powder" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/dusts/iron.json b/src/generated/resources/data/c/tags/item/dusts/iron.json new file mode 100644 index 000000000..47d2213b1 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/dusts/iron.json @@ -0,0 +1,5 @@ +{ + "values": [ + "superbwarfare:iron_powder" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/dusts/tungsten.json b/src/generated/resources/data/c/tags/item/dusts/tungsten.json new file mode 100644 index 000000000..10d289ef3 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/dusts/tungsten.json @@ -0,0 +1,5 @@ +{ + "values": [ + "superbwarfare:tungsten_powder" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/ingots.json b/src/generated/resources/data/c/tags/item/ingots.json new file mode 100644 index 000000000..403db512b --- /dev/null +++ b/src/generated/resources/data/c/tags/item/ingots.json @@ -0,0 +1,8 @@ +{ + "values": [ + "#c:ingots/lead", + "#c:ingots/steel", + "#c:ingots/tungsten", + "#c:ingots/silver" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/ingots/lead.json b/src/generated/resources/data/c/tags/item/ingots/lead.json new file mode 100644 index 000000000..478dd5d11 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/ingots/lead.json @@ -0,0 +1,5 @@ +{ + "values": [ + "superbwarfare:lead_ingot" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/ingots/silver.json b/src/generated/resources/data/c/tags/item/ingots/silver.json new file mode 100644 index 000000000..e0da7f053 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/ingots/silver.json @@ -0,0 +1,5 @@ +{ + "values": [ + "superbwarfare:silver_ingot" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/ingots/steel.json b/src/generated/resources/data/c/tags/item/ingots/steel.json new file mode 100644 index 000000000..bfc14f6e2 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/ingots/steel.json @@ -0,0 +1,5 @@ +{ + "values": [ + "superbwarfare:steel_ingot" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/ingots/tungsten.json b/src/generated/resources/data/c/tags/item/ingots/tungsten.json new file mode 100644 index 000000000..abc438f31 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/ingots/tungsten.json @@ -0,0 +1,5 @@ +{ + "values": [ + "superbwarfare:tungsten_ingot" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/ore_rates/singular.json b/src/generated/resources/data/c/tags/item/ore_rates/singular.json new file mode 100644 index 000000000..fc3876ad3 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/ore_rates/singular.json @@ -0,0 +1,10 @@ +{ + "values": [ + "superbwarfare:galena_ore", + "superbwarfare:deepslate_galena_ore", + "superbwarfare:scheelite_ore", + "superbwarfare:deepslate_scheelite_ore", + "superbwarfare:silver_ore", + "superbwarfare:deepslate_silver_ore" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/ores.json b/src/generated/resources/data/c/tags/item/ores.json new file mode 100644 index 000000000..f4c04b35e --- /dev/null +++ b/src/generated/resources/data/c/tags/item/ores.json @@ -0,0 +1,7 @@ +{ + "values": [ + "#c:ores/lead", + "#c:ores/tungsten", + "#c:ores/silver" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/ores/lead.json b/src/generated/resources/data/c/tags/item/ores/lead.json new file mode 100644 index 000000000..b8f2be6ac --- /dev/null +++ b/src/generated/resources/data/c/tags/item/ores/lead.json @@ -0,0 +1,6 @@ +{ + "values": [ + "superbwarfare:galena_ore", + "superbwarfare:deepslate_galena_ore" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/ores/silver.json b/src/generated/resources/data/c/tags/item/ores/silver.json new file mode 100644 index 000000000..e69de29bb diff --git a/src/generated/resources/data/c/tags/item/ores/tungsten.json b/src/generated/resources/data/c/tags/item/ores/tungsten.json new file mode 100644 index 000000000..205fed423 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/ores/tungsten.json @@ -0,0 +1,6 @@ +{ + "values": [ + "superbwarfare:scheelite_ore", + "superbwarfare:deepslate_scheelite_ore" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/raw_materials.json b/src/generated/resources/data/c/tags/item/raw_materials.json new file mode 100644 index 000000000..e69de29bb diff --git a/src/generated/resources/data/c/tags/item/raw_materials/lead.json b/src/generated/resources/data/c/tags/item/raw_materials/lead.json new file mode 100644 index 000000000..e69de29bb diff --git a/src/generated/resources/data/c/tags/item/raw_materials/silver.json b/src/generated/resources/data/c/tags/item/raw_materials/silver.json new file mode 100644 index 000000000..6ae4bdd37 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/raw_materials/silver.json @@ -0,0 +1,5 @@ +{ + "values": [ + "superbwarfare:raw_silver" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/raw_materials/tungsten.json b/src/generated/resources/data/c/tags/item/raw_materials/tungsten.json new file mode 100644 index 000000000..e69de29bb diff --git a/src/generated/resources/data/c/tags/item/storage_blocks.json b/src/generated/resources/data/c/tags/item/storage_blocks.json new file mode 100644 index 000000000..b035b8b3f --- /dev/null +++ b/src/generated/resources/data/c/tags/item/storage_blocks.json @@ -0,0 +1,8 @@ +{ + "values": [ + "#c:storage_blocks/lead", + "#c:storage_blocks/steel", + "#c:storage_blocks/tungsten", + "#c:storage_blocks/silver" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/storage_blocks/lead.json b/src/generated/resources/data/c/tags/item/storage_blocks/lead.json new file mode 100644 index 000000000..d9eb998c3 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/storage_blocks/lead.json @@ -0,0 +1,5 @@ +{ + "values": [ + "superbwarfare:lead_block" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/storage_blocks/silver.json b/src/generated/resources/data/c/tags/item/storage_blocks/silver.json new file mode 100644 index 000000000..d6c1bef53 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/storage_blocks/silver.json @@ -0,0 +1,5 @@ +{ + "values": [ + "superbwarfare:silver_block" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/storage_blocks/steel.json b/src/generated/resources/data/c/tags/item/storage_blocks/steel.json new file mode 100644 index 000000000..38f856dd3 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/storage_blocks/steel.json @@ -0,0 +1,5 @@ +{ + "values": [ + "superbwarfare:steel_block" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/c/tags/item/storage_blocks/tungsten.json b/src/generated/resources/data/c/tags/item/storage_blocks/tungsten.json new file mode 100644 index 000000000..ebd65d156 --- /dev/null +++ b/src/generated/resources/data/c/tags/item/storage_blocks/tungsten.json @@ -0,0 +1,5 @@ +{ + "values": [ + "superbwarfare:tungsten_block" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/block/mineable/axe.json b/src/generated/resources/data/minecraft/tags/block/mineable/axe.json new file mode 100644 index 000000000..9b87f3c42 --- /dev/null +++ b/src/generated/resources/data/minecraft/tags/block/mineable/axe.json @@ -0,0 +1,5 @@ +{ + "values": [ + "superbwarfare:barbed_wire" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json b/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json new file mode 100644 index 000000000..8a71eb356 --- /dev/null +++ b/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json @@ -0,0 +1,21 @@ +{ + "values": [ + "superbwarfare:galena_ore", + "superbwarfare:scheelite_ore", + "superbwarfare:deepslate_galena_ore", + "superbwarfare:deepslate_scheelite_ore", + "superbwarfare:dragon_teeth", + "superbwarfare:reforging_table", + "superbwarfare:lead_block", + "superbwarfare:steel_block", + "superbwarfare:tungsten_block", + "superbwarfare:cemented_carbide_block", + "superbwarfare:silver_ore", + "superbwarfare:deepslate_silver_ore", + "superbwarfare:silver_block", + "superbwarfare:jump_pad", + "superbwarfare:container", + "superbwarfare:charging_station", + "superbwarfare:fumo_25" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/block/mineable/shovel.json b/src/generated/resources/data/minecraft/tags/block/mineable/shovel.json new file mode 100644 index 000000000..340083688 --- /dev/null +++ b/src/generated/resources/data/minecraft/tags/block/mineable/shovel.json @@ -0,0 +1,5 @@ +{ + "values": [ + "superbwarfare:sandbag" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/block/needs_iron_tool.json b/src/generated/resources/data/minecraft/tags/block/needs_iron_tool.json new file mode 100644 index 000000000..b01142b0f --- /dev/null +++ b/src/generated/resources/data/minecraft/tags/block/needs_iron_tool.json @@ -0,0 +1,11 @@ +{ + "values": [ + "superbwarfare:galena_ore", + "superbwarfare:scheelite_ore", + "superbwarfare:deepslate_galena_ore", + "superbwarfare:deepslate_scheelite_ore", + "superbwarfare:dragon_teeth", + "superbwarfare:silver_ore", + "superbwarfare:deepslate_silver_ore" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/superbwarfare/tags/block/hard_collision.json b/src/generated/resources/data/superbwarfare/tags/block/hard_collision.json new file mode 100644 index 000000000..fcb4be304 --- /dev/null +++ b/src/generated/resources/data/superbwarfare/tags/block/hard_collision.json @@ -0,0 +1,14 @@ +{ + "values": [ + "#minecraft:logs", + "#minecraft:planks", + "#c:glass_blocks", + "#c:glass_panes", + "#minecraft:wooden_slabs", + "#minecraft:wooden_stairs", + "minecraft:ice", + "minecraft:frosted_ice", + "minecraft:packed_ice", + "minecraft:blue_ice" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/superbwarfare/tags/block/soft_collision.json b/src/generated/resources/data/superbwarfare/tags/block/soft_collision.json new file mode 100644 index 000000000..29c12762b --- /dev/null +++ b/src/generated/resources/data/superbwarfare/tags/block/soft_collision.json @@ -0,0 +1,22 @@ +{ + "values": [ + "#minecraft:leaves", + "#minecraft:fences", + "#minecraft:fence_gates", + "#minecraft:doors", + "#minecraft:trapdoors", + "#minecraft:walls", + "minecraft:cactus", + "minecraft:bamboo", + "minecraft:melon", + "minecraft:pumpkin", + "minecraft:hay_block", + "minecraft:bell", + "minecraft:chain", + "minecraft:snow_block", + "minecraft:cobweb", + "minecraft:mushroom_stem", + "minecraft:brown_mushroom_block", + "minecraft:red_mushroom_block" + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/superbwarfare/tags/item/ingots/cemented_carbide.json b/src/generated/resources/data/superbwarfare/tags/item/ingots/cemented_carbide.json new file mode 100644 index 000000000..74f9889b7 --- /dev/null +++ b/src/generated/resources/data/superbwarfare/tags/item/ingots/cemented_carbide.json @@ -0,0 +1,9 @@ +{ + "values": [ + "superbwarfare:cemented_carbide_ingot", + { + "id": "dreamaticvoyage:hqss_bread_ingot", + "required": false + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/superbwarfare/tags/item/ingots/steel.json b/src/generated/resources/data/superbwarfare/tags/item/ingots/steel.json new file mode 100644 index 000000000..03097e41e --- /dev/null +++ b/src/generated/resources/data/superbwarfare/tags/item/ingots/steel.json @@ -0,0 +1,9 @@ +{ + "values": [ + "#c:ingots/steel", + { + "id": "dreamaticvoyage:fukamizu_bread_ingot", + "required": false + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/superbwarfare/tags/item/storage_blocks/cemented_carbide.json b/src/generated/resources/data/superbwarfare/tags/item/storage_blocks/cemented_carbide.json new file mode 100644 index 000000000..f523d8d4f --- /dev/null +++ b/src/generated/resources/data/superbwarfare/tags/item/storage_blocks/cemented_carbide.json @@ -0,0 +1,9 @@ +{ + "values": [ + "superbwarfare:cemented_carbide_block", + { + "id": "dreamaticvoyage:hqss_bread_bricks", + "required": false + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/superbwarfare/tags/item/storage_blocks/steel.json b/src/generated/resources/data/superbwarfare/tags/item/storage_blocks/steel.json new file mode 100644 index 000000000..e69de29bb diff --git a/src/main/java/com/atsuishio/superbwarfare/client/AnimationHelper.java b/src/main/java/com/atsuishio/superbwarfare/client/AnimationHelper.java new file mode 100644 index 000000000..c9c7c9473 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/AnimationHelper.java @@ -0,0 +1,73 @@ +package com.atsuishio.superbwarfare.client; + +import com.atsuishio.superbwarfare.event.ClientEventHandler; +import com.atsuishio.superbwarfare.tools.GunsTool; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.util.FastColor; +import net.minecraft.util.Mth; +import net.minecraft.world.item.ItemStack; +import software.bernie.geckolib.animation.AnimationProcessor; +import software.bernie.geckolib.cache.object.GeoBone; + +public class AnimationHelper { + + public static void renderPartOverBone(ModelPart model, GeoBone bone, PoseStack stack, VertexConsumer buffer, int packedLightIn, int packedOverlayIn, float alpha) { + renderPartOverBone(model, bone, stack, buffer, packedLightIn, packedOverlayIn, 1.0f, 1.0f, 1.0f, alpha); + } + + public static void renderPartOverBone(ModelPart model, GeoBone bone, PoseStack stack, VertexConsumer buffer, int packedLightIn, int packedOverlayIn, float r, float g, float b, float a) { + setupModelFromBone(model, bone); + var color = FastColor.ARGB32.color((int) (a * 255), (int) (r * 255), (int) (g * 255), (int) (b * 255)); + model.render(stack, buffer, packedLightIn, packedOverlayIn, color); + } + + public static void setupModelFromBone(ModelPart model, GeoBone bone) { + model.setPos(bone.getPivotX(), bone.getPivotY(), bone.getPivotZ()); + model.xRot = 0.0f; + model.yRot = 0.0f; + model.zRot = 0.0f; + } + + public static void renderPartOverBone2(ModelPart model, GeoBone bone, PoseStack stack, VertexConsumer buffer, int packedLightIn, int packedOverlayIn, float alpha) { + renderPartOverBone2(model, bone, stack, buffer, packedLightIn, packedOverlayIn, 1.0f, 1.0f, 1.0f, alpha); + } + + public static void renderPartOverBone2(ModelPart model, GeoBone bone, PoseStack stack, VertexConsumer buffer, int packedLightIn, int packedOverlayIn, float r, float g, float b, float a) { + setupModelFromBone2(model, bone); + var color = FastColor.ARGB32.color((int) (a * 255), (int) (r * 255), (int) (g * 255), (int) (b * 255)); + model.render(stack, buffer, packedLightIn, packedOverlayIn, color); + } + + public static void setupModelFromBone2(ModelPart model, GeoBone bone) { + model.setPos(bone.getPivotX(), bone.getPivotY() + 7, bone.getPivotZ()); + model.xRot = 0.0f; + model.yRot = 180 * Mth.DEG_TO_RAD; + model.zRot = 180 * Mth.DEG_TO_RAD; + } + + public static void handleShellsAnimation(AnimationProcessor animationProcessor, float x, float y) { + GeoBone shell1 = animationProcessor.getBone("shell1"); + GeoBone shell2 = animationProcessor.getBone("shell2"); + GeoBone shell3 = animationProcessor.getBone("shell3"); + GeoBone shell4 = animationProcessor.getBone("shell4"); + GeoBone shell5 = animationProcessor.getBone("shell5"); + + ClientEventHandler.handleShells(x, y, shell1, shell2, shell3, shell4, shell5); + } + + public static void handleReloadShakeAnimation(ItemStack stack, GeoBone main, GeoBone camera, float roll, float pitch) { + if (GunsTool.getGunIntTag(stack, "ReloadTime") > 0) { + main.setRotX(roll * main.getRotX()); + main.setRotY(roll * main.getRotY()); + main.setRotZ(roll * main.getRotZ()); + main.setPosX(pitch * main.getPosX()); + main.setPosY(pitch * main.getPosY()); + main.setPosZ(pitch * main.getPosZ()); + camera.setRotX(roll * camera.getRotX()); + camera.setRotY(roll * camera.getRotY()); + camera.setRotZ(roll * camera.getRotZ()); + } + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/PoseTool.java b/src/main/java/com/atsuishio/superbwarfare/client/PoseTool.java new file mode 100644 index 000000000..42ceeb188 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/PoseTool.java @@ -0,0 +1,28 @@ +package com.atsuishio.superbwarfare.client; + +import com.atsuishio.superbwarfare.tools.GunsTool; +import com.atsuishio.superbwarfare.tools.NBTTool; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +public class PoseTool { + + public static HumanoidModel.ArmPose pose(LivingEntity entityLiving, InteractionHand hand, ItemStack stack) { + var tag = NBTTool.getOrCreateTag(stack); + if (tag.getBoolean("is_empty_reloading") + || tag.getBoolean("is_normal_reloading") + || GunsTool.getGunBooleanTag(stack, "Reloading") + || GunsTool.getGunBooleanTag(stack, "Charging")) { + return HumanoidModel.ArmPose.CROSSBOW_CHARGE; + } else if (entityLiving.isSprinting() && entityLiving.onGround() && entityLiving.getPersistentData().getDouble("noRun") == 0) { + return HumanoidModel.ArmPose.CROSSBOW_CHARGE; + } else { + return HumanoidModel.ArmPose.BOW_AND_ARROW; + } + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/layer/VectorLayer.java b/src/main/java/com/atsuishio/superbwarfare/client/layer/VectorLayer.java new file mode 100644 index 000000000..c59b9f0a5 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/layer/VectorLayer.java @@ -0,0 +1,27 @@ +package com.atsuishio.superbwarfare.client.layer; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.item.gun.smg.VectorItem; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.resources.ResourceLocation; +import software.bernie.geckolib.cache.object.BakedGeoModel; +import software.bernie.geckolib.renderer.GeoRenderer; +import software.bernie.geckolib.renderer.layer.GeoRenderLayer; + +public class VectorLayer extends GeoRenderLayer { + private static final ResourceLocation LAYER = ModUtils.loc("textures/item/vector_e.png"); + + public VectorLayer(GeoRenderer entityRenderer) { + super(entityRenderer); + } + + @Override + public void render(PoseStack poseStack, VectorItem animatable, BakedGeoModel bakedModel, RenderType renderType, MultiBufferSource bufferSource, VertexConsumer buffer, float partialTick, int packedLight, int packedOverlay) { + RenderType glowRenderType = RenderType.eyes(LAYER); + getRenderer().reRender(getDefaultBakedModel(animatable), poseStack, bufferSource, animatable, glowRenderType, bufferSource.getBuffer(glowRenderType), partialTick, packedLight, OverlayTexture.NO_OVERLAY, 0xFFFFFFFF); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/model/item/VectorItemModel.java b/src/main/java/com/atsuishio/superbwarfare/client/model/item/VectorItemModel.java new file mode 100644 index 000000000..4f21c9cef --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/model/item/VectorItemModel.java @@ -0,0 +1,163 @@ +package com.atsuishio.superbwarfare.client.model.item; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.client.AnimationHelper; +import com.atsuishio.superbwarfare.event.ClientEventHandler; +import com.atsuishio.superbwarfare.init.ModTags; +import com.atsuishio.superbwarfare.item.gun.smg.VectorItem; +import com.atsuishio.superbwarfare.tools.GunsTool; +import com.atsuishio.superbwarfare.tools.NBTTool; +import net.minecraft.client.Minecraft; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import software.bernie.geckolib.animation.AnimationState; +import software.bernie.geckolib.cache.object.GeoBone; +import software.bernie.geckolib.model.GeoModel; + +import static com.atsuishio.superbwarfare.event.ClientEventHandler.isProne; + +public class VectorItemModel extends GeoModel { + + public static float fireRotY = 0f; + public static float fireRotZ = 0f; + public static float rotXBipod = 0f; + public static float rotXSight = 0f; + + @Override + public ResourceLocation getAnimationResource(VectorItem animatable) { + return ModUtils.loc("animations/vector.animation.json"); + } + + @Override + public ResourceLocation getModelResource(VectorItem animatable) { + return ModUtils.loc("geo/vector.geo.json"); + } + + @Override + public ResourceLocation getTextureResource(VectorItem animatable) { + return ModUtils.loc("textures/item/vector.png"); + } + + @Override + public void setCustomAnimations(VectorItem animatable, long instanceId, AnimationState animationState) { + GeoBone gun = getAnimationProcessor().getBone("bone"); + GeoBone scope = getAnimationProcessor().getBone("Scope1"); + GeoBone cross1 = getAnimationProcessor().getBone("Cross1"); + GeoBone kmj = getAnimationProcessor().getBone("kuaimanji"); + GeoBone sight1fold = getAnimationProcessor().getBone("SightFold1"); + GeoBone sight2fold = getAnimationProcessor().getBone("SightFold2"); + + Player player = Minecraft.getInstance().player; + if (player == null) return; + ItemStack stack = player.getMainHandItem(); + if (!stack.is(ModTags.Items.GUN)) return; + + int mode = GunsTool.getGunIntTag(stack, "FireMode"); + if (mode == 0) { + kmj.setRotX(-120 * Mth.DEG_TO_RAD); + } + if (mode == 1) { + kmj.setRotX(-60 * Mth.DEG_TO_RAD); + } + if (mode == 2) { + kmj.setRotX(0); + } + + float times = 0.6f * (float) Math.min(Minecraft.getInstance().getTimer().getGameTimeDeltaTicks(), 0.8); + double zt = ClientEventHandler.zoomTime; + double zp = ClientEventHandler.zoomPos; + double zpz = ClientEventHandler.zoomPosZ; + double swayX = ClientEventHandler.swayX; + double swayY = ClientEventHandler.swayY; + float moveRotZ = (float) ClientEventHandler.moveRotZ; + float movePosX = (float) ClientEventHandler.movePosX; + float movePosY = (float) ClientEventHandler.movePosY; + double mph = ClientEventHandler.movePosHorizon; + double vY = ClientEventHandler.velocityY; + double turnRotX = ClientEventHandler.turnRot[0]; + double turnRotY = ClientEventHandler.turnRot[1]; + double turnRotZ = ClientEventHandler.turnRot[2]; + double fpz = ClientEventHandler.firePosZ * 20 * times; + double fp = ClientEventHandler.firePos; + double fr = ClientEventHandler.fireRot; + + int type = GunsTool.getAttachmentType(stack, GunsTool.AttachmentType.SCOPE); + + float posY = switch (type) { + case 1 -> 0.74f; + case 2 -> 0.12f; + default -> 0.07f; + }; + + gun.setPosX(2.356f * (float) zp); + gun.setPosY(posY * (float) zp - (float) (0.2f * zpz)); + gun.setPosZ((type == 2 ? 6 : 5) * (float) zp + (float) (0.3f * zpz)); + gun.setScaleZ(1f - (0.5f * (float) zp)); + scope.setScaleZ(1f - (0.2f * (float) zp)); + + NBTTool.getOrCreateTag(stack).putBoolean("HoloHidden", gun.getPosX() <= 2); + + GeoBone shen; + if (zt < 0.5) { + shen = getAnimationProcessor().getBone("fireRootNormal"); + } else { + shen = switch (type) { + case 0 -> getAnimationProcessor().getBone("fireRoot0"); + case 1 -> getAnimationProcessor().getBone("fireRoot1"); + case 2 -> getAnimationProcessor().getBone("fireRoot2"); + default -> getAnimationProcessor().getBone("fireRootNormal"); + }; + } + + fireRotY = (float) Mth.lerp(0.5f * times, fireRotY, 0.2f * ClientEventHandler.recoilHorizon * fpz); + fireRotZ = (float) Mth.lerp(2f * times, fireRotZ, (0.2f + 0.3 * fpz) * ClientEventHandler.recoilHorizon); + + shen.setPosX(-0.4f * (float) (ClientEventHandler.recoilHorizon * (0.5 + 0.4 * ClientEventHandler.fireSpread))); + shen.setPosY((float) (0.15f * fp + 0.18f * fr)); + shen.setPosZ((float) (0.375 * fp + 0.44f * fr + 0.75 * fpz)); + shen.setRotX((float) (0.01f * fp + 0.05f * fr + 0.01f * fpz)); + shen.setRotY(fireRotY); + shen.setRotZ(fireRotZ); + + shen.setPosX((float) (shen.getPosX() * (1 - 0.1 * zt))); + shen.setPosY((float) (shen.getPosY() * (-1 + 0.8 * zt))); + shen.setPosZ((float) (shen.getPosZ() * (1 - 0.1 * zt))); + shen.setRotX((float) (shen.getRotX() * (1 - (type == 3 ? 0.96 : type == 1 ? 0.8 : 0.9) * zt))); + shen.setRotY((float) (shen.getRotY() * (1 - (type == 3 ? 0.95 : 0.9) * zt))); + shen.setRotZ((float) (shen.getRotZ() * (1 - 0.4 * zt))); + + // TODO cross hair overlay gun rot +// CrossHairOverlay.gunRot = shen.getRotZ(); + + cross1.setPosY(-0.25f * (float) fpz); + + rotXSight = Mth.lerp(1.5f * times, rotXSight, type == 0 ? 0 : 90); + sight1fold.setRotX(rotXSight * Mth.DEG_TO_RAD); + sight2fold.setRotX(rotXSight * Mth.DEG_TO_RAD); + + GeoBone l = getAnimationProcessor().getBone("l"); + GeoBone r = getAnimationProcessor().getBone("r"); + rotXBipod = Mth.lerp(1.5f * times, rotXBipod, isProne(player) ? -90 : 0); + l.setRotX(rotXBipod * Mth.DEG_TO_RAD); + r.setRotX(rotXBipod * Mth.DEG_TO_RAD); + + GeoBone root = getAnimationProcessor().getBone("root"); + root.setPosX((float) (movePosX + 20 * ClientEventHandler.drawTime + 9.3f * mph)); + root.setPosY((float) (swayY + movePosY - 40 * ClientEventHandler.drawTime - 2f * vY)); + root.setRotX((float) (swayX - Mth.DEG_TO_RAD * 60 * ClientEventHandler.drawTime + Mth.DEG_TO_RAD * turnRotX - 0.15f * vY)); + root.setRotY((float) (0.2f * movePosX + Mth.DEG_TO_RAD * 300 * ClientEventHandler.drawTime + Mth.DEG_TO_RAD * turnRotY)); + root.setRotZ((float) (0.2f * movePosX + moveRotZ + Mth.DEG_TO_RAD * 90 * ClientEventHandler.drawTime + 2.7f * mph + Mth.DEG_TO_RAD * turnRotZ)); + + GeoBone camera = getAnimationProcessor().getBone("camera"); + GeoBone main = getAnimationProcessor().getBone("0"); + + float numR = (float) (1 - 0.92 * zt); + float numP = (float) (1 - 0.88 * zt); + + AnimationHelper.handleReloadShakeAnimation(stack, main, camera, numR, numP); + ClientEventHandler.shake(Mth.RAD_TO_DEG * camera.getRotX(), Mth.RAD_TO_DEG * camera.getRotY(), Mth.RAD_TO_DEG * camera.getRotZ()); + AnimationHelper.handleShellsAnimation(getAnimationProcessor(), 1.2f, 0.45f); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/renderer/item/VectorItemRenderer.java b/src/main/java/com/atsuishio/superbwarfare/client/renderer/item/VectorItemRenderer.java new file mode 100644 index 000000000..5b10aad52 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/renderer/item/VectorItemRenderer.java @@ -0,0 +1,158 @@ +package com.atsuishio.superbwarfare.client.renderer.item; + +import com.atsuishio.superbwarfare.client.AnimationHelper; +import com.atsuishio.superbwarfare.client.layer.VectorLayer; +import com.atsuishio.superbwarfare.client.model.item.VectorItemModel; +import com.atsuishio.superbwarfare.event.ClientEventHandler; +import com.atsuishio.superbwarfare.init.ModTags; +import com.atsuishio.superbwarfare.item.gun.smg.VectorItem; +import com.atsuishio.superbwarfare.tools.GunsTool; +import com.atsuishio.superbwarfare.tools.NBTTool; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.PlayerModel; +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.player.PlayerRenderer; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemDisplayContext; +import net.minecraft.world.item.ItemStack; +import software.bernie.geckolib.cache.object.BakedGeoModel; +import software.bernie.geckolib.cache.object.GeoBone; +import software.bernie.geckolib.renderer.GeoItemRenderer; +import software.bernie.geckolib.util.RenderUtil; + +import java.util.HashSet; +import java.util.Set; + +public class VectorItemRenderer extends GeoItemRenderer { + + public VectorItemRenderer() { + super(new VectorItemModel()); + this.addRenderLayer(new VectorLayer(this)); + } + + @Override + public RenderType getRenderType(VectorItem animatable, ResourceLocation texture, MultiBufferSource bufferSource, float partialTick) { + return RenderType.entityTranslucent(getTextureLocation(animatable)); + } + + private static final float SCALE_RECIPROCAL = 1.0f / 16.0f; + protected boolean renderArms = false; + protected MultiBufferSource currentBuffer; + protected RenderType renderType; + public ItemDisplayContext transformType; + protected VectorItem animatable; + private final Set hiddenBones = new HashSet<>(); + + @Override + public void renderByItem(ItemStack stack, ItemDisplayContext transformType, PoseStack matrixStack, MultiBufferSource bufferIn, int combinedLightIn, int p_239207_6_) { + this.transformType = transformType; + if (this.animatable != null) + this.animatable.getTransformType(transformType); + super.renderByItem(stack, transformType, matrixStack, bufferIn, combinedLightIn, p_239207_6_); + } + + @Override + public void actuallyRender(PoseStack matrixStackIn, VectorItem animatable, BakedGeoModel model, RenderType type, MultiBufferSource renderTypeBuffer, VertexConsumer vertexBuilder, boolean isRenderer, float partialTicks, int packedLightIn, + int packedOverlayIn, int color) { + this.currentBuffer = renderTypeBuffer; + this.renderType = type; + this.animatable = animatable; + super.actuallyRender(matrixStackIn, animatable, model, type, renderTypeBuffer, vertexBuilder, isRenderer, partialTicks, packedLightIn, packedOverlayIn, color); + if (this.renderArms) { + this.renderArms = false; + } + } + + @Override + public void renderRecursively(PoseStack stack, VectorItem animatable, GeoBone bone, RenderType type, MultiBufferSource buffer, VertexConsumer bufferIn, boolean isReRender, float partialTick, int packedLightIn, int packedOverlayIn, int color) { + Minecraft mc = Minecraft.getInstance(); + String name = bone.getName(); + boolean renderingArms = false; + if (name.equals("Lefthand") || name.equals("Righthand")) { + bone.setHidden(true); + renderingArms = true; + } else { + bone.setHidden(this.hiddenBones.contains(name)); + } + + Player player = mc.player; + if (player == null) return; + ItemStack itemStack = player.getMainHandItem(); + if (!itemStack.is(ModTags.Items.GUN)) return; + + if (name.equals("Cross1")) { + bone.setHidden(NBTTool.getOrCreateTag(itemStack).getBoolean("HoloHidden") + || !ClientEventHandler.zoom + || GunsTool.getAttachmentType(itemStack, GunsTool.AttachmentType.SCOPE) != 1); + } + + if (name.equals("Cross2")) { + bone.setHidden(NBTTool.getOrCreateTag(itemStack).getBoolean("HoloHidden") + || !ClientEventHandler.zoom + || GunsTool.getAttachmentType(itemStack, GunsTool.AttachmentType.SCOPE) != 2); + } + + if (name.equals("tuoxin")) { + bone.setHidden(GunsTool.getAttachmentType(itemStack, GunsTool.AttachmentType.STOCK) == 0); + } + + if (name.equals("flare")) { + if (ClientEventHandler.firePosTimer == 0 || ClientEventHandler.firePosTimer > 0.5 || GunsTool.getAttachmentType(itemStack, GunsTool.AttachmentType.BARREL) == 2) { + bone.setHidden(true); + } else { + bone.setHidden(false); + bone.setScaleX((float) (0.55 + 0.5 * (Math.random() - 0.5))); + bone.setScaleY((float) (0.55 + 0.5 * (Math.random() - 0.5))); + bone.setRotZ((float) (0.5 * (Math.random() - 0.5))); + } + } + + // TODO handle gun attachments +// ItemModelHelper.handleGunAttachments(bone, itemStack, name); + + if (this.transformType.firstPerson() && renderingArms) { + AbstractClientPlayer localPlayer = mc.player; + + if (localPlayer == null) { + return; + } + + PlayerRenderer playerRenderer = (PlayerRenderer) mc.getEntityRenderDispatcher().getRenderer(localPlayer); + PlayerModel model = playerRenderer.getModel(); + stack.pushPose(); + + RenderUtil.translateMatrixToBone(stack, bone); + RenderUtil.translateToPivotPoint(stack, bone); + RenderUtil.rotateMatrixAroundBone(stack, bone); + RenderUtil.scaleMatrixForBone(stack, bone); + RenderUtil.translateAwayFromPivotPoint(stack, bone); + ResourceLocation loc = localPlayer.getSkin().texture(); + VertexConsumer armBuilder = this.currentBuffer.getBuffer(RenderType.entitySolid(loc)); + VertexConsumer sleeveBuilder = this.currentBuffer.getBuffer(RenderType.entityTranslucent(loc)); + if (name.equals("Lefthand")) { + stack.translate(-1.0f * SCALE_RECIPROCAL, 2.0f * SCALE_RECIPROCAL, 0.0f); + AnimationHelper.renderPartOverBone(model.leftArm, bone, stack, armBuilder, packedLightIn, OverlayTexture.NO_OVERLAY, 1); + AnimationHelper.renderPartOverBone(model.leftSleeve, bone, stack, sleeveBuilder, packedLightIn, OverlayTexture.NO_OVERLAY, 1); + } else { + stack.translate(SCALE_RECIPROCAL, 2.0f * SCALE_RECIPROCAL, 0.0f); + AnimationHelper.renderPartOverBone(model.rightArm, bone, stack, armBuilder, packedLightIn, OverlayTexture.NO_OVERLAY, 1); + AnimationHelper.renderPartOverBone(model.rightSleeve, bone, stack, sleeveBuilder, packedLightIn, OverlayTexture.NO_OVERLAY, 1); + } + + this.currentBuffer.getBuffer(this.renderType); + stack.popPose(); + } + super.renderRecursively(stack, animatable, bone, type, buffer, bufferIn, isReRender, partialTick, packedLightIn, packedOverlayIn, color); + } + + @Override + public ResourceLocation getTextureLocation(VectorItem instance) { + return super.getTextureLocation(instance); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/component/ModDataComponents.java b/src/main/java/com/atsuishio/superbwarfare/component/ModDataComponents.java index cb79f2400..c57162ae7 100644 --- a/src/main/java/com/atsuishio/superbwarfare/component/ModDataComponents.java +++ b/src/main/java/com/atsuishio/superbwarfare/component/ModDataComponents.java @@ -7,6 +7,7 @@ import com.mojang.serialization.Codec; import net.minecraft.core.BlockPos; import net.minecraft.core.component.DataComponentType; import net.minecraft.core.registries.Registries; +import net.minecraft.nbt.CompoundTag; import net.neoforged.bus.api.IEventBus; import net.neoforged.neoforge.registries.DeferredHolder; import net.neoforged.neoforge.registries.DeferredRegister; @@ -32,6 +33,11 @@ public class ModDataComponents { builder -> builder.persistent(AmmoBoxInfo.CODEC) ); + public static final DeferredHolder, DataComponentType> GUN_DATA = register( + "gun_data", + builder -> builder.persistent(CompoundTag.CODEC) + ); + private static DeferredHolder, DataComponentType> register(String name, UnaryOperator> builderOperator) { return DATA_COMPONENT_TYPES.register(name, () -> builderOperator.apply(DataComponentType.builder()).build()); } diff --git a/src/main/java/com/atsuishio/superbwarfare/datagen/DataGenerators.java b/src/main/java/com/atsuishio/superbwarfare/datagen/DataGenerators.java new file mode 100644 index 000000000..95a69024f --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/datagen/DataGenerators.java @@ -0,0 +1,33 @@ +package com.atsuishio.superbwarfare.datagen; + +import com.atsuishio.superbwarfare.ModUtils; +import net.minecraft.core.HolderLookup; +import net.minecraft.data.DataGenerator; +import net.minecraft.data.PackOutput; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.common.data.ExistingFileHelper; +import net.neoforged.neoforge.data.event.GatherDataEvent; + +import java.util.concurrent.CompletableFuture; + +@EventBusSubscriber(modid = ModUtils.MODID, bus = EventBusSubscriber.Bus.MOD) +public class DataGenerators { + + @SubscribeEvent + public static void gatherData(GatherDataEvent event) { + DataGenerator generator = event.getGenerator(); + PackOutput packOutput = generator.getPackOutput(); + CompletableFuture lookupProvider = event.getLookupProvider(); + ExistingFileHelper existingFileHelper = event.getExistingFileHelper(); + +// generator.addProvider(event.includeServer(), ModLootTableProvider.create(packOutput)); +// generator.addProvider(event.includeServer(), new ModRecipeProvider(packOutput)); +// generator.addProvider(event.includeServer(), new ModBlockStateProvider(packOutput, existingFileHelper)); +// generator.addProvider(event.includeServer(), new ModItemModelProvider(packOutput, existingFileHelper)); + ModBlockTagProvider tagProvider = generator.addProvider(event.includeServer(), new ModBlockTagProvider(packOutput, lookupProvider, existingFileHelper)); + generator.addProvider(event.includeServer(), new ModItemTagProvider(packOutput, lookupProvider, tagProvider.contentsGetter(), existingFileHelper)); +// generator.addProvider(event.includeServer(), new ModDamageTypeTagProvider(packOutput, lookupProvider, existingFileHelper)); +// generator.addProvider(event.includeServer(), new ModAdvancementProvider(packOutput, existingFileHelper)); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/datagen/ModBlockTagProvider.java b/src/main/java/com/atsuishio/superbwarfare/datagen/ModBlockTagProvider.java new file mode 100644 index 000000000..be7bb7e5c --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/datagen/ModBlockTagProvider.java @@ -0,0 +1,48 @@ +package com.atsuishio.superbwarfare.datagen; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.init.ModBlocks; +import com.atsuishio.superbwarfare.init.ModTags; +import net.minecraft.core.HolderLookup; +import net.minecraft.data.PackOutput; +import net.minecraft.tags.BlockTags; +import net.minecraft.world.level.block.Blocks; +import net.neoforged.neoforge.common.Tags; +import net.neoforged.neoforge.common.data.BlockTagsProvider; +import net.neoforged.neoforge.common.data.ExistingFileHelper; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nullable; +import java.util.concurrent.CompletableFuture; + +@SuppressWarnings("unchecked") +public class ModBlockTagProvider extends BlockTagsProvider { + + public ModBlockTagProvider(PackOutput output, CompletableFuture lookupProvider, @Nullable ExistingFileHelper existingFileHelper) { + super(output, lookupProvider, ModUtils.MODID, existingFileHelper); + } + + @Override + protected void addTags(HolderLookup.@NotNull Provider pProvider) { + this.tag(BlockTags.NEEDS_IRON_TOOL).add(ModBlocks.GALENA_ORE.get(), ModBlocks.SCHEELITE_ORE.get(), + ModBlocks.DEEPSLATE_GALENA_ORE.get(), ModBlocks.DEEPSLATE_SCHEELITE_ORE.get(), ModBlocks.DRAGON_TEETH.get(), + ModBlocks.SILVER_ORE.get(), ModBlocks.DEEPSLATE_SILVER_ORE.get()); + + this.tag(BlockTags.MINEABLE_WITH_AXE).add(ModBlocks.BARBED_WIRE.get()); + this.tag(BlockTags.MINEABLE_WITH_PICKAXE).add(ModBlocks.GALENA_ORE.get(), ModBlocks.SCHEELITE_ORE.get(), + ModBlocks.DEEPSLATE_GALENA_ORE.get(), ModBlocks.DEEPSLATE_SCHEELITE_ORE.get(), ModBlocks.DRAGON_TEETH.get(), + ModBlocks.REFORGING_TABLE.get(), ModBlocks.LEAD_BLOCK.get(), ModBlocks.STEEL_BLOCK.get(), ModBlocks.TUNGSTEN_BLOCK.get(), + ModBlocks.CEMENTED_CARBIDE_BLOCK.get(), ModBlocks.SILVER_ORE.get(), ModBlocks.DEEPSLATE_SILVER_ORE.get(), + ModBlocks.SILVER_BLOCK.get(), ModBlocks.JUMP_PAD.get(), ModBlocks.CONTAINER.get(), ModBlocks.CHARGING_STATION.get(), + ModBlocks.FUMO_25.get()); + this.tag(BlockTags.MINEABLE_WITH_SHOVEL).add(ModBlocks.SANDBAG.get()); + + this.tag(ModTags.Blocks.SOFT_COLLISION) + .addTags(BlockTags.LEAVES, BlockTags.FENCES, BlockTags.FENCE_GATES, BlockTags.DOORS, BlockTags.TRAPDOORS, BlockTags.WALLS) + .add(Blocks.CACTUS, Blocks.BAMBOO, Blocks.MELON, Blocks.PUMPKIN, Blocks.HAY_BLOCK, Blocks.BELL, Blocks.CHAIN, Blocks.SNOW_BLOCK, + Blocks.COBWEB, Blocks.MUSHROOM_STEM, Blocks.BROWN_MUSHROOM_BLOCK, Blocks.RED_MUSHROOM_BLOCK); + this.tag(ModTags.Blocks.HARD_COLLISION) + .addTags(BlockTags.LOGS, BlockTags.PLANKS, Tags.Blocks.GLASS_BLOCKS, Tags.Blocks.GLASS_PANES, BlockTags.WOODEN_SLABS, BlockTags.WOODEN_STAIRS) + .add(Blocks.ICE, Blocks.FROSTED_ICE, Blocks.PACKED_ICE, Blocks.BLUE_ICE); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/datagen/ModItemTagProvider.java b/src/main/java/com/atsuishio/superbwarfare/datagen/ModItemTagProvider.java new file mode 100644 index 000000000..e8ffba843 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/datagen/ModItemTagProvider.java @@ -0,0 +1,146 @@ +package com.atsuishio.superbwarfare.datagen; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.init.ModItems; +import com.atsuishio.superbwarfare.init.ModTags; +import net.minecraft.core.HolderLookup; +import net.minecraft.data.PackOutput; +import net.minecraft.data.tags.ItemTagsProvider; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.ItemTags; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Block; +import net.neoforged.neoforge.common.Tags; +import net.neoforged.neoforge.common.data.ExistingFileHelper; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nullable; +import java.util.concurrent.CompletableFuture; + +public class ModItemTagProvider extends ItemTagsProvider { + + public ModItemTagProvider(PackOutput packOutput, CompletableFuture providerCompletableFuture, + CompletableFuture> tagLookupCompletableFuture, @Nullable ExistingFileHelper existingFileHelper) { + super(packOutput, providerCompletableFuture, tagLookupCompletableFuture, ModUtils.MODID, existingFileHelper); + } + + @SuppressWarnings("unchecked") + @Override + protected void addTags(HolderLookup.@NotNull Provider pProvider) { + this.tag(Tags.Items.DUSTS).addTags(cTag("dusts/coal_coke"), cTag("dusts/tungsten")); + this.tag(cTag("dusts/coal_coke")).add(ModItems.COAL_POWDER.get()); + this.tag(cTag("dusts/iron")).add(ModItems.IRON_POWDER.get()); + this.tag(cTag("dusts/tungsten")).add(ModItems.TUNGSTEN_POWDER.get()); + + this.tag(Tags.Items.INGOTS).addTags(cTag("ingots/lead"), cTag("ingots/steel"), cTag("ingots/tungsten"), cTag("ingots/silver")); + this.tag(cTag("ingots/lead")).add(ModItems.LEAD_INGOT.get()); + this.tag(cTag("ingots/steel")).add(ModItems.STEEL_INGOT.get()); + this.tag(cTag("ingots/tungsten")).add(ModItems.TUNGSTEN_INGOT.get()); + this.tag(cTag("ingots/silver")).add(ModItems.SILVER_INGOT.get()); + + this.tag(ModTags.Items.INGOTS_STEEL).addTag(cTag("ingots/steel")) + .addOptional(ResourceLocation.fromNamespaceAndPath("dreamaticvoyage", "fukamizu_bread_ingot")); + this.tag(ModTags.Items.INGOTS_CEMENTED_CARBIDE).add(ModItems.CEMENTED_CARBIDE_INGOT.get()) + .addOptional(ResourceLocation.fromNamespaceAndPath("dreamaticvoyage", "hqss_bread_ingot")); + + this.tag(Tags.Items.STORAGE_BLOCKS).addTags(cTag("storage_blocks/lead"), cTag("storage_blocks/steel"), cTag("storage_blocks/tungsten"), cTag("storage_blocks/silver")); + this.tag(cTag("storage_blocks/lead")).add(ModItems.LEAD_BLOCK.get()); + this.tag(cTag("storage_blocks/steel")).add(ModItems.STEEL_BLOCK.get()); + this.tag(cTag("storage_blocks/tungsten")).add(ModItems.TUNGSTEN_BLOCK.get()); + this.tag(cTag("storage_blocks/silver")).add(ModItems.SILVER_BLOCK.get()); + + this.tag(ModTags.Items.STORAGE_BLOCK_STEEL).addTag(cTag("storage_blocks/steel")) + .addOptional(ResourceLocation.fromNamespaceAndPath("dreamaticvoyage", "fukamizu_bread_bricks")); + this.tag(ModTags.Items.STORAGE_BLOCK_CEMENTED_CARBIDE).add(ModItems.CEMENTED_CARBIDE_BLOCK.get()) + .addOptional(ResourceLocation.fromNamespaceAndPath("dreamaticvoyage", "hqss_bread_bricks")); + + this.tag(Tags.Items.ORES).addTags(cTag("ores/lead"), cTag("ores/tungsten"), cTag("ores/silver")); + this.tag(cTag("ores/lead")).add(ModItems.GALENA_ORE.get(), ModItems.DEEPSLATE_GALENA_ORE.get()); + this.tag(cTag("ores/tungsten")).add(ModItems.SCHEELITE_ORE.get(), ModItems.DEEPSLATE_SCHEELITE_ORE.get()); + this.tag(cTag("ores/silver")).add(ModItems.SILVER_ORE.get(), ModItems.DEEPSLATE_SILVER_ORE.get()); + + this.tag(Tags.Items.RAW_MATERIALS).addTags(cTag("raw_materials/lead"), cTag("raw_materials/tungsten"), cTag("raw_materials/silver")); + this.tag(cTag("raw_materials/lead")).add(ModItems.GALENA.get()); + this.tag(cTag("raw_materials/tungsten")).add(ModItems.SCHEELITE.get()); + this.tag(cTag("raw_materials/silver")).add(ModItems.RAW_SILVER.get()); + + this.tag(Tags.Items.ORE_RATES_SINGULAR).add(ModItems.GALENA_ORE.get(), ModItems.DEEPSLATE_GALENA_ORE.get(), + ModItems.SCHEELITE_ORE.get(), ModItems.DEEPSLATE_SCHEELITE_ORE.get(), + ModItems.SILVER_ORE.get(), ModItems.DEEPSLATE_SILVER_ORE.get()); + + this.tag(Tags.Items.ORES_IN_GROUND_STONE).add(ModItems.GALENA_ORE.get(), ModItems.SCHEELITE_ORE.get(), ModItems.SILVER_ORE.get()); + this.tag(Tags.Items.ORES_IN_GROUND_DEEPSLATE).add(ModItems.DEEPSLATE_GALENA_ORE.get(), ModItems.DEEPSLATE_SCHEELITE_ORE.get(), ModItems.DEEPSLATE_SILVER_ORE.get()); + + this.tag(cTag("plates")).addTags(cTag("plates/copper")); + this.tag(cTag("plates/copper")).add(ModItems.COPPER_PLATE.get()); + + ModItems.GUNS.getEntries().forEach(registryObject -> this.tag(ModTags.Items.GUN).add(registryObject.get())); + + this.tag(ModTags.Items.SMG).add(ModItems.VECTOR.get()); + +// this.tag(ModTags.Items.HANDGUN).add(ModItems.TRACHELIUM.get(), ModItems.GLOCK_17.get(), ModItems.GLOCK_18.get(), ModItems.M_1911.get(), ModItems.MP_443.get()); + +// this.tag(ModTags.Items.RIFLE).add(ModItems.M_4.get(), ModItems.HK_416.get(), ModItems.SKS.get(), +// ModItems.MK_14.get(), ModItems.MARLIN.get(), ModItems.AK_47.get(), ModItems.AK_12.get(), ModItems.QBZ_95.get()); + +// this.tag(ModTags.Items.SNIPER_RIFLE).add(ModItems.HUNTING_RIFLE.get(), ModItems.SENTINEL.get(), +// ModItems.SVD.get(), ModItems.M_98B.get(), ModItems.K_98.get(), ModItems.MOSIN_NAGANT.get()); + +// this.tag(ModTags.Items.HEAVY_WEAPON).add(ModItems.NTW_20.get()); + +// this.tag(ModTags.Items.SHOTGUN).add(ModItems.HOMEMADE_SHOTGUN.get(), ModItems.M_870.get(), ModItems.AA_12.get()); + +// this.tag(ModTags.Items.MACHINE_GUN).add(ModItems.MINIGUN.get(), ModItems.DEVOTION.get(), ModItems.RPK.get(), ModItems.M_60.get()); + + this.tag(ModTags.Items.NORMAL_GUN).add( +// ModItems.HOMEMADE_SHOTGUN.get(), ModItems.AK_47.get(), ModItems.AK_12.get(), ModItems.SVD.get(), ModItems.M_60.get(), ModItems.MK_14.get(), + ModItems.VECTOR.get() +// ModItems.SKS.get(), ModItems.RPK.get(), ModItems.HK_416.get(), ModItems.AA_12.get(), ModItems.M_4.get(), ModItems.DEVOTION.get(), ModItems.TRACHELIUM.get(), +// ModItems.HUNTING_RIFLE.get(), ModItems.NTW_20.get(), ModItems.M_98B.get(), ModItems.SENTINEL.get(), ModItems.M_870.get(), ModItems.MARLIN.get(), ModItems.GLOCK_17.get(), +// ModItems.GLOCK_18.get(), ModItems.M_1911.get(), ModItems.QBZ_95.get(), ModItems.K_98.get(), ModItems.MOSIN_NAGANT.get(), ModItems.MP_443.get() + ); + + this.tag(ModTags.Items.USE_HANDGUN_AMMO).add( +// ModItems.GLOCK_17.get(), ModItems.GLOCK_18.get(), ModItems.M_1911.get(), + ModItems.VECTOR.get() +// ModItems.MP_443.get() + ); + +// this.tag(ModTags.Items.USE_RIFLE_AMMO).add(ModItems.M_4.get(), ModItems.HK_416.get(), ModItems.SKS.get(), ModItems.MINIGUN.get(), ModItems.DEVOTION.get(), ModItems.M_60.get(), +// ModItems.MK_14.get(), ModItems.MARLIN.get(), ModItems.AK_47.get(), ModItems.AK_12.get(), ModItems.QBZ_95.get(), ModItems.RPK.get(), ModItems.TRACHELIUM.get()); + +// this.tag(ModTags.Items.USE_SHOTGUN_AMMO).add(ModItems.HOMEMADE_SHOTGUN.get(), ModItems.M_870.get(), ModItems.AA_12.get()); + +// this.tag(ModTags.Items.USE_SNIPER_AMMO).add(ModItems.HUNTING_RIFLE.get(), ModItems.SENTINEL.get(), +// ModItems.SVD.get(), ModItems.M_98B.get(), ModItems.K_98.get(), ModItems.MOSIN_NAGANT.get()); + +// this.tag(ModTags.Items.USE_HEAVY_AMMO).add(ModItems.NTW_20.get()); + +// this.tag(ModTags.Items.LAUNCHER).add(ModItems.M_79.get(), ModItems.RPG.get(), ModItems.JAVELIN.get(), ModItems.SECONDARY_CATACLYSM.get()); + +// this.tag(ModTags.Items.REVOLVER).add(ModItems.TRACHELIUM.get()); + +// this.tag(ModTags.Items.MILITARY_ARMOR).add(ModItems.RU_CHEST_6B43.get(), ModItems.US_CHEST_IOTV.get()); + + this.tag(ModTags.Items.BLUEPRINT).addTags(ModTags.Items.COMMON_BLUEPRINT, ModTags.Items.RARE_BLUEPRINT, ModTags.Items.EPIC_BLUEPRINT, + ModTags.Items.LEGENDARY_BLUEPRINT, ModTags.Items.CANNON_BLUEPRINT); + this.tag(ModTags.Items.COMMON_BLUEPRINT).add(ModItems.GLOCK_17_BLUEPRINT.get(), ModItems.MP_443_BLUEPRINT.get(), ModItems.MARLIN_BLUEPRINT.get(), + ModItems.TASER_BLUEPRINT.get(), ModItems.M_1911_BLUEPRINT.get()); + this.tag(ModTags.Items.RARE_BLUEPRINT).add(ModItems.GLOCK_18_BLUEPRINT.get(), ModItems.M_79_BLUEPRINT.get(), ModItems.M_4_BLUEPRINT.get(), + ModItems.SKS_BLUEPRINT.get(), ModItems.M_870_BLUEPRINT.get(), ModItems.AK_47_BLUEPRINT.get(), ModItems.K_98_BLUEPRINT.get(), + ModItems.MOSIN_NAGANT_BLUEPRINT.get(), ModItems.M_2_HB_BLUEPRINT.get()); + this.tag(ModTags.Items.EPIC_BLUEPRINT).add(ModItems.TRACHELIUM_BLUEPRINT.get(), ModItems.HUNTING_RIFLE_BLUEPRINT.get(), ModItems.RPG_BLUEPRINT.get(), + ModItems.BOCEK_BLUEPRINT.get(), ModItems.HK_416_BLUEPRINT.get(), ModItems.RPK_BLUEPRINT.get(), ModItems.VECTOR_BLUEPRINT.get(), + ModItems.MK_14_BLUEPRINT.get(), ModItems.M_60_BLUEPRINT.get(), ModItems.SVD_BLUEPRINT.get(), ModItems.M_98B_BLUEPRINT.get(), + ModItems.AK_12_BLUEPRINT.get(), ModItems.DEVOTION_BLUEPRINT.get(), ModItems.QBZ_95_BLUEPRINT.get()); +// this.tag(ModTags.Items.LEGENDARY_BLUEPRINT).add(ModItems.AA_12_BLUEPRINT.get(), ModItems.NTW_20_BLUEPRINT.get(), ModItems.MINIGUN_BLUEPRINT.get(), +// ModItems.SENTINEL_BLUEPRINT.get(), ModItems.JAVELIN_BLUEPRINT.get(), ModItems.SECONDARY_CATACLYSM_BLUEPRINT.get(), ModItems.MK_42_BLUEPRINT.get(), +// ModItems.MLE_1934_BLUEPRINT.get(), ModItems.ANNIHILATOR_BLUEPRINT.get()); +// this.tag(ModTags.Items.CANNON_BLUEPRINT).add(ModItems.MK_42_BLUEPRINT.get(), ModItems.MLE_1934_BLUEPRINT.get(), ModItems.ANNIHILATOR_BLUEPRINT.get()); + } + + public static TagKey cTag(String name) { + return ItemTags.create(ResourceLocation.fromNamespaceAndPath("c", name)); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/event/ClientEventHandler.java b/src/main/java/com/atsuishio/superbwarfare/event/ClientEventHandler.java new file mode 100644 index 000000000..5c8ffc515 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/event/ClientEventHandler.java @@ -0,0 +1,1513 @@ +package com.atsuishio.superbwarfare.event; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.capability.ModCapabilities; +import com.atsuishio.superbwarfare.config.client.DisplayConfig; +import com.atsuishio.superbwarfare.init.*; +import com.atsuishio.superbwarfare.item.gun.GunItem; +import com.atsuishio.superbwarfare.network.message.LaserShootMessage; +import com.atsuishio.superbwarfare.network.message.ShootMessage; +import com.atsuishio.superbwarfare.tools.*; +import com.atsuishio.superbwarfare.tools.animation.AnimationCurves; +import net.minecraft.client.CameraType; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.commands.arguments.EntityAnchorArgument; +import net.minecraft.core.BlockPos; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.npc.AbstractVillager; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.ClipContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.event.*; +import net.neoforged.neoforge.network.PacketDistributor; +import net.neoforged.neoforge.network.handling.IPayloadContext; +import org.lwjgl.glfw.GLFW; +import software.bernie.geckolib.cache.object.GeoBone; + +import java.util.List; + +@EventBusSubscriber(modid = ModUtils.MODID, bus = EventBusSubscriber.Bus.GAME, value = Dist.CLIENT) +public class ClientEventHandler { + + public static double zoomTime = 0; + public static double zoomPos = 0; + public static double zoomPosZ = 0; + public static double swayTime = 0; + public static double swayX = 0; + public static double swayY = 0; + public static double moveXTime = 0; + public static double moveYTime = 0; + public static double movePosX = 0; + public static double movePosY = 0; + public static double moveRotZ = 0; + public static double movePosHorizon = 0; + public static double velocityY = 0; + + public static double[] turnRot = {0, 0, 0}; + public static double[] cameraRot = {0, 0, 0}; + + public static double fireRecoilTime = 0; + public static double firePosTimer = 0; + public static double fireRotTimer = 0; + public static double firePos = 0; + public static double firePosZ = 0; + public static double fireRot = 0; + + public static double recoilTime = 0; + + public static double recoilHorizon = 0; + public static double recoilY = 0; + + public static double droneFov = 1; + public static double droneFovLerp = 1; + + public static double breathTime = 0; + public static double fov = 0; + public static double pullTimer = 0; + public static double bowTimer = 0; + public static double handTimer = 0; + public static double pullPos = 0; + public static double bowPos = 0; + public static double handPos = 0; + public static double gunSpread = 0; + public static double fireSpread = 0; + public static double cantFireTime = 0; + public static double lookDistance = 0; + public static double cameraLocation = 0.6; + + public static double drawTime = 1; + + public static int shellIndex = 0; + public static double[] shellIndexTime = {0, 0, 0, 0, 0, 0}; + public static double[] randomShell = {0, 0, 0}; + + public static double customZoom = 0; + public static MillisTimer clientTimer = new MillisTimer(); + public static MillisTimer clientTimerVehicle = new MillisTimer(); + + public static boolean holdFire = false; + + public static boolean zoom = false; + public static boolean holdFireVehicle = false; + + public static boolean zoomVehicle = false; + public static int burstFireSize = 0; + + public static int customRpm = 0; + + public static double chamberRot = 0; + public static double actionMove = 0; + + public static int miniGunRot = 0; + + public static double revolverPreTime = 0; + public static double revolverWheelPreTime = 0; + + public static double shakeTime = 0; + public static double shakeRadius = 0; + public static double shakeAmplitude = 0; + public static double[] shakePos = {0, 0, 0}; + public static double shakeType = 0; + public static int lungeAttack; + public static int lungeDraw; + public static int gunMelee; + public static int lungeSprint; + public static Entity entity; + + public static int dismountCountdown = 0; + public static int aimVillagerCountdown = 0; + + public static CameraType lastCameraType; + + public static float cameraPitch; + public static float cameraYaw; + public static float cameraRoll; + + + @SubscribeEvent + public static void handleWeaponTurn(RenderHandEvent event) { + LocalPlayer player = Minecraft.getInstance().player; + if (player == null) { + return; + } + float xRotOffset = Mth.lerp(event.getPartialTick(), player.xBobO, player.xBob); + float yRotOffset = Mth.lerp(event.getPartialTick(), player.yBobO, player.yBob); + float xRot = player.getViewXRot(event.getPartialTick()) - xRotOffset; + float yRot = player.getViewYRot(event.getPartialTick()) - yRotOffset; + turnRot[0] = Mth.clamp(0.05 * xRot, -5, 5) * (1 - 0.75 * zoomTime); + turnRot[1] = Mth.clamp(0.05 * yRot, -10, 10) * (1 - 0.75 * zoomTime); + turnRot[2] = Mth.clamp(0.1 * yRot, -10, 10) * (1 - zoomTime); + } + + private static boolean notInGame() { + Minecraft mc = Minecraft.getInstance(); + if (mc.player == null) return true; + if (mc.getOverlay() != null) return true; + if (mc.screen != null) return true; + if (!mc.mouseHandler.isMouseGrabbed()) return true; + return !mc.isWindowActive(); + } + + public static boolean isFreeCam(Player player) { + // TODO Vehicle +// return player.getVehicle() instanceof VehicleEntity vehicle && vehicle.allowFreeCam() && Minecraft.getInstance().options.getCameraType() == CameraType.FIRST_PERSON && ModKeyMappings.FREE_CAMERA.isDown(); + return Minecraft.getInstance().options.getCameraType() == CameraType.FIRST_PERSON && ModKeyMappings.FREE_CAMERA.isDown(); + } + + private static boolean revolverPre() { + Player player = Minecraft.getInstance().player; + if (player == null) return false; + ItemStack stack = player.getMainHandItem(); + if (!stack.is(ModTags.Items.REVOLVER)) { + return true; + } else if (stack.is(ModTags.Items.REVOLVER) && (NBTTool.getOrCreateTag(stack).getBoolean("DA") || NBTTool.getOrCreateTag(stack).getBoolean("canImmediatelyShoot"))) { + return true; + } else { + return revolverPreTime >= 1; + } + } + + private static boolean isMoving() { + Player player = Minecraft.getInstance().player; + return Minecraft.getInstance().options.keyLeft.isDown() + || Minecraft.getInstance().options.keyRight.isDown() + || Minecraft.getInstance().options.keyUp.isDown() + || Minecraft.getInstance().options.keyDown.isDown() + || (player != null && player.isSprinting()); + } + + @SubscribeEvent + public static void handleClientTick(ClientTickEvent.Post event) { + LocalPlayer player = Minecraft.getInstance().player; + if (player == null) { + return; + } + ItemStack stack = player.getMainHandItem(); +// if (stack.is(ModItems.MINIGUN.get())) { +// if (holdFire || zoom) { +// miniGunRot = Math.min(miniGunRot + 5, 21); +// float rpm = (float) GunsTool.getGunIntTag(stack, "RPM", 0) / 3600; +// player.playSound(ModSounds.MINIGUN_ROT.get(), 1, 0.7f + rpm); +// } +// } + +// if (notInGame() && !ClickHandler.switchZoom) { +// zoom = false; +// } + + isProne(player); + beamShoot(player, stack); + handleLungeAttack(player, stack); + handleGunMelee(player, stack); + +// if (player.getVehicle() instanceof MobileVehicleEntity mobileVehicle && mobileVehicle.getFirstPassenger() == player && notInGame()) { +// ModUtils.PACKET_HANDLER.sendToServer(new VehicleMovementMessage(0, false)); +// ModUtils.PACKET_HANDLER.sendToServer(new VehicleMovementMessage(1, false)); +// ModUtils.PACKET_HANDLER.sendToServer(new VehicleMovementMessage(2, false)); +// ModUtils.PACKET_HANDLER.sendToServer(new VehicleMovementMessage(3, false)); +// ModUtils.PACKET_HANDLER.sendToServer(new VehicleMovementMessage(4, false)); +// ModUtils.PACKET_HANDLER.sendToServer(new VehicleMovementMessage(5, false)); +// ModUtils.PACKET_HANDLER.sendToServer(new VehicleMovementMessage(6, false)); +// } + + handleVariableDecrease(); + aimAtVillager(player); + } + + private static void handleVariableDecrease() { + if (miniGunRot > 0) { + miniGunRot--; + } + + if (dismountCountdown > 0) { + dismountCountdown--; + } + + if (aimVillagerCountdown > 0) { + aimVillagerCountdown--; + } + } + + public static boolean isProne(Player player) { + Level level = player.level(); + if (player.getBbHeight() <= 1) return true; + + return player.isCrouching() && level.getBlockState(BlockPos.containing(player.getX() + 0.7 * player.getLookAngle().x, player.getY() + 0.5, player.getZ() + 0.7 * player.getLookAngle().z)).canOcclude() + && !level.getBlockState(BlockPos.containing(player.getX() + 0.7 * player.getLookAngle().x, player.getY() + 1.5, player.getZ() + 0.7 * player.getLookAngle().z)).canOcclude(); + } + + public static void handleGunMelee(Player player, ItemStack stack) { + if (stack.getItem() instanceof GunItem gunItem) { + if (gunItem.hasMeleeAttack(stack) && gunMelee == 0 && drawTime < 0.01 + && ModKeyMappings.MELEE.isDown() +// && !(player.getVehicle() instanceof ArmedVehicleEntity iArmedVehicle && iArmedVehicle.banHand(player)) + && !holdFireVehicle + && !notInGame() +// && !player.getCapability(ModVariables.PLAYER_VARIABLES_CAPABILITY, null).orElse(new ModVariables.PlayerVariables()).edit + && !(NBTTool.getOrCreateTag(stack).getBoolean("is_normal_reloading") || NBTTool.getOrCreateTag(stack).getBoolean("is_empty_reloading")) + && !GunsTool.getGunBooleanTag(stack, "Reloading") + && !player.getCooldowns().isOnCooldown(stack.getItem()) + && !GunsTool.getGunBooleanTag(stack, "Charging")) { + gunMelee = 36; + cantFireTime = 40; + player.playSound(SoundEvents.PLAYER_ATTACK_SWEEP, 1f, 1); + } + if (gunMelee == 22) { +// Entity lookingEntity = TraceTool.findMeleeEntity(player, player.getEntityReach()); +// if (lookingEntity != null) { +// ModUtils.PACKET_HANDLER.sendToServer(new MeleeAttackMessage(lookingEntity.getUUID())); +// } + } + } + + if (gunMelee > 0) { + gunMelee--; + } + } + + public static void handleLungeAttack(Player player, ItemStack stack) { +// if (stack.is(ModItems.LUNGE_MINE.get()) && lungeAttack == 0 && lungeDraw == 0 && holdFire) { +// lungeAttack = 36; +// holdFire = false; +// player.playSound(SoundEvents.PLAYER_ATTACK_SWEEP, 1f, 1); +// } +// +// if (stack.is(ModItems.LUNGE_MINE.get()) && ((lungeAttack >= 18 && lungeAttack <= 21) || lungeSprint > 0)) { +// Entity lookingEntity = TraceTool.findLookingEntity(player, player.getEntityReach() + 1.5); +// +// BlockHitResult result = player.level().clip(new ClipContext(player.getEyePosition(), player.getEyePosition().add(player.getLookAngle().scale(player.getBlockReach() + 0.5)), +// ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)); +// +// Vec3 looking = Vec3.atLowerCornerOf(player.level().clip(new ClipContext(player.getEyePosition(), player.getEyePosition().add(player.getLookAngle().scale(player.getBlockReach() + 0.5)), ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)).getBlockPos()); +// BlockState blockState = player.level().getBlockState(BlockPos.containing(looking.x(), looking.y(), looking.z())); +// +// if (lookingEntity != null) { +// ModUtils.PACKET_HANDLER.sendToServer(new LungeMineAttackMessage(0, lookingEntity.getUUID(), result)); +// lungeSprint = 0; +// lungeAttack = 0; +// lungeDraw = 30; +// } else if ((blockState.canOcclude() || blockState.getBlock() instanceof DoorBlock || blockState.getBlock() instanceof CrossCollisionBlock || blockState.getBlock() instanceof BellBlock) && lungeSprint == 0) { +// ModUtils.PACKET_HANDLER.sendToServer(new LungeMineAttackMessage(1, player.getUUID(), result)); +// lungeSprint = 0; +// lungeAttack = 0; +// lungeDraw = 30; +// } +// } + + if (lungeSprint > 0) { + lungeSprint--; + } + + if (lungeAttack > 0) { + lungeAttack--; + } + + if (lungeDraw > 0) { + lungeDraw--; + } + } + + @SubscribeEvent + public static void handleWeaponFire(RenderFrameEvent.Pre event) { + ClientLevel level = Minecraft.getInstance().level; + Player player = Minecraft.getInstance().player; + + if (player == null) return; + if (level == null) return; + + if (notInGame()) { + holdFire = false; + } + + ItemStack stack = player.getMainHandItem(); + if (!stack.is(ModTags.Items.GUN)) { + clientTimer.stop(); + fireSpread = 0; + gunSpread = 0; + return; + } + +// var perk = PerkHelper.getPerkByType(stack, Perk.Type.AMMO); + int mode = GunsTool.getGunIntTag(stack, "FireMode"); + + // 精准度 + float times = (float) Math.min(Minecraft.getInstance().getTimer().getGameTimeDeltaTicks(), 0.8); + + double basicDev = GunsTool.getGunDoubleTag(stack, "Spread"); + double walk = isMoving() ? 0.3 * basicDev : 0; + double sprint = player.isSprinting() ? 0.25 * basicDev : 0; + double crouching = player.isCrouching() ? -0.15 * basicDev : 0; + double prone = isProne(player) ? -0.3 * basicDev : 0; + double jump = player.onGround() ? 0 * basicDev : 0.35 * basicDev; + double ride = player.onGround() ? -0.25 * basicDev : 0; + + double zoomSpread; + + if (stack.is(ModTags.Items.SNIPER_RIFLE) || stack.is(ModTags.Items.HEAVY_WEAPON)) { + zoomSpread = 1 - (0.995 * zoomTime); + } else if (stack.is(ModTags.Items.SHOTGUN)) { +// if (perk instanceof AmmoPerk ammoPerk && ammoPerk.slug) { +// zoomSpread = 1 - (0.85 * zoomTime); +// } else { +// zoomSpread = 1 - (0.25 * zoomTime); +// } +// } else if (stack.is(ModItems.MINIGUN.get())) { +// zoomSpread = 1 - (0.25 * zoomTime); + } else { + zoomSpread = 1 - (0.9 * zoomTime); + } + +// double spread = stack.is(ModTags.Items.SHOTGUN) || stack.is(ModItems.MINIGUN.get()) ? 1.2 * zoomSpread * (basicDev + 0.2 * (walk + sprint + crouching + prone + jump + ride) + fireSpread) : zoomSpread * (0.7 * basicDev + walk + sprint + crouching + prone + jump + ride + 0.8 * fireSpread); + +// gunSpread = Mth.lerp(0.14 * times, gunSpread, spread); + + // 开火部分 + double weight = GunsTool.getGunDoubleTag(stack, "Weight") + GunsTool.getGunDoubleTag(stack, "CustomWeight"); + double speed = 1 - (0.04 * weight); + + if (player.getPersistentData().getDouble("noRun") == 0 && player.isSprinting() && !zoom) { + cantFireTime = Mth.clamp(cantFireTime + 3 * times, 0, 24); + } else { + cantFireTime = Mth.clamp(cantFireTime - 6 * speed * times, 0, 40); + } + + int rpm = GunsTool.getGunIntTag(stack, "RPM", 0) + customRpm; + if (rpm == 0) { + rpm = 600; + } + + if (GunsTool.getPerkIntTag(stack, "DesperadoTimePost") > 0) { +// int perkLevel = PerkHelper.getItemPerkLevel(ModPerks.DESPERADO.get(), stack); +// rpm *= (int) (1.285 + 0.015 * perkLevel); + } + + double rps = (double) rpm / 60; + + // cooldown in ms + int cooldown = (int) (1000 / rps); + + //左轮类 + if (clientTimer.getProgress() == 0 && stack.is(ModTags.Items.REVOLVER) && ((holdFire && !NBTTool.getOrCreateTag(stack).getBoolean("DA")) + || (GunsTool.getGunIntTag(stack, "BoltActionTick") < 7 && GunsTool.getGunIntTag(stack, "BoltActionTick") > 2) || NBTTool.getOrCreateTag(stack).getBoolean("canImmediatelyShoot"))) { + revolverPreTime = Mth.clamp(revolverPreTime + 0.3 * times, 0, 1); + revolverWheelPreTime = Mth.clamp(revolverWheelPreTime + 0.32 * times, 0, revolverPreTime > 0.7 ? 1 : 0.55); + } else if (!NBTTool.getOrCreateTag(stack).getBoolean("DA") && !NBTTool.getOrCreateTag(stack).getBoolean("canImmediatelyShoot")) { + revolverPreTime = Mth.clamp(revolverPreTime - 1.2 * times, 0, 1); + } + + var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE); + + if ((holdFire || burstFireSize > 0) + // todo ban hand +// && !(player.getVehicle() instanceof ArmedVehicleEntity iArmedVehicle && iArmedVehicle.banHand(player)) + && !holdFireVehicle + && (stack.is(ModTags.Items.NORMAL_GUN) + && cantFireTime == 0 + && drawTime < 0.01 + && cap != null && !cap.edit + && !notInGame() + && (!(NBTTool.getOrCreateTag(stack).getBoolean("is_normal_reloading") || NBTTool.getOrCreateTag(stack).getBoolean("is_empty_reloading")) + && !GunsTool.getGunBooleanTag(stack, "Reloading") + && !GunsTool.getGunBooleanTag(stack, "Charging") + && GunsTool.getGunIntTag(stack, "Ammo", 0) > 0 + && !player.getCooldowns().isOnCooldown(stack.getItem()) + && !GunsTool.getGunBooleanTag(stack, "NeedBoltAction", false) + && revolverPre()) + || ( + // todo minigun +// stack.is(ModItems.MINIGUN.get()) && + !player.isSprinting() + && NBTTool.getOrCreateTag(stack).getDouble("overheat") == 0 + && !player.getCooldowns().isOnCooldown(stack.getItem()) && miniGunRot >= 20 + && (cap != null && cap.rifleAmmo > 0 || InventoryTool.hasCreativeAmmoBox(player)) + ))) { + if (mode == 0) { + if (clientTimer.getProgress() == 0) { + clientTimer.start(); + shootClient(player); + } + } else { + if (!clientTimer.started()) { + clientTimer.start(); + // 首发瞬间发射 + clientTimer.setProgress((cooldown + 1)); + } + + if (clientTimer.getProgress() >= cooldown) { + shootClient(player); + clientTimer.setProgress((clientTimer.getProgress() - cooldown)); + } + } + + if (notInGame()) { + clientTimer.stop(); + } + + } else { + if (mode != 0 && clientTimer.getProgress() >= cooldown) { + clientTimer.stop(); + } + fireSpread = 0; + } + + gunPartMove(times); + + if (mode == 0 && clientTimer.getProgress() >= cooldown) { + clientTimer.stop(); + } + +// if (stack.getItem() == ModItems.DEVOTION.get() && (GunNBTTool.getOrCreateTag(stack).getBoolean("is_normal_reloading") || GunNBTTool.getOrCreateTag(stack).getBoolean("is_empty_reloading"))) { +// customRpm = 0; +// } + } + + public static void beamShoot(Player player, ItemStack stack) { + if (stack.is(ModItems.BEAM_TEST.get()) && player.getUseItem() == stack) { + Entity lookingEntity = TraceTool.laserfindLookingEntity(player, 512); + + if (player.isCrouching()) { + Entity seekingEntity = SeekTool.seekLivingEntity(player, player.level(), 64, 32); + if (seekingEntity != null && seekingEntity.isAlive()) { + player.lookAt(EntityAnchorArgument.Anchor.EYES, seekingEntity.getEyePosition()); + } + } + + if (lookingEntity == null) { + return; + } + + boolean canAttack = lookingEntity != player && !(lookingEntity instanceof Player player_ && (player_.isCreative() || player_.isSpectator())) + && (!player.isAlliedTo(lookingEntity) || lookingEntity.getTeam() == null || lookingEntity.getTeam().getName().equals("TDM")); + + if (canAttack) { + PacketDistributor.sendToServer(new LaserShootMessage(0, lookingEntity.getUUID(), TraceTool.laserHeadshot)); + } + } + } + + public static void shootClient(Player player) { + ItemStack stack = player.getMainHandItem(); + if (stack.is(ModTags.Items.NORMAL_GUN)) { + if (GunsTool.getGunIntTag(stack, "Ammo", 0) > 0) { + int mode = GunsTool.getGunIntTag(stack, "FireMode"); + if (mode != 2) { + holdFire = false; + } + + if (mode == 1) { + if (GunsTool.getGunIntTag(stack, "Ammo", 0) == 1) { + burstFireSize = 1; + } + if (burstFireSize == 1) { + cantFireTime = 40; + } + } + + if (burstFireSize > 0) { + burstFireSize--; + } + +// if (stack.is(ModItems.DEVOTION.get())) { +// int perkLevel = PerkHelper.getItemPerkLevel(ModPerks.TURBO_CHARGER.get(), stack); +// customRpm = Math.min(customRpm + 15 + ((perkLevel > 0 ? 5 : 0) + 3 * perkLevel), 500); +// } + +// if (stack.getItem() == ModItems.SENTINEL.get()) { +// chamberRot = 1; +// } +// +// if (stack.getItem() == ModItems.NTW_20.get()) { +// actionMove = 1; +// } + + // 判断是否为栓动武器(BoltActionTime > 0),并在开火后给一个需要上膛的状态 + if (GunsTool.getGunIntTag(stack, "BoltActionTime", 0) > 0 && GunsTool.getGunIntTag(stack, "Ammo", 0) > (stack.is(ModTags.Items.REVOLVER) ? 0 : 1)) { + GunsTool.setGunBooleanTag(stack, "NeedBoltAction", true); + } + + revolverPreTime = 0; + revolverWheelPreTime = 0; + + playGunClientSounds(player); + handleClientShoot(); + } +// } else if (stack.is(ModItems.MINIGUN.get())) { +// var tag = GunNBTTool.getOrCreateTag(stack); +// +// if ((player.getCapability(ModVariables.PLAYER_VARIABLES_CAPABILITY, null).orElse(new ModVariables.PlayerVariables())).rifleAmmo > 0 +// || InventoryTool.hasCreativeAmmoBox(player)) { +// +// var perk = PerkHelper.getPerkByType(stack, Perk.Type.AMMO); +// float pitch = tag.getDouble("heat") <= 40 ? 1 : (float) (1 - 0.025 * Math.abs(40 - tag.getDouble("heat"))); +// +// player.playSound(ModSounds.MINIGUN_FIRE_1P.get(), 1f, pitch); +// +// if (perk == ModPerks.BEAST_BULLET.get()) { +// player.playSound(ModSounds.HENG.get(), 1f, 1f); +// } +// +// double shooterHeight = player.getEyePosition().distanceTo((Vec3.atLowerCornerOf(player.level().clip(new ClipContext(player.getEyePosition(), player.getEyePosition().add(new Vec3(0, -1, 0).scale(10)), +// ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)).getBlockPos()))); +// +// ModUtils.queueClientWork((int) (1 + 1.5 * shooterHeight), () -> player.playSound(ModSounds.SHELL_CASING_NORMAL.get(), (float) Math.max(1.5 - 0.2 * shooterHeight, 0), 1)); +// } +// +// handleClientShoot(); + } + } + + public static void gunPartMove(float times) { + chamberRot = Mth.lerp(0.07 * times, chamberRot, 0); + actionMove = Mth.lerp(0.125 * times, actionMove, 0); + } + + public static void handleClientShoot() { + Player player = Minecraft.getInstance().player; + if (player == null) return; + ItemStack stack = player.getMainHandItem(); + if (!stack.is(ModTags.Items.GUN)) return; + + PacketDistributor.sendToServer(new ShootMessage(gunSpread)); + fireRecoilTime = 10; + + float gunRecoilY = (float) GunsTool.getGunDoubleTag(stack, "RecoilY", 0) * 10; + + recoilY = (float) (2 * Math.random() - 1) * gunRecoilY; + + if (shellIndex < 5) { + shellIndex++; + } + + shellIndexTime[shellIndex] = 0.001; + + randomShell[0] = (1 + 0.2 * (Math.random() - 0.5)); + randomShell[1] = (0.2 + (Math.random() - 0.5)); + randomShell[2] = (0.7 + (Math.random() - 0.5)); + } + + public static void handleShakeClient(double time, double radius, double amplitude, double x, double y, double z, final IPayloadContext context) { +// if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) { +// Player player = Minecraft.getInstance().player; +// if (player == null) return; +// shakeTime = time; +// shakeRadius = radius; +// shakeAmplitude = amplitude * Mth.DEG_TO_RAD; +// shakePos[0] = x; +// shakePos[1] = y; +// shakePos[2] = z; +// shakeType = 2 * (Math.random() - 0.5); +// } + } + + public static void playGunClientSounds(Player player) { + ItemStack stack = player.getMainHandItem(); + if (!(stack.getItem() instanceof GunItem gunItem)) { + return; + } + + String origin = stack.getItem().getDescriptionId(); + String name = origin.substring(origin.lastIndexOf(".") + 1); + +// if (stack.getItem() == ModItems.SENTINEL.get()) { +// AtomicBoolean charged = new AtomicBoolean(false); +// +// stack.getCapability(ForgeCapabilities.ENERGY).ifPresent( +// e -> charged.set(e.getEnergyStored() > 0) +// ); +// +// if (charged.get()) { +// SoundEvent sound1p = BuiltInRegistries.SOUND_EVENT.get(ModUtils.loc( "sentinel_charge_fire_1p")); +// if (sound1p != null) { +// player.playSound(sound1p, 2f, 1); +// } +// return; +// } +// } + +// var perk = PerkHelper.getPerkByType(stack, Perk.Type.AMMO); +// +// if (perk == ModPerks.BEAST_BULLET.get()) { +// player.playSound(ModSounds.HENG.get(), 1f, 1f); +// } + + int barrelType = GunsTool.getAttachmentType(stack, GunsTool.AttachmentType.BARREL); + +// SoundEvent sound1p = ForgeRegistries.SOUND_EVENTS.getValue(ModUtils.loc(name + (barrelType == 2 ? "_fire_1p_s" : "_fire_1p"))); + +// if (sound1p != null) { +// player.playSound(sound1p, 2f, 1); +// } + + double shooterHeight = player.getEyePosition().distanceTo((Vec3.atLowerCornerOf(player.level().clip(new ClipContext(player.getEyePosition(), player.getEyePosition().add(new Vec3(0, -1, 0).scale(10)), + ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)).getBlockPos()))); + + ModUtils.queueClientWork((int) (1 + 1.5 * shooterHeight), () -> { + if (gunItem.canEjectShell(stack)) { + if (stack.is(ModTags.Items.SHOTGUN)) { + player.playSound(ModSounds.SHELL_CASING_SHOTGUN.get(), (float) Math.max(0.75 - 0.12 * shooterHeight, 0), 1); + } else if (stack.is(ModTags.Items.SNIPER_RIFLE) || stack.is(ModTags.Items.HEAVY_WEAPON)) { + player.playSound(ModSounds.SHELL_CASING_50CAL.get(), (float) Math.max(1 - 0.15 * shooterHeight, 0), 1); + } else { + player.playSound(ModSounds.SHELL_CASING_NORMAL.get(), (float) Math.max(1.5 - 0.2 * shooterHeight, 0), 1); + } + + } + }); + } + + @SubscribeEvent + public static void handleVehicleFire(RenderFrameEvent.Pre event) { + ClientLevel level = Minecraft.getInstance().level; + Player player = Minecraft.getInstance().player; + if (player == null) return; + if (level == null) return; + + if (notInGame()) { + clientTimerVehicle.stop(); + holdFireVehicle = false; + } + +// if (player.getVehicle() instanceof VehicleEntity pVehicle && player.getVehicle() instanceof WeaponVehicleEntity iVehicle && iVehicle.hasWeapon(pVehicle.getSeatIndex(player)) && iVehicle.canShoot(player)) { +// int rpm = iVehicle.mainGunRpm(player); +// if (rpm == 0) { +// rpm = 240; +// } +// +// double rps = (double) rpm / 60; +// int cooldown = (int) (1000 / rps); +// +// if ((holdFireVehicle)) { +// if (!clientTimerVehicle.started()) { +// clientTimerVehicle.start(); +// // 首发瞬间发射 +// clientTimerVehicle.setProgress((cooldown + 1)); +// } +// +// if (clientTimerVehicle.getProgress() >= cooldown) { +// ModUtils.PACKET_HANDLER.sendToServer(new VehicleFireMessage(pVehicle.getSeatIndex(player))); +// playVehicleClientSounds(player, iVehicle, pVehicle.getSeatIndex(player)); +// clientTimerVehicle.setProgress((clientTimerVehicle.getProgress() - cooldown)); +// } +// } else if (clientTimerVehicle.getProgress() >= cooldown) { +// clientTimerVehicle.stop(); +// } +// } else { +// clientTimerVehicle.stop(); +// } + } + +// public static void playVehicleClientSounds(Player player, WeaponVehicleEntity iVehicle, int type) { +// if (iVehicle instanceof SpeedboatEntity speedboat) { +// float pitch = speedboat.getEntityData().get(HEAT) <= 60 ? 1 : (float) (1 - 0.011 * Math.abs(60 - speedboat.getEntityData().get(HEAT))); +// player.playSound(ModSounds.M_2_FIRE_1P.get(), 1f, pitch); +// player.playSound(ModSounds.SHELL_CASING_50CAL.get(), 0.3f, 1); +// } +// +// if (iVehicle instanceof Ah6Entity ah6Entity) { +// float pitch = ah6Entity.getEntityData().get(HEAT) <= 60 ? 1 : (float) (1 - 0.011 * Math.abs(60 - ah6Entity.getEntityData().get(HEAT))); +// if (ah6Entity.getWeaponIndex(0) == 0) { +// player.playSound(ModSounds.HELICOPTER_CANNON_FIRE_1P.get(), 1f, pitch); +// } else if (ah6Entity.getWeaponIndex(0) == 1) { +// player.playSound(ModSounds.HELICOPTER_ROCKET_FIRE_1P.get(), 1f, 1); +// } +// } +// if (iVehicle instanceof Lav150Entity lav150) { +// if (lav150.getWeaponIndex(0) == 0) { +// float pitch = lav150.getEntityData().get(HEAT) <= 60 ? 1 : (float) (1 - 0.011 * Math.abs(60 - lav150.getEntityData().get(HEAT))); +// player.playSound(ModSounds.LAV_CANNON_FIRE_1P.get(), 1f, pitch); +// player.playSound(ModSounds.SHELL_CASING_50CAL.get(), 0.3f, 1); +// } else if (lav150.getWeaponIndex(0) == 1) { +// float pitch = lav150.getEntityData().get(COAX_HEAT) <= 60 ? 1 : (float) (1 - 0.011 * Math.abs(60 - lav150.getEntityData().get(COAX_HEAT))); +// player.playSound(ModSounds.COAX_FIRE_1P.get(), 1f, pitch); +// } +// +// } +// if (iVehicle instanceof Bmp2Entity bmp2) { +// if (bmp2.getWeaponIndex(0) == 0) { +// float pitch = bmp2.getEntityData().get(HEAT) <= 60 ? 1 : (float) (1 - 0.011 * Math.abs(60 - bmp2.getEntityData().get(HEAT))); +// player.playSound(ModSounds.BMP_CANNON_FIRE_1P.get(), 1f, pitch); +// player.playSound(ModSounds.SHELL_CASING_50CAL.get(), 0.3f, 1); +// } else if (bmp2.getWeaponIndex(0) == 1) { +// float pitch = bmp2.getEntityData().get(COAX_HEAT) <= 60 ? 1 : (float) (1 - 0.011 * Math.abs(60 - bmp2.getEntityData().get(COAX_HEAT))); +// player.playSound(ModSounds.COAX_FIRE_1P.get(), 1f, pitch); +// } else if (bmp2.getWeaponIndex(0) == 2) { +// player.playSound(ModSounds.BMP_MISSILE_FIRE_1P.get(), 1f, 1); +// } +// } +// if (iVehicle instanceof Yx100Entity yx100) { +// if (type == 1) { +// float pitch = yx100.getEntityData().get(HEAT) <= 60 ? 1 : (float) (1 - 0.011 * Math.abs(60 - yx100.getEntityData().get(HEAT))); +// player.playSound(ModSounds.M_2_FIRE_1P.get(), 1f, pitch); +// player.playSound(ModSounds.SHELL_CASING_50CAL.get(), 0.3f, 1); +// } else { +// player.playSound(ModSounds.YX_100_FIRE_1P.get(), 1f, 1); +// } +// } +// } + + @SubscribeEvent + public static void handleWeaponBreathSway(RenderFrameEvent.Pre event) { + Player player = Minecraft.getInstance().player; + if (player == null) return; + ItemStack stack = player.getMainHandItem(); + if (!(stack.getItem() instanceof GunItem gunItem)) return; +// if (player.getVehicle() instanceof ArmedVehicleEntity iArmedVehicle && iArmedVehicle.isDriver(player) && iArmedVehicle.hidePassenger(player)) +// return; + + float pose; + float times = 2 * (float) Math.min(Minecraft.getInstance().getTimer().getGameTimeDeltaTicks(), 0.8); + + if (player.isCrouching() && player.getBbHeight() >= 1 && !isProne(player)) { + pose = 0.85f; + } else if (isProne(player)) { + pose = (GunsTool.getAttachmentType(stack, GunsTool.AttachmentType.GRIP) == 3 || gunItem.hasBipod(stack)) ? 0 : 0.25f; + } else { + pose = 1; + } + + int stockType = GunsTool.getAttachmentType(stack, GunsTool.AttachmentType.STOCK); + + double sway = switch (stockType) { + case 1 -> 1; + case 2 -> 0.55; + default -> 0.8; + }; + + double customWeight = GunsTool.getGunDoubleTag(stack, "CustomWeight"); + + var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE, null); + + if (cap != null && !cap.breath && cap.zoom) { + float newPitch = (float) (player.getXRot() - 0.01f * Mth.sin((float) (0.03 * player.tickCount)) * pose * Mth.nextDouble(RandomSource.create(), 0.1, 1) * times * sway * (1 - 0.03 * customWeight)); + player.setXRot(newPitch); + player.xRotO = player.getXRot(); + + float newYaw = (float) (player.getYRot() - 0.005f * Mth.cos((float) (0.025 * (player.tickCount + 2 * Math.PI))) * pose * Mth.nextDouble(RandomSource.create(), 0.05, 1.25) * times * sway * (1 - 0.03 * customWeight)); + player.setYRot(newYaw); + player.yRotO = player.getYRot(); + } + } + + @SubscribeEvent + public static void computeCameraAngles(ViewportEvent.ComputeCameraAngles event) { + ClientLevel level = Minecraft.getInstance().level; + Entity entity = event.getCamera().getEntity(); + + if (!(entity instanceof LivingEntity living)) return; + ItemStack stack = living.getMainHandItem(); + + if (level != null + && ( + // todo monitor +// stack.is(ModItems.MONITOR.get()) && + NBTTool.getOrCreateTag(stack).getBoolean("Using") && NBTTool.getOrCreateTag(stack).getBoolean("Linked"))) { + handleDroneCamera(event, living); + } else { + var effect = Minecraft.getInstance().gameRenderer.currentEffect(); + if (effect != null && effect.getName().equals(ModUtils.MODID + ":shaders/post/scan_pincushion.json")) { + Minecraft.getInstance().gameRenderer.shutdownEffect(); + } + } + + float times = Minecraft.getInstance().getTimer().getGameTimeDeltaTicks(); + LocalPlayer player = Minecraft.getInstance().player; + + float yaw = event.getYaw(); + float pitch = event.getPitch(); + float roll = event.getRoll(); + + shakeTime = Mth.lerp(0.175 * times, shakeTime, 0); + + if (player != null && shakeTime > 0) { + float shakeRadiusAmplitude = (float) Mth.clamp(1 - player.position().distanceTo(new Vec3(shakePos[0], shakePos[1], shakePos[2])) / shakeRadius, 0, 1); + + boolean onVehicle = player.getVehicle() != null; + + if (shakeType > 0) { + event.setYaw((float) (yaw + (shakeTime * Math.sin(0.5 * Math.PI * shakeTime) * shakeAmplitude * shakeRadiusAmplitude * shakeType * (onVehicle ? 0.4 : 1)))); + event.setPitch((float) (pitch - (shakeTime * Math.sin(0.5 * Math.PI * shakeTime) * shakeAmplitude * shakeRadiusAmplitude * shakeType * (onVehicle ? 0.4 : 1)))); + event.setRoll((float) (roll - (shakeTime * Math.sin(0.5 * Math.PI * shakeTime) * shakeAmplitude * shakeRadiusAmplitude * (onVehicle ? 0.4 : 1)))); + } else { + event.setYaw((float) (yaw - (shakeTime * Math.sin(0.5 * Math.PI * shakeTime) * shakeAmplitude * shakeRadiusAmplitude * shakeType * (onVehicle ? 0.4 : 1)))); + event.setPitch((float) (pitch + (shakeTime * Math.sin(0.5 * Math.PI * shakeTime) * shakeAmplitude * shakeRadiusAmplitude * shakeType * (onVehicle ? 0.4 : 1)))); + event.setRoll((float) (roll + (shakeTime * Math.sin(0.5 * Math.PI * shakeTime) * shakeAmplitude * shakeRadiusAmplitude * (onVehicle ? 0.4 : 1)))); + } + } + + cameraPitch = event.getPitch(); + cameraYaw = event.getYaw(); + cameraRoll = event.getRoll(); + +// if (player != null && player.getVehicle() instanceof ArmedVehicleEntity iArmedVehicle && iArmedVehicle.banHand(player)) { +// return; +// } + + if (level != null && stack.is(ModTags.Items.GUN)) { + handleWeaponSway(living); + handleWeaponMove(living); + handleWeaponZoom(living); + handlePlayerBreath(living); + handleWeaponFire(event, living); + handleWeaponShell(); + handleGunRecoil(); + handleBowPullAnimation(living); + handleWeaponDraw(living); + handlePlayerCamera(event); + } + + handleShockCamera(event, living); + } + + private static void handleDroneCamera(ViewportEvent.ComputeCameraAngles event, LivingEntity entity) { + ItemStack stack = entity.getMainHandItem(); + float yaw = event.getYaw(); + +// DroneEntity drone = EntityFindUtil.findDrone(entity.level(), GunNBTTool.getOrCreateTag(stack).getString("LinkedDrone")); +// +// if (drone != null) { +// event.setRoll(drone.getRoll((float) event.getPartialTick()) * (1 - (drone.getPitch((float) event.getPartialTick()) / 90))); +// } +// +// if (drone != null && GunNBTTool.getOrCreateTag(stack).getBoolean("Using")) { +// if (Minecraft.getInstance().gameRenderer.currentEffect() == null) { +// Minecraft.getInstance().gameRenderer.loadEffect(ModUtils.loc("shaders/post/scan_pincushion.json")); +// } +// } + } + + @SubscribeEvent + public static void onRenderHand(RenderHandEvent event) { + Player player = Minecraft.getInstance().player; + if (player == null) return; + + InteractionHand leftHand = Minecraft.getInstance().options.mainHand().get() == HumanoidArm.RIGHT ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND; + InteractionHand rightHand = Minecraft.getInstance().options.mainHand().get() == HumanoidArm.RIGHT ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND; + + ItemStack rightHandItem = player.getItemInHand(rightHand); + + if (event.getHand() == leftHand) { + if (rightHandItem.is(ModTags.Items.GUN)) { + event.setCanceled(true); + } + } + + if (event.getHand() == rightHand) { + if (rightHandItem.is(ModTags.Items.GUN) && drawTime > 0.15) { + event.setCanceled(true); + } + } + + ItemStack stack = player.getMainHandItem(); +// if (stack.is(ModItems.MONITOR.get()) && GunNBTTool.getOrCreateTag(stack).getBoolean("Using") && GunNBTTool.getOrCreateTag(stack).getBoolean("Linked")) { +// if (EntityFindUtil.findDrone(player.level(), GunNBTTool.getOrCreateTag(stack).getString("LinkedDrone")) != null) { +// event.setCanceled(true); +// } +// } +// +// if (player.getVehicle() instanceof ArmedVehicleEntity iArmedVehicle && iArmedVehicle.banHand(player)) { +// event.setCanceled(true); +// } + } + + private static void handleWeaponSway(LivingEntity entity) { + ItemStack stack = entity.getMainHandItem(); + if (stack.getItem() instanceof GunItem gunItem && entity instanceof Player player) { +// float times = 2 * (float) Math.min(Minecraft.getInstance().getTimer().getGameTimeDeltaTicks(), 0.8); + double pose; + + if (player.isShiftKeyDown() && player.getBbHeight() >= 1 && isProne(player)) { + pose = 0.85; + } else if (isProne(player)) { + pose = (GunsTool.getAttachmentType(stack, GunsTool.AttachmentType.GRIP) == 3 || gunItem.hasBipod(stack)) ? 0 : 0.25f; + } else { + pose = 1; + } + +// swayTime += 0.05 * times; + + swayX = pose * -0.008 * Math.sin(swayTime) * (1 - 0.95 * zoomTime); + swayY = pose * 0.125 * Math.sin(swayTime - 1.585) * (1 - 0.95 * zoomTime) - 3 * moveRotZ; + } + } + + private static void handleWeaponMove(LivingEntity entity) { + if (entity.getMainHandItem().is(ModTags.Items.GUN)) { + float times = 3.7f * (float) Math.min(Minecraft.getInstance().getTimer().getGameTimeDeltaTicks(), 0.8); + double moveSpeed = (float) Mth.clamp(entity.getDeltaMovement().horizontalDistanceSqr(), 0, 0.02); + double onGround; + + if (entity.onGround()) { + if (entity.isSprinting()) { + onGround = 1.35; + } else { + onGround = 2.0; + } + } else { + onGround = 0.001; + } + + var cap = entity.getCapability(ModCapabilities.PLAYER_VARIABLE); + if (cap != null && !cap.edit) { + if (Minecraft.getInstance().options.keyUp.isDown() && firePosTimer == 0) { + moveRotZ = Mth.lerp(0.2f * times, moveRotZ, 0.14) * (1 - zoomTime); + } else { + moveRotZ = Mth.lerp(0.2f * times, moveRotZ, 0) * (1 - zoomTime); + } + } + + if (isMoving() && firePosTimer == 0) { + if (moveYTime < 1.25) { + moveYTime += 1.2 * onGround * times * moveSpeed; + } else { + moveYTime = 0.25; + } + + if (moveXTime < 2) { + moveXTime += 1.2 * onGround * times * moveSpeed; + } else { + moveXTime = 0; + } + + movePosX = 0.2 * Math.sin(1 * Math.PI * moveXTime) * (1 - 0.95 * zoomTime); + movePosY = -0.135 * Math.sin(2 * Math.PI * (moveYTime - 0.25)) * (1 - 0.95 * zoomTime); + } else { + moveXTime = Math.max(moveXTime - 0.5 * times, 0); + moveYTime = Math.max(moveYTime - 0.5 * times, 0.25); + + movePosX = Mth.lerp(0.1f * times, movePosX, 0); + movePosY = Mth.lerp(0.1f * times, movePosY, 0); + + } + + if (Minecraft.getInstance().options.keyRight.isDown()) { + movePosHorizon = Mth.lerp(0.05f * times, movePosHorizon, 0.04) * (1 - zoomTime); + } else if (Minecraft.getInstance().options.keyLeft.isDown()) { + movePosHorizon = Mth.lerp(0.05f * times, movePosHorizon, -0.04) * (1 - zoomTime); + } else { + movePosHorizon = Mth.lerp(0.1f * times, movePosHorizon, 0); + } + + double velocity = entity.getDeltaMovement().y() + 0.078; + + velocityY = Mth.clamp(Mth.lerp(0.23f * times, velocityY, velocity) * (1 - 0.8 * zoomTime), -0.8, 0.8); + } + } + + private static void handleWeaponZoom(LivingEntity entity) { + if (!(entity instanceof Player player)) return; + ItemStack stack = player.getMainHandItem(); + float times = 5 * Minecraft.getInstance().getTimer().getGameTimeDeltaTicks(); + + double weight = GunsTool.getGunDoubleTag(stack, "Weight") + GunsTool.getGunDoubleTag(stack, "CustomWeight"); + double speed = 1.5 - (0.07 * weight); + +// if (zoom +// && !(player.getVehicle() instanceof ArmedVehicleEntity iArmedVehicle && iArmedVehicle.banHand(player)) +// && !notInGame() +// && drawTime < 0.01 +// && !player.getCapability(ModVariables.PLAYER_VARIABLES_CAPABILITY, null).orElse(new ModVariables.PlayerVariables()).edit) { +// if (Minecraft.getInstance().player != null) { +// Minecraft.getInstance().player.getPersistentData().putDouble("noRun", 5); +// } +// if (cantFireTime <= 10) { +// zoomTime = Mth.clamp(zoomTime + 0.03 * speed * times, 0, 1); +// } +// +// } else { +// zoomTime = Mth.clamp(zoomTime - 0.04 * speed * times, 0, 1); +// } + zoomPos = AnimationCurves.EASE_IN_OUT_QUINT.apply(zoomTime); + zoomPosZ = AnimationCurves.PARABOLA.apply(zoomTime); + } + + private static void handleWeaponFire(ViewportEvent.ComputeCameraAngles event, LivingEntity entity) { + float times = 2f * Math.min(Minecraft.getInstance().getTimer().getGameTimeDeltaTicks(), 0.48f); + float yaw = event.getYaw(); + float pitch = event.getPitch(); + float roll = event.getRoll(); + ItemStack stack = entity.getMainHandItem(); + double amplitude = 15000 * GunsTool.getGunDoubleTag(stack, "RecoilY", 0) * GunsTool.getGunDoubleTag(stack, "RecoilX", 0); + + if (fireRecoilTime > 0) { + firePosTimer = 0.001; + fireRotTimer = 0.001; + fireRecoilTime -= 7 * times; + fireSpread += 0.1 * times; + firePosZ += (0.8 * firePosZ + 0.25) * (4 * Math.random() + 0.85) * times; + recoilTime = 0.01; + } + + fireSpread = Mth.clamp(fireSpread - 0.1 * (Math.pow(fireSpread, 2) * times), 0, 2); + firePosZ = Mth.clamp(firePosZ - 1.2 * (Math.pow(firePosZ, 2) * times), 0, 1.5); + + firePosZ *= 0.96f; + firePos *= 0.96f; + fireRot *= 0.96f; + + if (0 < firePosTimer) { + firePosTimer += 0.35 * (1.1 - firePosTimer) * times; + } + if (0 < firePosTimer && firePosTimer < 0.454) { + firePos = (-18.34) * Math.pow(firePosTimer, 2) + 8.58 * firePosTimer; + } + if (0.454 <= firePosTimer && firePosTimer < 1) { + firePos = 4.34 * Math.pow(firePosTimer, 2) - 6.5 * firePosTimer + 2.167; + } + + if (0 < fireRotTimer && fireRotTimer < 1.732) { + fireRotTimer += 0.18 * (1.9 - fireRotTimer) * times; + } + + double rpm = 1; + +// if (stack.is(ModItems.MINIGUN.get())) { +// rpm = (double) GunsTool.getGunIntTag(stack, "RPM", 0) / 1800; +// } + + float[] shake = {0, 0}; + shake[0] = (float) (1.3 * amplitude * (1 / 6.3 * (fireRotTimer - 0.5)) * Math.sin(6.3 * (fireRotTimer - 0.5)) * (3 - Math.pow(fireRotTimer, 2)) + 1 * Mth.clamp(0.3 - fireRotTimer, 0, 1) * (2 * Math.random() - 1)); + shake[1] = (float) (4.2 * amplitude * (1 / 6.3 * (fireRotTimer - 0.5)) * Math.sin(6.3 * (fireRotTimer - 0.5)) * (3 - Math.pow(fireRotTimer, 2)) + 3 * Mth.clamp(0.5 - fireRotTimer, 0, 0.5) * (2 * Math.random() - 1)); + + if (0 < fireRotTimer && fireRotTimer < 1.732) { + fireRot = 1 / 6.3 * (fireRotTimer - 0.5) * Math.sin(6.3 * (fireRotTimer - 0.5)) * (3 - Math.pow(fireRotTimer, 2)); + if (recoilY > 0) { + event.setYaw((float) (yaw - shake[0] * rpm)); + event.setPitch((float) (pitch + shake[0] * rpm)); + event.setRoll((float) (roll + shake[1] * rpm)); + } else if (recoilY <= 0) { + event.setYaw((float) (yaw + shake[0] * rpm)); + event.setPitch((float) (pitch - shake[0] * rpm)); + event.setRoll((float) (roll - shake[1] * rpm)); + } + } + + if (firePosTimer >= 1) { + firePosTimer = 0; + } + if (fireRotTimer >= 1.732) { + fireRotTimer = 0; + fireRot = 0; + } + } + + private static void handleWeaponShell() { + Player player = Minecraft.getInstance().player; + if (player == null) return; + + float times = (float) Math.min(Minecraft.getInstance().getTimer().getGameTimeDeltaTicks(), 0.8); + + if (shellIndex >= 5) { + shellIndex = 0; + shellIndexTime[0] = 0.001; + } + + for (int i = 0; i < 5; i++) { + if (shellIndexTime[i] > 0) { + shellIndexTime[i] = Math.min(shellIndexTime[i] + 8 * times, 50); + } + if (shellIndexTime[i] == 50) { + shellIndexTime[i] = 0; + } + } + } + + private static void handleGunRecoil() { + Player player = Minecraft.getInstance().player; + if (player == null) return; + ItemStack stack = player.getMainHandItem(); + if (!(stack.getItem() instanceof GunItem gunItem)) return; + + float times = (float) Math.min(Minecraft.getInstance().getTimer().getGameTimeDeltaTicks(), 1.6); + int barrelType = GunsTool.getAttachmentType(stack, GunsTool.AttachmentType.BARREL); + int gripType = GunsTool.getAttachmentType(stack, GunsTool.AttachmentType.GRIP); + + double recoil = switch (barrelType) { + case 1 -> 1.5; + case 2 -> 2.2; + default -> 2.4; + }; + + double gripRecoilX = switch (gripType) { + case 1 -> 1.25; + case 2 -> 0.25; + default -> 1.5; + }; + + double gripRecoilY = switch (gripType) { + case 1 -> 0.7; + case 2 -> 1.75; + default -> 2.0; + }; + + if (!gunItem.isCustomizable(stack)) { + recoil = 1.6; + gripRecoilX = 0.75; + gripRecoilY = 1.25; + } + + double customWeight = GunsTool.getGunDoubleTag(stack, "CustomWeight"); + + double rpm = 1; + +// if (stack.is(ModItems.MINIGUN.get())) { +// rpm = (double) GunsTool.getGunIntTag(stack, "RPM", 0) / 1800; +// } + + float gunRecoilX = (float) GunsTool.getGunDoubleTag(stack, "RecoilX", 0) * 60; + + recoilHorizon = Mth.lerp(0.2 * times, recoilHorizon, 0) + recoilY; + recoilY = 0; + + // 计算后坐力 + float pose = 1; + if (player.isShiftKeyDown() && player.getBbHeight() >= 1 && !isProne(player)) { + pose = 0.7f; + } else if (isProne(player)) { + if (GunsTool.getAttachmentType(stack, GunsTool.AttachmentType.GRIP) == 3 || gunItem.hasBipod(stack)) { + pose = 0.1f; + } else { + pose = 0.5f; + } + } + + // 水平后座 + float newYaw = player.getYRot() - (float) (0.6 * recoilHorizon * pose * times * (0.5 + fireSpread) * recoil * (1 - 0.06 * customWeight) * gripRecoilX * rpm); + player.setYRot(newYaw); + player.yRotO = player.getYRot(); + + double sinRes = 0; + + // 竖直后座 + if (0 < recoilTime && recoilTime < 0.5) { + float newPitch = (float) (player.getXRot() - 0.02f * gunRecoilX * times * recoil * (1 - 0.06 * customWeight) * gripRecoilY * rpm); + player.setXRot(newPitch); + player.xRotO = player.getXRot(); + } + + if (0 < recoilTime && recoilTime < 2) { + recoilTime = recoilTime + 0.3 * times; + sinRes = Math.sin(Math.PI * recoilTime); + } + + if (2 <= recoilTime && recoilTime < 2.5) { + recoilTime = recoilTime + 0.17 * times; + sinRes = 0.4 * Math.sin(2 * Math.PI * recoilTime); + } + + if (0 < recoilTime && recoilTime < 2.5) { + float newPitch = player.getXRot() - (float) (1.5 * pose * gunRecoilX * (sinRes + Mth.clamp(0.5 - recoilTime, 0, 0.5)) * times * (0.5 + fireSpread) * recoil * (1 - 0.06 * customWeight) * gripRecoilY * rpm); + player.setXRot(newPitch); + player.xRotO = player.getXRot(); + } + + if (recoilTime >= 2.5) recoilTime = 0; + } + + private static void handlePlayerBreath(LivingEntity entity) { + float times = (float) Math.min(Minecraft.getInstance().getTimer().getGameTimeDeltaTicks(), 0.8); + var cap = entity.getCapability(ModCapabilities.PLAYER_VARIABLE); + boolean breath = cap != null && cap.breath; + + breathTime = Mth.lerp(0.2f * times, breathTime, breath ? 1 : 0); + } + + private static void handleShockCamera(ViewportEvent.ComputeCameraAngles event, LivingEntity entity) { + if (entity.hasEffect(ModMobEffects.SHOCK) && Minecraft.getInstance().options.getCameraType() == CameraType.FIRST_PERSON) { + event.setYaw(Minecraft.getInstance().gameRenderer.getMainCamera().getYRot() + (float) Mth.nextDouble(RandomSource.create(), -3, 3)); + event.setPitch(Minecraft.getInstance().gameRenderer.getMainCamera().getXRot() + (float) Mth.nextDouble(RandomSource.create(), -3, 3)); + event.setRoll((float) Mth.nextDouble(RandomSource.create(), 8, 12)); + } + } + + public static void shake(double boneRotX, double boneRotY, double boneRotZ) { + LocalPlayer player = Minecraft.getInstance().player; + if (player != null) { + cameraRot[0] = -boneRotX; + cameraRot[1] = -boneRotY; + cameraRot[2] = -boneRotZ; + } + } + + private static void handlePlayerCamera(ViewportEvent.ComputeCameraAngles event) { + double yaw = event.getYaw(); + double pitch = event.getPitch(); + double roll = event.getRoll(); + float times = (float) Math.min(Minecraft.getInstance().getTimer().getGameTimeDeltaTicks(), 0.8); + LocalPlayer player = Minecraft.getInstance().player; + + if (GLFW.glfwGetKey(Minecraft.getInstance().getWindow().getWindow(), GLFW.GLFW_KEY_RIGHT) == GLFW.GLFW_PRESS) { + cameraLocation = Mth.clamp(cameraLocation - 0.05 * Minecraft.getInstance().getTimer().getGameTimeDeltaTicks(), -0.6, 0.6); + } + + if (GLFW.glfwGetKey(Minecraft.getInstance().getWindow().getWindow(), GLFW.GLFW_KEY_LEFT) == GLFW.GLFW_PRESS) { + cameraLocation = Mth.clamp(cameraLocation + 0.05 * Minecraft.getInstance().getTimer().getGameTimeDeltaTicks(), -0.6, 0.6); + } + + if (player == null) return; + + double range; + Entity lookingEntity = SeekTool.seekEntity(player, player.level(), 520, 5); + + if (lookingEntity != null) { + range = Math.max(player.distanceTo(lookingEntity), 0.01); + } else { + range = Math.max(player.position().distanceTo((Vec3.atLowerCornerOf(player.level().clip( + new ClipContext(player.getEyePosition(), player.getEyePosition().add(player.getLookAngle().scale(520)), + ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)).getBlockPos()))), 0.01); + } + + lookDistance = Mth.lerp(0.2f * times, lookDistance, range); + + double angle = 0; + + if (lookDistance != 0 && cameraLocation != 0) { + angle = Math.atan(Mth.abs((float) cameraLocation) / (lookDistance + 2.9)) * Mth.RAD_TO_DEG; + } + + event.setPitch((float) (pitch + cameraRot[0] + (DisplayConfig.CAMERA_ROTATE.get() ? 0.2 : 0) * turnRot[0] + 3 * velocityY)); + if (Minecraft.getInstance().options.getCameraType() == CameraType.THIRD_PERSON_BACK) { + event.setYaw((float) (yaw + cameraRot[1] + (DisplayConfig.CAMERA_ROTATE.get() ? 0.8 : 0) * turnRot[1] - (cameraLocation > 0 ? 1 : -1) * angle * zoomPos)); + } else { + event.setYaw((float) (yaw + cameraRot[1] + (DisplayConfig.CAMERA_ROTATE.get() ? 0.8 : 0) * turnRot[1])); + } + + event.setRoll((float) (roll + cameraRot[2] + (DisplayConfig.CAMERA_ROTATE.get() ? 0.35 : 0) * turnRot[2])); + } + + private static void handleBowPullAnimation(LivingEntity entity) { + float times = 4 * (float) Math.min(Minecraft.getInstance().getTimer().getGameTimeDeltaTicks(), 0.8); + + var cap = entity.getCapability(ModCapabilities.PLAYER_VARIABLE); + if (cap != null && cap.bowPull) { + pullTimer = Math.min(pullTimer + 0.024 * times, 1.4); + bowTimer = Math.min(bowTimer + 0.018 * times, 1); + handTimer = Math.min(handTimer + 0.018 * times, 1); + handPos = 0.5 * Math.cos(Math.PI * Math.pow(Math.pow(handTimer, 2) - 1, 2)) + 0.5; + } else { + pullTimer = Math.max(pullTimer - 0.015 * times, 0); + bowTimer = Math.max(bowTimer - 1 * times, 0); + handTimer = Math.max(handTimer - 0.04 * times, 0); + if (handTimer > 0 && handTimer < 0.5) { + handPos = 0.5 * Math.cos(Math.PI * Math.pow(Math.pow(handTimer, 2) - 1, 2)) + 0.5; + } + } + pullPos = 0.5 * Math.cos(Math.PI * Math.pow(Math.pow(Mth.clamp(pullTimer, 0, 1), 2) - 1, 2)) + 0.5; + bowPos = 0.5 * Math.cos(Math.PI * Math.pow(Math.pow(bowTimer, 2) - 1, 2)) + 0.5; + } + + @SubscribeEvent + public static void onFovUpdate(ViewportEvent.ComputeFov event) { + Minecraft mc = Minecraft.getInstance(); + float times = (float) Math.min(Minecraft.getInstance().getTimer().getGameTimeDeltaTicks(), 1.6); + Player player = mc.player; + if (player == null) { + return; + } + + ItemStack stack = player.getMainHandItem(); + +// if (player.getVehicle() instanceof WeaponVehicleEntity iVehicle && zoomVehicle) { +// event.setFOV(event.getFOV() / iVehicle.zoomFov()); +// return; +// } + + if (stack.is(ModTags.Items.GUN)) { + if (!event.usedConfiguredFov()) { + return; + } + + double p = zoomPos; +// double p; +// if (stack.is(ModItems.BOCEK.get())) { +// p = (pullPos + 0.25) * zoomTime; +// } else { +// p = zoomPos; +// } + + customZoom = Mth.lerp(0.6 * times, customZoom, GunsTool.getGunDoubleTag(stack, "CustomZoom", 0)); + + double zoomFov = 1.25 + customZoom; + + if (mc.options.getCameraType().isFirstPerson()) { + event.setFOV(event.getFOV() / (1.0 + p * (zoomFov - 1)) * (1 - 0.4 * breathTime)); + } else if (mc.options.getCameraType() == CameraType.THIRD_PERSON_BACK) + event.setFOV(event.getFOV() / (1.0 + p * 0.01) * (1 - 0.4 * breathTime)); + fov = event.getFOV(); + + var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE); + + // 智慧芯片 + if (zoom + && !notInGame() + && drawTime < 0.01 + && cap != null + && !cap.edit) { + if (!player.isShiftKeyDown()) { +// int intelligentChipLevel = PerkHelper.getItemPerkLevel(ModPerks.INTELLIGENT_CHIP.get(), stack); +// +// if (intelligentChipLevel > 0) { +// if (ClientEventHandler.entity == null || !entity.isAlive()) { +// ClientEventHandler.entity = SeekTool.seekLivingEntity(player, player.level(), 32 + 8 * (intelligentChipLevel - 1), 16 / zoomFov); +// } +// if (entity != null && entity.isAlive()) { +// Vec3 toVec = getVec3(event, player); +// look(player, toVec); +// } +// } + } else { + entity = null; + } + + } + return; + } + +// if (stack.is(ModItems.MONITOR.get()) && GunNBTTool.getOrCreateTag(stack).getBoolean("Using") && GunNBTTool.getOrCreateTag(stack).getBoolean("Linked")) { +// droneFovLerp = Mth.lerp(0.1 * Minecraft.getInstance().getTimer().getGameTimeDeltaTicks(), droneFovLerp, droneFov); +// event.setFOV(event.getFOV() / droneFovLerp); +// fov = event.getFOV(); +// } + } + + private static Vec3 getVec3(ViewportEvent.ComputeFov event, Player player) { + Vec3 targetVec = new Vec3(Mth.lerp(event.getPartialTick(), entity.xo, entity.getX()), Mth.lerp(event.getPartialTick(), entity.yo + entity.getEyeHeight(), entity.getEyeY()), Mth.lerp(event.getPartialTick(), entity.zo, entity.getZ())); + Vec3 playerVec = new Vec3(Mth.lerp(event.getPartialTick(), player.xo, player.getX()), Mth.lerp(event.getPartialTick(), player.yo + player.getEyeHeight(), player.getEyeY()), Mth.lerp(event.getPartialTick(), player.zo, player.getZ())); + return playerVec.vectorTo(targetVec); + } + + public static void look(Player player, Vec3 pTarget) { + double d0 = pTarget.x; + double d1 = pTarget.y; + double d2 = pTarget.z; + double d3 = Math.sqrt(d0 * d0 + d2 * d2); + player.setXRot(Mth.wrapDegrees((float) (-(Mth.atan2(d1, d3) * 57.2957763671875)))); + player.setYRot(Mth.wrapDegrees((float) (Mth.atan2(d2, d0) * 57.2957763671875) - 90.0F)); + player.setYHeadRot(player.getYRot()); + player.xRotO = player.getXRot(); + player.yRotO = player.getYRot(); + } + + @SubscribeEvent + public static void setPlayerInvisible(RenderPlayerEvent.Pre event) { + var otherPlayer = event.getEntity(); + +// if (otherPlayer.getVehicle() instanceof ArmedVehicleEntity iArmedVehicle && iArmedVehicle.hidePassenger(otherPlayer)) { +// event.setCanceled(true); +// } + } + +// @SubscribeEvent +// public static void handleRenderCrossHair(RenderGuiOverlayEvent.Pre event) { +// if (event.getOverlay() != VanillaGuiOverlay.CROSSHAIR.type()) { +// return; +// } +// +// Minecraft mc = Minecraft.getInstance(); +// Player player = mc.player; +// if (player == null) { +// return; +// } +// +// if (!mc.options.getCameraType().isFirstPerson()) { +// return; +// } +// +// ItemStack stack = player.getMainHandItem(); +// +// if (stack.getItem() instanceof GunItem) { +// event.setCanceled(true); +// } +// +// if (player.getVehicle() instanceof VehicleEntity pVehicle && player.getVehicle() instanceof WeaponVehicleEntity iVehicle && iVehicle.hasWeapon(pVehicle.getSeatIndex(player))) { +// event.setCanceled(true); +// } +// +// if (stack.is(ModItems.MONITOR.get()) && GunNBTTool.getOrCreateTag(stack).getBoolean("Using") && GunNBTTool.getOrCreateTag(stack).getBoolean("Linked")) { +// event.setCanceled(true); +// } +// } + + /** + * 载具banHand时,禁用快捷栏渲染 + */ +// @SubscribeEvent +// public static void handleAvoidRenderingHotbar(RenderGuiOverlayEvent.Pre event) { +// if (event.getOverlay() != VanillaGuiOverlay.HOTBAR.type()) { +// return; +// } +// +// Minecraft mc = Minecraft.getInstance(); +// Player player = mc.player; +// if (player == null) { +// return; +// } +// +// if (player.getVehicle() instanceof ArmedVehicleEntity vehicle && vehicle.banHand(player)) { +// event.setCanceled(true); +// } +// } + +// public static void handleDrawMessage(boolean draw, Supplier ctx) { +// if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) { +// drawTime = 1; +// for (int i = 0; i < 5; i++) { +// shellIndexTime[i] = 0; +// } +// zoom = false; +// holdFire = false; +// ClickHandler.switchZoom = false; +// lungeDraw = 30; +// lungeSprint = 0; +// lungeAttack = 0; +// } +// } + private static void handleWeaponDraw(LivingEntity entity) { + float times = Minecraft.getInstance().getTimer().getGameTimeDeltaTicks(); + ItemStack stack = entity.getMainHandItem(); + double weight = GunsTool.getGunDoubleTag(stack, "Weight") + GunsTool.getGunDoubleTag(stack, "CustomWeight"); + double speed = 3.2 - (0.13 * weight); + drawTime = Math.max(drawTime - Math.max(0.2 * speed * times * drawTime, 0.0008), 0); + } + + public static void handleShells(float x, float y, GeoBone... shells) { + for (int i = 0; i < shells.length; i++) { + if (i >= 5) break; + + shells[i].setPosX((float) (-x * shellIndexTime[i] * ((150 - shellIndexTime[i]) / 150))); + shells[i].setPosY((float) (y * randomShell[0] * shellIndexTime[i] - 0.025 * Math.pow(shellIndexTime[i], 2))); + shells[i].setRotX((float) (randomShell[1] * shellIndexTime[i])); + shells[i].setRotY((float) (randomShell[2] * shellIndexTime[i])); + } + } + + public static void aimAtVillager(Player player) { + if (aimVillagerCountdown > 0) return; + + var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE); + if (cap != null && cap.zoom) { + Entity entity = TraceTool.findLookingEntity(player, 10); + if (entity instanceof AbstractVillager villager) { + List entities = SeekTool.seekLivingEntities(villager, villager.level(), 16, 120); + for (var e : entities) { + if (e == player) { +// ModUtils.PACKET_HANDLER.sendToServer(new AimVillagerMessage(villager.getId())); + aimVillagerCountdown = 80; + } + } + } + } + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/event/GunEventHandler.java b/src/main/java/com/atsuishio/superbwarfare/event/GunEventHandler.java new file mode 100644 index 000000000..e5cb76239 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/event/GunEventHandler.java @@ -0,0 +1,942 @@ +package com.atsuishio.superbwarfare.event; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.capability.ModCapabilities; +import com.atsuishio.superbwarfare.capability.player.PlayerVariable; +import com.atsuishio.superbwarfare.entity.projectile.ProjectileEntity; +import com.atsuishio.superbwarfare.init.ModItems; +import com.atsuishio.superbwarfare.init.ModSounds; +import com.atsuishio.superbwarfare.init.ModTags; +import com.atsuishio.superbwarfare.item.gun.GunItem; +import com.atsuishio.superbwarfare.perk.Perk; +import com.atsuishio.superbwarfare.tools.*; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.ClipContext; +import net.minecraft.world.phys.Vec3; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.capabilities.Capabilities; +import net.neoforged.neoforge.event.tick.PlayerTickEvent; + +import java.text.DecimalFormat; + +@EventBusSubscriber(modid = ModUtils.MODID) +public class GunEventHandler { + + @SubscribeEvent + public static void onPlayerTick(PlayerTickEvent.Post event) { + Player player = event.getEntity(); + + ItemStack stack = player.getMainHandItem(); + + if (stack.is(ModTags.Items.GUN)) { + handleGunBolt(player); + handleGunReload(player); + handleGunSingleReload(player); + handleSentinelCharge(player); + } + } + + /** + * 拉大栓 + */ + private static void handleGunBolt(Player player) { + ItemStack stack = player.getMainHandItem(); + if (stack.is(ModTags.Items.NORMAL_GUN)) { + if (GunsTool.getGunIntTag(stack, "BoltActionTick") > 0) { + GunsTool.setGunIntTag(stack, "BoltActionTick", GunsTool.getGunIntTag(stack, "BoltActionTick") - 1); + } + + // todo marlin +// if (stack.getItem() == ModItems.MARLIN.get() && GunsTool.getGunIntTag(stack, "BoltActionTick") == 9) { +// GunNBTTool.getOrCreateTag(stack).putBoolean("empty", false); +// } + + if (GunsTool.getGunIntTag(stack, "BoltActionTick") == 1) { + GunsTool.setGunBooleanTag(stack, "NeedBoltAction", false); + if (stack.is(ModTags.Items.REVOLVER)) { + NBTTool.getOrCreateTag(stack).putBoolean("canImmediatelyShoot", true); + } + } + } + } + + /** + * 根据武器的注册名来寻找音效并播放 + */ + public static void playGunSounds(Player player) { + ItemStack stack = player.getMainHandItem(); + if (!stack.is(ModTags.Items.GUN)) { + return; + } + + if (!player.level().isClientSide) { + String origin = stack.getItem().getDescriptionId(); + String name = origin.substring(origin.lastIndexOf(".") + 1); + + // todo other guns +// if (stack.getItem() == ModItems.SENTINEL.get()) { +// AtomicBoolean charged = new AtomicBoolean(false); +// +// stack.getCapability(ForgeCapabilities.ENERGY).ifPresent( +// e -> charged.set(e.getEnergyStored() > 0) +// ); +// +// if (charged.get()) { +// float soundRadius = (float) GunsTool.getGunDoubleTag(stack, "SoundRadius"); +// +// SoundEvent sound3p = BuiltInRegistries.SOUND_EVENT.get(ModUtils.loc( "sentinel_charge_fire_3p")); +// if (sound3p != null) { +// player.playSound(sound3p, soundRadius * 0.4f, 1f); +// } +// +// SoundEvent soundFar = BuiltInRegistries.SOUND_EVENT.get(ModUtils.loc( "sentinel_charge_far")); +// if (soundFar != null) { +// player.playSound(soundFar, soundRadius * 0.7f, 1f); +// } +// +// SoundEvent soundVeryFar = BuiltInRegistries.SOUND_EVENT.get(ModUtils.loc( "sentinel_charge_veryfar")); +// if (soundVeryFar != null) { +// player.playSound(soundVeryFar, soundRadius, 1f); +// } +// +// return; +// } +// } + +// var perk = PerkHelper.getPerkByType(stack, Perk.Type.AMMO); +// +// if (perk == ModPerks.BEAST_BULLET.get()) { +// player.playSound(ModSounds.HENG.get(), 4f, 1f); +// } + + float soundRadius = (float) (GunsTool.getGunDoubleTag(stack, "SoundRadius") * GunsTool.getGunDoubleTag(stack, "CustomSoundRadius", 1)); + + int barrelType = GunsTool.getAttachmentType(stack, GunsTool.AttachmentType.BARREL); + + SoundEvent sound3p = BuiltInRegistries.SOUND_EVENT.get(ModUtils.loc(name + (barrelType == 2 ? "_fire_3p_s" : "_fire_3p"))); + if (sound3p != null) { + player.playSound(sound3p, soundRadius * 0.4f, 1f); + } + + SoundEvent soundFar = BuiltInRegistries.SOUND_EVENT.get(ModUtils.loc(name + (barrelType == 2 ? "_far_s" : "_far"))); + if (soundFar != null) { + player.playSound(soundFar, soundRadius * 0.7f, 1f); + } + + SoundEvent soundVeryFar = BuiltInRegistries.SOUND_EVENT.get(ModUtils.loc(name + (barrelType == 2 ? "_veryfar_s" : "_veryfar"))); + if (soundVeryFar != null) { + player.playSound(soundVeryFar, soundRadius, 1f); + } + } + } + + public static void playGunBoltSounds(Player player) { + ItemStack stack = player.getMainHandItem(); + if (!stack.is(ModTags.Items.GUN)) { + return; + } + + if (!player.level().isClientSide) { + String origin = stack.getItem().getDescriptionId(); + String name = origin.substring(origin.lastIndexOf(".") + 1); + + SoundEvent sound1p = BuiltInRegistries.SOUND_EVENT.get(ModUtils.loc(name + "_bolt")); + if (sound1p != null && player instanceof ServerPlayer serverPlayer) { + SoundTool.playLocalSound(serverPlayer, sound1p, 2f, 1f); + + double shooterHeight = player.getEyePosition().distanceTo((Vec3.atLowerCornerOf(player.level().clip(new ClipContext(player.getEyePosition(), player.getEyePosition().add(new Vec3(0, -1, 0).scale(10)), + ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)).getBlockPos()))); + + if (stack.is(ModTags.Items.REVOLVER)) return; + + ModUtils.queueServerWork((int) (GunsTool.getGunDoubleTag(stack, "BoltActionTime", 0) / 2 + 1.5 * shooterHeight), () -> { + if (stack.is(ModTags.Items.SHOTGUN)) { + SoundTool.playLocalSound(serverPlayer, ModSounds.SHELL_CASING_SHOTGUN.get(), (float) Math.max(0.75 - 0.12 * shooterHeight, 0), 1); + } else if (stack.is(ModTags.Items.SNIPER_RIFLE)) { + SoundTool.playLocalSound(serverPlayer, ModSounds.SHELL_CASING_50CAL.get(), (float) Math.max(1 - 0.15 * shooterHeight, 0), 1); + } else { + SoundTool.playLocalSound(serverPlayer, ModSounds.SHELL_CASING_NORMAL.get(), (float) Math.max(1.5 - 0.2 * shooterHeight, 0), 1); + } + }); + } + } + } + + public static void gunShoot(Player player, double spared) { + ItemStack stack = player.getMainHandItem(); + + if (!player.level().isClientSide()) { + float headshot = (float) GunsTool.getGunDoubleTag(stack, "Headshot", 0); + float damage = (float) (GunsTool.getGunDoubleTag(stack, "Damage", 0) + + GunsTool.getGunDoubleTag(stack, "ChargedDamage", 0)) * (float) perkDamage(stack); + float velocity = (float) ((GunsTool.getGunDoubleTag(stack, "Velocity", 0) + GunsTool.getGunDoubleTag(stack, "CustomVelocity", 0)) * perkSpeed(stack)); + int projectileAmount = GunsTool.getGunIntTag(stack, "ProjectileAmount", 1); + float bypassArmorRate = (float) GunsTool.getGunDoubleTag(stack, "BypassesArmor", 0); + + var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE); + boolean zoom = cap != null && cap.zoom; + + // TODO perk +// var perk = PerkHelper.getPerkByType(stack, Perk.Type.AMMO); +// +// if (perk != null && perk.descriptionId.equals("butterfly_bullet")) { +// if (handleButterflyBullet(perk, stack, player)) return; +// } + + ProjectileEntity projectile = new ProjectileEntity(player.level()) + .shooter(player) +// .damage(perk instanceof AmmoPerk ammoPerk && ammoPerk.slug ? projectileAmount * damage : damage) + .damage(damage) + .headShot(headshot) + .zoom(zoom); + +// if (perk instanceof AmmoPerk ammoPerk) { +// int level = PerkHelper.getItemPerkLevel(perk, stack); +// +// bypassArmorRate += ammoPerk.bypassArmorRate + (perk == ModPerks.AP_BULLET.get() ? 0.05f * (level - 1) : 0); +// projectile.setRGB(ammoPerk.rgb); +// +// if (!ammoPerk.mobEffects.get().isEmpty()) { +// int amplifier; +// if (perk.descriptionId.equals("blade_bullet")) { +// amplifier = level / 3; +// } else if (perk.descriptionId.equals("bread_bullet")) { +// amplifier = 1; +// } else { +// amplifier = level - 1; +// } +// +// ArrayList mobEffectInstances = new ArrayList<>(); +// for (MobEffect effect : ammoPerk.mobEffects.get()) { +// mobEffectInstances.add(new MobEffectInstance(effect, 70 + 30 * level, amplifier)); +// } +// projectile.effect(mobEffectInstances); +// } +// +// if (perk.descriptionId.equals("bread_bullet")) { +// projectile.knockback(level * 0.3f); +// projectile.forceKnockback(); +// } +// } + + bypassArmorRate = Math.max(bypassArmorRate, 0); + projectile.bypassArmorRate(bypassArmorRate); + +// if (perk == ModPerks.SILVER_BULLET.get()) { +// int level = PerkHelper.getItemPerkLevel(perk, stack); +// projectile.undeadMultiple(1.0f + 0.5f * level); +// } else if (perk == ModPerks.BEAST_BULLET.get()) { +// projectile.beast(); +// } else if (perk == ModPerks.JHP_BULLET.get()) { +// int level = PerkHelper.getItemPerkLevel(perk, stack); +// projectile.jhpBullet(level); +// } else if (perk == ModPerks.HE_BULLET.get()) { +// int level = PerkHelper.getItemPerkLevel(perk, stack); +// projectile.heBullet(level); +// } else if (perk == ModPerks.INCENDIARY_BULLET.get()) { +// int level = PerkHelper.getItemPerkLevel(perk, stack); +// projectile.fireBullet(level, stack.is(ModTags.Items.SHOTGUN)); +// } +// +// var dmgPerk = PerkHelper.getPerkByType(stack, Perk.Type.DAMAGE); +// if (dmgPerk == ModPerks.MONSTER_HUNTER.get()) { +// int level = PerkHelper.getItemPerkLevel(dmgPerk, stack); +// projectile.monsterMultiple(0.1f + 0.1f * level); +// } + + projectile.setPos(player.getX() - 0.1 * player.getLookAngle().x, player.getEyeY() - 0.1 - 0.1 * player.getLookAngle().y, player.getZ() + -0.1 * player.getLookAngle().z); + projectile.shoot(player, player.getLookAngle().x, player.getLookAngle().y + 0.001f, player.getLookAngle().z, +// TODO incendiary bullet +// stack.is(ModTags.Items.SHOTGUN) && perk == ModPerks.INCENDIARY_BULLET.get() ? 4.5f : velocity, + velocity, + (float) spared); + player.level().addFreshEntity(projectile); + } + } + + public static double perkDamage(ItemStack stack) { +// var perk = PerkHelper.getPerkByType(stack, Perk.Type.AMMO); +// if (perk instanceof AmmoPerk ammoPerk) { +// return ammoPerk.damageRate; +// } + return 1; + } + + public static double perkSpeed(ItemStack stack) { +// var perk = PerkHelper.getPerkByType(stack, Perk.Type.AMMO); +// if (perk instanceof AmmoPerk ammoPerk) { +// return ammoPerk.speedRate; +// } + return 1; + } + + @SuppressWarnings("ConstantValue") + private static boolean handleButterflyBullet(Perk perk, ItemStack heldItem, Player player) { +// int perkLevel = PerkHelper.getItemPerkLevel(perk, heldItem); + +// var entityType = CompatHolder.VRC_RAIN_SHOWER_BUTTERFLY; +// if (entityType != null) { +// Projectile projectile = entityType.create(player.level()); +// +// float inaccuracy = Math.max(0.0f, 1.1f - perkLevel * .1f); +// projectile.setOwner(player); +// projectile.setPos(player.getX() - 0.1 * player.getLookAngle().x, +// player.getEyeY() - 0.1 - 0.1 * player.getLookAngle().y, player.getZ() + -0.1 * player.getLookAngle().z); +// +// Vec3 vec3 = (new Vec3(player.getLookAngle().x, player.getLookAngle().y + 0.001f, player.getLookAngle().z)).normalize().scale(1.2). +// add(player.level().random.triangle(0.0D, 0.0172275D * (double) inaccuracy), +// player.level().random.triangle(0.0D, 0.0172275D * (double) inaccuracy), +// player.level().random.triangle(0.0D, 0.0172275D * (double) inaccuracy)). +// add(player.getDeltaMovement().x, player.onGround() ? 0.0 : 0.05 * player.getDeltaMovement().y, player.getDeltaMovement().z). +// scale(5.0f); +// projectile.setDeltaMovement(vec3); +// projectile.setYRot((float) (Mth.atan2(vec3.x, vec3.z) * (double) (180F / (float) Math.PI))); +// projectile.setXRot((float) (Mth.atan2(vec3.y, vec3.horizontalDistance()) * (double) (180F / (float) Math.PI))); +// projectile.yRotO = projectile.getYRot(); +// projectile.xRotO = projectile.getXRot(); +// +// projectile.setNoGravity(true); +// player.level().addFreshEntity(projectile); +// return true; +// } + + return false; + } + + /** + * 通用的武器换弹流程 + */ + private static void handleGunReload(Player player) { + ItemStack stack = player.getMainHandItem(); + if (!(stack.getItem() instanceof GunItem gunItem)) return; + + CompoundTag tag = NBTTool.getOrCreateTag(stack); + CompoundTag data = NBTTool.getOrCreateTag(stack).getCompound("GunData"); + // 启动换弹 + if (GunsTool.getGunBooleanTag(stack, "StartReload")) { + + // TODO reload event +// NeoForge.EVENT_BUS.post(new ReloadEvent.Pre(player, stack)); + if (gunItem.isOpenBolt(stack)) { + if (GunsTool.getGunIntTag(stack, "Ammo", 0) == 0) { + data.putInt("ReloadTime", data.getInt("EmptyReloadTime") + 1); + NBTTool.getOrCreateTag(stack).putBoolean("is_empty_reloading", true); + playGunEmptyReloadSounds(player); + } else { + data.putInt("ReloadTime", data.getInt("NormalReloadTime") + 1); + NBTTool.getOrCreateTag(stack).putBoolean("is_normal_reloading", true); + playGunNormalReloadSounds(player); + } + } else { + data.putInt("ReloadTime", data.getInt("EmptyReloadTime") + 2); + NBTTool.getOrCreateTag(stack).putBoolean("is_empty_reloading", true); + playGunEmptyReloadSounds(player); + } + data.putBoolean("StartReload", false); + } + + if (data.getInt("ReloadTime") > 0) { + data.putInt("ReloadTime", data.getInt("ReloadTime") - 1); + } + + // todo other guns +// if (stack.getItem() == ModItems.RPG.get()) { +// if (data.getInt("ReloadTime") == 84) { +// tag.putBoolean("empty", false); +// } +// if (data.getInt("ReloadTime") == 9) { +// data.putBoolean("CloseHammer", false); +// } +// } +// +// if (stack.getItem() == ModItems.MK_14.get()) { +// if (data.getInt("ReloadTime") == 18) { +// data.putBoolean("HoldOpen", false); +// } +// } +// +// if (stack.getItem() == ModItems.SVD.get()) { +// if (data.getInt("ReloadTime") == 17) { +// data.putBoolean("HoldOpen", false); +// } +// } +// +// if (stack.getItem() == ModItems.SKS.get()) { +// if (data.getInt("ReloadTime") == 14) { +// data.putBoolean("HoldOpen", false); +// } +// } +// +// if (stack.getItem() == ModItems.M_60.get()) { +// if (data.getInt("ReloadTime") == 55) { +// data.putBoolean("HideBulletChain", false); +// } +// } +// +// if (stack.getItem() == ModItems.GLOCK_17.get() || stack.getItem() == ModItems.GLOCK_18.get() || stack.getItem() == ModItems.M_1911.get() || stack.getItem() == ModItems.MP_443.get()) { +// if (data.getInt("ReloadTime") == 9) { +// data.putBoolean("HoldOpen", false); +// } +// } +// +// if (stack.getItem() == ModItems.QBZ_95.get()) { +// if (data.getInt("ReloadTime") == 14) { +// data.putBoolean("HoldOpen", false); +// } +// } + + if (data.getInt("ReloadTime") == 1) { + if (gunItem.isOpenBolt(stack)) { + if (GunsTool.getGunIntTag(stack, "Ammo", 0) == 0) { + playGunEmptyReload(player); + } else { + playGunNormalReload(player); + } + } else { + playGunEmptyReload(player); + } + data.putBoolean("StartReload", false); + } + + tag.put("GunData", data); + } + + public static void playGunNormalReload(Player player) { + ItemStack stack = player.getMainHandItem(); + if (!(stack.getItem() instanceof GunItem gunItem)) return; + + if (player.getInventory().hasAnyMatching(item -> item.is(ModItems.CREATIVE_AMMO_BOX.get()))) { + GunsTool.setGunIntTag(stack, "Ammo", GunsTool.getGunIntTag(stack, "Magazine", 0) + + GunsTool.getGunIntTag(stack, "CustomMagazine", 0) + + (gunItem.hasBulletInBarrel(stack) ? 1 : 0)); + } else { + if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO)) { + GunsTool.reload(player, stack, AmmoType.SHOTGUN, gunItem.hasBulletInBarrel(stack)); + } else if (stack.is(ModTags.Items.USE_SNIPER_AMMO)) { + GunsTool.reload(player, stack, AmmoType.SNIPER, true); + } else if (stack.is(ModTags.Items.USE_HANDGUN_AMMO)) { + GunsTool.reload(player, stack, AmmoType.HANDGUN, true); + } else if (stack.is(ModTags.Items.USE_RIFLE_AMMO)) { + GunsTool.reload(player, stack, AmmoType.RIFLE, gunItem.hasBulletInBarrel(stack)); + } else if (stack.is(ModTags.Items.USE_HEAVY_AMMO)) { + GunsTool.reload(player, stack, AmmoType.HEAVY, gunItem.hasBulletInBarrel(stack)); + } + } + NBTTool.getOrCreateTag(stack).putBoolean("is_normal_reloading", false); + NBTTool.getOrCreateTag(stack).putBoolean("is_empty_reloading", false); + + // TODO reload event +// NeoForge.EVENT_BUS.post(new ReloadEvent.Post(player, stack)); + } + + public static void playGunEmptyReload(Player player) { + ItemStack stack = player.getMainHandItem(); + + if (player.getInventory().hasAnyMatching(item -> item.is(ModItems.CREATIVE_AMMO_BOX.get()))) { + GunsTool.setGunIntTag(stack, "Ammo", GunsTool.getGunIntTag(stack, "Magazine", 0) + + GunsTool.getGunIntTag(stack, "CustomMagazine", 0)); + } else { + if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO)) { + GunsTool.reload(player, stack, AmmoType.SHOTGUN); + } else if (stack.is(ModTags.Items.USE_SNIPER_AMMO)) { + GunsTool.reload(player, stack, AmmoType.SNIPER); + } else if (stack.is(ModTags.Items.USE_HANDGUN_AMMO)) { + GunsTool.reload(player, stack, AmmoType.HANDGUN); + } else if (stack.is(ModTags.Items.USE_RIFLE_AMMO)) { + GunsTool.reload(player, stack, AmmoType.RIFLE); + } else if (stack.is(ModTags.Items.USE_HEAVY_AMMO)) { + GunsTool.reload(player, stack, AmmoType.HEAVY); + } + // todo other guns +// } else if (stack.getItem() == ModItems.TASER.get()) { +// GunsTool.setGunIntTag(stack, "Ammo", 1); +// player.getInventory().clearOrCountMatchingItems(p -> p.getItem() == ModItems.TASER_ELECTRODE.get(), 1, player.inventoryMenu.getCraftSlots()); +// } else if (stack.getItem() == ModItems.M_79.get()) { +// GunsTool.setGunIntTag(stack, "Ammo", 1); +// player.getInventory().clearOrCountMatchingItems(p -> p.getItem() == ModItems.GRENADE_40MM.get(), 1, player.inventoryMenu.getCraftSlots()); +// } else if (stack.getItem() == ModItems.RPG.get()) { +// GunsTool.setGunIntTag(stack, "Ammo", 1); +// player.getInventory().clearOrCountMatchingItems(p -> p.getItem() == ModItems.ROCKET.get(), 1, player.inventoryMenu.getCraftSlots()); +// } else if (stack.getItem() == ModItems.JAVELIN.get()) { +// GunsTool.setGunIntTag(stack, "Ammo", 1); +// player.getInventory().clearOrCountMatchingItems(p -> p.getItem() == ModItems.JAVELIN_MISSILE.get(), 1, player.inventoryMenu.getCraftSlots()); +// } + } + + NBTTool.getOrCreateTag(stack).putBoolean("is_normal_reloading", false); + NBTTool.getOrCreateTag(stack).putBoolean("is_empty_reloading", false); + + // TODO reload event +// NeoForge.EVENT_BUS.post(new ReloadEvent.Post(player, stack)); + } + + public static void playGunEmptyReloadSounds(Player player) { + ItemStack stack = player.getMainHandItem(); + if (!stack.is(ModTags.Items.GUN)) { + return; + } + + if (!player.level().isClientSide) { + String origin = stack.getItem().getDescriptionId(); + String name = origin.substring(origin.lastIndexOf(".") + 1); + + SoundEvent sound1p = BuiltInRegistries.SOUND_EVENT.get(ModUtils.loc(name + "_reload_empty")); + if (sound1p != null && player instanceof ServerPlayer serverPlayer) { + SoundTool.playLocalSound(serverPlayer, sound1p, 10f, 1f); + } + } + } + + public static void playGunNormalReloadSounds(Player player) { + ItemStack stack = player.getMainHandItem(); + if (!stack.is(ModTags.Items.GUN)) { + return; + } + + if (!player.level().isClientSide) { + String origin = stack.getItem().getDescriptionId(); + String name = origin.substring(origin.lastIndexOf(".") + 1); + + SoundEvent sound1p; + + sound1p = BuiltInRegistries.SOUND_EVENT.get(ModUtils.loc(name + "_reload_normal")); + + if (sound1p != null && player instanceof ServerPlayer serverPlayer) { + SoundTool.playLocalSound(serverPlayer, sound1p, 10f, 1f); + } + } + } + + /** + * 单发装填类的武器换弹流程 + */ + private static void handleGunSingleReload(Player player) { + ItemStack stack = player.getMainHandItem(); + CompoundTag tag = NBTTool.getOrCreateTag(stack); + + // 换弹流程计时器 + if (tag.getDouble("prepare") > 0) { + tag.putDouble("prepare", tag.getDouble("prepare") - 1); + } + if (tag.getDouble("prepare_load") > 0) { + tag.putDouble("prepare_load", tag.getDouble("prepare_load") - 1); + } + if (tag.getDouble("iterative") > 0) { + tag.putDouble("iterative", tag.getDouble("iterative") - 1); + } + if (tag.getDouble("finish") > 0) { + tag.putDouble("finish", tag.getDouble("finish") - 1); + } + + player.displayClientMessage(Component.literal("prepare: " + new DecimalFormat("##.#").format(tag.getDouble("prepare")) + + " prepare_load: " + new DecimalFormat("##.#").format(tag.getDouble("prepare_load")) + + " iterative: " + new DecimalFormat("##.#").format(tag.getDouble("iterative")) + + " finish: " + new DecimalFormat("##.#").format(tag.getDouble("finish")) + + " reload_stage: " + new DecimalFormat("##.#").format(tag.getDouble("reload_stage")) + ), true); + + // 一阶段 + if (tag.getBoolean("start_single_reload")) { + // todo reload event +// NeoForge.EVENT_BUS.post(new ReloadEvent.Pre(player, stack)); + + if ((GunsTool.getGunIntTag(stack, "PrepareLoadTime", 0) != 0 && GunsTool.getGunIntTag(stack, "Ammo", 0) == 0) +// todo 2nd +// || stack.is(ModItems.SECONDARY_CATACLYSM.get()) + ) { + // 此处判断空仓换弹的时候,是否在准备阶段就需要装填一发,如M870 + playGunPrepareLoadReloadSounds(player); + int prepareLoadTime = GunsTool.getGunIntTag(stack, "PrepareLoadTime", 0); + tag.putInt("prepare_load", prepareLoadTime + 1); + player.getCooldowns().addCooldown(stack.getItem(), prepareLoadTime); + } else if (GunsTool.getGunIntTag(stack, "PrepareEmptyTime", 0) != 0 && GunsTool.getGunIntTag(stack, "Ammo", 0) == 0) { + // 此处判断空仓换弹,如莫辛纳甘 + playGunEmptyPrepareSounds(player); + int prepareEmptyTime = GunsTool.getGunIntTag(stack, "PrepareEmptyTime", 0); + tag.putInt("prepare", prepareEmptyTime + 1); + player.getCooldowns().addCooldown(stack.getItem(), prepareEmptyTime); + } else { + playGunPrepareReloadSounds(player); + int prepareTime = GunsTool.getGunIntTag(stack, "PrepareTime", 0); + tag.putInt("prepare", prepareTime + 1); + player.getCooldowns().addCooldown(stack.getItem(), prepareTime); + } + + tag.putBoolean("force_stop", false); + tag.putBoolean("stop", false); + tag.putInt("reload_stage", 1); + GunsTool.setGunBooleanTag(stack, "Reloading", true); + tag.putBoolean("start_single_reload", false); + } + + // todo other guns +// if (stack.getItem() == ModItems.M_870.get()) { +// if (tag.getInt("prepare_load") == 10) { +// singleLoad(player); +// } +// } +// +// if (stack.getItem() == ModItems.SECONDARY_CATACLYSM.get()) { +// if (tag.getInt("prepare_load") == 3) { +// singleLoad(player); +// } +// } + + // 一阶段结束,检查备弹,如果有则二阶段启动,无则直接跳到三阶段 + if ((tag.getDouble("prepare") == 1 || tag.getDouble("prepare_load") == 1)) { + if (!InventoryTool.hasCreativeAmmoBox(player)) { + var capability = player.getCapability(ModCapabilities.PLAYER_VARIABLE); + if (capability == null) capability = new PlayerVariable(); + + if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO) && capability.shotgunAmmo == 0) { + tag.putBoolean("force_stage3_start", true); + } else if (stack.is(ModTags.Items.USE_SNIPER_AMMO) && capability.sniperAmmo == 0) { + tag.putBoolean("force_stage3_start", true); + } else if ((stack.is(ModTags.Items.USE_HANDGUN_AMMO) || stack.is(ModTags.Items.SMG)) && capability.handgunAmmo == 0) { + tag.putBoolean("force_stage3_start", true); + } else if (stack.is(ModTags.Items.USE_RIFLE_AMMO) && capability.rifleAmmo == 0) { + tag.putBoolean("force_stage3_start", true); + } else if (stack.is(ModTags.Items.USE_HEAVY_AMMO) && capability.heavyAmmo == 0) { + tag.putBoolean("force_stage3_start", true); + } else if (stack.is(ModTags.Items.LAUNCHER) && GunsTool.getGunIntTag(stack, "MaxAmmo") == 0) { + tag.putBoolean("force_stage3_start", true); + // todo 2nd +// } else if (stack.is(ModItems.SECONDARY_CATACLYSM.get()) && GunsTool.getGunIntTag(stack, "Ammo", 0) >= GunsTool.getGunIntTag(stack, "Magazine", 0)) { +// tag.putBoolean("force_stage3_start", true); + } else { + tag.putInt("reload_stage", 2); + } + } else { + // todo 2nd +// if (stack.is(ModItems.SECONDARY_CATACLYSM.get()) && GunsTool.getGunIntTag(stack, "Ammo", 0) >= GunsTool.getGunIntTag(stack, "Magazine", 0)) { +// tag.putBoolean("force_stage3_start", true); +// } else { + tag.putInt("reload_stage", 2); +// } + } + // 检查备弹 + } + + // 强制停止换弹,进入三阶段 + if (tag.getBoolean("force_stop") && tag.getInt("reload_stage") == 2 && tag.getInt("iterative") > 0) { + tag.putBoolean("stop", true); + } + + // 二阶段 + if ((tag.getDouble("prepare") == 0 || tag.getDouble("prepare_load") == 0) + && tag.getInt("reload_stage") == 2 + && tag.getInt("iterative") == 0 + && !tag.getBoolean("stop") + && GunsTool.getGunIntTag(stack, "Ammo", 0) < GunsTool.getGunIntTag(stack, "Magazine", 0) + + GunsTool.getGunIntTag(stack, "CustomMagazine", 0)) { + + playGunLoopReloadSounds(player); + int iterativeTime = GunsTool.getGunIntTag(stack, "IterativeTime", 0); + tag.putDouble("iterative", iterativeTime); + player.getCooldowns().addCooldown(stack.getItem(), iterativeTime); + // 动画播放nbt + if (tag.getDouble("load_index") == 1) { + tag.putDouble("load_index", 0); + } else { + tag.putDouble("load_index", 1); + } + } + + // 装填 todo other guns +// if (stack.getItem() == ModItems.M_870.get() || stack.getItem() == ModItems.MARLIN.get()) { +// if (tag.getInt("iterative") == 3) { +// singleLoad(player); +// } +// } +// +// if (stack.getItem() == ModItems.SECONDARY_CATACLYSM.get()) { +// if (tag.getInt("iterative") == 16) { +// singleLoad(player); +// } +// } +// +// if (stack.getItem() == ModItems.K_98.get() || stack.getItem() == ModItems.MOSIN_NAGANT.get()) { +// if (tag.getInt("iterative") == 1) { +// singleLoad(player); +// } +// } + + // 二阶段结束 + if (tag.getInt("iterative") == 1) { + // 装满结束 + if (GunsTool.getGunIntTag(stack, "Ammo", 0) >= GunsTool.getGunIntTag(stack, "Magazine", 0) + + GunsTool.getGunIntTag(stack, "CustomMagazine", 0)) { + tag.putInt("reload_stage", 3); + } + + // 备弹耗尽结束 + if (!InventoryTool.hasCreativeAmmoBox(player)) { + var capability = player.getCapability(ModCapabilities.PLAYER_VARIABLE); + if (capability == null) capability = new PlayerVariable(); + + if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO) && capability.shotgunAmmo == 0) { + tag.putInt("reload_stage", 3); + } else if (stack.is(ModTags.Items.USE_SNIPER_AMMO) && capability.sniperAmmo == 0) { + tag.putInt("reload_stage", 3); + } else if ((stack.is(ModTags.Items.USE_HANDGUN_AMMO) || stack.is(ModTags.Items.SMG)) && capability.handgunAmmo == 0) { + tag.putInt("reload_stage", 3); + } else if (stack.is(ModTags.Items.USE_RIFLE_AMMO) && capability.rifleAmmo == 0) { + tag.putInt("reload_stage", 3); + } else if (stack.is(ModTags.Items.USE_HEAVY_AMMO) && capability.heavyAmmo == 0) { + tag.putInt("reload_stage", 3); + } + } + + // 强制结束 + if (tag.getBoolean("stop")) { + tag.putInt("reload_stage", 3); + tag.putBoolean("force_stop", false); + tag.putBoolean("stop", false); + } + } + + // 三阶段 + if ((tag.getInt("iterative") == 1 && tag.getInt("reload_stage") == 3) || tag.getBoolean("force_stage3_start")) { + tag.putInt("reload_stage", 3); + tag.putBoolean("force_stage3_start", false); + int finishTime = GunsTool.getGunIntTag(stack, "FinishTime", 0); + tag.putInt("finish", finishTime + 2); + player.getCooldowns().addCooldown(stack.getItem(), finishTime + 2); + playGunEndReloadSounds(player); + } + + // todo marlin +// if (stack.getItem() == ModItems.MARLIN.get() && tag.getInt("finish") == 10) { +// tag.putBoolean("empty", false); +// } + + // 三阶段结束 + if (tag.getInt("finish") == 1) { + tag.putInt("reload_stage", 0); + if (GunsTool.getGunIntTag(stack, "BoltActionTime", 0) > 0) { + GunsTool.setGunBooleanTag(stack, "NeedBoltAction", false); + } + GunsTool.setGunBooleanTag(stack, "Reloading", false); + tag.putBoolean("start_single_reload", false); + + // todo reload event +// NeoForge.EVENT_BUS.post(new ReloadEvent.Post(player, stack)); + } + } + + public static void singleLoad(Player player) { + ItemStack stack = player.getMainHandItem(); + + GunsTool.setGunIntTag(stack, "Ammo", GunsTool.getGunIntTag(stack, "Ammo", 0) + 1); + + if (!InventoryTool.hasCreativeAmmoBox(player)) { + var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE); + if (cap == null) return; + + if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO)) { + AmmoType.SHOTGUN.add(cap, -1); + } else if (stack.is(ModTags.Items.USE_SNIPER_AMMO)) { + AmmoType.SNIPER.add(cap, -1); + } else if (stack.is(ModTags.Items.USE_HANDGUN_AMMO)) { + AmmoType.HANDGUN.add(cap, -1); + } else if (stack.is(ModTags.Items.USE_RIFLE_AMMO)) { + AmmoType.RIFLE.add(cap, -1); + } else if (stack.is(ModTags.Items.USE_HEAVY_AMMO)) { + AmmoType.HEAVY.add(cap, -1); + } + + // todo secondary +// } else if (stack.getItem() == ModItems.SECONDARY_CATACLYSM.get()) { +// player.getInventory().clearOrCountMatchingItems(p -> p.getItem() == ModItems.GRENADE_40MM.get(), 1, player.inventoryMenu.getCraftSlots()); +// } + + cap.syncPlayerVariables(player); + } + } + + public static void playGunPrepareReloadSounds(Player player) { + ItemStack stack = player.getMainHandItem(); + if (!stack.is(ModTags.Items.GUN)) { + return; + } + + if (!player.level().isClientSide) { + String origin = stack.getItem().getDescriptionId(); + String name = origin.substring(origin.lastIndexOf(".") + 1); + + SoundEvent sound1p = BuiltInRegistries.SOUND_EVENT.get(ModUtils.loc(name + "_prepare")); + if (sound1p != null && player instanceof ServerPlayer serverPlayer) { + SoundTool.playLocalSound(serverPlayer, sound1p, 10f, 1f); + } + } + } + + public static void playGunEmptyPrepareSounds(Player player) { + ItemStack stack = player.getMainHandItem(); + if (!stack.is(ModTags.Items.GUN)) { + return; + } + + if (!player.level().isClientSide) { + String origin = stack.getItem().getDescriptionId(); + String name = origin.substring(origin.lastIndexOf(".") + 1); + + SoundEvent sound1p = BuiltInRegistries.SOUND_EVENT.get(ModUtils.loc(name + "_prepare_empty")); + if (sound1p != null && player instanceof ServerPlayer serverPlayer) { + SoundTool.playLocalSound(serverPlayer, sound1p, 10f, 1f); + + double shooterHeight = player.getEyePosition().distanceTo((Vec3.atLowerCornerOf(player.level().clip(new ClipContext(player.getEyePosition(), player.getEyePosition().add(new Vec3(0, -1, 0).scale(10)), + ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)).getBlockPos()))); + + ModUtils.queueServerWork((int) (GunsTool.getGunIntTag(stack, "PrepareEmptyTime", 0) / 2 + 3 + 1.5 * shooterHeight), () -> { + if (stack.is(ModTags.Items.SHOTGUN)) { + SoundTool.playLocalSound(serverPlayer, ModSounds.SHELL_CASING_SHOTGUN.get(), (float) Math.max(0.75 - 0.12 * shooterHeight, 0), 1); + } else if (stack.is(ModTags.Items.SNIPER_RIFLE) || stack.is(ModTags.Items.HEAVY_WEAPON)) { + SoundTool.playLocalSound(serverPlayer, ModSounds.SHELL_CASING_50CAL.get(), (float) Math.max(1 - 0.15 * shooterHeight, 0), 1); + } else { + SoundTool.playLocalSound(serverPlayer, ModSounds.SHELL_CASING_NORMAL.get(), (float) Math.max(1.5 - 0.2 * shooterHeight, 0), 1); + } + }); + } + } + } + + public static void playGunPrepareLoadReloadSounds(Player player) { + ItemStack stack = player.getMainHandItem(); + if (!stack.is(ModTags.Items.GUN)) { + return; + } + + if (!player.level().isClientSide) { + String origin = stack.getItem().getDescriptionId(); + String name = origin.substring(origin.lastIndexOf(".") + 1); + + SoundEvent sound1p = BuiltInRegistries.SOUND_EVENT.get(ModUtils.loc(name + "_prepare_load")); + if (sound1p != null && player instanceof ServerPlayer serverPlayer) { + SoundTool.playLocalSound(serverPlayer, sound1p, 10f, 1f); + + double shooterHeight = player.getEyePosition().distanceTo((Vec3.atLowerCornerOf(player.level().clip(new ClipContext(player.getEyePosition(), player.getEyePosition().add(new Vec3(0, -1, 0).scale(10)), + ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)).getBlockPos()))); + + ModUtils.queueServerWork((int) (8 + 1.5 * shooterHeight), () -> { + if (stack.is(ModTags.Items.SHOTGUN)) { + SoundTool.playLocalSound(serverPlayer, ModSounds.SHELL_CASING_SHOTGUN.get(), (float) Math.max(0.75 - 0.12 * shooterHeight, 0), 1); + } else if (stack.is(ModTags.Items.SNIPER_RIFLE) || stack.is(ModTags.Items.HEAVY_WEAPON)) { + SoundTool.playLocalSound(serverPlayer, ModSounds.SHELL_CASING_50CAL.get(), (float) Math.max(1 - 0.15 * shooterHeight, 0), 1); + } else { + SoundTool.playLocalSound(serverPlayer, ModSounds.SHELL_CASING_NORMAL.get(), (float) Math.max(1.5 - 0.2 * shooterHeight, 0), 1); + } + }); + } + } + } + + public static void playGunLoopReloadSounds(Player player) { + ItemStack stack = player.getMainHandItem(); + if (!stack.is(ModTags.Items.GUN)) { + return; + } + + if (!player.level().isClientSide) { + String origin = stack.getItem().getDescriptionId(); + String name = origin.substring(origin.lastIndexOf(".") + 1); + + SoundEvent sound1p = BuiltInRegistries.SOUND_EVENT.get(ModUtils.loc(name + "_loop")); + if (sound1p != null && player instanceof ServerPlayer serverPlayer) { + SoundTool.playLocalSound(serverPlayer, sound1p, 10f, 1f); + } + } + } + + public static void playGunEndReloadSounds(Player player) { + ItemStack stack = player.getMainHandItem(); + if (!stack.is(ModTags.Items.GUN)) { + return; + } + + if (!player.level().isClientSide) { + String origin = stack.getItem().getDescriptionId(); + String name = origin.substring(origin.lastIndexOf(".") + 1); + + SoundEvent sound1p = BuiltInRegistries.SOUND_EVENT.get(ModUtils.loc(name + "_end")); + if (sound1p != null && player instanceof ServerPlayer serverPlayer) { + SoundTool.playLocalSound(serverPlayer, sound1p, 10f, 1f); + + double shooterHeight = player.getEyePosition().distanceTo((Vec3.atLowerCornerOf(player.level().clip(new ClipContext(player.getEyePosition(), player.getEyePosition().add(new Vec3(0, -1, 0).scale(10)), + ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)).getBlockPos()))); + + // todo marlin +// if (stack.is(ModItems.MARLIN.get())) { +// ModUtils.queueServerWork((int) (5 + 1.5 * shooterHeight), () -> SoundTool.playLocalSound(serverPlayer, ModSounds.SHELL_CASING_NORMAL.get(), (float) Math.max(1.5 - 0.2 * shooterHeight, 0), 1)); +// } + } + } + } + + /** + * 哨兵充能 + */ + private static void handleSentinelCharge(Player player) { + ItemStack stack = player.getMainHandItem(); + // 启动换弹 + if (GunsTool.getGunBooleanTag(stack, "StartCharge")) { + GunsTool.setGunIntTag(stack, "ChargeTime", 127); + GunsTool.setGunBooleanTag(stack, "Charging", true); + + SoundEvent sound1p = BuiltInRegistries.SOUND_EVENT.get(ModUtils.loc("sentinel_charge")); + if (sound1p != null && player instanceof ServerPlayer serverPlayer) { + SoundTool.playLocalSound(serverPlayer, sound1p, 2f, 1f); + } + + GunsTool.setGunBooleanTag(stack, "StartCharge", false); + } + + if (GunsTool.getGunIntTag(stack, "ChargeTime", 0) > 0) { + GunsTool.setGunIntTag(stack, "ChargeTime", GunsTool.getGunIntTag(stack, "ChargeTime", 0) - 1); + } + + if (GunsTool.getGunIntTag(stack, "ChargeTime", 0) == 17) { + for (var cell : player.getInventory().items) { + if (cell.is(ModItems.CELL.get())) { + var stackStorage = cell.getCapability(Capabilities.EnergyStorage.ITEM); + if (stackStorage == null) continue; + + int stackMaxEnergy = stackStorage.getMaxEnergyStored(); + int stackEnergy = stackStorage.getEnergyStored(); + + var cellStorage = cell.getCapability(Capabilities.EnergyStorage.ITEM); + if (cellStorage == null) continue; + int cellEnergy = cellStorage.getEnergyStored(); + + int stackEnergyNeed = Math.min(cellEnergy, stackMaxEnergy - stackEnergy); + + if (cellEnergy > 0) { + stackStorage.receiveEnergy(stackEnergyNeed, false); + } + cellStorage.extractEnergy(stackEnergyNeed, false); + } + } + } + + if (GunsTool.getGunIntTag(stack, "ChargeTime", 0) == 1) { + GunsTool.setGunBooleanTag(stack, "Charging", false); + } + } + + // TODO missing mapping event +// @SubscribeEvent +// public static void onMissingMappings(MissingMappingsEvent event) { +// for (MissingMappingsEvent.Mapping mapping : event.getAllMappings(Registries.ITEM)) { +// if (ModUtils.MODID.equals(mapping.getKey().getNamespace()) && mapping.getKey().getPath().equals("abekiri")) { +// mapping.remap(ModItems.HOMEMADE_SHOTGUN.get()); +// } +// } +// } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModItems.java b/src/main/java/com/atsuishio/superbwarfare/init/ModItems.java index dc3a38859..1b94fd1d4 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModItems.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModItems.java @@ -7,6 +7,7 @@ import com.atsuishio.superbwarfare.item.common.CannonShellItem; import com.atsuishio.superbwarfare.item.common.MaterialPack; import com.atsuishio.superbwarfare.item.common.ammo.*; import com.atsuishio.superbwarfare.item.common.ammo.box.AmmoBox; +import com.atsuishio.superbwarfare.item.gun.smg.VectorItem; import com.atsuishio.superbwarfare.tools.AmmoType; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; @@ -34,7 +35,7 @@ public class ModItems { // public static final DeferredHolder M_1911 = GUNS.register("m_1911", M1911Item::new); // public static final DeferredHolder HOMEMADE_SHOTGUN = GUNS.register("homemade_shotgun", HomemadeShotgunItem::new); // public static final DeferredHolder TRACHELIUM = GUNS.register("trachelium", Trachelium::new); -// public static final DeferredHolder VECTOR = GUNS.register("vector", VectorItem::new); +public static final DeferredHolder VECTOR = GUNS.register("vector", VectorItem::new); // public static final DeferredHolder AK_47 = GUNS.register("ak_47", AK47Item::new); // public static final DeferredHolder AK_12 = GUNS.register("ak_12", AK12Item::new); // public static final DeferredHolder SKS = GUNS.register("sks", SksItem::new); diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModProperties.java b/src/main/java/com/atsuishio/superbwarfare/init/ModProperties.java index 5fb02cb9c..17e2cf32d 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModProperties.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModProperties.java @@ -1,7 +1,5 @@ package com.atsuishio.superbwarfare.init; -import com.atsuishio.superbwarfare.ModUtils; -import net.minecraft.client.renderer.item.ItemProperties; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.common.EventBusSubscriber; @@ -12,8 +10,8 @@ public class ModProperties { @SubscribeEvent public static void propertyOverrideRegistry(FMLClientSetupEvent event) { // event.enqueueWork(() -> ItemProperties.register(ModItems.MONITOR.get(), ModUtils.loc("monitor_linked"), -// (itemStack, clientWorld, livingEntity, seed) -> ItemNBTTool.getBoolean(itemStack, "Linked", false) ? 1.0F : 0.0F)); +// (itemStack, clientWorld, livingEntity, seed) -> GunNBTTool.getBoolean(itemStack, "Linked", false) ? 1.0F : 0.0F)); // event.enqueueWork(() -> ItemProperties.register(ModItems.ARMOR_PLATE.get(), ModUtils.loc("armor_plate_infinite"), -// (itemStack, clientWorld, livingEntity, seed) -> ItemNBTTool.getBoolean(itemStack, "Infinite", false) ? 1.0F : 0.0F)); +// (itemStack, clientWorld, livingEntity, seed) -> GunNBTTool.getBoolean(itemStack, "Infinite", false) ? 1.0F : 0.0F)); } } \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModTabs.java b/src/main/java/com/atsuishio/superbwarfare/init/ModTabs.java index cb120aff0..dd5f73b49 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModTabs.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModTabs.java @@ -2,6 +2,7 @@ package com.atsuishio.superbwarfare.init; import com.atsuishio.superbwarfare.ModUtils; import com.atsuishio.superbwarfare.item.BatteryItem; +import com.atsuishio.superbwarfare.item.gun.smg.VectorItem; import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; import net.minecraft.world.item.CreativeModeTab; @@ -18,12 +19,13 @@ public class ModTabs { public static final DeferredRegister TABS = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, ModUtils.MODID); - // public static final DeferredHolder GUN_TAB = TABS.register("guns", -// () -> CreativeModeTab.builder() -// .title(Component.translatable("item_group.superbwarfare.guns")) + public static final DeferredHolder GUN_TAB = TABS.register("guns", + () -> CreativeModeTab.builder() + .title(Component.translatable("item_group.superbwarfare.guns")) // .icon(() -> new ItemStack(ModItems.TASER.get())) -// .displayItems( -// (param, output) -> { + .icon(() -> new ItemStack(ModItems.VECTOR.get())) + .displayItems( + (param, output) -> { // output.accept(TaserItem.getGunInstance()); // output.accept(Glock17Item.getGunInstance()); // output.accept(Glock18Item.getGunInstance()); @@ -31,7 +33,7 @@ public class ModTabs { // output.accept(Mp443Item.getGunInstance()); // output.accept(HomemadeShotgunItem.getGunInstance()); // output.accept(Trachelium.getGunInstance()); -// output.accept(VectorItem.getGunInstance()); + output.accept(VectorItem.getGunInstance()); // output.accept(SksItem.getGunInstance()); // output.accept(AK47Item.getGunInstance()); // output.accept(AK12Item.getGunInstance()); @@ -58,10 +60,10 @@ public class ModTabs { // output.accept(SecondaryCataclysm.getGunInstance()); // output.accept(RpgItem.getGunInstance()); // output.accept(JavelinItem.getGunInstance()); -// } -// ) -// .build()); -// + } + ) + .build()); + // public static final DeferredHolder PERK_TAB = TABS.register("perk", () -> CreativeModeTab.builder() .title(Component.translatable("item_group.superbwarfare.perk")) diff --git a/src/main/java/com/atsuishio/superbwarfare/item/gun/GunEvents.java b/src/main/java/com/atsuishio/superbwarfare/item/gun/GunEvents.java new file mode 100644 index 000000000..6738c26ee --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/item/gun/GunEvents.java @@ -0,0 +1,20 @@ +package com.atsuishio.superbwarfare.item.gun; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.init.ModTags; +import com.atsuishio.superbwarfare.tools.NBTTool; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.event.entity.player.ItemEntityPickupEvent; + +@EventBusSubscriber(modid = ModUtils.MODID) +public class GunEvents { + @SubscribeEvent + public static void onPickup(ItemEntityPickupEvent.Pre event) { + var stack = event.getItemEntity().getItem(); + if (stack.is(ModTags.Items.GUN)) { + NBTTool.getOrCreateTag(stack).putBoolean("draw", true); + NBTTool.getOrCreateTag(stack).putBoolean("init", true); + } + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/item/gun/GunItem.java b/src/main/java/com/atsuishio/superbwarfare/item/gun/GunItem.java new file mode 100644 index 000000000..c1cabecea --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/item/gun/GunItem.java @@ -0,0 +1,440 @@ +package com.atsuishio.superbwarfare.item.gun; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.capability.ModCapabilities; +import com.atsuishio.superbwarfare.client.PoseTool; +import com.atsuishio.superbwarfare.client.tooltip.component.GunImageComponent; +import com.atsuishio.superbwarfare.init.ModItems; +import com.atsuishio.superbwarfare.init.ModTags; +import com.atsuishio.superbwarfare.perk.Perk; +import com.atsuishio.superbwarfare.tools.AmmoType; +import com.atsuishio.superbwarfare.tools.GunsTool; +import com.atsuishio.superbwarfare.tools.NBTTool; +import net.minecraft.client.model.HumanoidModel; +import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.tooltip.TooltipComponent; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.extensions.common.IClientItemExtensions; +import net.neoforged.neoforge.client.extensions.common.RegisterClientExtensionsEvent; +import org.jetbrains.annotations.NotNull; +import software.bernie.geckolib.renderer.GeoItemRenderer; + +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.Optional; +import java.util.Set; + +@EventBusSubscriber(modid = ModUtils.MODID, bus = EventBusSubscriber.Bus.MOD) +public abstract class GunItem extends Item { + + public GunItem(Properties properties) { + super(properties); + } + + @Override + @ParametersAreNonnullByDefault + public boolean canAttackBlock(BlockState pState, Level pLevel, BlockPos pPos, Player pPlayer) { + return false; + } + + @Override + @ParametersAreNonnullByDefault + public void inventoryTick(ItemStack stack, Level level, Entity entity, int slot, boolean selected) { + if (!(entity instanceof LivingEntity)) return; + if (!stack.is(ModTags.Items.GUN)) return; + if (!(stack.getItem() instanceof GunItem gunItem)) return; + + if (!NBTTool.getBoolean(stack, "init", false)) { + GunsTool.initGun(level, stack, this.getDescriptionId().substring(this.getDescriptionId().lastIndexOf('.') + 1)); + GunsTool.generateAndSetUUID(stack); + NBTTool.setBoolean(stack, "init", true); + } + + if (NBTTool.getOrCreateTag(stack).getBoolean("draw")) { + NBTTool.getOrCreateTag(stack).putBoolean("draw", false); + } + + handleGunPerks(stack); + handleGunAttachment(stack); + + if ((gunItem.hasBulletInBarrel(stack) && GunsTool.getGunIntTag(stack, "Ammo", 0) > + GunsTool.getGunIntTag(stack, "Magazine", 0) + GunsTool.getGunIntTag(stack, "CustomMagazine", 0) + 1) + || (!gunItem.hasBulletInBarrel(stack) && GunsTool.getGunIntTag(stack, "Ammo", 0) > + GunsTool.getGunIntTag(stack, "Magazine", 0) + GunsTool.getGunIntTag(stack, "CustomMagazine", 0)) + ) { + int count = GunsTool.getGunIntTag(stack, "Ammo", 0) - GunsTool.getGunIntTag(stack, "Magazine", 0) + + GunsTool.getGunIntTag(stack, "CustomMagazine", 0) - (gunItem.hasBulletInBarrel(stack) ? 1 : 0); + + var capability = entity.getCapability(ModCapabilities.PLAYER_VARIABLE); + + if (capability != null) { + if (stack.is(ModTags.Items.USE_SHOTGUN_AMMO)) { + AmmoType.SHOTGUN.add(capability, count); + } else if (stack.is(ModTags.Items.USE_SNIPER_AMMO)) { + AmmoType.SNIPER.add(capability, count); + } else if (stack.is(ModTags.Items.USE_HANDGUN_AMMO)) { + AmmoType.HANDGUN.add(capability, count); + } else if (stack.is(ModTags.Items.USE_RIFLE_AMMO)) { + AmmoType.RIFLE.add(capability, count); + } else if (stack.is(ModTags.Items.USE_HEAVY_AMMO)) { + AmmoType.HEAVY.add(capability, count); + } + + capability.syncPlayerVariables(entity); + } + + GunsTool.setGunIntTag(stack, "Ammo", GunsTool.getGunIntTag(stack, "Magazine", 0) + + GunsTool.getGunIntTag(stack, "CustomMagazine", 0) + (gunItem.hasBulletInBarrel(stack) ? 1 : 0)); + } + } + + @Override + @ParametersAreNonnullByDefault + public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) { + return false; + } + + // TODO attribute modifier +// @Override +// public @NotNull ItemAttributeModifiers getDefaultAttributeModifiers(@NotNull ItemStack stack) { +// ItemAttributeModifiers map = super.getDefaultAttributeModifiers(stack); +// map.builder().add( +// Attribute.BASE, +// new AttributeModifier(uuid, ModUtils.ATTRIBUTE_MODIFIER, +// -0.01f - 0.005f * (GunsTool.getGunDoubleTag(stack, "Weight") + GunsTool.getGunDoubleTag(stack, "CustomWeight")), +// AttributeModifier.Operation.ADD_MULTIPLIED_BASE) +// ) +// +// map.put(Attributes.MOVEMENT_SPEED, +// new AttributeModifier(uuid, ModUtils.ATTRIBUTE_MODIFIER, +// -0.01f - 0.005f * (GunsTool.getGunDoubleTag(stack, "Weight") + GunsTool.getGunDoubleTag(stack, "CustomWeight")), +// AttributeModifier.Operation.ADD_MULTIPLIED_BASE)); +// return map; +// } + +// @Override +// public Multimap getAttributeModifiers(EquipmentSlot slot, ItemStack stack) { +// Multimap map = super.getAttributeModifiers(slot, stack); +// UUID uuid = new UUID(slot.toString().hashCode(), 0); +// if (slot == EquipmentSlot.MAINHAND) { +// map = HashMultimap.create(map); +// map.put(Attributes.MOVEMENT_SPEED, +// new AttributeModifier(uuid, ModUtils.ATTRIBUTE_MODIFIER, +// -0.01f - 0.005f * (GunsTool.getGunDoubleTag(stack, "Weight") + GunsTool.getGunDoubleTag(stack, "CustomWeight")), +// AttributeModifier.Operation.ADD_MULTIPLIED_BASE)); +// } +// return map; +// } + + @Override + public @NotNull Optional getTooltipImage(@NotNull ItemStack pStack) { + return Optional.of(new GunImageComponent(pStack)); + } + + public Set getReloadSound() { + return Set.of(); + } + + public ResourceLocation getGunIcon() { + return ModUtils.loc("textures/gun_icon/default_icon.png"); + } + + public String getGunDisplayName() { + return ""; + } + + @Override + public boolean isFoil(@NotNull ItemStack stack) { + return false; + } + + @Override + public boolean isEnchantable(@NotNull ItemStack stack) { + return false; + } + + @Override + @ParametersAreNonnullByDefault + public boolean supportsEnchantment(ItemStack stack, Holder enchantment) { + return false; + } + + + private void handleGunPerks(ItemStack stack) { + reducePerkTagCoolDown(stack, "HealClipTime", "KillClipReloadTime", "KillClipTime", "FourthTimesCharmTick", "HeadSeeker", + "DesperadoTime", "DesperadoTimePost"); + + // TODO perk +// if (PerkHelper.getItemPerkLevel(ModPerks.FOURTH_TIMES_CHARM.get(), stack) > 0) { +// int count = GunsTool.getPerkIntTag(stack, "FourthTimesCharmCount"); +// if (count >= 4) { +// GunsTool.setPerkIntTag(stack, "FourthTimesCharmTick", 0); +// GunsTool.setPerkIntTag(stack, "FourthTimesCharmCount", 0); +// +// int mag = GunsTool.getGunIntTag(stack, "Magazine", 0) + GunsTool.getGunIntTag(stack, "CustomMagazine", 0); +// GunsTool.setGunIntTag(stack, "Ammo", Math.min(mag, GunsTool.getGunIntTag(stack, "Ammo", 0) + 2)); +// } +// } + } + + private void handleGunAttachment(ItemStack stack) { + CompoundTag tag = NBTTool.getOrCreateTag(stack).getCompound("Attachments"); + + double scopeWeight = switch (tag.getInt("Scope")) { + case 1 -> 0.5; + case 2 -> 1; + case 3 -> 1.5; + default -> 0; + }; + + double barrelWeight = switch (tag.getInt("Barrel")) { + case 1 -> 0.5; + case 2 -> 1; + default -> 0; + }; + + double magazineWeight = switch (tag.getInt("Magazine")) { + case 1 -> 1; + case 2 -> 2; + default -> 0; + }; + + double stockWeight = switch (tag.getInt("Stock")) { + case 1 -> -2; + case 2 -> 1.5; + default -> 0; + }; + + double gripWeight = switch (tag.getInt("Grip")) { + case 1, 2 -> 0.25; + case 3 -> 1; + default -> 0; + }; + + double soundRadius = tag.getInt("Barrel") == 2 ? 0.6 : 1; + + GunsTool.setGunDoubleTag(stack, "CustomWeight", scopeWeight + barrelWeight + magazineWeight + stockWeight + gripWeight); + GunsTool.setGunDoubleTag(stack, "CustomSoundRadius", soundRadius); + } + + public boolean canApplyPerk(Perk perk) { + return true; + } + + private void reducePerkTagCoolDown(ItemStack stack, String... tags) { + var tag = NBTTool.getOrCreateTag(stack); + var compound = tag.getCompound("PerkData"); + + for (String t : tags) { + if (!compound.contains(t)) { + continue; + } + + if (compound.getInt(t) > 0) { + compound.putInt(t, Math.max(0, compound.getInt(t) - 1)); + } + } + tag.put("PerkData", compound); + } + + /** + * 是否使用弹匣换弹 + * + * @param stack 武器物品 + */ + public boolean isMagazineReload(ItemStack stack) { + return false; + } + + /** + * 是否使用弹夹换弹 + * + * @param stack 武器物品 + */ + public boolean isClipReload(ItemStack stack) { + return false; + } + + /** + * 是否是单发装填换弹 + * + * @param stack 武器物品 + */ + public boolean isIterativeReload(ItemStack stack) { + return false; + } + + /** + * 开膛待击 + * + * @param stack 武器物品 + */ + public boolean isOpenBolt(ItemStack stack) { + return false; + } + + /** + * 是否允许额外往枪管里塞入一发子弹 + * + * @param stack 武器物品 + */ + public boolean hasBulletInBarrel(ItemStack stack) { + return false; + } + + /** + * 武器是否为全自动武器 + * + * @param stack 武器物品 + */ + public boolean isAutoWeapon(ItemStack stack) { + return false; + } + + /** + * 武器是否直接使用背包内的弹药物品进行发射,而不是使用玩家存储的弹药 + * + * @param stack 武器物品 + */ + public boolean useBackpackAmmo(ItemStack stack) { + return false; + } + + /** + * 武器是否能进行改装 + * + * @param stack 武器物品 + */ + public boolean isCustomizable(ItemStack stack) { + return false; + } + + /** + * 武器是否能更换枪管配件 + * + * @param stack 武器物品 + */ + public boolean hasCustomBarrel(ItemStack stack) { + return false; + } + + /** + * 武器是否能更换枪托配件 + * + * @param stack 武器物品 + */ + public boolean hasCustomGrip(ItemStack stack) { + return false; + } + + /** + * 武器是否能更换弹匣配件 + * + * @param stack 武器物品 + */ + public boolean hasCustomMagazine(ItemStack stack) { + return false; + } + + /** + * 武器是否能更换瞄具配件 + * + * @param stack 武器物品 + */ + public boolean hasCustomScope(ItemStack stack) { + return false; + } + + /** + * 武器是否能更换枪托配件 + * + * @param stack 武器物品 + */ + public boolean hasCustomStock(ItemStack stack) { + return false; + } + + /** + * 武器是否有脚架 + * + * @param stack 武器物品 + */ + public boolean hasBipod(ItemStack stack) { + return false; + } + + /** + * 武器是否会抛壳 + * + * @param stack 武器物品 + */ + public boolean canEjectShell(ItemStack stack) { + return false; + } + + /** + * 武器是否能进行近战攻击 + * + * @param stack 武器物品 + */ + public boolean hasMeleeAttack(ItemStack stack) { + return false; + } + + /** + * 获取武器可用的开火模式 + */ + public int getAvailableFireModes() { + return 0; + } + + public enum FireMode { + SEMI(1), + BURST(2), + AUTO(4); + + public final int flag; + + FireMode(int i) { + this.flag = i; + } + } + + public abstract GeoItemRenderer getRenderer(); + + @SubscribeEvent + private static void registerGunExtensions(RegisterClientExtensionsEvent event) { + for (var item : ModItems.GUNS.getEntries()) { + if (item.get() instanceof GunItem gun) { + event.registerItem(new IClientItemExtensions() { + private final BlockEntityWithoutLevelRenderer renderer = gun.getRenderer(); + + @Override + public @NotNull BlockEntityWithoutLevelRenderer getCustomRenderer() { + return renderer; + } + + @Override + @ParametersAreNonnullByDefault + public HumanoidModel.ArmPose getArmPose(LivingEntity entityLiving, InteractionHand hand, ItemStack stack) { + return PoseTool.pose(entityLiving, hand, stack); + } + }, item); + } + } + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/item/gun/smg/VectorItem.java b/src/main/java/com/atsuishio/superbwarfare/item/gun/smg/VectorItem.java new file mode 100644 index 000000000..8affafef5 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/item/gun/smg/VectorItem.java @@ -0,0 +1,231 @@ +package com.atsuishio.superbwarfare.item.gun.smg; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.capability.ModCapabilities; +import com.atsuishio.superbwarfare.client.renderer.item.VectorItemRenderer; +import com.atsuishio.superbwarfare.event.ClientEventHandler; +import com.atsuishio.superbwarfare.init.ModItems; +import com.atsuishio.superbwarfare.init.ModSounds; +import com.atsuishio.superbwarfare.init.ModTags; +import com.atsuishio.superbwarfare.item.gun.GunItem; +import com.atsuishio.superbwarfare.perk.Perk; +import com.atsuishio.superbwarfare.tools.GunsTool; +import com.atsuishio.superbwarfare.tools.NBTTool; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.ItemDisplayContext; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Rarity; +import net.minecraft.world.level.Level; +import software.bernie.geckolib.animatable.GeoItem; +import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache; +import software.bernie.geckolib.animation.*; +import software.bernie.geckolib.renderer.GeoItemRenderer; +import software.bernie.geckolib.util.GeckoLibUtil; + +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.Set; + +public class VectorItem extends GunItem implements GeoItem { + + private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); + public static ItemDisplayContext transformType; + + public VectorItem() { + super(new Properties().stacksTo(1).rarity(Rarity.EPIC)); + } + + + public void getTransformType(ItemDisplayContext type) { + transformType = type; + } + + private PlayState idlePredicate(AnimationState event) { + LocalPlayer player = Minecraft.getInstance().player; + if (player == null) return PlayState.STOP; + ItemStack stack = player.getMainHandItem(); + if (!stack.is(ModTags.Items.GUN)) return PlayState.STOP; + boolean drum = GunsTool.getAttachmentType(stack, GunsTool.AttachmentType.MAGAZINE) == 2; + + + if (NBTTool.getOrCreateTag(stack).getBoolean("is_empty_reloading")) { + if (drum) { + return event.setAndContinue(RawAnimation.begin().thenPlay("animation.vec.reload_empty_drum")); + } else { + return event.setAndContinue(RawAnimation.begin().thenPlay("animation.vec.reload_empty")); + } + } + + if (NBTTool.getOrCreateTag(stack).getBoolean("is_normal_reloading")) { + if (drum) { + return event.setAndContinue(RawAnimation.begin().thenPlay("animation.vec.reload_normal_drum")); + } else { + return event.setAndContinue(RawAnimation.begin().thenPlay("animation.vec.reload_normal")); + } + } + + if (player.isSprinting() && player.onGround() && player.getPersistentData().getDouble("noRun") == 0 && ClientEventHandler.drawTime < 0.01) { + if (player.hasEffect(MobEffects.MOVEMENT_SPEED)) { + return event.setAndContinue(RawAnimation.begin().thenLoop("animation.vec.run_fast")); + } else { + return event.setAndContinue(RawAnimation.begin().thenLoop("animation.vec.run")); + } + } + + return event.setAndContinue(RawAnimation.begin().thenLoop("animation.vec.idle")); + } + + private PlayState editPredicate(AnimationState event) { + LocalPlayer player = Minecraft.getInstance().player; + if (player == null) return PlayState.STOP; + ItemStack stack = player.getMainHandItem(); + if (!stack.is(ModTags.Items.GUN)) return PlayState.STOP; + + var cap = player.getCapability(ModCapabilities.PLAYER_VARIABLE); + if (cap != null && cap.edit) { + return event.setAndContinue(RawAnimation.begin().thenPlay("animation.vector.edit")); + } + + return event.setAndContinue(RawAnimation.begin().thenLoop("animation.vec.idle")); + } + + @Override + public void registerControllers(AnimatableManager.ControllerRegistrar data) { + AnimationController idleController = new AnimationController<>(this, "idleController", 2, this::idlePredicate); + data.add(idleController); + var editController = new AnimationController<>(this, "editController", 1, this::editPredicate); + data.add(editController); + } + + @Override + public AnimatableInstanceCache getAnimatableInstanceCache() { + return this.cache; + } + + @Override + public GeoItemRenderer getRenderer() { + return new VectorItemRenderer(); + } + + @Override + @ParametersAreNonnullByDefault + public void inventoryTick(ItemStack stack, Level world, Entity entity, int slot, boolean selected) { + super.inventoryTick(stack, world, entity, slot, selected); + + int scopeType = GunsTool.getAttachmentType(stack, GunsTool.AttachmentType.SCOPE); + int magType = GunsTool.getAttachmentType(stack, GunsTool.AttachmentType.MAGAZINE); + + int customMag = switch (magType) { + case 1 -> 20; + case 2 -> 57; + default -> 0; + }; + + if (scopeType == 3) { + CompoundTag tag = NBTTool.getOrCreateTag(stack).getCompound("Attachments"); + tag.putInt("Scope", 0); + } + + double customZoom = switch (scopeType) { + case 0, 1 -> 0; + case 2 -> 0.75; + default -> GunsTool.getGunDoubleTag(stack, "CustomZoom", 0); + }; + + GunsTool.setGunDoubleTag(stack, "CustomZoom", customZoom); + GunsTool.setGunDoubleTag(stack, "CustomMagazine", customMag); + } + + public static ItemStack getGunInstance() { + ItemStack stack = new ItemStack(ModItems.VECTOR.get()); + GunsTool.initCreativeGun(stack, ModItems.VECTOR.getId().getPath()); + return stack; + } + + @Override + public Set getReloadSound() { + return Set.of(ModSounds.VECTOR_RELOAD_NORMAL.get(), ModSounds.VECTOR_RELOAD_EMPTY.get()); + } + + @Override + public ResourceLocation getGunIcon() { + return ModUtils.loc("textures/gun_icon/vector_icon.png"); + } + + @Override + public String getGunDisplayName() { + return "VECTOR"; + } + + @Override + public boolean canApplyPerk(Perk perk) { + // TODO perk +// return PerkHelper.SMG_PERKS.test(perk) || PerkHelper.MAGAZINE_PERKS.test(perk); + return false; + } + + @Override + public boolean isMagazineReload(ItemStack stack) { + return true; + } + + @Override + public boolean isOpenBolt(ItemStack stack) { + return true; + } + + @Override + public boolean hasBulletInBarrel(ItemStack stack) { + return true; + } + + @Override + public boolean isAutoWeapon(ItemStack stack) { + return true; + } + + @Override + public boolean isCustomizable(ItemStack stack) { + return true; + } + + @Override + public boolean hasCustomBarrel(ItemStack stack) { + return true; + } + + @Override + public boolean hasCustomGrip(ItemStack stack) { + return true; + } + + @Override + public boolean hasCustomMagazine(ItemStack stack) { + return true; + } + + @Override + public boolean hasCustomScope(ItemStack stack) { + return true; + } + + @Override + public boolean hasCustomStock(ItemStack stack) { + return true; + } + + @Override + public boolean canEjectShell(ItemStack stack) { + return true; + } + + @Override + public int getAvailableFireModes() { + return FireMode.SEMI.flag + FireMode.BURST.flag + FireMode.AUTO.flag; + } +} \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/network/NetworkRegistry.java b/src/main/java/com/atsuishio/superbwarfare/network/NetworkRegistry.java index c47afd285..d6a2f8573 100644 --- a/src/main/java/com/atsuishio/superbwarfare/network/NetworkRegistry.java +++ b/src/main/java/com/atsuishio/superbwarfare/network/NetworkRegistry.java @@ -13,9 +13,11 @@ public class NetworkRegistry { registrar.playToClient(ClientMotionSyncMessage.TYPE, ClientMotionSyncMessage.STREAM_CODEC, ClientMotionSyncMessage::handler); registrar.playToClient(ClientIndicatorMessage.TYPE, ClientIndicatorMessage.STREAM_CODEC, ClientIndicatorMessage::handler); registrar.playToClient(PlayerGunKillMessage.TYPE, PlayerGunKillMessage.STREAM_CODEC, PlayerGunKillMessage::handler); + registrar.playToClient(GunsDataMessage.TYPE, GunsDataMessage.STREAM_CODEC, GunsDataMessage::handler); registrar.playToServer(LaserShootMessage.TYPE, LaserShootMessage.STREAM_CODEC, LaserShootMessage::handler); registrar.playToServer(BreathMessage.TYPE, BreathMessage.STREAM_CODEC, BreathMessage::handler); + registrar.playToServer(ShootMessage.TYPE, ShootMessage.STREAM_CODEC, ShootMessage::handler); } } diff --git a/src/main/java/com/atsuishio/superbwarfare/network/message/GunsDataMessage.java b/src/main/java/com/atsuishio/superbwarfare/network/message/GunsDataMessage.java new file mode 100644 index 000000000..ba07ac498 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/network/message/GunsDataMessage.java @@ -0,0 +1,41 @@ +package com.atsuishio.superbwarfare.network.message; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.tools.GunsTool; +import io.netty.buffer.ByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.neoforged.neoforge.network.handling.IPayloadContext; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; + +public record GunsDataMessage(HashMap> gunsData) implements CustomPacketPayload { + public static final Type TYPE = new Type<>(ModUtils.loc("set_guns_data")); + + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.map( + HashMap::new, + ByteBufCodecs.STRING_UTF8, + ByteBufCodecs.map( + HashMap::new, + ByteBufCodecs.STRING_UTF8, + ByteBufCodecs.DOUBLE + ) + ), + GunsDataMessage::gunsData, + GunsDataMessage::new + ); + + + public static void handler(final GunsDataMessage message, final IPayloadContext context) { + GunsTool.gunsData = message.gunsData; + } + + @Override + public @NotNull Type type() { + return TYPE; + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/network/message/ShootMessage.java b/src/main/java/com/atsuishio/superbwarfare/network/message/ShootMessage.java new file mode 100644 index 000000000..f11dcc335 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/network/message/ShootMessage.java @@ -0,0 +1,129 @@ +package com.atsuishio.superbwarfare.network.message; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.event.GunEventHandler; +import com.atsuishio.superbwarfare.init.ModTags; +import com.atsuishio.superbwarfare.tools.GunsTool; +import com.atsuishio.superbwarfare.tools.NBTTool; +import io.netty.buffer.ByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.neoforged.neoforge.network.handling.IPayloadContext; +import org.jetbrains.annotations.NotNull; + +public record ShootMessage(double spread) implements CustomPacketPayload { + public static final Type TYPE = new Type<>(ModUtils.loc("shoot")); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.DOUBLE, + ShootMessage::spread, + ShootMessage::new + ); + + public static void handler(final ShootMessage message, final IPayloadContext context) { + pressAction(context.player(), message.spread); + } + + public static void pressAction(Player player, double spared) { + ItemStack stack = player.getMainHandItem(); + if (stack.is(ModTags.Items.NORMAL_GUN)) { + int projectileAmount = GunsTool.getGunIntTag(stack, "ProjectileAmount", 1); + + if (GunsTool.getGunIntTag(stack, "Ammo", 0) > 0) { + // 空仓挂机 + if (GunsTool.getGunIntTag(stack, "Ammo", 0) == 1) { + GunsTool.setGunBooleanTag(stack, "HoldOpen", true); + } + + if (stack.is(ModTags.Items.REVOLVER)) { + NBTTool.getOrCreateTag(stack).putBoolean("canImmediatelyShoot", false); + } + + // 判断是否为栓动武器(BoltActionTime > 0),并在开火后给一个需要上膛的状态 + if (GunsTool.getGunIntTag(stack, "BoltActionTime", 0) > 0 && GunsTool.getGunIntTag(stack, "Ammo", 0) > (stack.is(ModTags.Items.REVOLVER) ? 0 : 1)) { + GunsTool.setGunBooleanTag(stack, "NeedBoltAction", true); + } + + GunsTool.setGunIntTag(stack, "Ammo", GunsTool.getGunIntTag(stack, "Ammo", 0) - 1); + + NBTTool.getOrCreateTag(stack).putDouble("empty", 1); + +// if (stack.getItem() == ModItems.M_60.get() && GunsTool.getGunIntTag(stack, "Ammo", 0) <= 5) { +// GunsTool.setGunBooleanTag(stack, "HideBulletChain", true); +// } +// +// if (stack.getItem() == ModItems.HOMEMADE_SHOTGUN.get()) { +// stack.hurtAndBreak(1, player, p -> p.broadcastBreakEvent(InteractionHand.MAIN_HAND)); +// if (player instanceof ServerPlayer serverPlayer && player.level() instanceof ServerLevel serverLevel) { +// ParticleTool.sendParticle(serverLevel, ParticleTypes.CLOUD, player.getX() + 1.8 * player.getLookAngle().x, player.getY() + player.getBbHeight() - 0.1 + 1.8 * player.getLookAngle().y, +// player.getZ() + 1.8 * player.getLookAngle().z, 30, 0.4, 0.4, 0.4, 0.005, true, serverPlayer); +// } +// } +// +// if (stack.getItem() == ModItems.SENTINEL.get()) { +// stack.getCapability(ForgeCapabilities.ENERGY).ifPresent( +// iEnergyStorage -> iEnergyStorage.extractEnergy(3000, false) +// ); +// } +// +// var perk = PerkHelper.getPerkByType(stack, Perk.Type.AMMO); + + for (int index0 = 0; index0 < ( + // todo perk +// perk instanceof AmmoPerk ammoPerk && ammoPerk.slug ? 1 : projectileAmount + projectileAmount + ); index0++) { + GunEventHandler.gunShoot(player, spared); + } + + GunEventHandler.playGunSounds(player); + } + } + // todo minigun +// else if (stack.is(ModItems.MINIGUN.get())) { +// var tag = GunNBTTool.getOrCreateTag(stack); +// +// if ((player.getCapability(ModVariables.PLAYER_VARIABLES_CAPABILITY, null).orElse(new ModVariables.PlayerVariables())).rifleAmmo > 0 +// || InventoryTool.hasCreativeAmmoBox(player)) { +// tag.putDouble("heat", (tag.getDouble("heat") + 0.1)); +// if (tag.getDouble("heat") >= 50.5) { +// tag.putDouble("overheat", 40); +// player.getCooldowns().addCooldown(stack.getItem(), 40); +// if (!player.level().isClientSide() && player instanceof ServerPlayer serverPlayer) { +// SoundTool.playLocalSound(serverPlayer, ModSounds.MINIGUN_OVERHEAT.get(), 2f, 1f); +// } +// } +// var perk = PerkHelper.getPerkByType(stack, Perk.Type.AMMO); +// float pitch = tag.getDouble("heat") <= 40 ? 1 : (float) (1 - 0.025 * Math.abs(40 - tag.getDouble("heat"))); +// +// if (!player.level().isClientSide() && player instanceof ServerPlayer) { +// float soundRadius = (float) GunsTool.getGunDoubleTag(stack, "SoundRadius"); +// +// player.playSound(ModSounds.MINIGUN_FIRE_3P.get(), soundRadius * 0.2f, pitch); +// player.playSound(ModSounds.MINIGUN_FAR.get(), soundRadius * 0.5f, pitch); +// player.playSound(ModSounds.MINIGUN_VERYFAR.get(), soundRadius, pitch); +// +// if (perk == ModPerks.BEAST_BULLET.get()) { +// player.playSound(ModSounds.HENG.get(), 4f, pitch); +// } +// } +// +// GunEventHandler.gunShoot(player, spared); +// if (!InventoryTool.hasCreativeAmmoBox(player)) { +// player.getCapability(ModVariables.PLAYER_VARIABLES_CAPABILITY, null).ifPresent(capability -> { +// capability.rifleAmmo = player.getCapability(ModVariables.PLAYER_VARIABLES_CAPABILITY, null).orElse(new ModVariables.PlayerVariables()).rifleAmmo - 1; +// capability.syncPlayerVariables(player); +// }); +// } +// } +// } + } + + @Override + public @NotNull Type type() { + return TYPE; + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/tools/GunsTool.java b/src/main/java/com/atsuishio/superbwarfare/tools/GunsTool.java new file mode 100644 index 000000000..efe120431 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/tools/GunsTool.java @@ -0,0 +1,265 @@ +package com.atsuishio.superbwarfare.tools; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.capability.ModCapabilities; +import com.atsuishio.superbwarfare.component.ModDataComponents; +import com.atsuishio.superbwarfare.init.ModTags; +import com.atsuishio.superbwarfare.item.gun.GunItem; +import com.atsuishio.superbwarfare.network.message.GunsDataMessage; +import com.google.gson.stream.JsonReader; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.event.entity.player.PlayerEvent; +import net.neoforged.neoforge.event.server.ServerStartedEvent; +import net.neoforged.neoforge.network.PacketDistributor; + +import javax.annotation.Nullable; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.UUID; + +@EventBusSubscriber(modid = ModUtils.MODID) +public class GunsTool { + + public static HashMap> gunsData = new HashMap<>(); + + /** + * 初始化数据,从data中读取数据json文件 + */ + public static void initJsonData(ResourceManager manager) { + for (var entry : manager.listResources("guns", file -> file.getPath().endsWith(".json")).entrySet()) { + var id = entry.getKey(); + var attribute = entry.getValue(); + try { + JsonReader reader = new JsonReader(new InputStreamReader(attribute.open())); + + reader.beginObject(); + var map = new HashMap(); + while (reader.hasNext()) { + map.put(reader.nextName(), reader.nextDouble()); + } + var path = id.getPath(); + gunsData.put(path.substring(5, path.length() - 5), map); + + reader.endObject(); + reader.close(); + } catch (Exception e) { + ModUtils.LOGGER.error(e.getMessage()); + } + } + } + + public static void initGun(Level level, ItemStack stack, String location) { + if (level.getServer() == null) return; + gunsData.get(location).forEach((k, v) -> { + CompoundTag tag = NBTTool.getOrCreateTag(stack); + CompoundTag data = tag.getCompound("GunData"); + data.putDouble(k, v); + tag.put("GunData", data); + }); + } + + public static void initCreativeGun(ItemStack stack, String location) { + if (gunsData != null && gunsData.get(location) != null) { + gunsData.get(location).forEach((k, v) -> { + CompoundTag tag = NBTTool.getOrCreateTag(stack); + CompoundTag data = tag.getCompound("GunData"); + data.putDouble(k, v); + tag.put("GunData", data); + }); + GunsTool.setGunIntTag(stack, "Ammo", GunsTool.getGunIntTag(stack, "Magazine", 0) + + GunsTool.getGunIntTag(stack, "CustomMagazine", 0)); + } + } + + public static void generateAndSetUUID(ItemStack stack) { + UUID uuid = UUID.randomUUID(); + CompoundTag tag = NBTTool.getOrCreateTag(stack); + var data = tag.getCompound("GunData"); + data.putUUID("UUID", uuid); + tag.put("GunData", data); + } + + @SubscribeEvent + public static void onPlayerLogin(PlayerEvent.PlayerLoggedInEvent event) { + if (event.getEntity() instanceof ServerPlayer player) { + PacketDistributor.sendToPlayer(player, new GunsDataMessage(GunsTool.gunsData)); + } + } + + @SubscribeEvent + public static void serverStarted(ServerStartedEvent event) { + initJsonData(event.getServer().getResourceManager()); + } + + public static void reload(Player player, ItemStack stack, AmmoType type) { + reload(player, stack, type, false); + } + + public static void reload(Player player, ItemStack stack, AmmoType type, boolean extraOne) { + CompoundTag tag = NBTTool.getOrCreateTag(stack); + if (!(stack.getItem() instanceof GunItem)) return; + + int mag = GunsTool.getGunIntTag(stack, "Magazine", 0) + GunsTool.getGunIntTag(stack, "CustomMagazine", 0); + int ammo = GunsTool.getGunIntTag(stack, "Ammo", 0); + int ammoToAdd = mag - ammo + (extraOne ? 1 : 0); + + // 空仓换弹的栓动武器应该在换弹后取消待上膛标记 + if (ammo == 0 && GunsTool.getGunIntTag(stack, "BoltActionTime", 0) > 0 && !stack.is(ModTags.Items.REVOLVER)) { + GunsTool.setGunBooleanTag(stack, "NeedBoltAction", false); + } + + var capability = player.getCapability(ModCapabilities.PLAYER_VARIABLE); + var playerAmmo = 0; + + if (capability != null) { + playerAmmo = type.get(capability); + var newAmmoCount = Math.max(0, playerAmmo - ammoToAdd); + type.set(capability, newAmmoCount); + capability.syncPlayerVariables(player); + } + + int needToAdd = ammo + Math.min(ammoToAdd, playerAmmo); + + GunsTool.setGunIntTag(stack, "Ammo", needToAdd); + tag.putBoolean("is_normal_reloading", false); + tag.putBoolean("is_empty_reloading", false); + } + + /* PerkData */ + public static void setPerkIntTag(ItemStack stack, String name, int num) { + var rootTag = NBTTool.getOrCreateTag(stack); + CompoundTag tag = rootTag.getCompound("PerkData"); + tag.putInt(name, num); + rootTag.put("PerkData", tag); + } + + public static int getPerkIntTag(ItemStack stack, String name) { + CompoundTag tag = NBTTool.getOrCreateTag(stack).getCompound("PerkData"); + return tag.getInt(name); + } + + public static void setPerkDoubleTag(ItemStack stack, String name, double num) { + var rootTag = NBTTool.getOrCreateTag(stack); + CompoundTag tag = rootTag.getCompound("PerkData"); + tag.putDouble(name, num); + rootTag.put("PerkData", tag); + } + + public static double getPerkDoubleTag(ItemStack stack, String name) { + CompoundTag tag = NBTTool.getOrCreateTag(stack).getCompound("PerkData"); + return tag.getDouble(name); + } + + public static void setPerkBooleanTag(ItemStack stack, String name, boolean flag) { + var rootTag = NBTTool.getOrCreateTag(stack); + CompoundTag tag = rootTag.getCompound("PerkData"); + tag.putBoolean(name, flag); + rootTag.put("PerkData", tag); + } + + public static boolean getPerkBooleanTag(ItemStack stack, String name) { + CompoundTag tag = NBTTool.getOrCreateTag(stack).getCompound("PerkData"); + return tag.getBoolean(name); + } + + /* Attachments */ + public static int getAttachmentType(ItemStack stack, AttachmentType type) { + CompoundTag tag = NBTTool.getOrCreateTag(stack).getCompound("Attachments"); + return tag.getInt(type.getName()); + } + + public enum AttachmentType { + SCOPE("Scope"), + MAGAZINE("Magazine"), + BARREL("Barrel"), + STOCK("Stock"), + GRIP("Grip"); + + private final String name; + + AttachmentType(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } + + /* GunData */ + public static CompoundTag getGunData(ItemStack stack) { + CompoundTag tag = NBTTool.getOrCreateTag(stack); + return tag.getCompound("GunData"); + } + + public static void setGunIntTag(ItemStack stack, String name, int num) { + CompoundTag tag = NBTTool.getOrCreateTag(stack); + var data = tag.getCompound("GunData"); + data.putInt(name, num); + tag.put("GunData", data); + } + + public static int getGunIntTag(ItemStack stack, String name) { + return getGunIntTag(stack, name, 0); + } + + public static int getGunIntTag(ItemStack stack, String name, int defaultValue) { + CompoundTag tag = NBTTool.getOrCreateTag(stack); + var data = tag.getCompound("GunData"); + if (!data.contains(name)) return defaultValue; + return data.getInt(name); + } + + public static void setGunDoubleTag(ItemStack stack, String name, double num) { + CompoundTag tag = NBTTool.getOrCreateTag(stack); + var data = tag.getCompound("GunData"); + data.putDouble(name, num); + tag.put("GunData", data); + } + + public static double getGunDoubleTag(ItemStack stack, String name) { + return getGunDoubleTag(stack, name, 0); + } + + public static double getGunDoubleTag(ItemStack stack, String name, double defaultValue) { + CompoundTag tag = NBTTool.getOrCreateTag(stack); + var data = tag.getCompound("GunData"); + if (!data.contains(name)) return defaultValue; + return data.getDouble(name); + } + + public static void setGunBooleanTag(ItemStack stack, String name, boolean flag) { + CompoundTag tag = NBTTool.getOrCreateTag(stack); + var data = tag.getCompound("GunData"); + data.putBoolean(name, flag); + tag.put("GunData", data); + } + + public static boolean getGunBooleanTag(ItemStack stack, String name) { + return getGunBooleanTag(stack, name, false); + } + + public static boolean getGunBooleanTag(ItemStack stack, String name, boolean defaultValue) { + CompoundTag tag = NBTTool.getOrCreateTag(stack); + var data = tag.getCompound("GunData"); + if (!data.contains(name)) return defaultValue; + return data.getBoolean(name); + } + + @Nullable + public static UUID getGunUUID(ItemStack stack) { + CompoundTag tag = stack.get(ModDataComponents.GUN_DATA); + if (tag == null || !tag.contains("GunData")) return null; + + CompoundTag data = tag.getCompound("GunData"); + if (!data.hasUUID("UUID")) return null; + return data.getUUID("UUID"); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/tools/InventoryTool.java b/src/main/java/com/atsuishio/superbwarfare/tools/InventoryTool.java index c10e76e5a..058d79bed 100644 --- a/src/main/java/com/atsuishio/superbwarfare/tools/InventoryTool.java +++ b/src/main/java/com/atsuishio/superbwarfare/tools/InventoryTool.java @@ -1,5 +1,6 @@ package com.atsuishio.superbwarfare.tools; +import com.atsuishio.superbwarfare.init.ModItems; import net.minecraft.core.NonNullList; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; @@ -57,18 +58,18 @@ public class InventoryTool { * * @param itemList 物品列表 */ -// public static boolean hasCreativeAmmoBox(NonNullList itemList) { -// return countItem(itemList, ModItems.CREATIVE_AMMO_BOX.get()) > 0; -// } -// -// /** -// * 判断玩家背包内是否有创造模式弹药盒 -// * -// * @param player 玩家 -// */ -// public static boolean hasCreativeAmmoBox(Player player) { -// return hasItem(player, ModItems.CREATIVE_AMMO_BOX.get()); -// } + public static boolean hasCreativeAmmoBox(NonNullList itemList) { + return countItem(itemList, ModItems.CREATIVE_AMMO_BOX.get()) > 0; + } + + /** + * 判断玩家背包内是否有创造模式弹药盒 + * + * @param player 玩家 + */ + public static boolean hasCreativeAmmoBox(Player player) { + return hasItem(player, ModItems.CREATIVE_AMMO_BOX.get()); + } /** * 消耗物品列表内指定物品 diff --git a/src/main/java/com/atsuishio/superbwarfare/tools/NBTTool.java b/src/main/java/com/atsuishio/superbwarfare/tools/NBTTool.java new file mode 100644 index 000000000..e14af944e --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/tools/NBTTool.java @@ -0,0 +1,62 @@ +package com.atsuishio.superbwarfare.tools; + +import com.atsuishio.superbwarfare.component.ModDataComponents; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; + +// From Botania +public final class NBTTool { + public static boolean verifyExistence(ItemStack stack, String tag) { + var data = stack.get(ModDataComponents.GUN_DATA); + return !stack.isEmpty() && data != null && data.contains(tag); + } + + public static CompoundTag getOrCreateTag(ItemStack stack) { + var data = stack.get(ModDataComponents.GUN_DATA); + if (data != null) return data; + + var newTag = new CompoundTag(); + stack.set(ModDataComponents.GUN_DATA, newTag); + return newTag; + } + + public static void setBoolean(ItemStack stack, String tag, boolean b) { + getOrCreateTag(stack).putBoolean(tag, b); + } + + public static boolean getBoolean(ItemStack stack, String tag, boolean defaultExpected) { + return verifyExistence(stack, tag) ? getOrCreateTag(stack).getBoolean(tag) : defaultExpected; + } + + public static void setFloat(ItemStack stack, String tag, float f) { + getOrCreateTag(stack).putFloat(tag, f); + } + + public static float getFloat(ItemStack stack, String tag, float f) { + return verifyExistence(stack, tag) ? getOrCreateTag(stack).getFloat(tag) : f; + } + + public static void setInt(ItemStack stack, String tag, int num) { + getOrCreateTag(stack).putInt(tag, num); + } + + public static int getInt(ItemStack stack, String tag, int num) { + return verifyExistence(stack, tag) ? getOrCreateTag(stack).getInt(tag) : num; + } + + public static void setLong(ItemStack stack, String tag, long num) { + getOrCreateTag(stack).putLong(tag, num); + } + + public static long getLong(ItemStack stack, String tag, long num) { + return verifyExistence(stack, tag) ? getOrCreateTag(stack).getLong(tag) : num; + } + + public static void setDouble(ItemStack stack, String tag, double num) { + getOrCreateTag(stack).putDouble(tag, num); + } + + public static double getDouble(ItemStack stack, String tag, double num) { + return verifyExistence(stack, tag) ? getOrCreateTag(stack).getDouble(tag) : num; + } +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/aa_12.json b/src/main/resources/data/superbwarfare/guns/aa_12.json new file mode 100644 index 000000000..d61ad87c4 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/aa_12.json @@ -0,0 +1,17 @@ +{ + "Spread": 3.5, + "RecoilX": 0.006, + "RecoilY": 0.018, + "Damage": 2.5, + "Headshot": 1.5, + "Velocity": 17, + "Magazine": 25, + "ProjectileAmount": 12, + "Weight": 7, + "FireMode": 2, + "NormalReloadTime": 64, + "EmptyReloadTime": 85, + "BypassesArmor": 0.05, + "SoundRadius": 18, + "RPM": 360 +} diff --git a/src/main/resources/data/superbwarfare/guns/ak_12.json b/src/main/resources/data/superbwarfare/guns/ak_12.json new file mode 100644 index 000000000..e0d8a13c9 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/ak_12.json @@ -0,0 +1,18 @@ +{ + "MinZoom": 1.25, + "MaxZoom": 6, + "Spread": 3.5, + "RecoilX": 0.0015, + "RecoilY": 0.01, + "Damage": 7.7, + "Headshot": 2, + "Velocity": 44.5, + "Magazine": 30, + "Weight": 4, + "FireMode": 2, + "NormalReloadTime": 52, + "EmptyReloadTime": 58, + "BypassesArmor": 0.23, + "SoundRadius": 12, + "RPM": 700 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/ak_47.json b/src/main/resources/data/superbwarfare/guns/ak_47.json new file mode 100644 index 000000000..10eb5af3b --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/ak_47.json @@ -0,0 +1,18 @@ +{ + "MinZoom": 1.25, + "MaxZoom": 6, + "Spread": 4, + "RecoilX": 0.002, + "RecoilY": 0.012, + "Damage": 8.5, + "Headshot": 2, + "Velocity": 36, + "Magazine": 30, + "Weight": 5, + "FireMode": 2, + "NormalReloadTime": 52, + "EmptyReloadTime": 65, + "BypassesArmor": 0.2, + "SoundRadius": 14, + "RPM": 600 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/bocek.json b/src/main/resources/data/superbwarfare/guns/bocek.json new file mode 100644 index 000000000..865b77e9c --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/bocek.json @@ -0,0 +1,8 @@ +{ + "CustomZoom": 0.75, + "Spread": 4, + "Headshot": 2.5, + "Damage": 48, + "Weight": 3, + "BypassesArmor": 0.25 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/devotion.json b/src/main/resources/data/superbwarfare/guns/devotion.json new file mode 100644 index 000000000..d0eb57949 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/devotion.json @@ -0,0 +1,17 @@ +{ + "CustomZoom": 0.75, + "Spread": 5, + "RecoilX": 0.0018, + "RecoilY": 0.01, + "Damage": 9.5, + "Headshot": 2, + "Velocity": 40, + "Magazine": 55, + "Weight": 6, + "FireMode": 2, + "NormalReloadTime": 73, + "EmptyReloadTime": 95, + "BypassesArmor": 0.25, + "SoundRadius": 13, + "RPM": 400 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/glock_17.json b/src/main/resources/data/superbwarfare/guns/glock_17.json new file mode 100644 index 000000000..e96aa8237 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/glock_17.json @@ -0,0 +1,15 @@ +{ + "Spread": 2.5, + "RecoilX": 0.004, + "RecoilY": 0.013, + "Damage": 5.5, + "Headshot": 1.5, + "Velocity": 17, + "Magazine": 17, + "Weight": 1, + "NormalReloadTime": 44, + "EmptyReloadTime": 47, + "BypassesArmor": 0.15, + "SoundRadius": 8, + "RPM": 400 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/glock_18.json b/src/main/resources/data/superbwarfare/guns/glock_18.json new file mode 100644 index 000000000..68925ea43 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/glock_18.json @@ -0,0 +1,16 @@ +{ + "Spread": 2.5, + "RecoilX": 0.004, + "RecoilY": 0.013, + "Damage": 5.5, + "Headshot": 1.5, + "Velocity": 17, + "Magazine": 17, + "Weight": 1, + "FireMode": 2, + "NormalReloadTime": 44, + "EmptyReloadTime": 47, + "BypassesArmor": 0.15, + "SoundRadius": 8, + "RPM": 1300 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/hk_416.json b/src/main/resources/data/superbwarfare/guns/hk_416.json new file mode 100644 index 000000000..545dbd450 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/hk_416.json @@ -0,0 +1,18 @@ +{ + "MinZoom": 1.25, + "MaxZoom": 6, + "Spread": 3.5, + "RecoilX": 0.0016, + "RecoilY": 0.009, + "Damage": 7.5, + "Headshot": 2, + "Velocity": 44, + "Magazine": 30, + "Weight": 4, + "FireMode": 2, + "NormalReloadTime": 56, + "EmptyReloadTime": 64, + "BypassesArmor": 0.25, + "SoundRadius": 14, + "RPM": 900 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/homemade_shotgun.json b/src/main/resources/data/superbwarfare/guns/homemade_shotgun.json new file mode 100644 index 000000000..861af0b1d --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/homemade_shotgun.json @@ -0,0 +1,16 @@ +{ + "Spread": 4, + "RecoilX": 0.005, + "RecoilY": 0.026, + "Damage": 5, + "Headshot": 1.5, + "Velocity": 15, + "Magazine": 2, + "ProjectileAmount": 12, + "Weight": 1, + "NormalReloadTime": 66, + "EmptyReloadTime": 83, + "BypassesArmor": 0.01, + "SoundRadius": 16, + "RPM": 600 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/hunting_rifle.json b/src/main/resources/data/superbwarfare/guns/hunting_rifle.json new file mode 100644 index 000000000..4ca6850a4 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/hunting_rifle.json @@ -0,0 +1,13 @@ +{ + "Spread": 7, + "RecoilX": 0.004, + "RecoilY": 0.04, + "Damage": 65, + "Headshot": 3, + "Velocity": 38, + "Magazine": 1, + "Weight": 5, + "EmptyReloadTime": 64, + "BypassesArmor": 0.7, + "SoundRadius": 20 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/javelin.json b/src/main/resources/data/superbwarfare/guns/javelin.json new file mode 100644 index 000000000..ae0d7d302 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/javelin.json @@ -0,0 +1,10 @@ +{ + "CustomZoom": 1.75, + "Spread": 5, + "Magazine": 1, + "Weight": 10, + "EmptyReloadTime": 78, + "Damage": 700, + "ExplosionDamage": 60, + "ExplosionRadius": 5 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/k_98.json b/src/main/resources/data/superbwarfare/guns/k_98.json new file mode 100644 index 000000000..6d3a51656 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/k_98.json @@ -0,0 +1,18 @@ +{ + "Spread": 5, + "RecoilX": 0.002, + "RecoilY": 0.063, + "Damage": 35, + "Headshot": 3, + "Velocity": 37.75, + "Magazine": 5, + "BoltActionTime": 22, + "Weight": 5, + "FireMode": 0, + "EmptyReloadTime": 59, + "PrepareTime": 29, + "IterativeTime": 11, + "FinishTime": 18, + "BypassesArmor": 0.5, + "SoundRadius": 18 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/m_1911.json b/src/main/resources/data/superbwarfare/guns/m_1911.json new file mode 100644 index 000000000..7da655273 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/m_1911.json @@ -0,0 +1,15 @@ +{ + "Spread": 2.5, + "RecoilX": 0.006, + "RecoilY": 0.018, + "Damage": 9.5, + "Headshot": 1.5, + "Velocity": 15, + "Magazine": 7, + "Weight": 2, + "NormalReloadTime": 44, + "EmptyReloadTime": 47, + "BypassesArmor": 0.2, + "SoundRadius": 10, + "RPM": 400 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/m_4.json b/src/main/resources/data/superbwarfare/guns/m_4.json new file mode 100644 index 000000000..bdad9e132 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/m_4.json @@ -0,0 +1,18 @@ +{ + "MinZoom": 4, + "MaxZoom": 8, + "Spread": 4, + "RecoilX": 0.0015, + "RecoilY": 0.011, + "Damage": 7, + "Headshot": 2, + "Velocity": 44, + "Magazine": 30, + "Weight": 4, + "FireMode": 2, + "NormalReloadTime": 56, + "EmptyReloadTime": 64, + "BypassesArmor": 0.25, + "SoundRadius": 14, + "RPM": 850 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/m_60.json b/src/main/resources/data/superbwarfare/guns/m_60.json new file mode 100644 index 000000000..11a515089 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/m_60.json @@ -0,0 +1,16 @@ +{ + "Spread": 5, + "RecoilX": 0.004, + "RecoilY": 0.014, + "Damage": 9, + "Headshot": 2, + "Velocity": 43, + "Magazine": 100, + "Weight": 8, + "FireMode": 2, + "NormalReloadTime": 114, + "EmptyReloadTime": 133, + "BypassesArmor": 0.25, + "SoundRadius": 15, + "RPM": 600 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/m_79.json b/src/main/resources/data/superbwarfare/guns/m_79.json new file mode 100644 index 000000000..0d7cc1681 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/m_79.json @@ -0,0 +1,12 @@ +{ + "Spread": 1.5, + "RecoilX": 0.004, + "RecoilY": 0.023, + "Damage": 40, + "ExplosionDamage": 80, + "ExplosionRadius": 5, + "Velocity": 3.75, + "Magazine": 1, + "Weight": 4, + "EmptyReloadTime": 64 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/m_870.json b/src/main/resources/data/superbwarfare/guns/m_870.json new file mode 100644 index 000000000..c5774572f --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/m_870.json @@ -0,0 +1,18 @@ +{ + "Spread": 3, + "RecoilX": 0.009, + "RecoilY": 0.04, + "Damage": 3, + "Headshot": 1.5, + "Velocity": 17, + "Magazine": 8, + "ProjectileAmount": 12, + "Weight": 4, + "PrepareTime": 7, + "PrepareLoadTime": 36, + "IterativeTime": 16, + "FinishTime": 12, + "BypassesArmor": 0.05, + "SoundRadius": 16, + "BoltActionTime": 11 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/m_98b.json b/src/main/resources/data/superbwarfare/guns/m_98b.json new file mode 100644 index 000000000..03869e762 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/m_98b.json @@ -0,0 +1,18 @@ +{ + "CustomZoom": 4.75, + "MinZoom": 4, + "MaxZoom": 8, + "Spread": 6, + "RecoilX": 0.007, + "RecoilY": 0.013, + "Damage": 38, + "Headshot": 3, + "Velocity": 47.2, + "Magazine": 5, + "BoltActionTime": 18, + "Weight": 7, + "NormalReloadTime": 60, + "EmptyReloadTime": 78, + "BypassesArmor": 0.6, + "SoundRadius": 18 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/marlin.json b/src/main/resources/data/superbwarfare/guns/marlin.json new file mode 100644 index 000000000..111a87fa9 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/marlin.json @@ -0,0 +1,16 @@ +{ + "Spread": 2, + "RecoilX": 0.004, + "RecoilY": 0.031, + "Damage": 16, + "Headshot": 2.5, + "Velocity": 38, + "Magazine": 8, + "Weight": 3, + "PrepareTime": 7, + "IterativeTime": 16, + "FinishTime": 19, + "BypassesArmor": 0.3, + "SoundRadius": 15, + "BoltActionTime": 12 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/minigun.json b/src/main/resources/data/superbwarfare/guns/minigun.json new file mode 100644 index 000000000..92e4e445b --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/minigun.json @@ -0,0 +1,12 @@ +{ + "Spread": 1.5, + "RecoilX": 0.003, + "RecoilY": 0.02, + "Damage": 8, + "Headshot": 2, + "Velocity": 46, + "Weight": 10, + "BypassesArmor": 0.3, + "SoundRadius": 14, + "RPM": 1200 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/mk_14.json b/src/main/resources/data/superbwarfare/guns/mk_14.json new file mode 100644 index 000000000..a88d5d450 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/mk_14.json @@ -0,0 +1,18 @@ +{ + "MinZoom": 1.25, + "MaxZoom": 6, + "Spread": 5, + "RecoilX": 0.006, + "RecoilY": 0.014, + "Damage": 12, + "Headshot": 2.5, + "Velocity": 42.5, + "Magazine": 20, + "Weight": 5, + "FireMode": 2, + "NormalReloadTime": 54, + "EmptyReloadTime": 71, + "BypassesArmor": 0.4, + "SoundRadius": 16, + "RPM": 700 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/mosin_nagant.json b/src/main/resources/data/superbwarfare/guns/mosin_nagant.json new file mode 100644 index 000000000..4aace0cd9 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/mosin_nagant.json @@ -0,0 +1,18 @@ +{ + "CustomZoom": 2.25, + "Spread": 4.8, + "RecoilX": 0.002, + "RecoilY": 0.063, + "Damage": 33, + "Headshot": 3, + "Velocity": 42, + "Magazine": 5, + "BoltActionTime": 22, + "Weight": 5, + "PrepareTime": 29, + "PrepareEmptyTime": 16, + "IterativeTime": 11, + "FinishTime": 18, + "BypassesArmor": 0.54, + "SoundRadius": 18 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/mp_443.json b/src/main/resources/data/superbwarfare/guns/mp_443.json new file mode 100644 index 000000000..e96aa8237 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/mp_443.json @@ -0,0 +1,15 @@ +{ + "Spread": 2.5, + "RecoilX": 0.004, + "RecoilY": 0.013, + "Damage": 5.5, + "Headshot": 1.5, + "Velocity": 17, + "Magazine": 17, + "Weight": 1, + "NormalReloadTime": 44, + "EmptyReloadTime": 47, + "BypassesArmor": 0.15, + "SoundRadius": 8, + "RPM": 400 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/ntw_20.json b/src/main/resources/data/superbwarfare/guns/ntw_20.json new file mode 100644 index 000000000..64063bb64 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/ntw_20.json @@ -0,0 +1,17 @@ +{ + "MinZoom": 1.25, + "MaxZoom": 6, + "Spread": 8, + "RecoilX": 0.01, + "RecoilY": 0.038, + "Damage": 140, + "Headshot": 3, + "Velocity": 36, + "Magazine": 3, + "BoltActionTime": 37, + "Weight": 13, + "NormalReloadTime": 63, + "EmptyReloadTime": 92, + "BypassesArmor": 1, + "SoundRadius": 22 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/qbz_95.json b/src/main/resources/data/superbwarfare/guns/qbz_95.json new file mode 100644 index 000000000..b3592ecb8 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/qbz_95.json @@ -0,0 +1,18 @@ +{ + "MinZoom": 4, + "MaxZoom": 8, + "Spread": 3.7, + "RecoilX": 0.0013, + "RecoilY": 0.009, + "Damage": 8.25, + "Headshot": 2, + "Velocity": 46, + "Magazine": 30, + "Weight": 4, + "FireMode": 2, + "NormalReloadTime": 60, + "EmptyReloadTime": 74, + "BypassesArmor": 0.28, + "SoundRadius": 13, + "RPM": 650 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/rpg.json b/src/main/resources/data/superbwarfare/guns/rpg.json new file mode 100644 index 000000000..1e3a54d92 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/rpg.json @@ -0,0 +1,10 @@ +{ + "Spread": 5, + "RecoilX": 0.008, + "RecoilY": 0.018, + "Damage": 270, + "Velocity": 4, + "Magazine": 1, + "Weight": 7, + "EmptyReloadTime": 103 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/rpk.json b/src/main/resources/data/superbwarfare/guns/rpk.json new file mode 100644 index 000000000..d26bcaaf9 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/rpk.json @@ -0,0 +1,16 @@ +{ + "Spread": 5.5, + "RecoilX": 0.0018, + "RecoilY": 0.012, + "Damage": 8.75, + "Headshot": 2, + "Velocity": 38, + "Magazine": 75, + "Weight": 6, + "FireMode": 2, + "NormalReloadTime": 73, + "EmptyReloadTime": 95, + "BypassesArmor": 0.23, + "SoundRadius": 14, + "RPM": 600 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/secondary_cataclysm.json b/src/main/resources/data/superbwarfare/guns/secondary_cataclysm.json new file mode 100644 index 000000000..1d7c584c5 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/secondary_cataclysm.json @@ -0,0 +1,15 @@ +{ + "Spread": 1.5, + "RecoilX": 0.004, + "RecoilY": 0.023, + "Damage": 30, + "ExplosionDamage": 50, + "ExplosionRadius": 5, + "Velocity": 3.75, + "Magazine": 8, + "Weight": 9, + "PrepareLoadTime": 31, + "IterativeTime": 20, + "FinishTime": 19, + "SoundRadius": 8 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/sentinel.json b/src/main/resources/data/superbwarfare/guns/sentinel.json new file mode 100644 index 000000000..2ffe85528 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/sentinel.json @@ -0,0 +1,16 @@ +{ + "CustomZoom": 1.75, + "Spread": 6, + "RecoilX": 0.007, + "RecoilY": 0.018, + "Damage": 35, + "Magazine": 5, + "Headshot": 3, + "Velocity": 70, + "BoltActionTime": 22, + "Weight": 7, + "NormalReloadTime": 59, + "EmptyReloadTime": 89, + "BypassesArmor": 0.8, + "SoundRadius": 20 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/sks.json b/src/main/resources/data/superbwarfare/guns/sks.json new file mode 100644 index 000000000..bc8d0de03 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/sks.json @@ -0,0 +1,15 @@ +{ + "Spread": 4.5, + "RecoilX": 0.004, + "RecoilY": 0.015, + "Damage": 9.5, + "Headshot": 2, + "Velocity": 36, + "Magazine": 20, + "Weight": 4, + "NormalReloadTime": 54, + "EmptyReloadTime": 75, + "BypassesArmor": 0.23, + "SoundRadius": 16, + "RPM": 400 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/svd.json b/src/main/resources/data/superbwarfare/guns/svd.json new file mode 100644 index 000000000..9dad97016 --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/svd.json @@ -0,0 +1,17 @@ +{ + "MinZoom": 4, + "MaxZoom": 8, + "Spread": 5.5, + "RecoilX": 0.004, + "RecoilY": 0.009, + "Damage": 18, + "Headshot": 2.5, + "Velocity": 42, + "Magazine": 10, + "Weight": 5, + "NormalReloadTime": 59, + "EmptyReloadTime": 78, + "BypassesArmor": 0.45, + "SoundRadius": 17, + "RPM": 300 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/taser.json b/src/main/resources/data/superbwarfare/guns/taser.json new file mode 100644 index 000000000..e1333470d --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/taser.json @@ -0,0 +1,10 @@ +{ + "Spread": 2, + "RecoilX": 0.0001, + "RecoilY": 0.002, + "Damage": 5, + "Velocity": 3, + "Magazine": 1, + "Weight": 1, + "EmptyReloadTime": 58 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/trachelium.json b/src/main/resources/data/superbwarfare/guns/trachelium.json new file mode 100644 index 000000000..fae77792a --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/trachelium.json @@ -0,0 +1,14 @@ +{ + "Spread": 3, + "RecoilX": 0.005, + "RecoilY": 0.032, + "Damage": 19, + "Headshot": 2, + "Velocity": 24, + "Magazine": 6, + "Weight": 2, + "EmptyReloadTime": 65, + "BypassesArmor": 0.3, + "SoundRadius": 10, + "RPM": 240 +} \ No newline at end of file diff --git a/src/main/resources/data/superbwarfare/guns/vector.json b/src/main/resources/data/superbwarfare/guns/vector.json new file mode 100644 index 000000000..74e1248db --- /dev/null +++ b/src/main/resources/data/superbwarfare/guns/vector.json @@ -0,0 +1,17 @@ +{ + "Spread": 2.3, + "RecoilX": 0.002, + "RecoilY": 0.007, + "Damage": 6, + "Headshot": 1.5, + "Velocity": 16, + "Magazine": 13, + "Weight": 3, + "FireMode": 2, + "BurstSize": 3, + "NormalReloadTime": 46, + "EmptyReloadTime": 64, + "BypassesArmor": 0.15, + "SoundRadius": 11, + "RPM": 1200 +} \ No newline at end of file