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 yarn_mappings=1.21+build.9
loader_version=0.16.0 loader_version=0.16.0
# Mod Properties # Mod Properties
mod_version=1.0 mod_version=1.1
maven_group=systems.brn maven_group=systems.brn
archives_base_name=plasticgun archives_base_name=plasticgun
# Dependencies # Dependencies

@ -10,6 +10,8 @@ import net.minecraft.entity.EntityType;
import net.minecraft.entity.SpawnGroup; import net.minecraft.entity.SpawnGroup;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry; import net.minecraft.registry.Registry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import systems.brn.plasticgun.bullets.BulletEntity; import systems.brn.plasticgun.bullets.BulletEntity;
import systems.brn.plasticgun.bullets.BulletItem; import systems.brn.plasticgun.bullets.BulletItem;
import systems.brn.plasticgun.guns.Gun; import systems.brn.plasticgun.guns.Gun;
@ -32,6 +34,8 @@ public class PlasticGun implements ModInitializer {
public static EntityType<DamageTester> DAMAGE_TESTER_ENTITY_TYPE; public static EntityType<DamageTester> DAMAGE_TESTER_ENTITY_TYPE;
public static final Logger logger = LoggerFactory.getLogger(MOD_ID);;
@Override @Override
public void onInitialize() { public void onInitialize() {
@ -56,16 +60,18 @@ public class PlasticGun implements ModInitializer {
bullets.add(new BulletItem("force_container", 0, 888, false,0, 1)); bullets.add(new BulletItem("force_container", 0, 888, false,0, 1));
// Guns // Guns
guns.add(new Gun("357_revolver", 0.3, 3, 6, 43, 357, 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.25, 2, 8, 38, 32, 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.4, 2, 7, 48, 45, 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.35, 4, 6, 43, 45, 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.3, 2, 10, 41, 9, 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, 3, 5, 36, 38, 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.35, 2, 8, 45, 762, 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("rpg9", 2, 4, 20, 1, 10, 999, 8, false, 20, 0));
guns.add(new Gun("forcegun", 0, 2, 8, 10, 888, 0, 20)); guns.add(new Gun("forcegun", 0, 2, 5, 20, 10, 888, 0, false, 0, 20));
BULLET_ENTITY_TYPE = Registry.register( BULLET_ENTITY_TYPE = Registry.register(
@ -93,5 +99,6 @@ public class PlasticGun implements ModInitializer {
PolymerResourcePackUtils.addModAssets(MOD_ID); PolymerResourcePackUtils.addModAssets(MOD_ID);
PolymerResourcePackUtils.markAsRequired(); PolymerResourcePackUtils.markAsRequired();
logger.info("Guns are loaded");
} }
} }

@ -1,10 +1,15 @@
package systems.brn.plasticgun.bullets; package systems.brn.plasticgun.bullets;
import eu.pb4.polymer.virtualentity.api.tracker.DisplayTrackedData;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.render.model.json.ModelTransformationMode;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType; 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.entity.projectile.PersistentProjectileEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.sound.SoundEvent; import net.minecraft.sound.SoundEvent;
import net.minecraft.sound.SoundEvents; import net.minecraft.sound.SoundEvents;
@ -16,9 +21,11 @@ import net.minecraft.world.World;
import eu.pb4.polymer.core.api.entity.PolymerEntity; import eu.pb4.polymer.core.api.entity.PolymerEntity;
import net.minecraft.world.explosion.Explosion; import net.minecraft.world.explosion.Explosion;
import net.minecraft.world.explosion.ExplosionBehavior; import net.minecraft.world.explosion.ExplosionBehavior;
import org.joml.Vector3f;
import systems.brn.plasticgun.guns.Gun; import systems.brn.plasticgun.guns.Gun;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.List;
import static systems.brn.plasticgun.PlasticGun.BULLET_ENTITY_TYPE; import static systems.brn.plasticgun.PlasticGun.BULLET_ENTITY_TYPE;
import static systems.brn.plasticgun.PlasticGun.bullets; 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 explosionPower;
private final double repulsionPower; private final double repulsionPower;
private final boolean isIncendiary; 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); super(BULLET_ENTITY_TYPE, pos.x, pos.y + 1.5d, pos.z, player.getEntityWorld(), stack, weapon);
this.setOwner(player); this.setOwner(player);
this.setVelocity(player, player.getPitch(), player.getYaw(), 0.0F, speed, 0); 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.setDamage(damage);
this.setSilent(true); this.setSilent(true);
this.gun = gun; this.gun = gun;
this.scale = scale;
this.setCustomPierceLevel((byte) 1); this.setCustomPierceLevel((byte) 1);
this.setItemStack(stack);
this.explosionPower = explosionPower; this.explosionPower = explosionPower;
this.repulsionPower = repulsionPower; this.repulsionPower = repulsionPower;
this.isIncendiary = isIncendiary; 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) { public void setCustomPierceLevel(byte level) {
try { try {
Method method = PersistentProjectileEntity.class.getDeclaredMethod("setPierceLevel", byte.class); Method method = PersistentProjectileEntity.class.getDeclaredMethod("setPierceLevel", byte.class);
@ -59,6 +90,7 @@ public class BulletEntity extends PersistentProjectileEntity implements PolymerE
this.explosionPower = 0; this.explosionPower = 0;
this.repulsionPower = 0; this.repulsionPower = 0;
this.isIncendiary = false; this.isIncendiary = false;
this.scale = 1f;
} }
@Override @Override
@ -72,7 +104,7 @@ public class BulletEntity extends PersistentProjectileEntity implements PolymerE
@Override @Override
public EntityType<?> getPolymerEntityType(ServerPlayerEntity player) { public EntityType<?> getPolymerEntityType(ServerPlayerEntity player) {
return EntityType.ARROW; return EntityType.ITEM_DISPLAY;
} }
private void hitDamage(Vec3d pos){ private void hitDamage(Vec3d pos){

@ -21,8 +21,7 @@ import java.util.ArrayList;
import java.util.Set; import java.util.Set;
import static systems.brn.plasticgun.PlasticGun.bullets; import static systems.brn.plasticgun.PlasticGun.bullets;
import static systems.brn.plasticgun.lib.GunComponents.GUN_AMMO_COMPONENT; import static systems.brn.plasticgun.lib.GunComponents.*;
import static systems.brn.plasticgun.lib.GunComponents.GUN_LOADING_COMPONENT;
import static systems.brn.plasticgun.lib.Util.*; import static systems.brn.plasticgun.lib.Util.*;
public class Gun extends SimpleItem implements PolymerItem { public class Gun extends SimpleItem implements PolymerItem {
@ -35,14 +34,18 @@ public class Gun extends SimpleItem implements PolymerItem {
public final int caliber; public final int caliber;
private final double explosionPowerGun; private final double explosionPowerGun;
private final double repulsionPowerGun; 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( super(
new Settings() new Settings()
.maxCount(1) .maxCount(1)
.component(GUN_AMMO_COMPONENT, ItemStack.EMPTY) .component(GUN_AMMO_COMPONENT, ItemStack.EMPTY)
.component(GUN_COOLDOWN_COMPONENT, 0)
.component(GUN_RELOAD_COOLDOWN_COMPONENT, 0)
.maxDamage(clipSize + 1) .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); Item item = Registry.register(Registries.ITEM, id(path), this);
ItemGroupEvents.modifyEntriesEvent(ItemGroups.COMBAT).register(content -> content.add(item)); ItemGroupEvents.modifyEntriesEvent(ItemGroups.COMBAT).register(content -> content.add(item));
@ -60,11 +63,16 @@ public class Gun extends SimpleItem implements PolymerItem {
this.caliber = caliber; this.caliber = caliber;
this.explosionPowerGun = explosionPowerGun; this.explosionPowerGun = explosionPowerGun;
this.repulsionPowerGun = repulsionPowerGun; this.repulsionPowerGun = repulsionPowerGun;
this.cooldownTarget = cooldownTarget;
this.reloadTarget = reloadTarget + 1;
} }
public void reload(World world, PlayerEntity user, Hand hand) { public void reload(World world, PlayerEntity user, Hand hand) {
if (user instanceof ServerPlayerEntity player && !world.isClient()) { if (user instanceof ServerPlayerEntity player && !world.isClient()) {
ItemStack stack = user.getStackInHand(hand); ItemStack stack = user.getStackInHand(hand);
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 bulletStack = findBulletStack(ammo, player);
ItemStack chamber = stack.getOrDefault(GUN_AMMO_COMPONENT, ItemStack.EMPTY).copy(); ItemStack chamber = stack.getOrDefault(GUN_AMMO_COMPONENT, ItemStack.EMPTY).copy();
int bulletsInChamber = chamber.getCount(); int bulletsInChamber = chamber.getCount();
@ -112,6 +120,9 @@ public class Gun extends SimpleItem implements PolymerItem {
stack.set(GUN_AMMO_COMPONENT, new ItemStack(ammo.getFirst(), clipSize)); // Ensure ammo.get(0) is a valid item stack.set(GUN_AMMO_COMPONENT, new ItemStack(ammo.getFirst(), clipSize)); // Ensure ammo.get(0) is a valid item
} }
updateDamage(stack); updateDamage(stack);
} else {
world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.BLOCK_FIRE_EXTINGUISH, SoundCategory.PLAYERS, 1.0f, 2.0f);
}
} }
} }
@ -140,6 +151,7 @@ public class Gun extends SimpleItem implements PolymerItem {
if (user instanceof ServerPlayerEntity player && !world.isClient()) { if (user instanceof ServerPlayerEntity player && !world.isClient()) {
ItemStack stack = user.getStackInHand(hand); ItemStack stack = user.getStackInHand(hand);
int currentReload = stack.getOrDefault(GUN_LOADING_COMPONENT, 1); 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(); ItemStack chamber = stack.getOrDefault(GUN_AMMO_COMPONENT, ItemStack.EMPTY).copy();
BulletItem bullet = null; BulletItem bullet = null;
@ -150,7 +162,7 @@ public class Gun extends SimpleItem implements PolymerItem {
} }
} }
if (!chamber.isEmpty() && currentReload == 1) { if (!chamber.isEmpty() && currentReload == 1 && currentCooldown == 0) {
boolean isIncendiary = false; boolean isIncendiary = false;
double explosionPower = explosionPowerGun; double explosionPower = explosionPowerGun;
double repulsionPower = repulsionPowerGun; double repulsionPower = repulsionPowerGun;
@ -161,17 +173,20 @@ public class Gun extends SimpleItem implements PolymerItem {
repulsionPower *= bullet.repulsionPowerCoefficient; 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.spawnEntity(bulletEntity);
world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.ENTITY_GENERIC_EXPLODE.value(), SoundCategory.PLAYERS, 0.1f, 1.2f); world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.ENTITY_GENERIC_EXPLODE.value(), SoundCategory.PLAYERS, 0.1f, 1.2f);
chamber.decrement(1); chamber.decrement(1);
stack.set(GUN_COOLDOWN_COMPONENT, cooldownTarget);
doRecoil(player); doRecoil(player);
if (chamber.isEmpty()) { if (chamber.isEmpty()) {
stack.remove(GUN_AMMO_COMPONENT); stack.remove(GUN_AMMO_COMPONENT);
} else { } else {
stack.set(GUN_AMMO_COMPONENT, chamber); 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); world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.UI_BUTTON_CLICK.value(), SoundCategory.PLAYERS, 1.0f, 2.0f);
} }
updateDamage(stack); updateDamage(stack);

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

@ -11,8 +11,10 @@ import java.util.function.UnaryOperator;
public class GunComponents { public class GunComponents {
public static final ComponentType<ItemStack> GUN_AMMO_COMPONENT = register("gunammo", builder -> builder.codec(ItemStack.CODEC)); 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("gunload", builder -> builder.codec(Codec.INT)); 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) { private static <T> ComponentType<T> register(String id, UnaryOperator<ComponentType.Builder<T>> builderOperator) {
ComponentType<T> componentType = Registry.register( ComponentType<T> componentType = Registry.register(
@ -23,4 +25,12 @@ public class GunComponents {
PolymerComponent.registerDataComponent(componentType); PolymerComponent.registerDataComponent(componentType);
return 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);
}
}
} }