fix bug #9379 (renaming a moved unit can cause OOS)

Rename commands are now sent in order with regular commands.  They are
removed when recruits/recalls are undone, and their locations are
repaired when moves are undone.
This commit is contained in:
Jim 2007-07-03 18:33:02 +00:00
parent 4fb881071d
commit 6966ec2397
2 changed files with 49 additions and 5 deletions

View file

@ -13,6 +13,7 @@ Version 1.3.4+svn:
* Help topics for units now have 'advances from' links
* added experimental new transition between map and background
* miscellaneous and bug fixes
* fix renames causing OOS when made after moves or recruits
* fix a minor glitch when selecting the leftmost menu heading
* added some extra headers for the upcomming gcc 4.3 (debian bug #417764)
* fix bug #9398 (attacking units always above defending units)

View file

@ -353,7 +353,7 @@ void replay::clear_labels(const std::string& team_name)
void replay::add_rename(const std::string& name, const gamemap::location& loc)
{
config* const cmd = add_command(false);
(*cmd)["undo"] = "no";
(*cmd)["async"] = "yes"; // Not undoable, but depends on moves/recruits that are
config val;
loc.write(val);
val["name"] = name;
@ -442,15 +442,58 @@ config replay::get_data_range(int cmd_start, int cmd_end, DATA_TYPE data_type)
void replay::undo()
{
config::child_itors cmd = cfg_.child_range("command");
while(cmd.first != cmd.second && (**(cmd.second-1))["undo"] == "no") {
std::vector<config::child_iterator> async_cmds; // Remember cmds not yet synced and skip over them
while(cmd.first != cmd.second && (**(cmd.second-1))["undo"] == "no" || (**(cmd.second-1))["async"] == "yes") {
if ((**(cmd.second-1))["async"] == "yes")
async_cmds.push_back(cmd.second-1);
--cmd.second;
}
if(cmd.first != cmd.second) {
cfg_.remove_child("command",cmd.second - cmd.first - 1);
current_ = NULL;
set_random(NULL);
config* child;
config& cmd_second = (**(cmd.second-1));
if ((child = cmd_second.child("move")) != NULL)
{
// A unit's move is being undone.
// Repair unsynced cmds whose locations depend on that unit's location.
gamemap::location dst = read_location(*(child->child("destination")));
gamemap::location src = read_location(*(child->child("source")));
for (std::vector<config::child_iterator>::iterator async_cmd = async_cmds.begin(); async_cmd != async_cmds.end(); async_cmd++)
{
config* async_child;
if ((async_child = (***async_cmd).child("rename")) != NULL)
{
gamemap::location aloc = read_location(*async_child);
if (dst == aloc)
{
src.write(*async_child);
}
}
}
}
else if ((child = cmd_second.child("recruit")) != NULL || (child = cmd_second.child("recall")) != NULL)
{
// A unit is being un-recruited or un-recalled.
// Remove unsynced commands that would act on that unit.
gamemap::location src = read_location(*child);
for (std::vector<config::child_iterator>::iterator async_cmd = async_cmds.begin(); async_cmd != async_cmds.end(); async_cmd++)
{
config* async_child;
if ((async_child = (***async_cmd).child("rename")) != NULL)
{
gamemap::location aloc = read_location(*async_child);
if (src == aloc)
{
cfg_.remove_child("command", *async_cmd - cmd.first);
}
}
}
}
}
cfg_.remove_child("command",cmd.second - cmd.first - 1);
current_ = NULL;
set_random(NULL);
}
const config::child_list& replay::commands() const