Add stuff

This commit is contained in:
Bruno Rybársky 2024-07-27 15:31:06 +02:00
parent 4df69c27a1
commit d5a28040e4
70 changed files with 1133 additions and 102 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.1
mod_version=1.3
maven_group=systems.brn
archives_base_name=plasticgun
# Dependencies

@ -3,6 +3,7 @@ package systems.brn.plasticgun;
import eu.pb4.polymer.core.api.entity.PolymerEntityUtils;
import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerEntityEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.event.player.UseItemCallback;
import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry;
@ -14,8 +15,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import systems.brn.plasticgun.bullets.BulletEntity;
import systems.brn.plasticgun.bullets.BulletItem;
import systems.brn.plasticgun.grenades.GrenadeEntity;
import systems.brn.plasticgun.grenades.GrenadeItem;
import systems.brn.plasticgun.guns.Gun;
import systems.brn.plasticgun.lib.EventHandler;
import systems.brn.plasticgun.lib.ItemGroups;
import systems.brn.plasticgun.shurikens.ShurikenEntity;
import systems.brn.plasticgun.shurikens.ShurikenItem;
import systems.brn.plasticgun.testing.DamageTester;
import java.util.ArrayList;
@ -30,50 +36,97 @@ public class PlasticGun implements ModInitializer {
public static final ArrayList<BulletItem> bullets = new ArrayList<>();
public static final ArrayList<GrenadeItem> grenades = new ArrayList<>();
public static final ArrayList<ShurikenItem> shurikens = new ArrayList<>();
public static EntityType<BulletEntity> BULLET_ENTITY_TYPE;
public static EntityType<GrenadeEntity> GRENADE_ENTITY_TYPE;
public static EntityType<ShurikenEntity> SHURIKEN_ENTITY_TYPE;
public static EntityType<DamageTester> DAMAGE_TESTER_ENTITY_TYPE;
public static final Logger logger = LoggerFactory.getLogger(MOD_ID);;
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", 99, 1.4, 357, false, 0, 0));
bullets.add(new BulletItem("32_acp_high_velocity", 99, 0.9, 32, false, 0, 0));
bullets.add(new BulletItem("45_acp_hollow_point", 99, 1.2, 45, false, 0, 0));
bullets.add(new BulletItem("9mm_jhp", 99, 1.05, 9, false, 0, 0));
bullets.add(new BulletItem("38_special_p", 99, 1.3, 38, false, 0, 0));
bullets.add(new BulletItem("762_tokarev_ap", 99, 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", 99, 1, 357, false, 0, 0));
bullets.add(new BulletItem("32_acp", 99, 0.8, 32, false, 0, 0));
bullets.add(new BulletItem("45_acp", 99, 1, 45, false, 0, 0));
bullets.add(new BulletItem("9mm_parabellum", 99, 0.9, 9, false, 0, 0));
bullets.add(new BulletItem("38_special", 99, 0.95, 38, false, 0, 0));
bullets.add(new BulletItem("762_tokarev", 99, 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_incendiary", 4, 1.1, 999, true, 1, 0));
bullets.add(new BulletItem("rpg_shell", 4, 1.1, 999, false, 1, 0));
bullets.add(new BulletItem("force_container", 99, 0, 888, false, 0, 1));
// Guns
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("357_revolver", 1, 8, 5, 6, 45, 357, 14, false, 0, 0));
guns.add(new Gun("colt_1903", 0.3, 10, 5, 8, 38, 32, 5, false, 0, 0));
guns.add(new Gun("colt_45", 0.4, 9, 5, 7, 48, 45, 5, false, 0, 0));
guns.add(new Gun("colt_peacemaker", 0.6, 8, 5, 6, 43, 45, 5, false, 0, 0));
guns.add(new Gun("p2022", 0.2, 12, 5, 10, 41, 9, 5, false, 0, 0));
guns.add(new Gun("snub_nosed_revolver", 0.4, 7, 3, 5, 36, 38, 14, false, 0, 0));
guns.add(new Gun("tokarev_tt_33", 0.7, 10, 5, 8, 45, 762, 5, false, 0, 0));
guns.add(new Gun("ak_47", 0.2, 4, 5, 30, 45, 762, 0, false, 0, 0));
guns.add(new Gun("awp", 1, 4, 20, 1, 75, 762, 20, true, 0, 0));
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));
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));
grenades.add(new GrenadeItem("grenade_m67", 1, 6.5f, 0.5f, 60, false, true, 0, 0, 0, 10, 0)); // M67 Fragmentation Grenade
grenades.add(new GrenadeItem("grenade_mk2", 1, 7f, 0.5f, 60, false, true, 0, 0, 0, 10, 0)); // Mk 2 Fragmentation Grenade
grenades.add(new GrenadeItem("grenade_an_m14", 1, 5f, 0.5f, 40, true, false, 0, 0, 0, 8, 0)); // AN-M14 Incendiary Grenade
grenades.add(new GrenadeItem("grenade_m3d", 1, 10f, 0.5f, 60, true, true, 0, 0, 0, 10, 0)); // M34 White Phosphorus Incendiary Fragmentation Grenade
grenades.add(new GrenadeItem("grenade_m18", 1, 0.1f, 0.2f, 50, false, false, 0, 0, 100, 15, 0)); // M18 Smoke Grenade
grenades.add(new GrenadeItem("grenade_l109a1", 1, 6.5f, 0.5f, 60, false, true, 0, 0, 0, 10, 0)); // L109A1 Fragmentation Grenade
grenades.add(new GrenadeItem("grenade_m84", 1, 0.5f, 0.2f, 120, false, false, 10, 10, 5, 12, 10)); // M84 Stun Grenade (Flashbang)
grenades.add(new GrenadeItem("grenade_rgd_5", 1, 6.5f, 0.5f, 60, false, true, 0, 0, 0, 10, 0)); // RGD-5 Fragmentation Grenade
grenades.add(new GrenadeItem("grenade_thermite", 1, 4f, 0.3f, 80, true, false, 0, 0, 0, 8, 15)); // Thermite Grenade
grenades.add(new GrenadeItem("grenade_f1", 1, 7f, 0.5f, 60, false, true, 0, 0, 0, 10, 0)); // F1 Soviet Fragmentation Grenade
grenades.add(new GrenadeItem("grenade_mk3a2", 1, 6f, 0.4f, 60, false, false, 0, 0, 0, 10, 0)); // Mk3A2 Offensive Grenade
grenades.add(new GrenadeItem("grenade_m7a3", 1, 0.1f, 0.2f, 90, false, false, 0, 0, 50, 8, 40)); // M7A3 CS Gas Grenade
grenades.add(new GrenadeItem("grenade_no_69", 1, 5.5f, 0.4f, 60, false, false, 0, 0, 0, 10, 0)); // No. 69 British Offensive Grenade
grenades.add(new GrenadeItem("grenade_rgo", 1, 6.5f, 0.5f, 60, false, true, 0, 0, 0, 10, 0)); // RGO Fragmentation Grenade
grenades.add(new GrenadeItem("grenade_k417", 1, 7f, 0.5f, 70, false, true, 0, 0, 0, 10, 0)); // K417 Fragmentation Grenade
shurikens.add(new ShurikenItem("wooden_shuriken", 0.1, 5, 4f));
shurikens.add(new ShurikenItem("stone_shuriken", 0.2, 5, 4f));
shurikens.add(new ShurikenItem("iron_shuriken", 0.4, 5, 4f));
shurikens.add(new ShurikenItem("golden_shuriken", 0.3, 5, 4f));
shurikens.add(new ShurikenItem("diamond_shuriken", 0.8, 5, 4f));
shurikens.add(new ShurikenItem("netherite_shuriken", 1, 5, 4f));
GRENADE_ENTITY_TYPE = Registry.register(
Registries.ENTITY_TYPE,
id("grenade"),
EntityType.Builder.<GrenadeEntity>create(GrenadeEntity::new, SpawnGroup.MISC).build()
);
PolymerEntityUtils.registerType(GRENADE_ENTITY_TYPE);
BULLET_ENTITY_TYPE = Registry.register(
Registries.ENTITY_TYPE,
id("bullet"),
@ -81,10 +134,17 @@ public class PlasticGun implements ModInitializer {
);
PolymerEntityUtils.registerType(BULLET_ENTITY_TYPE);
SHURIKEN_ENTITY_TYPE = Registry.register(
Registries.ENTITY_TYPE,
id("shuriken"),
EntityType.Builder.<ShurikenEntity>create(ShurikenEntity::new, SpawnGroup.MISC).build()
);
PolymerEntityUtils.registerType(SHURIKEN_ENTITY_TYPE);
DAMAGE_TESTER_ENTITY_TYPE = Registry.register(
Registries.ENTITY_TYPE,
id("damagetester"),
EntityType.Builder.<DamageTester>create(DamageTester::new, SpawnGroup.MISC).build()
EntityType.Builder.create(DamageTester::new, SpawnGroup.MISC).build()
);
FabricDefaultAttributeRegistry.register(DAMAGE_TESTER_ENTITY_TYPE, DamageTester.createDamageTesterAttributes());
PolymerEntityUtils.registerType(DAMAGE_TESTER_ENTITY_TYPE);
@ -95,7 +155,11 @@ public class PlasticGun implements ModInitializer {
// Use a custom method to detect general hand swings
// This is done by checking the player's actions in the tick event
ServerTickEvents.END_WORLD_TICK.register(EventHandler::onWorldTick);
ServerTickEvents.END_WORLD_TICK.register(EventHandler::onServerWorldTick);
ServerEntityEvents.ENTITY_LOAD.register(EventHandler::onEntityLoad);
ItemGroups.register();
PolymerResourcePackUtils.addModAssets(MOD_ID);
PolymerResourcePackUtils.markAsRequired();

@ -1,27 +1,20 @@
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;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.Vec3d;
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 net.minecraft.world.World;
import systems.brn.plasticgun.guns.Gun;
import java.lang.reflect.Method;
@ -29,7 +22,7 @@ import java.util.List;
import static systems.brn.plasticgun.PlasticGun.BULLET_ENTITY_TYPE;
import static systems.brn.plasticgun.PlasticGun.bullets;
import static systems.brn.plasticgun.lib.Util.applyKnockbackToEntities;
import static systems.brn.plasticgun.lib.Util.*;
public class BulletEntity extends PersistentProjectileEntity implements PolymerEntity {
private final Gun gun;
@ -39,11 +32,11 @@ public class BulletEntity extends PersistentProjectileEntity implements PolymerE
private ItemStack itemStack = Items.ARROW.getDefaultStack();
private final float scale;
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);
public BulletEntity(ServerPlayerEntity player, ItemStack stack, Hand hand, Gun gun, float scale, double damage, float speed, double explosionPower, double repulsionPower, boolean isIncendiary) {
super(BULLET_ENTITY_TYPE, player.getPos().x, player.getPos().y + 1.5d, player.getPos().z, player.getServerWorld(), stack, player.getStackInHand(hand));
this.setOwner(player);
this.setVelocity(player, player.getPitch(), player.getYaw(), 0.0F, speed, 0);
this.pickupType = PickupPermission.CREATIVE_ONLY;
this.pickupType = PickupPermission.DISALLOWED;
this.setDamage(damage);
this.setSilent(true);
this.gun = gun;
@ -57,24 +50,13 @@ public class BulletEntity extends PersistentProjectileEntity implements PolymerE
@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()));
}
setProjectileData(data, initial, scale, this.itemStack);
}
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);
@ -107,15 +89,6 @@ public class BulletEntity extends PersistentProjectileEntity implements PolymerE
return EntityType.ITEM_DISPLAY;
}
private void hitDamage(Vec3d pos){
if(explosionPower > 0) {
getWorld().createExplosion(this, Explosion.createDamageSource(this.getWorld(), this), null, pos.getX(), pos.getY(), pos.getZ(), (float) explosionPower, isIncendiary, World.ExplosionSourceType.TNT);
}
if (repulsionPower > 0){
applyKnockbackToEntities(this, pos, repulsionPower * 100, repulsionPower);
}
}
@Override
protected void onBlockHit(BlockHitResult blockHitResult) {
this.setPosition(blockHitResult.getPos());
@ -130,7 +103,7 @@ public class BulletEntity extends PersistentProjectileEntity implements PolymerE
this.setOnFire(true);
super.onBlockHit(blockHitResult);
this.setOnFire(false);
hitDamage(blockHitResult.getPos());
hitDamage(blockHitResult.getPos(), explosionPower, repulsionPower, getWorld(), this, isIncendiary, 5, null);
this.discard();
}
@ -142,7 +115,7 @@ public class BulletEntity extends PersistentProjectileEntity implements PolymerE
setSilent(true);
super.onEntityHit(entityHitResult);
hitDamage(entityHitResult.getPos());
hitDamage(entityHitResult.getPos(), explosionPower, repulsionPower, getWorld(), this, isIncendiary, 5, null);
this.discard();
}

@ -1,13 +1,18 @@
package systems.brn.plasticgun.bullets;
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.LoreComponent;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroups;
import net.minecraft.item.Items;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.text.Text;
import systems.brn.plasticgun.lib.ItemGroups;
import systems.brn.plasticgun.lib.SimpleItem;
import java.util.List;
import static systems.brn.plasticgun.lib.Util.id;
public class BulletItem extends SimpleItem {
@ -16,14 +21,26 @@ public class BulletItem extends SimpleItem {
public final boolean isIncendiary;
public final double explosionPowerCoefficient;
public final double repulsionPowerCoefficient;
public BulletItem(String path, double damageCoefficient, int caliber, boolean isIncendiary, double explosionPowerCoefficient, double repulsionPowerCoefficient) {
super(new Settings().maxCount(99), id(path), Items.STICK);
public BulletItem(String path, int maxCount, double damageCoefficient, int caliber, boolean isIncendiary, double explosionPowerCoefficient, double repulsionPowerCoefficient) {
super(
new Settings()
.maxCount(maxCount)
.component(DataComponentTypes.LORE, new LoreComponent(List.of(
Text.translatable("gun.description.speed", damageCoefficient),
Text.translatable("gun.description.explosion_coefficient", explosionPowerCoefficient),
Text.translatable("gun.description.repulsion_efficient", repulsionPowerCoefficient),
Text.translatable("gun.description.repulsion_efficient", repulsionPowerCoefficient),
Text.translatable(isIncendiary ? "gun.description.incendiary_yes" : "gun.description.incendiary_no")
))
)
,
id(path),
Items.STICK);
this.damageCoefficient = damageCoefficient;
this.caliber = caliber;
this.isIncendiary = isIncendiary;
this.explosionPowerCoefficient = explosionPowerCoefficient;
this.repulsionPowerCoefficient = repulsionPowerCoefficient;
Item item = Registry.register(Registries.ITEM, this.identifier, this);
ItemGroupEvents.modifyEntriesEvent(ItemGroups.FUNCTIONAL).register(content -> content.add(item));
Registry.register(Registries.ITEM, this.identifier, this);
}
}

@ -0,0 +1,15 @@
package systems.brn.plasticgun.grenades;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockView;
import net.minecraft.world.explosion.Explosion;
import net.minecraft.world.explosion.ExplosionBehavior;
public class FragmentationExplosionBehavior extends ExplosionBehavior {
@Override
public boolean canDestroyBlock(Explosion explosion, BlockView world, BlockPos pos, BlockState state, float power) {
return state.getBlock() == Blocks.AIR;
}
}

@ -0,0 +1,178 @@
package systems.brn.plasticgun.grenades;
import eu.pb4.polymer.core.api.entity.PolymerEntity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.MovementType;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.item.ItemStack;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.random.Random;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.world.World;
import systems.brn.plasticgun.throwables.ThrowableProjectile;
import java.util.List;
import static systems.brn.plasticgun.PlasticGun.GRENADE_ENTITY_TYPE;
import static systems.brn.plasticgun.lib.Util.*;
public class GrenadeEntity extends ThrowableProjectile implements PolymerEntity {
public double explosionPower;
public double repulsionPower;
public boolean isIncendiary;
public final boolean isFragmentation;
public int timer;
public int flashBangDuration;
public int stunDuration;
public int smokeTicks;
public final int effectRadius;
public final int smokeCount;
public GrenadeEntity(World world, Vec3d pos, ItemStack itemStack, int timer, float scale, double explosionPower, double repulsionPower, boolean isIncendiary, boolean isFragmentation, int flashBangDuration, int stunDuration, int smokeTicks, int effectRadius, int smokeCount) {
super(GRENADE_ENTITY_TYPE, world, pos, itemStack, scale, 0f, PickupPermission.DISALLOWED, (byte) 255);
this.explosionPower = explosionPower;
this.repulsionPower = repulsionPower;
this.isIncendiary = isIncendiary;
this.timer = timer;
this.flashBangDuration = flashBangDuration;
this.stunDuration = stunDuration;
this.smokeTicks = smokeTicks;
this.effectRadius = effectRadius;
this.smokeCount = smokeCount;
this.isFragmentation = isFragmentation;
}
public GrenadeEntity(ServerPlayerEntity player, ItemStack itemStack, int timer, float scale, int speed, double explosionPower, double repulsionPower, boolean isIncendiary, boolean isFragmentation, int flashBangDuration, int stunDuration, int smokeTicks, int effectRadius, int smokeCount) {
super(GRENADE_ENTITY_TYPE, player, itemStack, scale, 1, 0d, PickupPermission.DISALLOWED, (byte) 255);
this.setVelocity(player, player.getPitch(), player.getYaw(), 0.0F, speed, 0);
this.explosionPower = explosionPower;
this.repulsionPower = repulsionPower;
this.isIncendiary = isIncendiary;
this.timer = timer;
this.flashBangDuration = flashBangDuration;
this.stunDuration = stunDuration;
this.smokeTicks = smokeTicks;
this.effectRadius = effectRadius;
this.smokeCount = smokeCount;
this.isFragmentation = isFragmentation;
}
@Override
public void tick() {
super.tick();
this.prevX = this.getX();
this.prevY = this.getY();
this.prevZ = this.getZ();
Vec3d vec3d = this.getVelocity();
this.applyGravity();
if (!this.getWorld().isClient) {
this.noClip = !this.getWorld().isSpaceEmpty(this, this.getBoundingBox().contract(1.0E-7));
if (this.noClip) {
this.pushOutOfBlocks(this.getX(), (this.getBoundingBox().minY + this.getBoundingBox().maxY) / 2.0, this.getZ());
}
}
if (!this.isOnGround() || this.getVelocity().horizontalLengthSquared() > 9.999999747378752E-6 || (this.age + this.getId()) % 4 == 0) {
this.move(MovementType.SELF, this.getVelocity());
float f = 0.98F;
if (this.isOnGround()) {
f = this.getWorld().getBlockState(this.getVelocityAffectingPos()).getBlock().getSlipperiness() * 0.98F;
}
this.setVelocity(this.getVelocity().multiply(f, 0.98, f));
if (this.isOnGround()) {
Vec3d vec3d2 = this.getVelocity();
if (vec3d2.y < 0.0) {
this.setVelocity(vec3d2.multiply(1.0, -0.5, 1.0));
}
}
}
this.velocityDirty |= this.updateWaterState();
if (!this.getWorld().isClient) {
double d = this.getVelocity().subtract(vec3d).lengthSquared();
if (d > 0.01) {
this.velocityDirty = true;
}
}
if (timer > 0) {
timer -= 1;
} else {
explode();
}
}
private void explode() {
hitDamage(getPos(), explosionPower, repulsionPower, getWorld(), this, isIncendiary, effectRadius, isFragmentation ? new FragmentationExplosionBehavior() : null);
List<Entity> nearbyEntities = getEntitiesAround(this, effectRadius);
if (stunDuration > 0) {
for (Entity entity : nearbyEntities) {
if (entity instanceof LivingEntity livingEntity) {
livingEntity.addStatusEffect(new StatusEffectInstance(StatusEffects.SLOWNESS, stunDuration, 255, true, false));
}
}
stunDuration = 0;
}
if (flashBangDuration > 0) {
for (Entity entity : nearbyEntities) {
if (entity instanceof LivingEntity livingEntity) {
livingEntity.addStatusEffect(new StatusEffectInstance(StatusEffects.BLINDNESS, stunDuration, 255, true, false));
}
}
flashBangDuration = 0;
}
if (explosionPower > 0) {
explosionPower = 0;
}
if (repulsionPower > 0) {
repulsionPower = 0;
}
if (isIncendiary) {
isIncendiary = false;
}
if (smokeTicks <= 0) {
discard();
} else {
smokeTicks--;
World worldTemp = getWorld();
if (worldTemp instanceof ServerWorld world) {
Random random = world.getRandom();
for (int ix = 0; ix < smokeCount; ix++) {
double deltaRadius = effectRadius / 2d;
double speed = random.nextBetween(1, 20) / 100d;
world.spawnParticles(ParticleTypes.LARGE_SMOKE, getX(), getY(), getZ(), smokeCount, deltaRadius, deltaRadius, deltaRadius, speed);
}
}
}
}
public GrenadeEntity(EntityType<GrenadeEntity> entityType, World world) {
super(entityType, world, Vec3d.ZERO, ItemStack.EMPTY, 1f, 0d, PickupPermission.DISALLOWED, (byte) 255);
this.explosionPower = 0;
this.repulsionPower = 0;
this.isIncendiary = false;
this.flashBangDuration = 0;
this.stunDuration = 0;
this.smokeTicks = 0;
this.effectRadius = 0;
this.smokeCount = 0;
this.isFragmentation = false;
}
}

@ -0,0 +1,135 @@
package systems.brn.plasticgun.grenades;
import eu.pb4.polymer.core.api.item.PolymerItem;
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.LoreComponent;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.*;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text;
import net.minecraft.util.Hand;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
import systems.brn.plasticgun.grenades.GrenadeEntity;
import systems.brn.plasticgun.lib.SimpleItem;
import java.util.List;
import static systems.brn.plasticgun.lib.GunComponents.*;
import static systems.brn.plasticgun.lib.Util.*;
public class GrenadeItem extends SimpleItem implements PolymerItem {
public final int speed;
public final double explosionPower;
public final double repulsionPower;
public final int explosionTarget;
public final boolean isIncendiary;
public final boolean isFragmentation;
public final int flashBangDuration;
public final int stunDuration;
public final int smokeTicks;
public final int smokeRadius;
public final int smokeCount;
public GrenadeItem(String path, int speed, double explosionPower, double repulsionPower, int explosionTarget, boolean isIncendiary, boolean isFragmentation, int flashBangDuration, int stunDuration, int smokeTicks, int effectRadius, int smokeCount) {
super(
new Settings()
.maxCount(16)
.component(GRENADE_TIMER_COMPONENT, -1)
.component(DataComponentTypes.LORE, new LoreComponent(List.of(
Text.translatable("gun.description.explosion_power", explosionPower),
Text.translatable("gun.description.repulsion_power", repulsionPower),
Text.translatable("gun.description.explosion_time", explosionTarget),
Text.translatable("gun.description.speed", speed),
Text.translatable(isIncendiary ? "gun.description.incendiary_yes" : "gun.description.incendiary_no"),
Text.translatable("gun.description.fragmentation_grenade", isFragmentation),
Text.translatable("gun.description.flashbang_duration", flashBangDuration),
Text.translatable("gun.description.stun_duration", stunDuration),
Text.translatable("gun.description.smoke_ticks", smokeTicks),
Text.translatable("gun.description.effect_radius", effectRadius),
Text.translatable("gun.description.particle_count", smokeCount)
)))
.maxDamage(explosionTarget + 1)
, id(path), Items.FLOWER_POT
);
this.explosionTarget = explosionTarget;
this.isIncendiary = isIncendiary;
Item item = Registry.register(Registries.ITEM, id(path), this);
this.speed = speed;
this.explosionPower = explosionPower;
this.repulsionPower = repulsionPower;
this.flashBangDuration = flashBangDuration;
this.stunDuration = stunDuration;
this.smokeTicks = smokeTicks;
this.smokeRadius = effectRadius;
this.smokeCount = smokeCount;
this.isFragmentation = isFragmentation;
}
public void unpin(World world, PlayerEntity user, Hand hand) {
if (user instanceof ServerPlayerEntity player && !world.isClient()) {
ItemStack stack = user.getStackInHand(hand);
int timer = stack.getOrDefault(GRENADE_TIMER_COMPONENT, -1);
if (timer == -1) {
stack.set(GRENADE_TIMER_COMPONENT, explosionTarget);
world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.BLOCK_LEVER_CLICK, SoundCategory.PLAYERS, 1f, 2.5f);
updateDamage(stack, this);
}
}
}
public static void updateDamage(ItemStack stack, GrenadeItem grenadeItem) {
int timer = stack.getOrDefault(GRENADE_TIMER_COMPONENT, -1);
if (timer < 0) {
timer = grenadeItem.explosionTarget + 1;
}
stack.setDamage((1 + grenadeItem.explosionTarget) - timer);
}
public void chuck(ServerWorld world, PlayerEntity user, Hand hand) {
if (user instanceof ServerPlayerEntity player && !world.isClient()) {
ItemStack stack = user.getStackInHand(hand);
int timer = stack.getOrDefault(GRENADE_TIMER_COMPONENT, -1);
if (timer > 0) {
turnIntoEntity(player, stack, speed, timer);
if (!player.isCreative()) {
stack.decrement(1);
}
if (!stack.isEmpty()) {
stack.setDamage(0);
}
}
}
}
private void turnIntoEntity(ServerPlayerEntity player, @Nullable ItemStack stack, int speed, int timer) {
GrenadeEntity grenadeEntity = new GrenadeEntity(player, stack, timer, 1f, speed, explosionPower, repulsionPower, isIncendiary, isFragmentation, flashBangDuration, stunDuration, smokeTicks, 8, smokeCount);
player.getServerWorld().spawnEntity(grenadeEntity);
player.getServerWorld().playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.UI_BUTTON_CLICK.value(), SoundCategory.PLAYERS, 1.0f, 2.0f);
}
public void checkExplosions(ServerWorld world, PlayerEntity playerEntity, ItemStack stackInSlot) {
if (playerEntity instanceof ServerPlayerEntity player && !world.isClient()) {
int timer = stackInSlot.getOrDefault(GRENADE_TIMER_COMPONENT, -1);
if (timer == 0) {
turnIntoEntity(player, getDefaultStack(), 0, 0);
if (!player.isCreative()) {
stackInSlot.decrement(1);
} else {
stackInSlot.set(GRENADE_TIMER_COMPONENT, -1);
stackInSlot.setDamage(0);
}
}
}
}
}

@ -2,14 +2,18 @@ package systems.brn.plasticgun.guns;
import eu.pb4.polymer.core.api.item.PolymerItem;
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.LoreComponent;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.*;
import net.minecraft.network.packet.s2c.play.PositionFlag;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text;
import net.minecraft.util.Hand;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
@ -18,7 +22,7 @@ import systems.brn.plasticgun.bullets.BulletItem;
import systems.brn.plasticgun.lib.SimpleItem;
import java.util.ArrayList;
import java.util.Set;
import java.util.List;
import static systems.brn.plasticgun.PlasticGun.bullets;
import static systems.brn.plasticgun.lib.GunComponents.*;
@ -36,6 +40,7 @@ public class Gun extends SimpleItem implements PolymerItem {
private final double repulsionPowerGun;
private final int cooldownTarget;
private final int reloadTarget;
private final boolean hasScope;
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(
@ -47,8 +52,7 @@ public class Gun extends SimpleItem implements PolymerItem {
.maxDamage(clipSize + 1)
, 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));
Registry.register(Registries.ITEM, id(path), this);
this.damage = damage;
this.reloadCount = reloadCount;
this.clipSize = clipSize;
@ -65,6 +69,7 @@ public class Gun extends SimpleItem implements PolymerItem {
this.repulsionPowerGun = repulsionPowerGun;
this.cooldownTarget = cooldownTarget;
this.reloadTarget = reloadTarget + 1;
this.hasScope = hasScope;
}
public void reload(World world, PlayerEntity user, Hand hand) {
@ -128,12 +133,54 @@ public class Gun extends SimpleItem implements PolymerItem {
public void updateDamage(ItemStack stack) {
ItemStack chamber = stack.getOrDefault(GUN_AMMO_COMPONENT, ItemStack.EMPTY).copy();
BulletItem bulletItem = null;
for (BulletItem bulletTemp : bullets) {
if (bulletTemp == chamber.getItem()) {
bulletItem = bulletTemp;
break;
}
}
int numBullets = chamber.getCount();
int currentReload = stack.getOrDefault(GUN_LOADING_COMPONENT, 1);
if (currentReload != 1) {
numBullets = -clipSize;
}
stack.setDamage((clipSize - numBullets) + 1);
List<Text> loreList = new ArrayList<>();
loreList.add(Text.translatable("gun.description.caliber", caliber));
loreList.add(Text.translatable("gun.description.damage_absolute", damage));
loreList.add(Text.translatable("gun.description.speed", speed));
loreList.add(Text.translatable("gun.description.clip_size", clipSize));
if (hasScope) {
loreList.add(Text.translatable("gun.description.has_scope"));
}
loreList.add(Text.translatable("gun.description.reload_cooldown", reloadTarget));
loreList.add(Text.translatable("gun.description.reload_cycles", reloadCount));
loreList.add(Text.translatable("gun.description.shoot_cooldown", cooldownTarget));
if (explosionPowerGun > 0) {
loreList.add(Text.translatable("gun.description.explosion_power", explosionPowerGun));
}
if (repulsionPowerGun > 0) {
loreList.add(Text.translatable("gun.description.repulsion_power", repulsionPowerGun));
}
loreList.add(Text.translatable("gun.description.magazine_count", numBullets, clipSize));
if (!chamber.isEmpty() && bulletItem != null) {
loreList.add(Text.translatable("gun.description.damage_with_coefficient", damage * bulletItem.damageCoefficient));
loreList.add(Text.translatable("gun.description.magazine_bullet", bulletItem.getName()));
loreList.add(Text.translatable("gun.description.damage_coefficient", bulletItem.damageCoefficient));
loreList.add(Text.translatable("gun.description.explosion_coefficient", bulletItem.explosionPowerCoefficient));
if (bulletItem.isIncendiary) {
loreList.add(Text.translatable("gun.description.incendiary"));
}
} else {
loreList.add(Text.translatable("gun.description.magazine_bullet", "Empty"));
}
LoreComponent newLore = new LoreComponent(loreList);
stack.set(DataComponentTypes.LORE, newLore);
}
public void doRecoil(ServerPlayerEntity player) {
@ -141,13 +188,13 @@ public class Gun extends SimpleItem implements PolymerItem {
Vec3d pos = player.getPos();
float yaw = player.getYaw();
float newPitch = player.getPitch();
newPitch -= player.getWorld().getRandom().nextBetween(1, 4);
yaw -= player.getWorld().getRandom().nextBetween(-2, 2);
newPitch -= player.getServerWorld().getRandom().nextBetween(1, 4);
yaw -= player.getServerWorld().getRandom().nextBetween(-2, 2);
player.teleport(player.getServerWorld(), pos.x, pos.y, pos.z, Set.of(PositionFlag.X_ROT, PositionFlag.Y_ROT), yaw, newPitch);
player.teleport(player.getServerWorld(), pos.x, pos.y, pos.z, PositionFlag.ROT, yaw, newPitch);
}
public void shoot(World world, PlayerEntity user, Hand hand) {
public void shoot(ServerWorld world, PlayerEntity user, Hand hand) {
if (user instanceof ServerPlayerEntity player && !world.isClient()) {
ItemStack stack = user.getStackInHand(hand);
int currentReload = stack.getOrDefault(GUN_LOADING_COMPONENT, 1);
@ -173,7 +220,7 @@ public class Gun extends SimpleItem implements PolymerItem {
repulsionPower *= bullet.repulsionPowerCoefficient;
}
BulletEntity bulletEntity = new BulletEntity(user.getPos(), player, chamber, user.getStackInHand(hand), this, 1f, damage, speed, explosionPower, repulsionPower, isIncendiary);
BulletEntity bulletEntity = new BulletEntity(player, chamber, 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);

@ -1,16 +1,22 @@
package systems.brn.plasticgun.lib;
import net.minecraft.entity.Entity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
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.grenades.GrenadeEntity;
import systems.brn.plasticgun.grenades.GrenadeItem;
import systems.brn.plasticgun.guns.Gun;
import systems.brn.plasticgun.shurikens.ShurikenItem;
import static systems.brn.plasticgun.PlasticGun.*;
import static systems.brn.plasticgun.lib.GunComponents.*;
@ -26,12 +32,26 @@ public class EventHandler {
break;
}
}
for (GrenadeItem grenade : grenades) {
if (grenade != null && grenade == stackInHand) {
grenade.unpin(world, playerEntity, hand);
break;
}
}
for (ShurikenItem shuriken : shurikens) {
if (shuriken != null && shuriken == stackInHand) {
shuriken.chuck(world, playerEntity, hand);
break;
}
}
}
return TypedActionResult.pass(stack);
}
public static void onWorldTick(World world) {
public static void onServerWorldTick(ServerWorld world) {
// Iterate through all players to detect hand swings or item interactions
for (PlayerEntity player : world.getPlayers()) {
if (!world.isClient) {
@ -49,6 +69,65 @@ public class EventHandler {
break;
}
}
for (GrenadeItem grenade : grenades) {
if (grenade != null && grenade == itemInHand) {
if (player.handSwinging && player.handSwingTicks == -1) {
grenade.chuck(world, player, hand);
}
break;
}
}
for (ShurikenItem shuriken : shurikens) {
if (shuriken != null && shuriken == itemInHand) {
if (player.handSwinging && player.handSwingTicks == -1) {
shuriken.chuck(world, player, hand);
}
break;
}
}
PlayerInventory playerInventory = player.getInventory();
for (int i = 1; i < playerInventory.main.size(); i++) {
ItemStack stackInSlot = playerInventory.main.get(i);
Item itemInSlot = stackInSlot.getItem();
for (GrenadeItem grenadeItem : grenades) {
if (grenadeItem == itemInSlot) {
decrementComponent(GRENADE_TIMER_COMPONENT, stackInSlot);
GrenadeItem.updateDamage(stackInSlot, grenadeItem);
grenadeItem.checkExplosions(world, player, stackInSlot);
}
}
}
}
}
}
public static void onEntityLoad(Entity entity, ServerWorld world) {
if (entity instanceof ItemEntity itemEntity) {
ItemStack entityStack = itemEntity.getStack();
for (GrenadeItem grenadeItem : grenades) {
if (entityStack.getItem() == grenadeItem) {
Entity owner = itemEntity.getOwner();
int timer = (1 + grenadeItem.explosionTarget) - entityStack.getDamage();
if (timer <= grenadeItem.explosionTarget) {
if (owner instanceof ServerPlayerEntity player) {
GrenadeEntity grenadeEntity = new GrenadeEntity(player, entityStack, timer, 1f, 0, grenadeItem.explosionPower, grenadeItem.repulsionPower, grenadeItem.isIncendiary, grenadeItem.isFragmentation, grenadeItem.flashBangDuration, grenadeItem.stunDuration, grenadeItem.smokeTicks, grenadeItem.smokeRadius, grenadeItem.smokeCount);
grenadeEntity.setVelocity(entity.getVelocity());
world.spawnEntity(grenadeEntity);
world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.UI_BUTTON_CLICK.value(), SoundCategory.PLAYERS, 1.0f, 2.0f);
} else {
GrenadeEntity grenadeEntity = new GrenadeEntity(world, entity.getPos(), entityStack, timer, 1f, grenadeItem.explosionPower, grenadeItem.repulsionPower, grenadeItem.isIncendiary, grenadeItem.isFragmentation, grenadeItem.flashBangDuration, grenadeItem.stunDuration, grenadeItem.smokeTicks, grenadeItem.smokeRadius, grenadeItem.smokeCount);
grenadeEntity.setVelocity(entity.getVelocity());
world.spawnEntity(grenadeEntity);
}
entity.discard();
}
break;
}
}
}
}

@ -15,6 +15,7 @@ public class GunComponents {
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));
public static final ComponentType<Integer> GRENADE_TIMER_COMPONENT = register("grenade_tuner", builder -> builder.codec(Codec.INT));
private static <T> ComponentType<T> register(String id, UnaryOperator<ComponentType.Builder<T>> builderOperator) {
ComponentType<T> componentType = Registry.register(

@ -0,0 +1,66 @@
package systems.brn.plasticgun.lib;
import eu.pb4.polymer.core.api.item.PolymerItemGroupUtils;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import systems.brn.plasticgun.PlasticGun;
import systems.brn.plasticgun.bullets.BulletItem;
import systems.brn.plasticgun.grenades.GrenadeItem;
import systems.brn.plasticgun.guns.Gun;
import systems.brn.plasticgun.shurikens.ShurikenItem;
import java.util.ArrayList;
import java.util.Collection;
import static systems.brn.plasticgun.lib.Util.id;
public class ItemGroups {
public static final ItemGroup GUNS_GROUP = PolymerItemGroupUtils.builder()
.icon(() -> new ItemStack(PlasticGun.guns.getFirst()))
.displayName(Text.translatable("guns.groups.guns"))
.entries(((context, entries) -> {
for (Gun gun : PlasticGun.guns) {
entries.add(gun);
}
}))
.build();
public static final ItemGroup AMMO_GROUP = PolymerItemGroupUtils.builder()
.icon(() -> new ItemStack(PlasticGun.bullets.getFirst()))
.displayName(Text.translatable("guns.groups.ammo"))
.entries(((context, entries) -> {
for (BulletItem bulletItem : PlasticGun.bullets) {
entries.add(bulletItem);
}
}))
.build();
public static final ItemGroup SHURIKEN_GROUP = PolymerItemGroupUtils.builder()
.icon(() -> new ItemStack(PlasticGun.shurikens.getFirst()))
.displayName(Text.translatable("guns.groups.shurikens"))
.entries(((context, entries) -> {
for (ShurikenItem shurikenItem : PlasticGun.shurikens) {
entries.add(shurikenItem);
}
}))
.build();
public static final ItemGroup GRENADES_GROUP = PolymerItemGroupUtils.builder()
.icon(() -> new ItemStack(PlasticGun.grenades.getFirst()))
.displayName(Text.translatable("guns.groups.grenades"))
.entries(((context, entries) -> {
for (GrenadeItem grenadeItem : PlasticGun.grenades) {
entries.add(grenadeItem);
}
}))
.build();
public static void register() {
PolymerItemGroupUtils.registerPolymerItemGroup(id("guns"), GUNS_GROUP);
PolymerItemGroupUtils.registerPolymerItemGroup(id("ammo"), AMMO_GROUP);
PolymerItemGroupUtils.registerPolymerItemGroup(id("shurikens"), SHURIKEN_GROUP);
PolymerItemGroupUtils.registerPolymerItemGroup(id("grenades"), GRENADES_GROUP);
}
}

@ -1,19 +1,27 @@
package systems.brn.plasticgun.lib;
import eu.pb4.polymer.virtualentity.api.tracker.DisplayTrackedData;
import net.minecraft.client.render.model.json.ModelTransformationMode;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.TntEntity;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.data.DataTracker;
import net.minecraft.entity.decoration.DisplayEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraft.world.explosion.Explosion;
import net.minecraft.world.explosion.ExplosionBehavior;
import org.jetbrains.annotations.Nullable;
import org.joml.Vector3f;
import java.util.ArrayList;
import java.util.List;
@ -148,5 +156,25 @@ public class Util {
}
}
public static void setProjectileData(List<DataTracker.SerializedEntry<?>> data, boolean initial, float scale, ItemStack itemStack) {
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, itemStack));
data.add(DataTracker.SerializedEntry.of(DisplayTrackedData.Item.ITEM_DISPLAY, ModelTransformationMode.FIXED.getIndex()));
}
}
public static void hitDamage(Vec3d pos, double explosionPower, double repulsionPower, World worldTemp, @Nullable Entity entity, boolean isIncendiary, int radius, @Nullable ExplosionBehavior explosionBehavior) {
if (worldTemp instanceof ServerWorld world) {
if (explosionPower > 0) {
world.createExplosion(entity, Explosion.createDamageSource(world, entity), explosionBehavior, pos.getX(), pos.getY(), pos.getZ(), (float) explosionPower, isIncendiary, ServerWorld.ExplosionSourceType.TNT);
}
if (repulsionPower > 0) {
applyKnockbackToEntities(entity, pos, repulsionPower * 100, radius);
}
}
}
}

@ -0,0 +1,48 @@
package systems.brn.plasticgun.shurikens;
import eu.pb4.polymer.core.api.entity.PolymerEntity;
import net.minecraft.block.BlockState;
import net.minecraft.entity.EntityType;
import net.minecraft.item.ItemStack;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import systems.brn.plasticgun.throwables.ThrowableProjectile;
import static systems.brn.plasticgun.PlasticGun.SHURIKEN_ENTITY_TYPE;
public class ShurikenEntity extends ThrowableProjectile implements PolymerEntity {
public ShurikenEntity(ServerPlayerEntity player, ItemStack itemStack, float speed, double damage) {
super(SHURIKEN_ENTITY_TYPE, player, itemStack, 1f, speed, damage, PickupPermission.ALLOWED, (byte) 0);
}
public ShurikenEntity(EntityType<ShurikenEntity> bulletEntityEntityType, World world) {
super(bulletEntityEntityType, world, Vec3d.ZERO, ItemStack.EMPTY, 1f, 0d, PickupPermission.DISALLOWED, (byte) 255);
}
@Override
protected void onBlockHit(BlockHitResult blockHitResult) {
this.setPosition(blockHitResult.getPos());
if (blockHitResult.getType() == HitResult.Type.BLOCK) {
BlockState block = this.getWorld().getBlockState(blockHitResult.getBlockPos());
SoundEvent soundEvent = block.getSoundGroup().getHitSound();
setSilent(false);
playSound(soundEvent, 4.0F, 1.0F);
setSilent(true);
ItemStack itemStack = getItemStack();
int maxDamage = itemStack.getMaxDamage();
int currentDamage = itemStack.getDamage();
currentDamage += 1;
if (currentDamage >= maxDamage) {
discard();
} else {
itemStack.setDamage(currentDamage);
}
}
super.onBlockHit(blockHitResult);
}
}

@ -0,0 +1,59 @@
package systems.brn.plasticgun.shurikens;
import eu.pb4.polymer.core.api.item.PolymerItem;
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.LoreComponent;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroups;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text;
import net.minecraft.util.Hand;
import net.minecraft.world.World;
import systems.brn.plasticgun.lib.SimpleItem;
import java.util.List;
import static systems.brn.plasticgun.lib.Util.id;
public class ShurikenItem extends SimpleItem implements PolymerItem {
public final double damage;
public final float speed;
public ShurikenItem(String path, double damage, int durability, float speed) {
super(
new Settings()
.maxCount(16)
.maxDamage(durability)
.component(DataComponentTypes.LORE, new LoreComponent(List.of(
Text.translatable("gun.description.damage", damage),
Text.translatable("gun.description.speed", speed)
)))
, id(path), Items.WOODEN_PICKAXE
);
Registry.register(Registries.ITEM, id(path), this);
this.damage = damage;
this.speed = speed;
}
public void chuck(World world, PlayerEntity user, Hand hand) {
if (user instanceof ServerPlayerEntity player && !world.isClient()) {
ItemStack stack = user.getStackInHand(hand);
ShurikenEntity ShurikenEntity = new ShurikenEntity(player, stack, speed, damage);
world.spawnEntity(ShurikenEntity);
world.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.ITEM_CROSSBOW_SHOOT, SoundCategory.PLAYERS, 1.0f, 2.0f);
if (!player.isCreative()) {
stack.decrement(1);
}
}
}
}

@ -13,21 +13,13 @@ import net.minecraft.item.Items;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.util.Arm;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import eu.pb4.polymer.core.api.entity.PolymerEntity;
import net.minecraft.world.World;
import java.util.Collections;
import static systems.brn.plasticgun.PlasticGun.*;
public class DamageTester extends LivingEntity implements PolymerEntity {
public DamageTester(Vec3d pos, World world) {
super(DAMAGE_TESTER_ENTITY_TYPE, world);
this.setPos(pos.x, pos.y, pos.z);
}
public DamageTester(EntityType<systems.brn.plasticgun.testing.DamageTester> entityType, World world) {
super(entityType, world);
}

@ -0,0 +1,79 @@
package systems.brn.plasticgun.throwables;
import eu.pb4.polymer.core.api.entity.PolymerEntity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.data.DataTracker;
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.util.math.Vec3d;
import net.minecraft.world.World;
import java.lang.reflect.Method;
import java.util.List;
import static systems.brn.plasticgun.lib.Util.setProjectileData;
public class ThrowableProjectile extends PersistentProjectileEntity implements PolymerEntity {
private ItemStack itemStack = Items.ARROW.getDefaultStack();
private final float scale;
public ThrowableProjectile(EntityType<? extends ThrowableProjectile> entityType, World world, Vec3d pos, ItemStack itemStack, float scale, double damage, PickupPermission pickupPermission, byte penetration) {
super(entityType, pos.getX(), pos.getY() + 1.5d, pos.getZ(), world, itemStack, itemStack);
this.pickupType = pickupPermission;
this.setDamage(damage);
this.setSilent(true);
this.scale = scale;
this.setCustomPierceLevel(penetration);
this.setItemStack(itemStack);
}
public ThrowableProjectile(EntityType<? extends PersistentProjectileEntity> entityType, ServerPlayerEntity player, ItemStack itemStack, float scale, float speed, double damage, PickupPermission pickupPermission, byte penetration) {
super(entityType, player.getPos().x, player.getPos().y + 1.5d, player.getPos().z, player.getServerWorld(), itemStack, itemStack);
this.setOwner(player);
this.setVelocity(player, player.getPitch(), player.getYaw(), 0.0F, speed, 0);
this.pickupType = pickupPermission;
this.setDamage(damage);
this.setSilent(true);
this.scale = scale;
this.setCustomPierceLevel(penetration);
this.setItemStack(itemStack);
}
@Override
public void modifyRawTrackedData(List<DataTracker.SerializedEntry<?>> data, ServerPlayerEntity player, boolean initial) {
setProjectileData(data, initial, scale, this.itemStack);
}
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);
method.setAccessible(true); // Allow access to private methods
method.invoke(this, level);
} catch (Exception ignored) {
}
}
@Override
protected ItemStack getDefaultItemStack() {
return this.itemStack();
}
@Override
public EntityType<?> getPolymerEntityType(ServerPlayerEntity player) {
return EntityType.ITEM_DISPLAY;
}
}

@ -17,6 +17,70 @@
"item.plasticgun.colt_peacemaker": "Colt Peacemaker",
"item.plasticgun.p2022": "P2022",
"item.plasticgun.snub_nosed_revolver": "Snub Nosed Revolver",
"item.plasticgun.tokarev_tt_33": "Tokarev TT-33"
"item.plasticgun.tokarev_tt_33": "Tokarev TT-33",
"item.plasticgun.ak_47": "AK-47",
"item.plasticgun.awp": "AWP",
"item.plasticgun.rpg9": "RPG-9",
"item.plasticgun.forcegun": "Force Gun",
"item.plasticgun.rpg_shell_incendiary": "RPG Shell Incendiary",
"item.plasticgun.rpg_shell": "RPG Shell",
"item.plasticgun.force_container": "Force Container",
"item.plasticgun.grenade": "Grenade",
"item.plasticgun.grenade_incendiary": "Incendiary Grenade",
"item.plasticgun.shuriken": "Shuriken",
"item.plasticgun.grenade_m67": "M67 Fragmentation Grenade",
"item.plasticgun.grenade_mk2": "Mk 2 Fragmentation Grenade",
"item.plasticgun.grenade_an_m14": "AN-M14 Incendiary Grenade",
"item.plasticgun.grenade_m3d": "M34 White Phosphorus Incendiary Fragmentation Grenade",
"item.plasticgun.grenade_m18": "M18 Smoke Grenade",
"item.plasticgun.grenade_l109a1": "L109A1 Fragmentation Grenade",
"item.plasticgun.grenade_m84": "M84 Stun Grenade (Flashbang)",
"item.plasticgun.grenade_rgd_5": "RGD-5 Fragmentation Grenade",
"item.plasticgun.grenade_thermite": "Thermite Grenade",
"item.plasticgun.grenade_f1": "F1 Soviet Fragmentation Grenade",
"item.plasticgun.grenade_mk3a2": "Mk3A2 Offensive Grenade",
"item.plasticgun.grenade_m7a3": "M7A3 CS Gas Grenade",
"item.plasticgun.grenade_no_69": "No. 69 British Offensive Grenade",
"item.plasticgun.grenade_rgo": "RGO Fragmentation Grenade",
"item.plasticgun.grenade_k417": "K417 Fragmentation Grenade",
"item.plasticgun.wooden_shuriken": "Wooden Shuriken",
"item.plasticgun.stone_shuriken": "Stone Shuriken",
"item.plasticgun.iron_shuriken": "Iron Shuriken",
"item.plasticgun.golden_shuriken": "Golden Shuriken",
"item.plasticgun.diamond_shuriken": "Diamond Shuriken",
"item.plasticgun.netherite_shuriken": "Netherite Shuriken",
"gun.description.damage_coefficient": "Damage coefficient: %d",
"gun.description.explosion_coefficient": "Explosion coefficient: %d",
"gun.description.repulsion_efficient": "Repulsion coefficient: %d",
"gun.description.incendiary_yes": "Is incendiary",
"gun.description.incendiary_no": "Is not incendiary",
"gun.description.incendiary": "Is incendiary",
"gun.description.caliber": "Caliber: %d",
"gun.description.damage_absolute": "Gun damage (speed 1): %d hp",
"gun.description.damage_with_coefficient": "Gun damage with coefficient (speed 1): %d hp",
"gun.description.damage": "Damage: %d hp",
"gun.description.speed": "Speed: %d b/t",
"gun.description.clip_size": "Magazine size: %d rounds",
"gun.description.has_scope": "Has scope",
"gun.description.reload_cooldown": "Reload cooldown: %d ticks",
"gun.description.reload_cycles": "Reload cycles: %d clicks",
"gun.description.shoot_cooldown": "Shooting cooldown: %d",
"gun.description.explosion_power": "Explosion power: %d",
"gun.description.repulsion_power": "Repulsion power: %d",
"gun.description.magazine_count": "Magazine: %d/%d",
"gun.description.magazine_bullet": "Magazine bullet: %s",
"gun.description.explosion_time": "Fuse: %d ticks",
"gun.description.flashbang_duration": "Flashbang: %d seconds",
"gun.description.stun_duration": "Stun: %d seconds",
"gun.description.smoke_ticks": "Smoke: %d ticks",
"gun.description.effect_radius": "Radius: %d blocks",
"gun.description.particle_count": "Particles per tick: %d particles",
"gun.description.fragmentation_grenade": "Fragmentation: %d",
"guns.groups.guns": "Guns",
"guns.groups.ammo": "Ammo",
"guns.groups.grenades": "Grenades",
"guns.groups.shurikens": "Shurikens"
}

@ -3,4 +3,4 @@
"textures": {
"layer0": "plasticgun:item/357_revolver"
}
}
}

@ -3,4 +3,4 @@
"textures": {
"layer0": "plasticgun:item/762_tokarev"
}
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/ak_47"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/awp"
}
}

@ -3,4 +3,4 @@
"textures": {
"layer0": "plasticgun:item/colt_1903"
}
}
}

@ -3,4 +3,4 @@
"textures": {
"layer0": "plasticgun:item/colt_45"
}
}
}

@ -3,4 +3,4 @@
"textures": {
"layer0": "plasticgun:item/colt_peacemaker"
}
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/diamond_shuriken"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/force_container"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/forcegun"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/golden_shuriken"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/grenade"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/grenade_an_m14"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/grenade_f1"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/grenade_incendiary"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/grenade_k417"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/grenade_l109a1"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/grenade_m18"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/grenade_m3d"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/grenade_m67"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/grenade_m7a3"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/grenade_m84"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/grenade_mk2"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/grenade_mk3a2"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/grenade_no_69"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/grenade_rgd_5"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/grenade_rgo"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/grenade_thermite"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/iron_shuriken"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/netherite_shuriken"
}
}

@ -3,4 +3,4 @@
"textures": {
"layer0": "plasticgun:item/p2022"
}
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/rpg9"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/rpg_shell"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/rpg_shell_incendiary"
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/shuriken"
}
}

@ -3,4 +3,4 @@
"textures": {
"layer0": "plasticgun:item/snub_nosed_revolver"
}
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/stone_shuriken"
}
}

@ -3,4 +3,4 @@
"textures": {
"layer0": "plasticgun:item/tokarev_tt_33"
}
}
}

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "plasticgun:item/wooden_shuriken"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 608 B

After

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 673 B

After

Width:  |  Height:  |  Size: 669 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 642 B

After

Width:  |  Height:  |  Size: 642 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 590 B

After

Width:  |  Height:  |  Size: 594 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 373 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 674 B

After

Width:  |  Height:  |  Size: 677 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 657 B

After

Width:  |  Height:  |  Size: 663 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 631 B

After

Width:  |  Height:  |  Size: 628 B