This commit is contained in:
griffi-gh 2023-11-20 20:59:34 +01:00
parent e2bec4bf2e
commit 43ca458896
7 changed files with 122 additions and 23 deletions

2
.gitignore vendored
View file

@ -13,3 +13,5 @@ target/
_src
_visualizer.json
*.kubi

27
Cargo.lock generated
View file

@ -1033,11 +1033,13 @@ dependencies = [
"glam",
"hashbrown 0.14.0",
"nohash-hasher",
"num_enum 0.7.1",
"postcard",
"rand",
"rand_xoshiro",
"serde",
"shipyard",
"static_assertions",
"strum",
]
@ -1223,7 +1225,7 @@ dependencies = [
"bitflags 1.3.2",
"jni-sys",
"ndk-sys",
"num_enum",
"num_enum 0.5.11",
"raw-window-handle 0.5.2",
"thiserror",
]
@ -1371,7 +1373,16 @@ version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9"
dependencies = [
"num_enum_derive",
"num_enum_derive 0.5.11",
]
[[package]]
name = "num_enum"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0"
dependencies = [
"num_enum_derive 0.7.1",
]
[[package]]
@ -1386,6 +1397,18 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "num_enum_derive"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.23",
]
[[package]]
name = "objc"
version = "0.2.7"

View file

@ -8,6 +8,7 @@ publish = false
glam = { version = "0.24", features = ["debug-glam-assert", "fast-math", "serde"] }
shipyard = { git = "https://github.com/leudz/shipyard", rev = "0934b426eb9a8", default-features = false, features = ["std"] }
strum = { version = "0.25", features = ["derive"] }
num_enum = "0.7"
postcard = { version = "1.0", features = ["alloc"] }
serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] }
bincode = "1.3"
@ -17,9 +18,8 @@ rand = { version = "0.8", default_features = false, features = ["std", "min_cons
rand_xoshiro = "0.6"
hashbrown = { version = "0.14", features = ["serde"] }
nohash-hasher = "0.2"
#bytemuck = { version = "1.14", features = ["derive"] }
#static_assertions = "1.1"
static_assertions = "1.1"
[features]
default = []

View file

@ -1,5 +1,6 @@
use serde::{Serialize, Deserialize};
use strum::EnumIter;
use num_enum::TryFromPrimitive;
#[derive(Serialize, Deserialize, Clone, Copy, Debug, EnumIter)]
#[repr(u8)]
@ -22,7 +23,7 @@ pub enum BlockTexture {
WaterSolid,
}
#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, EnumIter)]
#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, EnumIter, TryFromPrimitive)]
#[repr(u8)]
pub enum Block {
Air,

View file

@ -2,13 +2,20 @@ use std::{
fs::File,
mem::size_of,
io::{Read, Seek, SeekFrom, Write},
borrow::Cow
borrow::Cow,
sync::{Arc, RwLock}
};
use num_enum::TryFromPrimitive;
use serde::{Serialize, Deserialize};
use glam::IVec2;
use glam::IVec3;
use hashbrown::HashMap;
use anyhow::Result;
use crate::{block::Block, chunk::{CHUNK_SIZE, BlockDataRef}};
use shipyard::Unique;
use static_assertions::const_assert_eq;
use crate::{
block::Block,
chunk::{CHUNK_SIZE, BlockDataRef, BlockData}
};
const SECTOR_SIZE: usize = CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE * size_of::<Block>();
const RESERVED_SIZE: usize = 1048576; //~1mb (16 sectors assuming 32x32x32 world of 1byte blocks)
@ -20,13 +27,13 @@ const HEADER_MAGIC_STR: [u8; 4] = *b"KUBI";
const HEADER_MAGIC_IDENTITY: u32 = 1;
// #[repr(transparent)]
// struct IVec2Hash(IVec2);
// struct IVec3Hash(IVec3);
#[derive(Serialize, Deserialize)]
struct WorldSaveDataHeader {
pub struct WorldSaveDataHeader {
pub name: Cow<'static, str>,
pub seed: u64,
sector_count: u32,
chunk_map: HashMap<IVec2, u32>,
chunk_map: HashMap<IVec3, u32>,
}
impl Default for WorldSaveDataHeader {
@ -40,11 +47,14 @@ impl Default for WorldSaveDataHeader {
}
}
struct WorldSaveFile {
#[derive(Unique)]
pub struct WorldSaveFile {
pub file: File,
pub header: WorldSaveDataHeader,
}
pub type SharedSaveFile = Arc<RwLock<WorldSaveFile>>;
impl WorldSaveFile {
pub fn new(file: File) -> Self {
WorldSaveFile {
@ -82,13 +92,23 @@ impl WorldSaveFile {
Ok(())
}
pub fn initialize(&mut self) -> Result<()> {
self.write_header()?;
Ok(())
}
pub fn load_data(&mut self) -> Result<()> {
self.read_header()?;
Ok(())
}
fn allocate_sector(&mut self) -> u32 {
let value = self.header.sector_count + 1;
self.header.sector_count += 1;
value
}
pub fn save_chunk(&mut self, position: IVec2, data: &BlockDataRef) -> Result<()> {
pub fn save_chunk(&mut self, position: IVec3, data: &BlockDataRef) -> Result<()> {
let mut header_modified = false;
let sector = self.header.chunk_map.get(&position).copied().unwrap_or_else(|| {
header_modified = true;
@ -96,7 +116,8 @@ impl WorldSaveFile {
});
let offset = sector as u64 * SECTOR_SIZE as u64;
//SAFETY: *nuzzles* t-t-twust me pwease OwO
const_assert_eq!(size_of::<Block>(), 1);
let data: &[u8; SECTOR_SIZE] = unsafe { std::mem::transmute(data) };
self.file.seek(SeekFrom::Start(offset))?;
@ -108,4 +129,41 @@ impl WorldSaveFile {
self.file.sync_data()?;
Ok(())
}
///TODO partial chunk commit (No need to write whole 32kb for a single block change!)
pub fn chunk_set_block() {
todo!()
}
pub fn chunk_exists(&self, position: IVec3) -> bool {
self.header.chunk_map.contains_key(&position)
}
pub fn load_chunk(&mut self, position: IVec3) -> Result<Option<BlockData>> {
let Some(&sector) = self.header.chunk_map.get(&position) else {
return Ok(None);
};
let mut buffer = Box::new([0u8; CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE * size_of::<Block>()]);
let offset = sector as u64 * SECTOR_SIZE as u64;
self.file.seek(SeekFrom::Start(offset))?;
self.file.read_exact(&mut buffer[..])?;
//should be safe under these conditions:
//Block is a single byte
//All block data bytes are in valid range
const_assert_eq!(size_of::<Block>(), 1);
for &byte in &buffer[..] {
let block = Block::try_from_primitive(byte);
match block {
//Sanity check, not actually required: (should NEVER happen)
Ok(block) => debug_assert_eq!(byte, block as u8),
Err(_) => anyhow::bail!("invalid block data"),
}
}
let data: BlockData = unsafe { std::mem::transmute(buffer) };
Ok(Some(data))
}
}

View file

@ -1,9 +1,26 @@
use shipyard::{AllStoragesView, UniqueViewMut};
use std::{env, net::SocketAddr};
use std::{env, net::SocketAddr, fs::OpenOptions, path::{Path, PathBuf}, str::FromStr, sync::{Arc, RwLock}};
use anyhow::Result;
use crate::{
networking::{GameType, ServerAddress},
state::{GameState, NextState}
};
use kubi_shared::data::{WorldSaveFile, SharedSaveFile};
fn open_local_save_file(path: &Path) -> Result<WorldSaveFile> {
let mut save_file = WorldSaveFile::new({
OpenOptions::new()
.read(true)
.write(true)
.open("world.kbi")?
});
if save_file.file.metadata().unwrap().len() == 0 {
save_file.initialize()?;
} else {
save_file.load_data()?;
}
Ok(save_file)
}
pub fn initialize_from_args(
all_storages: AllStoragesView,

View file

@ -6,11 +6,9 @@ use shipyard::{
NonSendSync, WorkloadModificator,
SystemModificator
};
use glium::{
glutin::{
event_loop::{EventLoop, ControlFlow},
event::{Event, WindowEvent}
}
use glium::glutin::{
event_loop::{EventLoop, ControlFlow},
event::{Event, WindowEvent}
};
use glam::vec3;
use std::time::Instant;