valence/src/packet.rs
Ryan Johnson 740778ec41
Update chunk data packet cache lazily (#170)
Previously, the chunk data cache was regenerated at the end of each tick
every time a block or biome was modified in a chunk. This causes
performance problems in situations where chunks are being modified every
tick, like the conway example or redstone machines.

This changes things so that the chunk data packet is regenerated only
when a client actually needs to load the chunk. This isn't perfect
because the regeneration cannot happen in parallel, but the benefits
outweigh the costs. (The chunk data packet _is_ generated in parallel
when the chunk is first created. There is also some parallelism when
clients are loading different chunks. The packet cache is guarded by a
`Mutex`.)

This has revealed that compression is surprisingly slow. This should be
investigated later.
2022-12-13 22:56:22 -08:00

58 lines
1.5 KiB
Rust

use std::io::Write;
use valence_protocol::{write_packet, write_packet_compressed, Encode, Packet};
pub trait WritePacket {
fn write_packet<P>(&mut self, packet: &P) -> anyhow::Result<()>
where
P: Encode + Packet + ?Sized;
fn write_bytes(&mut self, bytes: &[u8]) -> anyhow::Result<()>;
}
impl<W: WritePacket> WritePacket for &mut W {
fn write_packet<P>(&mut self, packet: &P) -> anyhow::Result<()>
where
P: Encode + Packet + ?Sized,
{
(*self).write_packet(packet)
}
fn write_bytes(&mut self, bytes: &[u8]) -> anyhow::Result<()> {
(*self).write_bytes(bytes)
}
}
pub struct PacketWriter<'a, W> {
writer: W,
threshold: Option<u32>,
scratch: &'a mut Vec<u8>,
}
impl<'a, W: Write> PacketWriter<'a, W> {
pub fn new(writer: W, threshold: Option<u32>, scratch: &'a mut Vec<u8>) -> PacketWriter<W> {
Self {
writer,
threshold,
scratch,
}
}
}
impl<W: Write> WritePacket for PacketWriter<'_, W> {
fn write_packet<P>(&mut self, packet: &P) -> anyhow::Result<()>
where
P: Encode + Packet + ?Sized,
{
if let Some(threshold) = self.threshold {
write_packet_compressed(&mut self.writer, threshold, self.scratch, packet)
} else {
write_packet(&mut self.writer, packet)
}
}
fn write_bytes(&mut self, bytes: &[u8]) -> anyhow::Result<()> {
Ok(self.writer.write_all(bytes)?)
}
}