diff --git a/README.md b/README.md index b80768e..35f3d54 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ pub const CLIENT_MAP_GEN: bool = true; - T - toggle One/Thrid Person - E - Open composite rules list - Q - throw active toolbar object +- (Hold Left-Shift Left-Click)-rotation Cube Direction # Feature List - [x] Load unlimited maps diff --git a/README_CN.md b/README_CN.md index eceaeac..a77e36e 100644 --- a/README_CN.md +++ b/README_CN.md @@ -33,6 +33,8 @@ cargo run --release --bin client - T 切换视角 - E 打开合成表 - Q 丢弃toolbar上激活中的物品 +- 按住左Shirt+左键单机。旋转方块方向 + # LIB 中的配置常量 ```rust diff --git "a/assets/textures/\346\265\213\350\257\2251.png" "b/assets/textures/\346\265\213\350\257\2251.png" new file mode 100644 index 0000000..65de122 Binary files /dev/null and "b/assets/textures/\346\265\213\350\257\2251.png" differ diff --git "a/assets/textures/\346\265\213\350\257\2252.png" "b/assets/textures/\346\265\213\350\257\2252.png" new file mode 100644 index 0000000..1df689b Binary files /dev/null and "b/assets/textures/\346\265\213\350\257\2252.png" differ diff --git "a/assets/textures/\346\265\213\350\257\2253.png" "b/assets/textures/\346\265\213\350\257\2253.png" new file mode 100644 index 0000000..142fba7 Binary files /dev/null and "b/assets/textures/\346\265\213\350\257\2253.png" differ diff --git "a/assets/textures/\346\265\213\350\257\2254.png" "b/assets/textures/\346\265\213\350\257\2254.png" new file mode 100644 index 0000000..302d380 Binary files /dev/null and "b/assets/textures/\346\265\213\350\257\2254.png" differ diff --git "a/assets/textures/\346\265\213\350\257\2255.png" "b/assets/textures/\346\265\213\350\257\2255.png" new file mode 100644 index 0000000..6fdecba Binary files /dev/null and "b/assets/textures/\346\265\213\350\257\2255.png" differ diff --git "a/assets/textures/\346\265\213\350\257\2256.png" "b/assets/textures/\346\265\213\350\257\2256.png" new file mode 100644 index 0000000..c8358b9 Binary files /dev/null and "b/assets/textures/\346\265\213\350\257\2256.png" differ diff --git a/src/client/player/mouse_control.rs b/src/client/player/mouse_control.rs index 238ed77..ae88421 100644 --- a/src/client/player/mouse_control.rs +++ b/src/client/player/mouse_control.rs @@ -1,6 +1,6 @@ use bevy::{ prelude::{ - in_state, warn, Event, EventReader, EventWriter, IVec3, Input, IntoSystemConfigs, + in_state, warn, Event, EventReader, EventWriter, IVec3, Input, IntoSystemConfigs, KeyCode, MouseButton, Plugin, Query, Res, ResMut, Resource, Transform, Update, Vec3, }, time::{Time, Timer, TimerMode}, @@ -16,7 +16,7 @@ use crate::{ }, server::player::Player, tools::{vec3_to_chunk_key_any_xyz, zone::check_player_put_object_available}, - voxel_world::{chunk::ChunkKey, voxel::Voxel}, + voxel_world::{chunk::ChunkKey, chunk_map::ChunkMap, voxel::Voxel}, }; use super::controller::ControllerFlag; @@ -79,17 +79,43 @@ pub fn deal_broken_cube_event( //鼠标操作 pub fn mouse_button_system( mouse_button_input: Res>, + keyboard_input: Res>, choose_cube: Res, controller_flag: Res, mut client: ResMut, tool_bar_data: Res, mut attack_timer: ResMut, player_query: Query<(&Player, &Transform)>, + chunk_map: Res, ) { if !controller_flag.flag { // println!("3:{}", controller_flag.flag); return; } + + // 移动数据的方向 + if mouse_button_input.just_released(MouseButton::Left) + && keyboard_input.pressed(KeyCode::ShiftLeft) + { + if let Some(pos) = choose_cube.center { + let (chunk_key, xyz) = vec3_to_chunk_key_any_xyz(pos); + if let Some(voxel_type) = chunk_map.get_block(chunk_key, xyz) { + // FIXME: 这里要判断是否每种情况都可以去旋转! + let new_voxel = voxel_type.next_direction(); + println!("这里发送了旋转方块的指令{:?}", new_voxel); + let message = bincode::serialize(&ChunkQuery::Change { + chunk_key, + pos: xyz, + voxel_type: new_voxel, + center: pos, + active_index: None, + }) + .unwrap(); + client.send_message(ClientChannel::ChunkQuery, message); + } + } + } + if mouse_button_input.just_pressed(MouseButton::Left) || attack_timer.pressed { attack_timer.pressed = true; // println!("4:{}", controller_flag.flag); diff --git a/src/client/voxels/mesh.rs b/src/client/voxels/mesh.rs index a971478..81c69dc 100644 --- a/src/client/voxels/mesh.rs +++ b/src/client/voxels/mesh.rs @@ -10,7 +10,7 @@ use ndshape::{ConstShape, ConstShape3u32, Shape}; use crate::{ client::voxels::mesh_material::ATTRIBUTE_DATA, - voxel_world::voxel::{Voxel, VoxelMaterial, Water}, + voxel_world::voxel::{Voxel, VoxelDirection, VoxelMaterial, Water}, CHUNK_SIZE, CHUNK_SIZE_ADD_2_U32, }; @@ -52,14 +52,53 @@ where indices.extend_from_slice(&face.quad_mesh_indices(positions.len() as u32)); positions.extend_from_slice(&face.quad_mesh_positions(quad, 1.0)); normals.extend_from_slice(&face.quad_mesh_normals()); - tex_coords.extend_from_slice(&face.tex_coords( - RIGHT_HANDED_Y_UP_CONFIG.u_flip_face, - true, - quad, - )); - // 这里可以生成Data???? 但是怎么知道 是那个面的? + // 这里可以生成Data 但是怎么知道 是那个面的? let index = >::linearize(quad.minimum); + // 这里处理一下问题 + if block_face_normal_index == 1 || block_face_normal_index == 4 { + match voxels[index as usize].direction.clone() { + VoxelDirection::Z => { + tex_coords.extend_from_slice(&[ + [0.0, quad.height as f32], + [quad.width as f32, quad.height as f32], + [0.0, 0.0], + [quad.width as f32, 0.0], + ]); + } + VoxelDirection::X => { + tex_coords.extend_from_slice(&[ + [quad.width as f32, quad.height as f32], + [quad.width as f32, 0.0], + [0.0, quad.height as f32], + [0.0, 0.0], + ]); + } + VoxelDirection::NZ => { + tex_coords.extend_from_slice(&[ + [quad.width as f32, 0.0], + [0.0, 0.0], + [quad.width as f32, quad.height as f32], + [0.0, quad.height as f32], + ]); + } + VoxelDirection::NX => { + tex_coords.extend_from_slice(&[ + [0.0, 0.0], + [0.0, quad.height as f32], + [quad.width as f32, 0.0], + [quad.width as f32, quad.height as f32], + ]); + } + } + } else { + tex_coords.extend_from_slice(&face.tex_coords( + RIGHT_HANDED_Y_UP_CONFIG.u_flip_face, + true, + quad, + )); + } + // 法向量值 let normol_num = (block_face_normal_index as u32) << 8u32; // 计算贴图索引 @@ -67,8 +106,10 @@ where material_config.clone(), block_face_normal_index as u8, &voxels[index as usize].id, + voxels[index as usize].direction.clone(), ); - // todo 这里后面要知道是那个面的方便渲染 + + // 这里后面要知道是那个面的方便渲染 data.extend_from_slice(&[normol_num | (txt_index); 4]); } } @@ -165,6 +206,7 @@ pub fn gen_mesh_water(voxels: Vec, material_config: MaterailConfiguration material_config.clone(), block_face_normal_index as u8, &Water::ID, + VoxelDirection::Z, ); data.extend_from_slice(&[normol_num | (txt_index); 4]); } diff --git a/src/client/voxels/voxel_materail_config.rs b/src/client/voxels/voxel_materail_config.rs index 6c85723..020c6a7 100644 --- a/src/client/voxels/voxel_materail_config.rs +++ b/src/client/voxels/voxel_materail_config.rs @@ -5,7 +5,7 @@ use bevy_inspector_egui::prelude::*; use serde::{Deserialize, Serialize}; use walkdir::WalkDir; -use crate::voxel_world::voxel::{Grass, Soli, Stone, VoxelMaterial}; +use crate::voxel_world::voxel::{Grass, Soli, Stone, VoxelDirection, VoxelMaterial}; #[derive(Debug, Clone, Serialize, Deserialize, Default, Reflect, InspectorOptions)] #[reflect(InspectorOptions)] @@ -124,10 +124,17 @@ impl MaterailConfiguration { } // 通过面 和 体素类型获取 图片的索引 - pub fn find_volex_index(self, normal: u8, volex_type: &u8) -> u32 { + pub fn find_volex_index(self, normal: u8, volex_type: &u8, direction: VoxelDirection) -> u32 { + let change_normal = match direction { + VoxelDirection::Z => rotate_times(normal, 0), + VoxelDirection::X => rotate_times(normal, 1), + VoxelDirection::NZ => rotate_times(normal, 2), + VoxelDirection::NX => rotate_times(normal, 3), + }; + return match self.voxels.get(volex_type) { Some(config) => { - return match config.normal.get(&normal) { + return match config.normal.get(&change_normal) { Some(vconfig) => vconfig.index, None => config.default.index, }; @@ -136,3 +143,23 @@ impl MaterailConfiguration { }; } } + +fn rotate_times(normal: u8, times: usize) -> u8 { + let mut ret = normal; + if times > 0 { + for _ in 0..times { + ret = rotate_half_pi(ret); + } + } + ret +} + +fn rotate_half_pi(normal: u8) -> u8 { + return match normal { + 0 => 5, + 2 => 0, + 3 => 2, + 5 => 3, + _ => normal, + }; +} diff --git a/src/lib.rs b/src/lib.rs index a21f9f6..34f7ff3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,7 +27,7 @@ pub const CHUNK_SIZE: i32 = 16; pub const CHUNK_SIZE_U32: u32 = CHUNK_SIZE as u32; pub const CHUNK_SIZE_ADD_2_U32: u32 = CHUNK_SIZE_U32 + 2; // 贴图个数 -pub const MAX_TEXTURE_COUNT: usize = 16; +pub const MAX_TEXTURE_COUNT: usize = 22; // 物体选择半径 pub const TOUCH_RADIUS: f32 = 5.; pub const CLIENT_DEBUG: bool = false; diff --git a/src/server/async_chunk.rs b/src/server/async_chunk.rs index 9f9c1f5..5e08a3e 100644 --- a/src/server/async_chunk.rs +++ b/src/server/async_chunk.rs @@ -105,7 +105,10 @@ pub fn deal_chunk_query_system( warn!("基岩无法破坏"); continue; } - if old_voxel.id != Voxel::EMPTY.id && voxel_type.id != Voxel::EMPTY.id { + if old_voxel.id != Voxel::EMPTY.id + && voxel_type.id != Voxel::EMPTY.id + && active_index != None + { warn!("放置错误"); continue; } @@ -130,7 +133,11 @@ pub fn deal_chunk_query_system( } } else { warn!("{}|角色没有当前生成的index", client_id); - continue; + if old_voxel.direction == voxel_type.direction { + continue; + } else { + println!("转动方向"); + } } } else { warn!("{}|{}没有找到资源对应关系", client_id, voxel_type.id); diff --git a/src/voxel_world/voxel.rs b/src/voxel_world/voxel.rs index b38da62..9936d37 100644 --- a/src/voxel_world/voxel.rs +++ b/src/voxel_world/voxel.rs @@ -4,12 +4,47 @@ use serde::{Deserialize, Serialize}; /** * 体素类型 + * + * 这里要设计使用 u32的数据 + * voxel_data >> 8u & 0b111 8位后的数据 9 10 11位置的数据 + * voxel_data & 255u 表示取最后的8位 + * 方块是否透明是否要记录呢?不用在数据库中,但是转回来的时候我要知道。并且可以生成对应的mesh在地图中 + * + * 存储类型: + * 体素类型 方块方向 + * [0-8] [9 10] + * todo 在某种情况下计算不同位置的 图片索引和贴图? + * + * 展示时的数据 + * 贴图索引 法向量 方块方向 + * [0-8] [9-11] [12 13] + * + * 是否可视等 是在其他地方定义的 + * */ #[derive(Debug, Clone, Copy, Default, Deserialize, Serialize, Reflect, PartialEq, Eq, Hash)] pub struct Voxel { pub id: u8, + pub direction: VoxelDirection, } +// 体素方向 +#[derive(Debug, Clone, Copy, Reflect, Serialize, Deserialize, Default, PartialEq, Eq, Hash)] +pub enum VoxelDirection { + #[default] + Z, + NZ, // 指向Z的负数半轴 + X, + NX, // 指向X的负数半轴 +} + +pub const VOXEL_DIRECTION_VEC: [VoxelDirection; 4] = [ + VoxelDirection::Z, + VoxelDirection::NZ, + VoxelDirection::X, + VoxelDirection::NX, +]; + impl PartialOrd for Voxel { fn partial_cmp(&self, other: &Self) -> Option { self.id.partial_cmp(&other.id) @@ -23,8 +58,53 @@ impl Ord for Voxel { } impl Voxel { - pub const EMPTY: Self = Self { id: 0 }; - pub const FILLED: Self = Self { id: 1 }; + pub const EMPTY: Self = Self { + id: 0, + direction: VoxelDirection::Z, + }; + pub const FILLED: Self = Self { + id: 1, + direction: VoxelDirection::Z, + }; + + // 转换成32位的存在类型 + pub fn into_save_u32(&self) -> u32 { + let direction_base = match self.direction { + VoxelDirection::Z => 0u32 << 8u32, + VoxelDirection::NZ => 1u32 << 8u32, + VoxelDirection::X => 2u32 << 8u32, + VoxelDirection::NX => 3u32 << 8u32, + }; + (self.id as u32) | direction_base + } + + // u32 位置类型转换成 体素类型 + pub fn u32_into_voxel(data: u32) -> Self { + Self { + id: Self::pick_id(data), + direction: Self::pick_direction(data), + } + } + + pub fn pick_id(data: u32) -> u8 { + (data & 255u32) as u8 + } + + pub fn pick_direction(data: u32) -> VoxelDirection { + VOXEL_DIRECTION_VEC[(data >> 8u32 & 0b11) as usize] + } + + pub fn next_direction(&self) -> Self { + Self { + id: self.id, + direction: match self.direction { + VoxelDirection::Z => VoxelDirection::X, + VoxelDirection::X => VoxelDirection::NZ, + VoxelDirection::NZ => VoxelDirection::NX, + VoxelDirection::NX => VoxelDirection::Z, + }, + } + } } impl MeshVoxel for Voxel { @@ -49,7 +129,18 @@ pub trait VoxelMaterial { const ID: u8; fn into_voxel() -> Voxel { - Voxel { id: Self::ID } + Voxel { + id: Self::ID, + ..Default::default() + } + } + + // 转化成 有方向的体素数据 + fn into_voxel_with_dir(direction: VoxelDirection) -> Voxel { + Voxel { + id: Self::ID, + direction, + } } } @@ -81,3 +172,4 @@ voxel_material!(DryGrass, 干草地, 8); voxel_material!(BuleGrass, 苍翠地, 9); voxel_material!(AppleWood, 苹果树原木, 10); voxel_material!(AppleLeaf, 苹果树叶子, 11); +voxel_material!(TestCube, 测试方块, 12); diff --git a/staff.ron b/staff.ron index 5b02c00..49c4646 100644 --- a/staff.ron +++ b/staff.ron @@ -1,17 +1,18 @@ ( configs:[ - (id:0,name:"Stone",icon_string:"textures/002.png",staff_type:Voxel((id:1))), - (id:1,name:"Grass",icon_string:"textures/草坪.png",staff_type:Voxel((id:3))), - (id:2,name:"Soli",icon_string:"textures/003.png",staff_type:Voxel((id:2))), - (id:3,name:"Sand",icon_string:"textures/沙子.png",staff_type:Voxel((id:6))), - (id:4,name:"Sown",icon_string:"textures/雪.png",staff_type:Voxel((id:4))), + (id:0,name:"Stone",icon_string:"textures/002.png",staff_type:Voxel((id:1,direction:Z))), + (id:1,name:"Grass",icon_string:"textures/草坪.png",staff_type:Voxel((id:3,direction:Z))), + (id:2,name:"Soli",icon_string:"textures/003.png",staff_type:Voxel((id:2,direction:Z))), + (id:3,name:"Sand",icon_string:"textures/沙子.png",staff_type:Voxel((id:6,direction:Z))), + (id:4,name:"Sown",icon_string:"textures/雪.png",staff_type:Voxel((id:4,direction:Z))), (id:5,name:"FireWork",icon_string:"staff/烟花.png",staff_type:Consumable(0)), - (id:6,name:"DryGrass",icon_string:"textures/干草地.png",staff_type:Voxel((id:8))), - (id:7,name:"BlueGrass",icon_string:"textures/苍翠地.png",staff_type:Voxel((id:9))), - (id:8,name:"AppleWood",icon_string:"textures/苹果树A面.png",staff_type:Voxel((id:10))), - (id:9,name:"AppleLeaf",icon_string:"textures/苹果叶子.png",staff_type:Voxel((id:11))), + (id:6,name:"DryGrass",icon_string:"textures/干草地.png",staff_type:Voxel((id:8,direction:Z))), + (id:7,name:"BlueGrass",icon_string:"textures/苍翠地.png",staff_type:Voxel((id:9,direction:Z))), + (id:8,name:"AppleWood",icon_string:"textures/苹果树A面.png",staff_type:Voxel((id:10,direction:Z))), + (id:9,name:"AppleLeaf",icon_string:"textures/苹果叶子.png",staff_type:Voxel((id:11,direction:Z))), (id:10,name:"Apple",icon_string:"textures/苹果.png",staff_type:Consumable(0)), (id:11,name:"AppleLog",icon_string:"textures/棍子.png",staff_type:Consumable(0)), + (id:12,name:"TestCube",icon_string:"textures/测试1.png",staff_type:Voxel((id:12,direction:Z))), ], // 掉落配置 filled_configs:[ diff --git a/staff_rules.ron b/staff_rules.ron index 7397063..61601ff 100644 --- a/staff_rules.ron +++ b/staff_rules.ron @@ -14,4 +14,16 @@ base_on:None, desc:"测试使用的合成烟花的公式(测试一个合成多个)", ), + ( + id:1, + input:[ + (staff_id:0,num_needed:1), + ], + // 合成测试方块 + output: [ + (staff_id:12,num_needed:1), + ], + base_on:None, + desc:"合成测试使用的摆放方块", + ), ] \ No newline at end of file diff --git a/volex.ron b/volex.ron index 2e4b076..90a750e 100644 --- a/volex.ron +++ b/volex.ron @@ -1,5 +1,13 @@ ( voxels:{ + 12:(type_name:"TestCube",type_ch_name:"测试使用方块",default:(index:21,path:"textures/测试6.png"),normal:{ + 1:(index:16,path:"textures/测试1.png"), + 2:(index:17,path:"textures/测试2.png"), + 3:(index:18,path:"textures/测试3.png"), + 4:(index:19,path:"textures/测试4.png"), + 5:(index:20,path:"textures/测试5.png"), + 0:(index:21,path:"textures/测试6.png"), + }), 11:(type_name:"AppleLeaf",type_ch_name:"苹果树叶子",default:(index:15,path:"textures/苹果叶子.png"),normal:{}), 10:(type_name:"AppleWood",type_ch_name:"苹果树原木",default:(index:13,path:"textures/苹果树A面.png"),normal:{ 4:(index:14,path:"textures/苹果树B面.png"), @@ -44,4 +52,11 @@ "textures/苹果树B面.png", //15 "textures/苹果叶子.png", + "textures/测试1.png", + "textures/测试2.png", + "textures/测试3.png", + "textures/测试4.png", + //20 + "textures/测试5.png", + "textures/测试6.png", ]) \ No newline at end of file