Compare commits

..

No commits in common. "4948d85e05b9f151537da2bded5bde6cfc5be643" and "9f5b974f82f080c7c5dce2627a68b948691f5bfd" have entirely different histories.

15 changed files with 1118 additions and 1107 deletions

635
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -33,8 +33,3 @@ opt-level = 3
[profile.dev.package.rayon]
opt-level = 3
#this is cursed as fuck
#enabling debug assertions here causes the game to abort
[profile.dev.package.android-activity]
debug-assertions = false

View file

@ -1,29 +1,29 @@
[package]
name = "kubi-server"
version = "0.0.0"
edition = "2021"
publish = false
[dependencies]
kubi-shared = { path = "../kubi-shared" }
kubi-logging = { path = "../kubi-logging" }
log = "0.4"
shipyard = { git = "https://github.com/leudz/shipyard", rev = "9099b990e", default-features = false, features = ["std", "proc", "thread_local"] }
serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] }
toml = "0.8"
glam = { version = "0.25", features = ["debug-glam-assert", "fast-math"] }
hashbrown = "0.14"
nohash-hasher = "0.2"
anyhow = "1.0"
rayon = "1.7"
flume = "0.11"
rand = "0.8"
uflow = "0.7"
postcard = { version = "1.0", features = ["alloc"] }
lz4_flex = { version = "0.11", default-features = false, features = ["std"] }
[features]
default = ["parallel"]
parallel = ["shipyard/parallel"]
safe_lz4 = ["lz4_flex/safe-encode", "lz4_flex/safe-decode"]
nightly = ["hashbrown/nightly", "rand/nightly", "rand/simd_support", "glam/core-simd", "kubi-shared/nightly"]
[package]
name = "kubi-server"
version = "0.0.0"
edition = "2021"
publish = false
[dependencies]
kubi-shared = { path = "../kubi-shared" }
kubi-logging = { path = "../kubi-logging" }
log = "0.4"
shipyard = { git = "https://github.com/leudz/shipyard", rev = "8ef90ea6c4d1eb6c9cb0988f0d2f873f75044d49", default-features = false, features = ["std", "proc", "thread_local"] }
serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] }
toml = "0.8"
glam = { version = "0.24", features = ["debug-glam-assert", "fast-math"] }
hashbrown = "0.14"
nohash-hasher = "0.2"
anyhow = "1.0"
rayon = "1.7"
flume = "0.11"
rand = "0.8"
uflow = "0.7"
postcard = { version = "1.0", features = ["alloc"] }
lz4_flex = { version = "0.11", default-features = false, features = ["std"] }
[features]
default = ["parallel"]
parallel = ["shipyard/parallel"]
safe_lz4 = ["lz4_flex/safe-encode", "lz4_flex/safe-decode"]
nightly = ["hashbrown/nightly", "rand/nightly", "rand/simd_support", "glam/core-simd", "kubi-shared/nightly"]

View file

@ -1,28 +1,28 @@
[package]
name = "kubi-shared"
version = "0.0.0"
edition = "2021"
publish = false
[dependencies]
glam = { version = "0.25", features = ["debug-glam-assert", "fast-math", "serde"] }
shipyard = { git = "https://github.com/leudz/shipyard", rev = "9099b990e", default-features = false, features = ["std"] }
strum = { version = "0.26", features = ["derive"] }
num_enum = "0.7"
postcard = { version = "1.0", features = ["alloc"] }
serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] }
serde_with = "3.4"
bincode = "1.3"
anyhow = "1.0"
bracket-noise = "0.8"
rand = { version = "0.8", default_features = false, features = ["std", "min_const_gen"] }
rand_xoshiro = "0.6"
hashbrown = { version = "0.14", features = ["serde"] }
nohash-hasher = "0.2"
#bytemuck = { version = "1.14", features = ["derive"] }
static_assertions = "1.1"
nz = "0.3"
[features]
default = []
nightly = ["hashbrown/nightly", "rand/nightly", "rand/simd_support", "glam/core-simd"]
[package]
name = "kubi-shared"
version = "0.0.0"
edition = "2021"
publish = false
[dependencies]
glam = { version = "0.24", features = ["debug-glam-assert", "fast-math", "serde"] }
shipyard = { git = "https://github.com/leudz/shipyard", rev = "8ef90ea6c4d1eb6c9cb0988f0d2f873f75044d49", 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"] }
serde_with = "3.4"
bincode = "1.3"
anyhow = "1.0"
bracket-noise = "0.8"
rand = { version = "0.8", default_features = false, features = ["std", "min_const_gen"] }
rand_xoshiro = "0.6"
hashbrown = { version = "0.14", features = ["serde"] }
nohash-hasher = "0.2"
#bytemuck = { version = "1.14", features = ["derive"] }
static_assertions = "1.1"
nz = "0.3"
[features]
default = []
nightly = ["hashbrown/nightly", "rand/nightly", "rand/simd_support", "glam/core-simd"]

View file

@ -10,7 +10,7 @@ publish = false
kubi-ui = { path = "../kubi-ui" }
kubi-ui-glium = { path = "../kubi-ui-glium" }
kubi-logging = { path = "../kubi-logging" }
glium = { git = "https://github.com/glium/glium", rev = "a352c667" }
glium = { git = "https://github.com/glium/glium", rev = "968fc92378caf" }
winit = "0.29"
glam = "0.25"
glam = "0.24"
log = "0.4"

View file

@ -7,6 +7,6 @@ publish = false
[dependencies]
kubi-ui = { path = "../kubi-ui", default-features = false }
#kubi-ui = { path = "../kubi-ui" }
glium = { git = "https://github.com/glium/glium", rev = "a352c667" }
glam = "0.25"
glium = { git = "https://github.com/glium/glium", rev = "968fc92378caf" }
glam = "0.24"
log = "0.4"

View file

@ -50,8 +50,8 @@ impl BufferPair {
pub fn new<F: Facade>(facade: &F) -> Self {
log::debug!("init ui buffers...");
Self {
vertex_buffer: VertexBuffer::empty_dynamic(facade, 1024).unwrap(),
index_buffer: IndexBuffer::empty_dynamic(facade, PrimitiveType::TrianglesList, 1024).unwrap(),
vertex_buffer: VertexBuffer::empty_persistent(facade, 1024).unwrap(),
index_buffer: IndexBuffer::empty_persistent(facade, PrimitiveType::TrianglesList, 1024).unwrap(),
vertex_count: 0,
index_count: 0,
}
@ -68,13 +68,13 @@ impl BufferPair {
let new_idx_size = (need_idx + 1).next_power_of_two();
log::debug!("resizing buffers: vtx {} -> {}, idx {} -> {}", current_vtx_size, new_vtx_size, current_idx_size, new_idx_size);
if current_vtx_size != new_vtx_size {
self.vertex_buffer = VertexBuffer::empty_dynamic(
self.vertex_buffer = VertexBuffer::empty_persistent(
self.vertex_buffer.get_context(),
new_vtx_size
).unwrap();
}
if current_idx_size != new_idx_size {
self.index_buffer = IndexBuffer::empty_dynamic(
self.index_buffer = IndexBuffer::empty_persistent(
self.index_buffer.get_context(),
PrimitiveType::TrianglesList,
new_idx_size

View file

@ -1,19 +1,19 @@
[package]
name = "kubi-ui"
version = "0.0.0"
edition = "2021"
publish = false
[dependencies]
hashbrown = "0.14"
nohash-hasher = "0.2"
glam = "0.25"
fontdue = "0.8"
rect_packer = "0.2"
log = "0.4"
[features]
default = ["builtin_elements", "builtin_font"]
builtin_font = []
builtin_elements = []
#parallel = ["dep:rayon", "fontdue/parallel"]
[package]
name = "kubi-ui"
version = "0.0.0"
edition = "2021"
publish = false
[dependencies]
hashbrown = "0.14"
nohash-hasher = "0.2"
glam = "0.24"
fontdue = "0.8"
rect_packer = "0.2"
log = "0.4"
[features]
default = ["builtin_elements", "builtin_font"]
builtin_font = []
builtin_elements = []
#parallel = ["dep:rayon", "fontdue/parallel"]

View file

@ -1,89 +1,83 @@
[package]
name = "kubi"
version = "0.0.0"
edition = "2021"
publish = false
[lib]
name = "kubilib"
crate-type = ["lib", "cdylib"]
[dependencies]
kubi-shared = { path = "../kubi-shared" }
kubi-logging = { path = "../kubi-logging" }
kubi-ui = { path = "../kubi-ui" }
kubi-ui-glium = { path = "../kubi-ui-glium" }
log = "0.4"
glium = { git = "https://github.com/glium/glium", rev = "a352c667" }
glutin = "0.31"
winit = { version = "0.29", features = ["android-native-activity"] }
glutin-winit = "0.4"
raw-window-handle = "=0.5.*"
glam = { version = "0.25", features = ["debug-glam-assert", "fast-math"] }
image = { version = "0.24", default_features = false, features = ["png"] }
strum = { version = "0.26", features = ["derive"] }
hashbrown = "0.14"
nohash-hasher = "0.2"
rayon = "1.7"
shipyard = { git = "https://github.com/leudz/shipyard", rev = "9099b990e", default-features = false, features = ["std", "proc", "thread_local"] }
anyhow = "1.0"
flume = "0.11"
gilrs = { version = "0.10", default_features = false, features = ["xinput"] }
uflow = "0.7"
postcard = { version = "1.0", features = ["alloc"] }
lz4_flex = { version = "0.11", default-features = false, features = ["std"] }
static_assertions = "1.1"
tinyset = "0.4"
serde_json = { version = "1.0", optional = true } #only used for `generate_visualizer_data`
[target.'cfg(target_os = "android")'.dependencies]
android-activity = "^0.5.2"
ndk = "0.8"
[target.'cfg(target_os = "windows")'.dependencies]
winapi = "0.3"
[features]
default = ["raw-evt"]
raw-evt = [] #required for mouse input, but breaks keyboard on android
generate_visualizer_data = ["dep:serde_json", "shipyard/serde1"]
safe_lz4 = ["lz4_flex/safe-encode", "lz4_flex/safe-decode"]
parallel = ["shipyard/parallel"] # causes some serious issues!
nightly = ["hashbrown/nightly", "glam/core-simd", "static_assertions/nightly", "lz4_flex/nightly", "kubi-shared/nightly"]
#part of wip android support
[package.metadata.android]
package = "com.ggh.kubi"
build_targets = ["aarch64-linux-android"]
assets = "../assets"
apk_name = "kubi"
theme = "@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen"
label = "Kubi"
[package.metadata.android.sdk]
min_sdk_version = 16
target_sdk_version = 30
[[package.metadata.android.uses_feature]]
glEsVersion = 0x00030000
required = true
[[package.metadata.android.uses_feature]]
name = "android.hardware.touchscreen.multitouch"
required = true
[[package.metadata.android.uses_feature]]
name = "android.hardware.touchscreen.multitouch.distinct"
required = true
[package.metadata.android.application.activity]
label = "Kubi"
launch_mode = "singleTop"
orientation = "sensorLandscape"
config_changes = "orientation|keyboardHidden|screenLayout|screenSize"
exported = true
resizeable_activity = true
# [package.metadata.android.signing.release]
# path = "$HOME/.android/debug.keystore"
# keystore_password = "android"
[package]
name = "kubi"
version = "0.0.0"
edition = "2021"
publish = false
[lib]
name = "kubilib"
crate-type = ["lib", "cdylib"]
[dependencies]
kubi-shared = { path = "../kubi-shared" }
kubi-logging = { path = "../kubi-logging" }
kubi-ui = { path = "../kubi-ui" }
kubi-ui-glium = { path = "../kubi-ui-glium" }
log = "0.4"
glium = { git = "https://github.com/glium/glium", rev = "968fc92378caf" }
glutin = "0.31"
winit = { version = "0.29", features = ["android-native-activity"] }
glutin-winit = "0.4"
raw-window-handle = "0.5"
glam = { version = "0.24", features = ["debug-glam-assert", "fast-math"] }
image = { version = "0.24", default_features = false, features = ["png"] }
strum = { version = "0.25", features = ["derive"] }
hashbrown = "0.14"
nohash-hasher = "0.2"
rayon = "1.7"
shipyard = { git = "https://github.com/leudz/shipyard", rev = "8ef90ea6c4d1eb6c9cb0988f0d2f873f75044d49", default-features = false, features = ["std", "proc", "thread_local"] }
anyhow = "1.0"
flume = "0.11"
gilrs = { version = "0.10", default_features = false, features = ["xinput"] }
uflow = "0.7"
postcard = { version = "1.0", features = ["alloc"] }
lz4_flex = { version = "0.11", default-features = false, features = ["std"] }
static_assertions = "1.1"
tinyset = "0.4"
serde_json = { version = "1.0", optional = true } #only used for `generate_visualizer_data`
[target.'cfg(target_os = "android")'.dependencies]
android-activity = "0.5"
ndk = "0.8"
[target.'cfg(target_os = "windows")'.dependencies]
winapi = "0.3"
[features]
default = ["raw-evt"]
raw-evt = [] #required for mouse input, but breaks keyboard on android
generate_visualizer_data = ["dep:serde_json", "shipyard/serde1"]
safe_lz4 = ["lz4_flex/safe-encode", "lz4_flex/safe-decode"]
parallel = ["shipyard/parallel"] # causes some serious issues!
nightly = ["hashbrown/nightly", "glam/core-simd", "static_assertions/nightly", "lz4_flex/nightly", "kubi-shared/nightly"]
#part of wip android support
[package.metadata.android]
package = "com.ggh.kubi"
build_targets = ["aarch64-linux-android"]
assets = "../assets"
apk_name = "kubi"
theme = "@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen"
label = "Kubi"
orientation = "sensorLandscape"
[package.metadata.android.sdk]
min_sdk_version = 16
target_sdk_version = 30
[[package.metadata.android.uses_feature]]
required = true
glEsVersion = 0x00030000
[[package.metadata.android.uses_feature]]
name = "android.hardware.touchscreen.multitouch"
required = true
[[package.metadata.android.uses_feature]]
name = "android.hardware.touchscreen.multitouch.distinct"
required = true
[package.metadata.android.application.activity]
config_changes = "orientation|keyboardHidden|screenLayout|screenSize"
exported = true
resizeable_activity = true

View file

@ -1,52 +0,0 @@
//TODO client-side physics
//TODO move this to shared
use glam::{Mat4, Vec3};
use kubi_shared::transform::Transform;
use shipyard::{track, AllStoragesView, Component, IntoIter, Unique, UniqueView, View, ViewMut};
use crate::delta_time::DeltaTime;
#[derive(Unique)]
pub struct GlobalClPhysicsConfig {
pub gravity: Vec3,
}
#[derive(Component)]
pub struct ClPhysicsActor {
pub forces: Vec3,
pub velocity: Vec3,
pub terminal_velocity: f32,
//TODO: this should be configurable per block
pub friction_agains_ground: f32,
}
impl Default for ClPhysicsActor {
fn default() -> Self {
Self {
forces: Vec3::ZERO,
velocity: Vec3::ZERO,
terminal_velocity: 40.,
friction_agains_ground: 0.5,
}
}
}
pub fn init_client_physics(
storages: AllStoragesView,
) {
storages.add_unique(GlobalClPhysicsConfig {
gravity: Vec3::new(0., -9.8, 0.),
});
}
pub fn update_client_physics_late(
controllers: View<ClPhysicsActor>,
mut transforms: ViewMut<Transform, track::All>,
dt: UniqueView<DeltaTime>,
phy_conf: UniqueView<GlobalClPhysicsConfig>,
) {
// for (_, mut transform) in (&controllers, &mut transforms).iter() {
// let (scale, rotation, mut translation) = transform.0.to_scale_rotation_translation();
// translation.y -= dt.0.as_secs_f32() * 100.;
// transform.0 = Mat4::from_scale_rotation_translation(scale, rotation, translation);
// }
}

View file

@ -1,36 +1,36 @@
use shipyard::{AllStoragesView, Unique, NonSendSync, UniqueView, UniqueViewMut};
use crate::rendering::Renderer;
use winit::window::CursorGrabMode;
#[derive(Unique)]
pub struct CursorLock(pub bool);
pub fn update_cursor_lock_state(
lock: UniqueView<CursorLock>,
display: NonSendSync<UniqueView<Renderer>>
) {
if cfg!(target_os = "android") {
return
}
if lock.is_inserted_or_modified() {
//TODO MIGRATION
let window = &display.window;
window.set_cursor_grab(match lock.0 {
true => CursorGrabMode::Confined,
false => CursorGrabMode::None,
}).expect("Failed to change cursor grab state");
window.set_cursor_visible(!lock.0);
}
}
pub fn insert_lock_state(
storages: AllStoragesView
) {
storages.add_unique(CursorLock(false))
}
pub fn lock_cursor_now(
mut lock: UniqueViewMut<CursorLock>
) {
lock.0 = true
}
use shipyard::{AllStoragesView, Unique, NonSendSync, UniqueView, UniqueViewMut};
use crate::rendering::Renderer;
use winit::window::CursorGrabMode;
#[derive(Unique)]
pub struct CursorLock(pub bool);
pub fn update_cursor_lock_state(
lock: UniqueView<CursorLock>,
display: NonSendSync<UniqueView<Renderer>>
) {
if cfg!(target_os = "android") {
return
}
if lock.is_inserted_or_modified() {
//TODO MIGRATION
let window = &display.window;
window.set_cursor_grab(match lock.0 {
true => CursorGrabMode::Confined,
false => CursorGrabMode::None,
}).expect("Failed to change cursor grab state");
window.set_cursor_visible(!lock.0);
}
}
pub fn insert_lock_state(
storages: AllStoragesView
) {
storages.add_unique(CursorLock(false))
}
pub fn lock_cursor_now(
mut lock: UniqueViewMut<CursorLock>
) {
lock.0 = true
}

View file

@ -1,106 +1,106 @@
use glam::UVec2;
use shipyard::{World, Component, AllStoragesViewMut, SparseSet, NonSendSync, UniqueView};
use winit::event::{Event, DeviceEvent, DeviceId, WindowEvent, Touch};
use crate::rendering::Renderer;
pub mod player_actions;
#[derive(Component, Clone, Copy, Debug, Default)]
pub struct EventComponent;
#[derive(Component, Clone, Copy, Debug, Default)]
pub struct OnBeforeExitEvent;
#[derive(Component, Clone, Debug)]
pub struct InputDeviceEvent{
pub device_id: DeviceId,
pub event: DeviceEvent
}
#[derive(Component, Clone, Copy, Debug)]
#[repr(transparent)]
pub struct TouchEvent(pub Touch);
#[derive(Component, Clone, Copy, Debug, Default)]
pub struct WindowResizedEvent(pub UVec2);
pub fn process_winit_events(world: &mut World, event: &Event<()>) {
#[allow(clippy::collapsible_match, clippy::single_match)]
match event {
Event::WindowEvent { window_id: _, event } => match event {
WindowEvent::Resized(size) => {
world.add_entity((
EventComponent,
WindowResizedEvent(UVec2::new(size.width as _, size.height as _))
));
},
#[cfg(not(feature = "raw-evt"))]
WindowEvent::KeyboardInput { device_id, event, .. } => {
world.add_entity((
EventComponent,
InputDeviceEvent {
device_id: *device_id,
event: DeviceEvent::Key(RawKeyEvent {
physical_key: event.physical_key,
state: event.state,
})
}
));
}
WindowEvent::Touch(touch) => {
// if matches!(touch.phase, TouchPhase::Started | TouchPhase::Cancelled | TouchPhase::Ended) {
// println!("TOUCH ==================== {:#?}", touch);
// } else {
// println!("TOUCH MOVED {:?} {}", touch.phase, touch.id);
// }
world.add_entity((
EventComponent,
TouchEvent(*touch)
));
}
_ => ()
},
#[cfg(feature = "raw-evt")]
Event::DeviceEvent { device_id, event } => {
world.add_entity((
EventComponent,
InputDeviceEvent {
device_id: *device_id,
event: event.clone()
}
));
},
Event::LoopExiting => {
world.add_entity((
EventComponent,
OnBeforeExitEvent
));
},
_ => (),
}
}
pub fn initial_resize_event(
mut storages: AllStoragesViewMut,
) {
let (w, h) = {
let renderer = storages.borrow::<NonSendSync<UniqueView<Renderer>>>().unwrap();
renderer.display.get_framebuffer_dimensions()
};
storages.add_entity((
EventComponent,
WindowResizedEvent(UVec2::new(w, h))
));
}
pub fn clear_events(
mut all_storages: AllStoragesViewMut,
) {
all_storages.delete_any::<SparseSet<EventComponent>>();
}
use glam::UVec2;
use shipyard::{World, Component, AllStoragesViewMut, SparseSet, NonSendSync, UniqueView};
use winit::event::{Event, DeviceEvent, DeviceId, WindowEvent, Touch, RawKeyEvent, TouchPhase};
use crate::rendering::Renderer;
pub mod player_actions;
#[derive(Component, Clone, Copy, Debug, Default)]
pub struct EventComponent;
#[derive(Component, Clone, Copy, Debug, Default)]
pub struct OnBeforeExitEvent;
#[derive(Component, Clone, Debug)]
pub struct InputDeviceEvent{
pub device_id: DeviceId,
pub event: DeviceEvent
}
#[derive(Component, Clone, Copy, Debug)]
#[repr(transparent)]
pub struct TouchEvent(pub Touch);
#[derive(Component, Clone, Copy, Debug, Default)]
pub struct WindowResizedEvent(pub UVec2);
pub fn process_glutin_events(world: &mut World, event: &Event<()>) {
#[allow(clippy::collapsible_match, clippy::single_match)]
match event {
Event::WindowEvent { window_id: _, event } => match event {
WindowEvent::Resized(size) => {
world.add_entity((
EventComponent,
WindowResizedEvent(UVec2::new(size.width as _, size.height as _))
));
},
#[cfg(not(feature = "raw-evt"))]
WindowEvent::KeyboardInput { device_id, event, .. } => {
world.add_entity((
EventComponent,
InputDeviceEvent {
device_id: *device_id,
event: DeviceEvent::Key(RawKeyEvent {
physical_key: event.physical_key,
state: event.state,
})
}
));
}
WindowEvent::Touch(touch) => {
// if matches!(touch.phase, TouchPhase::Started | TouchPhase::Cancelled | TouchPhase::Ended) {
// println!("TOUCH ==================== {:#?}", touch);
// } else {
// println!("TOUCH MOVED {:?} {}", touch.phase, touch.id);
// }
world.add_entity((
EventComponent,
TouchEvent(*touch)
));
}
_ => ()
},
#[cfg(feature = "raw-evt")]
Event::DeviceEvent { device_id, event } => {
world.add_entity((
EventComponent,
InputDeviceEvent {
device_id: *device_id,
event: event.clone()
}
));
},
Event::LoopExiting => {
world.add_entity((
EventComponent,
OnBeforeExitEvent
));
},
_ => (),
}
}
pub fn initial_resize_event(
mut storages: AllStoragesViewMut,
) {
let (w, h) = {
let renderer = storages.borrow::<NonSendSync<UniqueView<Renderer>>>().unwrap();
renderer.display.get_framebuffer_dimensions()
};
storages.add_entity((
EventComponent,
WindowResizedEvent(UVec2::new(w, h))
));
}
pub fn clear_events(
mut all_storages: AllStoragesViewMut,
) {
all_storages.delete_any::<SparseSet<EventComponent>>();
}

View file

@ -1,53 +1,52 @@
use glam::{Vec3, Mat4, Quat, EulerRot, Vec2};
use shipyard::{Component, View, ViewMut, IntoIter, UniqueView, Workload, IntoWorkload, track};
use std::f32::consts::PI;
use crate::{transform::Transform, input::Inputs, settings::GameSettings, delta_time::DeltaTime};
#[derive(Component)]
pub struct FlyController;
pub fn update_controllers() -> Workload {
(
update_look,
update_movement
).into_sequential_workload()
}
const MAX_PITCH: f32 = PI/2. - 0.05;
fn update_look(
controllers: View<FlyController>,
mut transforms: ViewMut<Transform, track::All>,
inputs: UniqueView<Inputs>,
settings: UniqueView<GameSettings>,
dt: UniqueView<DeltaTime>,
) {
let look = inputs.look * settings.mouse_sensitivity * dt.0.as_secs_f32();
if look == Vec2::ZERO { return }
for (_, mut transform) in (&controllers, &mut transforms).iter() {
let (scale, mut rotation, translation) = transform.0.to_scale_rotation_translation();
let (mut yaw, mut pitch, _roll) = rotation.to_euler(EulerRot::YXZ);
yaw -= look.x;
pitch -= look.y;
pitch = pitch.clamp(-MAX_PITCH, MAX_PITCH);
rotation = Quat::from_euler(EulerRot::YXZ, yaw, pitch, 0.).normalize();
transform.0 = Mat4::from_scale_rotation_translation(scale, rotation, translation);
}
}
fn update_movement(
controllers: View<FlyController>,
mut transforms: ViewMut<Transform, track::All>,
inputs: UniqueView<Inputs>,
dt: UniqueView<DeltaTime>,
) {
if inputs.movement == Vec2::ZERO { return }
let movement = inputs.movement * 30. * dt.0.as_secs_f32();
for (_, mut transform) in (&controllers, &mut transforms).iter() {
let (scale, rotation, mut translation) = transform.0.to_scale_rotation_translation();
let rotation_norm = rotation.normalize();
translation += (rotation_norm * Vec3::NEG_Z).normalize() * movement.y;
translation += (rotation_norm * Vec3::X).normalize() * movement.x;
transform.0 = Mat4::from_scale_rotation_translation(scale, rotation_norm, translation);
}
}
use glam::{Vec3, Mat4, Quat, EulerRot, Vec2};
use shipyard::{Component, View, ViewMut, IntoIter, UniqueView, Workload, IntoWorkload, track};
use std::f32::consts::PI;
use crate::{transform::Transform, input::Inputs, settings::GameSettings, delta_time::DeltaTime};
#[derive(Component)]
pub struct FlyController;
pub fn update_controllers() -> Workload {
(
update_look,
update_movement
).into_sequential_workload()
}
const MAX_PITCH: f32 = PI/2. - 0.05;
fn update_look(
controllers: View<FlyController>,
mut transforms: ViewMut<Transform, track::All>,
inputs: UniqueView<Inputs>,
settings: UniqueView<GameSettings>,
dt: UniqueView<DeltaTime>,
) {
let look = inputs.look * settings.mouse_sensitivity * dt.0.as_secs_f32();
if look == Vec2::ZERO { return }
for (_, mut transform) in (&controllers, &mut transforms).iter() {
let (scale, mut rotation, translation) = transform.0.to_scale_rotation_translation();
let (mut yaw, mut pitch, _roll) = rotation.to_euler(EulerRot::YXZ);
yaw -= look.x;
pitch -= look.y;
pitch = pitch.clamp(-MAX_PITCH, MAX_PITCH);
rotation = Quat::from_euler(EulerRot::YXZ, yaw, pitch, 0.).normalize();
transform.0 = Mat4::from_scale_rotation_translation(scale, rotation, translation);
}
}
fn update_movement(
controllers: View<FlyController>,
mut transforms: ViewMut<Transform, track::All>,
inputs: UniqueView<Inputs>,
dt: UniqueView<DeltaTime>,
) {
if inputs.movement == Vec2::ZERO { return }
let movement = inputs.movement * 30. * dt.0.as_secs_f32();
for (_, mut transform) in (&controllers, &mut transforms).iter() {
let (scale, rotation, mut translation) = transform.0.to_scale_rotation_translation();
translation += (rotation * Vec3::NEG_Z).normalize() * movement.y;
translation += (rotation * Vec3::X).normalize() * movement.x;
transform.0 = Mat4::from_scale_rotation_translation(scale, rotation, translation);
}
}

View file

@ -1,318 +1,310 @@
#![allow(clippy::too_many_arguments)] // allowed because systems often need a lot of arguments
use shipyard::{
World, Workload, IntoWorkload,
UniqueView, UniqueViewMut,
NonSendSync, WorkloadModificator,
SystemModificator
};
use winit::{
event_loop::{EventLoop, ControlFlow},
event::{Event, WindowEvent}
};
use glam::vec3;
use std::time::Instant;
pub use kubi_shared::transform;
pub(crate) mod rendering;
pub(crate) mod world;
pub(crate) mod player;
pub(crate) mod prefabs;
pub(crate) mod settings;
pub(crate) mod camera;
pub(crate) mod events;
pub(crate) mod input;
pub(crate) mod fly_controller;
pub(crate) mod block_placement;
pub(crate) mod delta_time;
pub(crate) mod cursor_lock;
pub(crate) mod control_flow;
pub(crate) mod state;
pub(crate) mod kubi_ui_integration;
pub(crate) mod networking;
pub(crate) mod init;
pub(crate) mod color;
pub(crate) mod loading_screen;
pub(crate) mod connecting_screen;
pub(crate) mod fixed_timestamp;
pub(crate) mod filesystem;
pub(crate) mod client_physics;
use world::{
init_game_world,
loading::update_loaded_world_around_player,
raycast::update_raycasts,
queue::apply_queued_blocks,
tasks::ChunkTaskManager,
};
use player::{spawn_player, MainPlayer};
use prefabs::load_prefabs;
use settings::{load_settings, GameSettings};
use camera::compute_cameras;
use events::{
clear_events,
process_winit_events,
initial_resize_event,
player_actions::generate_move_events,
};
use input::{init_input, process_inputs};
use fly_controller::update_controllers;
use rendering::{
Renderer,
RenderTarget,
BackgroundColor,
clear_background,
init_window_size,
update_window_size,
primitives::init_primitives,
world::{draw_world, draw_current_chunk_border},
selection_box::render_selection_box,
entities::render_entities,
};
use block_placement::update_block_placement;
use delta_time::{DeltaTime, init_delta_time};
use cursor_lock::{insert_lock_state, update_cursor_lock_state, lock_cursor_now};
use control_flow::{exit_on_esc, insert_control_flow_unique, RequestExit};
use state::{is_ingame, is_ingame_or_loading, is_loading, init_state, update_state, is_connecting};
use networking::{update_networking, update_networking_late, is_multiplayer, disconnect_on_exit, is_singleplayer};
use init::initialize_from_args;
use kubi_ui_integration::{kubi_ui_init, kubi_ui_begin, kubi_ui_end, kubi_ui_draw};
use loading_screen::update_loading_screen;
use connecting_screen::switch_to_loading_if_connected;
use fixed_timestamp::init_fixed_timestamp_storage;
use filesystem::AssetManager;
use client_physics::{init_client_physics, update_client_physics_late};
/// stuff required to init the renderer and other basic systems
fn pre_startup() -> Workload {
(
load_settings,
).into_sequential_workload()
}
fn startup() -> Workload {
(
init_fixed_timestamp_storage,
initial_resize_event,
init_window_size,
kubi_ui_init,
load_prefabs,
init_primitives,
insert_lock_state,
init_state,
initialize_from_args,
lock_cursor_now,
init_input,
insert_control_flow_unique,
init_delta_time,
init_client_physics,
).into_sequential_workload()
}
fn update() -> Workload {
(
update_window_size,
update_cursor_lock_state,
process_inputs,
kubi_ui_begin,
(
init_game_world.run_if_missing_unique::<ChunkTaskManager>(),
(
spawn_player.run_if_storage_empty::<MainPlayer>(),
).into_sequential_workload().run_if(is_singleplayer),
).into_sequential_workload().run_if(is_ingame_or_loading),
update_networking().run_if(is_multiplayer),
(
switch_to_loading_if_connected
).into_sequential_workload().run_if(is_connecting),
(
update_loading_screen,
).into_sequential_workload().run_if(is_loading),
(
update_loaded_world_around_player,
).into_sequential_workload().run_if(is_ingame_or_loading),
(
update_controllers,
update_client_physics_late,
generate_move_events,
update_raycasts,
update_block_placement,
apply_queued_blocks,
).into_sequential_workload().run_if(is_ingame),
update_networking_late.run_if(is_multiplayer),
compute_cameras,
kubi_ui_end,
update_state,
exit_on_esc,
disconnect_on_exit.run_if(is_multiplayer),
).into_sequential_workload()
}
fn render() -> Workload {
(
clear_background,
(
draw_world,
draw_current_chunk_border,
render_selection_box,
render_entities,
).into_sequential_workload().run_if(is_ingame),
kubi_ui_draw,
).into_sequential_workload()
}
fn after_frame_end() -> Workload {
(
clear_events,
).into_sequential_workload()
}
#[cfg(all(windows, not(debug_assertions)))]
fn attach_console() {
use winapi::um::wincon::{AttachConsole, ATTACH_PARENT_PROCESS};
unsafe { AttachConsole(ATTACH_PARENT_PROCESS); }
}
#[no_mangle]
#[cfg(target_os = "android")]
pub fn android_main(app: android_activity::AndroidApp) {
use android_activity::WindowManagerFlags;
app.set_window_flags(WindowManagerFlags::FULLSCREEN, WindowManagerFlags::empty());
kubi_main(app)
}
#[no_mangle]
pub fn kubi_main(
#[cfg(target_os = "android")]
app: android_activity::AndroidApp
) {
//Attach console on release builds on windows
#[cfg(all(windows, not(debug_assertions)))]
attach_console();
//Print version
println!("{:─^54}", format!("[ ▄▀ Kubi client v. {} ]", env!("CARGO_PKG_VERSION")));
//Init env_logger
kubi_logging::init();
//Create a shipyard world
let mut world = World::new();
//Init assman
world.add_unique(AssetManager {
#[cfg(target_os = "android")]
app: app.clone()
});
//Register workloads
world.add_workload(pre_startup);
world.add_workload(startup);
world.add_workload(update);
world.add_workload(render);
world.add_workload(after_frame_end);
//Save _visualizer.json
#[cfg(feature = "generate_visualizer_data")]
std::fs::write(
"_visualizer.json",
serde_json::to_string(&world.workloads_info()).unwrap(),
).unwrap();
//Run pre-startup procedure
world.run_workload(pre_startup).unwrap();
//Create event loop
let event_loop ={
#[cfg(not(target_os = "android"))] { EventLoop::new().unwrap() }
#[cfg(target_os = "android")] {
use winit::{
platform::android::EventLoopBuilderExtAndroid,
event_loop::EventLoopBuilder
};
EventLoopBuilder::new().with_android_app(app).build().unwrap()
}
};
//Run the event loop
let mut last_update = Instant::now();
let mut ready = false;
event_loop.run(move |event, window_target| {
//Wait for the window to become active (required for android)
if !ready {
if Event::Resumed != event {
window_target.set_control_flow(ControlFlow::Wait);
return
}
//Initialize renderer
{
let settings = world.borrow::<UniqueView<GameSettings>>().unwrap();
world.add_unique_non_send_sync(Renderer::init(window_target, &settings));
}
world.add_unique(BackgroundColor(vec3(0.5, 0.5, 1.)));
//Run startup systems
world.run_workload(startup).unwrap();
ready = true;
}
window_target.set_control_flow(ControlFlow::Poll);
process_winit_events(&mut world, &event);
#[allow(clippy::collapsible_match, clippy::single_match)]
match event {
#[cfg(target_os = "android")]
Event::Suspended => {
window_target.exit();
}
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => {
log::info!("exit requested");
window_target.exit();
},
_ => (),
},
Event::AboutToWait => {
//Update delta time (maybe move this into a system?)
{
let mut dt_view = world.borrow::<UniqueViewMut<DeltaTime>>().unwrap();
let now = Instant::now();
dt_view.0 = now - last_update;
last_update = now;
}
//Run update workflows
world.run_workload(update).unwrap();
//Start rendering (maybe use custom views for this?)
let target = {
let renderer = world.borrow::<NonSendSync<UniqueView<Renderer>>>().unwrap();
renderer.display.draw()
};
world.add_unique_non_send_sync(RenderTarget(target));
//Run render workflow
world.run_workload(render).unwrap();
//Finish rendering
let target = world.remove_unique::<RenderTarget>().unwrap();
target.0.finish().unwrap();
//After frame end
world.run_workload(after_frame_end).unwrap();
//Process control flow changes
if world.borrow::<UniqueView<RequestExit>>().unwrap().0 {
window_target.exit();
}
},
_ => (),
};
}).unwrap();
}
#![allow(clippy::too_many_arguments)] // allowed because systems often need a lot of arguments
use shipyard::{
World, Workload, IntoWorkload,
UniqueView, UniqueViewMut,
NonSendSync, WorkloadModificator,
SystemModificator
};
use winit::{
event_loop::{EventLoop, ControlFlow},
event::{Event, WindowEvent}
};
use glam::vec3;
use std::time::Instant;
pub use kubi_shared::transform;
pub(crate) mod rendering;
pub(crate) mod world;
pub(crate) mod player;
pub(crate) mod prefabs;
pub(crate) mod settings;
pub(crate) mod camera;
pub(crate) mod events;
pub(crate) mod input;
pub(crate) mod fly_controller;
pub(crate) mod block_placement;
pub(crate) mod delta_time;
pub(crate) mod cursor_lock;
pub(crate) mod control_flow;
pub(crate) mod state;
pub(crate) mod kubi_ui_integration;
pub(crate) mod networking;
pub(crate) mod init;
pub(crate) mod color;
pub(crate) mod loading_screen;
pub(crate) mod connecting_screen;
pub(crate) mod fixed_timestamp;
pub(crate) mod filesystem;
use world::{
init_game_world,
loading::update_loaded_world_around_player,
raycast::update_raycasts,
queue::apply_queued_blocks,
tasks::ChunkTaskManager,
};
use player::{spawn_player, MainPlayer};
use prefabs::load_prefabs;
use settings::{load_settings, GameSettings};
use camera::compute_cameras;
use events::{
clear_events,
process_glutin_events,
initial_resize_event,
player_actions::generate_move_events,
};
use input::{init_input, process_inputs};
use fly_controller::update_controllers;
use rendering::{
Renderer,
RenderTarget,
BackgroundColor,
clear_background,
init_window_size,
update_window_size,
primitives::init_primitives,
world::{draw_world, draw_current_chunk_border},
selection_box::render_selection_box,
entities::render_entities,
};
use block_placement::update_block_placement;
use delta_time::{DeltaTime, init_delta_time};
use cursor_lock::{insert_lock_state, update_cursor_lock_state, lock_cursor_now};
use control_flow::{exit_on_esc, insert_control_flow_unique, RequestExit};
use state::{is_ingame, is_ingame_or_loading, is_loading, init_state, update_state, is_connecting};
use networking::{update_networking, update_networking_late, is_multiplayer, disconnect_on_exit, is_singleplayer};
use init::initialize_from_args;
use kubi_ui_integration::{kubi_ui_init, kubi_ui_begin, kubi_ui_end, kubi_ui_draw};
use loading_screen::update_loading_screen;
use connecting_screen::switch_to_loading_if_connected;
use fixed_timestamp::init_fixed_timestamp_storage;
use filesystem::AssetManager;
/// stuff required to init the renderer and other basic systems
fn pre_startup() -> Workload {
(
load_settings,
).into_sequential_workload()
}
fn startup() -> Workload {
(
init_fixed_timestamp_storage,
initial_resize_event,
init_window_size,
kubi_ui_init,
load_prefabs,
init_primitives,
insert_lock_state,
init_state,
initialize_from_args,
lock_cursor_now,
init_input,
insert_control_flow_unique,
init_delta_time,
).into_sequential_workload()
}
fn update() -> Workload {
(
update_window_size,
update_cursor_lock_state,
process_inputs,
kubi_ui_begin,
(
init_game_world.run_if_missing_unique::<ChunkTaskManager>(),
(
spawn_player.run_if_storage_empty::<MainPlayer>(),
).into_sequential_workload().run_if(is_singleplayer),
).into_sequential_workload().run_if(is_ingame_or_loading),
update_networking().run_if(is_multiplayer),
(
switch_to_loading_if_connected
).into_sequential_workload().run_if(is_connecting),
(
update_loading_screen,
).into_sequential_workload().run_if(is_loading),
(
update_loaded_world_around_player,
).into_sequential_workload().run_if(is_ingame_or_loading),
(
update_controllers,
generate_move_events,
update_raycasts,
update_block_placement,
apply_queued_blocks,
).into_sequential_workload().run_if(is_ingame),
update_networking_late.run_if(is_multiplayer),
compute_cameras,
kubi_ui_end,
update_state,
exit_on_esc,
disconnect_on_exit.run_if(is_multiplayer),
).into_sequential_workload()
}
fn render() -> Workload {
(
clear_background,
(
draw_world,
draw_current_chunk_border,
render_selection_box,
render_entities,
).into_sequential_workload().run_if(is_ingame),
kubi_ui_draw,
).into_sequential_workload()
}
fn after_frame_end() -> Workload {
(
clear_events,
).into_sequential_workload()
}
#[cfg(all(windows, not(debug_assertions)))]
fn attach_console() {
use winapi::um::wincon::{AttachConsole, ATTACH_PARENT_PROCESS};
unsafe { AttachConsole(ATTACH_PARENT_PROCESS); }
}
#[no_mangle]
#[cfg(target_os = "android")]
pub fn android_main(app: android_activity::AndroidApp) {
use android_activity::WindowManagerFlags;
app.set_window_flags(WindowManagerFlags::FULLSCREEN, WindowManagerFlags::empty());
kubi_main(app)
}
#[no_mangle]
pub fn kubi_main(#[cfg(target_os = "android")] app: android_activity::AndroidApp) {
//Attach console on release builds on windows
#[cfg(all(windows, not(debug_assertions)))] attach_console();
//Print version
println!("{:─^54}", format!("[ ▄▀ Kubi client v. {} ]", env!("CARGO_PKG_VERSION")));
//Init env_logger
kubi_logging::init();
//Create a shipyard world
let mut world = World::new();
//Init assman
world.add_unique(AssetManager {
#[cfg(target_os = "android")]
app: app.clone()
});
//Register workloads
world.add_workload(pre_startup);
world.add_workload(startup);
world.add_workload(update);
world.add_workload(render);
world.add_workload(after_frame_end);
//Save _visualizer.json
#[cfg(feature = "generate_visualizer_data")]
std::fs::write(
"_visualizer.json",
serde_json::to_string(&world.workloads_info()).unwrap(),
).unwrap();
//Run pre-startup procedure
world.run_workload(pre_startup).unwrap();
//Create event loop
let event_loop ={
#[cfg(not(target_os = "android"))] { EventLoop::new().unwrap() }
#[cfg(target_os = "android")] {
use winit::{
platform::android::EventLoopBuilderExtAndroid,
event_loop::EventLoopBuilder
};
EventLoopBuilder::new().with_android_app(app).build().unwrap()
}
};
//Run the event loop
let mut last_update = Instant::now();
let mut ready = false;
event_loop.run(move |event, window_target| {
//Wait for the window to become active (required for android)
if !ready {
if Event::Resumed != event {
window_target.set_control_flow(ControlFlow::Wait);
return
}
//Initialize renderer
{
let settings = world.borrow::<UniqueView<GameSettings>>().unwrap();
world.add_unique_non_send_sync(Renderer::init(window_target, &settings));
}
world.add_unique(BackgroundColor(vec3(0.5, 0.5, 1.)));
//Run startup systems
world.run_workload(startup).unwrap();
ready = true;
}
window_target.set_control_flow(ControlFlow::Poll);
process_glutin_events(&mut world, &event);
#[allow(clippy::collapsible_match, clippy::single_match)]
match event {
#[cfg(target_os = "android")]
Event::Suspended => {
window_target.exit();
}
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => {
log::info!("exit requested");
window_target.exit();
},
_ => (),
},
Event::AboutToWait => {
//Update delta time (maybe move this into a system?)
{
let mut dt_view = world.borrow::<UniqueViewMut<DeltaTime>>().unwrap();
let now = Instant::now();
dt_view.0 = now - last_update;
last_update = now;
}
//Run update workflows
world.run_workload(update).unwrap();
//Start rendering (maybe use custom views for this?)
let target = {
let renderer = world.borrow::<NonSendSync<UniqueView<Renderer>>>().unwrap();
renderer.display.draw()
};
world.add_unique_non_send_sync(RenderTarget(target));
//Run render workflow
world.run_workload(render).unwrap();
//Finish rendering
let target = world.remove_unique::<RenderTarget>().unwrap();
target.0.finish().unwrap();
//After frame end
world.run_workload(after_frame_end).unwrap();
//Process control flow changes
if world.borrow::<UniqueView<RequestExit>>().unwrap().0 {
window_target.exit();
}
},
_ => (),
};
}).unwrap();
}

View file

@ -1,89 +1,87 @@
use glam::Mat4;
use shipyard::{Component, AllStoragesViewMut, UniqueViewMut};
use kubi_shared::{
entity::{Entity, Health},
player::{Player, PLAYER_HEALTH, PlayerHolding},
block::Block,
networking::{
client::{Username, Client, ClientIdMap},
messages::ClientInitData
}
};
use crate::{
camera::Camera,
client_physics::ClPhysicsActor,
fly_controller::FlyController,
transform::Transform,
world::raycast::LookingAtBlock
};
#[derive(Component)]
pub struct MainPlayer;
pub fn spawn_player (
mut storages: AllStoragesViewMut,
) {
log::info!("spawning player");
storages.add_entity(((
Player,
MainPlayer,
Entity,
Health::new(PLAYER_HEALTH),
Transform::default(),
Camera::default(),
FlyController,
LookingAtBlock::default(),
PlayerHolding(Some(Block::Cobblestone)),
Username("LocalPlayer".into()),
),(
ClPhysicsActor::default(),
)));
}
pub fn spawn_local_player_multiplayer (
storages: &mut AllStoragesViewMut,
init: ClientInitData
) {
log::info!("spawning local multiplayer player");
let entity_id = storages.add_entity(((
Player,
Client(init.client_id),
MainPlayer,
Entity,
init.health,
Transform(Mat4::from_rotation_translation(init.direction, init.position)),
Camera::default(),
FlyController,
LookingAtBlock::default(),
PlayerHolding::default(),
),(
Username(init.username),
ClPhysicsActor::default(),
)));
//Add ourself to the client id map
let mut client_id_map = storages.borrow::<UniqueViewMut<ClientIdMap>>().unwrap();
client_id_map.0.insert(init.client_id, entity_id);
}
pub fn spawn_remote_player_multiplayer(
storages: &mut AllStoragesViewMut,
init: ClientInitData
) {
log::info!("spawning remote multiplayer player");
//Spawn player locally
let entity_id = storages.add_entity((
Username(init.username),
Client(init.client_id),
Player,
Entity,
init.health,
Transform(Mat4::from_rotation_translation(init.direction, init.position)),
PlayerHolding::default(),
));
//Add it to the client id map
let mut client_id_map = storages.borrow::<UniqueViewMut<ClientIdMap>>().unwrap();
client_id_map.0.insert(init.client_id, entity_id);
}
use glam::Mat4;
use shipyard::{Component, AllStoragesViewMut, UniqueViewMut};
use kubi_shared::{
entity::{Entity, Health},
player::{Player, PLAYER_HEALTH, PlayerHolding},
block::Block,
networking::{
client::{Username, Client, ClientIdMap},
messages::ClientInitData
}
};
use crate::{
transform::Transform,
camera::Camera,
fly_controller::FlyController,
world::raycast::LookingAtBlock,
};
#[derive(Component)]
pub struct MainPlayer;
pub fn spawn_player (
mut storages: AllStoragesViewMut,
) {
log::info!("spawning player");
storages.add_entity((
Player,
MainPlayer,
Entity,
Health::new(PLAYER_HEALTH),
Transform::default(),
Camera::default(),
FlyController,
LookingAtBlock::default(),
PlayerHolding(Some(Block::Cobblestone)),
Username("LocalPlayer".into())
));
}
pub fn spawn_local_player_multiplayer (
storages: &mut AllStoragesViewMut,
init: ClientInitData
) {
log::info!("spawning local multiplayer player");
let entity_id = storages.add_entity((
(
Player,
Client(init.client_id),
MainPlayer,
Entity,
init.health,
Transform(Mat4::from_rotation_translation(init.direction, init.position)),
Camera::default(),
FlyController,
LookingAtBlock::default(),
PlayerHolding::default(),
),(
Username(init.username)
)
));
//Add ourself to the client id map
let mut client_id_map = storages.borrow::<UniqueViewMut<ClientIdMap>>().unwrap();
client_id_map.0.insert(init.client_id, entity_id);
}
pub fn spawn_remote_player_multiplayer(
storages: &mut AllStoragesViewMut,
init: ClientInitData
) {
log::info!("spawning remote multiplayer player");
//Spawn player locally
let entity_id = storages.add_entity((
Username(init.username),
Client(init.client_id),
Player,
Entity,
init.health,
Transform(Mat4::from_rotation_translation(init.direction, init.position)),
PlayerHolding::default(),
));
//Add it to the client id map
let mut client_id_map = storages.borrow::<UniqueViewMut<ClientIdMap>>().unwrap();
client_id_map.0.insert(init.client_id, entity_id);
}