Files
PlasticGun/src/main/java/systems/brn/plasticgun/bullets/BulletEntity.java
bruno 4df69c27a1 Change bullet visuals
Add reloading and firing cooldowns
2024-07-25 21:08:08 +02:00

151 lines
5.7 KiB
Java

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.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 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;
import static systems.brn.plasticgun.lib.Util.applyKnockbackToEntities;
public class BulletEntity extends PersistentProjectileEntity implements PolymerEntity {
private final Gun gun;
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, 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);
this.pickupType = PickupPermission.CREATIVE_ONLY;
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);
method.setAccessible(true); // Allow access to private methods
method.invoke(this, level);
} catch (Exception ignored) {
}
}
public BulletEntity(EntityType<BulletEntity> entityType, World world) {
super(entityType, world);
this.gun = null;
this.explosionPower = 0;
this.repulsionPower = 0;
this.isIncendiary = false;
this.scale = 1f;
}
@Override
protected ItemStack getDefaultItemStack() {
if (gun != null) {
return gun.ammo.getFirst().getDefaultStack();
} else {
return bullets.getFirst().getDefaultStack();
}
}
@Override
public EntityType<?> getPolymerEntityType(ServerPlayerEntity player) {
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());
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);
}
this.setOnFire(true);
super.onBlockHit(blockHitResult);
this.setOnFire(false);
hitDamage(blockHitResult.getPos());
this.discard();
}
@Override
protected void onEntityHit(EntityHitResult entityHitResult) {
this.setPosition(entityHitResult.getPos());
setSilent(false);
playSound(SoundEvents.BLOCK_BAMBOO_HIT, 4.0F, 1.0F);
setSilent(true);
super.onEntityHit(entityHitResult);
hitDamage(entityHitResult.getPos());
this.discard();
}
}