Skip to content

Commit

Permalink
Merge pull request #46 from zzhgithub/opz-for-windows
Browse files Browse the repository at this point in the history
Opz for windows
  • Loading branch information
zzhgithub authored Sep 4, 2023
2 parents 116e2b5 + 908c3a2 commit b4b4292
Show file tree
Hide file tree
Showing 10 changed files with 159 additions and 27 deletions.
15 changes: 15 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,17 @@ egui-notify = "0.8.0"
rand = "0.8.5"
seldom_state = "0.7.0"
bevy_sprite3d = "2.5.0"
bit-vec = { version = "0.6", features = ["serde"] }
# 解决依赖冲突
num-rational = "^0.4.1"
fxhash = "^0.2.1"
simba = "^0.8"
bevy_mod_billboard = "0.4.0"
notify = "6.1.1"
egui_extras = "0.22.0"
huffman-compress = { git = "https://github.com/zzhgithub/rust-huffman-compress", branch = "features-serde", features = [
"serde",
] }


[profile.dev.package.bevy_rapier3d]
Expand Down
42 changes: 23 additions & 19 deletions src/client/mesh_display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ use ndshape::{ConstShape, ConstShape3u32};
use crate::{
common::ClipSpheres,
server::message_def::{chunk_result::ChunkResult, ServerChannel},
tools::get_empty_chunk,
tools::get_all_v_chunk,
voxel_world::{
chunk::{
find_chunk_keys_array_by_shpere_y_0, generate_offset_resoure,
generate_offset_resoure_min_1, ChunkKey, NeighbourOffest,
},
chunk_map::ChunkMap,
compress::uncompress,
voxel::Voxel,
},
CHUNK_SIZE, CHUNK_SIZE_U32, MATERIAL_RON, VIEW_RADIUS,
Expand Down Expand Up @@ -165,11 +166,11 @@ pub fn async_chunk_result(
let chunk_result: ChunkResult = bincode::deserialize(&message).unwrap();
match chunk_result {
ChunkResult::ChunkData { key, data } => {
let task = pool.spawn(async move { (key, data) });
let task = pool.spawn(async move { (key, uncompress(&data.0, data.1)) });
chunk_sync_task.tasks.push(task);
}
ChunkResult::ChunkEmpty(key) => {
let task = pool.spawn(async move { (key, get_empty_chunk()) });
ChunkResult::ChunkSame((key, voxel)) => {
let task = pool.spawn(async move { (key, get_all_v_chunk(voxel)) });
chunk_sync_task.tasks.push(task);
}
ChunkResult::ChunkUpdateOne {
Expand Down Expand Up @@ -260,15 +261,16 @@ pub fn update_mesh(
let volexs: Vec<Voxel> = chunk_map.get_with_neighbor_full_y(chunk_key_y0);
match gen_mesh(volexs.to_owned(), material_config.clone()) {
Some(render_mesh) => {
let mesh_handle = mesh_manager.mesh_storge.get(&chunk_key_y0).unwrap();
if let Some(mesh) = mesh_assets.get_mut(mesh_handle) {
// 更新AABB
if let Some(entity) = mesh_manager.entities.get(&chunk_key_y0) {
if let Some(aabb) = render_mesh.compute_aabb() {
commands.entity(*entity).insert(aabb);
if let Some(mesh_handle) = mesh_manager.mesh_storge.get(&chunk_key_y0) {
if let Some(mesh) = mesh_assets.get_mut(mesh_handle) {
// 更新AABB
if let Some(entity) = mesh_manager.entities.get(&chunk_key_y0) {
if let Some(aabb) = render_mesh.compute_aabb() {
commands.entity(*entity).insert(aabb);
}
}
*mesh = render_mesh;
}
*mesh = render_mesh;
}
// 没有生成mesh就不管反正后面要生成
}
Expand All @@ -281,14 +283,15 @@ pub fn update_mesh(
};
match gen_mesh_water(pick_water(volexs), material_config) {
Some(water_mesh) => {
let mesh_handle = mesh_manager.water_mesh_storge.get(&chunk_key_y0).unwrap();
if let Some(mesh) = mesh_assets.get_mut(mesh_handle) {
if let Some(entity) = mesh_manager.water_entities.get(&chunk_key_y0) {
if let Some(aabb) = water_mesh.compute_aabb() {
commands.entity(*entity).insert(aabb);
if let Some(mesh_handle) = mesh_manager.water_mesh_storge.get(&chunk_key_y0) {
if let Some(mesh) = mesh_assets.get_mut(mesh_handle) {
if let Some(entity) = mesh_manager.water_entities.get(&chunk_key_y0) {
if let Some(aabb) = water_mesh.compute_aabb() {
commands.entity(*entity).insert(aabb);
}
}
*mesh = water_mesh;
}
*mesh = water_mesh;
}
}
None => {
Expand Down Expand Up @@ -468,10 +471,11 @@ fn cycle_check_mesh(
let now: Instant = Instant::now();
let duration: Duration = now - *instant;
// 每2s检查一下五秒内没有加载好的数据
if !state && duration.as_millis() > 5 * 1000 && need_keys.contains(key) {
if !state && duration.as_millis() > 10 * 1000 && need_keys.contains(key) {
println!("超时重新请求chunkkey{:?}", key);
// TODO: 这可以检查具体少什么数据?
let message = bincode::serialize(&ChunkQuery::GetFullY(*key)).unwrap();
// todo 对边缘数据不处理!
// 对边缘数据不处理!
client.send_message(ClientChannel::ChunkQuery, message);
}
if duration.as_millis() > 5 * 1000
Expand Down
10 changes: 6 additions & 4 deletions src/server/async_chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ use crate::{
client::message_def::{chunk_query::ChunkQuery, ClientChannel},
server::{message_def::ServerChannel, object_filing::put_object::put_object},
staff::StaffInfoStroge,
tools::all_empty,
voxel_world::{
chunk::ChunkKey,
chunk_map::ChunkMap,
compress::compress,
map_database::{DbSaveTasks, MapDataBase},
player_state::PlayerOntimeState,
voxel::{BasicStone, Voxel, VoxelMaterial},
Expand Down Expand Up @@ -65,12 +65,14 @@ pub fn deal_chunk_query_system(
} else {
voxels = db.find_by_chunk_key(new_key, db_save_task.as_mut());
}
let message = if all_empty(&voxels) {
bincode::serialize(&ChunkResult::ChunkEmpty(new_key)).unwrap()
let (buffer, tree) = compress(voxels.clone());
let message = if buffer.len() == 0 {
bincode::serialize(&ChunkResult::ChunkSame((new_key, voxels[0])))
.unwrap()
} else {
bincode::serialize(&ChunkResult::ChunkData {
key: new_key,
data: voxels.clone(),
data: (buffer, tree),
})
.unwrap()
};
Expand Down
6 changes: 4 additions & 2 deletions src/server/message_def/chunk_result.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use bevy::prelude::Component;
use bit_vec::BitVec;
use huffman_compress::Tree;
use serde::{Deserialize, Serialize};

use crate::voxel_world::{chunk::ChunkKey, voxel::Voxel};
Expand All @@ -7,9 +9,9 @@ use crate::voxel_world::{chunk::ChunkKey, voxel::Voxel};
pub enum ChunkResult {
ChunkData {
key: ChunkKey,
data: Vec<Voxel>,
data: (BitVec, Tree<Voxel>),
},
ChunkEmpty(ChunkKey),
ChunkSame((ChunkKey,Voxel)),
ChunkUpdateOne {
chunk_key: ChunkKey,
pos: [u32; 3],
Expand Down
13 changes: 13 additions & 0 deletions src/tools/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,19 @@ pub fn get_empty_chunk() -> Vec<Voxel> {
voxels
}

/**
* 获取完全空的区块数据
* Get all empty chunk data
*/
pub fn get_all_v_chunk(voxel: Voxel) -> Vec<Voxel> {
let mut voxels = Vec::new();
type SampleShape = ConstShape3u32<CHUNK_SIZE_U32, CHUNK_SIZE_U32, CHUNK_SIZE_U32>;
for _ in 0..SampleShape::SIZE {
voxels.push(voxel.clone());
}
voxels
}

/**
* 获取cube中心点 属于的 chunkKey和x y z坐标
*/
Expand Down
3 changes: 2 additions & 1 deletion src/voxel_world/chunk_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ impl ChunkMap {
let nx = &IVec3::new(-1, 0, 0);
let pz = &IVec3::new(0, 0, 1);
let nz = &IVec3::new(0, 0, -1);
let n_self = &IVec3::new(0, 0, 0);

let offsets = [px, nx, pz, nz];
let offsets = [px, nx, pz, nz, n_self];
let last_inex = -128 / CHUNK_SIZE + 1;

for y_offset in last_inex..=128 / CHUNK_SIZE {
Expand Down
78 changes: 78 additions & 0 deletions src/voxel_world/compress.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use bevy::utils::HashMap;
use bit_vec::BitVec;
use huffman_compress::{CodeBuilder, Tree};

use super::voxel::Voxel;

pub fn compress(data: Vec<Voxel>) -> (BitVec, Tree<Voxel>) {
let mut weights: HashMap<Voxel, i32> = HashMap::new();
for &voxel in &data {
let count = weights.entry(voxel).or_insert(0);
*count += 1;
}

let (book, tree) = CodeBuilder::from_iter(weights).finish();
let mut buffer = BitVec::new();

for voxel in &data {
match book.encode(&mut buffer, voxel) {
Ok(_) => {}
Err(err) => {
println!("{}", err);
}
}
}
(buffer, tree)
}

pub fn uncompress(buffer: &BitVec, tree: Tree<Voxel>) -> Vec<Voxel> {
tree.decoder(buffer, buffer.len()).collect()
}

#[test]
fn test() {
let data = vec![
Voxel::EMPTY,
Voxel::FILLED,
Voxel::FILLED,
Voxel::FILLED,
Voxel::FILLED,
Voxel::FILLED,
Voxel::FILLED,
Voxel::FILLED,
Voxel::FILLED,
Voxel::FILLED,
Voxel::FILLED,
];
let (buffer, tree) = compress(data.clone());

let new_data = uncompress(&buffer, tree);
print!("{}", data.len());
print!("{}", new_data.len());
assert_eq!(data, new_data);
}

#[test]
fn test_serialization() {
let data = vec![
Voxel::EMPTY,
Voxel::FILLED,
Voxel::FILLED,
Voxel::FILLED,
Voxel::FILLED,
Voxel::FILLED,
Voxel::FILLED,
Voxel::FILLED,
Voxel::FILLED,
Voxel::FILLED,
Voxel::FILLED,
];
let (buffer, tree) = compress(data.clone());
let tree_s = bincode::serialize(&tree).unwrap();
let tree_ds: Tree<Voxel> = bincode::deserialize(&tree_s).unwrap();

let a = uncompress(&buffer.clone(), tree);
let b = uncompress(&buffer.clone(), tree_ds);

assert_eq!(a, b);
}
1 change: 1 addition & 0 deletions src/voxel_world/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ pub mod map_database;
pub mod map_generator;
pub mod player_state;
pub mod voxel;
pub mod compress;
14 changes: 13 additions & 1 deletion src/voxel_world/voxel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,23 @@ use serde::{Deserialize, Serialize};
/**
* 体素类型
*/
#[derive(Debug, Clone, Copy, Default, Deserialize, Serialize, Reflect)]
#[derive(Debug, Clone, Copy, Default, Deserialize, Serialize, Reflect, PartialEq, Eq, Hash)]
pub struct Voxel {
pub id: u8,
}

impl PartialOrd for Voxel {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.id.partial_cmp(&other.id)
}
}

impl Ord for Voxel {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.id.cmp(&other.id)
}
}

impl Voxel {
pub const EMPTY: Self = Self { id: 0 };
pub const FILLED: Self = Self { id: 1 };
Expand Down

0 comments on commit b4b4292

Please sign in to comment.