mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
Improved synchronization primitives
- Replaced all `std::sync::Mutex` by `parking_lot::Mutex` and refactored implementation accordingly - Replaced all `Mutex<T> where T: Copy` by `crossbeam::AtomicCell<T>` and refactored implementation accordingly
This commit is contained in:
84
Cargo.lock
generated
84
Cargo.lock
generated
@@ -534,6 +534,28 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-queue",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.5"
|
||||
@@ -553,6 +575,15 @@ dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-queue"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.20"
|
||||
@@ -1409,6 +1440,16 @@ version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.22"
|
||||
@@ -1671,6 +1712,29 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.15"
|
||||
@@ -1858,6 +1922,7 @@ version = "0.1.0-dev"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
"crossbeam",
|
||||
"ctrlc",
|
||||
"digest 0.11.0-pre.9",
|
||||
"hmac",
|
||||
@@ -1868,6 +1933,7 @@ dependencies = [
|
||||
"num-bigint",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"parking_lot",
|
||||
"pumpkin-config",
|
||||
"pumpkin-core",
|
||||
"pumpkin-entity",
|
||||
@@ -1922,9 +1988,11 @@ version = "0.1.0"
|
||||
name = "pumpkin-inventory"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"crossbeam",
|
||||
"itertools 0.13.0",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"parking_lot",
|
||||
"pumpkin-world",
|
||||
"thiserror",
|
||||
]
|
||||
@@ -1991,6 +2059,7 @@ dependencies = [
|
||||
"noise",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"parking_lot",
|
||||
"pumpkin-core",
|
||||
"rand",
|
||||
"rayon",
|
||||
@@ -2117,6 +2186,15 @@ dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.6"
|
||||
@@ -2376,6 +2454,12 @@ version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.23"
|
||||
|
||||
@@ -32,7 +32,12 @@ tokio = { version = "1.40", features = [
|
||||
"io-util",
|
||||
"sync",
|
||||
] }
|
||||
|
||||
# Concurrency/Parallelism and Synchronization
|
||||
rayon = "1.10.0"
|
||||
parking_lot = "0.12.3"
|
||||
crossbeam = "0.8.4"
|
||||
|
||||
uuid = { version = "1.10.0", features = ["serde", "v3", "v4"] }
|
||||
derive_more = { version = "1.0.0", features = ["full"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
||||
@@ -2,6 +2,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::vector3::Vector3;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
/// Aka Block Position
|
||||
pub struct WorldPosition(pub Vector3<i32>);
|
||||
|
||||
|
||||
@@ -93,12 +93,16 @@ impl<T: Math + Copy> Neg for Vector3<T> {
|
||||
}
|
||||
|
||||
impl<T> From<(T, T, T)> for Vector3<T> {
|
||||
|
||||
#[inline(always)]
|
||||
fn from((x, y, z): (T, T, T)) -> Self {
|
||||
Vector3 { x, y, z }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Vector3<T>> for (T, T, T) {
|
||||
|
||||
#[inline(always)]
|
||||
fn from(vector: Vector3<T>) -> Self {
|
||||
(vector.x, vector.y, vector.z)
|
||||
}
|
||||
|
||||
@@ -10,4 +10,6 @@ pumpkin-world = { path = "../pumpkin-world"}
|
||||
num-traits = "0.2"
|
||||
num-derive = "0.4"
|
||||
thiserror = "1.0.63"
|
||||
itertools = "0.13.0"
|
||||
itertools = "0.13.0"
|
||||
parking_lot.workspace = true
|
||||
crossbeam.workspace = true
|
||||
|
||||
@@ -2,9 +2,10 @@ use crate::container_click::MouseDragType;
|
||||
use crate::{Container, InventoryError};
|
||||
use itertools::Itertools;
|
||||
use num_traits::Euclid;
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use pumpkin_world::item::ItemStack;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
use std::sync::Arc;
|
||||
#[derive(Debug, Default)]
|
||||
pub struct DragHandler(RwLock<HashMap<u64, Arc<Mutex<Drag>>>>);
|
||||
|
||||
@@ -23,10 +24,7 @@ impl DragHandler {
|
||||
drag_type,
|
||||
slots: vec![],
|
||||
};
|
||||
let mut drags = match self.0.write() {
|
||||
Ok(drags) => drags,
|
||||
Err(_) => Err(InventoryError::LockError)?,
|
||||
};
|
||||
let mut drags = self.0.write();
|
||||
drags.insert(container_id, Arc::new(Mutex::new(drag)));
|
||||
Ok(())
|
||||
}
|
||||
@@ -37,13 +35,10 @@ impl DragHandler {
|
||||
player: i32,
|
||||
slot: usize,
|
||||
) -> Result<(), InventoryError> {
|
||||
let drags = match self.0.read() {
|
||||
Ok(drags) => drags,
|
||||
Err(_) => Err(InventoryError::LockError)?,
|
||||
};
|
||||
let drags = self.0.read();
|
||||
match drags.get(&container_id) {
|
||||
Some(drag) => {
|
||||
let mut drag = drag.lock().unwrap();
|
||||
let mut drag = drag.lock();
|
||||
if drag.player != player {
|
||||
Err(InventoryError::MultiplePlayersDragging)?
|
||||
}
|
||||
@@ -68,13 +63,11 @@ impl DragHandler {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let Ok(mut drags) = self.0.write() else {
|
||||
Err(InventoryError::LockError)?
|
||||
};
|
||||
let mut drags = self.0.write();
|
||||
let Some((_, drag)) = drags.remove_entry(container_id) else {
|
||||
Err(InventoryError::OutOfOrderDragging)?
|
||||
};
|
||||
let drag = drag.lock().unwrap();
|
||||
let drag = drag.lock();
|
||||
|
||||
if player != drag.player {
|
||||
Err(InventoryError::MultiplePlayersDragging)?
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::container_click::MouseClick;
|
||||
use crate::player::PlayerInventory;
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use num_derive::{FromPrimitive, ToPrimitive};
|
||||
use pumpkin_world::item::ItemStack;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::{Container, WindowType};
|
||||
use pumpkin_world::item::ItemStack;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::Arc;
|
||||
use parking_lot::Mutex;
|
||||
|
||||
pub struct OpenContainer {
|
||||
players: Vec<i32>,
|
||||
|
||||
@@ -2,6 +2,7 @@ use std::sync::atomic::AtomicU32;
|
||||
|
||||
use crate::container_click::MouseClick;
|
||||
use crate::{handle_item_change, Container, InventoryError, WindowType};
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use pumpkin_world::item::ItemStack;
|
||||
|
||||
pub struct PlayerInventory {
|
||||
|
||||
@@ -151,7 +151,7 @@ pub enum PacketError {
|
||||
MalformedLength,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
pub enum ConnectionState {
|
||||
HandShake,
|
||||
Status,
|
||||
|
||||
@@ -19,6 +19,8 @@ serde_json = "1.0"
|
||||
static_assertions = "1.1.0"
|
||||
log.workspace = true
|
||||
|
||||
parking_lot.workspace = true
|
||||
|
||||
noise = "0.9.0"
|
||||
|
||||
rand = "0.8.5"
|
||||
|
||||
@@ -3,11 +3,12 @@ use std::{
|
||||
fs::OpenOptions,
|
||||
io::{Read, Seek},
|
||||
path::PathBuf,
|
||||
sync::{Arc, Mutex},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use flate2::{bufread::ZlibDecoder, read::GzDecoder};
|
||||
use itertools::Itertools;
|
||||
use parking_lot::Mutex;
|
||||
use pumpkin_core::math::vector2::Vector2;
|
||||
use rayon::prelude::*;
|
||||
use thiserror::Error;
|
||||
@@ -152,40 +153,40 @@ impl Level {
|
||||
dbg!("a");
|
||||
return;
|
||||
}
|
||||
if let Ok(mut loaded_chunks) = self.loaded_chunks.lock() {
|
||||
let channel = channel.clone();
|
||||
let mut loaded_chunks = self.loaded_chunks.lock();
|
||||
let channel = channel.clone();
|
||||
|
||||
// Check if chunks is already loaded
|
||||
if loaded_chunks.contains_key(at) {
|
||||
channel
|
||||
.blocking_send(Ok(loaded_chunks.get(at).unwrap().clone()))
|
||||
.expect("Failed sending ChunkData.");
|
||||
return;
|
||||
}
|
||||
let at = *at;
|
||||
let data = match &self.save_file {
|
||||
Some(save_file) => {
|
||||
match Self::read_chunk(save_file, at) {
|
||||
Err(WorldError::ChunkNotGenerated(_)) => {
|
||||
// This chunk was not generated yet.
|
||||
Ok(self.world_gen.generate_chunk(at))
|
||||
}
|
||||
// TODO this doesn't warn the user about the error. fix.
|
||||
result => result,
|
||||
}
|
||||
}
|
||||
None => {
|
||||
// There is no savefile yet -> generate the chunks
|
||||
Ok(self.world_gen.generate_chunk(at))
|
||||
}
|
||||
}
|
||||
.unwrap();
|
||||
let data = Arc::new(data);
|
||||
// Check if chunks is already loaded
|
||||
if loaded_chunks.contains_key(at) {
|
||||
channel
|
||||
.blocking_send(Ok(data.clone()))
|
||||
.blocking_send(Ok(loaded_chunks.get(at).unwrap().clone()))
|
||||
.expect("Failed sending ChunkData.");
|
||||
loaded_chunks.insert(at, data);
|
||||
return;
|
||||
}
|
||||
let at = *at;
|
||||
let data = match &self.save_file {
|
||||
Some(save_file) => {
|
||||
match Self::read_chunk(save_file, at) {
|
||||
Err(WorldError::ChunkNotGenerated(_)) => {
|
||||
// This chunk was not generated yet.
|
||||
Ok(self.world_gen.generate_chunk(at))
|
||||
}
|
||||
// TODO this doesn't warn the user about the error. fix.
|
||||
result => result,
|
||||
}
|
||||
}
|
||||
None => {
|
||||
// There is no savefile yet -> generate the chunks
|
||||
Ok(self.world_gen.generate_chunk(at))
|
||||
}
|
||||
}
|
||||
.unwrap();
|
||||
let data = Arc::new(data);
|
||||
channel
|
||||
.blocking_send(Ok(data.clone()))
|
||||
.expect("Failed sending ChunkData.");
|
||||
loaded_chunks.insert(at, data);
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,8 @@ log.workspace = true
|
||||
# networking
|
||||
mio = { version = "1.0.2", features = ["os-poll", "net"]}
|
||||
|
||||
parking_lot.workspace = true
|
||||
crossbeam.workspace = true
|
||||
uuid.workspace = true
|
||||
tokio.workspace = true
|
||||
rayon.workspace = true
|
||||
|
||||
@@ -42,10 +42,9 @@ impl Client {
|
||||
let version = handshake.protocol_version.0;
|
||||
self.protocol_version
|
||||
.store(version, std::sync::atomic::Ordering::Relaxed);
|
||||
let mut connection_state = self.connection_state.lock().unwrap();
|
||||
|
||||
*connection_state = handshake.next_state;
|
||||
if *connection_state != ConnectionState::Status {
|
||||
self.connection_state.store(handshake.next_state);
|
||||
if self.connection_state.load() != ConnectionState::Status {
|
||||
let protocol = version;
|
||||
match protocol.cmp(&(CURRENT_MC_PROTOCOL as i32)) {
|
||||
std::cmp::Ordering::Less => {
|
||||
@@ -85,7 +84,7 @@ impl Client {
|
||||
}
|
||||
// default game profile, when no online mode
|
||||
// TODO: make offline uuid
|
||||
let mut gameprofile = self.gameprofile.lock().unwrap();
|
||||
let mut gameprofile = self.gameprofile.lock();
|
||||
*gameprofile = Some(GameProfile {
|
||||
id: login_start.uuid,
|
||||
name: login_start.name,
|
||||
@@ -125,7 +124,7 @@ impl Client {
|
||||
self.enable_encryption(&shared_secret)
|
||||
.unwrap_or_else(|e| self.kick(&e.to_string()));
|
||||
|
||||
let mut gameprofile = self.gameprofile.lock().unwrap();
|
||||
let mut gameprofile = self.gameprofile.lock();
|
||||
|
||||
if BASIC_CONFIG.online_mode {
|
||||
let hash = Sha1::new()
|
||||
@@ -133,7 +132,7 @@ impl Client {
|
||||
.chain_update(&server.public_key_der)
|
||||
.finalize();
|
||||
let hash = auth_digest(&hash);
|
||||
let ip = self.address.lock().unwrap().ip();
|
||||
let ip = self.address.lock().ip();
|
||||
match authentication::authenticate(
|
||||
&gameprofile.as_ref().unwrap().name,
|
||||
&hash,
|
||||
@@ -204,7 +203,7 @@ impl Client {
|
||||
server: &Arc<Server>,
|
||||
_login_acknowledged: SLoginAcknowledged,
|
||||
) {
|
||||
*self.connection_state.lock().unwrap() = ConnectionState::Config;
|
||||
self.connection_state.store(ConnectionState::Config);
|
||||
server.send_brand(self);
|
||||
|
||||
let resource_config = &ADVANCED_CONFIG.resource_pack;
|
||||
@@ -239,8 +238,8 @@ impl Client {
|
||||
_server: &Arc<Server>,
|
||||
client_information: SClientInformationConfig,
|
||||
) {
|
||||
dbg!("got client settings");
|
||||
*self.config.lock().unwrap() = Some(PlayerConfig {
|
||||
dbg!("got client settings");
|
||||
*self.config.lock() = Some(PlayerConfig {
|
||||
locale: client_information.locale,
|
||||
view_distance: client_information.view_distance,
|
||||
chat_mode: ChatMode::from_i32(client_information.chat_mode.into()).unwrap(),
|
||||
@@ -258,7 +257,7 @@ impl Client {
|
||||
{
|
||||
dbg!("got a client brand");
|
||||
match String::from_utf8(plugin_message.data) {
|
||||
Ok(brand) => *self.brand.lock().unwrap() = Some(brand),
|
||||
Ok(brand) => *self.brand.lock() = Some(brand),
|
||||
Err(e) => self.kick(&e.to_string()),
|
||||
}
|
||||
}
|
||||
@@ -283,7 +282,7 @@ impl Client {
|
||||
_config_acknowledged: SAcknowledgeFinishConfig,
|
||||
) {
|
||||
dbg!("config acknowledged");
|
||||
*self.connection_state.lock().unwrap() = ConnectionState::Play;
|
||||
self.connection_state.store(ConnectionState::Play);
|
||||
self.make_player
|
||||
.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::entity::player::Player;
|
||||
use crate::server::Server;
|
||||
use itertools::Itertools;
|
||||
use parking_lot::Mutex;
|
||||
use pumpkin_core::text::TextComponent;
|
||||
use pumpkin_core::GameMode;
|
||||
use pumpkin_inventory::container_click::{
|
||||
@@ -16,11 +17,11 @@ use pumpkin_protocol::client::play::{
|
||||
use pumpkin_protocol::server::play::SClickContainer;
|
||||
use pumpkin_protocol::slot::Slot;
|
||||
use pumpkin_world::item::ItemStack;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::Arc;
|
||||
|
||||
impl Player {
|
||||
pub fn open_container(&self, server: &Arc<Server>, minecraft_menu_id: &str) {
|
||||
let inventory = self.inventory.lock().unwrap();
|
||||
let inventory = self.inventory.lock();
|
||||
inventory
|
||||
.state_id
|
||||
.store(0, std::sync::atomic::Ordering::Relaxed);
|
||||
@@ -28,7 +29,7 @@ impl Player {
|
||||
let container = self.get_open_container(server);
|
||||
let mut container = container
|
||||
.as_ref()
|
||||
.map(|container| container.lock().unwrap());
|
||||
.map(|container| container.lock());
|
||||
let menu_protocol_id = (*pumpkin_world::global_registry::REGISTRY
|
||||
.get("minecraft:menu")
|
||||
.unwrap()
|
||||
@@ -54,7 +55,7 @@ impl Player {
|
||||
}
|
||||
|
||||
pub fn set_container_content(&self, container: Option<&mut Box<dyn Container>>) {
|
||||
let mut inventory = self.inventory.lock().unwrap();
|
||||
let mut inventory = self.inventory.lock();
|
||||
|
||||
let total_opened_containers = inventory.total_opened_containers;
|
||||
let container = OptionallyCombinedContainer::new(&mut inventory, container);
|
||||
@@ -66,7 +67,7 @@ impl Player {
|
||||
.collect_vec();
|
||||
|
||||
let carried_item = {
|
||||
if let Some(item) = self.carried_item.lock().unwrap().as_ref() {
|
||||
if let Some(item) = self.carried_item.load().as_ref() {
|
||||
item.into()
|
||||
} else {
|
||||
Slot::empty()
|
||||
@@ -87,7 +88,7 @@ impl Player {
|
||||
|
||||
/// The official Minecraft client is weird, and will always just close *any* window that is opened when this gets sent
|
||||
pub fn close_container(&self) {
|
||||
let mut inventory = self.inventory.lock().unwrap();
|
||||
let mut inventory = self.inventory.lock();
|
||||
inventory.total_opened_containers += 1;
|
||||
self.client
|
||||
.send_packet(&CCloseContainer::new(inventory.total_opened_containers))
|
||||
@@ -99,7 +100,7 @@ impl Player {
|
||||
) {
|
||||
let (id, value) = window_property.into_tuple();
|
||||
self.client.send_packet(&CSetContainerProperty::new(
|
||||
self.inventory.lock().unwrap().total_opened_containers,
|
||||
self.inventory.lock().total_opened_containers,
|
||||
id,
|
||||
value,
|
||||
));
|
||||
@@ -113,13 +114,12 @@ impl Player {
|
||||
let opened_container = self.get_open_container(server);
|
||||
let mut opened_container = opened_container
|
||||
.as_ref()
|
||||
.map(|container| container.lock().unwrap());
|
||||
.map(|container| container.lock());
|
||||
let drag_handler = &server.drag_handler;
|
||||
|
||||
let state_id = self
|
||||
.inventory
|
||||
.lock()
|
||||
.unwrap()
|
||||
.state_id
|
||||
.load(std::sync::atomic::Ordering::Relaxed);
|
||||
// This is just checking for regular desync, client hasn't done anything malicious
|
||||
@@ -129,7 +129,7 @@ impl Player {
|
||||
}
|
||||
|
||||
if opened_container.is_some() {
|
||||
if packet.window_id != self.inventory.lock().unwrap().total_opened_containers {
|
||||
if packet.window_id != self.inventory.lock().total_opened_containers {
|
||||
return Err(InventoryError::ClosedContainerInteract(self.entity_id()));
|
||||
}
|
||||
} else if packet.window_id != 0 {
|
||||
@@ -191,7 +191,7 @@ impl Player {
|
||||
drop(opened_container);
|
||||
self.send_whole_container_change(server).await?;
|
||||
} else if let container_click::Slot::Normal(slot_index) = click.slot {
|
||||
let mut inventory = self.inventory.lock().unwrap();
|
||||
let mut inventory = self.inventory.lock();
|
||||
let combined_container =
|
||||
OptionallyCombinedContainer::new(&mut inventory, Some(&mut opened_container));
|
||||
if let Some(slot) = combined_container.get_slot_excluding_inventory(slot_index) {
|
||||
@@ -211,15 +211,20 @@ impl Player {
|
||||
mouse_click: MouseClick,
|
||||
slot: container_click::Slot,
|
||||
) -> Result<(), InventoryError> {
|
||||
let mut inventory = self.inventory.lock().unwrap();
|
||||
let mut inventory = self.inventory.lock();
|
||||
let mut container = OptionallyCombinedContainer::new(&mut inventory, opened_container);
|
||||
|
||||
match slot {
|
||||
container_click::Slot::Normal(slot) => container.handle_item_change(
|
||||
&mut self.carried_item.lock().unwrap(),
|
||||
slot,
|
||||
mouse_click,
|
||||
),
|
||||
container_click::Slot::Normal(slot) => {
|
||||
let mut carried_item = self.carried_item.load();
|
||||
let res = container.handle_item_change(
|
||||
&mut carried_item,
|
||||
slot,
|
||||
mouse_click,
|
||||
);
|
||||
self.carried_item.store(carried_item);
|
||||
res
|
||||
},
|
||||
container_click::Slot::OutsideInventory => Ok(()),
|
||||
}
|
||||
}
|
||||
@@ -229,7 +234,7 @@ impl Player {
|
||||
opened_container: Option<&mut Box<dyn Container>>,
|
||||
slot: container_click::Slot,
|
||||
) -> Result<(), InventoryError> {
|
||||
let mut inventory = self.inventory.lock().unwrap();
|
||||
let mut inventory = self.inventory.lock();
|
||||
let mut container = OptionallyCombinedContainer::new(&mut inventory, opened_container);
|
||||
|
||||
match slot {
|
||||
@@ -281,7 +286,7 @@ impl Player {
|
||||
KeyClick::Slot(slot) => slot,
|
||||
KeyClick::Offhand => 45,
|
||||
};
|
||||
let mut inventory = self.inventory.lock().unwrap();
|
||||
let mut inventory = self.inventory.lock();
|
||||
let mut changing_item_slot = inventory.get_slot(changing_slot as usize)?.to_owned();
|
||||
let mut container = OptionallyCombinedContainer::new(&mut inventory, opened_container);
|
||||
|
||||
@@ -295,13 +300,13 @@ impl Player {
|
||||
opened_container: Option<&mut Box<dyn Container>>,
|
||||
slot: usize,
|
||||
) -> Result<(), InventoryError> {
|
||||
if *self.gamemode.lock().unwrap() != GameMode::Creative {
|
||||
if self.gamemode.load() != GameMode::Creative {
|
||||
return Err(InventoryError::PermissionError);
|
||||
}
|
||||
let mut inventory = self.inventory.lock().unwrap();
|
||||
let mut inventory = self.inventory.lock();
|
||||
let mut container = OptionallyCombinedContainer::new(&mut inventory, opened_container);
|
||||
if let Some(Some(item)) = container.all_slots().get_mut(slot) {
|
||||
*self.carried_item.lock().unwrap() = Some(item.to_owned())
|
||||
self.carried_item.store(Some(item.to_owned()));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -311,7 +316,7 @@ impl Player {
|
||||
opened_container: Option<&mut Box<dyn Container>>,
|
||||
slot: usize,
|
||||
) -> Result<(), InventoryError> {
|
||||
let mut inventory = self.inventory.lock().unwrap();
|
||||
let mut inventory = self.inventory.lock();
|
||||
let mut container = OptionallyCombinedContainer::new(&mut inventory, opened_container);
|
||||
let mut slots = container.all_slots();
|
||||
|
||||
@@ -340,7 +345,7 @@ impl Player {
|
||||
}
|
||||
}
|
||||
}
|
||||
*self.carried_item.lock().unwrap() = Some(carried_item);
|
||||
self.carried_item.store(Some(carried_item));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -358,7 +363,7 @@ impl Player {
|
||||
match mouse_drag_state {
|
||||
MouseDragState::Start(drag_type) => {
|
||||
if drag_type == MouseDragType::Middle
|
||||
&& *self.gamemode.lock().unwrap() != GameMode::Creative
|
||||
&& self.gamemode.load() != GameMode::Creative
|
||||
{
|
||||
Err(InventoryError::PermissionError)?
|
||||
}
|
||||
@@ -366,15 +371,18 @@ impl Player {
|
||||
}
|
||||
MouseDragState::AddSlot(slot) => drag_handler.add_slot(container_id, player_id, slot),
|
||||
MouseDragState::End => {
|
||||
let mut inventory = self.inventory.lock().unwrap();
|
||||
let mut inventory = self.inventory.lock();
|
||||
let mut container =
|
||||
OptionallyCombinedContainer::new(&mut inventory, opened_container);
|
||||
drag_handler.apply_drag(
|
||||
&mut self.carried_item.lock().unwrap(),
|
||||
let mut carried_item = self.carried_item.load();
|
||||
let res = drag_handler.apply_drag(
|
||||
&mut carried_item,
|
||||
&mut container,
|
||||
&container_id,
|
||||
player_id,
|
||||
)
|
||||
);
|
||||
self.carried_item.store(carried_item);
|
||||
res
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -383,10 +391,9 @@ impl Player {
|
||||
let player_ids = {
|
||||
let open_containers = server
|
||||
.open_containers
|
||||
.read()
|
||||
.expect("open_containers is poisoned");
|
||||
.read();
|
||||
open_containers
|
||||
.get(&self.open_container.lock().unwrap().unwrap())
|
||||
.get(&self.open_container.load().unwrap())
|
||||
.unwrap()
|
||||
.all_player_ids()
|
||||
.into_iter()
|
||||
@@ -403,7 +410,6 @@ impl Player {
|
||||
.world
|
||||
.current_players
|
||||
.lock()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.filter_map(|(token, player)| {
|
||||
if *token != player_token {
|
||||
@@ -428,7 +434,7 @@ impl Player {
|
||||
slot: Slot,
|
||||
) -> Result<(), InventoryError> {
|
||||
for player in self.get_current_players_in_container(server).await {
|
||||
let inventory = player.inventory.lock().unwrap();
|
||||
let inventory = player.inventory.lock();
|
||||
let total_opened_containers = inventory.total_opened_containers;
|
||||
|
||||
// Returns previous value
|
||||
@@ -451,14 +457,14 @@ impl Player {
|
||||
|
||||
for player in players {
|
||||
let container = player.get_open_container(server);
|
||||
let mut container = container.as_ref().map(|v| v.lock().unwrap());
|
||||
let mut container = container.as_ref().map(|v| v.lock());
|
||||
player.set_container_content(container.as_deref_mut());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_open_container(&self, server: &Server) -> Option<Arc<Mutex<Box<dyn Container>>>> {
|
||||
if let Some(id) = *self.open_container.lock().unwrap() {
|
||||
if let Some(id) = self.open_container.load() {
|
||||
server.try_get_container(self.entity_id(), id)
|
||||
} else {
|
||||
None
|
||||
|
||||
@@ -2,8 +2,7 @@ use std::{
|
||||
io::{self, Write},
|
||||
net::SocketAddr,
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicI32},
|
||||
Arc, Mutex,
|
||||
atomic::{AtomicBool, AtomicI32}, Arc,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -13,7 +12,9 @@ use crate::{
|
||||
};
|
||||
|
||||
use authentication::GameProfile;
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use mio::{event::Event, net::TcpStream, Token};
|
||||
use parking_lot::Mutex;
|
||||
use pumpkin_core::text::TextComponent;
|
||||
use pumpkin_protocol::{
|
||||
bytebuf::{packet_id::Packet, DeserializerError},
|
||||
@@ -71,7 +72,7 @@ pub struct Client {
|
||||
pub brand: Mutex<Option<String>>,
|
||||
|
||||
pub protocol_version: AtomicI32,
|
||||
pub connection_state: Mutex<ConnectionState>,
|
||||
pub connection_state: AtomicCell<ConnectionState>,
|
||||
pub encryption: AtomicBool,
|
||||
pub closed: AtomicBool,
|
||||
pub token: Token,
|
||||
@@ -93,7 +94,7 @@ impl Client {
|
||||
brand: Mutex::new(None),
|
||||
token,
|
||||
address: Mutex::new(address),
|
||||
connection_state: Mutex::new(ConnectionState::HandShake),
|
||||
connection_state: AtomicCell::new(ConnectionState::HandShake),
|
||||
connection: Arc::new(Mutex::new(connection)),
|
||||
enc: Arc::new(Mutex::new(PacketEncoder::default())),
|
||||
dec: Arc::new(Mutex::new(PacketDecoder::default())),
|
||||
@@ -106,7 +107,7 @@ impl Client {
|
||||
|
||||
/// adds a Incoming packet to the queue
|
||||
pub fn add_packet(&self, packet: RawPacket) {
|
||||
let mut client_packets_queue = self.client_packets_queue.lock().unwrap();
|
||||
let mut client_packets_queue = self.client_packets_queue.lock();
|
||||
client_packets_queue.push(packet);
|
||||
}
|
||||
|
||||
@@ -120,8 +121,8 @@ impl Client {
|
||||
let crypt_key: [u8; 16] = shared_secret
|
||||
.try_into()
|
||||
.map_err(|_| EncryptionError::SharedWrongLength)?;
|
||||
self.dec.lock().unwrap().enable_encryption(&crypt_key);
|
||||
self.enc.lock().unwrap().enable_encryption(&crypt_key);
|
||||
self.dec.lock().enable_encryption(&crypt_key);
|
||||
self.enc.lock().enable_encryption(&crypt_key);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -129,20 +130,18 @@ impl Client {
|
||||
pub fn set_compression(&self, compression: Option<(u32, u32)>) {
|
||||
self.dec
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_compression(compression.map(|v| v.0));
|
||||
self.enc.lock().unwrap().set_compression(compression);
|
||||
self.enc.lock().set_compression(compression);
|
||||
}
|
||||
|
||||
/// Send a Clientbound Packet to the Client
|
||||
pub fn send_packet<P: ClientPacket>(&self, packet: &P) {
|
||||
// assert!(!self.closed);
|
||||
let mut enc = self.enc.lock().unwrap();
|
||||
let mut enc = self.enc.lock();
|
||||
enc.append_packet(packet)
|
||||
.unwrap_or_else(|e| self.kick(&e.to_string()));
|
||||
self.connection
|
||||
.lock()
|
||||
.unwrap()
|
||||
.write_all(&enc.take())
|
||||
.map_err(|_| PacketError::ConnectionWrite)
|
||||
.unwrap_or_else(|e| self.kick(&e.to_string()));
|
||||
@@ -151,18 +150,17 @@ impl Client {
|
||||
pub fn try_send_packet<P: ClientPacket>(&self, packet: &P) -> Result<(), PacketError> {
|
||||
// assert!(!self.closed);
|
||||
|
||||
let mut enc = self.enc.lock().unwrap();
|
||||
let mut enc = self.enc.lock();
|
||||
enc.append_packet(packet)?;
|
||||
self.connection
|
||||
.lock()
|
||||
.unwrap()
|
||||
.write_all(&enc.take())
|
||||
.map_err(|_| PacketError::ConnectionWrite)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn process_packets(&self, server: &Arc<Server>) {
|
||||
while let Some(mut packet) = self.client_packets_queue.lock().unwrap().pop() {
|
||||
while let Some(mut packet) = self.client_packets_queue.lock().pop() {
|
||||
match self.handle_packet(server, &mut packet).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
@@ -182,7 +180,7 @@ impl Client {
|
||||
) -> Result<(), DeserializerError> {
|
||||
// TODO: handle each packet's Error instead of calling .unwrap()
|
||||
let bytebuf = &mut packet.bytebuf;
|
||||
let locked_state = self.connection_state.lock().unwrap();
|
||||
let locked_state = self.connection_state.load();
|
||||
let state = locked_state.clone();
|
||||
drop(locked_state);
|
||||
match state {
|
||||
@@ -291,7 +289,7 @@ impl Client {
|
||||
let mut bytes_read = 0;
|
||||
loop {
|
||||
let connection = self.connection.clone();
|
||||
let mut connection = connection.lock().unwrap();
|
||||
let mut connection = connection.lock();
|
||||
match connection.read(&mut received_data[bytes_read..]) {
|
||||
Ok(0) => {
|
||||
// Reading 0 bytes means the other side has closed the
|
||||
@@ -313,7 +311,7 @@ impl Client {
|
||||
}
|
||||
|
||||
if bytes_read != 0 {
|
||||
let mut dec = self.dec.lock().unwrap();
|
||||
let mut dec = self.dec.lock();
|
||||
dec.queue_slice(&received_data[..bytes_read]);
|
||||
match dec.decode() {
|
||||
Ok(packet) => {
|
||||
@@ -331,7 +329,7 @@ impl Client {
|
||||
/// Kicks the Client with a reason depending on the connection state
|
||||
pub fn kick(&self, reason: &str) {
|
||||
dbg!(reason);
|
||||
match *self.connection_state.lock().unwrap() {
|
||||
match self.connection_state.load() {
|
||||
ConnectionState::Login => {
|
||||
self.try_send_packet(&CLoginDisconnect::new(
|
||||
&serde_json::to_string_pretty(&reason).unwrap_or("".into()),
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::{
|
||||
use num_traits::FromPrimitive;
|
||||
use pumpkin_config::ADVANCED_CONFIG;
|
||||
use pumpkin_core::{
|
||||
math::{position::WorldPosition, wrap_degrees},
|
||||
math::{position::WorldPosition, vector3::Vector3, wrap_degrees},
|
||||
text::TextComponent,
|
||||
GameMode,
|
||||
};
|
||||
@@ -46,7 +46,7 @@ impl Player {
|
||||
_server: &Arc<Server>,
|
||||
confirm_teleport: SConfirmTeleport,
|
||||
) {
|
||||
let mut awaiting_teleport = self.awaiting_teleport.lock().unwrap();
|
||||
let mut awaiting_teleport = self.awaiting_teleport.lock();
|
||||
if let Some((id, position)) = awaiting_teleport.as_ref() {
|
||||
if id == &confirm_teleport.teleport_id {
|
||||
// we should set the pos now to that we requested in the teleport packet, Is may fixed issues when the client sended position packets while being teleported
|
||||
@@ -82,14 +82,14 @@ impl Player {
|
||||
Self::clamp_vertical(position.feet_y),
|
||||
Self::clamp_horizontal(position.z),
|
||||
);
|
||||
let mut last_position = self.last_position.lock().unwrap();
|
||||
let pos = entity.pos.lock().unwrap();
|
||||
*last_position = *pos;
|
||||
let pos = entity.pos.load();
|
||||
self.last_position.store(pos);
|
||||
let last_position = self.last_position.load();
|
||||
entity
|
||||
.on_ground
|
||||
.store(position.ground, std::sync::atomic::Ordering::Relaxed);
|
||||
let entity_id = entity.entity_id;
|
||||
let (x, y, z) = (*pos).into();
|
||||
let Vector3 { x, y, z } = pos;
|
||||
let (lastx, lasty, lastz) = (last_position.x, last_position.y, last_position.z);
|
||||
let world = &entity.world;
|
||||
|
||||
@@ -142,9 +142,9 @@ impl Player {
|
||||
Self::clamp_vertical(position_rotation.feet_y),
|
||||
Self::clamp_horizontal(position_rotation.z),
|
||||
);
|
||||
let mut last_position = self.last_position.lock().unwrap();
|
||||
let pos = entity.pos.lock().unwrap();
|
||||
*last_position = *pos;
|
||||
let pos = entity.pos.load();
|
||||
self.last_position.store(pos);
|
||||
let last_position = self.last_position.load();
|
||||
entity.on_ground.store(
|
||||
position_rotation.ground,
|
||||
std::sync::atomic::Ordering::Relaxed,
|
||||
@@ -155,10 +155,10 @@ impl Player {
|
||||
);
|
||||
|
||||
let entity_id = entity.entity_id;
|
||||
let (x, y, z) = (*pos).into();
|
||||
let Vector3 {x, y, z } = pos;
|
||||
let (lastx, lasty, lastz) = (last_position.x, last_position.y, last_position.z);
|
||||
let yaw = modulus(*entity.yaw.lock().unwrap() * 256.0 / 360.0, 256.0);
|
||||
let pitch = modulus(*entity.pitch.lock().unwrap() * 256.0 / 360.0, 256.0);
|
||||
let yaw = modulus(entity.yaw.load() * 256.0 / 360.0, 256.0);
|
||||
let pitch = modulus(entity.pitch.load() * 256.0 / 360.0, 256.0);
|
||||
// let head_yaw = (entity.head_yaw * 256.0 / 360.0).floor();
|
||||
let world = &entity.world;
|
||||
|
||||
@@ -210,8 +210,8 @@ impl Player {
|
||||
);
|
||||
// send new position to all other players
|
||||
let entity_id = entity.entity_id;
|
||||
let yaw = modulus(*entity.yaw.lock().unwrap() * 256.0 / 360.0, 256.0);
|
||||
let pitch = modulus(*entity.pitch.lock().unwrap() * 256.0 / 360.0, 256.0);
|
||||
let yaw = modulus(entity.yaw.load() * 256.0 / 360.0, 256.0);
|
||||
let pitch = modulus(entity.pitch.load() * 256.0 / 360.0, 256.0);
|
||||
// let head_yaw = modulus(entity.head_yaw * 256.0 / 360.0, 256.0);
|
||||
|
||||
let world = &entity.world;
|
||||
@@ -350,7 +350,7 @@ impl Player {
|
||||
Hand::from_i32(client_information.main_hand.into()),
|
||||
ChatMode::from_i32(client_information.chat_mode.into()),
|
||||
) {
|
||||
*self.config.lock().unwrap() = PlayerConfig {
|
||||
*self.config.lock() = PlayerConfig {
|
||||
locale: client_information.locale,
|
||||
view_distance: client_information.view_distance,
|
||||
chat_mode,
|
||||
@@ -383,19 +383,19 @@ impl Player {
|
||||
if let Some(player) = attacked_player {
|
||||
let victem_entity = &player.entity;
|
||||
if config.protect_creative
|
||||
&& *player.gamemode.lock().unwrap() == GameMode::Creative
|
||||
&& player.gamemode.load() == GameMode::Creative
|
||||
{
|
||||
return;
|
||||
}
|
||||
if config.knockback {
|
||||
let yaw = entity.yaw.lock().unwrap();
|
||||
let yaw = entity.yaw.load();
|
||||
let strength = 1.0;
|
||||
let mut victem_velocity = victem_entity.velocity.lock().unwrap();
|
||||
let saved_velo = *victem_velocity;
|
||||
let victem_velocity = victem_entity.velocity.load();
|
||||
let saved_velo = victem_velocity;
|
||||
victem_entity.knockback(
|
||||
strength * 0.5,
|
||||
(*yaw * (PI / 180.0)).sin() as f64,
|
||||
-(*yaw * (PI / 180.0)).cos() as f64,
|
||||
(yaw * (PI / 180.0)).sin() as f64,
|
||||
-(yaw * (PI / 180.0)).cos() as f64,
|
||||
);
|
||||
let packet = &CEntityVelocity::new(
|
||||
&entity_id,
|
||||
@@ -403,16 +403,16 @@ impl Player {
|
||||
victem_velocity.y as f32,
|
||||
victem_velocity.z as f32,
|
||||
);
|
||||
let mut velocity = entity.velocity.lock().unwrap();
|
||||
*velocity = velocity.multiply(0.6, 1.0, 0.6);
|
||||
let velocity = entity.velocity.load();
|
||||
victem_entity.velocity.store(velocity.multiply(0.6, 1.0, 0.6));
|
||||
|
||||
*victem_velocity = saved_velo;
|
||||
victem_entity.velocity.store(saved_velo);
|
||||
player.client.send_packet(packet);
|
||||
}
|
||||
if config.hurt_animation {
|
||||
world.broadcast_packet_all(&CHurtAnimation::new(
|
||||
&entity_id,
|
||||
*entity.yaw.lock().unwrap(),
|
||||
entity.yaw.load(),
|
||||
))
|
||||
}
|
||||
if config.swing {}
|
||||
@@ -441,7 +441,7 @@ impl Player {
|
||||
}
|
||||
// TODO: do validation
|
||||
// TODO: Config
|
||||
if *self.gamemode.lock().unwrap() == GameMode::Creative {
|
||||
if self.gamemode.load() == GameMode::Creative {
|
||||
let location = player_action.location;
|
||||
// Block break & block break sound
|
||||
// TODO: currently this is always dirt replace it
|
||||
@@ -509,7 +509,7 @@ impl Player {
|
||||
}
|
||||
|
||||
if let Some(face) = BlockFace::from_i32(use_item_on.face.0) {
|
||||
if let Some(item) = self.inventory.lock().unwrap().held_item() {
|
||||
if let Some(item) = self.inventory.lock().held_item() {
|
||||
let minecraft_id = global_registry::find_minecraft_id(
|
||||
global_registry::ITEM_REGISTRY,
|
||||
item.item_id,
|
||||
@@ -545,7 +545,7 @@ impl Player {
|
||||
if !(0..=8).contains(&slot) {
|
||||
self.kick(TextComponent::text("Invalid held slot"))
|
||||
}
|
||||
self.inventory.lock().unwrap().set_selected(slot as usize);
|
||||
self.inventory.lock().set_selected(slot as usize);
|
||||
}
|
||||
|
||||
pub fn handle_set_creative_slot(
|
||||
@@ -553,10 +553,10 @@ impl Player {
|
||||
_server: &Arc<Server>,
|
||||
packet: SSetCreativeSlot,
|
||||
) -> Result<(), InventoryError> {
|
||||
if *self.gamemode.lock().unwrap() != GameMode::Creative {
|
||||
if self.gamemode.load() != GameMode::Creative {
|
||||
return Err(InventoryError::PermissionError);
|
||||
}
|
||||
self.inventory.lock().unwrap().set_slot(
|
||||
self.inventory.lock().set_slot(
|
||||
packet.slot as usize,
|
||||
packet.clicked_item.to_item(),
|
||||
false,
|
||||
@@ -570,19 +570,17 @@ impl Player {
|
||||
// window_id 0 represents both 9x1 Generic AND inventory here
|
||||
self.inventory
|
||||
.lock()
|
||||
.unwrap()
|
||||
.state_id
|
||||
.store(0, std::sync::atomic::Ordering::Relaxed);
|
||||
let mut open_container = self.open_container.lock().unwrap();
|
||||
if let Some(id) = *open_container {
|
||||
let open_container = self.open_container.load();
|
||||
if let Some(id) = open_container {
|
||||
let mut open_containers = server
|
||||
.open_containers
|
||||
.write()
|
||||
.expect("open_containers got poisoned");
|
||||
.write();
|
||||
if let Some(container) = open_containers.get_mut(&id) {
|
||||
container.remove_player(self.entity_id())
|
||||
}
|
||||
*open_container = None;
|
||||
self.open_container.store(None);
|
||||
}
|
||||
let Some(_window_type) = WindowType::from_u8(packet.window_id) else {
|
||||
self.kick(TextComponent::text("Invalid window ID"));
|
||||
|
||||
@@ -11,12 +11,11 @@ pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> {
|
||||
CommandTree::new(NAMES, DESCRIPTION).execute(&|sender, server, _| {
|
||||
if let Some(player) = sender.as_mut_player() {
|
||||
let entity_id = player.entity_id();
|
||||
*player.open_container.lock().unwrap() = Some(0);
|
||||
player.open_container.store(Some(0));
|
||||
{
|
||||
let mut open_containers = server
|
||||
.open_containers
|
||||
.write()
|
||||
.expect("open_containers got poisoned");
|
||||
.write();
|
||||
match open_containers.get_mut(&0) {
|
||||
Some(ender_chest) => {
|
||||
ender_chest.add_player(entity_id);
|
||||
|
||||
@@ -65,7 +65,7 @@ pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> {
|
||||
let gamemode = parse_arg_gamemode(args)?;
|
||||
|
||||
return if let Player(target) = sender {
|
||||
if *target.gamemode.lock().unwrap() == gamemode {
|
||||
if target.gamemode.load() == gamemode {
|
||||
target.send_system_message(TextComponent::text(&format!(
|
||||
"You already in {:?} gamemode",
|
||||
gamemode
|
||||
@@ -89,7 +89,7 @@ pub(crate) fn init_command_tree<'a>() -> CommandTree<'a> {
|
||||
let gamemode = parse_arg_gamemode(args)?;
|
||||
let target = parse_arg_player(sender, ARG_TARGET, args)?;
|
||||
|
||||
if *target.gamemode.lock().unwrap() == gamemode {
|
||||
if target.gamemode.load() == gamemode {
|
||||
target.send_system_message(TextComponent::text(&format!(
|
||||
"You already in {:?} gamemode",
|
||||
gamemode
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::sync::{atomic::AtomicBool, Arc, Mutex};
|
||||
use std::sync::{atomic::AtomicBool, Arc};
|
||||
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use pumpkin_core::math::{
|
||||
get_section_cord, position::WorldPosition, vector2::Vector2, vector3::Vector3,
|
||||
};
|
||||
@@ -18,24 +19,24 @@ pub struct Entity {
|
||||
pub entity_type: EntityType,
|
||||
pub world: Arc<World>,
|
||||
|
||||
pub pos: Mutex<Vector3<f64>>,
|
||||
pub block_pos: Mutex<WorldPosition>,
|
||||
pub chunk_pos: Mutex<Vector2<i32>>,
|
||||
pub pos: AtomicCell<Vector3<f64>>,
|
||||
pub block_pos: AtomicCell<WorldPosition>,
|
||||
pub chunk_pos: AtomicCell<Vector2<i32>>,
|
||||
|
||||
pub sneaking: AtomicBool,
|
||||
pub sprinting: AtomicBool,
|
||||
pub fall_flying: AtomicBool,
|
||||
pub velocity: Mutex<Vector3<f64>>,
|
||||
pub velocity: AtomicCell<Vector3<f64>>,
|
||||
|
||||
// Should be not trusted
|
||||
pub on_ground: AtomicBool,
|
||||
|
||||
pub yaw: Mutex<f32>,
|
||||
pub head_yaw: Mutex<f32>,
|
||||
pub pitch: Mutex<f32>,
|
||||
pub yaw: AtomicCell<f32>,
|
||||
pub head_yaw: AtomicCell<f32>,
|
||||
pub pitch: AtomicCell<f32>,
|
||||
// TODO: Change this in diffrent poses
|
||||
pub standing_eye_height: f32,
|
||||
pub pose: Mutex<EntityPose>,
|
||||
pub pose: AtomicCell<EntityPose>,
|
||||
}
|
||||
|
||||
impl Entity {
|
||||
@@ -49,41 +50,41 @@ impl Entity {
|
||||
entity_id,
|
||||
entity_type,
|
||||
on_ground: AtomicBool::new(false),
|
||||
pos: Mutex::new(Vector3::new(0.0, 0.0, 0.0)),
|
||||
block_pos: Mutex::new(WorldPosition(Vector3::new(0, 0, 0))),
|
||||
chunk_pos: Mutex::new(Vector2::new(0, 0)),
|
||||
pos: AtomicCell::new(Vector3::new(0.0, 0.0, 0.0)),
|
||||
block_pos: AtomicCell::new(WorldPosition(Vector3::new(0, 0, 0))),
|
||||
chunk_pos: AtomicCell::new(Vector2::new(0, 0)),
|
||||
sneaking: AtomicBool::new(false),
|
||||
world,
|
||||
sprinting: AtomicBool::new(false),
|
||||
fall_flying: AtomicBool::new(false),
|
||||
yaw: Mutex::new(0.0),
|
||||
head_yaw: Mutex::new(0.0),
|
||||
pitch: Mutex::new(0.0),
|
||||
velocity: Mutex::new(Vector3::new(0.0, 0.0, 0.0)),
|
||||
yaw: AtomicCell::new(0.0),
|
||||
head_yaw: AtomicCell::new(0.0),
|
||||
pitch: AtomicCell::new(0.0),
|
||||
velocity: AtomicCell::new(Vector3::new(0.0, 0.0, 0.0)),
|
||||
standing_eye_height,
|
||||
pose: Mutex::new(EntityPose::Standing),
|
||||
pose: AtomicCell::new(EntityPose::Standing),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_pos(&self, x: f64, y: f64, z: f64) {
|
||||
let mut pos = self.pos.lock().unwrap();
|
||||
let pos = self.pos.load();
|
||||
if pos.x != x || pos.y != y || pos.z != z {
|
||||
*pos = Vector3::new(x, y, z);
|
||||
self.pos.store(Vector3::new(x, y, z));
|
||||
let i = x.floor() as i32;
|
||||
let j = y.floor() as i32;
|
||||
let k = z.floor() as i32;
|
||||
|
||||
let mut block_pos = self.block_pos.lock().unwrap();
|
||||
let block_pos = self.block_pos.load();
|
||||
let block_pos_vec = block_pos.0;
|
||||
if i != block_pos_vec.x || j != block_pos_vec.y || k != block_pos_vec.z {
|
||||
*block_pos = WorldPosition(Vector3::new(i, j, k));
|
||||
self.block_pos.store(WorldPosition(Vector3::new(i, j, k)));
|
||||
|
||||
let mut chunk_pos = self.chunk_pos.lock().unwrap();
|
||||
let chunk_pos = self.chunk_pos.load();
|
||||
if get_section_cord(i) != chunk_pos.x || get_section_cord(k) != chunk_pos.z {
|
||||
*chunk_pos = Vector2::new(
|
||||
self.chunk_pos.store(Vector2::new(
|
||||
get_section_cord(block_pos_vec.x),
|
||||
get_section_cord(block_pos_vec.z),
|
||||
);
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,8 +92,8 @@ impl Entity {
|
||||
|
||||
pub fn set_rotation(&self, yaw: f32, pitch: f32) {
|
||||
// TODO
|
||||
*self.yaw.lock().unwrap() = yaw;
|
||||
*self.pitch.lock().unwrap() = pitch
|
||||
self.yaw.store(yaw);
|
||||
self.pitch.store(pitch);
|
||||
}
|
||||
|
||||
pub async fn remove(&mut self) {
|
||||
@@ -109,8 +110,8 @@ impl Entity {
|
||||
}
|
||||
|
||||
let var8 = Vector3::new(x, 0.0, z).normalize() * strength;
|
||||
let mut velocity = self.velocity.lock().unwrap();
|
||||
*velocity = Vector3::new(
|
||||
let velocity = self.velocity.load();
|
||||
self.velocity.store(Vector3::new(
|
||||
velocity.x / 2.0 - var8.x,
|
||||
if self.on_ground.load(std::sync::atomic::Ordering::Relaxed) {
|
||||
(velocity.y / 2.0 + strength).min(0.4)
|
||||
@@ -118,7 +119,7 @@ impl Entity {
|
||||
velocity.y
|
||||
},
|
||||
velocity.z / 2.0 - var8.z,
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
pub async fn set_sneaking(&self, sneaking: bool) {
|
||||
@@ -171,7 +172,7 @@ impl Entity {
|
||||
}
|
||||
|
||||
pub async fn set_pose(&self, pose: EntityPose) {
|
||||
*self.pose.lock().unwrap() = pose;
|
||||
self.pose.store(pose);
|
||||
let pose = pose as i32;
|
||||
let packet = CSetEntityMetadata::<VarInt>::new(
|
||||
self.entity_id.into(),
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
use std::sync::{
|
||||
atomic::{AtomicI32, AtomicU8},
|
||||
Arc, Mutex,
|
||||
Arc,
|
||||
};
|
||||
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use num_derive::FromPrimitive;
|
||||
use num_traits::ToPrimitive;
|
||||
use parking_lot::Mutex;
|
||||
use pumpkin_core::{
|
||||
math::{boundingbox::BoundingBox, position::WorldPosition, vector3::Vector3},
|
||||
text::TextComponent,
|
||||
@@ -67,18 +69,18 @@ pub struct Player {
|
||||
pub client: Client,
|
||||
pub config: Mutex<PlayerConfig>,
|
||||
/// Current gamemode
|
||||
pub gamemode: Mutex<GameMode>,
|
||||
pub gamemode: AtomicCell<GameMode>,
|
||||
// TODO: prbly should put this into an Living Entitiy or something
|
||||
pub health: Mutex<f32>,
|
||||
pub health: AtomicCell<f32>,
|
||||
pub food: AtomicI32,
|
||||
pub food_saturation: Mutex<f32>,
|
||||
pub food_saturation: AtomicCell<f32>,
|
||||
pub inventory: Mutex<PlayerInventory>,
|
||||
pub open_container: Mutex<Option<u64>>,
|
||||
pub carried_item: Mutex<Option<ItemStack>>,
|
||||
pub open_container: AtomicCell<Option<u64>>,
|
||||
pub carried_item: AtomicCell<Option<ItemStack>>,
|
||||
|
||||
/// send `send_abilties_update` when changed
|
||||
pub abilities: PlayerAbilities,
|
||||
pub last_position: Mutex<Vector3<f64>>,
|
||||
pub last_position: AtomicCell<Vector3<f64>>,
|
||||
|
||||
// TODO: This is currently unused, We have to calculate the block breaking speed our own and then break the block our own if its done
|
||||
pub current_block_destroy_stage: AtomicU8,
|
||||
@@ -87,12 +89,12 @@ pub struct Player {
|
||||
// Current awaiting teleport id and location, None if did not teleport
|
||||
pub awaiting_teleport: Mutex<Option<(VarInt, Vector3<f64>)>>,
|
||||
|
||||
pub watched_section: Mutex<Vector3<i32>>,
|
||||
pub watched_section: AtomicCell<Vector3<i32>>,
|
||||
}
|
||||
|
||||
impl Player {
|
||||
pub fn new(client: Client, world: Arc<World>, entity_id: EntityId, gamemode: GameMode) -> Self {
|
||||
let gameprofile = match client.gameprofile.lock().unwrap().clone() {
|
||||
let gameprofile = match client.gameprofile.lock().clone() {
|
||||
Some(profile) => profile,
|
||||
None => {
|
||||
log::error!("No gameprofile?. Impossible");
|
||||
@@ -104,7 +106,7 @@ impl Player {
|
||||
}
|
||||
}
|
||||
};
|
||||
let config = client.config.lock().unwrap().clone().unwrap_or_default();
|
||||
let config = client.config.lock().clone().unwrap_or_default();
|
||||
Self {
|
||||
entity: Entity::new(entity_id, world, EntityType::Player, 1.62),
|
||||
config: Mutex::new(config),
|
||||
@@ -112,18 +114,18 @@ impl Player {
|
||||
client,
|
||||
awaiting_teleport: Mutex::new(None),
|
||||
// TODO: Load this from previous instance
|
||||
health: Mutex::new(20.0),
|
||||
health: AtomicCell::new(20.0),
|
||||
food: AtomicI32::new(20),
|
||||
food_saturation: Mutex::new(20.0),
|
||||
food_saturation: AtomicCell::new(20.0),
|
||||
current_block_destroy_stage: AtomicU8::new(0),
|
||||
inventory: Mutex::new(PlayerInventory::new()),
|
||||
open_container: Mutex::new(None),
|
||||
carried_item: Mutex::new(None),
|
||||
open_container: AtomicCell::new(None),
|
||||
carried_item: AtomicCell::new(None),
|
||||
teleport_id_count: AtomicI32::new(0),
|
||||
abilities: PlayerAbilities::default(),
|
||||
gamemode: Mutex::new(gamemode),
|
||||
watched_section: Mutex::new(Vector3::new(0, 0, 0)),
|
||||
last_position: Mutex::new(Vector3::new(0.0, 0.0, 0.0)),
|
||||
gamemode: AtomicCell::new(gamemode),
|
||||
watched_section: AtomicCell::new(Vector3::new(0, 0, 0)),
|
||||
last_position: AtomicCell::new(Vector3::new(0.0, 0.0, 0.0)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,7 +175,7 @@ impl Player {
|
||||
let entity = &self.entity;
|
||||
entity.set_pos(x, y, z);
|
||||
entity.set_rotation(yaw, pitch);
|
||||
*self.awaiting_teleport.lock().unwrap() = Some((teleport_id.into(), Vector3::new(x, y, z)));
|
||||
*self.awaiting_teleport.lock() = Some((teleport_id.into(), Vector3::new(x, y, z)));
|
||||
self.client.send_packet(&CSyncPlayerPosition::new(
|
||||
x,
|
||||
y,
|
||||
@@ -186,7 +188,7 @@ impl Player {
|
||||
}
|
||||
|
||||
pub fn block_interaction_range(&self) -> f64 {
|
||||
if *self.gamemode.lock().unwrap() == GameMode::Creative {
|
||||
if self.gamemode.load() == GameMode::Creative {
|
||||
5.0
|
||||
} else {
|
||||
4.5
|
||||
@@ -196,7 +198,7 @@ impl Player {
|
||||
pub fn can_interact_with_block_at(&self, pos: &WorldPosition, additional_range: f64) -> bool {
|
||||
let d = self.block_interaction_range() + additional_range;
|
||||
let box_pos = BoundingBox::from_block(pos);
|
||||
let entity_pos = self.entity.pos.lock().unwrap();
|
||||
let entity_pos = self.entity.pos.load();
|
||||
let standing_eye_height = self.entity.standing_eye_height;
|
||||
box_pos.squared_magnitude(Vector3 {
|
||||
x: entity_pos.x,
|
||||
@@ -207,7 +209,7 @@ impl Player {
|
||||
|
||||
/// Kicks the Client with a reason depending on the connection state
|
||||
pub fn kick(&self, reason: TextComponent) {
|
||||
assert!(*self.client.connection_state.lock().unwrap() == ConnectionState::Play);
|
||||
assert!(self.client.connection_state.load() == ConnectionState::Play);
|
||||
assert!(!self
|
||||
.client
|
||||
.closed
|
||||
@@ -225,19 +227,19 @@ impl Player {
|
||||
}
|
||||
|
||||
pub fn update_health(&self, health: f32, food: i32, food_saturation: f32) {
|
||||
*self.health.lock().unwrap() = health;
|
||||
self.health.store(health);
|
||||
self.food.store(food, std::sync::atomic::Ordering::Relaxed);
|
||||
*self.food_saturation.lock().unwrap() = food_saturation;
|
||||
self.food_saturation.store(food_saturation);
|
||||
}
|
||||
|
||||
pub fn set_gamemode(&self, gamemode: GameMode) {
|
||||
// We could send the same gamemode without problems. But why waste bandwidth ?
|
||||
let mut current_gamemode = self.gamemode.lock().unwrap();
|
||||
let current_gamemode = self.gamemode.load();
|
||||
assert!(
|
||||
*current_gamemode != gamemode,
|
||||
current_gamemode != gamemode,
|
||||
"Setting the same gamemode as already is"
|
||||
);
|
||||
*current_gamemode = gamemode;
|
||||
self.gamemode.store(gamemode);
|
||||
// So a little story time. I actually made an abitlties_from_gamemode function. I looked at vanilla and they always send the abilties from the gamemode. But the funny thing actually is. That the client
|
||||
// does actually use the same method and set the abilties when receiving the CGameEvent gamemode packet. Just Mojang nonsense
|
||||
self.entity
|
||||
@@ -261,7 +263,7 @@ impl Player {
|
||||
|
||||
impl Player {
|
||||
pub async fn process_packets(&self, server: &Arc<Server>) {
|
||||
let mut packets = self.client.client_packets_queue.lock().unwrap();
|
||||
let mut packets = self.client.client_packets_queue.lock();
|
||||
while let Some(mut packet) = packets.pop() {
|
||||
match self.handle_play_packet(server, &mut packet).await {
|
||||
Ok(_) => {}
|
||||
|
||||
@@ -172,7 +172,7 @@ fn main() -> io::Result<()> {
|
||||
dbg!("a");
|
||||
player.remove().await;
|
||||
dbg!("b");
|
||||
let connection = &mut player.client.connection.lock().unwrap();
|
||||
let connection = &mut player.client.connection.lock();
|
||||
dbg!("c");
|
||||
|
||||
poll.registry().deregister(connection.by_ref())?;
|
||||
@@ -201,7 +201,7 @@ fn main() -> io::Result<()> {
|
||||
if done || make_player {
|
||||
if let Some(client) = clients.remove(&token) {
|
||||
if done {
|
||||
let connection = &mut client.connection.lock().unwrap();
|
||||
let connection = &mut client.connection.lock();
|
||||
poll.registry().deregister(connection.by_ref())?;
|
||||
} else if make_player {
|
||||
let token = client.token;
|
||||
|
||||
@@ -62,7 +62,7 @@ pub fn receive_plugin_response(
|
||||
}
|
||||
// TODO: no unwrap
|
||||
let addr: SocketAddr = buf.get_string().unwrap().parse().unwrap();
|
||||
*client.address.lock().unwrap() = addr;
|
||||
*client.address.lock() = addr;
|
||||
todo!()
|
||||
} else {
|
||||
client.kick("This server requires you to connect with Velocity.")
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use base64::{engine::general_purpose, Engine};
|
||||
use image::GenericImageView;
|
||||
use mio::Token;
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use pumpkin_config::{BasicConfiguration, BASIC_CONFIG};
|
||||
use pumpkin_core::GameMode;
|
||||
use pumpkin_entity::EntityId;
|
||||
@@ -11,13 +12,11 @@ use pumpkin_protocol::{
|
||||
};
|
||||
use pumpkin_world::dimension::Dimension;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::RwLock;
|
||||
use std::{
|
||||
io::Cursor,
|
||||
path::Path,
|
||||
sync::{
|
||||
atomic::{AtomicI32, Ordering},
|
||||
Arc, Mutex,
|
||||
atomic::{AtomicI32, Ordering}, Arc,
|
||||
},
|
||||
time::Duration,
|
||||
};
|
||||
@@ -143,8 +142,7 @@ impl Server {
|
||||
) -> Option<Arc<Mutex<Box<dyn Container>>>> {
|
||||
let open_containers = self
|
||||
.open_containers
|
||||
.read()
|
||||
.expect("open_containers is poisoned");
|
||||
.read();
|
||||
open_containers
|
||||
.get(&container_id)?
|
||||
.try_open(player_id)
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, Mutex},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
pub mod player_chunker;
|
||||
|
||||
use mio::Token;
|
||||
use num_traits::ToPrimitive;
|
||||
use parking_lot::Mutex;
|
||||
use pumpkin_config::BasicConfiguration;
|
||||
use pumpkin_core::math::vector2::Vector2;
|
||||
use pumpkin_entity::{entity_type::EntityType, EntityId};
|
||||
@@ -45,7 +46,7 @@ impl World {
|
||||
where
|
||||
P: ClientPacket,
|
||||
{
|
||||
let current_players = self.current_players.lock().unwrap();
|
||||
let current_players = self.current_players.lock();
|
||||
for (_, player) in current_players.iter() {
|
||||
player.client.send_packet(packet);
|
||||
}
|
||||
@@ -56,7 +57,7 @@ impl World {
|
||||
where
|
||||
P: ClientPacket,
|
||||
{
|
||||
let current_players = self.current_players.lock().unwrap();
|
||||
let current_players = self.current_players.lock();
|
||||
for (_, player) in current_players.iter().filter(|c| !except.contains(c.0)) {
|
||||
player.client.send_packet(packet);
|
||||
}
|
||||
@@ -65,7 +66,7 @@ impl World {
|
||||
pub async fn spawn_player(&self, base_config: &BasicConfiguration, player: Arc<Player>) {
|
||||
// This code follows the vanilla packet order
|
||||
let entity_id = player.entity_id();
|
||||
let gamemode = player.gamemode.lock().unwrap();
|
||||
let gamemode = player.gamemode.load();
|
||||
log::debug!("spawning player, entity id {}", entity_id);
|
||||
|
||||
// login packet for our new player
|
||||
@@ -126,7 +127,6 @@ impl World {
|
||||
for (_, playerr) in self
|
||||
.current_players
|
||||
.lock()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.filter(|(c, _)| **c != player.client.token)
|
||||
{
|
||||
@@ -173,12 +173,11 @@ impl World {
|
||||
for (_, existing_player) in self
|
||||
.current_players
|
||||
.lock()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.filter(|c| c.0 != &token)
|
||||
{
|
||||
let entity = &existing_player.entity;
|
||||
let pos = entity.pos.lock().unwrap();
|
||||
let pos = entity.pos.load();
|
||||
let gameprofile = &existing_player.gameprofile;
|
||||
player.client.send_packet(&CSpawnEntity::new(
|
||||
existing_player.entity_id().into(),
|
||||
@@ -187,9 +186,9 @@ impl World {
|
||||
pos.x,
|
||||
pos.y,
|
||||
pos.z,
|
||||
*entity.yaw.lock().unwrap(),
|
||||
*entity.pitch.lock().unwrap(),
|
||||
*entity.head_yaw.lock().unwrap(),
|
||||
entity.yaw.load(),
|
||||
entity.pitch.load(),
|
||||
entity.head_yaw.load(),
|
||||
0.into(),
|
||||
0.0,
|
||||
0.0,
|
||||
@@ -198,7 +197,7 @@ impl World {
|
||||
}
|
||||
// entity meta data
|
||||
// set skin parts
|
||||
if let Some(config) = player.client.config.lock().unwrap().as_ref() {
|
||||
if let Some(config) = player.client.config.lock().as_ref() {
|
||||
let packet = CSetEntityMetadata::new(
|
||||
entity_id.into(),
|
||||
Metadata::new(17, VarInt(0), config.skin_parts),
|
||||
@@ -221,7 +220,7 @@ impl World {
|
||||
let closed = client.closed.load(std::sync::atomic::Ordering::Relaxed);
|
||||
let chunks = Arc::new(chunks);
|
||||
tokio::task::spawn_blocking(move || {
|
||||
level.lock().unwrap().fetch_chunks(&chunks, sender, closed)
|
||||
level.lock().fetch_chunks(&chunks, sender, closed)
|
||||
});
|
||||
|
||||
while let Some(chunk_data) = chunk_receiver.recv().await {
|
||||
@@ -254,7 +253,6 @@ impl World {
|
||||
for (_, player) in self
|
||||
.current_players
|
||||
.lock()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.filter(|c| c.0 != &from.client.token)
|
||||
{
|
||||
@@ -266,13 +264,12 @@ impl World {
|
||||
}
|
||||
|
||||
pub fn add_player(&self, token: Token, player: Arc<Player>) {
|
||||
self.current_players.lock().unwrap().insert(token, player);
|
||||
self.current_players.lock().insert(token, player);
|
||||
}
|
||||
|
||||
pub fn remove_player(&self, player: &Player) {
|
||||
self.current_players
|
||||
.lock()
|
||||
.unwrap()
|
||||
.remove(&player.client.token)
|
||||
.unwrap();
|
||||
let uuid = player.gameprofile.id;
|
||||
|
||||
@@ -15,16 +15,15 @@ fn get_view_distance(player: &Player) -> i8 {
|
||||
player
|
||||
.config
|
||||
.lock()
|
||||
.unwrap()
|
||||
.view_distance
|
||||
.clamp(2, BASIC_CONFIG.view_distance as i8)
|
||||
}
|
||||
|
||||
pub async fn player_join(world: &World, player: Arc<Player>) {
|
||||
let new_watched = chunk_section_from_pos(&player.entity.block_pos.lock().unwrap());
|
||||
let mut watched_section = player.watched_section.lock().unwrap();
|
||||
*watched_section = new_watched;
|
||||
let chunk_pos = player.entity.chunk_pos.lock().unwrap();
|
||||
let new_watched = chunk_section_from_pos(&player.entity.block_pos.load());
|
||||
player.watched_section.store(new_watched);
|
||||
let watched_section = new_watched;
|
||||
let chunk_pos = player.entity.chunk_pos.load();
|
||||
player.client.send_packet(&CCenterChunk {
|
||||
chunk_x: chunk_pos.x.into(),
|
||||
chunk_z: chunk_pos.z.into(),
|
||||
@@ -58,10 +57,10 @@ pub async fn player_join(world: &World, player: Arc<Player>) {
|
||||
}
|
||||
|
||||
pub async fn update_position(entity: &Entity, player: &Player) {
|
||||
let mut current_watched = player.watched_section.lock().unwrap();
|
||||
let new_watched = chunk_section_from_pos(&entity.block_pos.lock().unwrap());
|
||||
if *current_watched != new_watched {
|
||||
let chunk_pos = entity.chunk_pos.lock().unwrap();
|
||||
let current_watched = player.watched_section.load();
|
||||
let new_watched = chunk_section_from_pos(&entity.block_pos.load());
|
||||
if current_watched != new_watched {
|
||||
let chunk_pos = entity.chunk_pos.load();
|
||||
player.client.send_packet(&CCenterChunk {
|
||||
chunk_x: chunk_pos.x.into(),
|
||||
chunk_z: chunk_pos.z.into(),
|
||||
@@ -74,7 +73,7 @@ pub async fn update_position(entity: &Entity, player: &Player) {
|
||||
);
|
||||
let new_cylindrical =
|
||||
Cylindrical::new(Vector2::new(chunk_pos.x, chunk_pos.z), view_distance);
|
||||
*current_watched = new_watched;
|
||||
player.watched_section.store(new_watched);
|
||||
let mut loading_chunks = Vec::new();
|
||||
Cylindrical::for_each_changed_chunk(
|
||||
old_cylindrical,
|
||||
|
||||
Reference in New Issue
Block a user