diff --git a/pumpkin-codegen/src/block.rs b/pumpkin-codegen/src/block.rs index b3dcc3d8c..cd8b6e1cb 100644 --- a/pumpkin-codegen/src/block.rs +++ b/pumpkin-codegen/src/block.rs @@ -1456,7 +1456,8 @@ fn get_be_data_from_nbt( let data_end = reader.seek(SeekFrom::End(0)).unwrap(); let _ = reader.seek(SeekFrom::Start(data_start)); - let nbt_reader = &mut NbtReadHelperBedrock::new(pumpkin_nbt::deserializer::NbtStreamReader(&mut *reader)); + let nbt_reader = + &mut NbtReadHelperBedrock::new(pumpkin_nbt::deserializer::NbtStreamReader(&mut *reader)); loop { if nbt_reader.reader().0.stream_position().unwrap() >= data_end { diff --git a/pumpkin-codegen/src/item.rs b/pumpkin-codegen/src/item.rs index 62c98013a..db80431ca 100644 --- a/pumpkin-codegen/src/item.rs +++ b/pumpkin-codegen/src/item.rs @@ -835,7 +835,9 @@ impl ToTokens for ItemComponents { } if let Some(scale) = self.potion_duration_scale { let scale_lit = LitFloat::new(&format!("{scale:?}f32"), Span::call_site()); - tokens.extend(quote! { (PotionDurationScale, &PotionDurationScaleImpl { scale: #scale_lit }), }); + tokens.extend( + quote! { (PotionDurationScale, &PotionDurationScaleImpl { scale: #scale_lit }), }, + ); } if self.provides_banner_patterns.is_some() { tokens.extend(quote! { (ProvidesBannerPatterns, &ProvidesBannerPatternsImpl), }); diff --git a/pumpkin-codegen/src/main.rs b/pumpkin-codegen/src/main.rs index 24cce8ec5..87c342656 100644 --- a/pumpkin-codegen/src/main.rs +++ b/pumpkin-codegen/src/main.rs @@ -18,8 +18,8 @@ mod block; mod carver; pub mod chest_loot; mod chunk_gen_settings; -mod chunk_view_lut; mod chunk_status; +mod chunk_view_lut; mod composter_increase_chance; mod configured_feature; mod damage_type; diff --git a/pumpkin-codegen/src/noise_router.rs b/pumpkin-codegen/src/noise_router.rs index c9340a7e7..20fd0d44e 100644 --- a/pumpkin-codegen/src/noise_router.rs +++ b/pumpkin-codegen/src/noise_router.rs @@ -679,23 +679,39 @@ impl DensityFunctionRepr { fn optimize(&mut self) { match self { Self::BlendDensity { input } => input.optimize(), - Self::FindTopSurface { density, upper_bound, .. } => { + Self::FindTopSurface { + density, + upper_bound, + .. + } => { density.optimize(); upper_bound.optimize(); } - Self::ShiftedNoise { shift_x, shift_y, shift_z, .. } => { + Self::ShiftedNoise { + shift_x, + shift_y, + shift_z, + .. + } => { shift_x.optimize(); shift_y.optimize(); shift_z.optimize(); } - Self::IntervalSelect { input, functions, .. } => { + Self::IntervalSelect { + input, functions, .. + } => { input.optimize(); for f in functions.iter_mut() { f.optimize(); } } Self::Wrapper { input, .. } => input.optimize(), - Self::RangeChoice { input, when_in_range, when_out_range, .. } => { + Self::RangeChoice { + input, + when_in_range, + when_out_range, + .. + } => { input.optimize(); when_in_range.optimize(); when_out_range.optimize(); @@ -707,7 +723,9 @@ impl DensityFunctionRepr { LinearOperation::Add => value.0 + data.argument.0, LinearOperation::Mul => value.0 * data.argument.0, }; - *self = Self::Constant { value: HashableF64(val) }; + *self = Self::Constant { + value: HashableF64(val), + }; return; } match data.operation { @@ -720,22 +738,32 @@ impl DensityFunctionRepr { if data.argument.0 == 1.0 { *self = *input.clone(); } else if data.argument.0 == 0.0 { - *self = Self::Constant { value: HashableF64(0.0) }; + *self = Self::Constant { + value: HashableF64(0.0), + }; } } } } - Self::Binary { argument1, argument2, data } => { + Self::Binary { + argument1, + argument2, + data, + } => { argument1.optimize(); argument2.optimize(); - if let (Self::Constant { value: v1 }, Self::Constant { value: v2 }) = (&**argument1, &**argument2) { + if let (Self::Constant { value: v1 }, Self::Constant { value: v2 }) = + (&**argument1, &**argument2) + { let res = match data.operation { BinaryOperation::Add => v1.0 + v2.0, BinaryOperation::Mul => v1.0 * v2.0, BinaryOperation::Min => v1.0.min(v2.0), BinaryOperation::Max => v1.0.max(v2.0), }; - *self = Self::Constant { value: HashableF64(res) }; + *self = Self::Constant { + value: HashableF64(res), + }; return; } match data.operation { @@ -759,7 +787,9 @@ impl DensityFunctionRepr { *self = *argument2.clone(); return; } else if value.0 == 0.0 { - *self = Self::Constant { value: HashableF64(0.0) }; + *self = Self::Constant { + value: HashableF64(0.0), + }; return; } } @@ -768,7 +798,9 @@ impl DensityFunctionRepr { *self = *argument1.clone(); return; } else if value.0 == 0.0 { - *self = Self::Constant { value: HashableF64(0.0) }; + *self = Self::Constant { + value: HashableF64(0.0), + }; return; } } @@ -783,21 +815,43 @@ impl DensityFunctionRepr { UnaryOperation::Abs => value.0.abs(), UnaryOperation::Square => value.0 * value.0, UnaryOperation::Cube => value.0 * value.0 * value.0, - UnaryOperation::HalfNegative => if value.0 > 0.0 { value.0 } else { value.0 * 0.5 }, - UnaryOperation::QuarterNegative => if value.0 > 0.0 { value.0 } else { value.0 * 0.25 }, + UnaryOperation::HalfNegative => { + if value.0 > 0.0 { + value.0 + } else { + value.0 * 0.5 + } + } + UnaryOperation::QuarterNegative => { + if value.0 > 0.0 { + value.0 + } else { + value.0 * 0.25 + } + } UnaryOperation::Squeeze => { let c = value.0.clamp(-1.0, 1.0); c / 2.0 - c * c * c / 24.0 } - UnaryOperation::Invert => if value.0 == 0.0 { f64::INFINITY } else { 1.0 / value.0 }, + UnaryOperation::Invert => { + if value.0 == 0.0 { + f64::INFINITY + } else { + 1.0 / value.0 + } + } + }; + *self = Self::Constant { + value: HashableF64(val), }; - *self = Self::Constant { value: HashableF64(val) }; } } Self::Clamp { input, data } => { input.optimize(); if let Self::Constant { value } = &**input { - *self = Self::Constant { value: HashableF64(value.0.clamp(data.min_value.0, data.max_value.0)) }; + *self = Self::Constant { + value: HashableF64(value.0.clamp(data.min_value.0, data.max_value.0)), + }; } } _ => {} @@ -844,7 +898,8 @@ impl DensityFunctionRepr { } Self::Linear { input, data } => { let child_idx = input.get_index_for_component_readonly(hash_to_index_map); - let child_fn = syn::Ident::new(&format!("{}_{}", fn_prefix, child_idx), Span::call_site()); + let child_fn = + syn::Ident::new(&format!("{}_{}", fn_prefix, child_idx), Span::call_site()); let arg = data.argument.0; let body = match data.operation { LinearOperation::Add => quote! { #child_fn(pos, ctx) + #arg }, @@ -859,15 +914,24 @@ impl DensityFunctionRepr { } Self::Unary { input, data } => { let child_idx = input.get_index_for_component_readonly(hash_to_index_map); - let child_fn = syn::Ident::new(&format!("{}_{}", fn_prefix, child_idx), Span::call_site()); + let child_fn = + syn::Ident::new(&format!("{}_{}", fn_prefix, child_idx), Span::call_site()); let body = match data.operation { UnaryOperation::Abs => quote! { #child_fn(pos, ctx).abs() }, UnaryOperation::Square => quote! { let v = #child_fn(pos, ctx); v * v }, UnaryOperation::Cube => quote! { let v = #child_fn(pos, ctx); v * v * v }, - UnaryOperation::HalfNegative => quote! { let v = #child_fn(pos, ctx); if v > 0.0 { v } else { v * 0.5 } }, - UnaryOperation::QuarterNegative => quote! { let v = #child_fn(pos, ctx); if v > 0.0 { v } else { v * 0.25 } }, - UnaryOperation::Squeeze => quote! { let c = #child_fn(pos, ctx).clamp(-1.0, 1.0); c / 2.0 - c * c * c / 24.0 }, - UnaryOperation::Invert => quote! { let v = #child_fn(pos, ctx); if v == 0.0 { f64::INFINITY } else { 1.0 / v } }, + UnaryOperation::HalfNegative => { + quote! { let v = #child_fn(pos, ctx); if v > 0.0 { v } else { v * 0.5 } } + } + UnaryOperation::QuarterNegative => { + quote! { let v = #child_fn(pos, ctx); if v > 0.0 { v } else { v * 0.25 } } + } + UnaryOperation::Squeeze => { + quote! { let c = #child_fn(pos, ctx).clamp(-1.0, 1.0); c / 2.0 - c * c * c / 24.0 } + } + UnaryOperation::Invert => { + quote! { let v = #child_fn(pos, ctx); if v == 0.0 { f64::INFINITY } else { 1.0 / v } } + } }; quote! { #[inline(always)] @@ -878,7 +942,8 @@ impl DensityFunctionRepr { } Self::Clamp { input, data } => { let child_idx = input.get_index_for_component_readonly(hash_to_index_map); - let child_fn = syn::Ident::new(&format!("{}_{}", fn_prefix, child_idx), Span::call_site()); + let child_fn = + syn::Ident::new(&format!("{}_{}", fn_prefix, child_idx), Span::call_site()); let min_v = data.min_value.0; let max_v = data.max_value.0; quote! { @@ -888,16 +953,26 @@ impl DensityFunctionRepr { } } } - Self::Binary { argument1, argument2, data } => { + Self::Binary { + argument1, + argument2, + data, + } => { let child1_idx = argument1.get_index_for_component_readonly(hash_to_index_map); let child2_idx = argument2.get_index_for_component_readonly(hash_to_index_map); - let child1_fn = syn::Ident::new(&format!("{}_{}", fn_prefix, child1_idx), Span::call_site()); - let child2_fn = syn::Ident::new(&format!("{}_{}", fn_prefix, child2_idx), Span::call_site()); + let child1_fn = + syn::Ident::new(&format!("{}_{}", fn_prefix, child1_idx), Span::call_site()); + let child2_fn = + syn::Ident::new(&format!("{}_{}", fn_prefix, child2_idx), Span::call_site()); let body = match data.operation { BinaryOperation::Add => quote! { #child1_fn(pos, ctx) + #child2_fn(pos, ctx) }, BinaryOperation::Mul => quote! { #child1_fn(pos, ctx) * #child2_fn(pos, ctx) }, - BinaryOperation::Min => quote! { #child1_fn(pos, ctx).min(#child2_fn(pos, ctx)) }, - BinaryOperation::Max => quote! { #child1_fn(pos, ctx).max(#child2_fn(pos, ctx)) }, + BinaryOperation::Min => { + quote! { #child1_fn(pos, ctx).min(#child2_fn(pos, ctx)) } + } + BinaryOperation::Max => { + quote! { #child1_fn(pos, ctx).max(#child2_fn(pos, ctx)) } + } }; quote! { #[inline(always)] @@ -906,13 +981,24 @@ impl DensityFunctionRepr { } } } - Self::RangeChoice { input, when_in_range, when_out_range, data } => { + Self::RangeChoice { + input, + when_in_range, + when_out_range, + data, + } => { let input_idx = input.get_index_for_component_readonly(hash_to_index_map); let when_in_idx = when_in_range.get_index_for_component_readonly(hash_to_index_map); - let when_out_idx = when_out_range.get_index_for_component_readonly(hash_to_index_map); - let input_fn = syn::Ident::new(&format!("{}_{}", fn_prefix, input_idx), Span::call_site()); - let when_in_fn = syn::Ident::new(&format!("{}_{}", fn_prefix, when_in_idx), Span::call_site()); - let when_out_fn = syn::Ident::new(&format!("{}_{}", fn_prefix, when_out_idx), Span::call_site()); + let when_out_idx = + when_out_range.get_index_for_component_readonly(hash_to_index_map); + let input_fn = + syn::Ident::new(&format!("{}_{}", fn_prefix, input_idx), Span::call_site()); + let when_in_fn = + syn::Ident::new(&format!("{}_{}", fn_prefix, when_in_idx), Span::call_site()); + let when_out_fn = syn::Ident::new( + &format!("{}_{}", fn_prefix, when_out_idx), + Span::call_site(), + ); let min_inc = data.min_inclusive.0; let max_exc = data.max_exclusive.0; quote! { @@ -956,13 +1042,21 @@ impl DensityFunctionRepr { } } } - Self::ShiftedNoise { shift_x, shift_y, shift_z, data } => { + Self::ShiftedNoise { + shift_x, + shift_y, + shift_z, + data, + } => { let sx_idx = shift_x.get_index_for_component_readonly(hash_to_index_map); let sy_idx = shift_y.get_index_for_component_readonly(hash_to_index_map); let sz_idx = shift_z.get_index_for_component_readonly(hash_to_index_map); - let sx_fn = syn::Ident::new(&format!("{}_{}", fn_prefix, sx_idx), Span::call_site()); - let sy_fn = syn::Ident::new(&format!("{}_{}", fn_prefix, sy_idx), Span::call_site()); - let sz_fn = syn::Ident::new(&format!("{}_{}", fn_prefix, sz_idx), Span::call_site()); + let sx_fn = + syn::Ident::new(&format!("{}_{}", fn_prefix, sx_idx), Span::call_site()); + let sy_fn = + syn::Ident::new(&format!("{}_{}", fn_prefix, sy_idx), Span::call_site()); + let sz_fn = + syn::Ident::new(&format!("{}_{}", fn_prefix, sz_idx), Span::call_site()); let noise_id = quote::format_ident!("{}", data.noise_id.to_shouty_snake_case()); let xz_scale = data.xz_scale.0; let y_scale = data.y_scale.0; @@ -994,7 +1088,8 @@ impl DensityFunctionRepr { } Self::BlendDensity { input } => { let child_idx = input.get_index_for_component_readonly(hash_to_index_map); - let child_fn = syn::Ident::new(&format!("{}_{}", fn_prefix, child_idx), Span::call_site()); + let child_fn = + syn::Ident::new(&format!("{}_{}", fn_prefix, child_idx), Span::call_site()); quote! { #[inline(always)] pub fn #fn_name(pos: &pumpkin_util::math::vector3::Vector3, ctx: &mut C) -> f64 { @@ -1021,7 +1116,8 @@ impl DensityFunctionRepr { } Self::Wrapper { input, wrapper } => { let child_idx = input.get_index_for_component_readonly(hash_to_index_map); - let child_fn = syn::Ident::new(&format!("{}_{}", fn_prefix, child_idx), Span::call_site()); + let child_fn = + syn::Ident::new(&format!("{}_{}", fn_prefix, child_idx), Span::call_site()); let wrapper_repr = wrapper.into_token_stream(); let comp_idx = index; quote! { @@ -1031,9 +1127,14 @@ impl DensityFunctionRepr { } } } - Self::IntervalSelect { input, thresholds, functions } => { + Self::IntervalSelect { + input, + thresholds, + functions, + } => { let input_idx = input.get_index_for_component_readonly(hash_to_index_map); - let input_fn = syn::Ident::new(&format!("{}_{}", fn_prefix, input_idx), Span::call_site()); + let input_fn = + syn::Ident::new(&format!("{}_{}", fn_prefix, input_idx), Span::call_site()); let func_fns = functions .iter() .map(|f| { @@ -1044,7 +1145,11 @@ impl DensityFunctionRepr { let threshold_values = thresholds.iter().map(|t| t.0).collect::>(); let th_indices = (0..threshold_values.len()).collect::>(); let last_func_fn = func_fns.last().unwrap(); - let initial_func_fns = if func_fns.len() > 1 { &func_fns[..func_fns.len() - 1] } else { &[] }; + let initial_func_fns = if func_fns.len() > 1 { + &func_fns[..func_fns.len() - 1] + } else { + &[] + }; quote! { #[inline(always)] pub fn #fn_name(pos: &pumpkin_util::math::vector3::Vector3, ctx: &mut C) -> f64 { @@ -1075,10 +1180,15 @@ impl DensityFunctionRepr { Self::Spline { spline, .. } => { let loc_idx = match spline { SplineRepr::Fixed { .. } => None, - SplineRepr::Standard { location_function, .. } => Some(location_function.get_index_for_component_readonly(hash_to_index_map)), + SplineRepr::Standard { + location_function, .. + } => { + Some(location_function.get_index_for_component_readonly(hash_to_index_map)) + } }; if let Some(loc_idx) = loc_idx { - let loc_fn = syn::Ident::new(&format!("{}_{}", fn_prefix, loc_idx), Span::call_site()); + let loc_fn = + syn::Ident::new(&format!("{}_{}", fn_prefix, loc_idx), Span::call_site()); quote! { #[inline(always)] pub fn #fn_name(pos: &pumpkin_util::math::vector3::Vector3, ctx: &mut C) -> f64 { @@ -1087,7 +1197,10 @@ impl DensityFunctionRepr { } } } else { - let val = match spline { SplineRepr::Fixed { value } => value.0 as f64, _ => 0.0 }; + let val = match spline { + SplineRepr::Fixed { value } => value.0 as f64, + _ => 0.0, + }; quote! { #[inline(always)] pub fn #fn_name(pos: &pumpkin_util::math::vector3::Vector3, ctx: &mut C) -> f64 { @@ -1097,7 +1210,11 @@ impl DensityFunctionRepr { } } } - Self::FindTopSurface { density, upper_bound, data } => { + Self::FindTopSurface { + density, + upper_bound, + data, + } => { let d_idx = density.get_index_for_component_readonly(hash_to_index_map); let u_idx = upper_bound.get_index_for_component_readonly(hash_to_index_map); let d_fn = syn::Ident::new(&format!("{}_{}", fn_prefix, d_idx), Span::call_site()); @@ -1163,7 +1280,8 @@ impl DensityFunctionRepr { upper_bound, data, } => { - let density_index = density.get_index_for_component(stack, nodes, hash_to_index_map); + let density_index = + density.get_index_for_component(stack, nodes, hash_to_index_map); let upper_bound_index = upper_bound.get_index_for_component(stack, nodes, hash_to_index_map); let lower_bound = data.lower_bound; @@ -1246,9 +1364,12 @@ impl DensityFunctionRepr { shift_z, data, } => { - let shift_x_index = shift_x.get_index_for_component(stack, nodes, hash_to_index_map); - let shift_y_index = shift_y.get_index_for_component(stack, nodes, hash_to_index_map); - let shift_z_index = shift_z.get_index_for_component(stack, nodes, hash_to_index_map); + let shift_x_index = + shift_x.get_index_for_component(stack, nodes, hash_to_index_map); + let shift_y_index = + shift_y.get_index_for_component(stack, nodes, hash_to_index_map); + let shift_z_index = + shift_z.get_index_for_component(stack, nodes, hash_to_index_map); let xz_scale = &data.xz_scale; let y_scale = &data.y_scale; @@ -1274,7 +1395,8 @@ impl DensityFunctionRepr { data, } => { let input_index = input.get_index_for_component(stack, nodes, hash_to_index_map); - let when_in_index = when_in_range.get_index_for_component(stack, nodes, hash_to_index_map); + let when_in_index = + when_in_range.get_index_for_component(stack, nodes, hash_to_index_map); let when_out_index = when_out_range.get_index_for_component(stack, nodes, hash_to_index_map); @@ -1298,8 +1420,10 @@ impl DensityFunctionRepr { argument2, data, } => { - let argument1_index = argument1.get_index_for_component(stack, nodes, hash_to_index_map); - let argument2_index = argument2.get_index_for_component(stack, nodes, hash_to_index_map); + let argument1_index = + argument1.get_index_for_component(stack, nodes, hash_to_index_map); + let argument2_index = + argument2.get_index_for_component(stack, nodes, hash_to_index_map); let action = data.operation.get_token_stream(); quote! { @@ -1526,69 +1650,104 @@ impl NoiseRouterRepr { let mut noise_lookup_map = BTreeMap::new(); // The aquifer sampler is called most often - let final_density = self - .final_density - .get_index_for_component(&mut noise_component_stack, &mut noise_nodes, &mut noise_lookup_map); - let barrier_noise = self - .barrier_noise - .get_index_for_component(&mut noise_component_stack, &mut noise_nodes, &mut noise_lookup_map); - let fluid_level_floodedness_noise = self - .fluid_level_floodedness_noise - .get_index_for_component(&mut noise_component_stack, &mut noise_nodes, &mut noise_lookup_map); - let fluid_level_spread_noise = self - .fluid_level_spread_noise - .get_index_for_component(&mut noise_component_stack, &mut noise_nodes, &mut noise_lookup_map); - let lava_noise = self - .lava_noise - .get_index_for_component(&mut noise_component_stack, &mut noise_nodes, &mut noise_lookup_map); + let final_density = self.final_density.get_index_for_component( + &mut noise_component_stack, + &mut noise_nodes, + &mut noise_lookup_map, + ); + let barrier_noise = self.barrier_noise.get_index_for_component( + &mut noise_component_stack, + &mut noise_nodes, + &mut noise_lookup_map, + ); + let fluid_level_floodedness_noise = + self.fluid_level_floodedness_noise.get_index_for_component( + &mut noise_component_stack, + &mut noise_nodes, + &mut noise_lookup_map, + ); + let fluid_level_spread_noise = self.fluid_level_spread_noise.get_index_for_component( + &mut noise_component_stack, + &mut noise_nodes, + &mut noise_lookup_map, + ); + let lava_noise = self.lava_noise.get_index_for_component( + &mut noise_component_stack, + &mut noise_nodes, + &mut noise_lookup_map, + ); // Ore sampler is called fewer times than aquifer sampler - let vein_toggle = self - .vein_toggle - .get_index_for_component(&mut noise_component_stack, &mut noise_nodes, &mut noise_lookup_map); - let vein_ridged = self - .vein_ridged - .get_index_for_component(&mut noise_component_stack, &mut noise_nodes, &mut noise_lookup_map); - let vein_gap = self - .vein_gap - .get_index_for_component(&mut noise_component_stack, &mut noise_nodes, &mut noise_lookup_map); + let vein_toggle = self.vein_toggle.get_index_for_component( + &mut noise_component_stack, + &mut noise_nodes, + &mut noise_lookup_map, + ); + let vein_ridged = self.vein_ridged.get_index_for_component( + &mut noise_component_stack, + &mut noise_nodes, + &mut noise_lookup_map, + ); + let vein_gap = self.vein_gap.get_index_for_component( + &mut noise_component_stack, + &mut noise_nodes, + &mut noise_lookup_map, + ); // These should all be cached so it doesn't matter where their components are - let noise_erosion = self - .erosion - .get_index_for_component(&mut noise_component_stack, &mut noise_nodes, &mut noise_lookup_map); - let noise_depth = self - .depth - .get_index_for_component(&mut noise_component_stack, &mut noise_nodes, &mut noise_lookup_map); + let noise_erosion = self.erosion.get_index_for_component( + &mut noise_component_stack, + &mut noise_nodes, + &mut noise_lookup_map, + ); + let noise_depth = self.depth.get_index_for_component( + &mut noise_component_stack, + &mut noise_nodes, + &mut noise_lookup_map, + ); let mut surface_component_stack = Vec::new(); let mut surface_nodes = Vec::new(); let mut surface_lookup_map = BTreeMap::new(); - let _ = self - .preliminary_surface_level - .get_index_for_component(&mut surface_component_stack, &mut surface_nodes, &mut surface_lookup_map); + let _ = self.preliminary_surface_level.get_index_for_component( + &mut surface_component_stack, + &mut surface_nodes, + &mut surface_lookup_map, + ); let mut multinoise_component_stack = Vec::new(); let mut multinoise_nodes = Vec::new(); let mut multinoise_lookup_map = BTreeMap::new(); - let ridges = self - .ridges - .get_index_for_component(&mut multinoise_component_stack, &mut multinoise_nodes, &mut multinoise_lookup_map); - let temperature = self - .temperature - .get_index_for_component(&mut multinoise_component_stack, &mut multinoise_nodes, &mut multinoise_lookup_map); - let vegetation = self - .vegetation - .get_index_for_component(&mut multinoise_component_stack, &mut multinoise_nodes, &mut multinoise_lookup_map); - let continents = self - .continents - .get_index_for_component(&mut multinoise_component_stack, &mut multinoise_nodes, &mut multinoise_lookup_map); - let multi_erosion = self - .erosion - .get_index_for_component(&mut multinoise_component_stack, &mut multinoise_nodes, &mut multinoise_lookup_map); - let multi_depth = self - .depth - .get_index_for_component(&mut multinoise_component_stack, &mut multinoise_nodes, &mut multinoise_lookup_map); + let ridges = self.ridges.get_index_for_component( + &mut multinoise_component_stack, + &mut multinoise_nodes, + &mut multinoise_lookup_map, + ); + let temperature = self.temperature.get_index_for_component( + &mut multinoise_component_stack, + &mut multinoise_nodes, + &mut multinoise_lookup_map, + ); + let vegetation = self.vegetation.get_index_for_component( + &mut multinoise_component_stack, + &mut multinoise_nodes, + &mut multinoise_lookup_map, + ); + let continents = self.continents.get_index_for_component( + &mut multinoise_component_stack, + &mut multinoise_nodes, + &mut multinoise_lookup_map, + ); + let multi_erosion = self.erosion.get_index_for_component( + &mut multinoise_component_stack, + &mut multinoise_nodes, + &mut multinoise_lookup_map, + ); + let multi_depth = self.depth.get_index_for_component( + &mut multinoise_component_stack, + &mut multinoise_nodes, + &mut multinoise_lookup_map, + ); let base_routers_ts = quote! { BaseNoiseRouters { @@ -1623,13 +1782,15 @@ impl NoiseRouterRepr { let mod_ident = quote::format_ident!("{}_noise_evaluator", router_name); let prefix = format!("{}_node", router_name); - let fn_tokens = noise_nodes.iter().enumerate().map(|(idx, node)| { - node.emit_compiled_eval_fn(idx, &prefix, &noise_lookup_map) - }); + let fn_tokens = noise_nodes + .iter() + .enumerate() + .map(|(idx, node)| node.emit_compiled_eval_fn(idx, &prefix, &noise_lookup_map)); let final_density_fn = quote::format_ident!("{}_{}", prefix, final_density); let barrier_noise_fn = quote::format_ident!("{}_{}", prefix, barrier_noise); - let fluid_floodedness_fn = quote::format_ident!("{}_{}", prefix, fluid_level_floodedness_noise); + let fluid_floodedness_fn = + quote::format_ident!("{}_{}", prefix, fluid_level_floodedness_noise); let fluid_spread_fn = quote::format_ident!("{}_{}", prefix, fluid_level_spread_noise); let lava_noise_fn = quote::format_ident!("{}_{}", prefix, lava_noise); let vein_toggle_fn = quote::format_ident!("{}_{}", prefix, vein_toggle); @@ -1724,7 +1885,8 @@ pub fn build() -> TokenStream { let _ = reprs.end; let _ = reprs.end_islands; - let (overworld_router, overworld_compiled) = reprs.overworld.into_token_stream_compiled("overworld"); + let (overworld_router, overworld_compiled) = + reprs.overworld.into_token_stream_compiled("overworld"); let (nether_router, nether_compiled) = reprs.nether.into_token_stream_compiled("nether"); let (end_router, end_compiled) = reprs.end.into_token_stream_compiled("end"); diff --git a/pumpkin-codegen/src/placed_feature.rs b/pumpkin-codegen/src/placed_feature.rs index aa6d3d98c..6058e0fe4 100644 --- a/pumpkin-codegen/src/placed_feature.rs +++ b/pumpkin-codegen/src/placed_feature.rs @@ -34,10 +34,8 @@ pub fn build_enum() -> TokenStream { }) .collect(); - let all_names_tokens: Vec = all_names - .iter() - .map(|name| quote! { #name }) - .collect(); + let all_names_tokens: Vec = + all_names.iter().map(|name| quote! { #name }).collect(); quote! { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] diff --git a/pumpkin-plugin-api/src/events/block/block_damage.rs b/pumpkin-plugin-api/src/events/block/block_damage.rs new file mode 100644 index 000000000..3496bd773 --- /dev/null +++ b/pumpkin-plugin-api/src/events/block/block_damage.rs @@ -0,0 +1,19 @@ +use super::super::FromIntoEvent; +use crate::wit::pumpkin::plugin::event::{BlockDamageEventData, Event, EventType}; + +pub struct BlockDamageEvent; +impl FromIntoEvent for BlockDamageEvent { + const EVENT_TYPE: EventType = EventType::BlockDamageEvent; + type Data = BlockDamageEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::BlockDamageEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::BlockDamageEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/block/block_fade.rs b/pumpkin-plugin-api/src/events/block/block_fade.rs new file mode 100644 index 000000000..26cf14f94 --- /dev/null +++ b/pumpkin-plugin-api/src/events/block/block_fade.rs @@ -0,0 +1,19 @@ +use super::super::FromIntoEvent; +use crate::wit::pumpkin::plugin::event::{BlockFadeEventData, Event, EventType}; + +pub struct BlockFadeEvent; +impl FromIntoEvent for BlockFadeEvent { + const EVENT_TYPE: EventType = EventType::BlockFadeEvent; + type Data = BlockFadeEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::BlockFadeEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::BlockFadeEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/block/block_form.rs b/pumpkin-plugin-api/src/events/block/block_form.rs new file mode 100644 index 000000000..abc351b94 --- /dev/null +++ b/pumpkin-plugin-api/src/events/block/block_form.rs @@ -0,0 +1,19 @@ +use super::super::FromIntoEvent; +use crate::wit::pumpkin::plugin::event::{BlockFormEventData, Event, EventType}; + +pub struct BlockFormEvent; +impl FromIntoEvent for BlockFormEvent { + const EVENT_TYPE: EventType = EventType::BlockFormEvent; + type Data = BlockFormEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::BlockFormEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::BlockFormEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/block/block_from_to.rs b/pumpkin-plugin-api/src/events/block/block_from_to.rs new file mode 100644 index 000000000..5e4d4a852 --- /dev/null +++ b/pumpkin-plugin-api/src/events/block/block_from_to.rs @@ -0,0 +1,19 @@ +use super::super::FromIntoEvent; +use crate::wit::pumpkin::plugin::event::{BlockFromToEventData, Event, EventType}; + +pub struct BlockFromToEvent; +impl FromIntoEvent for BlockFromToEvent { + const EVENT_TYPE: EventType = EventType::BlockFromToEvent; + type Data = BlockFromToEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::BlockFromToEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::BlockFromToEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/block/block_ignite.rs b/pumpkin-plugin-api/src/events/block/block_ignite.rs new file mode 100644 index 000000000..28ff99cfa --- /dev/null +++ b/pumpkin-plugin-api/src/events/block/block_ignite.rs @@ -0,0 +1,19 @@ +use super::super::FromIntoEvent; +use crate::wit::pumpkin::plugin::event::{BlockIgniteEventData, Event, EventType}; + +pub struct BlockIgniteEvent; +impl FromIntoEvent for BlockIgniteEvent { + const EVENT_TYPE: EventType = EventType::BlockIgniteEvent; + type Data = BlockIgniteEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::BlockIgniteEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::BlockIgniteEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/block/mod.rs b/pumpkin-plugin-api/src/events/block/mod.rs index d752ac29f..aae2c2ee8 100644 --- a/pumpkin-plugin-api/src/events/block/mod.rs +++ b/pumpkin-plugin-api/src/events/block/mod.rs @@ -1,13 +1,23 @@ pub mod block_break; pub mod block_burn; pub mod block_can_build; +pub mod block_damage; +pub mod block_fade; +pub mod block_form; +pub mod block_from_to; pub mod block_grow; +pub mod block_ignite; pub mod block_place; pub mod block_redstone; pub use block_break::*; pub use block_burn::*; pub use block_can_build::*; +pub use block_damage::*; +pub use block_fade::*; +pub use block_form::*; +pub use block_from_to::*; pub use block_grow::*; +pub use block_ignite::*; pub use block_place::*; pub use block_redstone::*; diff --git a/pumpkin-plugin-api/src/events/entity/entity_combust.rs b/pumpkin-plugin-api/src/events/entity/entity_combust.rs new file mode 100644 index 000000000..f76de64df --- /dev/null +++ b/pumpkin-plugin-api/src/events/entity/entity_combust.rs @@ -0,0 +1,20 @@ +use crate::wit::pumpkin::plugin::event::{EntityCombustEventData, Event, EventType}; + +use super::super::FromIntoEvent; + +pub struct EntityCombustEvent; +impl FromIntoEvent for EntityCombustEvent { + const EVENT_TYPE: EventType = EventType::EntityCombustEvent; + type Data = EntityCombustEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::EntityCombustEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::EntityCombustEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/entity/entity_damage.rs b/pumpkin-plugin-api/src/events/entity/entity_damage.rs new file mode 100644 index 000000000..d3c3f4515 --- /dev/null +++ b/pumpkin-plugin-api/src/events/entity/entity_damage.rs @@ -0,0 +1,20 @@ +use crate::wit::pumpkin::plugin::event::{EntityDamageEventData, Event, EventType}; + +use super::super::FromIntoEvent; + +pub struct EntityDamageEvent; +impl FromIntoEvent for EntityDamageEvent { + const EVENT_TYPE: EventType = EventType::EntityDamageEvent; + type Data = EntityDamageEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::EntityDamageEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::EntityDamageEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/entity/entity_death.rs b/pumpkin-plugin-api/src/events/entity/entity_death.rs new file mode 100644 index 000000000..67bae6e16 --- /dev/null +++ b/pumpkin-plugin-api/src/events/entity/entity_death.rs @@ -0,0 +1,39 @@ +use crate::wit::pumpkin::plugin::event::{ + EntityDeathEventData, Event, EventType, PlayerDeathEventData, +}; + +use super::super::FromIntoEvent; + +pub struct EntityDeathEvent; +impl FromIntoEvent for EntityDeathEvent { + const EVENT_TYPE: EventType = EventType::EntityDeathEvent; + type Data = EntityDeathEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::EntityDeathEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::EntityDeathEvent(data) + } +} + +pub struct PlayerDeathEvent; +impl FromIntoEvent for PlayerDeathEvent { + const EVENT_TYPE: EventType = EventType::PlayerDeathEvent; + type Data = PlayerDeathEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::PlayerDeathEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::PlayerDeathEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/entity/entity_regain_health.rs b/pumpkin-plugin-api/src/events/entity/entity_regain_health.rs new file mode 100644 index 000000000..bc52b1f21 --- /dev/null +++ b/pumpkin-plugin-api/src/events/entity/entity_regain_health.rs @@ -0,0 +1,20 @@ +use crate::wit::pumpkin::plugin::event::{EntityRegainHealthEventData, Event, EventType}; + +use super::super::FromIntoEvent; + +pub struct EntityRegainHealthEvent; +impl FromIntoEvent for EntityRegainHealthEvent { + const EVENT_TYPE: EventType = EventType::EntityRegainHealthEvent; + type Data = EntityRegainHealthEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::EntityRegainHealthEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::EntityRegainHealthEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/entity/entity_spawn.rs b/pumpkin-plugin-api/src/events/entity/entity_spawn.rs new file mode 100644 index 000000000..4ac802a61 --- /dev/null +++ b/pumpkin-plugin-api/src/events/entity/entity_spawn.rs @@ -0,0 +1,20 @@ +use crate::wit::pumpkin::plugin::event::{EntitySpawnEventData, Event, EventType}; + +use super::super::FromIntoEvent; + +pub struct EntitySpawnEvent; +impl FromIntoEvent for EntitySpawnEvent { + const EVENT_TYPE: EventType = EventType::EntitySpawnEvent; + type Data = EntitySpawnEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::EntitySpawnEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::EntitySpawnEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/entity/mod.rs b/pumpkin-plugin-api/src/events/entity/mod.rs new file mode 100644 index 000000000..6c9dd8189 --- /dev/null +++ b/pumpkin-plugin-api/src/events/entity/mod.rs @@ -0,0 +1,11 @@ +pub mod entity_combust; +pub mod entity_damage; +pub mod entity_death; +pub mod entity_regain_health; +pub mod entity_spawn; + +pub use entity_combust::*; +pub use entity_damage::*; +pub use entity_death::*; +pub use entity_regain_health::*; +pub use entity_spawn::*; diff --git a/pumpkin-plugin-api/src/events/inventory/craft_item.rs b/pumpkin-plugin-api/src/events/inventory/craft_item.rs new file mode 100644 index 000000000..0067272b7 --- /dev/null +++ b/pumpkin-plugin-api/src/events/inventory/craft_item.rs @@ -0,0 +1,19 @@ +use super::super::FromIntoEvent; +use crate::wit::pumpkin::plugin::event::{CraftItemEventData, Event, EventType}; + +pub struct CraftItemEvent; +impl FromIntoEvent for CraftItemEvent { + const EVENT_TYPE: EventType = EventType::CraftItemEvent; + type Data = CraftItemEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::CraftItemEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::CraftItemEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/inventory/furnace_smelt.rs b/pumpkin-plugin-api/src/events/inventory/furnace_smelt.rs new file mode 100644 index 000000000..71181bceb --- /dev/null +++ b/pumpkin-plugin-api/src/events/inventory/furnace_smelt.rs @@ -0,0 +1,19 @@ +use super::super::FromIntoEvent; +use crate::wit::pumpkin::plugin::event::{Event, EventType, FurnaceSmeltEventData}; + +pub struct FurnaceSmeltEvent; +impl FromIntoEvent for FurnaceSmeltEvent { + const EVENT_TYPE: EventType = EventType::FurnaceSmeltEvent; + type Data = FurnaceSmeltEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::FurnaceSmeltEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::FurnaceSmeltEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/inventory/inventory_drag.rs b/pumpkin-plugin-api/src/events/inventory/inventory_drag.rs new file mode 100644 index 000000000..24cf00cbe --- /dev/null +++ b/pumpkin-plugin-api/src/events/inventory/inventory_drag.rs @@ -0,0 +1,19 @@ +use super::super::FromIntoEvent; +use crate::wit::pumpkin::plugin::event::{Event, EventType, InventoryDragEventData}; + +pub struct InventoryDragEvent; +impl FromIntoEvent for InventoryDragEvent { + const EVENT_TYPE: EventType = EventType::InventoryDragEvent; + type Data = InventoryDragEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::InventoryDragEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::InventoryDragEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/inventory/inventory_open.rs b/pumpkin-plugin-api/src/events/inventory/inventory_open.rs new file mode 100644 index 000000000..4e4c6870c --- /dev/null +++ b/pumpkin-plugin-api/src/events/inventory/inventory_open.rs @@ -0,0 +1,19 @@ +use super::super::FromIntoEvent; +use crate::wit::pumpkin::plugin::event::{Event, EventType, InventoryOpenEventData}; + +pub struct InventoryOpenEvent; +impl FromIntoEvent for InventoryOpenEvent { + const EVENT_TYPE: EventType = EventType::InventoryOpenEvent; + type Data = InventoryOpenEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::InventoryOpenEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::InventoryOpenEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/inventory/mod.rs b/pumpkin-plugin-api/src/events/inventory/mod.rs new file mode 100644 index 000000000..24100c452 --- /dev/null +++ b/pumpkin-plugin-api/src/events/inventory/mod.rs @@ -0,0 +1,9 @@ +pub mod craft_item; +pub mod furnace_smelt; +pub mod inventory_drag; +pub mod inventory_open; + +pub use craft_item::*; +pub use furnace_smelt::*; +pub use inventory_drag::*; +pub use inventory_open::*; diff --git a/pumpkin-plugin-api/src/events/mod.rs b/pumpkin-plugin-api/src/events/mod.rs index 23ea6d1ab..afd078854 100644 --- a/pumpkin-plugin-api/src/events/mod.rs +++ b/pumpkin-plugin-api/src/events/mod.rs @@ -15,14 +15,20 @@ pub use crate::wit::pumpkin::plugin::event::{ use crate::{Context, Result, Server, wit::pumpkin::plugin::event::EventType}; pub mod block; +pub mod entity; +pub mod inventory; pub mod packet; pub mod player; pub mod server; +pub mod world; pub use block::*; +pub use entity::*; +pub use inventory::*; pub use packet::*; pub use player::*; pub use server::*; +pub use world::*; pub(crate) static NEXT_HANDLER_ID: AtomicU32 = AtomicU32::new(0); pub(crate) static EVENT_HANDLERS: Mutex>> = diff --git a/pumpkin-plugin-api/src/events/player/inventory_click.rs b/pumpkin-plugin-api/src/events/player/inventory_click.rs new file mode 100644 index 000000000..0d65b0f16 --- /dev/null +++ b/pumpkin-plugin-api/src/events/player/inventory_click.rs @@ -0,0 +1,22 @@ +use crate::wit::pumpkin::plugin::event::{Event, EventType, InventoryClickEventData}; + +use super::super::FromIntoEvent; + +/// An event that occurs when a player clicks a slot in an inventory. +pub struct InventoryClickEvent; + +impl FromIntoEvent for InventoryClickEvent { + const EVENT_TYPE: EventType = EventType::InventoryClickEvent; + type Data = InventoryClickEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::InventoryClickEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::InventoryClickEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/player/inventory_close.rs b/pumpkin-plugin-api/src/events/player/inventory_close.rs new file mode 100644 index 000000000..35706e910 --- /dev/null +++ b/pumpkin-plugin-api/src/events/player/inventory_close.rs @@ -0,0 +1,22 @@ +use crate::wit::pumpkin::plugin::event::{Event, EventType, InventoryCloseEventData}; + +use super::super::FromIntoEvent; + +/// An event that occurs when a player closes an inventory. +pub struct InventoryCloseEvent; + +impl FromIntoEvent for InventoryCloseEvent { + const EVENT_TYPE: EventType = EventType::InventoryCloseEvent; + type Data = InventoryCloseEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::InventoryCloseEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::InventoryCloseEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/player/mod.rs b/pumpkin-plugin-api/src/events/player/mod.rs index d62ee5eed..8645860de 100644 --- a/pumpkin-plugin-api/src/events/player/mod.rs +++ b/pumpkin-plugin-api/src/events/player/mod.rs @@ -4,14 +4,22 @@ pub mod custom_click_action; pub mod egg_throw; pub mod exp_change; pub mod fish; +pub mod inventory_click; +pub mod inventory_close; pub mod item_held; +pub mod player_bed; +pub mod player_bucket; pub mod player_change_world; pub mod player_chat; pub mod player_command_send; pub mod player_custom_payload; +pub mod player_drop_item; pub mod player_gamemode_change; pub mod player_interact; +pub mod player_interact_entity; pub mod player_interact_unknown_entity; +pub mod player_item_consume; +pub mod player_item_damage; pub mod player_join; pub mod player_leave; pub mod player_login; @@ -23,18 +31,28 @@ pub mod player_toggle_flight; pub mod player_toggle_sneak; pub mod player_toggle_sprint; +pub use bedrock_form_response::*; pub use changed_main_hand::*; +pub use custom_click_action::*; pub use egg_throw::*; pub use exp_change::*; pub use fish::*; +pub use inventory_click::*; +pub use inventory_close::*; pub use item_held::*; +pub use player_bed::*; +pub use player_bucket::*; pub use player_change_world::*; pub use player_chat::*; pub use player_command_send::*; pub use player_custom_payload::*; +pub use player_drop_item::*; pub use player_gamemode_change::*; pub use player_interact::*; +pub use player_interact_entity::*; pub use player_interact_unknown_entity::*; +pub use player_item_consume::*; +pub use player_item_damage::*; pub use player_join::*; pub use player_leave::*; pub use player_login::*; diff --git a/pumpkin-plugin-api/src/events/player/player_bed.rs b/pumpkin-plugin-api/src/events/player/player_bed.rs new file mode 100644 index 000000000..40887299f --- /dev/null +++ b/pumpkin-plugin-api/src/events/player/player_bed.rs @@ -0,0 +1,38 @@ +use super::super::FromIntoEvent; +use crate::wit::pumpkin::plugin::event::{ + Event, EventType, PlayerBedEnterEventData, PlayerBedLeaveEventData, +}; + +pub struct PlayerBedEnterEvent; +impl FromIntoEvent for PlayerBedEnterEvent { + const EVENT_TYPE: EventType = EventType::PlayerBedEnterEvent; + type Data = PlayerBedEnterEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::PlayerBedEnterEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::PlayerBedEnterEvent(data) + } +} + +pub struct PlayerBedLeaveEvent; +impl FromIntoEvent for PlayerBedLeaveEvent { + const EVENT_TYPE: EventType = EventType::PlayerBedLeaveEvent; + type Data = PlayerBedLeaveEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::PlayerBedLeaveEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::PlayerBedLeaveEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/player/player_bucket.rs b/pumpkin-plugin-api/src/events/player/player_bucket.rs new file mode 100644 index 000000000..0a247b4de --- /dev/null +++ b/pumpkin-plugin-api/src/events/player/player_bucket.rs @@ -0,0 +1,38 @@ +use super::super::FromIntoEvent; +use crate::wit::pumpkin::plugin::event::{ + Event, EventType, PlayerBucketEmptyEventData, PlayerBucketFillEventData, +}; + +pub struct PlayerBucketEmptyEvent; +impl FromIntoEvent for PlayerBucketEmptyEvent { + const EVENT_TYPE: EventType = EventType::PlayerBucketEmptyEvent; + type Data = PlayerBucketEmptyEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::PlayerBucketEmptyEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::PlayerBucketEmptyEvent(data) + } +} + +pub struct PlayerBucketFillEvent; +impl FromIntoEvent for PlayerBucketFillEvent { + const EVENT_TYPE: EventType = EventType::PlayerBucketFillEvent; + type Data = PlayerBucketFillEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::PlayerBucketFillEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::PlayerBucketFillEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/player/player_drop_item.rs b/pumpkin-plugin-api/src/events/player/player_drop_item.rs new file mode 100644 index 000000000..cc9d32a01 --- /dev/null +++ b/pumpkin-plugin-api/src/events/player/player_drop_item.rs @@ -0,0 +1,19 @@ +use super::super::FromIntoEvent; +use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerDropItemEventData}; + +pub struct PlayerDropItemEvent; +impl FromIntoEvent for PlayerDropItemEvent { + const EVENT_TYPE: EventType = EventType::PlayerDropItemEvent; + type Data = PlayerDropItemEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::PlayerDropItemEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::PlayerDropItemEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/player/player_interact_entity.rs b/pumpkin-plugin-api/src/events/player/player_interact_entity.rs new file mode 100644 index 000000000..4c7ce0396 --- /dev/null +++ b/pumpkin-plugin-api/src/events/player/player_interact_entity.rs @@ -0,0 +1,22 @@ +use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerInteractEntityEventData}; + +use super::super::FromIntoEvent; + +/// An event that occurs when a player interacts with an entity. +pub struct PlayerInteractEntityEvent; + +impl FromIntoEvent for PlayerInteractEntityEvent { + const EVENT_TYPE: EventType = EventType::PlayerInteractEntityEvent; + type Data = PlayerInteractEntityEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::PlayerInteractEntityEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::PlayerInteractEntityEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/player/player_item_consume.rs b/pumpkin-plugin-api/src/events/player/player_item_consume.rs new file mode 100644 index 000000000..64554997a --- /dev/null +++ b/pumpkin-plugin-api/src/events/player/player_item_consume.rs @@ -0,0 +1,19 @@ +use super::super::FromIntoEvent; +use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerItemConsumeEventData}; + +pub struct PlayerItemConsumeEvent; +impl FromIntoEvent for PlayerItemConsumeEvent { + const EVENT_TYPE: EventType = EventType::PlayerItemConsumeEvent; + type Data = PlayerItemConsumeEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::PlayerItemConsumeEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::PlayerItemConsumeEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/player/player_item_damage.rs b/pumpkin-plugin-api/src/events/player/player_item_damage.rs new file mode 100644 index 000000000..9ed7de431 --- /dev/null +++ b/pumpkin-plugin-api/src/events/player/player_item_damage.rs @@ -0,0 +1,19 @@ +use super::super::FromIntoEvent; +use crate::wit::pumpkin::plugin::event::{Event, EventType, PlayerItemDamageEventData}; + +pub struct PlayerItemDamageEvent; +impl FromIntoEvent for PlayerItemDamageEvent { + const EVENT_TYPE: EventType = EventType::PlayerItemDamageEvent; + type Data = PlayerItemDamageEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::PlayerItemDamageEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::PlayerItemDamageEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/world/chunk_load.rs b/pumpkin-plugin-api/src/events/world/chunk_load.rs new file mode 100644 index 000000000..73c29ce9a --- /dev/null +++ b/pumpkin-plugin-api/src/events/world/chunk_load.rs @@ -0,0 +1,22 @@ +use crate::wit::pumpkin::plugin::event::{ChunkLoadEventData, Event, EventType}; + +use super::super::FromIntoEvent; + +/// An event that occurs when a chunk is loaded in a world. +pub struct ChunkLoadEvent; + +impl FromIntoEvent for ChunkLoadEvent { + const EVENT_TYPE: EventType = EventType::ChunkLoadEvent; + type Data = ChunkLoadEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::ChunkLoadEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::ChunkLoadEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/world/chunk_save.rs b/pumpkin-plugin-api/src/events/world/chunk_save.rs new file mode 100644 index 000000000..7c592feea --- /dev/null +++ b/pumpkin-plugin-api/src/events/world/chunk_save.rs @@ -0,0 +1,22 @@ +use crate::wit::pumpkin::plugin::event::{ChunkSaveEventData, Event, EventType}; + +use super::super::FromIntoEvent; + +/// An event that occurs when a chunk is saved in a world. +pub struct ChunkSaveEvent; + +impl FromIntoEvent for ChunkSaveEvent { + const EVENT_TYPE: EventType = EventType::ChunkSaveEvent; + type Data = ChunkSaveEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::ChunkSaveEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::ChunkSaveEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/world/chunk_send.rs b/pumpkin-plugin-api/src/events/world/chunk_send.rs new file mode 100644 index 000000000..e8c6a5919 --- /dev/null +++ b/pumpkin-plugin-api/src/events/world/chunk_send.rs @@ -0,0 +1,22 @@ +use crate::wit::pumpkin::plugin::event::{ChunkSendEventData, Event, EventType}; + +use super::super::FromIntoEvent; + +/// An event that occurs when a chunk is sent to a client. +pub struct ChunkSendEvent; + +impl FromIntoEvent for ChunkSendEvent { + const EVENT_TYPE: EventType = EventType::ChunkSendEvent; + type Data = ChunkSendEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::ChunkSendEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::ChunkSendEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/world/mod.rs b/pumpkin-plugin-api/src/events/world/mod.rs new file mode 100644 index 000000000..29228dc8c --- /dev/null +++ b/pumpkin-plugin-api/src/events/world/mod.rs @@ -0,0 +1,11 @@ +pub mod chunk_load; +pub mod chunk_save; +pub mod chunk_send; +pub mod weather_change; +pub mod world_load; + +pub use chunk_load::*; +pub use chunk_save::*; +pub use chunk_send::*; +pub use weather_change::*; +pub use world_load::*; diff --git a/pumpkin-plugin-api/src/events/world/weather_change.rs b/pumpkin-plugin-api/src/events/world/weather_change.rs new file mode 100644 index 000000000..b316416be --- /dev/null +++ b/pumpkin-plugin-api/src/events/world/weather_change.rs @@ -0,0 +1,38 @@ +use super::super::FromIntoEvent; +use crate::wit::pumpkin::plugin::event::{ + Event, EventType, ThunderChangeEventData, WeatherChangeEventData, +}; + +pub struct WeatherChangeEvent; +impl FromIntoEvent for WeatherChangeEvent { + const EVENT_TYPE: EventType = EventType::WeatherChangeEvent; + type Data = WeatherChangeEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::WeatherChangeEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::WeatherChangeEvent(data) + } +} + +pub struct ThunderChangeEvent; +impl FromIntoEvent for ThunderChangeEvent { + const EVENT_TYPE: EventType = EventType::ThunderChangeEvent; + type Data = ThunderChangeEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::ThunderChangeEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::ThunderChangeEvent(data) + } +} diff --git a/pumpkin-plugin-api/src/events/world/world_load.rs b/pumpkin-plugin-api/src/events/world/world_load.rs new file mode 100644 index 000000000..037ae9183 --- /dev/null +++ b/pumpkin-plugin-api/src/events/world/world_load.rs @@ -0,0 +1,38 @@ +use super::super::FromIntoEvent; +use crate::wit::pumpkin::plugin::event::{ + Event, EventType, WorldLoadEventData, WorldUnloadEventData, +}; + +pub struct WorldLoadEvent; +impl FromIntoEvent for WorldLoadEvent { + const EVENT_TYPE: EventType = EventType::WorldLoadEvent; + type Data = WorldLoadEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::WorldLoadEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::WorldLoadEvent(data) + } +} + +pub struct WorldUnloadEvent; +impl FromIntoEvent for WorldUnloadEvent { + const EVENT_TYPE: EventType = EventType::WorldUnloadEvent; + type Data = WorldUnloadEventData; + + fn data_from_event(event: Event) -> Self::Data { + match event { + Event::WorldUnloadEvent(data) => data, + _ => panic!("unexpected event"), + } + } + + fn data_into_event(data: Self::Data) -> Event { + Event::WorldUnloadEvent(data) + } +} diff --git a/pumpkin/src/block/blocks/bed.rs b/pumpkin/src/block/blocks/bed.rs index 07cf589e0..32ba97fc4 100644 --- a/pumpkin/src/block/blocks/bed.rs +++ b/pumpkin/src/block/blocks/bed.rs @@ -358,6 +358,18 @@ impl BlockBehaviour for BedBlock { } } + if let Some(server) = args.world.server.upgrade() { + let mut event = + crate::plugin::api::events::player::player_bed::PlayerBedEnterEvent::new( + args.player.clone(), + bed_head_pos, + ); + server.plugin_manager.fire(&server, &mut event).await; + if event.cancelled { + return BlockActionResult::SuccessServer; + } + } + args.player.sleep(bed_head_pos); args.player .trigger_advancement( diff --git a/pumpkin/src/block/blocks/fire/fire.rs b/pumpkin/src/block/blocks/fire/fire.rs index b2ed1e27a..d64408c03 100644 --- a/pumpkin/src/block/blocks/fire/fire.rs +++ b/pumpkin/src/block/blocks/fire/fire.rs @@ -165,6 +165,17 @@ impl FireBlock { .set_block_state(pos, new_state_id, BlockFlags::NOTIFY_NEIGHBORS) .await; } else { + let mut burn_event = crate::plugin::block::block_burn::BlockBurnEvent { + igniting_block: &Block::FIRE, + block: old_block, + cancelled: false, + }; + if let Some(server) = world.server.upgrade() { + server.plugin_manager.fire(&server, &mut burn_event).await; + } + if burn_event.cancelled { + return; + } world .set_block_state( pos, diff --git a/pumpkin/src/block/fluid/lava.rs b/pumpkin/src/block/fluid/lava.rs index 4a02040f4..652490609 100644 --- a/pumpkin/src/block/fluid/lava.rs +++ b/pumpkin/src/block/fluid/lava.rs @@ -124,6 +124,17 @@ impl FlowingLava { return false; } if below_is_soul_soil && world.get_block(&neighbor_pos) == &Block::BLUE_ICE { + if let Some(server) = world.server.upgrade() { + let mut event = + crate::plugin::api::events::block::block_form::BlockFormEvent::new( + *block_pos, + &Block::BASALT, + ); + server.plugin_manager.fire(&server, &mut event).await; + if event.cancelled { + return false; + } + } world .set_block_state( block_pos, diff --git a/pumpkin/src/block/registry.rs b/pumpkin/src/block/registry.rs index 0da221f81..6128dd472 100644 --- a/pumpkin/src/block/registry.rs +++ b/pumpkin/src/block/registry.rs @@ -597,14 +597,34 @@ impl BlockRegistry { // Mirror vanilla obstruction checks: only entities that block building should prevent // placement. (e.g. arrows/xp orbs/displays/markers should not) let state = BlockState::from_id(new_state); + let mut buildable = true; for shape in state.get_block_collision_shapes() { let placed_box = shape.at_pos(final_block_pos); if Self::has_blocking_entity_in_box(world.as_ref(), &placed_box) { - return Ok(None); + buildable = false; + break; } } + let mut can_build_event = crate::plugin::block::block_can_build::BlockCanBuildEvent { + block_to_build: placed_block, + buildable, + player: player.clone(), + block: clicked_block, + cancelled: false, + }; + server + .plugin_manager + .fire::( + server, + &mut can_build_event, + ) + .await; + if can_build_event.cancelled || !can_build_event.buildable { + return Ok(None); + } + let mut event = crate::plugin::block::block_place::BlockPlaceEvent::new( player.clone(), placed_block, diff --git a/pumpkin/src/entity/player.rs b/pumpkin/src/entity/player.rs index 469e398ca..323388273 100644 --- a/pumpkin/src/entity/player.rs +++ b/pumpkin/src/entity/player.rs @@ -1266,6 +1266,16 @@ impl Player { }; if let Some((result, updated_stack)) = updated { + if let Some(server) = self.world().server.upgrade() + && let Some(player_arc) = self.world().get_player_by_uuid(self.gameprofile.id) + { + let mut event = crate::plugin::api::events::player::player_item_damage::PlayerItemDamageEvent::new( + player_arc, + updated_stack.item.registry_key.to_string(), + amount, + ); + server.plugin_manager.fire(&server, &mut event).await; + } // Send the break status before clearing the slot so the client can // use the item texture for break particles. if result == pumpkin_data::item_stack::DamageResult::Broken { @@ -1766,6 +1776,17 @@ impl Player { return; }; + if let Some(server) = world.server.upgrade() + && let Some(player_arc) = world.get_player_by_uuid(self.gameprofile.id) + { + let mut event = + crate::plugin::api::events::player::player_bed::PlayerBedLeaveEvent::new( + player_arc, + respawn_point.position, + ); + server.plugin_manager.fire(&server, &mut event).await; + } + let (bed, bed_state) = world.get_block_and_state_id(&respawn_point.position); BedBlock::set_occupied(false, &world, bed, &respawn_point.position, bed_state).await; @@ -3199,6 +3220,22 @@ impl Player { let drop_amount = if drop_stack { item_stack.item_count } else { 1 }; let dropped_stack = item_stack.copy_with_count(drop_amount); + + if let Some(server) = self.world().server.upgrade() + && let Some(player_arc) = self.world().get_player_by_uuid(self.gameprofile.id) + { + let mut event = + crate::plugin::api::events::player::player_drop_item::PlayerDropItemEvent::new( + player_arc, + dropped_stack.item.registry_key.to_string(), + dropped_stack.item_count as u8, + ); + server.plugin_manager.fire(&server, &mut event).await; + if event.cancelled { + return; + } + } + item_stack.decrement(drop_amount); let updated_stack = item_stack.clone(); let selected_slot = self.inventory.get_selected_slot(); @@ -3706,6 +3743,17 @@ impl Player { self.close_handled_screen().await; } + if let Some(server) = self.world().server.upgrade() { + let mut event = + crate::plugin::api::events::inventory::inventory_open::InventoryOpenEvent::new( + self.clone(), + ); + server.plugin_manager.fire(&server, &mut event).await; + if event.cancelled { + return None; + } + } + self.increment_screen_handler_sync_id(); if let Some(screen_handler) = screen_handler_factory diff --git a/pumpkin/src/item/items/bucket.rs b/pumpkin/src/item/items/bucket.rs index 752c4602d..3e2938314 100644 --- a/pumpkin/src/item/items/bucket.rs +++ b/pumpkin/src/item/items/bucket.rs @@ -314,6 +314,21 @@ impl ItemBehaviour for EmptyBucketItem { return; }; + if let Some(server) = world.server.upgrade() + && let Some(player_arc) = world.get_player_by_uuid(player.gameprofile.id) + { + let mut event = + crate::plugin::api::events::player::player_bucket::PlayerBucketFillEvent::new( + player_arc, + block_pos, + item.registry_key.to_string(), + ); + server.plugin_manager.fire(&server, &mut event).await; + if event.cancelled { + return; + } + } + give_player_bucket_item(player, item).await; }) } @@ -352,6 +367,18 @@ impl ItemBehaviour for FilledBucketItem { return; } + if let Some(server) = world.server.upgrade() + && let Some(player_arc) = world.get_player_by_uuid(player.gameprofile.id) + { + let mut event = + crate::plugin::api::events::player::player_bucket::PlayerBucketEmptyEvent::new( + player_arc, + pos, + item.registry_key.to_string(), + ); + server.plugin_manager.fire(&server, &mut event).await; + } + //TODO: Spawn entity if applicable if player.gamemode.load() != GameMode::Creative { let item_stack = ItemStack::new(1, &Item::BUCKET); diff --git a/pumpkin/src/item/items/ignite/flint_and_steel.rs b/pumpkin/src/item/items/ignite/flint_and_steel.rs index 900816004..e2afc968a 100644 --- a/pumpkin/src/item/items/ignite/flint_and_steel.rs +++ b/pumpkin/src/item/items/ignite/flint_and_steel.rs @@ -35,6 +35,23 @@ impl ItemBehaviour for FlintAndSteelItem { _server: &'a Server, ) -> Pin + Send + 'a>> { Box::pin(async move { + if let Some(server_ref) = player.world().server.upgrade() { + let player_arc = player.world().get_player_by_uuid(player.gameprofile.id); + let mut event = + crate::plugin::api::events::block::block_ignite::BlockIgniteEvent::new( + location, + &pumpkin_data::Block::FIRE, + player_arc, + ); + server_ref + .plugin_manager + .fire(&server_ref, &mut event) + .await; + if event.cancelled { + return; + } + } + let ignited = Ignition::ignite_block( |world: Arc, pos: BlockPos, new_state_id: BlockStateId| async move { world diff --git a/pumpkin/src/net/java/play.rs b/pumpkin/src/net/java/play.rs index ebd2c62dc..014dded15 100644 --- a/pumpkin/src/net/java/play.rs +++ b/pumpkin/src/net/java/play.rs @@ -1933,6 +1933,24 @@ impl JavaClient { let world = entity.world.load_full(); let (block, state) = world.get_block_and_state(&position); + if let Some(server_arc) = world.server.upgrade() { + let mut event = + crate::plugin::api::events::block::block_damage::BlockDamageEvent::new( + player.clone(), + block, + position, + false, + ); + server_arc + .plugin_manager + .fire(&server_arc, &mut event) + .await; + if event.cancelled { + self.update_sequence(player, player_action.sequence.0); + return; + } + } + if block == &pumpkin_data::Block::NOTE_BLOCK { let props = pumpkin_data::block_properties::NoteBlockLikeProperties::from_state_id( diff --git a/pumpkin/src/plugin/api/events/block/block_damage.rs b/pumpkin/src/plugin/api/events/block/block_damage.rs new file mode 100644 index 000000000..74f281e13 --- /dev/null +++ b/pumpkin/src/plugin/api/events/block/block_damage.rs @@ -0,0 +1,40 @@ +use crate::entity::player::Player; +use pumpkin_data::Block; +use pumpkin_macros::{Event, cancellable}; +use pumpkin_util::math::position::BlockPos; +use std::sync::Arc; + +/// An event that occurs when a player damages / breaks a block. +#[cancellable] +#[derive(Event, Clone)] +pub struct BlockDamageEvent { + /// The player damaging the block. + pub player: Arc, + + /// The block being damaged. + pub block: &'static Block, + + /// The position of the block. + pub block_pos: BlockPos, + + /// Whether the block is instantly broken. + pub insta_break: bool, +} + +impl BlockDamageEvent { + #[must_use] + pub const fn new( + player: Arc, + block: &'static Block, + block_pos: BlockPos, + insta_break: bool, + ) -> Self { + Self { + player, + block, + block_pos, + insta_break, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/block/block_dispense.rs b/pumpkin/src/plugin/api/events/block/block_dispense.rs new file mode 100644 index 000000000..9ceb19267 --- /dev/null +++ b/pumpkin/src/plugin/api/events/block/block_dispense.rs @@ -0,0 +1,21 @@ +use pumpkin_macros::{Event, cancellable}; +use pumpkin_util::math::position::BlockPos; + +/// An event that occurs when a block dispenses an item. +#[cancellable] +#[derive(Event, Clone)] +pub struct BlockDispenseEvent { + pub block_pos: BlockPos, + pub item_name: String, +} + +impl BlockDispenseEvent { + #[must_use] + pub const fn new(block_pos: BlockPos, item_name: String) -> Self { + Self { + block_pos, + item_name, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/block/block_explode.rs b/pumpkin/src/plugin/api/events/block/block_explode.rs new file mode 100644 index 000000000..c002c016b --- /dev/null +++ b/pumpkin/src/plugin/api/events/block/block_explode.rs @@ -0,0 +1,21 @@ +use pumpkin_macros::{Event, cancellable}; +use pumpkin_util::math::position::BlockPos; + +/// An event that occurs when a block explodes. +#[cancellable] +#[derive(Event, Clone)] +pub struct BlockExplodeEvent { + pub block_pos: BlockPos, + pub yield_rate: f32, +} + +impl BlockExplodeEvent { + #[must_use] + pub const fn new(block_pos: BlockPos, yield_rate: f32) -> Self { + Self { + block_pos, + yield_rate, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/block/block_fade.rs b/pumpkin/src/plugin/api/events/block/block_fade.rs new file mode 100644 index 000000000..83367294e --- /dev/null +++ b/pumpkin/src/plugin/api/events/block/block_fade.rs @@ -0,0 +1,25 @@ +use pumpkin_data::Block; +use pumpkin_macros::{Event, cancellable}; +use pumpkin_util::math::position::BlockPos; + +/// An event that occurs when a block fades or melts away (e.g. ice, snow). +#[cancellable] +#[derive(Event, Clone)] +pub struct BlockFadeEvent { + /// The position of the fading block. + pub block_pos: BlockPos, + + /// The block fading. + pub block: &'static Block, +} + +impl BlockFadeEvent { + #[must_use] + pub const fn new(block_pos: BlockPos, block: &'static Block) -> Self { + Self { + block_pos, + block, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/block/block_form.rs b/pumpkin/src/plugin/api/events/block/block_form.rs new file mode 100644 index 000000000..432cdaf75 --- /dev/null +++ b/pumpkin/src/plugin/api/events/block/block_form.rs @@ -0,0 +1,25 @@ +use pumpkin_data::Block; +use pumpkin_macros::{Event, cancellable}; +use pumpkin_util::math::position::BlockPos; + +/// An event that occurs when a block forms naturally (e.g. ice, snow, cobblestone). +#[cancellable] +#[derive(Event, Clone)] +pub struct BlockFormEvent { + /// The position where the block forms. + pub block_pos: BlockPos, + + /// The formed block type. + pub block: &'static Block, +} + +impl BlockFormEvent { + #[must_use] + pub const fn new(block_pos: BlockPos, block: &'static Block) -> Self { + Self { + block_pos, + block, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/block/block_from_to.rs b/pumpkin/src/plugin/api/events/block/block_from_to.rs new file mode 100644 index 000000000..8b198cad1 --- /dev/null +++ b/pumpkin/src/plugin/api/events/block/block_from_to.rs @@ -0,0 +1,29 @@ +use pumpkin_data::Block; +use pumpkin_macros::{Event, cancellable}; +use pumpkin_util::math::position::BlockPos; + +/// An event that occurs when a block (such as fluid) spreads/flows from one location to another. +#[cancellable] +#[derive(Event, Clone)] +pub struct BlockFromToEvent { + /// The source block position. + pub from_pos: BlockPos, + + /// The destination block position. + pub to_pos: BlockPos, + + /// The block flowing. + pub block: &'static Block, +} + +impl BlockFromToEvent { + #[must_use] + pub const fn new(from_pos: BlockPos, to_pos: BlockPos, block: &'static Block) -> Self { + Self { + from_pos, + to_pos, + block, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/block/block_ignite.rs b/pumpkin/src/plugin/api/events/block/block_ignite.rs new file mode 100644 index 000000000..4d22f2950 --- /dev/null +++ b/pumpkin/src/plugin/api/events/block/block_ignite.rs @@ -0,0 +1,35 @@ +use crate::entity::player::Player; +use pumpkin_data::Block; +use pumpkin_macros::{Event, cancellable}; +use pumpkin_util::math::position::BlockPos; +use std::sync::Arc; + +/// An event that occurs when a block ignites. +#[cancellable] +#[derive(Event, Clone)] +pub struct BlockIgniteEvent { + /// The position of the ignited block. + pub block_pos: BlockPos, + + /// The block that ignited this block. + pub igniting_block: &'static Block, + + /// The player that ignited the block, if any. + pub player: Option>, +} + +impl BlockIgniteEvent { + #[must_use] + pub const fn new( + block_pos: BlockPos, + igniting_block: &'static Block, + player: Option>, + ) -> Self { + Self { + block_pos, + igniting_block, + player, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/block/block_physics.rs b/pumpkin/src/plugin/api/events/block/block_physics.rs new file mode 100644 index 000000000..9be91db01 --- /dev/null +++ b/pumpkin/src/plugin/api/events/block/block_physics.rs @@ -0,0 +1,21 @@ +use pumpkin_macros::{Event, cancellable}; +use pumpkin_util::math::position::BlockPos; + +/// An event that occurs when a block physics check is run. +#[cancellable] +#[derive(Event, Clone)] +pub struct BlockPhysicsEvent { + pub block_pos: BlockPos, + pub changed_pos: BlockPos, +} + +impl BlockPhysicsEvent { + #[must_use] + pub const fn new(block_pos: BlockPos, changed_pos: BlockPos) -> Self { + Self { + block_pos, + changed_pos, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/block/block_piston.rs b/pumpkin/src/plugin/api/events/block/block_piston.rs new file mode 100644 index 000000000..5d00cb952 --- /dev/null +++ b/pumpkin/src/plugin/api/events/block/block_piston.rs @@ -0,0 +1,40 @@ +use pumpkin_macros::{Event, cancellable}; +use pumpkin_util::math::position::BlockPos; + +/// An event that occurs when a piston extends. +#[cancellable] +#[derive(Event, Clone)] +pub struct BlockPistonExtendEvent { + pub block_pos: BlockPos, + pub direction: String, +} + +impl BlockPistonExtendEvent { + #[must_use] + pub const fn new(block_pos: BlockPos, direction: String) -> Self { + Self { + block_pos, + direction, + cancelled: false, + } + } +} + +/// An event that occurs when a piston retracts. +#[cancellable] +#[derive(Event, Clone)] +pub struct BlockPistonRetractEvent { + pub block_pos: BlockPos, + pub direction: String, +} + +impl BlockPistonRetractEvent { + #[must_use] + pub const fn new(block_pos: BlockPos, direction: String) -> Self { + Self { + block_pos, + direction, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/block/mod.rs b/pumpkin/src/plugin/api/events/block/mod.rs index 92b9c26b8..5dfd366a0 100644 --- a/pumpkin/src/plugin/api/events/block/mod.rs +++ b/pumpkin/src/plugin/api/events/block/mod.rs @@ -1,9 +1,42 @@ pub mod block_break; pub mod block_burn; pub mod block_can_build; +pub mod block_damage; +pub mod block_dispense; +pub mod block_explode; +pub mod block_fade; +pub mod block_form; +pub mod block_from_to; pub mod block_grow; +pub mod block_ignite; +pub mod block_physics; +pub mod block_piston; pub mod block_place; pub mod block_redstone; +pub mod note_play; +pub mod sign_change; +pub mod sponge_absorb; +pub mod tnt_prime; + +pub use block_break::*; +pub use block_burn::*; +pub use block_can_build::*; +pub use block_damage::*; +pub use block_dispense::*; +pub use block_explode::*; +pub use block_fade::*; +pub use block_form::*; +pub use block_from_to::*; +pub use block_grow::*; +pub use block_ignite::*; +pub use block_physics::*; +pub use block_piston::*; +pub use block_place::*; +pub use block_redstone::*; +pub use note_play::*; +pub use sign_change::*; +pub use sponge_absorb::*; +pub use tnt_prime::*; use pumpkin_data::Block; diff --git a/pumpkin/src/plugin/api/events/block/note_play.rs b/pumpkin/src/plugin/api/events/block/note_play.rs new file mode 100644 index 000000000..b63c477f5 --- /dev/null +++ b/pumpkin/src/plugin/api/events/block/note_play.rs @@ -0,0 +1,23 @@ +use pumpkin_macros::{Event, cancellable}; +use pumpkin_util::math::position::BlockPos; + +/// An event that occurs when a note block plays. +#[cancellable] +#[derive(Event, Clone)] +pub struct NotePlayEvent { + pub block_pos: BlockPos, + pub instrument: String, + pub note: u8, +} + +impl NotePlayEvent { + #[must_use] + pub const fn new(block_pos: BlockPos, instrument: String, note: u8) -> Self { + Self { + block_pos, + instrument, + note, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/block/sign_change.rs b/pumpkin/src/plugin/api/events/block/sign_change.rs new file mode 100644 index 000000000..f07bedce0 --- /dev/null +++ b/pumpkin/src/plugin/api/events/block/sign_change.rs @@ -0,0 +1,25 @@ +use crate::entity::player::Player; +use pumpkin_macros::{Event, cancellable}; +use pumpkin_util::math::position::BlockPos; +use std::sync::Arc; + +/// An event that occurs when a sign's text is changed. +#[cancellable] +#[derive(Event, Clone)] +pub struct SignChangeEvent { + pub player: Arc, + pub block_pos: BlockPos, + pub lines: Vec, +} + +impl SignChangeEvent { + #[must_use] + pub const fn new(player: Arc, block_pos: BlockPos, lines: Vec) -> Self { + Self { + player, + block_pos, + lines, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/block/sponge_absorb.rs b/pumpkin/src/plugin/api/events/block/sponge_absorb.rs new file mode 100644 index 000000000..2f4c5001c --- /dev/null +++ b/pumpkin/src/plugin/api/events/block/sponge_absorb.rs @@ -0,0 +1,19 @@ +use pumpkin_macros::{Event, cancellable}; +use pumpkin_util::math::position::BlockPos; + +/// An event that occurs when a sponge absorbs water. +#[cancellable] +#[derive(Event, Clone)] +pub struct SpongeAbsorbEvent { + pub block_pos: BlockPos, +} + +impl SpongeAbsorbEvent { + #[must_use] + pub const fn new(block_pos: BlockPos) -> Self { + Self { + block_pos, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/block/tnt_prime.rs b/pumpkin/src/plugin/api/events/block/tnt_prime.rs new file mode 100644 index 000000000..b61b2ca7b --- /dev/null +++ b/pumpkin/src/plugin/api/events/block/tnt_prime.rs @@ -0,0 +1,21 @@ +use pumpkin_macros::{Event, cancellable}; +use pumpkin_util::math::position::BlockPos; + +/// An event that occurs when TNT is primed. +#[cancellable] +#[derive(Event, Clone)] +pub struct TNTPrimeEvent { + pub block_pos: BlockPos, + pub prime_reason: String, +} + +impl TNTPrimeEvent { + #[must_use] + pub const fn new(block_pos: BlockPos, prime_reason: String) -> Self { + Self { + block_pos, + prime_reason, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/entity/entity_combust.rs b/pumpkin/src/plugin/api/events/entity/entity_combust.rs new file mode 100644 index 000000000..88276a958 --- /dev/null +++ b/pumpkin/src/plugin/api/events/entity/entity_combust.rs @@ -0,0 +1,23 @@ +use pumpkin_macros::{Event, cancellable}; + +/// An event that occurs when an entity catches fire. +#[cancellable] +#[derive(Event, Clone)] +pub struct EntityCombustEvent { + /// The ID of the entity that caught fire. + pub entity_id: i32, + + /// The duration in seconds the entity will burn. + pub duration_secs: f32, +} + +impl EntityCombustEvent { + #[must_use] + pub const fn new(entity_id: i32, duration_secs: f32) -> Self { + Self { + entity_id, + duration_secs, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/entity/entity_damage.rs b/pumpkin/src/plugin/api/events/entity/entity_damage.rs new file mode 100644 index 000000000..575a3d01c --- /dev/null +++ b/pumpkin/src/plugin/api/events/entity/entity_damage.rs @@ -0,0 +1,27 @@ +use pumpkin_macros::{Event, cancellable}; + +/// An event that occurs when an entity takes damage. +#[cancellable] +#[derive(Event, Clone)] +pub struct EntityDamageEvent { + /// The ID of the entity taking damage. + pub entity_id: i32, + + /// The amount of damage taken. + pub damage: f32, + + /// The cause or type of damage as a string. + pub cause: String, +} + +impl EntityDamageEvent { + #[must_use] + pub const fn new(entity_id: i32, damage_type: String, damage_amount: f32) -> Self { + Self { + entity_id, + damage: damage_amount, + cause: damage_type, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/entity/entity_death.rs b/pumpkin/src/plugin/api/events/entity/entity_death.rs new file mode 100644 index 000000000..f146794d2 --- /dev/null +++ b/pumpkin/src/plugin/api/events/entity/entity_death.rs @@ -0,0 +1,54 @@ +use crate::entity::player::Player; +use pumpkin_macros::{Event, cancellable}; +use pumpkin_util::text::TextComponent; +use std::sync::Arc; + +/// An event that occurs when an entity dies. +#[derive(Event, Clone)] +pub struct EntityDeathEvent { + /// The ID of the entity that died. + pub entity_id: i32, + + /// The amount of experience dropped by the entity. + pub dropped_exp: i32, +} + +impl EntityDeathEvent { + #[must_use] + pub const fn new(entity_id: i32, dropped_exp: i32) -> Self { + Self { + entity_id, + dropped_exp, + } + } +} + +/// An event that occurs when a player dies. +#[cancellable] +#[derive(Event, Clone)] +pub struct PlayerDeathEvent { + /// The player that died. + pub player: Arc, + + /// The death message to be broadcasted. + pub death_message: TextComponent, + + /// The amount of experience dropped by the player. + pub dropped_exp: i32, + + /// Whether the player keeps their inventory upon death. + pub keep_inventory: bool, +} + +impl PlayerDeathEvent { + #[must_use] + pub const fn new(player: Arc, death_message: TextComponent, dropped_exp: i32) -> Self { + Self { + player, + death_message, + dropped_exp, + keep_inventory: false, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/entity/entity_regain_health.rs b/pumpkin/src/plugin/api/events/entity/entity_regain_health.rs new file mode 100644 index 000000000..1806bcd66 --- /dev/null +++ b/pumpkin/src/plugin/api/events/entity/entity_regain_health.rs @@ -0,0 +1,23 @@ +use pumpkin_macros::{Event, cancellable}; + +/// An event that occurs when an entity regains health. +#[cancellable] +#[derive(Event, Clone)] +pub struct EntityRegainHealthEvent { + /// The ID of the entity regaining health. + pub entity_id: i32, + + /// The amount of health regained. + pub amount: f32, +} + +impl EntityRegainHealthEvent { + #[must_use] + pub const fn new(entity_id: i32, amount: f32) -> Self { + Self { + entity_id, + amount, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/entity/entity_spawn.rs b/pumpkin/src/plugin/api/events/entity/entity_spawn.rs new file mode 100644 index 000000000..fb7cbd287 --- /dev/null +++ b/pumpkin/src/plugin/api/events/entity/entity_spawn.rs @@ -0,0 +1,39 @@ +use crate::world::World; +use pumpkin_macros::{Event, cancellable}; +use pumpkin_util::math::vector3::Vector3; +use std::sync::Arc; + +/// An event that occurs when an entity is spawned into a world. +#[cancellable] +#[derive(Event, Clone)] +pub struct EntitySpawnEvent { + /// The ID of the spawned entity. + pub entity_id: i32, + + /// The registry name of the entity type. + pub entity_type: String, + + /// The position where the entity is spawned. + pub position: Vector3, + + /// The world in which the entity is spawned. + pub world: Arc, +} + +impl EntitySpawnEvent { + #[must_use] + pub const fn new( + entity_id: i32, + entity_type: String, + position: Vector3, + world: Arc, + ) -> Self { + Self { + entity_id, + entity_type, + position, + world, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/entity/mod.rs b/pumpkin/src/plugin/api/events/entity/mod.rs new file mode 100644 index 000000000..6c9dd8189 --- /dev/null +++ b/pumpkin/src/plugin/api/events/entity/mod.rs @@ -0,0 +1,11 @@ +pub mod entity_combust; +pub mod entity_damage; +pub mod entity_death; +pub mod entity_regain_health; +pub mod entity_spawn; + +pub use entity_combust::*; +pub use entity_damage::*; +pub use entity_death::*; +pub use entity_regain_health::*; +pub use entity_spawn::*; diff --git a/pumpkin/src/plugin/api/events/inventory/craft_item.rs b/pumpkin/src/plugin/api/events/inventory/craft_item.rs new file mode 100644 index 000000000..f9710d0cb --- /dev/null +++ b/pumpkin/src/plugin/api/events/inventory/craft_item.rs @@ -0,0 +1,25 @@ +use crate::entity::player::Player; +use pumpkin_macros::{Event, cancellable}; +use std::sync::Arc; + +/// An event that occurs when a player crafts an item. +#[cancellable] +#[derive(Event, Clone)] +pub struct CraftItemEvent { + /// The player crafting the item. + pub player: Arc, + + /// The recipe identifier. + pub recipe_id: String, +} + +impl CraftItemEvent { + #[must_use] + pub const fn new(player: Arc, recipe_id: String) -> Self { + Self { + player, + recipe_id, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/inventory/furnace_smelt.rs b/pumpkin/src/plugin/api/events/inventory/furnace_smelt.rs new file mode 100644 index 000000000..a30271573 --- /dev/null +++ b/pumpkin/src/plugin/api/events/inventory/furnace_smelt.rs @@ -0,0 +1,28 @@ +use pumpkin_macros::{Event, cancellable}; +use pumpkin_util::math::position::BlockPos; + +/// An event that occurs when a furnace smelts an item. +#[cancellable] +#[derive(Event, Clone)] +pub struct FurnaceSmeltEvent { + /// The position of the furnace block. + pub block_pos: BlockPos, + + /// The source item being smelted. + pub source_item: String, + + /// The resulting smelted item. + pub result_item: String, +} + +impl FurnaceSmeltEvent { + #[must_use] + pub const fn new(block_pos: BlockPos, source_item: String, result_item: String) -> Self { + Self { + block_pos, + source_item, + result_item, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/inventory/inventory_drag.rs b/pumpkin/src/plugin/api/events/inventory/inventory_drag.rs new file mode 100644 index 000000000..0012296f7 --- /dev/null +++ b/pumpkin/src/plugin/api/events/inventory/inventory_drag.rs @@ -0,0 +1,21 @@ +use crate::entity::player::Player; +use pumpkin_macros::{Event, cancellable}; +use std::sync::Arc; + +/// An event that occurs when a player drags items across inventory slots. +#[cancellable] +#[derive(Event, Clone)] +pub struct InventoryDragEvent { + /// The player dragging items. + pub player: Arc, +} + +impl InventoryDragEvent { + #[must_use] + pub const fn new(player: Arc) -> Self { + Self { + player, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/inventory/inventory_open.rs b/pumpkin/src/plugin/api/events/inventory/inventory_open.rs new file mode 100644 index 000000000..f02b31a59 --- /dev/null +++ b/pumpkin/src/plugin/api/events/inventory/inventory_open.rs @@ -0,0 +1,21 @@ +use crate::entity::player::Player; +use pumpkin_macros::{Event, cancellable}; +use std::sync::Arc; + +/// An event that occurs when a player opens an inventory. +#[cancellable] +#[derive(Event, Clone)] +pub struct InventoryOpenEvent { + /// The player opening the inventory. + pub player: Arc, +} + +impl InventoryOpenEvent { + #[must_use] + pub const fn new(player: Arc) -> Self { + Self { + player, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/inventory/mod.rs b/pumpkin/src/plugin/api/events/inventory/mod.rs new file mode 100644 index 000000000..24100c452 --- /dev/null +++ b/pumpkin/src/plugin/api/events/inventory/mod.rs @@ -0,0 +1,9 @@ +pub mod craft_item; +pub mod furnace_smelt; +pub mod inventory_drag; +pub mod inventory_open; + +pub use craft_item::*; +pub use furnace_smelt::*; +pub use inventory_drag::*; +pub use inventory_open::*; diff --git a/pumpkin/src/plugin/api/events/mod.rs b/pumpkin/src/plugin/api/events/mod.rs index 78ddb7143..73d5cd597 100644 --- a/pumpkin/src/plugin/api/events/mod.rs +++ b/pumpkin/src/plugin/api/events/mod.rs @@ -2,6 +2,8 @@ use std::any::Any; use std::sync::Arc; pub mod block; +pub mod entity; +pub mod inventory; pub mod player; pub mod server; pub mod world; diff --git a/pumpkin/src/plugin/api/events/player/mod.rs b/pumpkin/src/plugin/api/events/player/mod.rs index 852f29dbe..e2b38c7ed 100644 --- a/pumpkin/src/plugin/api/events/player/mod.rs +++ b/pumpkin/src/plugin/api/events/player/mod.rs @@ -7,14 +7,19 @@ pub mod fish; pub mod inventory_close; pub mod inventory_interact; pub mod item_held; +pub mod player_bed; +pub mod player_bucket; pub mod player_change_world; pub mod player_chat; pub mod player_command_send; pub mod player_custom_payload; +pub mod player_drop_item; pub mod player_gamemode_change; pub mod player_interact_entity_event; pub mod player_interact_event; pub mod player_interact_unknown_entity_event; +pub mod player_item_consume; +pub mod player_item_damage; pub mod player_join; pub mod player_leave; pub mod player_login; @@ -26,6 +31,39 @@ pub mod player_toggle_flight_event; pub mod player_toggle_sneak_event; pub mod player_toggle_sprint_event; +pub use bedrock_form_response::*; +pub use changed_main_hand::*; +pub use custom_click_action::*; +pub use egg_throw::*; +pub use exp_change::*; +pub use fish::*; +pub use inventory_close::*; +pub use inventory_interact::*; +pub use item_held::*; +pub use player_bed::*; +pub use player_bucket::*; +pub use player_change_world::*; +pub use player_chat::*; +pub use player_command_send::*; +pub use player_custom_payload::*; +pub use player_drop_item::*; +pub use player_gamemode_change::*; +pub use player_interact_entity_event::*; +pub use player_interact_event::*; +pub use player_interact_unknown_entity_event::*; +pub use player_item_consume::*; +pub use player_item_damage::*; +pub use player_join::*; +pub use player_leave::*; +pub use player_login::*; +pub use player_move::*; +pub use player_permission_check::*; +pub use player_respawn::*; +pub use player_teleport::*; +pub use player_toggle_flight_event::*; +pub use player_toggle_sneak_event::*; +pub use player_toggle_sprint_event::*; + use std::sync::Arc; use crate::entity::player::Player; diff --git a/pumpkin/src/plugin/api/events/player/player_bed.rs b/pumpkin/src/plugin/api/events/player/player_bed.rs new file mode 100644 index 000000000..ef4f6a5f4 --- /dev/null +++ b/pumpkin/src/plugin/api/events/player/player_bed.rs @@ -0,0 +1,43 @@ +use crate::entity::player::Player; +use pumpkin_macros::{Event, cancellable}; +use pumpkin_util::math::position::BlockPos; +use std::sync::Arc; + +/// An event that occurs when a player enters a bed. +#[cancellable] +#[derive(Event, Clone)] +pub struct PlayerBedEnterEvent { + /// The player entering the bed. + pub player: Arc, + + /// The position of the bed. + pub bed_pos: BlockPos, +} + +impl PlayerBedEnterEvent { + #[must_use] + pub const fn new(player: Arc, bed_pos: BlockPos) -> Self { + Self { + player, + bed_pos, + cancelled: false, + } + } +} + +/// An event that occurs when a player leaves a bed. +#[derive(Event, Clone)] +pub struct PlayerBedLeaveEvent { + /// The player leaving the bed. + pub player: Arc, + + /// The position of the bed. + pub bed_pos: BlockPos, +} + +impl PlayerBedLeaveEvent { + #[must_use] + pub const fn new(player: Arc, bed_pos: BlockPos) -> Self { + Self { player, bed_pos } + } +} diff --git a/pumpkin/src/plugin/api/events/player/player_bucket.rs b/pumpkin/src/plugin/api/events/player/player_bucket.rs new file mode 100644 index 000000000..fe7dbf45d --- /dev/null +++ b/pumpkin/src/plugin/api/events/player/player_bucket.rs @@ -0,0 +1,56 @@ +use crate::entity::player::Player; +use pumpkin_macros::{Event, cancellable}; +use pumpkin_util::math::position::BlockPos; +use std::sync::Arc; + +/// An event that occurs when a player empties a bucket. +#[cancellable] +#[derive(Event, Clone)] +pub struct PlayerBucketEmptyEvent { + /// The player emptying the bucket. + pub player: Arc, + + /// The target block position where the bucket is emptied. + pub block_pos: BlockPos, + + /// The bucket item used. + pub bucket: String, +} + +impl PlayerBucketEmptyEvent { + #[must_use] + pub const fn new(player: Arc, block_pos: BlockPos, bucket: String) -> Self { + Self { + player, + block_pos, + bucket, + cancelled: false, + } + } +} + +/// An event that occurs when a player fills a bucket. +#[cancellable] +#[derive(Event, Clone)] +pub struct PlayerBucketFillEvent { + /// The player filling the bucket. + pub player: Arc, + + /// The target block position being targeted for filling. + pub block_pos: BlockPos, + + /// The bucket item used. + pub bucket: String, +} + +impl PlayerBucketFillEvent { + #[must_use] + pub const fn new(player: Arc, block_pos: BlockPos, bucket: String) -> Self { + Self { + player, + block_pos, + bucket, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/player/player_drop_item.rs b/pumpkin/src/plugin/api/events/player/player_drop_item.rs new file mode 100644 index 000000000..6f93399a3 --- /dev/null +++ b/pumpkin/src/plugin/api/events/player/player_drop_item.rs @@ -0,0 +1,29 @@ +use crate::entity::player::Player; +use pumpkin_macros::{Event, cancellable}; +use std::sync::Arc; + +/// An event that occurs when a player drops an item. +#[cancellable] +#[derive(Event, Clone)] +pub struct PlayerDropItemEvent { + /// The player dropping the item. + pub player: Arc, + + /// The registry name of the dropped item. + pub item_name: String, + + /// The stack count of dropped items. + pub count: u8, +} + +impl PlayerDropItemEvent { + #[must_use] + pub const fn new(player: Arc, item_name: String, count: u8) -> Self { + Self { + player, + item_name, + count, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/player/player_item_consume.rs b/pumpkin/src/plugin/api/events/player/player_item_consume.rs new file mode 100644 index 000000000..6b7f96682 --- /dev/null +++ b/pumpkin/src/plugin/api/events/player/player_item_consume.rs @@ -0,0 +1,25 @@ +use crate::entity::player::Player; +use pumpkin_macros::{Event, cancellable}; +use std::sync::Arc; + +/// An event that occurs when a player consumes an item (food, potion, etc.). +#[cancellable] +#[derive(Event, Clone)] +pub struct PlayerItemConsumeEvent { + /// The player consuming the item. + pub player: Arc, + + /// The registry name of the item being consumed. + pub item_name: String, +} + +impl PlayerItemConsumeEvent { + #[must_use] + pub const fn new(player: Arc, item_name: String) -> Self { + Self { + player, + item_name, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/player/player_item_damage.rs b/pumpkin/src/plugin/api/events/player/player_item_damage.rs new file mode 100644 index 000000000..43fe6a397 --- /dev/null +++ b/pumpkin/src/plugin/api/events/player/player_item_damage.rs @@ -0,0 +1,29 @@ +use crate::entity::player::Player; +use pumpkin_macros::{Event, cancellable}; +use std::sync::Arc; + +/// An event that occurs when an item held or worn by a player takes durability damage. +#[cancellable] +#[derive(Event, Clone)] +pub struct PlayerItemDamageEvent { + /// The player whose item is taking damage. + pub player: Arc, + + /// The registry name of the item taking damage. + pub item_name: String, + + /// The amount of durability damage. + pub damage: i32, +} + +impl PlayerItemDamageEvent { + #[must_use] + pub const fn new(player: Arc, item_name: String, damage: i32) -> Self { + Self { + player, + item_name, + damage, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/world/mod.rs b/pumpkin/src/plugin/api/events/world/mod.rs index 367d98b11..0fcc2b81d 100644 --- a/pumpkin/src/plugin/api/events/world/mod.rs +++ b/pumpkin/src/plugin/api/events/world/mod.rs @@ -2,3 +2,12 @@ pub mod chunk_load; pub mod chunk_save; pub mod chunk_send; pub mod spawn_change; +pub mod weather_change; +pub mod world_load; + +pub use chunk_load::*; +pub use chunk_save::*; +pub use chunk_send::*; +pub use spawn_change::*; +pub use weather_change::*; +pub use world_load::*; diff --git a/pumpkin/src/plugin/api/events/world/weather_change.rs b/pumpkin/src/plugin/api/events/world/weather_change.rs new file mode 100644 index 000000000..b9f555062 --- /dev/null +++ b/pumpkin/src/plugin/api/events/world/weather_change.rs @@ -0,0 +1,47 @@ +use crate::world::World; +use pumpkin_macros::{Event, cancellable}; +use std::sync::Arc; + +/// An event that occurs when weather (raining) changes in a world. +#[cancellable] +#[derive(Event, Clone)] +pub struct WeatherChangeEvent { + /// The world where weather is changing. + pub world: Arc, + + /// The new weather state (true = raining, false = clear). + pub to_weather_state: bool, +} + +impl WeatherChangeEvent { + #[must_use] + pub const fn new(world: Arc, to_weather_state: bool) -> Self { + Self { + world, + to_weather_state, + cancelled: false, + } + } +} + +/// An event that occurs when thundering state changes in a world. +#[cancellable] +#[derive(Event, Clone)] +pub struct ThunderChangeEvent { + /// The world where thunder state is changing. + pub world: Arc, + + /// The new thunder state (true = thundering, false = clear). + pub to_thunder_state: bool, +} + +impl ThunderChangeEvent { + #[must_use] + pub const fn new(world: Arc, to_thunder_state: bool) -> Self { + Self { + world, + to_thunder_state, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/api/events/world/world_load.rs b/pumpkin/src/plugin/api/events/world/world_load.rs new file mode 100644 index 000000000..ebc27bedc --- /dev/null +++ b/pumpkin/src/plugin/api/events/world/world_load.rs @@ -0,0 +1,35 @@ +use crate::world::World; +use pumpkin_macros::{Event, cancellable}; +use std::sync::Arc; + +/// An event that occurs when a world is loaded. +#[derive(Event, Clone)] +pub struct WorldLoadEvent { + /// The world that was loaded. + pub world: Arc, +} + +impl WorldLoadEvent { + #[must_use] + pub const fn new(world: Arc) -> Self { + Self { world } + } +} + +/// An event that occurs when a world is unloaded. +#[cancellable] +#[derive(Event, Clone)] +pub struct WorldUnloadEvent { + /// The world being unloaded. + pub world: Arc, +} + +impl WorldUnloadEvent { + #[must_use] + pub const fn new(world: Arc) -> Self { + Self { + world, + cancelled: false, + } + } +} diff --git a/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/context.rs b/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/context.rs index cb218a064..ba827d746 100644 --- a/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/context.rs +++ b/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/context.rs @@ -46,12 +46,15 @@ async fn register_player_event( event_type: EventType, ) { use crate::plugin::player::{ - changed_main_hand::PlayerChangedMainHandEvent, egg_throw::PlayerEggThrowEvent, - exp_change::PlayerExpChangeEvent, fish::PlayerFishEvent, item_held::PlayerItemHeldEvent, - player_change_world::PlayerChangeWorldEvent, player_chat::PlayerChatEvent, - player_command_send::PlayerCommandSendEvent, + bedrock_form_response::BedrockFormResponseEvent, + changed_main_hand::PlayerChangedMainHandEvent, custom_click_action::CustomClickActionEvent, + egg_throw::PlayerEggThrowEvent, exp_change::PlayerExpChangeEvent, fish::PlayerFishEvent, + inventory_close::InventoryCloseEvent, inventory_interact::InventoryClickEvent, + item_held::PlayerItemHeldEvent, player_change_world::PlayerChangeWorldEvent, + player_chat::PlayerChatEvent, player_command_send::PlayerCommandSendEvent, player_custom_payload::PlayerCustomPayloadEvent, player_gamemode_change::PlayerGamemodeChangeEvent, + player_interact_entity_event::PlayerInteractEntityEvent, player_interact_event::PlayerInteractEvent, player_interact_unknown_entity_event::PlayerInteractUnknownEntityEvent, player_join::PlayerJoinEvent, player_leave::PlayerLeaveEvent, @@ -136,6 +139,12 @@ async fn register_player_event( ) .await; } + EventType::PlayerInteractEntityEvent => { + register_typed_event::( + resource, handler, priority, blocking, + ) + .await; + } EventType::PlayerInteractEvent => { register_typed_event::(resource, handler, priority, blocking) .await; @@ -152,6 +161,64 @@ async fn register_player_event( register_typed_event::(resource, handler, priority, blocking) .await; } + EventType::InventoryClickEvent => { + register_typed_event::(resource, handler, priority, blocking) + .await; + } + EventType::InventoryCloseEvent => { + register_typed_event::(resource, handler, priority, blocking) + .await; + } + EventType::BedrockFormResponseEvent => { + register_typed_event::(resource, handler, priority, blocking) + .await; + } + EventType::CustomClickActionEvent => { + register_typed_event::(resource, handler, priority, blocking) + .await; + } + EventType::PlayerItemConsumeEvent => { + register_typed_event::< + crate::plugin::api::events::player::player_item_consume::PlayerItemConsumeEvent, + >(resource, handler, priority, blocking) + .await; + } + EventType::PlayerItemDamageEvent => { + register_typed_event::< + crate::plugin::api::events::player::player_item_damage::PlayerItemDamageEvent, + >(resource, handler, priority, blocking) + .await; + } + EventType::PlayerDropItemEvent => { + register_typed_event::< + crate::plugin::api::events::player::player_drop_item::PlayerDropItemEvent, + >(resource, handler, priority, blocking) + .await; + } + EventType::PlayerBedEnterEvent => { + register_typed_event::< + crate::plugin::api::events::player::player_bed::PlayerBedEnterEvent, + >(resource, handler, priority, blocking) + .await; + } + EventType::PlayerBedLeaveEvent => { + register_typed_event::< + crate::plugin::api::events::player::player_bed::PlayerBedLeaveEvent, + >(resource, handler, priority, blocking) + .await; + } + EventType::PlayerBucketEmptyEvent => { + register_typed_event::< + crate::plugin::api::events::player::player_bucket::PlayerBucketEmptyEvent, + >(resource, handler, priority, blocking) + .await; + } + EventType::PlayerBucketFillEvent => { + register_typed_event::< + crate::plugin::api::events::player::player_bucket::PlayerBucketFillEvent, + >(resource, handler, priority, blocking) + .await; + } _ => { tracing::error!("non-player event should not be routed to register_player_event"); } @@ -173,6 +240,78 @@ impl PluginHostState { } } +async fn register_entity_event( + resource: &ContextResource, + handler: &Arc, + priority: crate::plugin::EventPriority, + blocking: bool, + event_type: EventType, +) { + use crate::plugin::entity::{ + entity_combust::EntityCombustEvent, + entity_damage::EntityDamageEvent, + entity_death::{EntityDeathEvent, PlayerDeathEvent}, + entity_regain_health::EntityRegainHealthEvent, + entity_spawn::EntitySpawnEvent, + }; + + match event_type { + EventType::EntityDamageEvent => { + register_typed_event::(resource, handler, priority, blocking).await; + } + EventType::EntityDeathEvent => { + register_typed_event::(resource, handler, priority, blocking).await; + } + EventType::PlayerDeathEvent => { + register_typed_event::(resource, handler, priority, blocking).await; + } + EventType::EntitySpawnEvent => { + register_typed_event::(resource, handler, priority, blocking).await; + } + EventType::EntityCombustEvent => { + register_typed_event::(resource, handler, priority, blocking).await; + } + EventType::EntityRegainHealthEvent => { + register_typed_event::(resource, handler, priority, blocking) + .await; + } + _ => { + tracing::error!("non-entity event should not be routed to register_entity_event"); + } + } +} + +async fn register_inventory_event( + resource: &ContextResource, + handler: &Arc, + priority: crate::plugin::EventPriority, + blocking: bool, + event_type: EventType, +) { + use crate::plugin::inventory::{ + craft_item::CraftItemEvent, furnace_smelt::FurnaceSmeltEvent, + inventory_drag::InventoryDragEvent, inventory_open::InventoryOpenEvent, + }; + + match event_type { + EventType::InventoryOpenEvent => { + register_typed_event::(resource, handler, priority, blocking).await; + } + EventType::InventoryDragEvent => { + register_typed_event::(resource, handler, priority, blocking).await; + } + EventType::CraftItemEvent => { + register_typed_event::(resource, handler, priority, blocking).await; + } + EventType::FurnaceSmeltEvent => { + register_typed_event::(resource, handler, priority, blocking).await; + } + _ => { + tracing::error!("non-inventory event should not be routed to register_inventory_event"); + } + } +} + async fn register_world_event( resource: &ContextResource, handler: &Arc, @@ -180,12 +319,48 @@ async fn register_world_event( blocking: bool, event_type: EventType, ) { - use crate::plugin::world::spawn_change::SpawnChangeEvent; + use crate::plugin::world::{ + chunk_load::ChunkLoad, chunk_save::ChunkSave, chunk_send::ChunkSend, + spawn_change::SpawnChangeEvent, + }; match event_type { EventType::SpawnChangeEvent => { register_typed_event::(resource, handler, priority, blocking).await; } + EventType::ChunkLoadEvent => { + register_typed_event::(resource, handler, priority, blocking).await; + } + EventType::ChunkSaveEvent => { + register_typed_event::(resource, handler, priority, blocking).await; + } + EventType::ChunkSendEvent => { + register_typed_event::(resource, handler, priority, blocking).await; + } + EventType::WeatherChangeEvent => { + register_typed_event::< + crate::plugin::api::events::world::weather_change::WeatherChangeEvent, + >(resource, handler, priority, blocking) + .await; + } + EventType::ThunderChangeEvent => { + register_typed_event::< + crate::plugin::api::events::world::weather_change::ThunderChangeEvent, + >(resource, handler, priority, blocking) + .await; + } + EventType::WorldLoadEvent => { + register_typed_event::( + resource, handler, priority, blocking, + ) + .await; + } + EventType::WorldUnloadEvent => { + register_typed_event::< + crate::plugin::api::events::world::world_load::WorldUnloadEvent, + >(resource, handler, priority, blocking) + .await; + } _ => { tracing::error!("non-world event should not be routed to register_world_event"); } @@ -224,6 +399,37 @@ async fn register_block_event( EventType::BlockPlaceEvent => { register_typed_event::(resource, handler, priority, blocking).await; } + EventType::BlockDamageEvent => { + register_typed_event::< + crate::plugin::api::events::block::block_damage::BlockDamageEvent, + >(resource, handler, priority, blocking) + .await; + } + EventType::BlockIgniteEvent => { + register_typed_event::< + crate::plugin::api::events::block::block_ignite::BlockIgniteEvent, + >(resource, handler, priority, blocking) + .await; + } + EventType::BlockFromToEvent => { + register_typed_event::< + crate::plugin::api::events::block::block_from_to::BlockFromToEvent, + >(resource, handler, priority, blocking) + .await; + } + EventType::BlockFormEvent => { + register_typed_event::( + resource, handler, priority, blocking, + ) + .await; + } + EventType::BlockFadeEvent => { + register_typed_event::( + resource, handler, priority, blocking, + ) + .await; + } + _ => { tracing::error!("non-block event should not be routed to register_block_event"); } @@ -344,17 +550,43 @@ impl pumpkin::plugin::context::HostContext for PluginHostState { | EventType::ServerTickStartEvent) => { register_server_event(resource, &handler, priority, blocking, event_type).await; } - event_type @ EventType::SpawnChangeEvent => { + event_type @ (EventType::SpawnChangeEvent + | EventType::ChunkLoadEvent + | EventType::ChunkSaveEvent + | EventType::ChunkSendEvent + | EventType::WeatherChangeEvent + | EventType::ThunderChangeEvent + | EventType::WorldLoadEvent + | EventType::WorldUnloadEvent) => { register_world_event(resource, &handler, priority, blocking, event_type).await; } + event_type @ (EventType::EntityDamageEvent + | EventType::EntityDeathEvent + | EventType::PlayerDeathEvent + | EventType::EntitySpawnEvent + | EventType::EntityCombustEvent + | EventType::EntityRegainHealthEvent) => { + register_entity_event(resource, &handler, priority, blocking, event_type).await; + } event_type @ (EventType::BlockRedstoneEvent | EventType::BlockBreakEvent | EventType::BlockBurnEvent | EventType::BlockCanBuildEvent | EventType::BlockGrowEvent - | EventType::BlockPlaceEvent) => { + | EventType::BlockPlaceEvent + | EventType::BlockDamageEvent + | EventType::BlockIgniteEvent + | EventType::BlockFromToEvent + | EventType::BlockFormEvent + | EventType::BlockFadeEvent) => { register_block_event(resource, &handler, priority, blocking, event_type).await; } + event_type @ (EventType::InventoryOpenEvent + | EventType::InventoryDragEvent + | EventType::CraftItemEvent + | EventType::FurnaceSmeltEvent) => { + register_inventory_event(resource, &handler, priority, blocking, event_type).await; + } event_type => { register_player_event(resource, &handler, priority, blocking, event_type).await; } diff --git a/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/block.rs b/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/block.rs index dcc1dbe15..2b3d4cee0 100644 --- a/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/block.rs +++ b/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/block.rs @@ -15,7 +15,9 @@ use crate::plugin::{ }, pumpkin::plugin::event::{ BlockBreakEventData, BlockBurnEventData, BlockCanBuildEventData, - BlockGrowEventData, BlockPlaceEventData, BlockRedstoneEventData, Event, + BlockDamageEventData, BlockFadeEventData, BlockFormEventData, BlockFromToEventData, + BlockGrowEventData, BlockIgniteEventData, BlockPlaceEventData, + BlockRedstoneEventData, Event, }, }, }, @@ -198,3 +200,114 @@ impl ToFromWasmEvent for BlockPlaceEvent { } } } + +impl ToFromWasmEvent for crate::plugin::api::events::block::block_damage::BlockDamageEvent { + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let player = state + .add_player(self.player.clone()) + .expect("failed to add player resource"); + + Event::BlockDamageEvent(BlockDamageEventData { + player, + block_pos: to_wasm_block_position(self.block_pos), + insta_break: self.insta_break, + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::BlockDamageEvent(data) => Self { + player: consume_player(state, &data.player), + block: &pumpkin_data::Block::AIR, + block_pos: from_wasm_block_position(data.block_pos), + insta_break: data.insta_break, + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for crate::plugin::api::events::block::block_ignite::BlockIgniteEvent { + fn to_wasm_event(&self, _state: &mut PluginHostState) -> Event { + Event::BlockIgniteEvent(BlockIgniteEventData { + block_pos: to_wasm_block_position(self.block_pos), + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, _state: &mut PluginHostState) -> Self { + match event { + Event::BlockIgniteEvent(data) => Self { + block_pos: from_wasm_block_position(data.block_pos), + igniting_block: &pumpkin_data::Block::FIRE, + player: None, + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for crate::plugin::api::events::block::block_from_to::BlockFromToEvent { + fn to_wasm_event(&self, _state: &mut PluginHostState) -> Event { + Event::BlockFromToEvent(BlockFromToEventData { + from_pos: to_wasm_block_position(self.from_pos), + to_pos: to_wasm_block_position(self.to_pos), + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, _state: &mut PluginHostState) -> Self { + match event { + Event::BlockFromToEvent(data) => Self { + from_pos: from_wasm_block_position(data.from_pos), + to_pos: from_wasm_block_position(data.to_pos), + block: &pumpkin_data::Block::WATER, + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for crate::plugin::api::events::block::block_form::BlockFormEvent { + fn to_wasm_event(&self, _state: &mut PluginHostState) -> Event { + Event::BlockFormEvent(BlockFormEventData { + block_pos: to_wasm_block_position(self.block_pos), + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, _state: &mut PluginHostState) -> Self { + match event { + Event::BlockFormEvent(data) => Self { + block_pos: from_wasm_block_position(data.block_pos), + block: &pumpkin_data::Block::SNOW, + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for crate::plugin::api::events::block::block_fade::BlockFadeEvent { + fn to_wasm_event(&self, _state: &mut PluginHostState) -> Event { + Event::BlockFadeEvent(BlockFadeEventData { + block_pos: to_wasm_block_position(self.block_pos), + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, _state: &mut PluginHostState) -> Self { + match event { + Event::BlockFadeEvent(data) => Self { + block_pos: from_wasm_block_position(data.block_pos), + block: &pumpkin_data::Block::ICE, + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} diff --git a/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/entity.rs b/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/entity.rs new file mode 100644 index 000000000..f268d25f2 --- /dev/null +++ b/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/entity.rs @@ -0,0 +1,174 @@ +use crate::plugin::{ + entity::{ + entity_combust::EntityCombustEvent, + entity_damage::EntityDamageEvent, + entity_death::{EntityDeathEvent, PlayerDeathEvent}, + entity_regain_health::EntityRegainHealthEvent, + entity_spawn::EntitySpawnEvent, + }, + loader::wasm::wasm_host::{ + state::PluginHostState, + wit::v0_1::{ + events::{ + ToFromWasmEvent, consume_player, consume_text_component, consume_world, + to_wasm_position, + }, + pumpkin::plugin::event::{ + EntityCombustEventData, EntityDamageEventData, EntityDeathEventData, + EntityRegainHealthEventData, EntitySpawnEventData, Event, PlayerDeathEventData, + }, + }, + }, +}; + +impl ToFromWasmEvent for EntityDamageEvent { + fn to_wasm_event(&self, _state: &mut PluginHostState) -> Event { + Event::EntityDamageEvent(EntityDamageEventData { + entity_id: self.entity_id, + damage: self.damage, + cause: self.cause.clone(), + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, _state: &mut PluginHostState) -> Self { + match event { + Event::EntityDamageEvent(data) => Self { + entity_id: data.entity_id, + damage: data.damage, + cause: data.cause, + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for EntityDeathEvent { + fn to_wasm_event(&self, _state: &mut PluginHostState) -> Event { + Event::EntityDeathEvent(EntityDeathEventData { + entity_id: self.entity_id, + dropped_exp: self.dropped_exp, + }) + } + + fn from_wasm_event(event: Event, _state: &mut PluginHostState) -> Self { + match event { + Event::EntityDeathEvent(data) => Self { + entity_id: data.entity_id, + dropped_exp: data.dropped_exp, + }, + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for PlayerDeathEvent { + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let player = state + .add_player(self.player.clone()) + .expect("failed to add player resource"); + let death_message = state + .add_text_component(self.death_message.clone()) + .expect("failed to add text component resource"); + + Event::PlayerDeathEvent(PlayerDeathEventData { + player, + death_message, + dropped_exp: self.dropped_exp, + keep_inventory: self.keep_inventory, + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::PlayerDeathEvent(data) => Self { + player: consume_player(state, &data.player), + death_message: consume_text_component(state, &data.death_message), + dropped_exp: data.dropped_exp, + keep_inventory: data.keep_inventory, + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for EntitySpawnEvent { + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let target_world = state + .add_world(self.world.clone()) + .expect("failed to add world resource"); + + Event::EntitySpawnEvent(EntitySpawnEventData { + entity_id: self.entity_id, + entity_type: self.entity_type.clone(), + position: to_wasm_position(self.position), + target_world, + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::EntitySpawnEvent(data) => { + let world = consume_world(state, &data.target_world); + Self { + entity_id: data.entity_id, + entity_type: data.entity_type, + position: pumpkin_util::math::vector3::Vector3::new( + data.position.0, + data.position.1, + data.position.2, + ), + world, + cancelled: data.cancelled, + } + } + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for EntityCombustEvent { + fn to_wasm_event(&self, _state: &mut PluginHostState) -> Event { + Event::EntityCombustEvent(EntityCombustEventData { + entity_id: self.entity_id, + duration_secs: self.duration_secs, + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, _state: &mut PluginHostState) -> Self { + match event { + Event::EntityCombustEvent(data) => Self { + entity_id: data.entity_id, + duration_secs: data.duration_secs, + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for EntityRegainHealthEvent { + fn to_wasm_event(&self, _state: &mut PluginHostState) -> Event { + Event::EntityRegainHealthEvent(EntityRegainHealthEventData { + entity_id: self.entity_id, + amount: self.amount, + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, _state: &mut PluginHostState) -> Self { + match event { + Event::EntityRegainHealthEvent(data) => Self { + entity_id: data.entity_id, + amount: data.amount, + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} diff --git a/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/inventory.rs b/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/inventory.rs new file mode 100644 index 000000000..8216133e5 --- /dev/null +++ b/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/inventory.rs @@ -0,0 +1,112 @@ +use crate::plugin::{ + inventory::{ + craft_item::CraftItemEvent, furnace_smelt::FurnaceSmeltEvent, + inventory_drag::InventoryDragEvent, inventory_open::InventoryOpenEvent, + }, + loader::wasm::wasm_host::{ + state::PluginHostState, + wit::v0_1::{ + events::{ + ToFromWasmEvent, consume_player, from_wasm_block_position, to_wasm_block_position, + }, + pumpkin::plugin::event::{ + CraftItemEventData, Event, FurnaceSmeltEventData, InventoryDragEventData, + InventoryOpenEventData, + }, + }, + }, +}; + +impl ToFromWasmEvent for InventoryOpenEvent { + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let player = state + .add_player(self.player.clone()) + .expect("failed to add player resource"); + + Event::InventoryOpenEvent(InventoryOpenEventData { + player, + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::InventoryOpenEvent(data) => Self { + player: consume_player(state, &data.player), + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for InventoryDragEvent { + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let player = state + .add_player(self.player.clone()) + .expect("failed to add player resource"); + + Event::InventoryDragEvent(InventoryDragEventData { + player, + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::InventoryDragEvent(data) => Self { + player: consume_player(state, &data.player), + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for CraftItemEvent { + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let player = state + .add_player(self.player.clone()) + .expect("failed to add player resource"); + + Event::CraftItemEvent(CraftItemEventData { + player, + recipe_id: self.recipe_id.clone(), + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::CraftItemEvent(data) => Self { + player: consume_player(state, &data.player), + recipe_id: data.recipe_id, + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for FurnaceSmeltEvent { + fn to_wasm_event(&self, _state: &mut PluginHostState) -> Event { + Event::FurnaceSmeltEvent(FurnaceSmeltEventData { + block_pos: to_wasm_block_position(self.block_pos), + source_item: self.source_item.clone(), + result_item: self.result_item.clone(), + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, _state: &mut PluginHostState) -> Self { + match event { + Event::FurnaceSmeltEvent(data) => Self { + block_pos: from_wasm_block_position(data.block_pos), + source_item: data.source_item, + result_item: data.result_item, + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} diff --git a/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/mod.rs b/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/mod.rs index a53474b8e..2fec18664 100644 --- a/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/mod.rs +++ b/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/mod.rs @@ -24,6 +24,8 @@ use crate::{ }; pub mod block; +pub mod entity; +pub mod inventory; pub mod player; pub mod server; pub mod world; diff --git a/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/player.rs b/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/player.rs index c54d0aed4..c060f5214 100644 --- a/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/player.rs +++ b/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/player.rs @@ -14,12 +14,15 @@ use crate::plugin::{ pumpkin::plugin::event::{ BedrockFormResponseEventData, CustomClickActionEventData, Event, InteractAction as WasmInteractAction, InventoryClickEventData, - InventoryCloseEventData, PlayerChangeWorldEventData, + InventoryCloseEventData, PlayerBedEnterEventData, PlayerBedLeaveEventData, + PlayerBucketEmptyEventData, PlayerBucketFillEventData, PlayerChangeWorldEventData, PlayerChangedMainHandEventData, PlayerChatEventData, PlayerCommandSendEventData, - PlayerCustomPayloadEventData, PlayerEggThrowEventData, PlayerExpChangeEventData, - PlayerFishEventData, PlayerFishState as WasmPlayerFishState, - PlayerGamemodeChangeEventData, PlayerInteractEventData, - PlayerInteractUnknownEntityEventData, PlayerItemHeldEventData, PlayerJoinEventData, + PlayerCustomPayloadEventData, PlayerDropItemEventData, PlayerEggThrowEventData, + PlayerExpChangeEventData, PlayerFishEventData, + PlayerFishState as WasmPlayerFishState, PlayerGamemodeChangeEventData, + PlayerInteractEntityEventData, PlayerInteractEventData, + PlayerInteractUnknownEntityEventData, PlayerItemConsumeEventData, + PlayerItemDamageEventData, PlayerItemHeldEventData, PlayerJoinEventData, PlayerLeaveEventData, PlayerLoginEventData, PlayerMoveEventData, PlayerPermissionCheckEventData, PlayerRespawnEventData, PlayerTeleportEventData, PlayerToggleFlightEventData, PlayerToggleSneakEventData, @@ -43,6 +46,7 @@ use crate::plugin::{ player_command_send::PlayerCommandSendEvent, player_custom_payload::PlayerCustomPayloadEvent, player_gamemode_change::PlayerGamemodeChangeEvent, + player_interact_entity_event::PlayerInteractEntityEvent, player_interact_event::{InteractAction, PlayerInteractEvent}, player_interact_unknown_entity_event::PlayerInteractUnknownEntityEvent, player_join::PlayerJoinEvent, @@ -848,3 +852,225 @@ impl ToFromWasmEvent for CustomClickActionEvent { } } } + +impl ToFromWasmEvent for PlayerInteractEntityEvent { + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let player = state + .add_player(self.player.clone()) + .expect("failed to add player resource"); + + Event::PlayerInteractEntityEvent(PlayerInteractEntityEventData { + player, + entity_id: self.target.get_entity().entity_id, + action: to_wasm_entity_interaction_action(&self.action), + sneaking: self.sneaking, + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::PlayerInteractEntityEvent(data) => { + let player = consume_player(state, &data.player); + let target = player + .world() + .get_entity_by_id(data.entity_id) + .expect("entity not found"); + Self { + player, + target, + action: from_wasm_entity_interaction_action(data.action), + target_position: None, + sneaking: data.sneaking, + cancelled: data.cancelled, + } + } + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent + for crate::plugin::api::events::player::player_item_consume::PlayerItemConsumeEvent +{ + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let player = state + .add_player(self.player.clone()) + .expect("failed to add player resource"); + + Event::PlayerItemConsumeEvent(PlayerItemConsumeEventData { + player, + item_name: self.item_name.clone(), + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::PlayerItemConsumeEvent(data) => Self { + player: consume_player(state, &data.player), + item_name: data.item_name, + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent + for crate::plugin::api::events::player::player_item_damage::PlayerItemDamageEvent +{ + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let player = state + .add_player(self.player.clone()) + .expect("failed to add player resource"); + + Event::PlayerItemDamageEvent(PlayerItemDamageEventData { + player, + item_name: self.item_name.clone(), + damage: self.damage, + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::PlayerItemDamageEvent(data) => Self { + player: consume_player(state, &data.player), + item_name: data.item_name, + damage: data.damage, + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for crate::plugin::api::events::player::player_drop_item::PlayerDropItemEvent { + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let player = state + .add_player(self.player.clone()) + .expect("failed to add player resource"); + + Event::PlayerDropItemEvent(PlayerDropItemEventData { + player, + item_name: self.item_name.clone(), + count: self.count, + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::PlayerDropItemEvent(data) => Self { + player: consume_player(state, &data.player), + item_name: data.item_name, + count: data.count, + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for crate::plugin::api::events::player::player_bed::PlayerBedEnterEvent { + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let player = state + .add_player(self.player.clone()) + .expect("failed to add player resource"); + + Event::PlayerBedEnterEvent(PlayerBedEnterEventData { + player, + bed_pos: to_wasm_block_position(self.bed_pos), + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::PlayerBedEnterEvent(data) => Self { + player: consume_player(state, &data.player), + bed_pos: from_wasm_block_position(data.bed_pos), + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for crate::plugin::api::events::player::player_bed::PlayerBedLeaveEvent { + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let player = state + .add_player(self.player.clone()) + .expect("failed to add player resource"); + + Event::PlayerBedLeaveEvent(PlayerBedLeaveEventData { + player, + bed_pos: to_wasm_block_position(self.bed_pos), + }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::PlayerBedLeaveEvent(data) => Self { + player: consume_player(state, &data.player), + bed_pos: from_wasm_block_position(data.bed_pos), + }, + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for crate::plugin::api::events::player::player_bucket::PlayerBucketEmptyEvent { + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let player = state + .add_player(self.player.clone()) + .expect("failed to add player resource"); + + Event::PlayerBucketEmptyEvent(PlayerBucketEmptyEventData { + player, + block_pos: to_wasm_block_position(self.block_pos), + bucket: self.bucket.clone(), + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::PlayerBucketEmptyEvent(data) => Self { + player: consume_player(state, &data.player), + block_pos: from_wasm_block_position(data.block_pos), + bucket: data.bucket, + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for crate::plugin::api::events::player::player_bucket::PlayerBucketFillEvent { + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let player = state + .add_player(self.player.clone()) + .expect("failed to add player resource"); + + Event::PlayerBucketFillEvent(PlayerBucketFillEventData { + player, + block_pos: to_wasm_block_position(self.block_pos), + bucket: self.bucket.clone(), + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::PlayerBucketFillEvent(data) => Self { + player: consume_player(state, &data.player), + block_pos: from_wasm_block_position(data.block_pos), + bucket: data.bucket, + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} diff --git a/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/world.rs b/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/world.rs index 0a003b133..321a63821 100644 --- a/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/world.rs +++ b/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/events/world.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use crate::plugin::{ loader::wasm::wasm_host::{ state::PluginHostState, @@ -5,10 +7,17 @@ use crate::plugin::{ events::{ ToFromWasmEvent, consume_world, from_wasm_block_position, to_wasm_block_position, }, - pumpkin::plugin::event::{Event, SpawnChangeEventData}, + pumpkin::plugin::event::{ + ChunkLoadEventData, ChunkSaveEventData, ChunkSendEventData, Event, + SpawnChangeEventData, ThunderChangeEventData, WeatherChangeEventData, + WorldLoadEventData, WorldUnloadEventData, + }, }, }, - world::spawn_change::SpawnChangeEvent, + world::{ + chunk_load::ChunkLoad, chunk_save::ChunkSave, chunk_send::ChunkSend, + spawn_change::SpawnChangeEvent, + }, }; impl ToFromWasmEvent for SpawnChangeEvent { @@ -43,3 +52,241 @@ impl ToFromWasmEvent for SpawnChangeEvent { } } } + +impl ToFromWasmEvent for ChunkLoad { + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let target_world = state + .add_world(self.world.clone()) + .expect("failed to add world resource"); + + let guard = self.chunk.blocking_read(); + Event::ChunkLoadEvent(ChunkLoadEventData { + target_world, + chunk_x: guard.x, + chunk_z: guard.z, + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::ChunkLoadEvent(data) => { + let world = consume_world(state, &data.target_world); + let chunk_data = pumpkin_world::chunk::ChunkData { + section: pumpkin_world::chunk::ChunkSections::new(24, -64), + heightmap: std::sync::Mutex::new( + pumpkin_world::chunk::ChunkHeightmaps::default(), + ), + x: data.chunk_x, + z: data.chunk_z, + block_ticks: pumpkin_world::tick::scheduler::ChunkTickScheduler::default(), + fluid_ticks: pumpkin_world::tick::scheduler::ChunkTickScheduler::default(), + pending_block_entities: std::sync::Mutex::new( + std::collections::HashMap::default(), + ), + light_engine: std::sync::Mutex::new(pumpkin_world::chunk::ChunkLight::default()), + light_populated: std::sync::atomic::AtomicBool::new(false), + status: pumpkin_data::chunk::ChunkStatus::Empty, + blending_data: None, + dirty: std::sync::atomic::AtomicBool::new(false), + inhabited_time: std::sync::atomic::AtomicU64::new(0), + }; + Self { + world, + chunk: Arc::new(tokio::sync::RwLock::new(chunk_data)), + cancelled: data.cancelled, + } + } + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for ChunkSave { + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let target_world = state + .add_world(self.world.clone()) + .expect("failed to add world resource"); + + let guard = self.chunk.blocking_read(); + Event::ChunkSaveEvent(ChunkSaveEventData { + target_world, + chunk_x: guard.x, + chunk_z: guard.z, + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::ChunkSaveEvent(data) => { + let world = consume_world(state, &data.target_world); + let chunk_data = pumpkin_world::chunk::ChunkData { + section: pumpkin_world::chunk::ChunkSections::new(24, -64), + heightmap: std::sync::Mutex::new( + pumpkin_world::chunk::ChunkHeightmaps::default(), + ), + x: data.chunk_x, + z: data.chunk_z, + block_ticks: pumpkin_world::tick::scheduler::ChunkTickScheduler::default(), + fluid_ticks: pumpkin_world::tick::scheduler::ChunkTickScheduler::default(), + pending_block_entities: std::sync::Mutex::new( + std::collections::HashMap::default(), + ), + light_engine: std::sync::Mutex::new(pumpkin_world::chunk::ChunkLight::default()), + light_populated: std::sync::atomic::AtomicBool::new(false), + status: pumpkin_data::chunk::ChunkStatus::Empty, + blending_data: None, + dirty: std::sync::atomic::AtomicBool::new(false), + inhabited_time: std::sync::atomic::AtomicU64::new(0), + }; + Self { + world, + chunk: Arc::new(tokio::sync::RwLock::new(chunk_data)), + cancelled: data.cancelled, + } + } + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for ChunkSend { + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let target_world = state + .add_world(self.world.clone()) + .expect("failed to add world resource"); + + Event::ChunkSendEvent(ChunkSendEventData { + target_world, + chunk_x: self.chunk.x, + chunk_z: self.chunk.z, + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::ChunkSendEvent(data) => { + let world = consume_world(state, &data.target_world); + let chunk_data = pumpkin_world::chunk::ChunkData { + section: pumpkin_world::chunk::ChunkSections::new(24, -64), + heightmap: std::sync::Mutex::new( + pumpkin_world::chunk::ChunkHeightmaps::default(), + ), + x: data.chunk_x, + z: data.chunk_z, + block_ticks: pumpkin_world::tick::scheduler::ChunkTickScheduler::default(), + fluid_ticks: pumpkin_world::tick::scheduler::ChunkTickScheduler::default(), + pending_block_entities: std::sync::Mutex::new( + std::collections::HashMap::default(), + ), + light_engine: std::sync::Mutex::new(pumpkin_world::chunk::ChunkLight::default()), + light_populated: std::sync::atomic::AtomicBool::new(false), + status: pumpkin_data::chunk::ChunkStatus::Empty, + blending_data: None, + dirty: std::sync::atomic::AtomicBool::new(false), + inhabited_time: std::sync::atomic::AtomicU64::new(0), + }; + Self { + world, + chunk: Arc::new(chunk_data), + cancelled: data.cancelled, + } + } + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for crate::plugin::api::events::world::weather_change::WeatherChangeEvent { + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let target_world = state + .add_world(self.world.clone()) + .expect("failed to add world resource"); + + Event::WeatherChangeEvent(WeatherChangeEventData { + target_world, + to_weather_state: self.to_weather_state, + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::WeatherChangeEvent(data) => Self { + world: consume_world(state, &data.target_world), + to_weather_state: data.to_weather_state, + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for crate::plugin::api::events::world::weather_change::ThunderChangeEvent { + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let target_world = state + .add_world(self.world.clone()) + .expect("failed to add world resource"); + + Event::ThunderChangeEvent(ThunderChangeEventData { + target_world, + to_thunder_state: self.to_thunder_state, + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::ThunderChangeEvent(data) => Self { + world: consume_world(state, &data.target_world), + to_thunder_state: data.to_thunder_state, + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for crate::plugin::api::events::world::world_load::WorldLoadEvent { + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let target_world = state + .add_world(self.world.clone()) + .expect("failed to add world resource"); + + Event::WorldLoadEvent(WorldLoadEventData { target_world }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::WorldLoadEvent(data) => Self { + world: consume_world(state, &data.target_world), + }, + _ => panic!("unexpected event type"), + } + } +} + +impl ToFromWasmEvent for crate::plugin::api::events::world::world_load::WorldUnloadEvent { + fn to_wasm_event(&self, state: &mut PluginHostState) -> Event { + let target_world = state + .add_world(self.world.clone()) + .expect("failed to add world resource"); + + Event::WorldUnloadEvent(WorldUnloadEventData { + target_world, + cancelled: self.cancelled, + }) + } + + fn from_wasm_event(event: Event, state: &mut PluginHostState) -> Self { + match event { + Event::WorldUnloadEvent(data) => Self { + world: consume_world(state, &data.target_world), + cancelled: data.cancelled, + }, + _ => panic!("unexpected event type"), + } + } +} diff --git a/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/generated_packets.rs b/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/generated_packets.rs index d31459b64..bd93df64b 100644 --- a/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/generated_packets.rs +++ b/pumpkin/src/plugin/loader/wasm/wasm_host/wit/v0_1/generated_packets.rs @@ -205,6 +205,16 @@ pub fn serialize_java_packet( crate::net::java::JavaClient::write_packet_for_version(&p, version, &mut buf).unwrap(); Some(buf.into()) } + ClientboundPacket::CDebugSample(data) => { + let sample_vec: Vec = data.sample.iter().map(|v| *v as i64).collect(); + let p = pumpkin_protocol::java::client::play::CDebugSample { + sample: &sample_vec, + sample_type: VarInt(data.sample_type), + }; + let mut buf = Vec::new(); + crate::net::java::JavaClient::write_packet_for_version(&p, version, &mut buf).unwrap(); + Some(buf.into()) + } ClientboundPacket::CPlayDisconnect(data) => { let component_reason = pumpkin_util::text::TextComponent::text(data.reason.clone()); let p = pumpkin_protocol::java::client::play::CPlayDisconnect { @@ -525,6 +535,15 @@ pub fn serialize_java_packet( crate::net::java::JavaClient::write_packet_for_version(&p, version, &mut buf).unwrap(); Some(buf.into()) } + ClientboundPacket::CSetEntityLink(data) => { + let p = pumpkin_protocol::java::client::play::CSetEntityLink { + attached_entity_id: data.attached_entity_id.try_into().unwrap(), + holding_entity_id: data.holding_entity_id.try_into().unwrap(), + }; + let mut buf = Vec::new(); + crate::net::java::JavaClient::write_packet_for_version(&p, version, &mut buf).unwrap(); + Some(buf.into()) + } ClientboundPacket::CSetExperience(data) => { let p = pumpkin_protocol::java::client::play::CSetExperience { progress: data.progress.try_into().unwrap(), @@ -767,11 +786,12 @@ pub fn deserialize_java_serverbound_packet( keep_alive_id: p.keep_alive_id.try_into().unwrap(), })) } - id if id == pumpkin_protocol::java::server::config::SKnownPacks::to_id(version) => { + id if id == pumpkin_protocol::java::server::config::SPluginMessage::to_id(version) => { use pumpkin_protocol::ServerPacket; - let p = ::read(&mut payload, &version).ok()?; - Some(ServerboundPacket::ConfigSKnownPacks(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::java_packets::ConfigSKnownPacks { - known_pack_count: p.known_packs.len().try_into().unwrap(), + let p = ::read(&mut payload, &version).ok()?; + Some(ServerboundPacket::ConfigSPluginMessage(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::java_packets::ConfigSPluginMessage { + channel: p.channel.into(), + data: p.data.iter().map(|v| *v as _).collect(), })) } id if id == pumpkin_protocol::java::server::config::SConfigResourcePack::to_id(version) => { @@ -864,6 +884,32 @@ pub fn deserialize_java_serverbound_packet( button_id: p.button_id.0.try_into().unwrap(), })) } + id if id == pumpkin_protocol::java::server::play::SCustomPayload::to_id(version) => { + use pumpkin_protocol::ServerPacket; + let p = ::read(&mut payload, &version).ok()?; + Some(ServerboundPacket::SCustomPayload(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::java_packets::SCustomPayload { + channel: p.channel.into(), + data: p.data.iter().map(|v| *v as _).collect(), + })) + } + id if id + == pumpkin_protocol::java::server::play::SDebugSampleSubscription::to_id(version) => + { + use pumpkin_protocol::ServerPacket; + let p = ::read(&mut payload, &version).ok()?; + Some(ServerboundPacket::SDebugSampleSubscription(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::java_packets::SDebugSampleSubscription { + sample_type: p.sample_type.0.try_into().unwrap(), + })) + } + id if id + == pumpkin_protocol::java::server::play::SDebugSubscriptionRequest::to_id(version) => + { + use pumpkin_protocol::ServerPacket; + let p = ::read(&mut payload, &version).ok()?; + Some(ServerboundPacket::SDebugSubscriptionRequest(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::java_packets::SDebugSubscriptionRequest { + sample_type: p.sample_type.0.try_into().unwrap(), + })) + } id if id == pumpkin_protocol::java::server::play::SJigsawGenerate::to_id(version) => { use pumpkin_protocol::ServerPacket; let p = ::read(&mut payload, &version).ok()?; @@ -911,7 +957,7 @@ pub fn deserialize_java_serverbound_packet( use pumpkin_protocol::ServerPacket; let p = ::read(&mut payload, &version).ok()?; Some(ServerboundPacket::SPickItemFromEntity(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::java_packets::SPickItemFromEntity { - id: p.id.0, + id: p.id.0.try_into().unwrap(), include_data: p.include_data.try_into().unwrap(), })) } @@ -1076,6 +1122,18 @@ pub fn deserialize_java_serverbound_packet( target: crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::uuid::Uuid { high: p.target.as_u64_pair().1, low: p.target.as_u64_pair().0 }, })) } + id if id == pumpkin_protocol::java::server::play::SUpdateSign::to_id(version) => { + use pumpkin_protocol::ServerPacket; + let p = ::read(&mut payload, &version).ok()?; + Some(ServerboundPacket::SUpdateSign(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::java_packets::SUpdateSign { + location: (p.location.0.x, p.location.0.y, p.location.0.z), + is_front_text: p.is_front_text.try_into().unwrap(), + line_1: p.line_1.into(), + line_2: p.line_2.into(), + line_3: p.line_3.into(), + line_4: p.line_4.into(), + })) + } id if id == pumpkin_protocol::java::server::play::SUseItem::to_id(version) => { use pumpkin_protocol::ServerPacket; let p = ::read(&mut payload, &version).ok()?; @@ -1283,6 +1341,15 @@ impl ToWitClientboundJava for pumpkin_protocol::java::client::play::CCustomPaylo } } +impl ToWitClientboundJava for pumpkin_protocol::java::client::play::CDebugSample<'_> { + fn to_wit(&self) -> ClientboundPacket { + ClientboundPacket::CDebugSample(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::java_packets::CDebugSample { + sample: self.sample.iter().map(|v| *v as _).collect(), + sample_type: self.sample_type.0.try_into().unwrap(), + }) + } +} + impl ToWitClientboundJava for pumpkin_protocol::java::client::play::CPlayDisconnect<'_> { fn to_wit(&self) -> ClientboundPacket { ClientboundPacket::CPlayDisconnect(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::java_packets::CPlayDisconnect { @@ -1557,6 +1624,15 @@ impl ToWitClientboundJava for pumpkin_protocol::java::client::play::CSetContaine } } +impl ToWitClientboundJava for pumpkin_protocol::java::client::play::CSetEntityLink { + fn to_wit(&self) -> ClientboundPacket { + ClientboundPacket::CSetEntityLink(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::java_packets::CSetEntityLink { + attached_entity_id: self.attached_entity_id.try_into().unwrap(), + holding_entity_id: self.holding_entity_id.try_into().unwrap(), + }) + } +} + impl ToWitClientboundJava for pumpkin_protocol::java::client::play::CSetExperience { fn to_wit(&self) -> ClientboundPacket { ClientboundPacket::CSetExperience(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::java_packets::CSetExperience { @@ -1814,6 +1890,9 @@ pub fn clientbound_java_any_to_wit(any: &dyn Any) -> Option { if let Some(p) = any.downcast_ref::() { return Some(p.to_wit()); } + if let Some(p) = any.downcast_ref::() { + return Some(p.to_wit()); + } if let Some(p) = any.downcast_ref::() { return Some(p.to_wit()); } @@ -1911,6 +1990,9 @@ pub fn clientbound_java_any_to_wit(any: &dyn Any) -> Option { { return Some(p.to_wit()); } + if let Some(p) = any.downcast_ref::() { + return Some(p.to_wit()); + } if let Some(p) = any.downcast_ref::() { return Some(p.to_wit()); } @@ -1983,6 +2065,21 @@ use crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::bedrock_ #[must_use] pub fn serialize_bedrock_packet(packet: &BClientboundPacket) -> Option { match packet { + BClientboundPacket::CChangeDimension(data) => { + let p = pumpkin_protocol::bedrock::client::CChangeDimension { + dimension: VarInt(data.dimension), + position: pumpkin_util::math::vector3::Vector3::new( + data.position.0 as _, + data.position.1 as _, + data.position.2 as _, + ), + respawn: data.respawn.try_into().unwrap(), + has_loading_screen_id: data.has_loading_screen_id.try_into().unwrap(), + }; + let mut buf = Vec::new(); + crate::net::bedrock::BedrockClient::write_raw_packet(&p, &mut buf).unwrap(); + Some(buf.into()) + } BClientboundPacket::CChunkRadiusUpdate(data) => { let p = pumpkin_protocol::bedrock::client::CChunkRadiusUpdate { chunk_radius: VarInt(data.chunk_radius), @@ -2053,6 +2150,25 @@ pub fn serialize_bedrock_packet(packet: &BClientboundPacket) -> Option { crate::net::bedrock::BedrockClient::write_raw_packet(&p, &mut buf).unwrap(); Some(buf.into()) } + BClientboundPacket::CLevelSoundEvent(data) => { + let p = pumpkin_protocol::bedrock::client::CLevelSoundEvent { + sound_id: pumpkin_protocol::codec::var_uint::VarUInt( + data.sound_id.try_into().unwrap(), + ), + position: pumpkin_util::math::vector3::Vector3::new( + data.position.0 as _, + data.position.1 as _, + data.position.2 as _, + ), + extra_data: VarInt(data.extra_data), + entity_type: data.entity_type.clone(), + is_baby_mob: data.is_baby_mob.try_into().unwrap(), + is_global: data.is_global.try_into().unwrap(), + }; + let mut buf = Vec::new(); + crate::net::bedrock::BedrockClient::write_raw_packet(&p, &mut buf).unwrap(); + Some(buf.into()) + } BClientboundPacket::CModalFormRequest(data) => { let p = pumpkin_protocol::bedrock::client::CModalFormRequest { form_id: VarInt(data.form_id), @@ -2211,6 +2327,16 @@ pub fn serialize_bedrock_packet(packet: &BClientboundPacket) -> Option { crate::net::bedrock::BedrockClient::write_raw_packet(&p, &mut buf).unwrap(); Some(buf.into()) } + BClientboundPacket::CSetDifficulty(data) => { + let p = pumpkin_protocol::bedrock::client::CSetDifficulty { + difficulty: pumpkin_protocol::codec::var_uint::VarUInt( + data.difficulty.try_into().unwrap(), + ), + }; + let mut buf = Vec::new(); + crate::net::bedrock::BedrockClient::write_raw_packet(&p, &mut buf).unwrap(); + Some(buf.into()) + } BClientboundPacket::CSetHealth(data) => { let p = pumpkin_protocol::bedrock::client::CSetHealth { health: VarInt(data.health), @@ -2219,6 +2345,25 @@ pub fn serialize_bedrock_packet(packet: &BClientboundPacket) -> Option { crate::net::bedrock::BedrockClient::write_raw_packet(&p, &mut buf).unwrap(); Some(buf.into()) } + BClientboundPacket::CSetSpawnPosition(data) => { + let p = pumpkin_protocol::bedrock::client::CSetSpawnPosition { + spawn_type: VarInt(data.spawn_type), + position: pumpkin_util::math::position::BlockPos::new( + data.position.0, + data.position.1, + data.position.2, + ), + dimension: VarInt(data.dimension), + spawn_position: pumpkin_util::math::position::BlockPos::new( + data.spawn_position.0, + data.spawn_position.1, + data.spawn_position.2, + ), + }; + let mut buf = Vec::new(); + crate::net::bedrock::BedrockClient::write_raw_packet(&p, &mut buf).unwrap(); + Some(buf.into()) + } BClientboundPacket::CSetTime(data) => { let p = pumpkin_protocol::bedrock::client::CSetTime { time: VarInt(data.time), @@ -2242,6 +2387,17 @@ pub fn serialize_bedrock_packet(packet: &BClientboundPacket) -> Option { crate::net::bedrock::BedrockClient::write_raw_packet(&p, &mut buf).unwrap(); Some(buf.into()) } + BClientboundPacket::CShowCredits(data) => { + let p = pumpkin_protocol::bedrock::client::CShowCredits { + player_runtime_id: pumpkin_protocol::codec::var_ulong::VarULong( + data.player_runtime_id.try_into().unwrap(), + ), + status: VarInt(data.status), + }; + let mut buf = Vec::new(); + crate::net::bedrock::BedrockClient::write_raw_packet(&p, &mut buf).unwrap(); + Some(buf.into()) + } BClientboundPacket::CTakeItemActor(data) => { let p = pumpkin_protocol::bedrock::client::CTakeItemActor { item_runtime_id: pumpkin_protocol::codec::var_ulong::VarULong( @@ -2308,19 +2464,6 @@ pub fn deserialize_bedrock_serverbound_packet( cache_supported: p.cache_supported.try_into().unwrap(), })) } - id if id == ::PACKET_ID as i32 => { - use pumpkin_protocol::BServerPacket; - let p = ::read(&mut Cursor::new(payload)).ok()?; - Some(BServerboundPacket::SCommandRequest(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::bedrock_packets::SCommandRequest { - command: p.command.into(), - command_type: p.command_type.into(), - command_uuid: crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::uuid::Uuid { high: p.command_uuid.as_u64_pair().1, low: p.command_uuid.as_u64_pair().0 }, - request_id: p.request_id.into(), - player_actor_unique_id: p.player_actor_unique_id.try_into().unwrap(), - is_internal_source: p.is_internal_source.try_into().unwrap(), - version: p.version.into(), - })) - } id if id == ::PACKET_ID as i32 => { use pumpkin_protocol::BServerPacket; let p = ::read(&mut Cursor::new(payload)).ok()?; @@ -2330,16 +2473,13 @@ pub fn deserialize_bedrock_serverbound_packet( server_initiated: p.server_initiated.try_into().unwrap(), })) } - id if id == ::PACKET_ID as i32 => { + id if id == ::PACKET_ID as i32 => { use pumpkin_protocol::BServerPacket; - let p = ::read(&mut Cursor::new(payload)).ok()?; - Some(BServerboundPacket::SEmote(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::bedrock_packets::SEmote { - runtime_entity_id: p.runtime_entity_id.0.try_into().unwrap(), - emote_id: p.emote_id.into(), - emote_length: p.emote_length.try_into().unwrap(), - xuid: p.xuid.into(), - platform_id: p.platform_id.into(), - flags: p.flags.try_into().unwrap(), + let p = ::read(&mut Cursor::new(payload)).ok()?; + Some(BServerboundPacket::SPlayerHotbar(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::bedrock_packets::SPlayerHotbar { + selected_slot: p.selected_slot.try_into().unwrap(), + container_id: p.container_id.try_into().unwrap(), + select_slot: p.select_slot.try_into().unwrap(), })) } id if id == ::PACKET_ID as i32 => { @@ -2391,6 +2531,17 @@ pub trait ToWitClientboundBedrock { fn to_wit(&self) -> BClientboundPacket; } +impl ToWitClientboundBedrock for pumpkin_protocol::bedrock::client::CChangeDimension { + fn to_wit(&self) -> BClientboundPacket { + BClientboundPacket::CChangeDimension(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::bedrock_packets::CChangeDimension { + dimension: self.dimension.0.try_into().unwrap(), + position: (self.position.x as _, self.position.y as _, self.position.z as _), + respawn: self.respawn.try_into().unwrap(), + has_loading_screen_id: self.has_loading_screen_id.try_into().unwrap(), + }) + } +} + impl ToWitClientboundBedrock for pumpkin_protocol::bedrock::client::CChunkRadiusUpdate { fn to_wit(&self) -> BClientboundPacket { BClientboundPacket::CChunkRadiusUpdate(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::bedrock_packets::CChunkRadiusUpdate { @@ -2443,6 +2594,19 @@ impl ToWitClientboundBedrock for pumpkin_protocol::bedrock::client::CLevelEvent } } +impl ToWitClientboundBedrock for pumpkin_protocol::bedrock::client::CLevelSoundEvent { + fn to_wit(&self) -> BClientboundPacket { + BClientboundPacket::CLevelSoundEvent(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::bedrock_packets::CLevelSoundEvent { + sound_id: self.sound_id.0.try_into().unwrap(), + position: (self.position.x as _, self.position.y as _, self.position.z as _), + extra_data: self.extra_data.0.try_into().unwrap(), + entity_type: self.entity_type.to_string(), + is_baby_mob: self.is_baby_mob.try_into().unwrap(), + is_global: self.is_global.try_into().unwrap(), + }) + } +} + impl ToWitClientboundBedrock for pumpkin_protocol::bedrock::client::CModalFormRequest { fn to_wit(&self) -> BClientboundPacket { BClientboundPacket::CModalFormRequest(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::bedrock_packets::CModalFormRequest { @@ -2575,6 +2739,14 @@ impl ToWitClientboundBedrock for pumpkin_protocol::bedrock::client::CSetActorMot } } +impl ToWitClientboundBedrock for pumpkin_protocol::bedrock::client::CSetDifficulty { + fn to_wit(&self) -> BClientboundPacket { + BClientboundPacket::CSetDifficulty(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::bedrock_packets::CSetDifficulty { + difficulty: self.difficulty.0.try_into().unwrap(), + }) + } +} + impl ToWitClientboundBedrock for pumpkin_protocol::bedrock::client::CSetHealth { fn to_wit(&self) -> BClientboundPacket { BClientboundPacket::CSetHealth(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::bedrock_packets::CSetHealth { @@ -2583,6 +2755,17 @@ impl ToWitClientboundBedrock for pumpkin_protocol::bedrock::client::CSetHealth { } } +impl ToWitClientboundBedrock for pumpkin_protocol::bedrock::client::CSetSpawnPosition { + fn to_wit(&self) -> BClientboundPacket { + BClientboundPacket::CSetSpawnPosition(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::bedrock_packets::CSetSpawnPosition { + spawn_type: self.spawn_type.0.try_into().unwrap(), + position: (self.position.0.x, self.position.0.y, self.position.0.z), + dimension: self.dimension.0.try_into().unwrap(), + spawn_position: (self.spawn_position.0.x, self.spawn_position.0.y, self.spawn_position.0.z), + }) + } +} + impl ToWitClientboundBedrock for pumpkin_protocol::bedrock::client::CSetTime { fn to_wit(&self) -> BClientboundPacket { BClientboundPacket::CSetTime(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::bedrock_packets::CSetTime { @@ -2606,6 +2789,15 @@ impl ToWitClientboundBedrock for pumpkin_protocol::bedrock::client::CSetTitle { } } +impl ToWitClientboundBedrock for pumpkin_protocol::bedrock::client::CShowCredits { + fn to_wit(&self) -> BClientboundPacket { + BClientboundPacket::CShowCredits(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::bedrock_packets::CShowCredits { + player_runtime_id: self.player_runtime_id.0.try_into().unwrap(), + status: self.status.0.try_into().unwrap(), + }) + } +} + impl ToWitClientboundBedrock for pumpkin_protocol::bedrock::client::CTakeItemActor { fn to_wit(&self) -> BClientboundPacket { BClientboundPacket::CTakeItemActor(crate::plugin::loader::wasm::wasm_host::wit::v0_1::pumpkin::plugin::bedrock_packets::CTakeItemActor { @@ -2638,6 +2830,9 @@ impl ToWitClientboundBedrock for pumpkin_protocol::bedrock::client::CUpdateBlock #[must_use] pub fn clientbound_bedrock_any_to_wit(any: &dyn Any) -> Option { + if let Some(p) = any.downcast_ref::() { + return Some(p.to_wit()); + } if let Some(p) = any.downcast_ref::() { return Some(p.to_wit()); } @@ -2653,6 +2848,9 @@ pub fn clientbound_bedrock_any_to_wit(any: &dyn Any) -> Option() { return Some(p.to_wit()); } + if let Some(p) = any.downcast_ref::() { + return Some(p.to_wit()); + } if let Some(p) = any.downcast_ref::() { return Some(p.to_wit()); } @@ -2686,15 +2884,24 @@ pub fn clientbound_bedrock_any_to_wit(any: &dyn Any) -> Option() { return Some(p.to_wit()); } + if let Some(p) = any.downcast_ref::() { + return Some(p.to_wit()); + } if let Some(p) = any.downcast_ref::() { return Some(p.to_wit()); } + if let Some(p) = any.downcast_ref::() { + return Some(p.to_wit()); + } if let Some(p) = any.downcast_ref::() { return Some(p.to_wit()); } if let Some(p) = any.downcast_ref::() { return Some(p.to_wit()); } + if let Some(p) = any.downcast_ref::() { + return Some(p.to_wit()); + } if let Some(p) = any.downcast_ref::() { return Some(p.to_wit()); } diff --git a/pumpkin/src/world/mod.rs b/pumpkin/src/world/mod.rs index b98ce485a..f66e22f22 100644 --- a/pumpkin/src/world/mod.rs +++ b/pumpkin/src/world/mod.rs @@ -1747,6 +1747,17 @@ impl World { } pub async fn set_raining(&self, raining: bool) { + if let Some(server) = self.server.upgrade() { + let world_arc = server.get_world_from_dimension(&self.dimension); + let mut event = + crate::plugin::api::events::world::weather_change::WeatherChangeEvent::new( + world_arc, raining, + ); + server.plugin_manager.fire(&server, &mut event).await; + if event.cancelled { + return; + } + } let mut weather = self.weather.lock().await; if weather.raining != raining { let thunder = weather.thundering; @@ -1759,6 +1770,17 @@ impl World { } pub async fn set_thundering(&self, thundering: bool) { + if let Some(server) = self.server.upgrade() { + let world_arc = server.get_world_from_dimension(&self.dimension); + let mut event = + crate::plugin::api::events::world::weather_change::ThunderChangeEvent::new( + world_arc, thundering, + ); + server.plugin_manager.fire(&server, &mut event).await; + if event.cancelled { + return; + } + } let mut weather = self.weather.lock().await; if weather.thundering != thundering { let raining = weather.raining; @@ -2688,6 +2710,14 @@ impl World { .level .get_or_fetch_chunk(center_chunk, std::clone::Clone::clone) .await; + if let Some(server) = self.server.upgrade() { + let mut event = + crate::plugin::world::chunk_send::ChunkSend::new(player.world(), chunk.clone()); + server.plugin_manager.fire(&server, &mut event).await; + if event.cancelled { + return; + } + } client.send_packet_now(&CChunkBatchStart).await; client.send_packet_now(&CChunkData(&chunk)).await; client.send_packet_now(&CChunkBatchEnd::new(1u16)).await;