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