mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Make train tracks configurable as a worldgen feature. Fixes for clippy and fmt.
This commit is contained in:
parent
372ffe45d7
commit
f83afcd5a8
@ -15,4 +15,5 @@
|
|||||||
wildlife_density: 1.0,
|
wildlife_density: 1.0,
|
||||||
peak_naming: true,
|
peak_naming: true,
|
||||||
biome_naming: true,
|
biome_naming: true,
|
||||||
|
train_tracks: false, // TODO: train stations, train entities
|
||||||
)
|
)
|
||||||
|
@ -61,7 +61,7 @@ use rand::{thread_rng, Rng};
|
|||||||
use specs::{
|
use specs::{
|
||||||
saveload::MarkerAllocator, storage::StorageEntry, Builder, Entity as EcsEntity, Join, WorldExt,
|
saveload::MarkerAllocator, storage::StorageEntry, Builder, Entity as EcsEntity, Join, WorldExt,
|
||||||
};
|
};
|
||||||
use std::{str::FromStr, fmt::Write, sync::Arc};
|
use std::{fmt::Write, str::FromStr, sync::Arc};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
use wiring::{Circuit, Wire, WireNode, WiringAction, WiringActionEffect, WiringElement};
|
use wiring::{Circuit, Wire, WireNode, WiringAction, WiringActionEffect, WiringElement};
|
||||||
use world::util::{Sampler, LOCALITY};
|
use world::util::{Sampler, LOCALITY};
|
||||||
|
@ -223,8 +223,8 @@ impl<'a> Widget for Chat<'a> {
|
|||||||
// Maintain scrolling //
|
// Maintain scrolling //
|
||||||
if !self.new_messages.is_empty() {
|
if !self.new_messages.is_empty() {
|
||||||
for message in self.new_messages.iter() {
|
for message in self.new_messages.iter() {
|
||||||
// Log the output of commands since the ingame terminal doesn't support copying the
|
// Log the output of commands since the ingame terminal doesn't support copying
|
||||||
// output to the clipboard
|
// the output to the clipboard
|
||||||
if let ChatType::CommandInfo = message.chat_type {
|
if let ChatType::CommandInfo = message.chat_type {
|
||||||
tracing::info!("{}", message.message);
|
tracing::info!("{}", message.message);
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,13 @@ impl DebugShape {
|
|||||||
DebugShape::Line([a, b]) => {
|
DebugShape::Line([a, b]) => {
|
||||||
//let h = Vec3::new(0.0, 1.0, 0.0);
|
//let h = Vec3::new(0.0, 1.0, 0.0);
|
||||||
//mesh.push_quad(quad(*a, a + h, b + h, *b));
|
//mesh.push_quad(quad(*a, a + h, b + h, *b));
|
||||||
box_along_line(LineSegment3 { start: *a, end: *b }, 0.1, 0.1, [1.0; 4], &mut mesh);
|
box_along_line(
|
||||||
|
LineSegment3 { start: *a, end: *b },
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
[1.0; 4],
|
||||||
|
&mut mesh,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
DebugShape::Cylinder { radius, height } => {
|
DebugShape::Cylinder { radius, height } => {
|
||||||
const SUBDIVISIONS: u8 = 16;
|
const SUBDIVISIONS: u8 = 16;
|
||||||
@ -221,7 +227,8 @@ impl DebugShape {
|
|||||||
let start = path.evaluate(i as f32 * step_size);
|
let start = path.evaluate(i as f32 * step_size);
|
||||||
let end = path.evaluate((i + 1) as f32 * step_size);
|
let end = path.evaluate((i + 1) as f32 * step_size);
|
||||||
let center = LineSegment3 { start, end };
|
let center = LineSegment3 { start, end };
|
||||||
let dx = *rail_sep * Vec3::unit_z().cross(center.end - center.start).normalized();
|
let dx =
|
||||||
|
*rail_sep * Vec3::unit_z().cross(center.end - center.start).normalized();
|
||||||
let dz = -dx.cross(center.end - center.start).normalized();
|
let dz = -dx.cross(center.end - center.start).normalized();
|
||||||
let left = LineSegment3 {
|
let left = LineSegment3 {
|
||||||
start: center.start + dx,
|
start: center.start + dx,
|
||||||
|
@ -1311,7 +1311,7 @@ impl Scene {
|
|||||||
let mut ret = Vec::new();
|
let mut ret = Vec::new();
|
||||||
for bezier in chunk.meta().tracks().iter() {
|
for bezier in chunk.meta().tracks().iter() {
|
||||||
let shape_id = self.debug.add_shape(DebugShape::TrainTrack {
|
let shape_id = self.debug.add_shape(DebugShape::TrainTrack {
|
||||||
path: *bezier,
|
path: *bezier,
|
||||||
rail_width: 0.25,
|
rail_width: 0.25,
|
||||||
rail_sep: 1.0,
|
rail_sep: 1.0,
|
||||||
plank_width: 0.5,
|
plank_width: 0.5,
|
||||||
@ -1319,7 +1319,8 @@ impl Scene {
|
|||||||
plank_sep: 2.0,
|
plank_sep: 2.0,
|
||||||
});
|
});
|
||||||
ret.push(shape_id);
|
ret.push(shape_id);
|
||||||
self.debug.set_context(shape_id, [0.0; 4], [1.0; 4], [0.0, 0.0, 0.0, 1.0]);
|
self.debug
|
||||||
|
.set_context(shape_id, [0.0; 4], [1.0; 4], [0.0, 0.0, 0.0, 1.0]);
|
||||||
}
|
}
|
||||||
for point in chunk.meta().debug_points().iter() {
|
for point in chunk.meta().debug_points().iter() {
|
||||||
let shape_id = self.debug.add_shape(DebugShape::Cylinder {
|
let shape_id = self.debug.add_shape(DebugShape::Cylinder {
|
||||||
@ -1327,12 +1328,20 @@ impl Scene {
|
|||||||
height: 0.1,
|
height: 0.1,
|
||||||
});
|
});
|
||||||
ret.push(shape_id);
|
ret.push(shape_id);
|
||||||
self.debug.set_context(shape_id, point.with_w(0.0).into_array(), [1.0; 4], [0.0, 0.0, 0.0, 1.0]);
|
self.debug.set_context(
|
||||||
|
shape_id,
|
||||||
|
point.with_w(0.0).into_array(),
|
||||||
|
[1.0; 4],
|
||||||
|
[0.0, 0.0, 0.0, 1.0],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
for line in chunk.meta().debug_lines().iter() {
|
for line in chunk.meta().debug_lines().iter() {
|
||||||
let shape_id = self.debug.add_shape(DebugShape::Line([line.start.into(), line.end.into()]));
|
let shape_id = self
|
||||||
|
.debug
|
||||||
|
.add_shape(DebugShape::Line([line.start, line.end]));
|
||||||
ret.push(shape_id);
|
ret.push(shape_id);
|
||||||
self.debug.set_context(shape_id, [0.0; 4], [1.0; 4], [0.0, 0.0, 0.0, 1.0]);
|
self.debug
|
||||||
|
.set_context(shape_id, [0.0; 4], [1.0; 4], [0.0, 0.0, 0.0, 1.0]);
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
});
|
});
|
||||||
|
@ -93,6 +93,7 @@ pub struct Features {
|
|||||||
pub wildlife_density: f32,
|
pub wildlife_density: f32,
|
||||||
pub peak_naming: bool,
|
pub peak_naming: bool,
|
||||||
pub biome_naming: bool,
|
pub biome_naming: bool,
|
||||||
|
pub train_tracks: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl assets::Asset for Features {
|
impl assets::Asset for Features {
|
||||||
|
@ -42,7 +42,7 @@ use crate::{
|
|||||||
index::Index,
|
index::Index,
|
||||||
layer::spot::Spot,
|
layer::spot::Spot,
|
||||||
site::{SiteKind, SpawnRules},
|
site::{SiteKind, SpawnRules},
|
||||||
util::{Grid, Sampler, NEIGHBORS},
|
util::{Grid, Sampler},
|
||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
assets,
|
assets,
|
||||||
@ -359,11 +359,11 @@ impl World {
|
|||||||
entities: Vec::new(),
|
entities: Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
if index.features.train_tracks {
|
||||||
let mut splines = Vec::new();
|
let mut splines = Vec::new();
|
||||||
let g = |v: Vec2<f32>| -> Vec3<f32> {
|
let g = |v: Vec2<f32>| -> Vec3<f32> {
|
||||||
let path_nearest =
|
let path_nearest = self
|
||||||
self.sim
|
.sim
|
||||||
.get_nearest_path(v.as_::<i32>())
|
.get_nearest_path(v.as_::<i32>())
|
||||||
.map(|x| x.1)
|
.map(|x| x.1)
|
||||||
.unwrap_or(v.as_::<f32>());
|
.unwrap_or(v.as_::<f32>());
|
||||||
@ -375,7 +375,12 @@ impl World {
|
|||||||
};
|
};
|
||||||
v.with_z(alt)
|
v.with_z(alt)
|
||||||
};
|
};
|
||||||
fn hermit_to_bezier(p0: Vec3<f32>, m0: Vec3<f32>, p3: Vec3<f32>, m3: Vec3<f32>) -> CubicBezier3<f32> {
|
fn hermite_to_bezier(
|
||||||
|
p0: Vec3<f32>,
|
||||||
|
m0: Vec3<f32>,
|
||||||
|
p3: Vec3<f32>,
|
||||||
|
m3: Vec3<f32>,
|
||||||
|
) -> CubicBezier3<f32> {
|
||||||
let hermite = Vec4::new(p0, p3, m0, m3);
|
let hermite = Vec4::new(p0, p3, m0, m3);
|
||||||
let hermite = hermite.map(|v| v.with_w(0.0));
|
let hermite = hermite.map(|v| v.with_w(0.0));
|
||||||
let hermite: [[f32; 4]; 4] =
|
let hermite: [[f32; 4]; 4] =
|
||||||
@ -390,27 +395,25 @@ impl World {
|
|||||||
m.invert();
|
m.invert();
|
||||||
let bezier = m * Mat4::from_row_arrays(hermite);
|
let bezier = m * Mat4::from_row_arrays(hermite);
|
||||||
let bezier: Vec4<Vec4<f32>> =
|
let bezier: Vec4<Vec4<f32>> =
|
||||||
Vec4::<[f32; 4]>::from(bezier.into_row_arrays())
|
Vec4::<[f32; 4]>::from(bezier.into_row_arrays()).map(Vec4::from);
|
||||||
.map(Vec4::from);
|
let bezier = bezier.map(Vec3::from);
|
||||||
let bezier = bezier.map(|v| Vec3::from(v));
|
|
||||||
CubicBezier3::from(bezier)
|
CubicBezier3::from(bezier)
|
||||||
}
|
}
|
||||||
for (_, _, _, _, bez, _) in self.sim.get_nearest_ways(chunk_center_wpos2d, &|chunk| Some(chunk.path)) {
|
for (_, _, _, _, bez, _) in self
|
||||||
|
.sim
|
||||||
|
.get_nearest_ways(chunk_center_wpos2d, &|chunk| Some(chunk.path))
|
||||||
|
{
|
||||||
if bez.length_by_discretization(16) < 0.125 {
|
if bez.length_by_discretization(16) < 0.125 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/*if bez.ctrl.as_::<i32>().distance_squared(chunk_center_wpos2d) > 20i32.pow(2) {
|
|
||||||
continue;
|
|
||||||
}*/
|
|
||||||
//println!("chunk: {:?}, bez: {:?}", chunk_center_wpos2d, bez);
|
|
||||||
let a = 0.0;
|
let a = 0.0;
|
||||||
let b = 1.0;
|
let b = 1.0;
|
||||||
for bez in bez.split((a + b) / 2.0) {
|
for bez in bez.split((a + b) / 2.0) {
|
||||||
let p0 = g(bez.evaluate(a));
|
let p0 = g(bez.evaluate(a));
|
||||||
let p1 = g(bez.evaluate(a + (b - a) / 3.0));
|
let p1 = g(bez.evaluate(a + (b - a) / 3.0));
|
||||||
let p2 = g(bez.evaluate(a + 2.0 * (b-a)/3.0));
|
let p2 = g(bez.evaluate(a + 2.0 * (b - a) / 3.0));
|
||||||
let p3 = g(bez.evaluate(b));
|
let p3 = g(bez.evaluate(b));
|
||||||
splines.push(hermit_to_bezier(p0, 3.0 * (p1 - p0), p3, 3.0 * (p3 - p2)));
|
splines.push(hermite_to_bezier(p0, 3.0 * (p1 - p0), p3, 3.0 * (p3 - p2)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for spline in splines.into_iter() {
|
for spline in splines.into_iter() {
|
||||||
|
@ -2137,7 +2137,16 @@ impl WorldSim {
|
|||||||
&'a self,
|
&'a self,
|
||||||
wpos: Vec2<i32>,
|
wpos: Vec2<i32>,
|
||||||
get_way: &'a impl Fn(&SimChunk) -> Option<(Way, M)>,
|
get_way: &'a impl Fn(&SimChunk) -> Option<(Way, M)>,
|
||||||
) -> impl Iterator<Item=(usize, f32, Vec2<f32>, M, QuadraticBezier2<f32>, impl FnOnce() -> Vec2<f32>)> + 'a {
|
) -> impl Iterator<
|
||||||
|
Item = (
|
||||||
|
usize,
|
||||||
|
f32,
|
||||||
|
Vec2<f32>,
|
||||||
|
M,
|
||||||
|
QuadraticBezier2<f32>,
|
||||||
|
impl FnOnce() -> Vec2<f32>,
|
||||||
|
),
|
||||||
|
> + 'a {
|
||||||
let chunk_pos = wpos.map2(TerrainChunkSize::RECT_SIZE, |e, sz: u32| {
|
let chunk_pos = wpos.map2(TerrainChunkSize::RECT_SIZE, |e, sz: u32| {
|
||||||
e.div_euclid(sz as i32)
|
e.div_euclid(sz as i32)
|
||||||
});
|
});
|
||||||
@ -2182,7 +2191,9 @@ impl WorldSim {
|
|||||||
NEIGHBORS
|
NEIGHBORS
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter(move |(i, _)| way.neighbors & (1 << *i as u8) != 0 && Some(*i) != start_idx)
|
.filter(move |(i, _)| {
|
||||||
|
way.neighbors & (1 << *i as u8) != 0 && Some(*i) != start_idx
|
||||||
|
})
|
||||||
.filter_map(move |(i, end_rpos)| {
|
.filter_map(move |(i, end_rpos)| {
|
||||||
let end_pos_chunk = chunk_pos + *ctrl + end_rpos;
|
let end_pos_chunk = chunk_pos + *ctrl + end_rpos;
|
||||||
let (end_way, end_meta) = get_way(self.get(end_pos_chunk)?)?;
|
let (end_way, end_meta) = get_way(self.get(end_pos_chunk)?)?;
|
||||||
@ -2236,14 +2247,19 @@ impl WorldSim {
|
|||||||
self.get_nearest_way(wpos, |chunk| Some(chunk.cave))
|
self.get_nearest_way(wpos, |chunk| Some(chunk.cave))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_nearest_path_for_direction(&self, wpos: Vec2<i32>, dir: usize) -> Option<(f32, Vec2<f32>, Path, QuadraticBezier2<f32>, Vec2<f32>)> {
|
pub fn get_nearest_path_for_direction(
|
||||||
|
&self,
|
||||||
|
wpos: Vec2<i32>,
|
||||||
|
dir: usize,
|
||||||
|
) -> Option<(f32, Vec2<f32>, Path, QuadraticBezier2<f32>, Vec2<f32>)> {
|
||||||
self.get_nearest_ways(wpos, &|chunk| Some(chunk.path))
|
self.get_nearest_ways(wpos, &|chunk| Some(chunk.path))
|
||||||
.filter(|(i, _, _, _, _, _)| *i == dir)
|
.filter(|(i, _, _, _, _, _)| *i == dir)
|
||||||
.min_by_key(|(_, dist_sqrd, _, _, _, _)| (dist_sqrd * 1024.0) as i32)
|
.min_by_key(|(_, dist_sqrd, _, _, _, _)| (dist_sqrd * 1024.0) as i32)
|
||||||
.map(|(_, dist, pos, meta, bez, calc_tangent)| (dist.sqrt(), pos, meta, bez, calc_tangent()))
|
.map(|(_, dist, pos, meta, bez, calc_tangent)| {
|
||||||
|
(dist.sqrt(), pos, meta, bez, calc_tangent())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Create a [`Lottery<Option<ForestKind>>`] that generates [`ForestKind`]s
|
/// Create a [`Lottery<Option<ForestKind>>`] that generates [`ForestKind`]s
|
||||||
/// according to the conditions at the given position. If no or fewer
|
/// according to the conditions at the given position. If no or fewer
|
||||||
/// trees are appropriate for the conditions, `None` may be generated.
|
/// trees are appropriate for the conditions, `None` may be generated.
|
||||||
|
Loading…
Reference in New Issue
Block a user