Skip to content

Commit a623cff

Browse files
committed
Refactor building storage
1 parent 5a3d42d commit a623cff

File tree

4 files changed

+78
-69
lines changed

4 files changed

+78
-69
lines changed

src/logic/vm/buildings.rs

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::rc::Rc;
1+
use std::{cell::RefCell, rc::Rc};
22

33
use strum_macros::IntoStaticStr;
44

@@ -32,14 +32,31 @@ const MESSAGE_MAX_LINES: usize = 24;
3232
pub struct Building {
3333
pub block: &'static Block,
3434
pub position: Point2,
35-
pub data: BuildingData,
35+
pub data: Rc<RefCell<BuildingData>>,
3636
}
3737

3838
impl Building {
39-
pub fn new(name: &str, position: Point2, config: &Object, vm: &LogicVM) -> VMLoadResult<Self> {
39+
pub fn new(name: &str, position: Point2, data: BuildingData) -> VMLoadResult<Self> {
40+
let block = *content::blocks::FROM_NAME
41+
.get(name)
42+
.ok_or_else(|| VMLoadError::UnknownBlockType(name.to_string()))?;
43+
44+
Ok(Self {
45+
block,
46+
position,
47+
data: Rc::new(RefCell::new(data)),
48+
})
49+
}
50+
51+
pub fn from_config(
52+
name: &str,
53+
position: Point2,
54+
config: &Object,
55+
vm: &LogicVM,
56+
) -> VMLoadResult<Self> {
4057
let data = match name {
4158
MICRO_PROCESSOR | LOGIC_PROCESSOR | HYPER_PROCESSOR | WORLD_PROCESSOR => {
42-
return Self::new_processor(
59+
return Self::from_processor_config(
4360
name,
4461
position,
4562
&ProcessorBuilder::parse_config(config)?,
@@ -79,10 +96,10 @@ impl Building {
7996
},
8097
};
8198

82-
Self::from_data(name, position, data)
99+
Self::new(name, position, data)
83100
}
84101

85-
pub fn new_processor(
102+
pub fn from_processor_config(
86103
name: &str,
87104
position: Point2,
88105
config: &ProcessorConfig,
@@ -145,7 +162,7 @@ impl Building {
145162
}
146163
};
147164

148-
Self::from_data(name, position, data)
165+
Self::new(name, position, data)
149166
}
150167

151168
pub fn from_schematic_tile(
@@ -157,19 +174,7 @@ impl Building {
157174
}: &SchematicTile,
158175
vm: &LogicVM,
159176
) -> VMLoadResult<Self> {
160-
Self::new(name, (*position).into(), config, vm)
161-
}
162-
163-
pub fn from_data(name: &str, position: Point2, data: BuildingData) -> VMLoadResult<Self> {
164-
let block = *content::blocks::FROM_NAME
165-
.get(name)
166-
.ok_or_else(|| VMLoadError::UnknownBlockType(name.to_string()))?;
167-
168-
Ok(Self {
169-
block,
170-
position,
171-
data,
172-
})
177+
Self::from_config(name, (*position).into(), config, vm)
173178
}
174179
}
175180

src/logic/vm/instructions.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ struct Print {
192192
}
193193

194194
impl Print {
195-
fn to_string(value: &LValue) -> Cow<'_, str> {
195+
fn to_string<'a>(value: &'a LValue, vm: &LogicVM) -> Cow<'a, str> {
196196
match value {
197197
LValue::Null => Cow::from("null"),
198198
LValue::Number(n) => {
@@ -206,19 +206,22 @@ impl Print {
206206
LValue::String(s) => Cow::Borrowed(s),
207207
LValue::Content(content) => Cow::Borrowed(content.name()),
208208
LValue::Team(team) => team.name(),
209-
LValue::Building { block, .. } => Cow::Borrowed(&block.name),
209+
LValue::Building(position) => vm
210+
.building(*position)
211+
.map(|b| Cow::Borrowed(b.block.name.as_str()))
212+
.unwrap_or(Cow::from("null")),
210213
}
211214
}
212215
}
213216

214217
impl SimpleInstruction for Print {
215-
fn execute(&self, state: &mut ProcessorState, _: &LogicVM) {
218+
fn execute(&self, state: &mut ProcessorState, vm: &LogicVM) {
216219
if state.printbuffer.len() >= MAX_TEXT_BUFFER {
217220
return;
218221
}
219222

220223
let value = self.value.get(state);
221-
state.append_printbuffer(&Print::to_string(&value));
224+
state.append_printbuffer(&Print::to_string(&value, vm));
222225
}
223226
}
224227

@@ -245,7 +248,7 @@ struct Format {
245248
}
246249

247250
impl SimpleInstruction for Format {
248-
fn execute(&self, state: &mut ProcessorState, _: &LogicVM) {
251+
fn execute(&self, state: &mut ProcessorState, vm: &LogicVM) {
249252
if state.printbuffer.len() >= MAX_TEXT_BUFFER {
250253
return;
251254
}
@@ -273,7 +276,7 @@ impl SimpleInstruction for Format {
273276
let value = self.value.get(state);
274277
state.printbuffer.splice(
275278
placeholder_index..placeholder_index + 3,
276-
ProcessorState::encode_utf16(&Print::to_string(&value)),
279+
ProcessorState::encode_utf16(&Print::to_string(&value, vm)),
277280
);
278281
}
279282
}

src/logic/vm/mod.rs

Lines changed: 43 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ mod variables;
77

88
use std::{
99
borrow::Cow,
10-
cell::{Cell, RefCell},
10+
cell::Cell,
1111
collections::HashMap,
1212
rc::Rc,
1313
time::{Duration, Instant},
@@ -25,8 +25,10 @@ const MILLIS_PER_SEC: u64 = 1_000;
2525
const NANOS_PER_MILLI: u32 = 1_000_000;
2626

2727
pub struct LogicVM<'a> {
28-
buildings: HashMap<Point2, Rc<RefCell<Building>>>,
29-
processors: Vec<Rc<RefCell<Building>>>,
28+
/// Sorted with all processors first, then all other buildings.
29+
buildings: Vec<Building>,
30+
buildings_map: HashMap<Point2, usize>,
31+
total_processors: usize,
3032
running_processors: Rc<Cell<usize>>,
3133
time: Rc<Cell<f64>>,
3234
globals: Cow<'a, HashMap<String, LVar>>,
@@ -39,8 +41,9 @@ impl<'a> LogicVM<'a> {
3941

4042
pub fn new_with_globals(globals: Cow<'a, HashMap<String, LVar>>) -> Self {
4143
Self {
42-
buildings: HashMap::new(),
43-
processors: Vec::new(),
44+
buildings: Vec::new(),
45+
buildings_map: HashMap::new(),
46+
total_processors: 0,
4447
running_processors: Rc::new(Cell::new(0)),
4548
time: Rc::new(Cell::new(0.)),
4649
globals,
@@ -57,41 +60,42 @@ impl<'a> LogicVM<'a> {
5760
Ok(vm)
5861
}
5962

60-
pub fn add_building(&mut self, building: Building) -> VMLoadResult<()> {
63+
pub fn add_building(&mut self, building: Building) {
6164
let position = building.position;
6265
let size = building.block.size;
6366

64-
let building = Rc::new(RefCell::new(building));
67+
let index = if let BuildingData::Processor(processor) = &*building.data.borrow() {
68+
if processor.state.enabled() {
69+
self.running_processors.update(|n| n + 1);
70+
}
71+
self.total_processors += 1;
72+
self.total_processors - 1
73+
} else {
74+
self.buildings.len()
75+
};
76+
77+
self.buildings.insert(index, building);
6578

6679
for x in position.x..position.x + size {
6780
for y in position.y..position.y + size {
68-
self.buildings.insert(Point2 { x, y }, building.clone());
69-
}
70-
}
71-
72-
if let BuildingData::Processor(processor) = &building.borrow().data {
73-
self.processors.push(building.clone());
74-
if processor.state.enabled() {
75-
self.running_processors.update(|n| n + 1);
81+
self.buildings_map.insert(Point2 { x, y }, index);
7682
}
7783
}
78-
79-
Ok(())
8084
}
8185

82-
pub fn add_buildings<T>(&mut self, buildings: T) -> VMLoadResult<()>
86+
pub fn add_buildings<T>(&mut self, buildings: T)
8387
where
8488
T: IntoIterator<Item = Building>,
8589
{
8690
for building in buildings.into_iter() {
87-
self.add_building(building)?;
91+
self.add_building(building);
8892
}
89-
Ok(())
9093
}
9194

9295
pub fn add_schematic_tile(&mut self, tile: &SchematicTile) -> VMLoadResult<()> {
9396
let building = Building::from_schematic_tile(tile, self)?;
94-
self.add_building(building)
97+
self.add_building(building);
98+
Ok(())
9599
}
96100

97101
pub fn add_schematic_tiles(&mut self, tiles: &[SchematicTile]) -> VMLoadResult<()> {
@@ -101,6 +105,12 @@ impl<'a> LogicVM<'a> {
101105
Ok(())
102106
}
103107

108+
pub fn building(&self, position: Point2) -> Option<&Building> {
109+
self.buildings_map
110+
.get(&position)
111+
.map(|&i| &self.buildings[i])
112+
}
113+
104114
/// Run the simulation until all processors halt, or until a number of ticks are finished.
105115
/// Returns true if all processors halted, or false if the tick limit was reached.
106116
pub fn run(&mut self, max_ticks: Option<usize>) -> bool {
@@ -134,10 +144,10 @@ impl<'a> LogicVM<'a> {
134144
let time = self.time.get() + duration_millis_f64(delta).max(0.);
135145
self.time.set(time);
136146

137-
for processor in &self.processors {
147+
for processor in self.buildings.iter().take(self.total_processors) {
138148
processor
139-
.borrow_mut()
140149
.data
150+
.borrow_mut()
141151
.unwrap_processor_mut()
142152
.do_tick(self, time);
143153
}
@@ -189,23 +199,22 @@ mod tests {
189199
buildings::{HYPER_PROCESSOR, MICRO_PROCESSOR},
190200
variables::{Content, LValue, LVar},
191201
},
192-
types::{Object, PackedPoint2, ProcessorConfig, Team, colors::COLORS, content},
202+
types::{Object, PackedPoint2, ProcessorConfig, Team, colors::COLORS},
193203
};
194204

195205
use super::{buildings::WORLD_PROCESSOR, processor::Processor, *};
196206

197207
fn single_processor_vm<'a>(name: &str, code: &str) -> LogicVM<'a> {
198208
let mut vm = LogicVM::new();
199209
vm.add_building(
200-
Building::new_processor(
210+
Building::from_processor_config(
201211
name,
202212
Point2::new(0, 0),
203213
&ProcessorConfig::from_code(code),
204214
&vm,
205215
)
206216
.unwrap(),
207-
)
208-
.unwrap();
217+
);
209218
vm
210219
}
211220

@@ -216,15 +225,14 @@ mod tests {
216225
) -> LogicVM<'a> {
217226
let mut vm = LogicVM::new_with_globals(Cow::Borrowed(globals));
218227
vm.add_building(
219-
Building::new_processor(
228+
Building::from_processor_config(
220229
name,
221230
Point2::new(0, 0),
222231
&ProcessorConfig::from_code(code),
223232
&vm,
224233
)
225234
.unwrap(),
226-
)
227-
.unwrap();
235+
);
228236
vm
229237
}
230238

@@ -239,19 +247,15 @@ mod tests {
239247
}
240248

241249
fn with_processor(vm: &mut LogicVM, idx: usize, f: impl FnOnce(&mut Processor)) {
242-
f(vm.processors[idx].borrow_mut().data.unwrap_processor_mut())
250+
f(vm.buildings[idx].data.borrow_mut().unwrap_processor_mut())
243251
}
244252

245253
fn take_processor(vm: &mut LogicVM, idx: usize) -> Processor {
246-
vm.processors[idx]
247-
.replace(Building {
248-
position: Point2::new(0, 0),
249-
block: &content::blocks::VALUES[0],
250-
data: BuildingData::Unknown {
251-
config: Object::Null,
252-
},
253-
})
254+
vm.buildings[idx]
254255
.data
256+
.replace(BuildingData::Unknown {
257+
config: Object::Null,
258+
})
255259
.into_processor()
256260
}
257261

src/logic/vm/variables.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,10 +179,7 @@ pub enum LValue {
179179
String(Rc<str>),
180180
Content(Content),
181181
Team(Team),
182-
Building {
183-
block: &'static Block,
184-
position: Point2,
185-
},
182+
Building(Point2),
186183
}
187184

188185
impl LValue {

0 commit comments

Comments
 (0)