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