1#include <base/logger.h>
2#include <base/system.h>
3
4#include <engine/shared/datafile.h>
5#include <engine/storage.h>
6
7#include <game/mapitems.h>
8
9class CEnvelopedQuad
10{
11public:
12 int m_GroupId;
13 int m_LayerId;
14 int m_TilePosX;
15 int m_TilePosY;
16};
17
18static bool OpenMap(const char pMapName[64], CDataFileReader &InputMap)
19{
20 std::unique_ptr<IStorage> pStorage = CreateLocalStorage();
21 if(!pStorage)
22 {
23 log_error("map_find_env", "Error creating local storage");
24 return false;
25 }
26
27 if(!InputMap.Open(pStorage: pStorage.get(), pFilename: pMapName, StorageType: IStorage::TYPE_ABSOLUTE))
28 {
29 dbg_msg(sys: "map_find_env", fmt: "ERROR: unable to open map '%s'", pMapName);
30 return false;
31 }
32 return true;
33}
34
35static bool GetLayerGroupIds(CDataFileReader &InputMap, const int LayerNumber, int &GroupId, int &LayerRelativeId)
36{
37 int Start, Num;
38 InputMap.GetType(Type: MAPITEMTYPE_GROUP, pStart: &Start, pNum: &Num);
39
40 for(int i = 0; i < Num; i++)
41 {
42 CMapItemGroup *pItem = (CMapItemGroup *)InputMap.GetItem(Index: Start + i);
43 if(LayerNumber >= pItem->m_StartLayer && LayerNumber <= pItem->m_StartLayer + pItem->m_NumLayers)
44 {
45 GroupId = i;
46 LayerRelativeId = LayerNumber - pItem->m_StartLayer - 1;
47 return true;
48 }
49 }
50
51 return false;
52}
53
54static int FxToTilePos(const int FxPos)
55{
56 return std::floor(x: fx2f(v: FxPos) / 32);
57}
58
59static bool GetEnvelopedQuads(const CQuad *pQuads, const int NumQuads, const int EnvId, const int GroupId, const int LayerId, int &QuadsCounter, CEnvelopedQuad pEnvQuads[1024])
60{
61 bool Found = false;
62 for(int i = 0; i < NumQuads; i++)
63 {
64 if(pQuads[i].m_PosEnv != EnvId && pQuads[i].m_ColorEnv != EnvId)
65 continue;
66
67 pEnvQuads[QuadsCounter].m_GroupId = GroupId;
68 pEnvQuads[QuadsCounter].m_LayerId = LayerId;
69 pEnvQuads[QuadsCounter].m_TilePosX = FxToTilePos(FxPos: pQuads[i].m_aPoints[4].x);
70 pEnvQuads[QuadsCounter].m_TilePosY = FxToTilePos(FxPos: pQuads[i].m_aPoints[4].y);
71
72 QuadsCounter++;
73 Found = true;
74 }
75
76 return Found;
77}
78
79static void PrintEnvelopedQuads(const CEnvelopedQuad pEnvQuads[1024], const int EnvId, const int QuadsCounter)
80{
81 if(!QuadsCounter)
82 {
83 dbg_msg(sys: "map_find_env", fmt: "No quads found with env number #%d", EnvId + 1);
84 return;
85 }
86
87 dbg_msg(sys: "map_find_env", fmt: "Found %d quads with env number #%d:", QuadsCounter, EnvId + 1);
88 for(int i = 0; i < QuadsCounter; i++)
89 dbg_msg(sys: "map_find_env", fmt: "%*d. Group: #%d - Layer: #%d - Pos: %d,%d", (int)(std::log10(x: absolute(a: QuadsCounter))) + 1, i + 1, pEnvQuads[i].m_GroupId, pEnvQuads[i].m_LayerId, pEnvQuads[i].m_TilePosX, pEnvQuads[i].m_TilePosY);
90}
91
92static bool FindEnv(const char aFilename[64], const int EnvId)
93{
94 CDataFileReader InputMap;
95 if(!OpenMap(pMapName: aFilename, InputMap))
96 return false;
97
98 int LayersStart, LayersCount, QuadsCounter = 0;
99 InputMap.GetType(Type: MAPITEMTYPE_LAYER, pStart: &LayersStart, pNum: &LayersCount);
100 CEnvelopedQuad pEnvQuads[1024];
101
102 for(int i = 0; i < LayersCount; i++)
103 {
104 CMapItemLayer *pItem;
105 pItem = (CMapItemLayer *)InputMap.GetItem(Index: LayersStart + i);
106
107 if(pItem->m_Type != LAYERTYPE_QUADS)
108 continue;
109
110 CMapItemLayerQuads *pQuadLayer = (CMapItemLayerQuads *)pItem;
111 CQuad *pQuads = (CQuad *)InputMap.GetDataSwapped(Index: pQuadLayer->m_Data);
112
113 int GroupId = 0, LayerRelativeId = 0;
114 if(!GetLayerGroupIds(InputMap, LayerNumber: i + 1, GroupId, LayerRelativeId))
115 return false;
116
117 GetEnvelopedQuads(pQuads, NumQuads: pQuadLayer->m_NumQuads, EnvId, GroupId, LayerId: LayerRelativeId, QuadsCounter, pEnvQuads);
118 }
119
120 PrintEnvelopedQuads(pEnvQuads, EnvId, QuadsCounter);
121
122 return true;
123}
124
125int main(int argc, const char **argv)
126{
127 CCmdlineFix CmdlineFix(&argc, &argv);
128 log_set_global_logger_default();
129
130 if(argc < 3)
131 {
132 dbg_msg(sys: "map_find_env", fmt: "Invalid arguments");
133 dbg_msg(sys: "map_find_env", fmt: "Usage: %s <input_map> <env_number>", argv[0]);
134 dbg_msg(sys: "map_find_env", fmt: "Note: returned quads positions are relative to their layers");
135
136 return -1;
137 }
138
139 char aFilename[64];
140 str_copy(dst&: aFilename, src: argv[1]);
141 int EnvId = str_toint(str: argv[2]) - 1;
142 dbg_msg(sys: "map_find_env", fmt: "input_map='%s'; env_number='#%d';", aFilename, EnvId + 1);
143
144 return FindEnv(aFilename, EnvId);
145}
146