diff --git a/assets/voxygen/shaders/include/cloud/regular.glsl b/assets/voxygen/shaders/include/cloud/regular.glsl index 5bbd262112..f6b6c80d41 100644 --- a/assets/voxygen/shaders/include/cloud/regular.glsl +++ b/assets/voxygen/shaders/include/cloud/regular.glsl @@ -24,7 +24,7 @@ vec3 cloud_at(vec3 pos, float dist) { // Mist sits close to the ground in valleys (TODO: use base_alt to put it closer to water) float MIST_MIN = 300; const float MIST_FADE_HEIGHT = 250; - float mist = 0.00025 * pow(clamp(1.0 - (pos.z - MIST_MIN) / MIST_FADE_HEIGHT, 0.0, 1), 2) / (1.0 + pow(1.0 + dist / 20000.0, 2.0)); + float mist = 0.0003 * pow(clamp(1.0 - (pos.z - MIST_MIN) / MIST_FADE_HEIGHT, 0.0, 1), 2) / (1.0 + pow(1.0 + dist / 20000.0, 2.0)); vec3 wind_pos = vec3(pos.xy + wind_offset, pos.z); diff --git a/assets/voxygen/shaders/lod-terrain-frag.glsl b/assets/voxygen/shaders/lod-terrain-frag.glsl index 16fee17483..4e65cdbf0d 100644 --- a/assets/voxygen/shaders/lod-terrain-frag.glsl +++ b/assets/voxygen/shaders/lod-terrain-frag.glsl @@ -278,8 +278,8 @@ void main() { // return true; // } - bvec3 hit_yz_xz_xy; - vec3 dist_yz_xz_xy; + //bvec3 hit_yz_xz_xy; + //vec3 dist_yz_xz_xy; /* { // vec3 rDotn = -f_orig_view_dir * -sides; // vec3 rDotn = f_orig_view_dir * sides; @@ -301,8 +301,8 @@ void main() { // vec3 s = -sides * (f_pos + delta_sides - cam_pos.xyz) / (-f_orig_view_dir * -sides); // vec3 s = (f_pos + delta_sides - cam_pos.xyz) / -f_orig_view_dir; // dist_yz_xz_xy = abs(s); - hit_yz_xz_xy = greaterThanEqual(f_orig_view_dir * sides, vec3(0.000001)); - dist_yz_xz_xy = abs((f_pos + delta_sides - cam_pos.xyz) / f_orig_view_dir); + //hit_yz_xz_xy = greaterThanEqual(f_orig_view_dir * sides, vec3(0.000001)); + //dist_yz_xz_xy = abs((f_pos + delta_sides - cam_pos.xyz) / f_orig_view_dir); } // vec3 xy_point = f_pos, xz_point = f_pos, yz_point = f_pos; @@ -310,11 +310,12 @@ void main() { // bool hit_xz = (/*ao_xy < 1.0 || ao_yz < 1.0*//*min(f_ao_vec.x, f_ao_vec.z)*//*f_ao_vec.y < 1.0*/true/*min(corner_xy.y, corner_yz.x) < 1.0*//*min(corner_xz.x, corner_xz.y) < 1.0*/) && IntersectRayPlane(cam_pos.xyz, -f_orig_view_dir, vec3(f_pos.x, f_pos.y + delta_sides.y/* - sides.y*/, f_pos.z), vec3(0.0, -sides.y, 0.0), xz_point); // bool hit_yz = (/*ao_xy < 1.0 || ao_xz < 1.0*//*min(f_ao_vec.y, f_ao_vec.z) < 1.0*//*f_ao_vec.x < 1.0*/true/*true*//*min(corner_xy.x, corner_xz.x) < 1.0*//*min(corner_yz.x, corner_yz.y) < 1.0*/) && IntersectRayPlane(cam_pos.xyz, -f_orig_view_dir, vec3(f_pos.x + delta_sides.x/* - sides.x*/, f_pos.y, f_pos.z), vec3(-sides.x, 0.0, 0.0), yz_point); // float xy_dist = distance(cam_pos.xyz, xy_point), xz_dist = distance(cam_pos.xyz, xz_point), yz_dist = distance(cam_pos.xyz, yz_point); - bool hit_xy = hit_yz_xz_xy.z, hit_xz = hit_yz_xz_xy.y, hit_yz = hit_yz_xz_xy.x; - float xy_dist = dist_yz_xz_xy.z, xz_dist = dist_yz_xz_xy.y, yz_dist = dist_yz_xz_xy.x; + //bool hit_xy = hit_yz_xz_xy.z, hit_xz = hit_yz_xz_xy.y, hit_yz = hit_yz_xz_xy.x; + //float xy_dist = dist_yz_xz_xy.z, xz_dist = dist_yz_xz_xy.y, yz_dist = dist_yz_xz_xy.x; // hit_xy = hit_xy && distance(f_pos.xy + delta_sides.xy, xy_point.xy) <= 1.0; // hit_xz = hit_xz && distance(f_pos.xz + delta_sides.xz, xz_point.xz) <= 1.0; // hit_yz = hit_yz && distance(f_pos.yz + delta_sides.yz, yz_point.yz) <= 1.0; + /* vec3 voxel_norm = hit_yz ? hit_xz ? @@ -325,8 +326,10 @@ void main() { hit_xz ? hit_xy ? xz_dist < xy_dist ? vec3(0.0, sides.y, 0.0) : vec3(0.0, 0.0, sides.z) : vec3(0.0, sides.y, 0.0) : hit_xy ? vec3(0.0, 0.0, sides.z) : vec3(0.0, 0.0, 0.0); + */ + vec3 voxel_norm; - const float VOXELIZE_DIST = 2500; + const float VOXELIZE_DIST = 2000; float voxelize_factor = clamp(1.0 - (distance(focus_pos.xy, f_pos.xy) - view_distance.x) / VOXELIZE_DIST, 0, 1); vec3 cam_dir = normalize(cam_pos.xyz - f_pos.xyz); vec3 side_norm = normalize(vec3(my_norm.xy, 0)); diff --git a/client/src/lib.rs b/client/src/lib.rs index 231a2b6e36..a2124406d6 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -29,6 +29,7 @@ use common::{ ClientType, DisconnectReason, InviteAnswer, Notification, PingMsg, PlayerInfo, PlayerListUpdate, PresenceKind, RegisterError, ServerGeneral, ServerInfo, ServerInit, ServerRegisterAnswer, MAX_BYTES_CHAT_MSG, + world_msg::SiteInfo, }, outcome::Outcome, recipe::RecipeBook, @@ -101,6 +102,7 @@ pub struct Client { pub world_map: (Arc, Vec2, Vec2), pub player_list: HashMap, pub character_list: CharacterList, + sites: Vec, recipe_book: RecipeBook, available_recipes: HashSet, @@ -191,6 +193,7 @@ impl Client { lod_alt, lod_horizon, world_map, + sites, recipe_book, max_group_size, client_timeout, @@ -255,7 +258,7 @@ impl Client { let horizons = [unzip_horizons(&west), unzip_horizons(&east)]; // Redraw map (with shadows this time). - let mut world_map = vec![0u32; rgba.len()]; + let mut world_map_rgba = vec![0u32; rgba.len()]; let mut map_config = common::terrain::map::MapConfig::orthographic( map_size_lg, core::ops::RangeInclusive::new(0.0, max_height), @@ -322,13 +325,13 @@ impl Client { }) }, |pos, (r, g, b, a)| { - world_map[pos.y * map_size.x as usize + pos.x] = + world_map_rgba[pos.y * map_size.x as usize + pos.x] = u32::from_le_bytes([r, g, b, a]); }, ); ping_stream.send(PingMsg::Ping)?; let make_raw = |rgba| -> Result<_, Error> { - let mut raw = vec![0u8; 4 * world_map.len()]; + let mut raw = vec![0u8; 4 * world_map_rgba.len()]; LittleEndian::write_u32_into(rgba, &mut raw); Ok(Arc::new( image::DynamicImage::ImageRgba8({ @@ -345,7 +348,7 @@ impl Client { ping_stream.send(PingMsg::Ping)?; let lod_base = rgba; let lod_alt = alt; - let world_map = make_raw(&world_map)?; + let world_map_img = make_raw(&world_map_rgba)?; let horizons = (west.0, west.1, east.0, east.1) .into_par_iter() .map(|(wa, wh, ea, eh)| u32::from_le_bytes([wa, wh, ea, eh])) @@ -360,7 +363,8 @@ impl Client { lod_base, lod_alt, lod_horizon, - (world_map, map_size, map_bounds), + (world_map_img, map_size, map_bounds), + world_map.sites, recipe_book, max_group_size, client_timeout, @@ -389,6 +393,7 @@ impl Client { lod_horizon, player_list: HashMap::new(), character_list: CharacterList::default(), + sites, recipe_book, available_recipes: HashSet::default(), @@ -640,6 +645,11 @@ impl Client { .collect(); } + /// Unstable, likely to be removed in a future release + pub fn sites(&self) -> &[SiteInfo] { + &self.sites + } + pub fn enable_lantern(&mut self) { self.send_msg(ClientGeneral::ControlEvent(ControlEvent::EnableLantern)); } diff --git a/common/src/msg/world_msg.rs b/common/src/msg/world_msg.rs index c19c855166..6126ed9d06 100644 --- a/common/src/msg/world_msg.rs +++ b/common/src/msg/world_msg.rs @@ -120,4 +120,20 @@ pub struct WorldMapMsg { /// angles, or that we don't need as much precision as we currently have /// (256 possible angles). pub horizons: [(Vec, Vec); 2], + pub sites: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SiteInfo { + pub kind: SiteKind, + pub wpos: Vec2, + pub name: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[repr(u8)] +pub enum SiteKind { + Town, + Dungeon, + Castle, } diff --git a/server/src/lib.rs b/server/src/lib.rs index 99f9e73c67..26048289c0 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -53,6 +53,7 @@ use common::{ event::{EventBus, ServerEvent}, msg::{ ClientType, DisconnectReason, ServerGeneral, ServerInfo, ServerInit, ServerMsg, WorldMapMsg, + world_msg::{SiteInfo, SiteKind}, }, outcome::Outcome, recipe::default_recipe_book, @@ -83,7 +84,6 @@ use uvth::{ThreadPool, ThreadPoolBuilder}; use vek::*; #[cfg(feature = "worldgen")] use world::{ - civ::SiteKind, sim::{FileOpts, WorldOpts, DEFAULT_WORLD_MAP}, IndexOwned, World, }; @@ -256,6 +256,7 @@ impl Server { horizons: [(vec![0], vec![0]), (vec![0], vec![0])], sea_level: 0.0, alt: vec![30], + sites: Vec::new(), }; #[cfg(feature = "worldgen")] @@ -272,7 +273,7 @@ impl Server { let spawn_chunk = world .civs() .sites() - .filter(|site| matches!(site.kind, SiteKind::Settlement)) + .filter(|site| matches!(site.kind, world::civ::SiteKind::Settlement)) .map(|site| site.center) .min_by_key(|site_pos| site_pos.distance_squared(center_chunk)) .unwrap_or(center_chunk); diff --git a/server/src/rtsim/mod.rs b/server/src/rtsim/mod.rs index 81cd7e82a9..2aa5cf0ef3 100644 --- a/server/src/rtsim/mod.rs +++ b/server/src/rtsim/mod.rs @@ -55,12 +55,12 @@ impl RtSim { } pub fn assimilate_entity(&mut self, entity: RtSimId) { - tracing::info!("Assimilated rtsim entity {}", entity); + // tracing::info!("Assimilated rtsim entity {}", entity); self.entities.get_mut(entity).map(|e| e.is_loaded = false); } pub fn reify_entity(&mut self, entity: RtSimId) { - tracing::info!("Reified rtsim entity {}", entity); + // tracing::info!("Reified rtsim entity {}", entity); self.entities.get_mut(entity).map(|e| e.is_loaded = true); } @@ -69,7 +69,7 @@ impl RtSim { } pub fn destroy_entity(&mut self, entity: RtSimId) { - tracing::info!("Destroyed rtsim entity {}", entity); + // tracing::info!("Destroyed rtsim entity {}", entity); self.entities.remove(entity); } } @@ -102,7 +102,7 @@ pub fn init(state: &mut State, world: &world::World) { brain: Default::default(), }); - tracing::info!("Spawned rtsim NPC {} at {:?}", id, pos); + // tracing::info!("Spawned rtsim NPC {} at {:?}", id, pos); } state.ecs_mut().insert(rtsim); diff --git a/voxygen/src/hud/img_ids.rs b/voxygen/src/hud/img_ids.rs index 48a42cd860..30a2940e64 100644 --- a/voxygen/src/hud/img_ids.rs +++ b/voxygen/src/hud/img_ids.rs @@ -193,6 +193,8 @@ image_ids! { mmap_minus: "voxygen.element.buttons.min_plus.mmap_button-min", mmap_minus_hover: "voxygen.element.buttons.min_plus.mmap_button-min_hover", mmap_minus_press: "voxygen.element.buttons.min_plus.mmap_button-min_press", + mmap_site_town: "voxygen.element.map.town", + mmap_site_dungeon: "voxygen.element.map.dungeon", // Window Parts window_3: "voxygen.element.frames.window_3", diff --git a/voxygen/src/hud/minimap.rs b/voxygen/src/hud/minimap.rs index d897fa3074..18ebb4213c 100644 --- a/voxygen/src/hud/minimap.rs +++ b/voxygen/src/hud/minimap.rs @@ -4,7 +4,7 @@ use super::{ }; use crate::ui::{fonts::Fonts, img_ids}; use client::{self, Client}; -use common::{comp, terrain::TerrainChunkSize, vol::RectVolSize}; +use common::{comp, terrain::TerrainChunkSize, vol::RectVolSize, msg::world_msg::SiteKind}; use conrod_core::{ color, position, widget::{self, Button, Image, Rectangle, Text}, @@ -28,6 +28,7 @@ widget_ids! { mmap_east, mmap_south, mmap_west, + mmap_site_icons[], } } @@ -222,6 +223,41 @@ impl<'a> Widget for MiniMap<'a> { .parent(ui.window) .set(state.ids.indicator, ui); + // Map icons + if state.ids.mmap_site_icons.len() < self.client.sites().len() { + state.update(|state| { + state.ids.mmap_site_icons.resize( + self.client.sites().len(), + &mut ui.widget_id_generator(), + ) + }); + } + for (i, site) in self.client.sites().iter().enumerate() { + let rwpos = site.wpos.map(|e| e as f32) - player_pos; + let rcpos = rwpos.map2(TerrainChunkSize::RECT_SIZE, |e, sz| e / sz as f32) * state.zoom as f32 / 4.0; + let rpos = Vec2::unit_x().rotated_z(self.ori.x) * rcpos.x + + Vec2::unit_y().rotated_z(self.ori.x) * rcpos.y; + + // TODO: Why does this require the magic constant 0.73? This this related to scaling issues? + if rpos.map2(map_size, |e, sz| e.abs() > sz as f32 / 0.73 / 2.0).reduce_or() { + continue; + } + + Image::new(match &site.kind { + SiteKind::Town => self.imgs.mmap_site_town, + SiteKind::Dungeon => self.imgs.mmap_site_dungeon, + SiteKind::Castle => continue, + }) + .x_y_position_relative_to( + state.ids.grid, + position::Relative::Scalar(rpos.x as f64), + position::Relative::Scalar(rpos.y as f64), + ) + .floating(true) + .parent(ui.window) + .set(state.ids.mmap_site_icons[i], ui); + } + // Compass directions let dirs = [ (Vec2::new(0.0, 1.0), state.ids.mmap_north, "N", true), diff --git a/world/src/lib.rs b/world/src/lib.rs index 0bca796afc..944653450f 100644 --- a/world/src/lib.rs +++ b/world/src/lib.rs @@ -41,7 +41,7 @@ use crate::{ }; use common::{ generation::{ChunkSupplement, EntityInfo}, - msg::WorldMapMsg, + msg::{WorldMapMsg, world_msg}, terrain::{Block, BlockKind, SpriteKind, TerrainChunk, TerrainChunkMeta, TerrainChunkSize}, vol::{ReadVol, RectVolSize, WriteVol}, }; @@ -90,7 +90,26 @@ impl World { // TODO } - pub fn get_map_data(&self, index: IndexRef) -> WorldMapMsg { self.sim.get_map(index) } + pub fn get_map_data(&self, index: IndexRef) -> WorldMapMsg { + WorldMapMsg { + sites: self.civs().sites + .iter() + .map(|(_, site)| { + world_msg::SiteInfo { + // TODO: Probably unify these, at some point + kind: match &site.kind { + civ::SiteKind::Settlement => world_msg::SiteKind::Town, + civ::SiteKind::Dungeon => world_msg::SiteKind::Dungeon, + civ::SiteKind::Castle => world_msg::SiteKind::Castle, + }, + wpos: site.center * TerrainChunkSize::RECT_SIZE.map(|e| e as i32), + name: None, + } + }) + .collect(), + ..self.sim.get_map(index) + } + } pub fn sample_columns( &self, diff --git a/world/src/sim/map.rs b/world/src/sim/map.rs index 02254e01a1..f71888bfad 100644 --- a/world/src/sim/map.rs +++ b/world/src/sim/map.rs @@ -247,9 +247,9 @@ pub fn sample_pos( ), }; // TODO: Make principled. - let rgb = if near_site { + let rgb = /*if near_site { Rgb::new(0x57, 0x39, 0x33) - } else if is_path { + } else*/ if is_path { Rgb::new(0x37, 0x29, 0x23) } else if is_cave { Rgb::new(0x37, 0x37, 0x37) diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index 3d49b60c92..0339efc3a9 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -1501,6 +1501,7 @@ impl WorldSim { rgba: v, alt: alts, horizons, + sites: Vec::new(), // Will be substituted later } }