Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
ModInfo.cpp
Go to the documentation of this file.
1 /* Project Starshatter 4.5
2  Destroyer Studios LLC
3  Copyright © 1997-2004. All Rights Reserved.
4 
5  SUBSYSTEM: Stars.exe
6  FILE: ModInfo.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Information block for describing and deploying third party mods
13 */
14 
15 
16 #include "MemDebug.h"
17 #include "ModInfo.h"
18 #include "Campaign.h"
19 #include "ShipDesign.h"
20 #include "ParseUtil.h"
21 
22 #include "Archive.h"
23 #include "DataLoader.h"
24 #include "PCX.h"
25 #include "Bitmap.h"
26 
27 // +-------------------------------------------------------------------+
28 
30 : logo(0), distribute(false), enabled(false), catalog(0)
31 { }
32 
33 ModInfo::ModInfo(const char* fname)
34 : logo(0), distribute(false), enabled(false), catalog(0)
35 {
36  if (fname && *fname) {
37  Load(fname);
38  }
39 }
40 
41 ModInfo::ModInfo(const char* n, const char* v, const char* u)
42 : name(n), logo(0), version(v), url(u), distribute(false), enabled(false), catalog(0)
43 { }
44 
46 {
47  if (enabled)
48  Disable();
49 
50  delete logo;
51  delete catalog;
52  campaigns.destroy();
53 }
54 
55 // +-------------------------------------------------------------------+
56 
57 bool
58 ModInfo::Load(const char* fname)
59 {
60  bool ok = false;
61 
62  filename = fname;
63  DataArchive a(filename);
64 
65  int n = a.FindEntry("mod_info.def");
66  if (n > -1) {
67  BYTE* buf = 0;
68  int len = a.ExpandEntry(n, buf, true);
69 
70  if (len > 0 && buf != 0) {
71  ok = ParseModInfo((const char*) buf);
72  delete [] buf;
73  }
74  }
75 
76  if (logoname.length()) {
77  PcxImage pcx;
78 
79  logo = new(__FILE__,__LINE__) Bitmap;
80 
81  n = a.FindEntry(logoname);
82  if (n > -1) {
83  BYTE* buf = 0;
84  int len = a.ExpandEntry(n, buf, true);
85 
86  pcx.LoadBuffer(buf, len);
87  delete [] buf;
88  }
89 
90  // now copy the image into the bitmap:
91  if (pcx.bitmap) {
92  logo->CopyImage(pcx.width, pcx.height, pcx.bitmap);
93  }
94 
95  else if (pcx.himap) {
96  logo->CopyHighColorImage(pcx.width, pcx.height, pcx.himap);
97  }
98 
99  else {
100  logo->ClearImage();
101  }
102  }
103 
104  return ok;
105 }
106 
107 bool
108 ModInfo::ParseModInfo(const char* block)
109 {
110  bool ok = false;
111  Parser parser(new(__FILE__,__LINE__) BlockReader(block));
112  Term* term = parser.ParseTerm();
113 
114  if (!term) {
115  Print("ERROR: could not parse '%s'\n", filename.data());
116  return ok;
117  }
118  else {
119  TermText* file_type = term->isText();
120  if (!file_type || file_type->value() != "MOD_INFO") {
121  Print("ERROR: invalid mod_info file '%s'\n", filename.data());
122  term->print(10);
123  return ok;
124  }
125  }
126 
127  ok = true;
128 
129  do {
130  delete term; term = 0;
131  term = parser.ParseTerm();
132 
133  if (term) {
134  TermDef* def = term->isDef();
135  if (def) {
136  Text defname = def->name()->value();
137 
138  if (defname == "name")
139  GetDefText(name, def, filename);
140 
141  else if (defname == "desc" || defname == "description")
142  GetDefText(desc, def, filename);
143 
144  else if (defname == "author")
145  GetDefText(author, def, filename);
146 
147  else if (defname == "url")
148  GetDefText(url, def, filename);
149 
150  else if (defname == "copyright")
151  GetDefText(copyright, def, filename);
152 
153  else if (defname == "logo")
154  GetDefText(logoname, def, filename);
155 
156  else if (defname == "version") {
157  if (def->term()) {
158  if (def->term()->isNumber()) {
159  int v = 0;
160  char buf[32];
161  GetDefNumber(v, def, filename);
162  sprintf_s(buf, "%d", v);
163 
164  version = buf;
165  }
166 
167  else if (def->term()->isText()) {
168  GetDefText(version, def, filename);
169  }
170  }
171  }
172 
173  else if (defname == "distribute")
174  GetDefBool(distribute, def, filename);
175 
176  else if (defname == "campaign") {
177  if (!def->term() || !def->term()->isStruct()) {
178  Print("WARNING: campaign structure missing in mod_info.def for '%s'\n", name.data());
179  }
180  else {
181  TermStruct* val = def->term()->isStruct();
182 
183  ModCampaign* c = new(__FILE__,__LINE__) ModCampaign;
184 
185  for (int i = 0; i < val->elements()->size(); i++) {
186  TermDef* pdef = val->elements()->at(i)->isDef();
187  if (pdef) {
188  defname = pdef->name()->value();
189 
190  if (defname == "name") {
191  GetDefText(c->name, pdef, filename);
192  }
193 
194  else if (defname == "path") {
195  GetDefText(c->path, pdef, filename);
196  }
197 
198  else if (defname == "dynamic") {
199  GetDefBool(c->dynamic, pdef, filename);
200  }
201  }
202  }
203 
204  if (c->name.length() && c->path.length())
205  campaigns.append(c);
206  else
207  delete c;
208  }
209  }
210 
211  else if (defname == "catalog") {
212  if (!def->term() || !def->term()->isStruct()) {
213  Print("WARNING: catalog structure missing in mod_info.def for '%s'\n", name.data());
214  }
215  else {
216  TermStruct* val = def->term()->isStruct();
217 
218  ModCatalog* c = new(__FILE__,__LINE__) ModCatalog;
219 
220  for (int i = 0; i < val->elements()->size(); i++) {
221  TermDef* pdef = val->elements()->at(i)->isDef();
222  if (pdef) {
223  defname = pdef->name()->value();
224 
225  if (defname == "file") {
226  GetDefText(c->file, pdef, filename);
227  }
228 
229  else if (defname == "path") {
230  GetDefText(c->path, pdef, filename);
231 
232  char last_char = c->path[c->path.length()-1];
233 
234  if (last_char != '/' && last_char != '\\')
235  c->path += "/";
236  }
237  }
238  }
239 
240  if (c->file.length() && c->path.length() && !catalog)
241  catalog = c;
242  else
243  delete c;
244  }
245  }
246  } // def
247  } // term
248  }
249  while (term);
250 
251  return ok;
252 }
253 
254 // +-------------------------------------------------------------------+
255 
256 bool
258 {
259  DataLoader* loader = DataLoader::GetLoader();
260 
261  if (loader && !enabled) {
262  loader->EnableDatafile(filename);
263  enabled = true;
264 
265  if (catalog)
266  ShipDesign::LoadCatalog(catalog->Path(), catalog->File(), true);
267 
268  ShipDesign::LoadSkins("/Mods/Skins/", filename);
269 
270  for (int i = 0; i < campaigns.size(); i++) {
271  ModCampaign* c = campaigns[i];
273  }
274  }
275 
276  return enabled;
277 }
278 
279 bool
281 {
282  DataLoader* loader = DataLoader::GetLoader();
283 
284  if (loader) {
285  loader->DisableDatafile(filename);
286  enabled = false;
287  }
288 
289  return !enabled;
290 }
291 
292 // +-------------------------------------------------------------------+