1
0
Fork 0

Updated Wildfire: Added support for synchronized loading of event logs.

A fire log can now be loaded at startup time with, e.g.,
--prop:environment/wildfire/events-file=$HOME/.fgfs/Wildfire/small_fire.xml
(Note: Wildfire is only authorized to load logs from ~/.fgfs/Wildfire .)

Additionally, a time at which the fire starts to evolve (past the event log)
can be specified with, e.g.,
--prop:environment/wildfire/time-hack-gmt='2012:08:23:15:15'

Instances of FlightGear that are started with the same event log and time-hack
should arrive at similar wildfire states (prior to new events).
This commit is contained in:
Anders Gidenstam 2012-08-23 23:08:24 +02:00
parent f5bfd65f72
commit acd0091d9d

View file

@ -95,7 +95,7 @@ var resolve_foam_drop = func (pos, radius, volume, source=1) {
# x < last event - fast forward all the way to current time (use 0). # x < last event - fast forward all the way to current time (use 0).
# NOTE: Can be VERY time consuming. # NOTE: Can be VERY time consuming.
# -1 - skip to current time. # -1 - skip to current time.
var load_event_log = func (filename, skip_ahead_until=-1) { var load_event_log = func (filename, skip_ahead_until) {
CAFire.load_event_log(filename, skip_ahead_until); CAFire.load_event_log(filename, skip_ahead_until);
} }
@ -129,6 +129,9 @@ var restore_on_startup_pp = "environment/wildfire/restore-on-startup";
var crash_fire_pp = "environment/wildfire/fire-on-crash"; var crash_fire_pp = "environment/wildfire/fire-on-crash";
var impact_fire_pp = "environment/wildfire/fire-on-impact"; var impact_fire_pp = "environment/wildfire/fire-on-impact";
var report_score_pp = "environment/wildfire/report-score"; var report_score_pp = "environment/wildfire/report-score";
var event_file_pp = "environment/wildfire/events-file";
var time_hack_pp = "environment/wildfire/time-hack-gmt";
# Format: "yyyy:mm:dd:hh:mm:ss"
# Internal properties to control the models # Internal properties to control the models
var models_enabled_pp = "environment/wildfire/models/enabled"; var models_enabled_pp = "environment/wildfire/models/enabled";
var fire_LOD_pp = "environment/wildfire/models/fire-lod"; var fire_LOD_pp = "environment/wildfire/models/fire-lod";
@ -788,7 +791,7 @@ CAFire.save_event_log = func (filename) {
# to current time. # to current time.
# x < last event - fast forward all the way to current time (use 0). # x < last event - fast forward all the way to current time (use 0).
# -1 - skip to current time. # -1 - skip to current time.
CAFire.load_event_log = func (filename, skip_ahead_until=-1) { CAFire.load_event_log = func (filename, skip_ahead_until) {
me.load_count += 1; me.load_count += 1;
var logbase = "/tmp/wildfire-load-log[" ~ me.load_count ~ "]"; var logbase = "/tmp/wildfire-load-log[" ~ me.load_count ~ "]";
if (!fgcommand("loadxml", if (!fgcommand("loadxml",
@ -814,7 +817,7 @@ CAFire.load_event_log = func (filename, skip_ahead_until=-1) {
event.getNode("type").getValue()]; event.getNode("type").getValue()];
# Fast forward state. # Fast forward state.
while (me.generation * me.GENERATION_DURATION <= e[0]) { while (me.generation * me.GENERATION_DURATION < e[0]) {
# print("between event ff " ~ me.generation); # print("between event ff " ~ me.generation);
me.update(); me.update();
} }
@ -958,6 +961,8 @@ _setlistener("/sim/signals/nasal-dir-initialized", func {
props.globals.initNode(restore_on_startup_pp, 0, "BOOL"); props.globals.initNode(restore_on_startup_pp, 0, "BOOL");
props.globals.initNode(models_enabled_pp, 1, "BOOL"); props.globals.initNode(models_enabled_pp, 1, "BOOL");
props.globals.initNode(report_score_pp, 1, "BOOL"); props.globals.initNode(report_score_pp, 1, "BOOL");
props.globals.initNode(event_file_pp, "", "STRING");
props.globals.initNode(time_hack_pp, "", "STRING");
props.globals.initNode(fire_LOD_pp, 10, "INT"); props.globals.initNode(fire_LOD_pp, 10, "INT");
props.globals.initNode(smoke_LOD_pp, 10, "INT"); props.globals.initNode(smoke_LOD_pp, 10, "INT");
@ -977,10 +982,35 @@ _setlistener("/sim/signals/nasal-dir-initialized", func {
CAFire.save_event_log(SAVEDIR ~ "fire_log.xml"); CAFire.save_event_log(SAVEDIR ~ "fire_log.xml");
}); });
if (getprop(restore_on_startup_pp)) { # Determine the skip-ahead-to time, if any.
var time_hack = time_string_to_epoch(getprop(time_hack_pp));
if (time_hack > SimTime.current_time()) {
printlog("alert",
"wildfire.nas: Ignored time hack " ~
(SimTime.current_time() - time_hack) ~
" seconds into the future.");
# Skip ahead to current time instead.
time_hack = -1;
} elsif (time_hack > 0) {
printlog("alert",
"wildfire.nas: Time hack " ~
(SimTime.current_time() - time_hack) ~
" seconds ago.");
} else {
# Skip ahead to current time instead.
time_hack = -1;
}
if (getprop(event_file_pp) != "") {
settimer(func { settimer(func {
# Delay loading the log until the terrain is there. Note: hack. # Delay loading the log until the terrain is there. Note: hack.
CAFire.load_event_log(SAVEDIR ~ "fire_log.xml", 1); CAFire.load_event_log(getprop(event_file_pp), time_hack);
}, 3);
} elsif (getprop(restore_on_startup_pp)) {
settimer(func {
# Delay loading the log until the terrain is there. Note: hack.
# Restore skips ahead to current time.
CAFire.load_event_log(SAVEDIR ~ "fire_log.xml", -1);
}, 3); }, 3);
} }
@ -990,17 +1020,16 @@ _setlistener("/sim/signals/nasal-dir-initialized", func {
wildfire.ignite(geo.aircraft_position()); wildfire.ignite(geo.aircraft_position());
}); });
# Detect impact # Detect impact.
var impact_node = props.globals.getNode("sim/ai/aircraft/impact/bomb", 1); var impact_node = props.globals.getNode("sim/ai/aircraft/impact/bomb", 1);
setlistener("sim/ai/aircraft/impact/bomb", func(n) { setlistener("sim/ai/aircraft/impact/bomb", func(n) {
if (getprop(impact_fire_pp) and n.getBoolValue()){ if (getprop(impact_fire_pp) and n.getBoolValue()){
var node = props.globals.getNode(n.getValue(), 1); var node = props.globals.getNode(n.getValue(), 1);
var impactpos = geo.Coord.new(); var impactpos = geo.Coord.new();
impactpos.set_latlon( impactpos.set_latlon
node.getNode("impact/latitude-deg").getValue(), (node.getNode("impact/latitude-deg").getValue(),
node.getNode("impact/longitude-deg").getValue() node.getNode("impact/longitude-deg").getValue());
);
wildfire.ignite(impactpos); wildfire.ignite(impactpos);
} }
@ -1010,6 +1039,40 @@ _setlistener("/sim/signals/nasal-dir-initialized", func {
}); });
############################################################################### ###############################################################################
###############################################################################
# Utility functions
# Convert a time string in the format yyyy[:mm[:dd[:hh[:mm[:ss]]]]]
# to seconds since 1970:01:01:00:00:00.
#
# Note: This is an over simplified approximation.
var time_string_to_epoch = func (time) {
var res = [];
if (string.scanf(time, "%d:%d:%d:%d:%d:%d", var res1 = []) != 0) {
res = res1;
} elsif (string.scanf(time, "%d:%d:%d:%d:%d", var res2 = []) != 0) {
res = res2 ~ [0];
} elsif (string.scanf(time, "%d:%d:%d:%d", var res3 = []) != 0) {
res = res3 ~ [0, 0];
} elsif (string.scanf(time, "%d:%d:%d", var res4 = []) != 0) {
res = res4 ~ [0, 0, 0];
} elsif (string.scanf(time, "%d:%d", var res5 = []) != 0) {
res = res5 ~ [0, 0, 0, 0];
} elsif (string.scanf(time, "%d", var res6 = []) != 0) {
res = res6 ~ [0, 0, 0, 0, 0];
} else {
return -1;
}
return
(res[0] - 1970) * 3.15569e7 +
(res[1] - 1) * 2.63e+6 +
(res[2] - 1) * 86400 +
res[3] * 3600 +
res[4] * 60 +
res[5];
}
############################################################################### ###############################################################################
## WildFire configuration dialog. ## WildFire configuration dialog.
## Partly based on Till Bush's multiplayer dialog ## Partly based on Till Bush's multiplayer dialog
@ -1126,7 +1189,7 @@ var dialog = {
################################################################# #################################################################
select_and_load : func { select_and_load : func {
var selector = gui.FileSelector.new var selector = gui.FileSelector.new
(func (n) { CAFire.load_event_log(n.getValue()); }, (func (n) { load_event_log(n.getValue(), -1); },
"Load Wildfire log", # dialog title "Load Wildfire log", # dialog title
"Load", # button text "Load", # button text
["*.xml"], # pattern for files ["*.xml"], # pattern for files