fix: unix rlimit
This commit is contained in:
parent
f8d1627697
commit
9258bb9023
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -3475,6 +3475,7 @@ dependencies = [
|
|||||||
"hyper",
|
"hyper",
|
||||||
"image",
|
"image",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
"libc",
|
||||||
"libloading",
|
"libloading",
|
||||||
"notify",
|
"notify",
|
||||||
"num-bigint 0.5.1",
|
"num-bigint 0.5.1",
|
||||||
|
|||||||
@ -163,6 +163,7 @@ heck = { version = "0.5", default-features = false }
|
|||||||
hmac = { version = "=0.13.0", default-features = false }
|
hmac = { version = "=0.13.0", default-features = false }
|
||||||
indexmap = { version = "2.14", default-features = false, features = ["std"] }
|
indexmap = { version = "2.14", default-features = false, features = ["std"] }
|
||||||
itertools = { version = "0.15.0", default-features = false, features = ["use_std"] }
|
itertools = { version = "0.15.0", default-features = false, features = ["use_std"] }
|
||||||
|
libc = { version = "0.2", default-features = false }
|
||||||
libloading = { version = "0.9", default-features = false, features = ["std"] }
|
libloading = { version = "0.9", default-features = false, features = ["std"] }
|
||||||
lru = { version = "0.18.3", default-features = false }
|
lru = { version = "0.18.3", default-features = false }
|
||||||
lz4-java-wrc = { version = "0.2.0", default-features = false, features = ["lz4_flex"] }
|
lz4-java-wrc = { version = "0.2.0", default-features = false, features = ["lz4_flex"] }
|
||||||
|
|||||||
@ -17,7 +17,7 @@ pub struct QueryConfig {
|
|||||||
impl Default for QueryConfig {
|
impl Default for QueryConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
enabled: true,
|
enabled: false,
|
||||||
address: SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 25565),
|
address: SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 25565),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -379,4 +379,3 @@ impl ClientPacket for CSpawnLivingEntity {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -100,6 +100,7 @@ rustc-hash.workspace = true
|
|||||||
tokio-util = { workspace = true, features = ["rt"] }
|
tokio-util = { workspace = true, features = ["rt"] }
|
||||||
|
|
||||||
# System details & Rustc version
|
# System details & Rustc version
|
||||||
|
libc = { workspace = true }
|
||||||
sysinfo.workspace = true
|
sysinfo.workspace = true
|
||||||
rustc_version_runtime.workspace = true
|
rustc_version_runtime.workspace = true
|
||||||
|
|
||||||
|
|||||||
@ -59,11 +59,12 @@ impl BlockBehaviour for FarmlandBlock {
|
|||||||
let mut props = FarmlandProperties::default(args.block);
|
let mut props = FarmlandProperties::default(args.block);
|
||||||
let mut new_moisture = 7;
|
let mut new_moisture = 7;
|
||||||
if let Some(server) = args.world.server.upgrade() {
|
if let Some(server) = args.world.server.upgrade() {
|
||||||
let mut event = crate::plugin::api::events::block::moisture_change::MoistureChangeEvent::new(
|
let mut event =
|
||||||
*args.position,
|
crate::plugin::api::events::block::moisture_change::MoistureChangeEvent::new(
|
||||||
args.world.clone(),
|
*args.position,
|
||||||
new_moisture,
|
args.world.clone(),
|
||||||
);
|
new_moisture,
|
||||||
|
);
|
||||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||||
if event.cancelled {
|
if event.cancelled {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -102,10 +102,11 @@ impl BlockBehaviour for LeavesBlock {
|
|||||||
let props = OakLeavesLikeProperties::from_state_id(state_id);
|
let props = OakLeavesLikeProperties::from_state_id(state_id);
|
||||||
if !props.persistent && props.distance == DECAY_DISTANCE {
|
if !props.persistent && props.distance == DECAY_DISTANCE {
|
||||||
if let Some(server) = args.world.server.upgrade() {
|
if let Some(server) = args.world.server.upgrade() {
|
||||||
let mut event = crate::plugin::api::events::block::leaves_decay::LeavesDecayEvent::new(
|
let mut event =
|
||||||
*args.position,
|
crate::plugin::api::events::block::leaves_decay::LeavesDecayEvent::new(
|
||||||
args.world.clone(),
|
*args.position,
|
||||||
);
|
args.world.clone(),
|
||||||
|
);
|
||||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||||
if event.cancelled {
|
if event.cancelled {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -74,14 +74,15 @@ trait CropBlockBase: PlantBlockBase {
|
|||||||
if rand::rng().random_range(0..=(25.0 / f).floor() as i64) == 0 {
|
if rand::rng().random_range(0..=(25.0 / f).floor() as i64) == 0 {
|
||||||
let new_state_id = self.state_with_age(block, state, age + 1);
|
let new_state_id = self.state_with_age(block, state, age + 1);
|
||||||
if let Some(server) = world.server.upgrade() {
|
if let Some(server) = world.server.upgrade() {
|
||||||
let mut event = crate::plugin::api::events::block::block_grow::BlockGrowEvent::new(
|
let mut event =
|
||||||
world.clone(),
|
crate::plugin::api::events::block::block_grow::BlockGrowEvent::new(
|
||||||
block,
|
world.clone(),
|
||||||
state,
|
block,
|
||||||
block,
|
state,
|
||||||
new_state_id,
|
block,
|
||||||
*pos,
|
new_state_id,
|
||||||
);
|
*pos,
|
||||||
|
);
|
||||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||||
if event.cancelled {
|
if event.cancelled {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -56,10 +56,7 @@ impl BlockBehaviour for SweetBerryBushBlock {
|
|||||||
}
|
}
|
||||||
props.age = 1;
|
props.age = 1;
|
||||||
for stack in drops {
|
for stack in drops {
|
||||||
args.world.drop_stack(
|
args.world.drop_stack(args.position, stack);
|
||||||
args.position,
|
|
||||||
stack,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
args.world.set_block_state(
|
args.world.set_block_state(
|
||||||
args.position,
|
args.position,
|
||||||
|
|||||||
@ -134,11 +134,12 @@ impl CrafterBlock {
|
|||||||
|
|
||||||
let mut result_stack = ItemStack::new(recipe_result.count, item);
|
let mut result_stack = ItemStack::new(recipe_result.count, item);
|
||||||
if let Some(server) = world.server.upgrade() {
|
if let Some(server) = world.server.upgrade() {
|
||||||
let mut event = crate::plugin::api::events::block::crafter_craft::CrafterCraftEvent::new(
|
let mut event =
|
||||||
*pos,
|
crate::plugin::api::events::block::crafter_craft::CrafterCraftEvent::new(
|
||||||
world.clone(),
|
*pos,
|
||||||
result_stack.clone(),
|
world.clone(),
|
||||||
);
|
result_stack.clone(),
|
||||||
|
);
|
||||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||||
if event.cancelled {
|
if event.cancelled {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -465,7 +465,8 @@ impl crate::block::entities::BlockEntity for BrewingStandBlockEntity {
|
|||||||
if fuel_event.cancelled {
|
if fuel_event.cancelled {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
self.fuel.store(fuel_event.fuel_power as i32, Ordering::Relaxed);
|
self.fuel
|
||||||
|
.store(fuel_event.fuel_power as i32, Ordering::Relaxed);
|
||||||
items[4].decrement(1);
|
items[4].decrement(1);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
@ -506,12 +507,15 @@ impl crate::block::entities::BlockEntity for BrewingStandBlockEntity {
|
|||||||
}
|
}
|
||||||
} else if brewable && self.fuel.load(Ordering::Relaxed) > 0 {
|
} else if brewable && self.fuel.load(Ordering::Relaxed) > 0 {
|
||||||
let brew_time = if let Some(server) = world.server.upgrade() {
|
let brew_time = if let Some(server) = world.server.upgrade() {
|
||||||
let mut start_event = crate::plugin::api::events::block::brewing_start::BrewingStartEvent::new(
|
let mut start_event =
|
||||||
self.position,
|
crate::plugin::api::events::block::brewing_start::BrewingStartEvent::new(
|
||||||
world.clone(),
|
self.position,
|
||||||
400,
|
world.clone(),
|
||||||
);
|
400,
|
||||||
server.plugin_manager.fire_blocking(&server, &mut start_event);
|
);
|
||||||
|
server
|
||||||
|
.plugin_manager
|
||||||
|
.fire_blocking(&server, &mut start_event);
|
||||||
if start_event.cancelled {
|
if start_event.cancelled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -527,12 +527,13 @@ impl BlockRegistry {
|
|||||||
}
|
}
|
||||||
if behaviour.is_bonemeal_success(args) {
|
if behaviour.is_bonemeal_success(args) {
|
||||||
if let Some(server) = world.server.upgrade() {
|
if let Some(server) = world.server.upgrade() {
|
||||||
let mut event = crate::plugin::api::events::block::block_fertilize::BlockFertilizeEvent::new(
|
let mut event =
|
||||||
*position,
|
crate::plugin::api::events::block::block_fertilize::BlockFertilizeEvent::new(
|
||||||
world.clone(),
|
*position,
|
||||||
None,
|
world.clone(),
|
||||||
vec![],
|
None,
|
||||||
);
|
vec![],
|
||||||
|
);
|
||||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||||
if event.cancelled {
|
if event.cancelled {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -8,6 +8,7 @@ use crate::command::string_reader::StringReader;
|
|||||||
use crate::command::suggestion::suggestions::{Suggestions, SuggestionsBuilder};
|
use crate::command::suggestion::suggestions::{Suggestions, SuggestionsBuilder};
|
||||||
use pumpkin_data::entity::EntityType;
|
use pumpkin_data::entity::EntityType;
|
||||||
use pumpkin_data::translation;
|
use pumpkin_data::translation;
|
||||||
|
use pumpkin_protocol::java::client::play::SuggestionProviders;
|
||||||
use pumpkin_util::identifier::Identifier;
|
use pumpkin_util::identifier::Identifier;
|
||||||
use pumpkin_util::text::TextComponent;
|
use pumpkin_util::text::TextComponent;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
@ -144,6 +145,7 @@ impl ArgumentType for ResourceArgument {
|
|||||||
if self.0 == ENTITY_TYPE_REGISTRY {
|
if self.0 == ENTITY_TYPE_REGISTRY {
|
||||||
let entity_types = EntityType::ALL
|
let entity_types = EntityType::ALL
|
||||||
.iter()
|
.iter()
|
||||||
|
.filter(|entity_type| entity_type.summonable)
|
||||||
.map(|entity_type| format!("minecraft:{}", entity_type.resource_name));
|
.map(|entity_type| format!("minecraft:{}", entity_type.resource_name));
|
||||||
suggestions_builder
|
suggestions_builder
|
||||||
.filter_and_suggest_iter(entity_types)
|
.filter_and_suggest_iter(entity_types)
|
||||||
@ -216,6 +218,10 @@ impl ArgumentType for ResourceArgument {
|
|||||||
identifier: self.0.clone(),
|
identifier: self.0.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn override_suggestion_providers(&self) -> Option<SuggestionProviders> {
|
||||||
|
(self.0 == ENTITY_TYPE_REGISTRY).then_some(SuggestionProviders::SummonableEntities)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResourceArgument {
|
impl ResourceArgument {
|
||||||
@ -228,10 +234,11 @@ impl ResourceArgument {
|
|||||||
TextComponent::text(format!("Could not find argument with name '{name}'")),
|
TextComponent::text(format!("Could not find argument with name '{name}'")),
|
||||||
);
|
);
|
||||||
let node = context
|
let node = context
|
||||||
.tree
|
.nodes
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|node| {
|
.rev()
|
||||||
if let AttachedNode::Argument(cur) = node
|
.find_map(|parsed| {
|
||||||
|
if let AttachedNode::Argument(cur) = &context.tree[parsed.node]
|
||||||
&& cur.meta.name == name
|
&& cur.meta.name == name
|
||||||
{
|
{
|
||||||
Some(cur)
|
Some(cur)
|
||||||
@ -239,6 +246,17 @@ impl ResourceArgument {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.or_else(|| {
|
||||||
|
context.tree.iter().find_map(|node| {
|
||||||
|
if let AttachedNode::Argument(cur) = node
|
||||||
|
&& cur.meta.name == name
|
||||||
|
{
|
||||||
|
Some(cur)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
.ok_or(missing_argument.clone())?;
|
.ok_or(missing_argument.clone())?;
|
||||||
let invalid_argument =
|
let invalid_argument =
|
||||||
DISPATCHER_PARSE_EXCEPTION.create_without_context(TextComponent::text(format!(
|
DISPATCHER_PARSE_EXCEPTION.create_without_context(TextComponent::text(format!(
|
||||||
|
|||||||
@ -1,22 +1,41 @@
|
|||||||
use pumpkin_data::translation;
|
use pumpkin_data::translation;
|
||||||
use pumpkin_util::PermissionLvl;
|
use pumpkin_util::PermissionLvl;
|
||||||
|
use pumpkin_util::difficulty::Difficulty;
|
||||||
|
use pumpkin_util::math::position::BlockPos;
|
||||||
use pumpkin_util::permission::{Permission, PermissionDefault, PermissionRegistry};
|
use pumpkin_util::permission::{Permission, PermissionDefault, PermissionRegistry};
|
||||||
use pumpkin_util::text::TextComponent;
|
use pumpkin_util::text::TextComponent;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::command::argument_builder::{ArgumentBuilder, argument, command};
|
use crate::command::argument_builder::{ArgumentBuilder, argument, command};
|
||||||
use crate::command::argument_types::coordinates::vec3::Vec3ArgumentType;
|
use crate::command::argument_types::coordinates::vec3::Vec3ArgumentType;
|
||||||
|
use crate::command::argument_types::nbt::NbtCompoundArgumentType;
|
||||||
use crate::command::argument_types::resource::{ENTITY_TYPE_ARGUMENT, ResourceArgument};
|
use crate::command::argument_types::resource::{ENTITY_TYPE_ARGUMENT, ResourceArgument};
|
||||||
use crate::command::context::command_context::CommandContext;
|
use crate::command::context::command_context::CommandContext;
|
||||||
|
use crate::command::errors::error_types::CommandErrorType;
|
||||||
use crate::command::node::dispatcher::CommandDispatcher;
|
use crate::command::node::dispatcher::CommandDispatcher;
|
||||||
use crate::command::node::{CommandExecutor, CommandExecutorResult};
|
use crate::command::node::{CommandExecutor, CommandExecutorResult};
|
||||||
use crate::entity::r#type::from_type;
|
use crate::entity::r#type::from_type;
|
||||||
|
use crate::world::World;
|
||||||
|
|
||||||
const DESCRIPTION: &str = "Spawns an entity at position.";
|
const DESCRIPTION: &str = "Spawns an entity at position.";
|
||||||
const PERMISSION: &str = "minecraft:command.summon";
|
const PERMISSION: &str = "minecraft:command.summon";
|
||||||
|
|
||||||
|
const ERROR_FAILED_PEACEFUL: CommandErrorType<0> = CommandErrorType::new(
|
||||||
|
translation::java::COMMANDS_SUMMON_FAILED_PEACEFUL,
|
||||||
|
translation::bedrock::COMMANDS_SUMMON_FAILED,
|
||||||
|
);
|
||||||
|
const ERROR_DUPLICATE_UUID: CommandErrorType<0> = CommandErrorType::new(
|
||||||
|
translation::java::COMMANDS_SUMMON_FAILED_UUID,
|
||||||
|
translation::bedrock::COMMANDS_SUMMON_FAILED,
|
||||||
|
);
|
||||||
|
const INVALID_POSITION: CommandErrorType<0> = CommandErrorType::new(
|
||||||
|
translation::java::COMMANDS_SUMMON_INVALIDPOSITION,
|
||||||
|
translation::bedrock::COMMANDS_SUMMON_OUTOFWORLD,
|
||||||
|
);
|
||||||
|
|
||||||
struct SummonExecutor {
|
struct SummonExecutor {
|
||||||
has_pos: bool,
|
has_pos: bool,
|
||||||
|
has_nbt: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommandExecutor for SummonExecutor {
|
impl CommandExecutor for SummonExecutor {
|
||||||
@ -28,8 +47,42 @@ impl CommandExecutor for SummonExecutor {
|
|||||||
context.source.position
|
context.source.position
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let block_pos = BlockPos::floored_v(pos);
|
||||||
|
if !World::is_valid(block_pos) {
|
||||||
|
return Err(INVALID_POSITION.create_without_context());
|
||||||
|
}
|
||||||
|
|
||||||
let world = context.source.world();
|
let world = context.source.world();
|
||||||
let entity = from_type(entity_type, pos, world, Uuid::new_v4());
|
let difficulty = world.level_info.load().difficulty;
|
||||||
|
if difficulty == Difficulty::Peaceful && !entity_type.category.is_friendly {
|
||||||
|
return Err(ERROR_FAILED_PEACEFUL.create_without_context());
|
||||||
|
}
|
||||||
|
|
||||||
|
let nbt = if self.has_nbt {
|
||||||
|
Some(NbtCompoundArgumentType::get(context, "nbt")?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let uuid = nbt
|
||||||
|
.and_then(|nbt| nbt.get_uuid("UUID"))
|
||||||
|
.unwrap_or_else(Uuid::new_v4);
|
||||||
|
|
||||||
|
let entity = from_type(entity_type, pos, world, uuid);
|
||||||
|
if let Some(nbt) = nbt {
|
||||||
|
entity.read_nbt_non_mut(nbt);
|
||||||
|
entity.get_entity().set_pos(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
if world
|
||||||
|
.entities
|
||||||
|
.load()
|
||||||
|
.iter()
|
||||||
|
.any(|e| e.get_entity().entity_uuid == entity.get_entity().entity_uuid)
|
||||||
|
{
|
||||||
|
return Err(ERROR_DUPLICATE_UUID.create_without_context());
|
||||||
|
}
|
||||||
|
|
||||||
let name = entity.get_display_name();
|
let name = entity.get_display_name();
|
||||||
world.spawn_entity(entity);
|
world.spawn_entity(entity);
|
||||||
|
|
||||||
@ -56,11 +109,69 @@ pub fn register(dispatcher: &mut CommandDispatcher, registry: &PermissionRegistr
|
|||||||
dispatcher.register(
|
dispatcher.register(
|
||||||
command("summon", DESCRIPTION).requires(PERMISSION).then(
|
command("summon", DESCRIPTION).requires(PERMISSION).then(
|
||||||
argument("entity", ENTITY_TYPE_ARGUMENT.clone())
|
argument("entity", ENTITY_TYPE_ARGUMENT.clone())
|
||||||
.executes(SummonExecutor { has_pos: false })
|
.executes(SummonExecutor {
|
||||||
|
has_pos: false,
|
||||||
|
has_nbt: false,
|
||||||
|
})
|
||||||
.then(
|
.then(
|
||||||
argument("pos", Vec3ArgumentType::Default)
|
argument("pos", Vec3ArgumentType::Default)
|
||||||
.executes(SummonExecutor { has_pos: true }),
|
.executes(SummonExecutor {
|
||||||
|
has_pos: true,
|
||||||
|
has_nbt: false,
|
||||||
|
})
|
||||||
|
.then(
|
||||||
|
argument("nbt", NbtCompoundArgumentType).executes(SummonExecutor {
|
||||||
|
has_pos: true,
|
||||||
|
has_nbt: true,
|
||||||
|
}),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::command::commands::fetchprofile;
|
||||||
|
use crate::command::context::command_source::CommandSource;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_summon_cat() {
|
||||||
|
let mut dispatcher = CommandDispatcher::new();
|
||||||
|
let registry = PermissionRegistry::default();
|
||||||
|
|
||||||
|
// Register fetchprofile first to ensure its "entity" argument doesn't collide
|
||||||
|
fetchprofile::register(&mut dispatcher, ®istry);
|
||||||
|
register(&mut dispatcher, ®istry);
|
||||||
|
|
||||||
|
let source = Arc::new(CommandSource::dummy());
|
||||||
|
let result = dispatcher.parse_input("summon cat", &source);
|
||||||
|
assert!(result.errors.is_empty());
|
||||||
|
let context = result.context.build("summon cat");
|
||||||
|
let entity_type = ResourceArgument::get_summonable_entity_type(&context, "entity")
|
||||||
|
.expect("Should resolve summonable cat entity type");
|
||||||
|
assert_eq!(entity_type.resource_name, "cat");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_summon_cat_with_pos_and_nbt() {
|
||||||
|
let mut dispatcher = CommandDispatcher::new();
|
||||||
|
let registry = PermissionRegistry::default();
|
||||||
|
|
||||||
|
fetchprofile::register(&mut dispatcher, ®istry);
|
||||||
|
register(&mut dispatcher, ®istry);
|
||||||
|
|
||||||
|
let source = Arc::new(CommandSource::dummy());
|
||||||
|
let result = dispatcher.parse_input("summon cat ~ ~ ~ {NoAI:1b}", &source);
|
||||||
|
assert!(result.errors.is_empty());
|
||||||
|
let context = result.context.build("summon cat ~ ~ ~ {NoAI:1b}");
|
||||||
|
let entity_type = ResourceArgument::get_summonable_entity_type(&context, "entity")
|
||||||
|
.expect("Should resolve summonable cat entity type");
|
||||||
|
assert_eq!(entity_type.resource_name, "cat");
|
||||||
|
let nbt =
|
||||||
|
NbtCompoundArgumentType::get(&context, "nbt").expect("Should resolve NBT argument");
|
||||||
|
assert_eq!(nbt.get_byte("NoAI"), Some(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -480,7 +480,15 @@ impl CommandSource {
|
|||||||
/// server (i.e. this is a dummy [`CommandSource`].)
|
/// server (i.e. this is a dummy [`CommandSource`].)
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn has_permission(&self, permission: &str) -> bool {
|
pub fn has_permission(&self, permission: &str) -> bool {
|
||||||
self.output.has_permission(self.server(), permission)
|
self.server.as_ref().map_or(
|
||||||
|
matches!(
|
||||||
|
self.output,
|
||||||
|
crate::command::CommandSender::Console
|
||||||
|
| crate::command::CommandSender::Rcon(_)
|
||||||
|
| crate::command::CommandSender::Dummy
|
||||||
|
),
|
||||||
|
|server| self.output.has_permission(server, permission),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether this source has the permission provided.
|
/// Returns whether this source has the permission provided.
|
||||||
|
|||||||
@ -606,7 +606,8 @@ impl CombatTracker {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else if let Some(killer_name) = kill_credit_name.or_else(|| {
|
} else if let Some(killer_name) = kill_credit_name.or_else(|| {
|
||||||
self.get_killer_entry().and_then(|k| k.attacker_name.clone())
|
self.get_killer_entry()
|
||||||
|
.and_then(|k| k.attacker_name.clone())
|
||||||
}) {
|
}) {
|
||||||
pumpkin_util::text::TextComponent::translate_cross(
|
pumpkin_util::text::TextComponent::translate_cross(
|
||||||
format!("death.attack.{msg_id}.player"),
|
format!("death.attack.{msg_id}.player"),
|
||||||
|
|||||||
@ -1666,9 +1666,7 @@ impl LivingEntity {
|
|||||||
source: Option<&dyn EntityBase>,
|
source: Option<&dyn EntityBase>,
|
||||||
cause: Option<&dyn EntityBase>,
|
cause: Option<&dyn EntityBase>,
|
||||||
) -> TextComponent {
|
) -> TextComponent {
|
||||||
let kill_credit = dyn_self
|
let kill_credit = dyn_self.get_living_entity().and_then(Self::get_kill_credit);
|
||||||
.get_living_entity()
|
|
||||||
.and_then(Self::get_kill_credit);
|
|
||||||
let kill_credit_name = kill_credit.as_ref().map(|c| c.get_display_name());
|
let kill_credit_name = kill_credit.as_ref().map(|c| c.get_display_name());
|
||||||
|
|
||||||
if let Some(living) = dyn_self.get_living_entity() {
|
if let Some(living) = dyn_self.get_living_entity() {
|
||||||
@ -1687,7 +1685,11 @@ impl LivingEntity {
|
|||||||
format!("death.attack.{}", damage_type.message_id),
|
format!("death.attack.{}", damage_type.message_id),
|
||||||
[dyn_self.get_display_name(), cause.get_display_name()],
|
[dyn_self.get_display_name(), cause.get_display_name()],
|
||||||
)
|
)
|
||||||
} else if let Some(killer) = cause.or(source).map(|c| c.get_display_name()).or(kill_credit_name) {
|
} else if let Some(killer) = cause
|
||||||
|
.or(source)
|
||||||
|
.map(|c| c.get_display_name())
|
||||||
|
.or(kill_credit_name)
|
||||||
|
{
|
||||||
TextComponent::translate_cross(
|
TextComponent::translate_cross(
|
||||||
format!("death.attack.{}.player", damage_type.message_id),
|
format!("death.attack.{}.player", damage_type.message_id),
|
||||||
format!("death.attack.{}.player", damage_type.message_id),
|
format!("death.attack.{}.player", damage_type.message_id),
|
||||||
@ -1887,11 +1889,12 @@ impl LivingEntity {
|
|||||||
if let Some(player_arc) = world.get_player_by_uuid(player.gameprofile.id)
|
if let Some(player_arc) = world.get_player_by_uuid(player.gameprofile.id)
|
||||||
&& let Some(server) = world.server.upgrade()
|
&& let Some(server) = world.server.upgrade()
|
||||||
{
|
{
|
||||||
let mut event = crate::plugin::api::events::entity::entity_death::PlayerDeathEvent::new(
|
let mut event =
|
||||||
player_arc,
|
crate::plugin::api::events::entity::entity_death::PlayerDeathEvent::new(
|
||||||
final_death_message.clone(),
|
player_arc,
|
||||||
0,
|
final_death_message.clone(),
|
||||||
);
|
0,
|
||||||
|
);
|
||||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||||
if event.cancelled {
|
if event.cancelled {
|
||||||
return;
|
return;
|
||||||
@ -1902,9 +1905,7 @@ impl LivingEntity {
|
|||||||
player.handle_killed(&final_death_message);
|
player.handle_killed(&final_death_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
if show_death_messages
|
if show_death_messages && let Some(server) = world.server.upgrade() {
|
||||||
&& let Some(server) = world.server.upgrade()
|
|
||||||
{
|
|
||||||
for player in server.get_all_players() {
|
for player in server.get_all_players() {
|
||||||
player.send_system_message(&final_death_message);
|
player.send_system_message(&final_death_message);
|
||||||
}
|
}
|
||||||
@ -2639,7 +2640,13 @@ impl LivingEntity {
|
|||||||
| DamageType::STALAGMITE
|
| DamageType::STALAGMITE
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
let damager_pos = position.map(|p| BlockPos(Vector3::new(p.x.floor() as i32, p.y.floor() as i32, p.z.floor() as i32)));
|
let damager_pos = position.map(|p| {
|
||||||
|
BlockPos(Vector3::new(
|
||||||
|
p.x.floor() as i32,
|
||||||
|
p.y.floor() as i32,
|
||||||
|
p.z.floor() as i32,
|
||||||
|
))
|
||||||
|
});
|
||||||
let mut by_block_event =
|
let mut by_block_event =
|
||||||
crate::plugin::api::events::entity::entity_damage_by_block::EntityDamageByBlockEvent {
|
crate::plugin::api::events::entity::entity_damage_by_block::EntityDamageByBlockEvent {
|
||||||
entity_id: self.entity.entity_id,
|
entity_id: self.entity.entity_id,
|
||||||
@ -2897,8 +2904,7 @@ impl LivingEntity {
|
|||||||
|
|
||||||
if let Some(attacker) = cause.or(source) {
|
if let Some(attacker) = cause.or(source) {
|
||||||
let attacker_id = attacker.get_entity().entity_id;
|
let attacker_id = attacker.get_entity().entity_id;
|
||||||
self.last_attacker_id
|
self.last_attacker_id.store(attacker_id, Relaxed);
|
||||||
.store(attacker_id, Relaxed);
|
|
||||||
self.last_attacked_time
|
self.last_attacked_time
|
||||||
.store(self.entity.age.load(Relaxed), Relaxed);
|
.store(self.entity.age.load(Relaxed), Relaxed);
|
||||||
|
|
||||||
|
|||||||
@ -3371,12 +3371,13 @@ impl Entity {
|
|||||||
&& let Some(player) = holder.get_player()
|
&& let Some(player) = holder.get_player()
|
||||||
&& let Some(player_arc) = world.get_player_by_uuid(player.gameprofile.id)
|
&& let Some(player_arc) = world.get_player_by_uuid(player.gameprofile.id)
|
||||||
{
|
{
|
||||||
let mut event = crate::plugin::api::events::player::player_leash_entity::PlayerLeashEntityEvent {
|
let mut event =
|
||||||
player: player_arc,
|
crate::plugin::api::events::player::player_leash_entity::PlayerLeashEntityEvent {
|
||||||
entity_id: self.entity_id,
|
player: player_arc,
|
||||||
holder_id: holder_entity_id,
|
entity_id: self.entity_id,
|
||||||
cancelled: false,
|
holder_id: holder_entity_id,
|
||||||
};
|
cancelled: false,
|
||||||
|
};
|
||||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||||
if event.cancelled {
|
if event.cancelled {
|
||||||
return;
|
return;
|
||||||
@ -3416,10 +3417,11 @@ impl Entity {
|
|||||||
pub fn unleash(&self) {
|
pub fn unleash(&self) {
|
||||||
let world = self.world.load();
|
let world = self.world.load();
|
||||||
if let Some(server) = world.server.upgrade() {
|
if let Some(server) = world.server.upgrade() {
|
||||||
let mut event = crate::plugin::api::events::entity::entity_unleash::EntityUnleashEvent::new(
|
let mut event =
|
||||||
self.entity_id,
|
crate::plugin::api::events::entity::entity_unleash::EntityUnleashEvent::new(
|
||||||
"unleashed".to_string(),
|
self.entity_id,
|
||||||
);
|
"unleashed".to_string(),
|
||||||
|
);
|
||||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||||
if event.cancelled {
|
if event.cancelled {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -1607,12 +1607,13 @@ impl Player {
|
|||||||
if let Some(player_arc) = self.world().get_player_by_uuid(self.gameprofile.id)
|
if let Some(player_arc) = self.world().get_player_by_uuid(self.gameprofile.id)
|
||||||
&& let Some(server) = self.world().server.upgrade()
|
&& let Some(server) = self.world().server.upgrade()
|
||||||
{
|
{
|
||||||
let mut event = crate::plugin::api::events::player::player_spawn_change::PlayerSpawnChangeEvent {
|
let mut event =
|
||||||
player: player_arc,
|
crate::plugin::api::events::player::player_spawn_change::PlayerSpawnChangeEvent {
|
||||||
new_spawn: Some(block_pos),
|
player: player_arc,
|
||||||
forced,
|
new_spawn: Some(block_pos),
|
||||||
cancelled: false,
|
forced,
|
||||||
};
|
cancelled: false,
|
||||||
|
};
|
||||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||||
if event.cancelled {
|
if event.cancelled {
|
||||||
return false;
|
return false;
|
||||||
@ -1628,7 +1629,12 @@ impl Player {
|
|||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
self.client.try_enqueue_packet_editioned(
|
self.client.try_enqueue_packet_editioned(
|
||||||
&CPlayerSpawnPosition::new(final_block_pos, yaw, pitch, dimension.minecraft_name.to_owned()),
|
&CPlayerSpawnPosition::new(
|
||||||
|
final_block_pos,
|
||||||
|
yaw,
|
||||||
|
pitch,
|
||||||
|
dimension.minecraft_name.to_owned(),
|
||||||
|
),
|
||||||
&pumpkin_protocol::bedrock::client::CSetSpawnPosition {
|
&pumpkin_protocol::bedrock::client::CSetSpawnPosition {
|
||||||
spawn_position_type:
|
spawn_position_type:
|
||||||
pumpkin_protocol::bedrock::client::SpawnPositionType::PlayerRespawn,
|
pumpkin_protocol::bedrock::client::SpawnPositionType::PlayerRespawn,
|
||||||
@ -2315,12 +2321,13 @@ impl Player {
|
|||||||
if let Some(player_arc) = self.world().get_player_by_uuid(self.gameprofile.id)
|
if let Some(player_arc) = self.world().get_player_by_uuid(self.gameprofile.id)
|
||||||
&& let Some(server) = self.world().server.upgrade()
|
&& let Some(server) = self.world().server.upgrade()
|
||||||
{
|
{
|
||||||
let mut event = crate::plugin::api::events::player::player_open_sign::PlayerOpenSignEvent {
|
let mut event =
|
||||||
player: player_arc,
|
crate::plugin::api::events::player::player_open_sign::PlayerOpenSignEvent {
|
||||||
block_pos: location,
|
player: player_arc,
|
||||||
is_front: is_front_text,
|
block_pos: location,
|
||||||
cancelled: false,
|
is_front: is_front_text,
|
||||||
};
|
cancelled: false,
|
||||||
|
};
|
||||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||||
if event.cancelled {
|
if event.cancelled {
|
||||||
return;
|
return;
|
||||||
@ -2334,11 +2341,12 @@ impl Player {
|
|||||||
if let Some(player_arc) = self.world().get_player_by_uuid(self.gameprofile.id)
|
if let Some(player_arc) = self.world().get_player_by_uuid(self.gameprofile.id)
|
||||||
&& let Some(server) = self.world().server.upgrade()
|
&& let Some(server) = self.world().server.upgrade()
|
||||||
{
|
{
|
||||||
let mut event = crate::plugin::api::events::player::player_velocity::PlayerVelocityEvent {
|
let mut event =
|
||||||
player: player_arc,
|
crate::plugin::api::events::player::player_velocity::PlayerVelocityEvent {
|
||||||
velocity,
|
player: player_arc,
|
||||||
cancelled: false,
|
velocity,
|
||||||
};
|
cancelled: false,
|
||||||
|
};
|
||||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||||
if event.cancelled {
|
if event.cancelled {
|
||||||
return;
|
return;
|
||||||
@ -2391,10 +2399,11 @@ impl Player {
|
|||||||
&& let Some(server) = self.world().server.upgrade()
|
&& let Some(server) = self.world().server.upgrade()
|
||||||
{
|
{
|
||||||
let link_strings = links.iter().map(|l| l.url.clone()).collect();
|
let link_strings = links.iter().map(|l| l.url.clone()).collect();
|
||||||
let mut event = crate::plugin::api::events::player::player_links_send::PlayerLinksSendEvent::new(
|
let mut event =
|
||||||
player_arc,
|
crate::plugin::api::events::player::player_links_send::PlayerLinksSendEvent::new(
|
||||||
link_strings,
|
player_arc,
|
||||||
);
|
link_strings,
|
||||||
|
);
|
||||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||||
if event.cancelled {
|
if event.cancelled {
|
||||||
return;
|
return;
|
||||||
@ -3089,7 +3098,8 @@ impl Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn increment_stat(&self, category: statistics::StatisticCategory, stat: i32, amount: i32) {
|
pub fn increment_stat(&self, category: statistics::StatisticCategory, stat: i32, amount: i32) {
|
||||||
let final_amount = if let Some(player_arc) = self.world().get_player_by_uuid(self.gameprofile.id)
|
let final_amount = if let Some(player_arc) =
|
||||||
|
self.world().get_player_by_uuid(self.gameprofile.id)
|
||||||
&& let Some(server) = self.world().server.upgrade()
|
&& let Some(server) = self.world().server.upgrade()
|
||||||
{
|
{
|
||||||
let mut event = crate::plugin::api::events::player::player_statistic_increment::PlayerStatisticIncrementEvent {
|
let mut event = crate::plugin::api::events::player::player_statistic_increment::PlayerStatisticIncrementEvent {
|
||||||
@ -5228,13 +5238,14 @@ impl Player {
|
|||||||
if let Some(player_arc) = self.world().get_player_by_uuid(self.gameprofile.id)
|
if let Some(player_arc) = self.world().get_player_by_uuid(self.gameprofile.id)
|
||||||
&& let Some(server) = self.world().server.upgrade()
|
&& let Some(server) = self.world().server.upgrade()
|
||||||
{
|
{
|
||||||
let mut event = crate::plugin::api::events::player::player_item_mend::PlayerItemMendEvent {
|
let mut event =
|
||||||
player: player_arc,
|
crate::plugin::api::events::player::player_item_mend::PlayerItemMendEvent {
|
||||||
item_name: stack.item.registry_key.to_string(),
|
player: player_arc,
|
||||||
repair_amount: repaired,
|
item_name: stack.item.registry_key.to_string(),
|
||||||
exp_consumed: xp_used,
|
repair_amount: repaired,
|
||||||
cancelled: false,
|
exp_consumed: xp_used,
|
||||||
};
|
cancelled: false,
|
||||||
|
};
|
||||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||||
if event.cancelled {
|
if event.cancelled {
|
||||||
return xp;
|
return xp;
|
||||||
|
|||||||
@ -71,10 +71,11 @@ impl FireworkRocketEntity {
|
|||||||
pub fn explode_and_remove(&self, world: &World) {
|
pub fn explode_and_remove(&self, world: &World) {
|
||||||
let entity = self.get_entity();
|
let entity = self.get_entity();
|
||||||
if let Some(server) = world.server.upgrade() {
|
if let Some(server) = world.server.upgrade() {
|
||||||
let mut event = crate::plugin::api::events::entity::firework_explode::FireworkExplodeEvent {
|
let mut event =
|
||||||
entity_id: entity.entity_id,
|
crate::plugin::api::events::entity::firework_explode::FireworkExplodeEvent {
|
||||||
cancelled: false,
|
entity_id: entity.entity_id,
|
||||||
};
|
cancelled: false,
|
||||||
|
};
|
||||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||||
if event.cancelled {
|
if event.cancelled {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -244,14 +244,18 @@ impl EntityBase for SplashPotionEntity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let affected_ids: Vec<i32> = affected.iter().map(|(c, _)| c.get_entity().entity_id).collect();
|
let affected_ids: Vec<i32> = affected
|
||||||
|
.iter()
|
||||||
|
.map(|(c, _)| c.get_entity().entity_id)
|
||||||
|
.collect();
|
||||||
if let Some(server) = world.server.upgrade() {
|
if let Some(server) = world.server.upgrade() {
|
||||||
let mut event = crate::plugin::api::events::entity::potion_splash::PotionSplashEvent::new(
|
let mut event =
|
||||||
self.get_entity().entity_id,
|
crate::plugin::api::events::entity::potion_splash::PotionSplashEvent::new(
|
||||||
block_pos,
|
self.get_entity().entity_id,
|
||||||
stack.item.registry_key.to_string(),
|
block_pos,
|
||||||
affected_ids,
|
stack.item.registry_key.to_string(),
|
||||||
);
|
affected_ids,
|
||||||
|
);
|
||||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||||
if event.cancelled {
|
if event.cancelled {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -120,12 +120,13 @@ impl ItemBehaviour for BrushItem {
|
|||||||
if let Some(player_arc) = player.world().get_player_by_uuid(player.gameprofile.id)
|
if let Some(player_arc) = player.world().get_player_by_uuid(player.gameprofile.id)
|
||||||
&& let Some(server) = player.world().server.upgrade()
|
&& let Some(server) = player.world().server.upgrade()
|
||||||
{
|
{
|
||||||
let mut event = crate::plugin::api::events::block::block_brush::BlockBrushEvent::new(
|
let mut event =
|
||||||
location,
|
crate::plugin::api::events::block::block_brush::BlockBrushEvent::new(
|
||||||
world.clone(),
|
location,
|
||||||
player_arc,
|
world.clone(),
|
||||||
player.inventory().held_item(),
|
player_arc,
|
||||||
);
|
player.inventory().held_item(),
|
||||||
|
);
|
||||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||||
if event.cancelled {
|
if event.cancelled {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -194,12 +194,13 @@ fn handle_beehive(
|
|||||||
if let Some(player_arc) = player.world().get_player_by_uuid(player.gameprofile.id)
|
if let Some(player_arc) = player.world().get_player_by_uuid(player.gameprofile.id)
|
||||||
&& let Some(server) = player.world().server.upgrade()
|
&& let Some(server) = player.world().server.upgrade()
|
||||||
{
|
{
|
||||||
let mut event = crate::plugin::api::events::player::player_harvest_block::PlayerHarvestBlockEvent {
|
let mut event =
|
||||||
player: player_arc,
|
crate::plugin::api::events::player::player_harvest_block::PlayerHarvestBlockEvent {
|
||||||
block_pos: *location,
|
player: player_arc,
|
||||||
harvested_items: drops.clone(),
|
block_pos: *location,
|
||||||
cancelled: false,
|
harvested_items: drops.clone(),
|
||||||
};
|
cancelled: false,
|
||||||
|
};
|
||||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||||
if event.cancelled {
|
if event.cancelled {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -68,11 +68,12 @@ impl ItemBehaviour for TridentItem {
|
|||||||
if let Some(player_arc) = world.get_player_by_uuid(player.gameprofile.id)
|
if let Some(player_arc) = world.get_player_by_uuid(player.gameprofile.id)
|
||||||
&& let Some(server) = world.server.upgrade()
|
&& let Some(server) = world.server.upgrade()
|
||||||
{
|
{
|
||||||
let mut event = crate::plugin::api::events::player::player_riptide::PlayerRiptideEvent {
|
let mut event =
|
||||||
player: player_arc,
|
crate::plugin::api::events::player::player_riptide::PlayerRiptideEvent {
|
||||||
item_name: "trident".to_string(),
|
player: player_arc,
|
||||||
cancelled: false,
|
item_name: "trident".to_string(),
|
||||||
};
|
cancelled: false,
|
||||||
|
};
|
||||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||||
if event.cancelled {
|
if event.cancelled {
|
||||||
player.living_entity.clear_active_hand();
|
player.living_entity.clear_active_hand();
|
||||||
|
|||||||
@ -251,6 +251,9 @@ impl PumpkinServer {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
let server = Server::new(basic_config, advanced_config, vanilla_data).await;
|
let server = Server::new(basic_config, advanced_config, vanilla_data).await;
|
||||||
|
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
adjust_file_descriptor_limit();
|
||||||
|
|
||||||
let rcon = server.advanced_config.networking.rcon.clone();
|
let rcon = server.advanced_config.networking.rcon.clone();
|
||||||
|
|
||||||
if rcon.enabled {
|
if rcon.enabled {
|
||||||
@ -615,6 +618,15 @@ impl PumpkinServer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
if e.raw_os_error() == Some(libc::EMFILE) {
|
||||||
|
error!(
|
||||||
|
"Too many open files! Server reached file descriptor limit. \
|
||||||
|
New connections cannot be accepted until existing connections close or `ulimit -n` is increased."
|
||||||
|
);
|
||||||
|
sleep(Duration::from_millis(500)).await;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
error!("Failed to accept Java client connection: {e}");
|
error!("Failed to accept Java client connection: {e}");
|
||||||
sleep(Duration::from_millis(50)).await;
|
sleep(Duration::from_millis(50)).await;
|
||||||
}
|
}
|
||||||
@ -826,3 +838,58 @@ fn scrub_address(ip: &str) -> String {
|
|||||||
.map(|ch| if ch == '.' || ch == ':' { ch } else { 'x' })
|
.map(|ch| if ch == '.' || ch == ':' { ch } else { 'x' })
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
fn adjust_file_descriptor_limit() {
|
||||||
|
let mut rlim = libc::rlimit {
|
||||||
|
rlim_cur: 0,
|
||||||
|
rlim_max: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
// SAFETY: Passing a valid mutable pointer to a stack-allocated `rlimit` struct.
|
||||||
|
if unsafe { libc::getrlimit(libc::RLIMIT_NOFILE, &raw mut rlim) } != 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let max_target = if rlim.rlim_max == libc::RLIM_INFINITY {
|
||||||
|
1_048_576
|
||||||
|
} else {
|
||||||
|
rlim.rlim_max
|
||||||
|
};
|
||||||
|
|
||||||
|
if rlim.rlim_cur < max_target {
|
||||||
|
let old_limit = rlim.rlim_cur;
|
||||||
|
rlim.rlim_cur = max_target;
|
||||||
|
|
||||||
|
// SAFETY: Calling `setrlimit` with a valid resource and valid pointer to initialized `rlimit`.
|
||||||
|
let res = unsafe { libc::setrlimit(libc::RLIMIT_NOFILE, &raw const rlim) };
|
||||||
|
if res == 0 {
|
||||||
|
debug!("Increased open file descriptor limit from {old_limit} to {max_target}");
|
||||||
|
} else {
|
||||||
|
// Fallback: try setting to a reasonable high value (65,536) if max_target was rejected by the OS.
|
||||||
|
let fallback = 65_536.min(max_target);
|
||||||
|
if fallback > old_limit {
|
||||||
|
rlim.rlim_cur = fallback;
|
||||||
|
// SAFETY: Calling `setrlimit` with a valid resource and valid pointer to initialized `rlimit`.
|
||||||
|
if unsafe { libc::setrlimit(libc::RLIMIT_NOFILE, &raw const rlim) } == 0 {
|
||||||
|
debug!("Increased open file descriptor limit from {old_limit} to {fallback}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut current_rlim = libc::rlimit {
|
||||||
|
rlim_cur: 0,
|
||||||
|
rlim_max: 0,
|
||||||
|
};
|
||||||
|
// SAFETY: Passing a valid mutable pointer to a stack-allocated `rlimit` struct.
|
||||||
|
if unsafe { libc::getrlimit(libc::RLIMIT_NOFILE, &raw mut current_rlim) } == 0
|
||||||
|
&& current_rlim.rlim_cur < 4096
|
||||||
|
{
|
||||||
|
warn!(
|
||||||
|
"Open file descriptor limit is low ({}). Supporting >1000 concurrent players may fail with 'Too many open files'. \
|
||||||
|
Consider increasing the limit with `ulimit -n 65535` or setting `LimitNOFILE=65535` in systemd.",
|
||||||
|
current_rlim.rlim_cur
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -160,8 +160,7 @@ impl ChunkSender {
|
|||||||
epoch: u32,
|
epoch: u32,
|
||||||
version: JavaMinecraftVersion,
|
version: JavaMinecraftVersion,
|
||||||
) -> Option<PreparedBatch> {
|
) -> Option<PreparedBatch> {
|
||||||
if version >= JavaMinecraftVersion::V_1_20_2
|
if version >= JavaMinecraftVersion::V_1_20_2 && self.in_flight_batches >= self.max_in_flight
|
||||||
&& self.in_flight_batches >= self.max_in_flight
|
|
||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -149,14 +149,18 @@ impl PendingConnection {
|
|||||||
server: &Arc<Server>,
|
server: &Arc<Server>,
|
||||||
profile: &GameProfile,
|
profile: &GameProfile,
|
||||||
) -> Option<PacketHandlerResult> {
|
) -> Option<PacketHandlerResult> {
|
||||||
let mut pre_login_event = crate::plugin::api::events::player::async_player_pre_login::AsyncPlayerPreLoginEvent {
|
let mut pre_login_event =
|
||||||
player_name: profile.name.clone(),
|
crate::plugin::api::events::player::async_player_pre_login::AsyncPlayerPreLoginEvent {
|
||||||
player_uuid: profile.id,
|
player_name: profile.name.clone(),
|
||||||
ip_address: self.address,
|
player_uuid: profile.id,
|
||||||
kick_message: TextComponent::text("Disconnected"),
|
ip_address: self.address,
|
||||||
cancelled: false,
|
kick_message: TextComponent::text("Disconnected"),
|
||||||
};
|
cancelled: false,
|
||||||
server.plugin_manager.fire(server, &mut pre_login_event).await;
|
};
|
||||||
|
server
|
||||||
|
.plugin_manager
|
||||||
|
.fire(server, &mut pre_login_event)
|
||||||
|
.await;
|
||||||
if pre_login_event.cancelled {
|
if pre_login_event.cancelled {
|
||||||
self.kick(pre_login_event.kick_message).await;
|
self.kick(pre_login_event.kick_message).await;
|
||||||
return Some(PacketHandlerResult::Stop);
|
return Some(PacketHandlerResult::Stop);
|
||||||
|
|||||||
@ -1183,7 +1183,9 @@ impl JavaClient {
|
|||||||
player.clone(),
|
player.clone(),
|
||||||
ch.to_string(),
|
ch.to_string(),
|
||||||
);
|
);
|
||||||
server.plugin_manager.fire_blocking(server, &mut unreg_event);
|
server
|
||||||
|
.plugin_manager
|
||||||
|
.fire_blocking(server, &mut unreg_event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,14 +16,15 @@ impl JavaClient {
|
|||||||
if let Some(player_arc) = player.world().get_player_by_uuid(player.gameprofile.id)
|
if let Some(player_arc) = player.world().get_player_by_uuid(player.gameprofile.id)
|
||||||
&& let Some(server) = player.world().server.upgrade()
|
&& let Some(server) = player.world().server.upgrade()
|
||||||
{
|
{
|
||||||
let mut event = crate::plugin::api::events::player::player_edit_book::PlayerEditBookEvent {
|
let mut event =
|
||||||
player: player_arc,
|
crate::plugin::api::events::player::player_edit_book::PlayerEditBookEvent {
|
||||||
slot,
|
player: player_arc,
|
||||||
pages: pages.clone(),
|
slot,
|
||||||
title: title.clone(),
|
pages: pages.clone(),
|
||||||
signing,
|
title: title.clone(),
|
||||||
cancelled: false,
|
signing,
|
||||||
};
|
cancelled: false,
|
||||||
|
};
|
||||||
server.plugin_manager.fire_blocking(&server, &mut event);
|
server.plugin_manager.fire_blocking(&server, &mut event);
|
||||||
if event.cancelled {
|
if event.cancelled {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -169,7 +169,9 @@ impl JavaClient {
|
|||||||
world.clone(),
|
world.clone(),
|
||||||
player.inventory().held_item(),
|
player.inventory().held_item(),
|
||||||
);
|
);
|
||||||
server_arc.plugin_manager.fire_blocking(&server_arc, &mut abort_event);
|
server_arc
|
||||||
|
.plugin_manager
|
||||||
|
.fire_blocking(&server_arc, &mut abort_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
player.mining.store(false, Ordering::Relaxed);
|
player.mining.store(false, Ordering::Relaxed);
|
||||||
|
|||||||
@ -930,4 +930,3 @@ pub(crate) fn from_wit_entity_type(
|
|||||||
.copied()
|
.copied()
|
||||||
.ok_or_else(|| wasmtime::Error::msg(format!("Invalid entity type index: {index}")))
|
.ok_or_else(|| wasmtime::Error::msg(format!("Invalid entity type index: {index}")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1024,8 +1024,7 @@ impl pumpkin::plugin::world::HostWorld for PluginHostState {
|
|||||||
let world_ref = self.get_world_res(&world)?;
|
let world_ref = self.get_world_res(&world)?;
|
||||||
let world_provider = world_ref.provider.clone();
|
let world_provider = world_ref.provider.clone();
|
||||||
|
|
||||||
let internal_type =
|
let internal_type = super::entity::from_wit_entity_type(entity_type)?;
|
||||||
super::entity::from_wit_entity_type(entity_type)?;
|
|
||||||
|
|
||||||
let internal_pos = pumpkin_util::math::vector3::Vector3::new(pos.0, pos.1, pos.2);
|
let internal_pos = pumpkin_util::math::vector3::Vector3::new(pos.0, pos.1, pos.2);
|
||||||
let entity = crate::entity::r#type::from_type(
|
let entity = crate::entity::r#type::from_type(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user