Files
voxel-game/src/client/mod.rs
2024-06-21 00:47:33 -04:00

173 lines
5.0 KiB
Rust

mod app;
mod camera;
mod component;
mod handle_input;
mod input;
pub mod render;
mod rsc;
mod state;
mod system;
pub use app::*;
use bevy_ecs::{entity::Entity, system::SystemId, world::World};
use component::RenderCommands;
use render::RenderCommand;
use rsc::FRAME_TIME;
pub use state::*;
use system::render::add_grid;
use crate::{
server::Server,
common::{ClientMessage, ServerHandle, ServerMessage},
};
use self::{input::Input, render::Renderer, ClientState};
use std::{
collections::HashMap,
sync::Arc,
time::{Duration, Instant},
};
use winit::{
event::WindowEvent,
window::{Window, WindowAttributes},
};
pub struct Client<'a> {
window: Arc<Window>,
state: ClientState,
renderer: Renderer<'a>,
render_commands: Vec<RenderCommand>,
exit: bool,
input: Input,
prev_update: Instant,
grabbed_cursor: bool,
keep_cursor: bool,
world: World,
server: ServerHandle,
server_id_map: HashMap<Entity, Entity>,
systems: ClientSystems,
target: Instant,
frame_time: Duration,
the_thing: bool,
}
pub struct ClientSystems {
render_add_grid: SystemId,
render_update_transform: SystemId,
render_add_chunk: SystemId,
}
impl Client<'_> {
pub fn new(event_loop: &winit::event_loop::ActiveEventLoop) -> Self {
let mut world = World::new();
let window = Arc::new(
event_loop
.create_window(WindowAttributes::default())
.expect("Failed to create window"),
);
let renderer = Renderer::spawn(window.clone());
world.insert_resource(RenderCommands(Vec::new()));
let state = ClientState::new();
let server = ServerHandle::spawn(Server::start);
server.send(ServerMessage::Join);
Self {
window,
exit: false,
renderer,
render_commands: Vec::new(),
state,
input: Input::new(),
prev_update: Instant::now(),
grabbed_cursor: false,
keep_cursor: false,
systems: ClientSystems {
render_add_grid: world.register_system(add_grid),
render_update_transform: world.register_system(system::render::update_transform),
render_add_chunk: world.register_system(system::render::add_chunk),
},
world,
server,
server_id_map: HashMap::new(),
target: Instant::now(),
frame_time: FRAME_TIME,
the_thing: false,
}
}
pub fn update(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
let now = Instant::now();
let dt = now - self.prev_update;
self.prev_update = now;
self.handle_input(&dt);
self.input.end();
self.recv();
self.world
.run_system(self.systems.render_add_grid)
.expect("WHAT v2");
self.world
.run_system(self.systems.render_update_transform)
.expect("WHAT");
self.world
.run_system(self.systems.render_add_chunk)
.expect("WHAT v3");
self.world.clear_trackers();
if self.state.camera.pos.y < -10.0 {
self.the_thing = !self.the_thing;
if self.the_thing == true {
// let thing = include_bytes!("../../../../videos/meme/rab_falls_and_dies.mp4");
}
}
if now >= self.target {
self.target += self.frame_time;
let mut commands = std::mem::take(&mut self.render_commands);
let world_cmds = std::mem::take(&mut self.world.resource_mut::<RenderCommands>().0);
commands.extend(world_cmds);
self.renderer.handle_commands(commands);
self.renderer.draw();
}
if self.exit {
event_loop.exit();
}
}
pub fn recv(&mut self) {
for msg in self.server.recv() {
match msg {
ClientMessage::SpawnVoxelGrid(entity, grid) => {
let id = self.world.spawn(grid).id();
self.server_id_map.insert(entity, id);
}
ClientMessage::LoadChunk(entity, chunk) => {
let id = self.world.spawn(chunk).id();
self.server_id_map.insert(entity, id);
}
ClientMessage::PosUpdate(e, pos) => {
if let Some(id) = self.server_id_map.get(&e) {
self.world.entity_mut(*id).insert(pos);
}
}
}
}
}
pub fn window_event(&mut self, event: WindowEvent) {
match event {
WindowEvent::CloseRequested => self.exit = true,
WindowEvent::Resized(size) => self.renderer.resize(size),
WindowEvent::RedrawRequested => self.renderer.draw(),
WindowEvent::CursorLeft { .. } => {
self.input.clear();
}
_ => self.input.update_window(event),
}
}
}