Method for shifting world nodes texture
This commit is contained in:
+1
-1
@@ -27,7 +27,7 @@ impl Game {
|
|||||||
Self {
|
Self {
|
||||||
state: GameState::Paused,
|
state: GameState::Paused,
|
||||||
player: Player::new(),
|
player: Player::new(),
|
||||||
world: World::new("default".to_string()),
|
world: World::init("hello".to_string()),
|
||||||
prev_pos: None
|
prev_pos: None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ impl WorldChunk {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
pub fn from_bytes(bytes: Vec<u8>) -> Self {
|
pub fn from_bytes(bytes: Vec<u8>) -> Self {
|
||||||
let mut instance = Self::new();
|
let mut instance = Self::new();
|
||||||
|
|
||||||
@@ -61,7 +60,6 @@ impl WorldChunk {
|
|||||||
instance
|
instance
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
pub fn to_bytes(&self) -> Vec<u8> {
|
pub fn to_bytes(&self) -> Vec<u8> {
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct WorldData {
|
||||||
|
pub name: String,
|
||||||
|
pub display_name: String
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for WorldData {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
name: String::from("default"),
|
||||||
|
display_name: String::from("Default")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+60
-71
@@ -1,4 +1,5 @@
|
|||||||
mod generator;
|
mod generator;
|
||||||
|
mod data;
|
||||||
pub mod chunk;
|
pub mod chunk;
|
||||||
pub mod block;
|
pub mod block;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
@@ -6,17 +7,12 @@ use std::path::PathBuf;
|
|||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use cgmath::{Point3, Vector3};
|
use cgmath::Vector3;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use generator::WorldGen;
|
use generator::WorldGen;
|
||||||
use chunk::WorldChunk;
|
use chunk::WorldChunk;
|
||||||
use block::WorldBlock;
|
use block::WorldBlock;
|
||||||
|
use data::WorldData;
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
|
||||||
struct WorldData {
|
|
||||||
#[serde(default)]
|
|
||||||
pub name: String
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct World {
|
pub struct World {
|
||||||
data: WorldData,
|
data: WorldData,
|
||||||
@@ -25,43 +21,56 @@ pub struct World {
|
|||||||
|
|
||||||
impl World {
|
impl World {
|
||||||
|
|
||||||
pub fn new(name: String) -> Self {
|
pub fn init(name: String) -> Self {
|
||||||
Self {
|
let mut instance = Self {
|
||||||
data: WorldData { name },
|
data: WorldData { name, ..Default::default() },
|
||||||
chunks: HashMap::new(),
|
chunks: HashMap::new(),
|
||||||
|
};
|
||||||
|
instance.load_metadata();
|
||||||
|
instance.save_all();
|
||||||
|
instance
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loads metadata
|
||||||
|
*/
|
||||||
|
fn load_metadata(&mut self) -> bool {
|
||||||
|
let filepath = dirs::data_local_dir().unwrap().join("Voxelgame").join(self.data.name.clone()).join("world.dat");
|
||||||
|
if let Ok(mut file) = fs::File::open(filepath) {
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
file.read_to_end(&mut buf).unwrap();
|
||||||
|
if let Ok(data) = toml::from_slice::<WorldData>(&buf[..]) {
|
||||||
|
self.data = data;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn all_blocks(&self) -> Vec<(Vector3<i32>, &WorldBlock)> {
|
/*
|
||||||
self.chunks.iter().map(|(chunk_pos, chunk)| {
|
* Saves metadata and all loaded chunks
|
||||||
let off = chunk_pos * chunk::SIZE as i32;
|
*/
|
||||||
let result: Vec<(Vector3<i32>, &WorldBlock)> = chunk.all_blocks().iter().map(|(pos, block)| {
|
pub fn save_all(&self) {
|
||||||
(
|
|
||||||
Vector3{x: off.x+pos.x as i32, y: off.y+pos.y as i32, z: off.z+pos.z as i32},
|
|
||||||
*block
|
|
||||||
)
|
|
||||||
}).collect();
|
|
||||||
result
|
|
||||||
}).flatten().collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn save(&self) {
|
|
||||||
// Get directory
|
// Get directory
|
||||||
let dir = dirs::data_local_dir().unwrap().join("Voxelgame");
|
let dirpath = dirs::data_local_dir().unwrap().join("Voxelgame").join("saves").join(&self.data.name);
|
||||||
fs::create_dir_all(&dir).expect("Failed to create directory");
|
fs::create_dir_all(&dirpath).expect("Failed to create world directory");
|
||||||
|
|
||||||
// Save all chunks
|
// Save all chunks
|
||||||
for (pos, chunk) in self.chunks.iter() {
|
for (pos, chunk) in self.chunks.iter() {
|
||||||
let path = dir.with_file_name(format!("chunk_{}_{}_{}.dat", pos.x, pos.y, pos.z));
|
let filepath = dirpath.join(format!("chunk_{}_{}_{}.dat", pos.x, pos.y, pos.z));
|
||||||
let mut file = fs::File::create(path).expect("Failed to create file");
|
let mut file = fs::File::create(filepath).expect("Failed to create chunk file");
|
||||||
file.write(&chunk.to_bytes()).unwrap();
|
file.write(&chunk.to_bytes()).expect("Failed to write chunk file");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save metadata
|
// Save metadata
|
||||||
let data_str = toml::to_string(&self.data).unwrap();
|
let datastr = toml::to_string(&self.data).unwrap();
|
||||||
let data_path: PathBuf = [dir.to_str().unwrap(), "world.dat"].iter().collect();
|
let datapath: PathBuf = dirpath.join("world.dat");
|
||||||
let mut data_file = fs::File::create(data_path).unwrap();
|
let mut datafile = fs::File::create(datapath).expect("Failed to create world metadata file");
|
||||||
data_file.write_all(data_str.as_bytes()).expect("Failed to write world metadata");
|
datafile.write_all(datastr.as_bytes()).expect("Failed to write world metadata");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_chunk(&mut self, chunk_wpos: &Vector3<i32>) -> Option<&mut WorldChunk> {
|
||||||
|
self.chunks.get_mut(chunk_wpos)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -76,12 +85,13 @@ impl World {
|
|||||||
|
|
||||||
// Try loading chunk from file
|
// Try loading chunk from file
|
||||||
let filename = format!("chunk_{}_{}_{}.dat", pos.x, pos.y, pos.z);
|
let filename = format!("chunk_{}_{}_{}.dat", pos.x, pos.y, pos.z);
|
||||||
let filepath = dirs::data_local_dir().unwrap().join("Voxelgame").with_file_name(filename);
|
let filepath = dirs::data_local_dir().unwrap().join("Voxelgame").join("saves").join(&self.data.name).join(filename);
|
||||||
|
|
||||||
if filepath.is_file() {
|
if filepath.is_file() {
|
||||||
let timer = Instant::now();
|
let timer = Instant::now();
|
||||||
let mut buff = Vec::new();
|
let mut buff = Vec::new();
|
||||||
let mut file = fs::File::open(filepath).expect("Failed to open file");
|
let mut file = fs::File::open(filepath).expect("Failed to open chunk file");
|
||||||
file.read_to_end(&mut buff).expect("Failed to read file");
|
file.read_to_end(&mut buff).expect("Failed to read chunk file");
|
||||||
let chunk = WorldChunk::from_bytes(buff);
|
let chunk = WorldChunk::from_bytes(buff);
|
||||||
self.chunks.insert(pos, chunk);
|
self.chunks.insert(pos, chunk);
|
||||||
println!("Chunk at {:?} loaded ({} ms)", pos, timer.elapsed().as_millis());
|
println!("Chunk at {:?} loaded ({} ms)", pos, timer.elapsed().as_millis());
|
||||||
@@ -99,13 +109,11 @@ impl World {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save
|
// Save generated chunk to file
|
||||||
let timer1 = Instant::now();
|
let timer1 = Instant::now();
|
||||||
let dir = dirs::data_local_dir().unwrap().join("Voxelgame");
|
fs::create_dir_all(&filepath.parent().unwrap()).expect("Failed to create world directory");
|
||||||
fs::create_dir_all(&dir).expect("Failed to create directory");
|
let mut file = fs::File::create(filepath).expect("Failed to create chunk file");
|
||||||
let path = dir.with_file_name(format!("chunk_{}_{}_{}.dat", pos.x, pos.y, pos.z));
|
file.write(&chunk.to_bytes()).expect("Failed to write chunk file");
|
||||||
let mut file = fs::File::create(path).expect("Failed to create file");
|
|
||||||
file.write(&chunk.to_bytes()).unwrap();
|
|
||||||
|
|
||||||
// Add to list
|
// Add to list
|
||||||
self.chunks.insert(pos, chunk);
|
self.chunks.insert(pos, chunk);
|
||||||
@@ -117,33 +125,14 @@ impl World {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load(&mut self) -> bool {
|
// pub fn get_block(&mut self, block_wpos: &Vector3<i32>) -> Option<&WorldBlock> {
|
||||||
// Load metadata
|
// // Split world space to chunk and block space
|
||||||
let filepath = dirs::data_local_dir().unwrap().join("Voxelgame").with_file_name("world.dat");
|
// let ch_pos = block_wpos / chunk::SIZE as i32;
|
||||||
if let Ok(mut file) = fs::File::open(filepath) {
|
// let bl_pos = block_wpos % chunk::SIZE as i32;
|
||||||
let mut buf = Vec::new();
|
// // Return block if exists
|
||||||
file.read_to_end(&mut buf).unwrap();
|
// if let Some(chunk) = self.chunks.get_mut(&ch_pos) {
|
||||||
if let Ok(data) = toml::from_slice::<WorldData>(&buf[..]) {
|
// return Some(chunk.get_block(&bl_pos));
|
||||||
self.data = data;
|
// }
|
||||||
return true;
|
// None
|
||||||
}
|
// }
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
pub fn get_block(&mut self, block_wpos: &Vector3<i32>) -> Option<&WorldBlock> {
|
|
||||||
// Split world space to chunk and block space
|
|
||||||
let ch_pos = block_wpos / chunk::SIZE as i32;
|
|
||||||
let bl_pos = block_wpos % chunk::SIZE as i32;
|
|
||||||
// Return block if exists
|
|
||||||
if let Some(chunk) = self.chunks.get_mut(&ch_pos) {
|
|
||||||
return Some(chunk.get_block(&bl_pos));
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_chunk(&mut self, chunk_wpos: &Vector3<i32>) -> Option<&mut WorldChunk> {
|
|
||||||
self.chunks.get_mut(chunk_wpos)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+23
-6
@@ -1,3 +1,5 @@
|
|||||||
|
use cgmath::Vector3;
|
||||||
|
use crate::renderer::renderer_view::RendererView;
|
||||||
use winit::{
|
use winit::{
|
||||||
event::{Event, WindowEvent, KeyboardInput, ElementState, VirtualKeyCode, MouseButton},
|
event::{Event, WindowEvent, KeyboardInput, ElementState, VirtualKeyCode, MouseButton},
|
||||||
event_loop::{ControlFlow, EventLoop},
|
event_loop::{ControlFlow, EventLoop},
|
||||||
@@ -43,13 +45,28 @@ fn main() {
|
|||||||
match event {
|
match event {
|
||||||
// Window closed (ALT+F4,)
|
// Window closed (ALT+F4,)
|
||||||
WindowEvent::CloseRequested => { *c = ControlFlow::Exit; }
|
WindowEvent::CloseRequested => { *c = ControlFlow::Exit; }
|
||||||
// Escape key
|
// Key pressed
|
||||||
WindowEvent::KeyboardInput { input: KeyboardInput { state: ElementState::Pressed, virtual_keycode: Some(VirtualKeyCode::Escape), .. }, .. } => {
|
WindowEvent::KeyboardInput { input: KeyboardInput { state: ElementState::Pressed, virtual_keycode, .. }, .. } => {
|
||||||
// Request pause
|
if let Some(key) = virtual_keycode {
|
||||||
if let GameState::Paused = game.update_state(GameState::Paused) {
|
match key {
|
||||||
window.set_cursor_grab(false).unwrap();
|
// Escape pressed
|
||||||
window.set_cursor_visible(true);
|
VirtualKeyCode::Escape => {
|
||||||
|
if let GameState::Paused = game.update_state(GameState::Paused) {
|
||||||
|
window.set_cursor_grab(false).unwrap();
|
||||||
|
window.set_cursor_visible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Test key
|
||||||
|
VirtualKeyCode::T => {
|
||||||
|
let t = &mut renderer as &mut dyn RendererView;
|
||||||
|
t.shift(&Vector3::<i32>{ x:32, y:0, z:0 });
|
||||||
|
println!("shifted");
|
||||||
|
}
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// Window clicked
|
// Window clicked
|
||||||
WindowEvent::MouseInput { state: ElementState::Pressed, button: MouseButton::Left, .. } => {
|
WindowEvent::MouseInput { state: ElementState::Pressed, button: MouseButton::Left, .. } => {
|
||||||
|
|||||||
@@ -101,7 +101,6 @@ impl Content {
|
|||||||
ContentStats { node_tex_size, block_tex_size, block_tex_used, block_count, block_used }
|
ContentStats { node_tex_size, block_tex_size, block_tex_used, block_count, block_used }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
pub fn write(&mut self, queue: &wgpu::Queue, block_pos: &Vector3<i32>, block: &WorldBlock) {
|
pub fn write(&mut self, queue: &wgpu::Queue, block_pos: &Vector3<i32>, block: &WorldBlock) {
|
||||||
|
|
||||||
// Get node
|
// Get node
|
||||||
@@ -139,6 +138,37 @@ impl Content {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn shift(&mut self, offset: &Vector3<i32>) {
|
||||||
|
let timer = Instant::now();
|
||||||
|
let mut result = vec![0_u32; self.node_buffer.len()].into_boxed_slice();
|
||||||
|
let ox = offset.x as usize;
|
||||||
|
let oy = offset.y as usize;
|
||||||
|
let oz = offset.z as usize;
|
||||||
|
|
||||||
|
for x0 in 0..NODE_TEX_SIZE {
|
||||||
|
let x1 = x0+ox;
|
||||||
|
if x1 >= NODE_TEX_SIZE { continue; }
|
||||||
|
|
||||||
|
for y0 in 0..NODE_TEX_SIZE {
|
||||||
|
let y1 = y0+oy;
|
||||||
|
if y1 >= NODE_TEX_SIZE { continue; }
|
||||||
|
|
||||||
|
for z0 in 0..NODE_TEX_SIZE {
|
||||||
|
let z1 = z0+oz;
|
||||||
|
if z1 >= NODE_TEX_SIZE { continue; }
|
||||||
|
|
||||||
|
let idx0 = x0 + NODE_TEX_SIZE * (y0 + NODE_TEX_SIZE * z0);
|
||||||
|
let idx1 = x1 + NODE_TEX_SIZE * (y1 + NODE_TEX_SIZE * z1);
|
||||||
|
result[idx1] = self.node_buffer[idx0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.node_buffer = result;
|
||||||
|
self.node_dirty = true;
|
||||||
|
println!("Shifted in {} ms", timer.elapsed().as_millis());
|
||||||
|
}
|
||||||
|
|
||||||
fn write_nodes(&mut self, queue: &wgpu::Queue, z: usize) {
|
fn write_nodes(&mut self, queue: &wgpu::Queue, z: usize) {
|
||||||
// Convert u32 node buffer to u8
|
// Convert u32 node buffer to u8
|
||||||
let node_origin = wgpu::Origin3d{ x:0, y: 0, z: z as u32 };
|
let node_origin = wgpu::Origin3d{ x:0, y: 0, z: z as u32 };
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use cgmath::Vector3;
|
|||||||
|
|
||||||
pub trait RendererView {
|
pub trait RendererView {
|
||||||
fn write(&mut self, block_pos: &Vector3<i32>, block: &WorldBlock);
|
fn write(&mut self, block_pos: &Vector3<i32>, block: &WorldBlock);
|
||||||
|
fn shift(&mut self, offset: &Vector3<i32>);
|
||||||
fn get_camera_transform(&mut self) -> &mut dyn CameraTransform;
|
fn get_camera_transform(&mut self) -> &mut dyn CameraTransform;
|
||||||
fn get_ui(&mut self) -> &mut UserInterface;
|
fn get_ui(&mut self) -> &mut UserInterface;
|
||||||
}
|
}
|
||||||
@@ -16,6 +17,10 @@ impl RendererView for Renderer {
|
|||||||
self.buffers.content.write(&self.queue, block_pos, block)
|
self.buffers.content.write(&self.queue, block_pos, block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn shift(&mut self, offset: &Vector3<i32>) {
|
||||||
|
self.buffers.content.shift(offset);
|
||||||
|
}
|
||||||
|
|
||||||
fn get_camera_transform(&mut self) -> &mut dyn CameraTransform {
|
fn get_camera_transform(&mut self) -> &mut dyn CameraTransform {
|
||||||
&mut self.camera
|
&mut self.camera
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user