feat: add end crystals
This commit is contained in:
parent
94bdae9684
commit
8feb6c9b93
@ -164,7 +164,7 @@ impl BlockBehaviour for BedBlock {
|
||||
.await;
|
||||
|
||||
args.world
|
||||
.explode(args.server, bed_head_pos.to_centered_f64(), 5.0)
|
||||
.explode(bed_head_pos.to_centered_f64(), 5.0)
|
||||
.await;
|
||||
|
||||
return BlockActionResult::SuccessServer;
|
||||
|
||||
67
pumpkin/src/entity/decoration/end_crystal.rs
Normal file
67
pumpkin/src/entity/decoration/end_crystal.rs
Normal file
@ -0,0 +1,67 @@
|
||||
use core::f32;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::entity::{Entity, EntityBase, NBTStorage, living::LivingEntity};
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::damage::DamageType;
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
use pumpkin_protocol::java::client::play::{MetaDataType, Metadata};
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
|
||||
pub struct EndCrystalEntity {
|
||||
entity: Entity,
|
||||
}
|
||||
|
||||
impl EndCrystalEntity {
|
||||
pub fn new(entity: Entity) -> Self {
|
||||
Self { entity }
|
||||
}
|
||||
}
|
||||
|
||||
impl EndCrystalEntity {
|
||||
pub async fn set_show_bottom(&self, show_bottom: bool) {
|
||||
self.entity
|
||||
.send_meta_data(&[Metadata::new(9, MetaDataType::Boolean, show_bottom)])
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl NBTStorage for EndCrystalEntity {
|
||||
async fn write_nbt(&self, _nbt: &mut NbtCompound) {}
|
||||
|
||||
async fn read_nbt_non_mut(&self, _nbt: &NbtCompound) {}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl EntityBase for EndCrystalEntity {
|
||||
fn get_entity(&self) -> &Entity {
|
||||
&self.entity
|
||||
}
|
||||
|
||||
fn get_living_entity(&self) -> Option<&LivingEntity> {
|
||||
None
|
||||
}
|
||||
|
||||
async fn damage_with_context(
|
||||
&self,
|
||||
_caller: Arc<dyn EntityBase>,
|
||||
_amount: f32,
|
||||
damage_type: DamageType,
|
||||
_position: Option<Vector3<f64>>,
|
||||
_source: Option<&dyn EntityBase>,
|
||||
_cause: Option<&dyn EntityBase>,
|
||||
) -> bool {
|
||||
if damage_type != DamageType::EXPLOSION {
|
||||
self.entity.world.explode(self.entity.pos.load(), 6.0).await;
|
||||
}
|
||||
|
||||
// TODO
|
||||
self.entity.remove().await;
|
||||
true
|
||||
}
|
||||
|
||||
fn as_nbt_storage(&self) -> &dyn NBTStorage {
|
||||
self
|
||||
}
|
||||
}
|
||||
@ -1 +1,2 @@
|
||||
pub mod end_crystal;
|
||||
pub mod painting;
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::Block;
|
||||
use pumpkin_data::{entity::EntityType};
|
||||
use pumpkin_data::entity::EntityType;
|
||||
use pumpkin_protocol::java::client::play::{MetaDataType, Metadata};
|
||||
use pumpkin_util::math::{position::BlockPos};
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::{BlockStateId, world::BlockFlags};
|
||||
use std::sync::{Arc, atomic::Ordering};
|
||||
use uuid::Uuid;
|
||||
|
||||
@ -18,12 +18,12 @@ use crate::world::loot::{LootContextParameters, LootTableExt};
|
||||
use async_trait::async_trait;
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use pumpkin_config::advanced_config;
|
||||
use pumpkin_data::Block;
|
||||
use pumpkin_data::damage::DeathMessageType;
|
||||
use pumpkin_data::data_component_impl::{DeathProtectionImpl, EquipmentSlot, FoodImpl};
|
||||
use pumpkin_data::effect::StatusEffect;
|
||||
use pumpkin_data::entity::{EntityPose, EntityStatus, EntityType};
|
||||
use pumpkin_data::sound::SoundCategory;
|
||||
use pumpkin_data::Block;
|
||||
use pumpkin_data::{damage::DamageType, sound::Sound};
|
||||
use pumpkin_inventory::entity_equipment::EntityEquipment;
|
||||
use pumpkin_nbt::compound::NbtCompound;
|
||||
@ -871,6 +871,7 @@ impl LivingEntity {
|
||||
if let Some(player) = caller.get_player() {
|
||||
return player.inventory.held_item();
|
||||
}
|
||||
// TODO: this is wrong
|
||||
let slot = self
|
||||
.equipment_slots
|
||||
.get(&PlayerInventory::OFF_HAND_SLOT)
|
||||
|
||||
@ -2,7 +2,7 @@ use super::{Entity, EntityBase, NBTStorage, living::LivingEntity};
|
||||
use crate::server::Server;
|
||||
use async_trait::async_trait;
|
||||
use core::f32;
|
||||
use pumpkin_data::{Block};
|
||||
use pumpkin_data::Block;
|
||||
use pumpkin_protocol::{
|
||||
codec::var_int::VarInt,
|
||||
java::client::play::{MetaDataType, Metadata},
|
||||
@ -65,7 +65,7 @@ impl EntityBase for TNTEntity {
|
||||
self.entity.remove().await;
|
||||
self.entity
|
||||
.world
|
||||
.explode(server, self.entity.pos.load(), self.power)
|
||||
.explode(self.entity.pos.load(), self.power)
|
||||
.await;
|
||||
} else {
|
||||
entity.update_fluid_state(&caller).await;
|
||||
|
||||
@ -5,7 +5,11 @@ use pumpkin_util::math::vector3::Vector3;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
entity::{Entity, EntityBase, decoration::painting::PaintingEntity, mob::zombie::Zombie},
|
||||
entity::{
|
||||
Entity, EntityBase,
|
||||
decoration::{end_crystal::EndCrystalEntity, painting::PaintingEntity},
|
||||
mob::zombie::Zombie,
|
||||
},
|
||||
world::World,
|
||||
};
|
||||
|
||||
@ -21,6 +25,7 @@ pub async fn from_type(
|
||||
let mob: Arc<dyn EntityBase> = match entity_type.id {
|
||||
id if id == EntityType::ZOMBIE.id => Zombie::make(entity).await,
|
||||
id if id == EntityType::PAINTING.id => Arc::new(PaintingEntity::new(entity)),
|
||||
id if id == EntityType::END_CRYSTAL.id => Arc::new(EndCrystalEntity::new(entity)),
|
||||
// TODO
|
||||
_ => Arc::new(entity), // Fallback Entity
|
||||
};
|
||||
|
||||
@ -5,10 +5,10 @@ use async_trait::async_trait;
|
||||
use pumpkin_data::BlockDirection;
|
||||
use pumpkin_data::block_properties::BlockProperties;
|
||||
use pumpkin_data::block_properties::{OakDoorLikeProperties, PaleOakWoodLikeProperties};
|
||||
use pumpkin_data::item::Item;
|
||||
use pumpkin_data::tag::Taggable;
|
||||
use pumpkin_data::{Block, tag};
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::item::ItemStack;
|
||||
use pumpkin_world::world::BlockFlags;
|
||||
|
||||
pub struct AxeItem;
|
||||
@ -24,7 +24,7 @@ impl ItemBehaviour for AxeItem {
|
||||
#[allow(clippy::too_many_lines)]
|
||||
async fn use_on_block(
|
||||
&self,
|
||||
_item: &Item,
|
||||
_item: &mut ItemStack,
|
||||
player: &Player,
|
||||
location: BlockPos,
|
||||
_face: BlockDirection,
|
||||
|
||||
58
pumpkin/src/item/items/end_crystal.rs
Normal file
58
pumpkin/src/item/items/end_crystal.rs
Normal file
@ -0,0 +1,58 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::entity::Entity;
|
||||
use crate::entity::decoration::end_crystal::EndCrystalEntity;
|
||||
use crate::entity::player::Player;
|
||||
use crate::item::{ItemBehaviour, ItemMetadata};
|
||||
use crate::server::Server;
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::entity::EntityType;
|
||||
use pumpkin_data::item::Item;
|
||||
use pumpkin_data::{Block, BlockDirection};
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::item::ItemStack;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub struct EndCrystalItem;
|
||||
|
||||
impl ItemMetadata for EndCrystalItem {
|
||||
fn ids() -> Box<[u16]> {
|
||||
[Item::END_CRYSTAL.id].into()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl ItemBehaviour for EndCrystalItem {
|
||||
async fn use_on_block(
|
||||
&self,
|
||||
item: &mut ItemStack,
|
||||
player: &Player,
|
||||
location: BlockPos,
|
||||
_face: BlockDirection,
|
||||
_block: &Block,
|
||||
_server: &Server,
|
||||
) {
|
||||
let world = player.world();
|
||||
let block = world.get_block(&location).await;
|
||||
if block != &Block::OBSIDIAN && block != &Block::BEDROCK {
|
||||
return;
|
||||
}
|
||||
|
||||
let location = location.up();
|
||||
let entity = Entity::new(
|
||||
Uuid::new_v4(),
|
||||
world.clone(),
|
||||
location.to_f64(),
|
||||
&EntityType::END_CRYSTAL,
|
||||
false,
|
||||
);
|
||||
let end_crystal = Arc::new(EndCrystalEntity::new(entity));
|
||||
world.spawn_entity(end_crystal.clone()).await;
|
||||
end_crystal.set_show_bottom(false).await;
|
||||
item.decrement_unless_creative(player.gamemode.load(), 1);
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn std::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,7 @@ use std::sync::Arc;
|
||||
use crate::{server::Server, world::portal::end::EndPortal};
|
||||
use pumpkin_data::{Block, BlockDirection, item::Item};
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::item::ItemStack;
|
||||
use pumpkin_world::world::BlockFlags;
|
||||
|
||||
use crate::item::{ItemBehaviour, ItemMetadata};
|
||||
@ -21,7 +22,7 @@ impl ItemMetadata for EnderEyeItem {
|
||||
impl ItemBehaviour for EnderEyeItem {
|
||||
async fn use_on_block(
|
||||
&self,
|
||||
_item: &Item,
|
||||
_item: &mut ItemStack,
|
||||
player: &Player,
|
||||
location: BlockPos,
|
||||
_face: BlockDirection,
|
||||
|
||||
@ -26,7 +26,7 @@ impl ItemMetadata for HoeItem {
|
||||
impl ItemBehaviour for HoeItem {
|
||||
async fn use_on_block(
|
||||
&self,
|
||||
_item: &Item,
|
||||
_item: &mut ItemStack,
|
||||
player: &Player,
|
||||
location: BlockPos,
|
||||
face: BlockDirection,
|
||||
|
||||
@ -17,6 +17,7 @@ use pumpkin_data::{Block, tag};
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::block::entities::BlockEntity;
|
||||
use pumpkin_world::block::entities::sign::SignBlockEntity;
|
||||
use pumpkin_world::item::ItemStack;
|
||||
use pumpkin_world::world::BlockFlags;
|
||||
|
||||
pub struct HoneyCombItem;
|
||||
@ -31,7 +32,7 @@ impl ItemMetadata for HoneyCombItem {
|
||||
impl ItemBehaviour for HoneyCombItem {
|
||||
async fn use_on_block(
|
||||
&self,
|
||||
_item: &Item,
|
||||
_item: &mut ItemStack,
|
||||
player: &Player,
|
||||
location: BlockPos,
|
||||
_face: BlockDirection,
|
||||
|
||||
@ -7,6 +7,7 @@ use pumpkin_data::item::Item;
|
||||
use pumpkin_data::sound::Sound;
|
||||
use pumpkin_data::sound::SoundCategory;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::item::ItemStack;
|
||||
use pumpkin_world::world::BlockFlags;
|
||||
|
||||
use crate::entity::player::Player;
|
||||
@ -27,7 +28,7 @@ impl ItemMetadata for FireChargeItem {
|
||||
impl ItemBehaviour for FireChargeItem {
|
||||
async fn use_on_block(
|
||||
&self,
|
||||
_item: &Item,
|
||||
_item: &mut ItemStack,
|
||||
player: &Player,
|
||||
location: BlockPos,
|
||||
face: BlockDirection,
|
||||
@ -44,7 +45,6 @@ impl ItemBehaviour for FireChargeItem {
|
||||
.play_block_sound(Sound::ItemFirechargeUse, SoundCategory::Blocks, pos)
|
||||
.await;
|
||||
},
|
||||
_item,
|
||||
player,
|
||||
location,
|
||||
face,
|
||||
|
||||
@ -8,6 +8,7 @@ use pumpkin_data::Block;
|
||||
use pumpkin_data::BlockDirection;
|
||||
use pumpkin_data::item::Item;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::item::ItemStack;
|
||||
use pumpkin_world::world::BlockFlags;
|
||||
use std::sync::Arc;
|
||||
|
||||
@ -25,7 +26,7 @@ impl ItemMetadata for FlintAndSteelItem {
|
||||
impl ItemBehaviour for FlintAndSteelItem {
|
||||
async fn use_on_block(
|
||||
&self,
|
||||
item: &Item,
|
||||
_item: &mut ItemStack,
|
||||
player: &Player,
|
||||
location: BlockPos,
|
||||
face: BlockDirection,
|
||||
@ -38,7 +39,6 @@ impl ItemBehaviour for FlintAndSteelItem {
|
||||
.set_block_state(&pos, new_state_id, BlockFlags::NOTIFY_ALL)
|
||||
.await;
|
||||
},
|
||||
item,
|
||||
player,
|
||||
location,
|
||||
face,
|
||||
|
||||
@ -4,7 +4,6 @@ use crate::entity::player::Player;
|
||||
use crate::server::Server;
|
||||
use crate::world::World;
|
||||
use pumpkin_data::fluid::Fluid;
|
||||
use pumpkin_data::item::Item;
|
||||
use pumpkin_data::{Block, BlockDirection};
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use std::sync::Arc;
|
||||
@ -14,7 +13,6 @@ pub struct Ignition;
|
||||
impl Ignition {
|
||||
pub async fn ignite_block<F, Fut>(
|
||||
ignite_logic: F,
|
||||
_item: &Item,
|
||||
player: &Player,
|
||||
location: BlockPos,
|
||||
face: BlockDirection,
|
||||
|
||||
@ -15,6 +15,7 @@ use pumpkin_data::tag::Taggable;
|
||||
use pumpkin_data::{Block, tag};
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
use pumpkin_world::item::ItemStack;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub struct MinecartItem;
|
||||
@ -51,7 +52,7 @@ impl ItemMetadata for MinecartItem {
|
||||
impl ItemBehaviour for MinecartItem {
|
||||
async fn use_on_block(
|
||||
&self,
|
||||
item: &Item,
|
||||
item: &mut ItemStack,
|
||||
player: &Player,
|
||||
location: BlockPos,
|
||||
_face: BlockDirection,
|
||||
@ -74,7 +75,7 @@ impl ItemBehaviour for MinecartItem {
|
||||
.is_ascending()
|
||||
};
|
||||
let height = if is_ascending { 0.5 } else { 0.0 };
|
||||
let entity_type = Self::item_to_entity(item);
|
||||
let entity_type = Self::item_to_entity(item.item);
|
||||
let pos = location.to_f64();
|
||||
let entity = Arc::new(Entity::new(
|
||||
Uuid::new_v4(),
|
||||
|
||||
@ -2,6 +2,7 @@ pub mod axe;
|
||||
pub mod bucket;
|
||||
pub mod dye;
|
||||
pub mod egg;
|
||||
pub mod end_crystal;
|
||||
pub mod ender_eye;
|
||||
pub mod glowing_ink_sac;
|
||||
pub mod hoe;
|
||||
@ -15,6 +16,7 @@ pub mod snowball;
|
||||
pub mod swords;
|
||||
pub mod trident;
|
||||
|
||||
use crate::item::items::end_crystal::EndCrystalItem;
|
||||
use crate::item::items::minecart::MinecartItem;
|
||||
|
||||
use super::registry::ItemRegistry;
|
||||
@ -51,6 +53,7 @@ pub fn default_registry() -> Arc<ItemRegistry> {
|
||||
manager.register(FilledBucketItem);
|
||||
manager.register(ShovelItem);
|
||||
manager.register(AxeItem);
|
||||
manager.register(EndCrystalItem);
|
||||
manager.register(MinecartItem);
|
||||
manager.register(HoneyCombItem);
|
||||
manager.register(EnderEyeItem);
|
||||
|
||||
@ -4,11 +4,11 @@ use crate::server::Server;
|
||||
use async_trait::async_trait;
|
||||
use pumpkin_data::BlockDirection;
|
||||
use pumpkin_data::block_properties::{BlockProperties, CampfireLikeProperties};
|
||||
use pumpkin_data::item::Item;
|
||||
use pumpkin_data::sound::{Sound, SoundCategory};
|
||||
use pumpkin_data::world::WorldEvent;
|
||||
use pumpkin_data::{Block, tag};
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::item::ItemStack;
|
||||
use pumpkin_world::world::BlockFlags;
|
||||
use rand::{Rng, rng};
|
||||
|
||||
@ -24,7 +24,7 @@ impl ItemMetadata for ShovelItem {
|
||||
impl ItemBehaviour for ShovelItem {
|
||||
async fn use_on_block(
|
||||
&self,
|
||||
_item: &Item,
|
||||
_item: &mut ItemStack,
|
||||
player: &Player,
|
||||
location: BlockPos,
|
||||
face: BlockDirection,
|
||||
|
||||
@ -11,6 +11,7 @@ use pumpkin_data::BlockDirection;
|
||||
use pumpkin_data::item::Item;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_util::math::vector3::Vector3;
|
||||
use pumpkin_world::item::ItemStack;
|
||||
|
||||
pub trait ItemMetadata {
|
||||
fn ids() -> Box<[u16]>;
|
||||
@ -22,7 +23,7 @@ pub trait ItemBehaviour: Send + Sync {
|
||||
|
||||
async fn use_on_block(
|
||||
&self,
|
||||
_item: &Item,
|
||||
_item: &mut ItemStack,
|
||||
_player: &Player,
|
||||
_location: BlockPos,
|
||||
_face: BlockDirection,
|
||||
|
||||
@ -4,6 +4,7 @@ use pumpkin_data::Block;
|
||||
use pumpkin_data::BlockDirection;
|
||||
use pumpkin_data::item::Item;
|
||||
use pumpkin_util::math::position::BlockPos;
|
||||
use pumpkin_world::item::ItemStack;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
@ -32,17 +33,17 @@ impl ItemRegistry {
|
||||
|
||||
pub async fn use_on_block(
|
||||
&self,
|
||||
item: &Item,
|
||||
stack: &mut ItemStack,
|
||||
player: &Player,
|
||||
location: BlockPos,
|
||||
face: BlockDirection,
|
||||
block: &Block,
|
||||
server: &Server,
|
||||
) {
|
||||
let pumpkin_item = self.get_pumpkin_item(item);
|
||||
let pumpkin_item = self.get_pumpkin_item(stack.item);
|
||||
if let Some(pumpkin_item) = pumpkin_item {
|
||||
pumpkin_item
|
||||
.use_on_block(item, player, location, face, block, server)
|
||||
.use_on_block(stack, player, location, face, block, server)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1432,20 +1432,14 @@ impl JavaClient {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut stack = item.lock().await;
|
||||
server
|
||||
.item_registry
|
||||
.use_on_block(
|
||||
item.lock().await.item,
|
||||
player,
|
||||
position,
|
||||
face,
|
||||
block,
|
||||
server,
|
||||
)
|
||||
.use_on_block(&mut stack, player, position, face, block, server)
|
||||
.await;
|
||||
|
||||
// Check if the item is a block, because not every item can be placed :D
|
||||
let item_id = item.lock().await.item.id;
|
||||
let item_id = stack.item.id;
|
||||
if let Some(block) = Block::from_item_id(item_id) {
|
||||
should_try_decrement = self
|
||||
.run_is_block_place(player, block, server, use_item_on, position, face)
|
||||
@ -1453,7 +1447,7 @@ impl JavaClient {
|
||||
}
|
||||
|
||||
// Check if the item is a spawn egg
|
||||
let item_id = item.lock().await.item.id;
|
||||
let item_id = stack.item.id;
|
||||
if let Some(entity) = entity_from_egg(item_id) {
|
||||
self.spawn_entity_from_egg(player, entity, position, face)
|
||||
.await;
|
||||
@ -1464,7 +1458,7 @@ impl JavaClient {
|
||||
// TODO: Config
|
||||
// Decrease block count
|
||||
if player.gamemode.load() != GameMode::Creative {
|
||||
item.lock().await.decrement(1);
|
||||
stack.decrement(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,6 @@ use pumpkin_util::math::{position::BlockPos, vector3::Vector3};
|
||||
|
||||
use crate::{
|
||||
block::{ExplodeArgs, drop_loot},
|
||||
server::Server,
|
||||
world::loot::LootContextParameters,
|
||||
};
|
||||
|
||||
@ -74,14 +73,14 @@ impl Explosion {
|
||||
map
|
||||
}
|
||||
|
||||
pub async fn explode(&self, server: &Server, world: &Arc<World>) {
|
||||
pub async fn explode(&self, world: &Arc<World>) {
|
||||
let blocks = self.get_blocks_to_destroy(world).await;
|
||||
// TODO: Entity damage, fire
|
||||
for (pos, (block, state)) in blocks {
|
||||
if state.is_air() {
|
||||
continue;
|
||||
}
|
||||
let pumpkin_block = server.block_registry.get_pumpkin_block(block);
|
||||
let pumpkin_block = world.block_registry.get_pumpkin_block(block);
|
||||
|
||||
world.set_block_state(&pos, 0, BlockFlags::NOTIFY_ALL).await;
|
||||
|
||||
|
||||
@ -1726,9 +1726,9 @@ impl World {
|
||||
player.set_health(20.0).await;
|
||||
}
|
||||
|
||||
pub async fn explode(self: &Arc<Self>, server: &Server, position: Vector3<f64>, power: f32) {
|
||||
pub async fn explode(self: &Arc<Self>, position: Vector3<f64>, power: f32) {
|
||||
let explosion = Explosion::new(power, position);
|
||||
explosion.explode(server, self).await;
|
||||
explosion.explode(self).await;
|
||||
let particle = if power < 2.0 {
|
||||
Particle::Explosion
|
||||
} else {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user