mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Updated changelog, cleaned up warnings, minor fixes
This commit is contained in:
parent
15b1717295
commit
85ed5ad356
@ -53,6 +53,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Functional group-system with exp-sharing and disabled damage to group members
|
||||
- Some Campfire, fireball & bomb; particle, light & sound effects.
|
||||
- Added setting to change resolution
|
||||
- Rare (unfinished) castles
|
||||
- Caves with monsters and treasure
|
||||
- Furniture and decals in towns
|
||||
|
||||
### Changed
|
||||
|
||||
@ -85,6 +88,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Dehardcoded many item variants
|
||||
- Tooltips avoid the mouse better and disappear when hovered
|
||||
- Improved social window functions and visuals
|
||||
- Changed agent behaviour to allow fleeing
|
||||
- Waypoints now spawn on dungeon staircases
|
||||
|
||||
### Removed
|
||||
|
||||
|
@ -121,7 +121,7 @@ impl<S: Clone + Eq + Hash, H: BuildHasher + Clone> Astar<S, H> {
|
||||
{
|
||||
let iter_limit = self.max_iters.min(self.iter + iters);
|
||||
while self.iter < iter_limit {
|
||||
if let Some(PathEntry { node, cost }) = self.potential_nodes.pop() {
|
||||
if let Some(PathEntry { node, .. }) = self.potential_nodes.pop() {
|
||||
if satisfied(&node) {
|
||||
return PathResult::Path(self.reconstruct_path_to(node));
|
||||
} else {
|
||||
|
@ -121,17 +121,8 @@ impl Route {
|
||||
.unwrap_or(false))
|
||||
});
|
||||
|
||||
let next0_tgt = next0.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0);
|
||||
let next1_tgt = next1.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0);
|
||||
let next_tgt = next0_tgt;
|
||||
|
||||
// // Maybe skip a node (useful with traversing downhill)
|
||||
// let closest_tgt = if next0_tgt.distance_squared(pos) < next1_tgt.distance_squared(pos) {
|
||||
// next0_tgt
|
||||
// } else {
|
||||
// next1_tgt
|
||||
// };
|
||||
let closest_tgt = next0_tgt.map2(pos, |tgt, pos| pos.clamped(tgt.floor(), tgt.ceil()));
|
||||
let next_tgt = next0.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0);
|
||||
let closest_tgt = next_tgt.map2(pos, |tgt, pos| pos.clamped(tgt.floor(), tgt.ceil()));
|
||||
|
||||
// Determine whether we're close enough to the next to to consider it completed
|
||||
let dist_sqrd = pos.xy().distance_squared(closest_tgt.xy());
|
||||
|
@ -94,7 +94,7 @@ impl<'a> System<'a> for Sys {
|
||||
let mut event_emitter = event_bus.emitter();
|
||||
|
||||
// Apply movement inputs
|
||||
for (entity, scale, sticky, collider, mut pos, mut vel, _ori, _) in (
|
||||
for (entity, _scale, sticky, collider, mut pos, mut vel, _ori, _) in (
|
||||
&entities,
|
||||
scales.maybe(),
|
||||
stickies.maybe(),
|
||||
@ -113,7 +113,8 @@ impl<'a> System<'a> for Sys {
|
||||
continue;
|
||||
}
|
||||
|
||||
let scale = scale.map(|s| s.0).unwrap_or(1.0);
|
||||
// TODO: Use this
|
||||
//let scale = scale.map(|s| s.0).unwrap_or(1.0);
|
||||
|
||||
let old_vel = *vel;
|
||||
// Integrate forces
|
||||
|
@ -3230,15 +3230,15 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
if let Some(models) = self.sprite_models.get(&kind) {
|
||||
renderer.render_sprites(
|
||||
if dist_sqrd < sprite_high_detail_distance.powf(2.0) {
|
||||
&self.sprite_models[&kind][0]
|
||||
&models[0]
|
||||
} else if dist_sqrd < sprite_hid_detail_distance.powf(2.0) {
|
||||
&self.sprite_models[&kind][1]
|
||||
&models[1]
|
||||
} else if dist_sqrd < sprite_mid_detail_distance.powf(2.0) {
|
||||
&self.sprite_models[&kind][2]
|
||||
&models[2]
|
||||
} else if dist_sqrd < sprite_low_detail_distance.powf(2.0) {
|
||||
&self.sprite_models[&kind][3]
|
||||
&models[3]
|
||||
} else {
|
||||
&self.sprite_models[&kind][4]
|
||||
&models[4]
|
||||
},
|
||||
globals,
|
||||
&instances,
|
||||
|
@ -9,7 +9,7 @@ use common::{
|
||||
terrain::{structure::StructureBlock, Block, BlockKind, Structure},
|
||||
vol::{ReadVol, Vox},
|
||||
};
|
||||
use std::ops::{Add, Div, Mul, Neg};
|
||||
use std::ops::{Div, Mul};
|
||||
use vek::*;
|
||||
|
||||
pub struct BlockGen<'a> {
|
||||
|
@ -264,7 +264,7 @@ impl Civs {
|
||||
1 << ((to_next_idx as u8 + 4) % 8);
|
||||
}
|
||||
|
||||
for (i, loc) in path.iter().enumerate() {
|
||||
for loc in path.iter() {
|
||||
let mut chunk = ctx.sim.get_mut(loc.0).unwrap();
|
||||
let depth = loc.1 * 250.0 - 20.0;
|
||||
chunk.cave.1.alt =
|
||||
|
@ -14,7 +14,7 @@ use roots::find_roots_cubic;
|
||||
use std::{
|
||||
cmp::Reverse,
|
||||
f32, f64,
|
||||
ops::{Add, Div, Mul, Neg, Sub},
|
||||
ops::{Add, Div, Mul, Sub},
|
||||
};
|
||||
use tracing::error;
|
||||
use vek::*;
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::site::Site;
|
||||
use common::store::{Id, Store};
|
||||
use noise::{NoiseFn, Seedable, SuperSimplex};
|
||||
use common::store::Store;
|
||||
use noise::{Seedable, SuperSimplex};
|
||||
|
||||
pub struct Index {
|
||||
pub seed: u32,
|
||||
|
@ -135,7 +135,7 @@ pub fn apply_paths_to<'a>(
|
||||
wpos2d: Vec2<i32>,
|
||||
mut get_column: impl FnMut(Vec2<i32>) -> Option<&'a ColumnSample<'a>>,
|
||||
vol: &mut (impl BaseVol<Vox = Block> + RectSizedVol + ReadVol + WriteVol),
|
||||
index: &Index,
|
||||
_index: &Index,
|
||||
) {
|
||||
for y in 0..vol.size_xy().y as i32 {
|
||||
for x in 0..vol.size_xy().x as i32 {
|
||||
@ -239,7 +239,7 @@ pub fn apply_caves_to<'a>(
|
||||
};
|
||||
let surface_z = col_sample.riverless_alt.floor() as i32;
|
||||
|
||||
if let Some((cave_dist, cave_nearest, cave, _)) = col_sample
|
||||
if let Some((cave_dist, _, cave, _)) = col_sample
|
||||
.cave
|
||||
.filter(|(dist, _, cave, _)| *dist < cave.width)
|
||||
{
|
||||
@ -286,8 +286,11 @@ pub fn apply_caves_to<'a>(
|
||||
);
|
||||
}
|
||||
|
||||
let cave_depth = (col_sample.alt - cave.alt).max(0.0);
|
||||
let difficulty = cave_depth / 200.0;
|
||||
|
||||
// Scatter things in caves
|
||||
if RandomField::new(index.seed).chance(wpos2d.into(), 0.001)
|
||||
if RandomField::new(index.seed).chance(wpos2d.into(), 0.002 * difficulty)
|
||||
&& cave_base < surface_z as i32 - 25
|
||||
{
|
||||
let kind = *assets::load_expect::<Lottery<BlockKind>>("common.cave_scatter")
|
||||
@ -324,7 +327,7 @@ pub fn apply_caves_supplement<'a>(
|
||||
};
|
||||
let surface_z = col_sample.riverless_alt.floor() as i32;
|
||||
|
||||
if let Some((cave_dist, cave_nearest, cave, _)) = col_sample
|
||||
if let Some((cave_dist, _, cave, _)) = col_sample
|
||||
.cave
|
||||
.filter(|(dist, _, cave, _)| *dist < cave.width)
|
||||
{
|
||||
@ -332,14 +335,15 @@ pub fn apply_caves_supplement<'a>(
|
||||
|
||||
// Relative units
|
||||
let cave_floor = 0.0 - 0.5 * (1.0 - cave_x.powf(2.0)).max(0.0).sqrt() * cave.width;
|
||||
let cave_height = (1.0 - cave_x.powf(2.0)).max(0.0).sqrt() * cave.width;
|
||||
|
||||
// Abs units
|
||||
let cave_base = (cave.alt + cave_floor) as i32;
|
||||
let cave_roof = (cave.alt + cave_height) as i32;
|
||||
|
||||
let cave_depth = (col_sample.alt - cave.alt).max(0.0);
|
||||
let difficulty = cave_depth / 200.0;
|
||||
|
||||
// Scatter things in caves
|
||||
if RandomField::new(index.seed).chance(wpos2d.into(), 0.00005)
|
||||
if RandomField::new(index.seed).chance(wpos2d.into(), 0.0001 * difficulty)
|
||||
&& cave_base < surface_z as i32 - 40
|
||||
{
|
||||
let entity = EntityInfo::at(Vec3::new(
|
||||
|
@ -26,7 +26,6 @@ pub use self::{
|
||||
use crate::{
|
||||
all::ForestKind,
|
||||
civ::Place,
|
||||
column::{ColumnGen, ColumnSample},
|
||||
site::Site,
|
||||
util::{seed_expan, FastNoise, RandomField, StructureGen2d, LOCALITY, NEIGHBORS},
|
||||
Index, CONFIG,
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
Index,
|
||||
};
|
||||
use common::store::Id;
|
||||
use tracing::{debug, info, warn};
|
||||
use tracing::debug;
|
||||
|
||||
const MONTH: f32 = 30.0;
|
||||
const YEAR: f32 = 12.0 * MONTH;
|
||||
@ -78,7 +78,7 @@ pub fn simulate(index: &mut Index, world: &mut WorldSim) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tick(index: &mut Index, world: &mut WorldSim, dt: f32) {
|
||||
pub fn tick(index: &mut Index, _world: &mut WorldSim, dt: f32) {
|
||||
for site in index.sites.ids() {
|
||||
tick_site_economy(index, site, dt);
|
||||
}
|
||||
@ -137,8 +137,6 @@ pub fn tick_site_economy(index: &mut Index, site: Id<Site>, dt: f32) {
|
||||
// Note that values are used for workforce allocation and are not the same thing
|
||||
// as price
|
||||
let values = &mut site.economy.values;
|
||||
let marginal_surplus = &site.economy.marginal_surplus;
|
||||
let stocks = &site.economy.stocks;
|
||||
site.economy.surplus.iter().for_each(|(good, surplus)| {
|
||||
// Value rationalisation
|
||||
let val = 2.0f32.powf(1.0 - *surplus / demand[good]);
|
||||
@ -151,12 +149,12 @@ pub fn tick_site_economy(index: &mut Index, site: Id<Site>, dt: f32) {
|
||||
});
|
||||
|
||||
// Update export targets based on relative values
|
||||
let value_avg = values
|
||||
.iter()
|
||||
.map(|(_, v)| (*v).unwrap_or(0.0))
|
||||
.sum::<f32>()
|
||||
.max(0.01)
|
||||
/ values.iter().filter(|(_, v)| v.is_some()).count() as f32;
|
||||
// let value_avg = values
|
||||
// .iter()
|
||||
// .map(|(_, v)| (*v).unwrap_or(0.0))
|
||||
// .sum::<f32>()
|
||||
// .max(0.01)
|
||||
// / values.iter().filter(|(_, v)| v.is_some()).count() as f32;
|
||||
//let export_targets = &mut site.economy.export_targets;
|
||||
//let last_exports = &self.last_exports;
|
||||
// site.economy.values.iter().for_each(|(stock, value)| {
|
||||
|
@ -1,20 +0,0 @@
|
||||
use vek::*;
|
||||
use crate::{
|
||||
util::{attempt, Grid, RandomField, Sampler, CARDINALS, DIRS},
|
||||
};
|
||||
|
||||
pub struct Keep {
|
||||
offset: Vec2<i32>,
|
||||
cols: Grid<KeepCol>,
|
||||
}
|
||||
|
||||
const KEEP_CELL_STOREY: i32 = 12;
|
||||
|
||||
pub struct KeepCol {
|
||||
z_offset: i32,
|
||||
storeys: Vec<KeepCell>,
|
||||
}
|
||||
|
||||
enum KeepCell {
|
||||
Cube,
|
||||
}
|
@ -1,35 +1,19 @@
|
||||
mod keep;
|
||||
|
||||
use super::SpawnRules;
|
||||
use crate::{
|
||||
block::block_from_structure,
|
||||
column::ColumnSample,
|
||||
sim::WorldSim,
|
||||
site::{
|
||||
settlement::building::{
|
||||
archetype::keep::{Attr, Keep as KeepArchetype},
|
||||
Archetype, Branch, Ori,
|
||||
},
|
||||
BlockMask,
|
||||
site::settlement::building::{
|
||||
archetype::keep::{Attr, Keep as KeepArchetype},
|
||||
Archetype, Ori,
|
||||
},
|
||||
util::{attempt, Grid, RandomField, Sampler, CARDINALS, DIRS},
|
||||
};
|
||||
use common::{
|
||||
assets,
|
||||
astar::Astar,
|
||||
comp,
|
||||
generation::{ChunkSupplement, EntityInfo},
|
||||
npc,
|
||||
spiral::Spiral2d,
|
||||
store::{Id, Store},
|
||||
terrain::{Block, BlockKind, Structure, TerrainChunkSize},
|
||||
vol::{BaseVol, ReadVol, RectSizedVol, RectVolSize, Vox, WriteVol},
|
||||
generation::ChunkSupplement,
|
||||
terrain::{Block, BlockKind},
|
||||
vol::{BaseVol, ReadVol, RectSizedVol, Vox, WriteVol},
|
||||
};
|
||||
use core::{f32, hash::BuildHasherDefault};
|
||||
use fxhash::FxHasher64;
|
||||
use lazy_static::lazy_static;
|
||||
use core::f32;
|
||||
use rand::prelude::*;
|
||||
use std::sync::Arc;
|
||||
use vek::*;
|
||||
|
||||
struct Keep {
|
||||
@ -47,8 +31,7 @@ struct Tower {
|
||||
|
||||
pub struct Castle {
|
||||
origin: Vec2<i32>,
|
||||
alt: i32,
|
||||
seed: u32,
|
||||
//seed: u32,
|
||||
radius: i32,
|
||||
towers: Vec<Tower>,
|
||||
keeps: Vec<Keep>,
|
||||
@ -57,8 +40,6 @@ pub struct Castle {
|
||||
flags: bool,
|
||||
|
||||
evil: bool,
|
||||
|
||||
keep: Option<keep::Keep>,
|
||||
}
|
||||
|
||||
pub struct GenCtx<'a, R: Rng> {
|
||||
@ -69,7 +50,7 @@ pub struct GenCtx<'a, R: Rng> {
|
||||
impl Castle {
|
||||
#[allow(clippy::let_and_return)] // TODO: Pending review in #587
|
||||
pub fn generate(wpos: Vec2<i32>, sim: Option<&mut WorldSim>, rng: &mut impl Rng) -> Self {
|
||||
let mut ctx = GenCtx { sim, rng };
|
||||
let ctx = GenCtx { sim, rng };
|
||||
|
||||
let boundary_towers = ctx.rng.gen_range(5, 10);
|
||||
let keep_count = ctx.rng.gen_range(1, 4);
|
||||
@ -77,15 +58,15 @@ impl Castle {
|
||||
|
||||
let radius = 150;
|
||||
|
||||
let mut this = Self {
|
||||
let this = Self {
|
||||
origin: wpos,
|
||||
alt: ctx
|
||||
.sim
|
||||
.as_ref()
|
||||
.and_then(|sim| sim.get_alt_approx(wpos))
|
||||
.unwrap_or(0.0) as i32
|
||||
+ 6,
|
||||
seed: ctx.rng.gen(),
|
||||
// alt: ctx
|
||||
// .sim
|
||||
// .as_ref()
|
||||
// .and_then(|sim| sim.get_alt_approx(wpos))
|
||||
// .unwrap_or(0.0) as i32
|
||||
// + 6,
|
||||
//seed: ctx.rng.gen(),
|
||||
radius,
|
||||
|
||||
towers: (0..boundary_towers)
|
||||
@ -150,8 +131,6 @@ impl Castle {
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
|
||||
keep: None,
|
||||
};
|
||||
|
||||
this
|
||||
@ -231,7 +210,7 @@ impl Castle {
|
||||
}
|
||||
}
|
||||
|
||||
let (wall_dist, wall_pos, wall_alt, wall_ori, towers) = (0..self.towers.len())
|
||||
let (wall_dist, wall_pos, wall_alt, wall_ori, _towers) = (0..self.towers.len())
|
||||
.map(|i| {
|
||||
let tower0 = &self.towers[i];
|
||||
let tower1 = &self.towers[(i + 1) % self.towers.len()];
|
||||
@ -273,7 +252,6 @@ impl Castle {
|
||||
.min_by_key(|x| x.0)
|
||||
.unwrap();
|
||||
let border_pos = (wall_pos - rpos).map(|e| e.abs());
|
||||
let wall_normal = (rpos - wall_pos).map(|e| e as f32);
|
||||
let wall_rpos = if wall_ori == Ori::East {
|
||||
rpos
|
||||
} else {
|
||||
@ -428,10 +406,10 @@ impl Castle {
|
||||
#[allow(clippy::or_fun_call)] // TODO: Pending review in #587
|
||||
pub fn apply_supplement<'a>(
|
||||
&'a self,
|
||||
rng: &mut impl Rng,
|
||||
wpos2d: Vec2<i32>,
|
||||
_rng: &mut impl Rng,
|
||||
_wpos2d: Vec2<i32>,
|
||||
_get_column: impl FnMut(Vec2<i32>) -> Option<&'a ColumnSample<'a>>,
|
||||
supplement: &mut ChunkSupplement,
|
||||
_supplement: &mut ChunkSupplement,
|
||||
) {
|
||||
// TODO
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ impl Economy {
|
||||
}
|
||||
|
||||
pub fn replenish(&mut self, time: f32) {
|
||||
use rand::Rng;
|
||||
//use rand::Rng;
|
||||
for (i, (g, v)) in [
|
||||
(Wheat, 50.0),
|
||||
(Logs, 20.0),
|
||||
|
@ -14,10 +14,9 @@ use crate::column::ColumnSample;
|
||||
use common::{
|
||||
generation::ChunkSupplement,
|
||||
terrain::Block,
|
||||
vol::{BaseVol, ReadVol, RectSizedVol, Vox, WriteVol},
|
||||
vol::{BaseVol, ReadVol, RectSizedVol, WriteVol},
|
||||
};
|
||||
use rand::Rng;
|
||||
use std::{fmt, sync::Arc};
|
||||
use vek::*;
|
||||
|
||||
pub struct SpawnRules {
|
||||
|
@ -122,7 +122,7 @@ pub struct Attr {
|
||||
}
|
||||
|
||||
impl Attr {
|
||||
pub fn generate<R: Rng>(rng: &mut R, locus: i32) -> Self {
|
||||
pub fn generate<R: Rng>(rng: &mut R, _locus: i32) -> Self {
|
||||
Self {
|
||||
central_supports: rng.gen(),
|
||||
storey_fill: match rng.gen_range(0, 2) {
|
||||
@ -222,14 +222,14 @@ impl Archetype for House {
|
||||
#[allow(clippy::int_plus_one)] // TODO: Pending review in #587
|
||||
fn draw(
|
||||
&self,
|
||||
pos: Vec3<i32>,
|
||||
_pos: Vec3<i32>,
|
||||
dist: i32,
|
||||
bound_offset: Vec2<i32>,
|
||||
center_offset: Vec2<i32>,
|
||||
z: i32,
|
||||
ori: Ori,
|
||||
locus: i32,
|
||||
len: i32,
|
||||
_len: i32,
|
||||
attr: &Self::Attr,
|
||||
) -> BlockMask {
|
||||
let profile = Vec2::new(bound_offset.x, z);
|
||||
@ -521,7 +521,7 @@ impl Archetype for House {
|
||||
{
|
||||
let ornament = match self.noise.get(Vec3::new(center_offset.x, center_offset.y, z + 100)) % 4 {
|
||||
0 => BlockKind::HangingSign,
|
||||
1 | 2 => BlockKind::HangingBasket,
|
||||
1 | 2 | 3 => BlockKind::HangingBasket,
|
||||
_ => BlockKind::DungeonWallDecor,
|
||||
};
|
||||
|
||||
|
@ -82,13 +82,13 @@ impl Archetype for Keep {
|
||||
fn draw(
|
||||
&self,
|
||||
pos: Vec3<i32>,
|
||||
dist: i32,
|
||||
_dist: i32,
|
||||
bound_offset: Vec2<i32>,
|
||||
center_offset: Vec2<i32>,
|
||||
z: i32,
|
||||
ori: Ori,
|
||||
locus: i32,
|
||||
len: i32,
|
||||
_len: i32,
|
||||
attr: &Self::Attr,
|
||||
) -> BlockMask {
|
||||
let profile = Vec2::new(bound_offset.x, z);
|
||||
|
@ -640,8 +640,8 @@ impl Settlement {
|
||||
Some(Plot::Dirt) => Some(Rgb::new(90, 70, 50)),
|
||||
Some(Plot::Grass) => Some(Rgb::new(100, 200, 0)),
|
||||
Some(Plot::Water) => Some(Rgb::new(100, 150, 250)),
|
||||
Some(Plot::Town { district }) => None,
|
||||
Some(Plot::Town { district }) => {
|
||||
//Some(Plot::Town { district }) => None,
|
||||
Some(Plot::Town { .. }) => {
|
||||
if let Some((_, path_nearest, _, _)) = col_sample.path {
|
||||
let path_dir = (path_nearest - wpos2d.map(|e| e as f32))
|
||||
.rotated_z(f32::consts::PI / 2.0)
|
||||
@ -662,7 +662,7 @@ impl Settlement {
|
||||
}
|
||||
}
|
||||
|
||||
Some(Rgb::new(100, 90, 75).map2(Rgb::iota(), |e: u8, i: i32| {
|
||||
Some(Rgb::new(100, 105, 75).map2(Rgb::iota(), |e: u8, i: i32| {
|
||||
e.saturating_add(
|
||||
(self.noise.get(Vec3::new(wpos2d.x, wpos2d.y, i * 5)) % 1)
|
||||
as u8,
|
||||
@ -744,7 +744,7 @@ impl Settlement {
|
||||
{
|
||||
let diff = (surface_z - land_surface_z).abs();
|
||||
|
||||
for z in -8 - diff..3 + diff {
|
||||
for z in -8 - diff..4 + diff {
|
||||
let pos = Vec3::new(offs.x, offs.y, surface_z + z);
|
||||
let block = vol.get(pos).ok().copied().unwrap_or(Block::empty());
|
||||
|
||||
@ -1162,6 +1162,7 @@ impl Land {
|
||||
self.tiles.get(&pos).map(|tile| self.plots.get(tile.plot))
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn plot_at_mut(&mut self, pos: Vec2<i32>) -> Option<&mut Plot> {
|
||||
self.tiles
|
||||
.get(&pos)
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::{GenCtx, AREA_SIZE};
|
||||
use common::store::{Id, Store};
|
||||
use common::store::Store;
|
||||
use rand::prelude::*;
|
||||
use vek::*;
|
||||
|
||||
|
@ -20,7 +20,7 @@ pub use self::{
|
||||
unit_chooser::UnitChooser,
|
||||
};
|
||||
|
||||
use fxhash::{FxHasher32, FxHasher64};
|
||||
use fxhash::FxHasher32;
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use std::hash::BuildHasherDefault;
|
||||
use vek::*;
|
||||
|
Loading…
Reference in New Issue
Block a user