1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
use std::collections::{HashSet};
use specs::{
ReadStorage,
Read,
Write,
System,
Join,
Entities
};
use crate::{Pos, Sprite};
use crate::components::{Visible, Player, Position, Inventory, New, Moved, Removed, Health};
use crate::resources::{Size, Output, Ground};
use crate::worldmessages::{WorldMessage, FieldMessage};
#[derive(Default)]
pub struct View;
impl <'a> System<'a> for View {
type SystemData = (
Entities<'a>,
ReadStorage<'a, Position>,
ReadStorage<'a, Inventory>,
ReadStorage<'a, Health>,
ReadStorage<'a, Visible>,
Read<'a, Size>,
ReadStorage<'a, Player>,
Write<'a, Output>,
ReadStorage<'a, New>,
ReadStorage<'a, Moved>,
ReadStorage<'a, Removed>,
Read<'a, Ground>
);
fn run(&mut self, (entities, positions, inventories, healths, visible, size, players, mut output, new, moved, removed, ground): Self::SystemData) {
let mut changed = HashSet::new();
for (pos, _new) in (&positions, &new).join() {
changed.insert(pos.pos);
}
for (pos, mov) in (&positions, &moved).join() {
changed.insert(pos.pos);
changed.insert(mov.from);
}
for (pos, _removed) in (&positions, &removed).join() {
changed.insert(pos.pos);
}
let has_changed: bool = !changed.is_empty();
let mut changes: Vec<(Pos, Vec<Sprite>)> = Vec::new();
for pos in changed {
changes.push((pos, cell_sprites(ground.components_on(pos, &visible))));
}
output.output.clear();
for (ent, player, pos) in (&entities, &players, &positions).join() {
let mut updates = WorldMessage::default();
if new.get(ent).is_some() {
let (values, mapping) = draw_room(&ground, (size.width, size.height), &visible);
let field = FieldMessage{
width: size.width,
height: size.height,
field: values,
mapping
};
updates.field = Some(field);
} else if has_changed {
updates.change = Some(changes.clone());
}
if let Some(inventory) = inventories.get(ent){
updates.inventory = Some(inventory.items.iter().map(|item| item.name.clone()).collect());
}
if let Some(health) = healths.get(ent){
updates.health = Some((health.health, health.maxhealth));
}
updates.ground = Some(
ground
.by_height(&pos.pos, &visible, &ent)
.into_iter()
.map(|ent| visible.get(ent).unwrap().name.clone())
.collect()
);
updates.pos = Some(pos.pos);
if !updates.is_empty() {
output.output.insert(player.id.clone(), updates);
}
}
}
}
fn cell_sprites(mut visibles: Vec<&Visible>) -> Vec<Sprite> {
visibles.sort_by(|a, b| b.height.partial_cmp(&a.height).unwrap());
visibles.iter().map(|vis| vis.sprite.clone()).collect()
}
fn draw_room(ground: &Read<Ground>, (width, height): (i64, i64), visible: &ReadStorage<Visible>) -> (Vec<usize>, Vec<Vec<Sprite>>){
let size = width * height;
let mut values :Vec<usize> = Vec::with_capacity(size as usize);
let mut mapping: Vec<Vec<Sprite>> = Vec::new();
for y in 0..height {
for x in 0..width {
let sprites: Vec<Sprite> = cell_sprites(ground.components_on(Pos{x, y}, visible));
values.push(
match mapping.iter().position(|x| x == &sprites) {
Some(index) => {
index
}
None => {
mapping.push(sprites);
mapping.len() - 1
}
}
)
}
}
(values, mapping)
}
|