mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 14:26:04 +00:00
fix shared worlds*
*there's a bug that entities and bots will have their positions exaggerated because the relative movement packet is applied for every entity once per bot
This commit is contained in:
parent
93bebefe83
commit
d41d6480ea
7 changed files with 66 additions and 9 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -406,6 +406,7 @@ version = "0.2.0"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"azalea",
|
||||
"azalea-protocol",
|
||||
"env_logger",
|
||||
"parking_lot",
|
||||
"rand",
|
||||
|
|
|
@ -34,7 +34,7 @@ use azalea_world::{
|
|||
entity::{metadata, Entity, EntityData, EntityMetadata},
|
||||
WeakWorld, WeakWorldContainer, World,
|
||||
};
|
||||
use log::{debug, error, info, warn};
|
||||
use log::{debug, error, info, trace, warn};
|
||||
use parking_lot::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
|
@ -751,8 +751,29 @@ impl Client {
|
|||
.update_view_center(&ChunkPos::new(p.x, p.z));
|
||||
}
|
||||
ClientboundGamePacket::LevelChunkWithLight(p) => {
|
||||
debug!("Got chunk with light packet {} {}", p.x, p.z);
|
||||
// warn!("Got chunk with light packet {} {}", p.x, p.z);
|
||||
let pos = ChunkPos::new(p.x, p.z);
|
||||
|
||||
// OPTIMIZATION: if we already know about the chunk from the
|
||||
// shared world (and not ourselves), then we don't need to
|
||||
// parse it again. This is only used when we have a shared
|
||||
// world, since we check that the chunk isn't currently owned
|
||||
// by this client.
|
||||
let shared_has_chunk = client.world.read().get_chunk(&pos).is_some();
|
||||
let this_client_has_chunk = client
|
||||
.world
|
||||
.read()
|
||||
.chunk_storage
|
||||
.limited_get(&pos)
|
||||
.is_some();
|
||||
if shared_has_chunk && !this_client_has_chunk {
|
||||
trace!(
|
||||
"Skipping parsing chunk {:?} because we already know about it",
|
||||
pos
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// let chunk = Chunk::read_with_world_height(&mut p.chunk_data);
|
||||
// debug("chunk {:?}")
|
||||
if let Err(e) = client
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::WeakWorld;
|
||||
use crate::{WeakWorld, World};
|
||||
use azalea_core::ResourceLocation;
|
||||
use log::error;
|
||||
use std::{
|
||||
|
|
|
@ -7,12 +7,17 @@ use azalea_block::BlockState;
|
|||
use azalea_buf::BufReadError;
|
||||
use azalea_core::{BlockPos, ChunkPos, PositionDelta8, Vec3};
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use std::{io::Cursor, sync::Arc};
|
||||
use std::fmt::Debug;
|
||||
use std::{fmt::Formatter, io::Cursor, sync::Arc};
|
||||
use uuid::Uuid;
|
||||
|
||||
/// A world is a collection of chunks and entities. They're called "levels" in Minecraft's source code.
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Default)]
|
||||
pub struct World {
|
||||
// we just need to keep a strong reference to `shared` so it doesn't get
|
||||
// dropped, we don't need to do anything with it
|
||||
_shared: Arc<WeakWorld>,
|
||||
|
||||
pub chunk_storage: LimitedChunkStorage,
|
||||
pub entity_storage: EntityStorage,
|
||||
}
|
||||
|
@ -27,6 +32,7 @@ pub struct WeakWorld {
|
|||
impl World {
|
||||
pub fn new(chunk_radius: u32, shared: Arc<WeakWorld>) -> Self {
|
||||
World {
|
||||
_shared: shared.clone(),
|
||||
chunk_storage: LimitedChunkStorage::new(chunk_radius, shared.chunk_storage.clone()),
|
||||
entity_storage: EntityStorage::new(shared.entity_storage.clone()),
|
||||
}
|
||||
|
@ -156,3 +162,12 @@ impl WeakWorld {
|
|||
self.chunk_storage.read().min_y
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for World {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("World")
|
||||
.field("chunk_storage", &self.chunk_storage)
|
||||
.field("entity_storage", &self.entity_storage)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ use log::error;
|
|||
use parking_lot::{Mutex, RwLock};
|
||||
use std::{future::Future, net::SocketAddr, sync::Arc, time::Duration};
|
||||
use thiserror::Error;
|
||||
use tokio::sync::mpsc::{self, UnboundedSender};
|
||||
use tokio::sync::mpsc::{self, UnboundedSender};
|
||||
|
||||
/// A helper macro that generates a [`Plugins`] struct from a list of objects
|
||||
/// that implement [`Plugin`].
|
||||
|
@ -47,7 +47,7 @@ pub struct Swarm<S> {
|
|||
|
||||
resolved_address: SocketAddr,
|
||||
address: ServerAddress,
|
||||
world_container: Arc<RwLock<WeakWorldContainer>>,
|
||||
pub worlds: Arc<RwLock<WeakWorldContainer>>,
|
||||
/// Plugins that are set for new bots
|
||||
plugins: Plugins,
|
||||
|
||||
|
@ -161,7 +161,7 @@ pub async fn start_swarm<
|
|||
|
||||
resolved_address,
|
||||
address,
|
||||
world_container,
|
||||
worlds: world_container,
|
||||
plugins,
|
||||
|
||||
bots_tx,
|
||||
|
@ -265,7 +265,7 @@ where
|
|||
// tx is moved to the bot so it can send us events
|
||||
// rx is used to receive events from the bot
|
||||
let (tx, mut rx) = mpsc::unbounded_channel();
|
||||
let mut bot = Client::new(game_profile, conn, Some(self.world_container.clone()));
|
||||
let mut bot = Client::new(game_profile, conn, Some(self.worlds.clone()));
|
||||
tx.send(Event::Initialize).unwrap();
|
||||
bot.start_tasks(tx);
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ version = "0.2.0"
|
|||
[dependencies]
|
||||
anyhow = "1.0.65"
|
||||
azalea = {path = "../azalea"}
|
||||
azalea-protocol = {path = "../azalea-protocol"}
|
||||
env_logger = "0.9.1"
|
||||
parking_lot = {version = "^0.12.1", features = ["deadlock_detection"]}
|
||||
rand = "0.8.5"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use azalea::pathfinder::BlockPosGoal;
|
||||
use azalea::{prelude::*, BlockPos, Swarm, SwarmEvent};
|
||||
use azalea::{Account, Client, Event};
|
||||
use azalea_protocol::packets::game::serverbound_client_command_packet::ServerboundClientCommandPacket;
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
|
@ -96,6 +97,11 @@ async fn handle(bot: Client, event: Event, _state: State) -> anyhow::Result<()>
|
|||
Event::Initialize => {
|
||||
println!("initialized");
|
||||
}
|
||||
Event::Death(_) => {
|
||||
bot.write_packet(ServerboundClientCommandPacket {
|
||||
action: azalea_protocol::packets::game::serverbound_client_command_packet::Action::PerformRespawn,
|
||||
}.get()).await?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
@ -115,6 +121,19 @@ async fn swarm_handle(
|
|||
}
|
||||
SwarmEvent::Chat(m) => {
|
||||
println!("swarm chat message: {}", m.message().to_ansi(None));
|
||||
if m.message().to_string() == "<py5> world" {
|
||||
let worlds = swarm.worlds.read();
|
||||
for (name, world) in &swarm.worlds.read().worlds {
|
||||
println!("world name: {}", name);
|
||||
if let Some(w) = world.upgrade() {
|
||||
for chunk_pos in w.chunk_storage.read().chunks.values() {
|
||||
println!("chunk: {:?}", chunk_pos);
|
||||
}
|
||||
} else {
|
||||
println!("nvm world is gone");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue