Merge branch 'tracerestrict-sx' into jgrpp
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#include "group.h"
|
||||
#include "pathfinder/yapf/yapf_cache.h"
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
/** @file
|
||||
*
|
||||
@@ -855,13 +856,152 @@ static uint32 GetDualInstructionInitialValue(TraceRestrictItem item)
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> T InstructionIteratorNext(T iter)
|
||||
{
|
||||
return IsTraceRestrictDoubleItem(*iter) ? iter + 2 : iter + 1;
|
||||
}
|
||||
|
||||
template <typename T> void InstructionIteratorAdvance(T &iter)
|
||||
{
|
||||
iter = InstructionIteratorNext(iter);
|
||||
}
|
||||
|
||||
CommandCost TraceRestrictProgramRemoveItemAt(std::vector<TraceRestrictItem> &items, uint32 offset, bool shallow_mode)
|
||||
{
|
||||
TraceRestrictItem old_item = *TraceRestrictProgram::InstructionAt(items, offset);
|
||||
if (IsTraceRestrictConditional(old_item) && GetTraceRestrictCondFlags(old_item) != TRCF_OR) {
|
||||
bool remove_whole_block = false;
|
||||
if (GetTraceRestrictCondFlags(old_item) == 0) {
|
||||
if (GetTraceRestrictType(old_item) == TRIT_COND_ENDIF) {
|
||||
// this is an end if, can't remove these
|
||||
return_cmd_error(STR_TRACE_RESTRICT_ERROR_CAN_T_REMOVE_ENDIF);
|
||||
} else {
|
||||
// this is an opening if
|
||||
remove_whole_block = true;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 recursion_depth = 1;
|
||||
std::vector<TraceRestrictItem>::iterator remove_start = TraceRestrictProgram::InstructionAt(items, offset);
|
||||
std::vector<TraceRestrictItem>::iterator remove_end = InstructionIteratorNext(remove_start);
|
||||
|
||||
// iterate until matching end block found
|
||||
for (; remove_end != items.end(); InstructionIteratorAdvance(remove_end)) {
|
||||
TraceRestrictItem current_item = *remove_end;
|
||||
if (IsTraceRestrictConditional(current_item)) {
|
||||
if (GetTraceRestrictCondFlags(current_item) == 0) {
|
||||
if (GetTraceRestrictType(current_item) == TRIT_COND_ENDIF) {
|
||||
// this is an end if
|
||||
recursion_depth--;
|
||||
if (recursion_depth == 0) {
|
||||
if (remove_whole_block) {
|
||||
if (shallow_mode) {
|
||||
// must erase endif first, as it is later in the vector
|
||||
items.erase(remove_end, InstructionIteratorNext(remove_end));
|
||||
} else {
|
||||
// inclusively remove up to here
|
||||
InstructionIteratorAdvance(remove_end);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
// exclusively remove up to here
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// this is an opening if
|
||||
recursion_depth++;
|
||||
}
|
||||
} else {
|
||||
// this is an else/or type block
|
||||
if (recursion_depth == 1 && !remove_whole_block) {
|
||||
// exclusively remove up to here
|
||||
recursion_depth = 0;
|
||||
break;
|
||||
}
|
||||
if (recursion_depth == 1 && remove_whole_block && shallow_mode) {
|
||||
// shallow-removing whole if block, and it contains an else/or if, bail out
|
||||
return_cmd_error(STR_TRACE_RESTRICT_ERROR_CAN_T_SHALLOW_REMOVE_IF_ELIF);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (recursion_depth != 0) return CMD_ERROR; // ran off the end
|
||||
if (shallow_mode) {
|
||||
items.erase(remove_start, InstructionIteratorNext(remove_start));
|
||||
} else {
|
||||
items.erase(remove_start, remove_end);
|
||||
}
|
||||
} else {
|
||||
std::vector<TraceRestrictItem>::iterator remove_start = TraceRestrictProgram::InstructionAt(items, offset);
|
||||
std::vector<TraceRestrictItem>::iterator remove_end = InstructionIteratorNext(remove_start);
|
||||
|
||||
items.erase(remove_start, remove_end);
|
||||
}
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
CommandCost TraceRestrictProgramMoveItemAt(std::vector<TraceRestrictItem> &items, uint32 &offset, bool up, bool shallow_mode)
|
||||
{
|
||||
std::vector<TraceRestrictItem>::iterator move_start = TraceRestrictProgram::InstructionAt(items, offset);
|
||||
std::vector<TraceRestrictItem>::iterator move_end = InstructionIteratorNext(move_start);
|
||||
|
||||
TraceRestrictItem old_item = *move_start;
|
||||
if (!shallow_mode) {
|
||||
if (IsTraceRestrictConditional(old_item)) {
|
||||
if (GetTraceRestrictCondFlags(old_item) != 0) {
|
||||
// can't move or/else blocks
|
||||
return_cmd_error(STR_TRACE_RESTRICT_ERROR_CAN_T_MOVE_ITEM);
|
||||
}
|
||||
if (GetTraceRestrictType(old_item) == TRIT_COND_ENDIF) {
|
||||
// this is an end if, can't move these
|
||||
return_cmd_error(STR_TRACE_RESTRICT_ERROR_CAN_T_MOVE_ITEM);
|
||||
}
|
||||
|
||||
uint32 recursion_depth = 1;
|
||||
// iterate until matching end block found
|
||||
for (; move_end != items.end(); InstructionIteratorAdvance(move_end)) {
|
||||
TraceRestrictItem current_item = *move_end;
|
||||
if (IsTraceRestrictConditional(current_item)) {
|
||||
if (GetTraceRestrictCondFlags(current_item) == 0) {
|
||||
if (GetTraceRestrictType(current_item) == TRIT_COND_ENDIF) {
|
||||
// this is an end if
|
||||
recursion_depth--;
|
||||
if (recursion_depth == 0) {
|
||||
// inclusively remove up to here
|
||||
InstructionIteratorAdvance(move_end);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// this is an opening if
|
||||
recursion_depth++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (recursion_depth != 0) return CMD_ERROR; // ran off the end
|
||||
}
|
||||
}
|
||||
|
||||
if (up) {
|
||||
if (move_start == items.begin()) return_cmd_error(STR_TRACE_RESTRICT_ERROR_CAN_T_MOVE_ITEM);
|
||||
std::rotate(TraceRestrictProgram::InstructionAt(items, offset - 1), move_start, move_end);
|
||||
offset--;
|
||||
} else {
|
||||
if (move_end == items.end()) return_cmd_error(STR_TRACE_RESTRICT_ERROR_CAN_T_MOVE_ITEM);
|
||||
std::rotate(move_start, move_end, InstructionIteratorNext(move_end));
|
||||
offset++;
|
||||
}
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* The main command for editing a signal tracerestrict program.
|
||||
* @param tile The tile which contains the signal.
|
||||
* @param flags Internal command handler stuff.
|
||||
* Below apply for instruction modification actions only
|
||||
* @param p1 Bitstuffed items
|
||||
* @param p2 Item, for insert and modify operations
|
||||
* @param p2 Item, for insert and modify operations. Flags for instruction move operations
|
||||
* @return the cost of this operation (which is free), or an error
|
||||
*/
|
||||
CommandCost CmdProgramSignalTraceRestrict(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||
@@ -939,71 +1079,16 @@ CommandCost CmdProgramSignalTraceRestrict(TileIndex tile, DoCommandFlag flags, u
|
||||
break;
|
||||
}
|
||||
|
||||
case TRDCT_REMOVE_ITEM: {
|
||||
TraceRestrictItem old_item = *TraceRestrictProgram::InstructionAt(items, offset);
|
||||
if (IsTraceRestrictConditional(old_item) && GetTraceRestrictCondFlags(old_item) != TRCF_OR) {
|
||||
bool remove_whole_block = false;
|
||||
if (GetTraceRestrictCondFlags(old_item) == 0) {
|
||||
if (GetTraceRestrictType(old_item) == TRIT_COND_ENDIF) {
|
||||
// this is an end if, can't remove these
|
||||
return_cmd_error(STR_TRACE_RESTRICT_ERROR_CAN_T_REMOVE_ENDIF);
|
||||
} else {
|
||||
// this is an opening if
|
||||
remove_whole_block = true;
|
||||
}
|
||||
}
|
||||
case TRDCT_REMOVE_ITEM:
|
||||
case TRDCT_SHALLOW_REMOVE_ITEM: {
|
||||
CommandCost res = TraceRestrictProgramRemoveItemAt(items, offset, type == TRDCT_SHALLOW_REMOVE_ITEM);
|
||||
if (res.Failed()) return res;
|
||||
break;
|
||||
}
|
||||
|
||||
uint32 recursion_depth = 1;
|
||||
std::vector<TraceRestrictItem>::iterator remove_start = TraceRestrictProgram::InstructionAt(items, offset);
|
||||
std::vector<TraceRestrictItem>::iterator remove_end = remove_start + 1;
|
||||
|
||||
// iterate until matching end block found
|
||||
for (; remove_end != items.end(); ++remove_end) {
|
||||
TraceRestrictItem current_item = *remove_end;
|
||||
if (IsTraceRestrictConditional(current_item)) {
|
||||
if (GetTraceRestrictCondFlags(current_item) == 0) {
|
||||
if (GetTraceRestrictType(current_item) == TRIT_COND_ENDIF) {
|
||||
// this is an end if
|
||||
recursion_depth--;
|
||||
if (recursion_depth == 0) {
|
||||
if (remove_whole_block) {
|
||||
// inclusively remove up to here
|
||||
++remove_end;
|
||||
break;
|
||||
} else {
|
||||
// exclusively remove up to here
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// this is an opening if
|
||||
recursion_depth++;
|
||||
}
|
||||
} else {
|
||||
// this is an else/or type block
|
||||
if (recursion_depth == 1 && !remove_whole_block) {
|
||||
// exclusively remove up to here
|
||||
recursion_depth = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (IsTraceRestrictDoubleItem(current_item)) {
|
||||
// this is a double-item, jump over the next item as well
|
||||
++remove_end;
|
||||
}
|
||||
}
|
||||
if (recursion_depth != 0) return CMD_ERROR; // ran off the end
|
||||
items.erase(remove_start, remove_end);
|
||||
} else {
|
||||
std::vector<TraceRestrictItem>::iterator remove_start = TraceRestrictProgram::InstructionAt(items, offset);
|
||||
std::vector<TraceRestrictItem>::iterator remove_end = remove_start + 1;
|
||||
|
||||
if (IsTraceRestrictDoubleItem(old_item)) {
|
||||
// this is a double-item, remove the next item as well
|
||||
++remove_end;
|
||||
}
|
||||
items.erase(remove_start, remove_end);
|
||||
}
|
||||
case TRDCT_MOVE_ITEM: {
|
||||
CommandCost res = TraceRestrictProgramMoveItemAt(items, offset, p2 & 1, p2 & 2);
|
||||
if (res.Failed()) return res;
|
||||
break;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user