# HG changeset patch # User alfadur # Date 1643244673 -10800 # Node ID 44b49f255e3122e18f4655af3a66b26c9ce61bf4 # Parent 64b0a5cead86109113a2a645058542c1f0ec1f03 add type safe power of two sizes diff -r 64b0a5cead86 -r 44b49f255e31 rust/hwphysics/src/collision.rs --- a/rust/hwphysics/src/collision.rs Tue Jan 25 23:46:11 2022 +0300 +++ b/rust/hwphysics/src/collision.rs Thu Jan 27 03:51:13 2022 +0300 @@ -3,7 +3,7 @@ use crate::{common::GearId, data::GearDataManager, grid::Grid}; use fpnum::*; -use integral_geometry::{Point, Size}; +use integral_geometry::{Point, PotSize}; use land2d::Land2D; pub fn fppoint_round(point: &FPPoint) -> Point { @@ -105,7 +105,7 @@ data.register::(); } - pub fn new(size: Size) -> Self { + pub fn new(size: PotSize) -> Self { Self { grid: Grid::new(size), enabled_collisions: EnabledCollisionsCollection::new(), diff -r 64b0a5cead86 -r 44b49f255e31 rust/hwphysics/src/grid.rs --- a/rust/hwphysics/src/grid.rs Tue Jan 25 23:46:11 2022 +0300 +++ b/rust/hwphysics/src/grid.rs Thu Jan 27 03:51:13 2022 +0300 @@ -4,7 +4,7 @@ }; use fpnum::FPPoint; -use integral_geometry::{GridIndex, Point, Size}; +use integral_geometry::{GridIndex, Point, PotSize}; struct GridBin { refs: Vec, @@ -39,35 +39,41 @@ pub struct Grid { bins: Vec, - space_size: Size, - bins_count: Size, + space_size: PotSize, + bins_count: PotSize, index: GridIndex, } impl Grid { - pub fn new(size: Size) -> Self { - assert!(size.is_power_of_two()); - let bins_count = Size::new(size.width / GRID_BIN_SIZE, size.height / GRID_BIN_SIZE); + pub fn new(size: PotSize) -> Self { + let bins_count = + PotSize::new(size.width() / GRID_BIN_SIZE, size.height() / GRID_BIN_SIZE).unwrap(); Self { bins: (0..bins_count.area()).map(|_| GridBin::new()).collect(), space_size: size, bins_count, - index: Size::square(GRID_BIN_SIZE).to_grid_index(), + index: PotSize::square(GRID_BIN_SIZE).unwrap().to_grid_index(), } } + fn linear_bin_index(&self, index: Point) -> usize { + self.bins_count + .linear_index(index.x as usize, index.y as usize) + } + fn bin_index(&self, position: &FPPoint) -> Point { self.index.map(fppoint_round(position)) } fn get_bin(&mut self, index: Point) -> &mut GridBin { - &mut self.bins[index.y as usize * self.bins_count.width + index.x as usize] + let index = self.linear_bin_index(index); + &mut self.bins[index] } fn try_get_bin(&mut self, index: Point) -> Option<&mut GridBin> { - self.bins - .get_mut(index.y as usize * self.bins_count.width + index.x as usize) + let index = self.linear_bin_index(index); + self.bins.get_mut(index) } fn lookup_bin(&mut self, position: &FPPoint) -> &mut GridBin { @@ -94,14 +100,11 @@ } else { self.remove_all(gear_id); } - } pub fn check_collisions(&self, collisions: &mut DetectedCollisions) { for bin in &self.bins { - for (index, bounds) in bin.entries.iter().enumerate() { - - } + for (index, bounds) in bin.entries.iter().enumerate() {} } } } diff -r 64b0a5cead86 -r 44b49f255e31 rust/hwphysics/src/lib.rs --- a/rust/hwphysics/src/lib.rs Tue Jan 25 23:46:11 2022 +0300 +++ b/rust/hwphysics/src/lib.rs Thu Jan 27 03:51:13 2022 +0300 @@ -4,7 +4,7 @@ mod grid; pub mod physics; -use integral_geometry::Size; +use integral_geometry::PotSize; use land2d::Land2D; use crate::{ @@ -22,7 +22,7 @@ } impl World { - pub fn new(world_size: Size) -> Self { + pub fn new(world_size: PotSize) -> Self { let mut data = GearDataManager::new(); PhysicsProcessor::register_components(&mut data); CollisionProcessor::register_components(&mut data); @@ -72,12 +72,12 @@ World, }; use fpnum::{fp, FPNum, FPPoint}; - use integral_geometry::Size; + use integral_geometry::PotSize; use land2d::Land2D; #[test] fn data_flow() { - let world_size = Size::new(2048, 2048); + let world_size = PotSize::new(2048, 2048).unwrap; let mut world = World::new(world_size); let gear_id = world.new_gear().unwrap(); diff -r 64b0a5cead86 -r 44b49f255e31 rust/hwphysics/src/physics.rs --- a/rust/hwphysics/src/physics.rs Tue Jan 25 23:46:11 2022 +0300 +++ b/rust/hwphysics/src/physics.rs Thu Jan 27 03:51:13 2022 +0300 @@ -67,11 +67,7 @@ } } - pub fn process( - &mut self, - data: &mut GearDataManager, - time_step: Millis, - ) -> &PositionUpdates { + pub fn process(&mut self, data: &mut GearDataManager, time_step: Millis) -> &PositionUpdates { if time_step == Millis::new(1) { self.process_impl::(data, time_step) } else { diff -r 64b0a5cead86 -r 44b49f255e31 rust/integral-geometry/src/lib.rs --- a/rust/integral-geometry/src/lib.rs Tue Jan 25 23:46:11 2022 +0300 +++ b/rust/integral-geometry/src/lib.rs Thu Jan 27 03:51:13 2022 +0300 @@ -141,11 +141,16 @@ } #[inline] - pub fn next_power_of_two(&self) -> Self { - Self { - width: self.width.next_power_of_two(), - height: self.height.next_power_of_two(), - } + pub const fn as_power_of_two(&self) -> Option { + PotSize::new(self.width, self.height) + } + + #[inline] + pub const fn next_power_of_two(&self) -> PotSize { + PotSize::new_impl( + self.width.next_power_of_two(), + self.height.next_power_of_two(), + ) } #[inline] @@ -154,19 +159,10 @@ } #[inline] - pub fn to_mask(&self) -> SizeMask { - SizeMask::new(*self) - } - - #[inline] pub fn to_square(&self) -> Self { Self::square(max(self.width, self.height)) } - pub fn to_grid_index(&self) -> GridIndex { - GridIndex::new(*self) - } - #[inline] pub const fn contains(&self, other: Self) -> bool { self.width >= other.width && self.height >= other.height @@ -174,11 +170,96 @@ #[inline] pub fn join(&self, other: Self) -> Self { + Self::new(max(self.width, other.width), max(self.height, other.height)) + } +} + +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct PotSize { + size: Size, +} + +impl PotSize { + #[inline] + const fn new_impl(width: usize, height: usize) -> Self { + debug_assert!(width.is_power_of_two() && height.is_power_of_two()); Self { - width: max(self.width, other.width), - height: max(self.height, other.height) + size: Size::new(width, height), + } + } + + #[inline] + pub const fn new(width: usize, height: usize) -> Option { + if width.is_power_of_two() && height.is_power_of_two() { + Some(Self::new_impl(width, height)) + } else { + None + } + } + + pub const fn size(&self) -> Size { + self.size + } + + pub const fn width(&self) -> usize { + self.size.width + } + + pub const fn height(&self) -> usize { + self.size.height + } + + #[inline] + pub const fn square(size: usize) -> Option { + if size.is_power_of_two() { + Some(Self::new_impl(size, size)) + } else { + None } } + + #[inline] + pub const fn area(&self) -> usize { + self.size.area() + } + + #[inline] + pub const fn linear_index(&self, x: usize, y: usize) -> usize { + self.size.linear_index(x, y) + } + + #[inline] + pub const fn transpose(&self) -> Self { + Self::new_impl(self.height(), self.width()) + } + + #[inline] + pub fn to_square(&self) -> Self { + let size = max(self.width(), self.height()); + Self::new_impl(size, size) + } + + #[inline] + pub const fn to_mask(&self) -> SizeMask { + SizeMask::new(*self) + } + + pub const fn to_grid_index(&self) -> GridIndex { + GridIndex::new(*self) + } + + #[inline] + pub const fn contains(&self, other: Self) -> bool { + self.size.contains(other.size) + } + + #[inline] + pub fn join(&self, other: Self) -> Self { + Self::new_impl( + max(self.width(), other.width()), + max(self.height(), other.height()), + ) + } } #[derive(PartialEq, Eq, Clone, Copy, Debug)] @@ -188,13 +269,10 @@ impl SizeMask { #[inline] - pub fn new(size: Size) -> Self { - debug_assert!(size.is_power_of_two()); - let size = Size { - width: !(size.width - 1), - height: !(size.height - 1), - }; - Self { size } + pub const fn new(size: PotSize) -> Self { + Self { + size: Size::new(!(size.width() - 1), !(size.height() - 1)), + } } #[inline] @@ -211,6 +289,11 @@ pub fn contains(&self, point: Point) -> bool { self.contains_x(point.x as usize) && self.contains_y(point.y as usize) } + + #[inline] + pub const fn to_size(&self) -> PotSize { + PotSize::new_impl(!self.size.width + 1, !self.size.height + 1) + } } pub struct GridIndex { @@ -218,11 +301,10 @@ } impl GridIndex { - pub fn new(size: Size) -> Self { - debug_assert!(size.is_power_of_two()); + pub const fn new(size: PotSize) -> Self { let shift = Point::new( - size.width.trailing_zeros() as i32, - size.height.trailing_zeros() as i32, + size.width().trailing_zeros() as i32, + size.height().trailing_zeros() as i32, ); Self { shift } } @@ -324,7 +406,7 @@ }; #[inline] - pub fn new(top_left: Point, bottom_right: Point) -> Self { + pub const fn new(top_left: Point, bottom_right: Point) -> Self { debug_assert!(top_left.x <= bottom_right.x + 1); debug_assert!(top_left.y <= bottom_right.y + 1); Self { @@ -333,7 +415,7 @@ } } - pub fn from_box(left: i32, right: i32, top: i32, bottom: i32) -> Self { + pub const fn from_box(left: i32, right: i32, top: i32, bottom: i32) -> Self { Self::new(Point::new(left, top), Point::new(right, bottom)) } @@ -450,7 +532,7 @@ } #[inline] - pub fn split_at(&self, point: Point) -> [Rect; 4] { + pub const fn split_at(&self, point: Point) -> [Rect; 4] { debug_assert!(self.contains_inside(point)); [ Self::from_box(self.left(), point.x, self.top(), point.y), @@ -461,7 +543,7 @@ } #[inline] - pub fn with_margins(&self, left: i32, right: i32, top: i32, bottom: i32) -> Self { + pub const fn with_margins(&self, left: i32, right: i32, top: i32, bottom: i32) -> Self { Self::from_box( self.left() - left, self.right() + right, diff -r 64b0a5cead86 -r 44b49f255e31 rust/land2d/src/lib.rs --- a/rust/land2d/src/lib.rs Tue Jan 25 23:46:11 2022 +0300 +++ b/rust/land2d/src/lib.rs Thu Jan 27 03:51:13 2022 +0300 @@ -1,9 +1,6 @@ -use std::{ - cmp, - ops::Index -}; +use std::{cmp, ops::Index}; -use integral_geometry::{ArcPoints, EquidistantPoints, Line, Point, Rect, Size, SizeMask}; +use integral_geometry::{ArcPoints, EquidistantPoints, Line, Point, PotSize, Rect, Size, SizeMask}; pub struct Land2D { pixels: vec2d::Vec2D, @@ -15,13 +12,13 @@ pub fn new(play_size: Size, fill_value: T) -> Self { let real_size = play_size.next_power_of_two(); let top_left = Point::new( - ((real_size.width - play_size.width) / 2) as i32, - (real_size.height - play_size.height) as i32, + ((real_size.width() - play_size.width) / 2) as i32, + (real_size.height() - play_size.height) as i32, ); let play_box = Rect::from_size(top_left, play_size); Self { play_box, - pixels: vec2d::Vec2D::new(real_size, fill_value), + pixels: vec2d::Vec2D::new(real_size.size(), fill_value), mask: real_size.to_mask(), } } @@ -31,9 +28,7 @@ } pub fn raw_pixel_bytes(&self) -> &[u8] { - unsafe { - self.pixels.as_bytes() - } + unsafe { self.pixels.as_bytes() } } #[inline] @@ -47,8 +42,8 @@ } #[inline] - pub fn size(&self) -> Size { - self.pixels.size() + pub fn size(&self) -> PotSize { + self.mask.to_size() } #[inline] @@ -117,7 +112,8 @@ *v = value; 1 }) - }).count() + }) + .count() } pub fn draw_line(&mut self, line: Line, value: T) -> usize { @@ -149,31 +145,34 @@ let start_x_l = (start_point.x - 1) as usize; let start_x_r = start_point.x as usize; for dir in [-1, 1].iter().cloned() { - push(mask, &mut stack, start_x_l, start_x_r, start_point.y as usize, dir); + push( + mask, + &mut stack, + start_x_l, + start_x_r, + start_point.y as usize, + dir, + ); } while let Some((mut xl, mut xr, y, dir)) = stack.pop() { let row = &mut self.pixels[y][..]; - while xl > 0 && row[xl] != border_value && row[xl] != fill_value - { + while xl > 0 && row[xl] != border_value && row[xl] != fill_value { xl -= 1; } - while xr < width - 1 && row[xr] != border_value && row[xr] != fill_value - { + while xr < width - 1 && row[xr] != border_value && row[xr] != fill_value { xr += 1; } while xl < xr { - while xl <= xr && (row[xl] == border_value || row[xl] == fill_value) - { + while xl <= xr && (row[xl] == border_value || row[xl] == fill_value) { xl += 1; } let x = xl; - while xl <= xr && row[xl] != border_value && row[xl] != fill_value - { + while xl <= xr && row[xl] != border_value && row[xl] != fill_value { row[xl] = fill_value; xl += 1; } @@ -257,7 +256,8 @@ .iter() .map(|m| self.fill_row(center, vector.transform(m), value)) .sum::() - }).sum() + }) + .sum() } pub fn draw_thick_line(&mut self, line: Line, radius: i32, value: T) -> usize { diff -r 64b0a5cead86 -r 44b49f255e31 rust/land_dump/src/main.rs --- a/rust/land_dump/src/main.rs Tue Jan 25 23:46:11 2022 +0300 +++ b/rust/land_dump/src/main.rs Thu Jan 27 03:51:13 2022 +0300 @@ -2,23 +2,21 @@ use std::{ fs::File, io::{BufWriter, Read}, - path::{Path, PathBuf} + path::{Path, PathBuf}, }; use structopt::StructOpt; use integral_geometry::{Point, Rect, Size}; +use land2d::Land2D; use landgen::{ - outline_template::OutlineTemplate, - template_based::TemplatedLandGenerator, - LandGenerationParameters, - LandGenerator -}; -use mapgen::{ - MapGenerator, - theme::{Theme, slice_u32_to_u8} + outline_template::OutlineTemplate, template_based::TemplatedLandGenerator, + LandGenerationParameters, LandGenerator, }; use lfprng::LaggedFibonacciPRNG; -use land2d::Land2D; +use mapgen::{ + theme::{slice_u32_to_u8, Theme}, + MapGenerator, +}; #[derive(StructOpt, Debug)] #[structopt(name = "basic")] @@ -36,7 +34,7 @@ #[structopt(short = "t", long = "template-type")] template_type: Option, #[structopt(short = "z", long = "theme-dir")] - theme_dir: Option + theme_dir: Option, } fn template() -> OutlineTemplate { @@ -60,7 +58,8 @@ skip_bezier: bool, file_name: &Path, ) -> std::io::Result> { - let params = LandGenerationParameters::new(0 as u8, 255, distance_divisor, skip_distort, skip_bezier); + let params = + LandGenerationParameters::new(0 as u8, 255, distance_divisor, skip_distort, skip_bezier); let landgen = TemplatedLandGenerator::new(template.clone()); let mut prng = LaggedFibonacciPRNG::new(seed); let land = landgen.generate_land(¶ms, &mut prng); @@ -87,40 +86,39 @@ let ref mut w = BufWriter::new(file); let mut encoder = png::Encoder::new(w, land.width() as u32, land.height() as u32); // Width is 2 pixels and height is 1. - encoder - .set(png::ColorType::RGBA) - .set(png::BitDepth::Eight); + encoder.set(png::ColorType::RGBA).set(png::BitDepth::Eight); let mut writer = encoder.write_header().unwrap(); - writer.write_image_data(slice_u32_to_u8(texture.as_slice())).unwrap(); + writer + .write_image_data(slice_u32_to_u8(texture.as_slice())) + .unwrap(); } fn main() { let opt = Opt::from_args(); println!("{:?}", opt); - let template = - if let Some(path) = opt.templates_file { - let mut result = String::new(); - File::open(path) - .expect("Unable to read templates file") - .read_to_string(&mut result); + let template = if let Some(path) = opt.templates_file { + let mut result = String::new(); + File::open(path) + .expect("Unable to read templates file") + .read_to_string(&mut result); - let mut generator = MapGenerator::new(); + let mut generator = MapGenerator::new(); - let source = &result[..]; + let source = &result[..]; - generator.import_yaml_templates(source); + generator.import_yaml_templates(source); - let template_type = &opt.template_type - .expect("No template type specified"); - generator.get_template(template_type) - .expect(&format!("Template type {} not found", template_type)) - .clone() - } else { - template() - }; + let template_type = &opt.template_type.expect("No template type specified"); + generator + .get_template(template_type) + .expect(&format!("Template type {} not found", template_type)) + .clone() + } else { + template() + }; if opt.dump_before_distort { dump( @@ -155,10 +153,6 @@ .unwrap(); if let Some(dir) = opt.theme_dir { - texturize( - &Path::new(&dir), - &land, - &Path::new("out.texture.png") - ); + texturize(&Path::new(&dir), &land, &Path::new("out.texture.png")); } } diff -r 64b0a5cead86 -r 44b49f255e31 rust/landgen/src/lib.rs --- a/rust/landgen/src/lib.rs Tue Jan 25 23:46:11 2022 +0300 +++ b/rust/landgen/src/lib.rs Thu Jan 27 03:51:13 2022 +0300 @@ -11,7 +11,13 @@ } impl LandGenerationParameters { - pub fn new(zero: T, basic: T, distance_divisor: u32, skip_distort: bool, skip_bezier: bool) -> Self { + pub fn new( + zero: T, + basic: T, + distance_divisor: u32, + skip_distort: bool, + skip_bezier: bool, + ) -> Self { Self { zero, basic, diff -r 64b0a5cead86 -r 44b49f255e31 rust/landgen/src/outline.rs --- a/rust/landgen/src/outline.rs Tue Jan 25 23:46:11 2022 +0300 +++ b/rust/landgen/src/outline.rs Thu Jan 27 03:51:13 2022 +0300 @@ -1,7 +1,7 @@ use itertools::Itertools; use std::cmp::min; -use integral_geometry::{Line, Ray, Point, Polygon, Rect, Size}; +use integral_geometry::{Line, Point, Polygon, Ray, Rect, Size}; use land2d::Land2D; use crate::outline_template::OutlineTemplate; @@ -76,16 +76,14 @@ fn solve_intersection( intersections_box: &Rect, ray: &Ray, - edge: &Line - ) -> Option<(i32, u32)> - { + edge: &Line, + ) -> Option<(i32, u32)> { let edge_dir = edge.scaled_direction(); let aqpb = ray.direction.cross(edge_dir) as i64; if aqpb != 0 { - let mut iy = - ((((edge.start.x - ray.start.x) as i64 * ray.direction.y as i64 - + ray.start.y as i64 * ray.direction.x as i64) + let mut iy = ((((edge.start.x - ray.start.x) as i64 * ray.direction.y as i64 + + ray.start.y as i64 * ray.direction.x as i64) * edge_dir.y as i64 - edge.start.y as i64 * edge_dir.x as i64 * ray.direction.y as i64) / aqpb) as i32; @@ -147,7 +145,7 @@ // same for the right border let right_intersection = Point::new( map_box.right(), - mid_point.y + normal.tangent_mul(map_box.right() - mid_point.x) , + mid_point.y + normal.tangent_mul(map_box.right() - mid_point.x), ); dist_right = (mid_point - right_intersection).integral_norm(); @@ -203,7 +201,9 @@ if intersects(&pi.ray_with_dir(normal), &segment) { // ray from segment.start if let Some((t, d)) = solve_intersection( - &self.intersections_box, &normal_ray, &segment.start.line_to(pi), + &self.intersections_box, + &normal_ray, + &segment.start.line_to(pi), ) { if t > 0 { dist_right = min(dist_right, d); @@ -214,7 +214,9 @@ // ray from segment.end if let Some((t, d)) = solve_intersection( - &self.intersections_box, &normal_ray, &segment.end.line_to(pi) + &self.intersections_box, + &normal_ray, + &segment.end.line_to(pi), ) { if t > 0 { dist_right = min(dist_right, d); diff -r 64b0a5cead86 -r 44b49f255e31 rust/landgen/src/template_based.rs --- a/rust/landgen/src/template_based.rs Tue Jan 25 23:46:11 2022 +0300 +++ b/rust/landgen/src/template_based.rs Thu Jan 27 03:51:13 2022 +0300 @@ -1,11 +1,9 @@ +use crate::{ + outline::OutlinePoints, outline_template::OutlineTemplate, LandGenerationParameters, + LandGenerator, +}; use integral_geometry::{Point, Size}; use land2d::Land2D; -use crate::{ - LandGenerationParameters, - LandGenerator, - outline::OutlinePoints, - outline_template::OutlineTemplate -}; pub struct TemplatedLandGenerator { outline_template: OutlineTemplate, @@ -28,7 +26,7 @@ let mut points = OutlinePoints::from_outline_template( &self.outline_template, land.play_box(), - land.size(), + land.size().size(), random_numbers, ); diff -r 64b0a5cead86 -r 44b49f255e31 rust/lib-hedgewars-engine/src/render/atlas.rs --- a/rust/lib-hedgewars-engine/src/render/atlas.rs Tue Jan 25 23:46:11 2022 +0300 +++ b/rust/lib-hedgewars-engine/src/render/atlas.rs Thu Jan 27 03:51:13 2022 +0300 @@ -14,8 +14,8 @@ impl Fit { fn new() -> Self { Self { - short_side: u32::max_value(), - long_side: u32::max_value(), + short_side: u32::MAX, + long_side: u32::MAX, } } diff -r 64b0a5cead86 -r 44b49f255e31 rust/lib-hedgewars-engine/src/time.rs --- a/rust/lib-hedgewars-engine/src/time.rs Tue Jan 25 23:46:11 2022 +0300 +++ b/rust/lib-hedgewars-engine/src/time.rs Thu Jan 27 03:51:13 2022 +0300 @@ -1,8 +1,8 @@ +use hwphysics::common::{GearId, Millis}; use std::{ cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}, collections::BinaryHeap, }; -use hwphysics::common::{GearId, Millis}; pub type EventId = u16; diff -r 64b0a5cead86 -r 44b49f255e31 rust/lib-hedgewars-engine/src/world.rs --- a/rust/lib-hedgewars-engine/src/world.rs Tue Jan 25 23:46:11 2022 +0300 +++ b/rust/lib-hedgewars-engine/src/world.rs Thu Jan 27 03:51:13 2022 +0300 @@ -100,7 +100,7 @@ // based on old engine min_distance... dunno if this is the correct place tho let distance_divisor = (self.feature_size as u32).pow(2) / 8 + 10; - let params = LandGenerationParameters::new(0u8, u8::max_value(), distance_divisor, false, false); + let params = LandGenerationParameters::new(0u8, u8::MAX, distance_divisor, false, false); let landgen = TemplatedLandGenerator::new(template()); self.preview = Some(landgen.generate_land(¶ms, &mut self.random_numbers_gen)); } @@ -110,12 +110,12 @@ } pub fn init(&mut self, template: OutlineTemplate) { - let physics = hwp::World::new(template.size); - - let params = LandGenerationParameters::new(0u32, u32::max_value(), 5, false, false); + let params = LandGenerationParameters::new(0u32, u32::MAX, 5, false, false); let landgen = TemplatedLandGenerator::new(template); let land = landgen.generate_land(¶ms, &mut self.random_numbers_gen); + let physics = hwp::World::new(land.size()); + self.game_state = Some(GameState::new(land, physics)); } diff -r 64b0a5cead86 -r 44b49f255e31 rust/mapgen/src/lib.rs --- a/rust/mapgen/src/lib.rs Tue Jan 25 23:46:11 2022 +0300 +++ b/rust/mapgen/src/lib.rs Thu Jan 27 03:51:13 2022 +0300 @@ -121,7 +121,7 @@ where LandT: Copy + Default + PartialEq, { - let mut texture = Vec2D::new(land.size(), 0); + let mut texture = Vec2D::new(land.size().size(), 0); if let Some(land_sprite) = theme.land_texture() { for (row_index, (land_row, tex_row)) in land.rows().zip(texture.rows_mut()).enumerate()