Change bullet visuals

Add reloading and firing cooldowns
This commit is contained in:
Bruno Rybársky 2024-07-25 21:08:08 +02:00
parent 96d369b2f7
commit 4df69c27a1
6 changed files with 152 additions and 77 deletions

@ -6,7 +6,7 @@ minecraft_version=1.21
yarn_mappings=1.21+build.9
loader_version=0.16.0
# Mod Properties
mod_version=1.0
mod_version=1.1
maven_group=systems.brn
archives_base_name=plasticgun
# Dependencies

@ -10,6 +10,8 @@ import net.minecraft.entity.EntityType;
import net.minecraft.entity.SpawnGroup;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import systems.brn.plasticgun.bullets.BulletEntity;
import systems.brn.plasticgun.bullets.BulletItem;
import systems.brn.plasticgun.guns.Gun;
@ -32,40 +34,44 @@ public class PlasticGun implements ModInitializer {
public static EntityType<DamageTester> DAMAGE_TESTER_ENTITY_TYPE;
public static final Logger logger = LoggerFactory.getLogger(MOD_ID);;
@Override
public void onInitialize() {
// Bullets - Batch 1 (Better Bullets First)
bullets.add(new BulletItem("357_magnum", 1.4, 357, false, 0, 0));
bullets.add(new BulletItem("32_acp_high_velocity", 0.9, 32, false, 0, 0));
bullets.add(new BulletItem("45_acp_hollow_point", 1.2, 45, false, 0, 0));
bullets.add(new BulletItem("9mm_jhp", 1.05, 9, false, 0, 0));
bullets.add(new BulletItem("38_special_p", 1.3, 38, false, 0, 0));
bullets.add(new BulletItem("762_tokarev_ap", 1.2, 762, false, 0, 0));
bullets.add(new BulletItem("357_magnum", 1.4, 357, false,0, 0));
bullets.add(new BulletItem("32_acp_high_velocity", 0.9, 32, false,0, 0));
bullets.add(new BulletItem("45_acp_hollow_point", 1.2, 45, false,0, 0));
bullets.add(new BulletItem("9mm_jhp", 1.05, 9, false,0, 0));
bullets.add(new BulletItem("38_special_p", 1.3, 38, false,0, 0));
bullets.add(new BulletItem("762_tokarev_ap", 1.2, 762, false,0, 0));
// Bullets - Batch 2 (Standard Bullets)
bullets.add(new BulletItem("357_standard", 1, 357, false, 0, 0));
bullets.add(new BulletItem("32_acp", 0.8, 32, false, 0, 0));
bullets.add(new BulletItem("45_acp", 1, 45, false, 0, 0));
bullets.add(new BulletItem("9mm_parabellum", 0.9, 9, false, 0, 0));
bullets.add(new BulletItem("38_special", 0.95, 38, false, 0, 0));
bullets.add(new BulletItem("762_tokarev", 1.1, 762, false, 0, 0));
bullets.add(new BulletItem("357_standard", 1, 357, false,0, 0));
bullets.add(new BulletItem("32_acp", 0.8, 32, false,0, 0));
bullets.add(new BulletItem("45_acp", 1, 45, false,0, 0));
bullets.add(new BulletItem("9mm_parabellum", 0.9, 9, false,0, 0));
bullets.add(new BulletItem("38_special", 0.95, 38, false,0, 0));
bullets.add(new BulletItem("762_tokarev", 1.1, 762, false,0, 0));
bullets.add(new BulletItem("rpg_shell_incendiary", 1.1, 999, true, 1, 0));
bullets.add(new BulletItem("rpg_shell", 1.1, 999, false, 1, 0));
bullets.add(new BulletItem("force_container", 0, 888, false, 0, 1));
bullets.add(new BulletItem("rpg_shell", 1.1, 999, false,1, 0));
bullets.add(new BulletItem("force_container", 0, 888, false,0, 1));
// Guns
guns.add(new Gun("357_revolver", 0.3, 3, 6, 43, 357, 0, 0));
guns.add(new Gun("colt_1903", 0.25, 2, 8, 38, 32, 0, 0));
guns.add(new Gun("colt_45", 0.4, 2, 7, 48, 45, 0, 0));
guns.add(new Gun("colt_peacemaker", 0.35, 4, 6, 43, 45, 0, 0));
guns.add(new Gun("p2022", 0.3, 2, 10, 41, 9, 0, 0));
guns.add(new Gun("snub_nosed_revolver", 0.3, 3, 5, 36, 38, 0, 0));
guns.add(new Gun("tokarev_tt_33", 0.35, 2, 8, 45, 762, 0, 0));
guns.add(new Gun("357_revolver", 0.5, 8, 5, 6, 43, 357, 14, false,0, 0));
guns.add(new Gun("colt_1903", 0.28, 10, 5, 8, 38, 32, 5, false, 0, 0));
guns.add(new Gun("colt_45", 0.3, 9, 5, 7, 48, 45, 5, false, 0, 0));
guns.add(new Gun("colt_peacemaker", 0.3, 8, 5, 6, 43, 45, 5, false, 0, 0));
guns.add(new Gun("p2022", 0.1, 12, 5, 10, 41, 9, 5, false, 0, 0));
guns.add(new Gun("snub_nosed_revolver", 0.3, 7, 3, 5, 36, 38, 14, false, 0, 0));
guns.add(new Gun("tokarev_tt_33", 0.2, 10, 5, 8, 45, 762, 5, false, 0, 0));
guns.add(new Gun("ak_47", 0.15, 4, 5, 30, 45, 762, 2, false, 0, 0));
guns.add(new Gun("awp", 0.3, 4, 20, 1, 75, 762, 20, true, 0, 0));
guns.add(new Gun("rpg9", 2, 2, 8, 10, 999, 8, 0));
guns.add(new Gun("forcegun", 0, 2, 8, 10, 888, 0, 20));
guns.add(new Gun("rpg9", 2, 4, 20, 1, 10, 999, 8, false, 20, 0));
guns.add(new Gun("forcegun", 0, 2, 5, 20, 10, 888, 0, false, 0, 20));
BULLET_ENTITY_TYPE = Registry.register(
@ -93,5 +99,6 @@ public class PlasticGun implements ModInitializer {
PolymerResourcePackUtils.addModAssets(MOD_ID);
PolymerResourcePackUtils.markAsRequired();
logger.info("Guns are loaded");
}
}

@ -1,10 +1,15 @@
package systems.brn.plasticgun.bullets;
import eu.pb4.polymer.virtualentity.api.tracker.DisplayTrackedData;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.json.ModelTransformationMode;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.data.DataTracker;
import net.minecraft.entity.decoration.DisplayEntity;
import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.sound.SoundEvent;
import net.minecraft.sound.SoundEvents;
@ -16,9 +21,11 @@ import net.minecraft.world.World;
import eu.pb4.polymer.core.api.entity.PolymerEntity;
import net.minecraft.world.explosion.Explosion;
import net.minecraft.world.explosion.ExplosionBehavior;
import org.joml.Vector3f;
import systems.brn.plasticgun.guns.Gun;
import java.lang.reflect.Method;
import java.util.List;
import static systems.brn.plasticgun.PlasticGun.BULLET_ENTITY_TYPE;
import static systems.brn.plasticgun.PlasticGun.bullets;
@ -29,8 +36,10 @@ public class BulletEntity extends PersistentProjectileEntity implements PolymerE
private final double explosionPower;
private final double repulsionPower;
private final boolean isIncendiary;
private ItemStack itemStack = Items.ARROW.getDefaultStack();
private final float scale;
public BulletEntity(Vec3d pos, ServerPlayerEntity player, ItemStack stack, ItemStack weapon, Gun gun, double damage, int speed, double explosionPower, double repulsionPower, boolean isIncendiary) {
public BulletEntity(Vec3d pos, ServerPlayerEntity player, ItemStack stack, ItemStack weapon, Gun gun, float scale, double damage, int speed, double explosionPower, double repulsionPower, boolean isIncendiary) {
super(BULLET_ENTITY_TYPE, pos.x, pos.y + 1.5d, pos.z, player.getEntityWorld(), stack, weapon);
this.setOwner(player);
this.setVelocity(player, player.getPitch(), player.getYaw(), 0.0F, speed, 0);
@ -38,12 +47,34 @@ public class BulletEntity extends PersistentProjectileEntity implements PolymerE
this.setDamage(damage);
this.setSilent(true);
this.gun = gun;
this.scale = scale;
this.setCustomPierceLevel((byte) 1);
this.setItemStack(stack);
this.explosionPower = explosionPower;
this.repulsionPower = repulsionPower;
this.isIncendiary = isIncendiary;
}
@Override
public void modifyRawTrackedData(List<DataTracker.SerializedEntry<?>> data, ServerPlayerEntity player, boolean initial) {
if (initial) {
data.add(DataTracker.SerializedEntry.of(DisplayTrackedData.TELEPORTATION_DURATION, 2));
data.add(DataTracker.SerializedEntry.of(DisplayTrackedData.SCALE, new Vector3f(scale)));
data.add(DataTracker.SerializedEntry.of(DisplayTrackedData.BILLBOARD, (byte) DisplayEntity.BillboardMode.CENTER.ordinal()));
data.add(DataTracker.SerializedEntry.of(DisplayTrackedData.Item.ITEM, this.itemStack));
data.add(DataTracker.SerializedEntry.of(DisplayTrackedData.Item.ITEM_DISPLAY, ModelTransformationMode.FIXED.getIndex()));
}
}
public void setItemStack(ItemStack itemStack) {
this.itemStack = itemStack;
}
public ItemStack itemStack() {
return itemStack;
}
public void setCustomPierceLevel(byte level) {
try {
Method method = PersistentProjectileEntity.class.getDeclaredMethod("setPierceLevel", byte.class);
@ -59,6 +90,7 @@ public class BulletEntity extends PersistentProjectileEntity implements PolymerE
this.explosionPower = 0;
this.repulsionPower = 0;
this.isIncendiary = false;
this.scale = 1f;
}
@Override
@ -72,7 +104,7 @@ public class BulletEntity extends PersistentProjectileEntity implements PolymerE
@Override
public EntityType<?> getPolymerEntityType(ServerPlayerEntity player) {
return EntityType.ARROW;
return EntityType.ITEM_DISPLAY;
}
private void hitDamage(Vec3d pos){

@ -21,8 +21,7 @@ import java.util.ArrayList;
import java.util.Set;
import static systems.brn.plasticgun.PlasticGun.bullets;
import static systems.brn.plasticgun.lib.GunComponents.GUN_AMMO_COMPONENT;
import static systems.brn.plasticgun.lib.GunComponents.GUN_LOADING_COMPONENT;
import static systems.brn.plasticgun.lib.GunComponents.*;
import static systems.brn.plasticgun.lib.Util.*;
public class Gun extends SimpleItem implements PolymerItem {
@ -35,14 +34,18 @@ public class Gun extends SimpleItem implements PolymerItem {
public final int caliber;
private final double explosionPowerGun;
private final double repulsionPowerGun;
private final int cooldownTarget;
private final int reloadTarget;
public Gun(String path, double damage, int reloadCount, int clipSize, int speed, int caliber, double explosionPowerGun, double repulsionPowerGun) {
public Gun(String path, double damage, int reloadCount, int reloadTarget, int clipSize, int speed, int caliber, int cooldownTarget, boolean hasScope, double explosionPowerGun, double repulsionPowerGun) {
super(
new Settings()
.maxCount(1)
.component(GUN_AMMO_COMPONENT, ItemStack.EMPTY)
.component(GUN_COOLDOWN_COMPONENT, 0)
.component(GUN_RELOAD_COOLDOWN_COMPONENT, 0)
.maxDamage(clipSize + 1)
, id(path), Items.WOODEN_SWORD
, id(path), hasScope ? Items.SPYGLASS : Items.WOODEN_SWORD
);
Item item = Registry.register(Registries.ITEM, id(path), this);
ItemGroupEvents.modifyEntriesEvent(ItemGroups.COMBAT).register(content -> content.add(item));
@ -60,58 +63,66 @@ public class Gun extends SimpleItem implements PolymerItem {
this.caliber = caliber;
this.explosionPowerGun = explosionPowerGun;
this.repulsionPowerGun = repulsionPowerGun;
this.cooldownTarget = cooldownTarget;
this.reloadTarget = reloadTarget + 1;
}
public void reload(World world, PlayerEntity user, Hand hand) {
if (user instanceof ServerPlayerEntity player && !world.isClient()) {
ItemStack stack = user.getStackInHand(hand);
ItemStack bulletStack = findBulletStack(ammo, player);
ItemStack chamber = stack.getOrDefault(GUN_AMMO_COMPONENT, ItemStack.EMPTY).copy();
int bulletsInChamber = chamber.getCount();
int currentReload = stack.getOrDefault(GUN_LOADING_COMPONENT, 1);
int currentReloadCooldown = stack.getOrDefault(GUN_RELOAD_COOLDOWN_COMPONENT, 0);
if (currentReloadCooldown == 0) {
stack.set(GUN_RELOAD_COOLDOWN_COMPONENT, reloadTarget);
ItemStack bulletStack = findBulletStack(ammo, player);
ItemStack chamber = stack.getOrDefault(GUN_AMMO_COMPONENT, ItemStack.EMPTY).copy();
int bulletsInChamber = chamber.getCount();
int currentReload = stack.getOrDefault(GUN_LOADING_COMPONENT, 1);
if (bulletStack != null && !bulletStack.isEmpty()) { //we have ammo
if (currentReload < reloadCount) { //still reloading
stack.set(GUN_LOADING_COMPONENT, currentReload + 1);
world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.BLOCK_COMPARATOR_CLICK, SoundCategory.PLAYERS, 0.1f, 1.8f);
} else if (currentReload == reloadCount) { //now reload
int addedBullets = Math.min(bulletStack.getCount(), clipSize - bulletsInChamber); //how many
if (chamber.isEmpty() || chamber.getItem() == bulletStack.getItem()) {
if (chamber.isEmpty()) {
chamber = bulletStack.copy();
}
chamber.setCount(bulletsInChamber + addedBullets);
bulletStack.decrement(addedBullets);
if (chamber.isEmpty()) {
stack.remove(GUN_AMMO_COMPONENT);
} else {
stack.set(GUN_AMMO_COMPONENT, chamber);
world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.BLOCK_LEVER_CLICK, SoundCategory.PLAYERS, 0.5f, 1.0f);
}
stack.set(GUN_LOADING_COMPONENT, 1);
} else {
if (canInsertItemIntoInventory(player.getInventory(), chamber.copy()) == chamber.getCount()) { //can take out chamber
insertStackIntoInventory(player.getInventory(), chamber.copy());
chamber.setCount(0); //empty
int targetCount = Math.min(bulletStack.getCount(), clipSize);
chamber = bulletStack.copy();
chamber.setCount(targetCount);
if (bulletStack != null && !bulletStack.isEmpty()) { //we have ammo
if (currentReload < reloadCount) { //still reloading
stack.set(GUN_LOADING_COMPONENT, currentReload + 1);
world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.BLOCK_COMPARATOR_CLICK, SoundCategory.PLAYERS, 0.1f, 1.8f);
} else if (currentReload == reloadCount) { //now reload
int addedBullets = Math.min(bulletStack.getCount(), clipSize - bulletsInChamber); //how many
if (chamber.isEmpty() || chamber.getItem() == bulletStack.getItem()) {
if (chamber.isEmpty()) {
chamber = bulletStack.copy();
}
chamber.setCount(bulletsInChamber + addedBullets);
bulletStack.decrement(addedBullets);
if (chamber.isEmpty()) {
stack.remove(GUN_AMMO_COMPONENT);
} else {
stack.set(GUN_AMMO_COMPONENT, chamber);
world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.BLOCK_LEVER_CLICK, SoundCategory.PLAYERS, 1f, 2.5f);
world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.BLOCK_LEVER_CLICK, SoundCategory.PLAYERS, 0.5f, 1.0f);
}
bulletStack.decrement(targetCount);
stack.set(GUN_LOADING_COMPONENT, 1);
} else {
if (canInsertItemIntoInventory(player.getInventory(), chamber.copy()) == chamber.getCount()) { //can take out chamber
insertStackIntoInventory(player.getInventory(), chamber.copy());
chamber.setCount(0); //empty
int targetCount = Math.min(bulletStack.getCount(), clipSize);
chamber = bulletStack.copy();
chamber.setCount(targetCount);
if (chamber.isEmpty()) {
stack.remove(GUN_AMMO_COMPONENT);
} else {
stack.set(GUN_AMMO_COMPONENT, chamber);
world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.BLOCK_LEVER_CLICK, SoundCategory.PLAYERS, 1f, 2.5f);
}
bulletStack.decrement(targetCount);
stack.set(GUN_LOADING_COMPONENT, 1);
}
}
}
}
if (player.isCreative()) {
stack.set(GUN_AMMO_COMPONENT, new ItemStack(ammo.getFirst(), clipSize)); // Ensure ammo.get(0) is a valid item
}
updateDamage(stack);
} else {
world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.BLOCK_FIRE_EXTINGUISH, SoundCategory.PLAYERS, 1.0f, 2.0f);
}
if (player.isCreative()) {
stack.set(GUN_AMMO_COMPONENT, new ItemStack(ammo.getFirst(), clipSize)); // Ensure ammo.get(0) is a valid item
}
updateDamage(stack);
}
}
@ -140,6 +151,7 @@ public class Gun extends SimpleItem implements PolymerItem {
if (user instanceof ServerPlayerEntity player && !world.isClient()) {
ItemStack stack = user.getStackInHand(hand);
int currentReload = stack.getOrDefault(GUN_LOADING_COMPONENT, 1);
int currentCooldown = stack.getOrDefault(GUN_COOLDOWN_COMPONENT, 0);
ItemStack chamber = stack.getOrDefault(GUN_AMMO_COMPONENT, ItemStack.EMPTY).copy();
BulletItem bullet = null;
@ -150,28 +162,31 @@ public class Gun extends SimpleItem implements PolymerItem {
}
}
if (!chamber.isEmpty() && currentReload == 1) {
if (!chamber.isEmpty() && currentReload == 1 && currentCooldown == 0) {
boolean isIncendiary = false;
double explosionPower = explosionPowerGun;
double repulsionPower = repulsionPowerGun;
if (bullet != null){
if (bullet != null) {
isIncendiary = bullet.isIncendiary;
explosionPower *= bullet.explosionPowerCoefficient;
repulsionPower *= bullet.repulsionPowerCoefficient;
}
BulletEntity bulletEntity = new BulletEntity(user.getPos(), player, chamber, user.getStackInHand(hand), this, damage, speed, explosionPower, repulsionPower, isIncendiary);
BulletEntity bulletEntity = new BulletEntity(user.getPos(), player, chamber, user.getStackInHand(hand), this, 1f, damage, speed, explosionPower, repulsionPower, isIncendiary);
world.spawnEntity(bulletEntity);
world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.ENTITY_GENERIC_EXPLODE.value(), SoundCategory.PLAYERS, 0.1f, 1.2f);
chamber.decrement(1);
stack.set(GUN_COOLDOWN_COMPONENT, cooldownTarget);
doRecoil(player);
if (chamber.isEmpty()) {
stack.remove(GUN_AMMO_COMPONENT);
} else {
stack.set(GUN_AMMO_COMPONENT, chamber);
}
} else {
} else if (cooldownTarget > 0) {
world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.BLOCK_FIRE_EXTINGUISH, SoundCategory.PLAYERS, 1.0f, 2.0f);
} else if (currentReload > 1) {
world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.UI_BUTTON_CLICK.value(), SoundCategory.PLAYERS, 1.0f, 2.0f);
}
updateDamage(stack);

@ -3,12 +3,17 @@ package systems.brn.plasticgun.lib;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.world.World;
import org.slf4j.LoggerFactory;
import systems.brn.plasticgun.guns.Gun;
import static systems.brn.plasticgun.PlasticGun.guns;
import static systems.brn.plasticgun.PlasticGun.*;
import static systems.brn.plasticgun.lib.GunComponents.*;
public class EventHandler {
public static TypedActionResult<ItemStack> onItemUse(PlayerEntity playerEntity, World world, Hand hand) {
@ -29,12 +34,18 @@ public class EventHandler {
public static void onWorldTick(World world) {
// Iterate through all players to detect hand swings or item interactions
for (PlayerEntity player : world.getPlayers()) {
if (!world.isClient && player.handSwinging && player.handSwingTicks == 1) {
if (!world.isClient) {
Hand hand = player.getActiveHand();
Item stackInHand = player.getStackInHand(hand).getItem();
ItemStack stackInHand = player.getStackInHand(hand);
Item itemInHand = stackInHand.getItem();
for (Gun gun : guns) {
if (gun == stackInHand) {
gun.shoot(world, player, hand);
if (gun == itemInHand) {
decrementComponent(GUN_COOLDOWN_COMPONENT, stackInHand);
decrementComponent(GUN_RELOAD_COOLDOWN_COMPONENT, stackInHand);
if (player.handSwinging && player.handSwingTicks == -1) {
gun.shoot(world, player, hand);
}
break;
}
}

@ -11,8 +11,10 @@ import java.util.function.UnaryOperator;
public class GunComponents {
public static final ComponentType<ItemStack> GUN_AMMO_COMPONENT = register("gunammo", builder -> builder.codec(ItemStack.CODEC));
public static final ComponentType<Integer> GUN_LOADING_COMPONENT = register("gunload", builder -> builder.codec(Codec.INT));
public static final ComponentType<ItemStack> GUN_AMMO_COMPONENT = register("gun_ammo", builder -> builder.codec(ItemStack.CODEC));
public static final ComponentType<Integer> GUN_LOADING_COMPONENT = register("gun_load", builder -> builder.codec(Codec.INT));
public static final ComponentType<Integer> GUN_COOLDOWN_COMPONENT = register("gun_cooldown", builder -> builder.codec(Codec.INT));
public static final ComponentType<Integer> GUN_RELOAD_COOLDOWN_COMPONENT = register("gun_reload_cooldown", builder -> builder.codec(Codec.INT));
private static <T> ComponentType<T> register(String id, UnaryOperator<ComponentType.Builder<T>> builderOperator) {
ComponentType<T> componentType = Registry.register(
@ -23,4 +25,12 @@ public class GunComponents {
PolymerComponent.registerDataComponent(componentType);
return componentType;
}
public static void decrementComponent(ComponentType<Integer> componentType, ItemStack stack) {
int component = stack.getOrDefault(componentType, 0);
if (component > 0) {
component--;
stack.set(componentType, component);
}
}
}