From df3791af172f209c67aa14d618090b79b539424d Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Sun, 21 May 2023 03:14:04 +0200 Subject: [PATCH] initial android support (fails on textures) --- Cargo.lock | 20 +++ kubi-logging/Cargo.toml | 5 + kubi-logging/src/lib.rs | 26 ++-- kubi/Cargo.toml | 6 + kubi/src/lib.rs | 268 ++++++++++++++++++++++++++++++++++++++++ kubi/src/main.rs | 264 +-------------------------------------- 6 files changed, 318 insertions(+), 271 deletions(-) create mode 100644 kubi/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 117b02f..6e7f493 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -48,6 +48,24 @@ dependencies = [ "memchr", ] +[[package]] +name = "android_log-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27f0fc03f560e1aebde41c2398b691cb98b5ea5996a6184a7a67bbbb77448969" + +[[package]] +name = "android_logger" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fa490e751f3878eb9accb9f18988eca52c2337ce000a8bf31ef50d4c723ca9e" +dependencies = [ + "android_log-sys", + "env_logger", + "log", + "once_cell", +] + [[package]] name = "anyhow" version = "1.0.71" @@ -949,6 +967,7 @@ dependencies = [ "kubi-shared", "log", "lz4_flex", + "ndk-glue", "nohash-hasher", "postcard", "rayon", @@ -964,6 +983,7 @@ dependencies = [ name = "kubi-logging" version = "0.1.0" dependencies = [ + "android_logger", "env_logger", "log", ] diff --git a/kubi-logging/Cargo.toml b/kubi-logging/Cargo.toml index c88c172..582dad6 100644 --- a/kubi-logging/Cargo.toml +++ b/kubi-logging/Cargo.toml @@ -5,4 +5,9 @@ edition = "2021" [dependencies] log = "0.4" + +[target.'cfg(not(target_os = "android"))'.dependencies] env_logger = "0.10" + +[target.'cfg(target_os = "android")'.dependencies] +android_logger = "0.13" diff --git a/kubi-logging/src/lib.rs b/kubi-logging/src/lib.rs index 7a4c922..bbc39c4 100644 --- a/kubi-logging/src/lib.rs +++ b/kubi-logging/src/lib.rs @@ -1,14 +1,13 @@ +//! Custom env_logger options and styling + /// Custom env_logger options and styling - -use env_logger::{fmt::Color, Builder, Env}; -use log::Level; -use std::io::Write; - -pub use log; -pub use env_logger; - #[inline] +#[cfg(not(target_os = "android"))] pub fn init() { + use log::Level; + use std::io::Write; + use env_logger::{fmt::Color, Builder, Env}; + let env = Env::default() .filter_or("RUST_LOG", "trace,gilrs=warn,rusty_xinput=warn"); Builder::from_env(env) @@ -51,3 +50,14 @@ pub fn init() { }) .init(); } + +/// Custom env_logger options and styling +#[inline] +#[cfg(target_os = "android")] +pub fn init() { + use log::LevelFilter; + use android_logger::Config; + android_logger::init_once( + Config::default().with_max_level(LevelFilter::Trace), + ); +} diff --git a/kubi/Cargo.toml b/kubi/Cargo.toml index 000ea28..5c148f9 100644 --- a/kubi/Cargo.toml +++ b/kubi/Cargo.toml @@ -4,6 +4,9 @@ version = "0.0.0" edition = "2021" publish = false +[lib] +crate-type = ["lib", "cdylib"] + [dependencies] kubi-shared = { path = "../kubi-shared" } kubi-logging = { path = "../kubi-logging" } @@ -25,6 +28,9 @@ serde_json = { version = "1.0", optional = true } lz4_flex = { version = "0.10", default-features = false, features = ["std", "checked-decode"] } static_assertions = "1.1" +[target.'cfg(target_os = "android")'.dependencies] +ndk-glue = "0.7" + [target.'cfg(target_os = "windows")'.dependencies] winapi = { version = "0.3" } diff --git a/kubi/src/lib.rs b/kubi/src/lib.rs new file mode 100644 index 0000000..037f1df --- /dev/null +++ b/kubi/src/lib.rs @@ -0,0 +1,268 @@ +#![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 glium::{ + glutin::{ + 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 gui; +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; + +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, SetControlFlow}; +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 gui::{render_gui, init_gui, update_gui}; +use loading_screen::update_loading_screen; +use connecting_screen::switch_to_loading_if_connected; +use fixed_timestamp::init_fixed_timestamp_storage; + +/// 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, + load_prefabs, + init_primitives, + insert_lock_state, + init_state, + initialize_from_args, + lock_cursor_now, + init_input, + init_gui, + insert_control_flow_unique, + init_delta_time, + ).into_sequential_workload() +} + +fn update() -> Workload { + ( + update_window_size, + update_cursor_lock_state, + process_inputs, + ( + init_game_world.run_if_missing_unique::(), + ( + spawn_player.run_if_storage_empty::(), + ).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, + update_gui, + 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), + render_gui, + ).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_attr(target_os = "android", ndk_glue::main(backtrace = "on"))] +pub fn kubi_main() { + //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(); + + //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); + + //Run pre-startup procedure + world.run_workload(pre_startup).unwrap(); + + //Create event loop + let event_loop = EventLoop::new(); + + //Initialize renderer + { + let settings = world.borrow::>().unwrap(); + world.add_unique_non_send_sync(Renderer::init(&event_loop, &settings)); + } + world.add_unique(BackgroundColor(vec3(0.5, 0.5, 1.))); + + //Save _visualizer.json + #[cfg(feature = "generate_visualizer_data")] + std::fs::write( + "_visualizer.json", + serde_json::to_string(&world.workloads_info()).unwrap(), + ).unwrap(); + + //Run startup systems + world.run_workload(startup).unwrap(); + + //Run the event loop + let mut last_update = Instant::now(); + event_loop.run(move |event, _, control_flow| { + *control_flow = ControlFlow::Poll; + process_glutin_events(&mut world, &event); + #[allow(clippy::collapsible_match, clippy::single_match)] + match event { + Event::WindowEvent { event, .. } => match event { + WindowEvent::CloseRequested => { + log::info!("exit requested"); + *control_flow = ControlFlow::Exit; + }, + _ => (), + }, + Event::MainEventsCleared => { + //Update delta time (maybe move this into a system?) + { + let mut dt_view = world.borrow::>().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::>>().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::().unwrap(); + target.0.finish().unwrap(); + + //After frame end + world.run_workload(after_frame_end).unwrap(); + + //Process control flow changes + if let Some(flow) = world.borrow::>().unwrap().0 { + *control_flow = flow; + } + }, + _ => (), + }; + }); +} diff --git a/kubi/src/main.rs b/kubi/src/main.rs index 6de4157..f4a01c7 100644 --- a/kubi/src/main.rs +++ b/kubi/src/main.rs @@ -2,269 +2,7 @@ all(windows, not(debug_assertions)), windows_subsystem = "windows" )] -#![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 glium::{ - glutin::{ - 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 gui; -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; - -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, SetControlFlow}; -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 gui::{render_gui, init_gui, update_gui}; -use loading_screen::update_loading_screen; -use connecting_screen::switch_to_loading_if_connected; -use fixed_timestamp::init_fixed_timestamp_storage; - -/// 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, - load_prefabs, - init_primitives, - insert_lock_state, - init_state, - initialize_from_args, - lock_cursor_now, - init_input, - init_gui, - insert_control_flow_unique, - init_delta_time, - ).into_sequential_workload() -} - -fn update() -> Workload { - ( - update_window_size, - update_cursor_lock_state, - process_inputs, - ( - init_game_world.run_if_missing_unique::(), - ( - spawn_player.run_if_storage_empty::(), - ).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, - update_gui, - 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), - render_gui, - ).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); } -} fn main() { - //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(); - - //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); - - //Run pre-startup procedure - world.run_workload(pre_startup).unwrap(); - - //Create event loop - let event_loop = EventLoop::new(); - - //Initialize renderer - { - let settings = world.borrow::>().unwrap(); - world.add_unique_non_send_sync(Renderer::init(&event_loop, &settings)); - } - world.add_unique(BackgroundColor(vec3(0.5, 0.5, 1.))); - - //Save _visualizer.json - #[cfg(feature = "generate_visualizer_data")] - std::fs::write( - "_visualizer.json", - serde_json::to_string(&world.workloads_info()).unwrap(), - ).unwrap(); - - //Run startup systems - world.run_workload(startup).unwrap(); - - //Run the event loop - let mut last_update = Instant::now(); - event_loop.run(move |event, _, control_flow| { - *control_flow = ControlFlow::Poll; - process_glutin_events(&mut world, &event); - #[allow(clippy::collapsible_match, clippy::single_match)] - match event { - Event::WindowEvent { event, .. } => match event { - WindowEvent::CloseRequested => { - log::info!("exit requested"); - *control_flow = ControlFlow::Exit; - }, - _ => (), - }, - Event::MainEventsCleared => { - //Update delta time (maybe move this into a system?) - { - let mut dt_view = world.borrow::>().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::>>().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::().unwrap(); - target.0.finish().unwrap(); - - //After frame end - world.run_workload(after_frame_end).unwrap(); - - //Process control flow changes - if let Some(flow) = world.borrow::>().unwrap().0 { - *control_flow = flow; - } - }, - _ => (), - }; - }); + kubi::kubi_main(); }