5 * Created by Alyssa Milburn on Sun Jun 13 2004.
6 * Copyright (c) 2004 Alyssa Milburn. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
21 #include "caosScript.h" // PRAY INJT
23 #include "Catalogue.h"
24 #include <boost/format.hpp>
25 #include <boost/filesystem/convenience.hpp>
26 namespace fs
= boost::filesystem
;
28 bool prayInstall(std::string name
, unsigned int type
, bool actually_install
) {
29 std::string directory
= world
.praymanager
.getResourceDir(type
);
30 caos_assert(!directory
.empty());
32 fs::path dir
= fs::path(world
.getUserDataDir(), fs::native
) / fs::path(directory
, fs::native
);
34 fs::create_directory(dir
);
35 caos_assert(fs::exists(dir
) && fs::is_directory(dir
));
37 fs::path outputfile
= dir
/ fs::path(name
, fs::native
);
38 if (fs::exists(outputfile
)) {
39 // TODO: update file if necessary? check it's not a directory :P
43 fs::path possiblefile
= fs::path(directory
, fs::native
) / fs::path(name
, fs::native
);
44 if (!world
.findFile(possiblefile
.native_directory_string()).empty()) {
45 // TODO: we need to return 'okay' if the file exists anywhere, but someone needs to work out update behaviour (see other comment above, also)
49 std::map
<std::string
, prayBlock
*>::iterator i
= world
.praymanager
.blocks
.find(name
);
50 if (i
== world
.praymanager
.blocks
.end()) {
51 std::cout
<< "PRAY FILE: couldn't find block " << name
<< std::endl
;
55 prayBlock
*p
= i
->second
;
56 if (p
->type
!= "FILE") {
57 std::cout
<< "PRAY FILE: block " << name
<< " is " << p
->type
<< " not FILE" << std::endl
;
58 // TODO: correct behaviour? possibly not..
62 if (!actually_install
) {
63 // TODO: work out if we've tested enough
68 std::ofstream
output(outputfile
.native_directory_string().c_str(), std::ios::binary
);
69 output
.write((char *)p
->getBuffer(), p
->getSize());
73 output
.flush(); output
.close();
74 // TODO: verify it is a catalogue file first, perhaps?
75 catalogue
.addFile(outputfile
);
81 int prayInstallDeps(std::string name
, bool actually_install
) {
82 std::map
<std::string
, prayBlock
*>::iterator i
= world
.praymanager
.blocks
.find(name
);
83 caos_assert(i
!= world
.praymanager
.blocks
.end());
85 prayBlock
*p
= i
->second
;
88 std::map
<std::string
, int>::iterator j
= p
->integerValues
.find("Agent Type");
89 if (j
== p
->integerValues
.end()) {
92 // I have no idea what this is, so let's just error out when it's not zero, pending fix. - fuzzie
93 caos_assert(j
->second
== 0);
95 j
= p
->integerValues
.find("Dependency Count");
96 if (j
== p
->integerValues
.end()) {
99 int nodeps
= j
->second
; caos_assert(nodeps
>= 0);
101 for (int z
= 1; z
<= nodeps
; z
++) {
102 std::string depcatname
= boost::str(boost::format("Dependency Category %d") % z
);
103 std::string depname
= boost::str(boost::format("Dependency %d") % z
);
104 j
= p
->integerValues
.find(depcatname
);
105 if (j
== p
->integerValues
.end()) {
106 return (-2 - nodeps
- z
);
108 int depcat
= j
->second
; caos_assert(depcat
>= 0 && depcat
<= 11);
109 std::map
<std::string
, std::string
>::iterator k
= p
->stringValues
.find(depname
);
110 if (k
== p
->stringValues
.end()) {
113 std::string dep
= k
->second
;
115 // TODO: CL docs say 2*count to 3*count is the category ID for that dependency being invalid
116 if (!prayInstall(dep
, depcat
, actually_install
)) {
124 //used by PRAY BACK, PRAY FORE, PRAY NEXT and PRAY PREV to implement their functionality
125 std::string
findBlock(std::string type
, std::string last
, bool forward
, bool loop
) {
126 prayBlock
*firstblock
= 0, *currblock
= 0;
127 bool foundblock
= false;
129 if (world
.praymanager
.blocks
.size() == 0) return ""; // We definitely can't find anything in that case!
131 // Where do we start?
132 std::map
<std::string
, prayBlock
*>::iterator i
;
134 i
= world
.praymanager
.blocks
.begin();
136 i
= world
.praymanager
.blocks
.end();
140 // Loop through all the blocks.
142 if (i
->second
->type
== type
) {
143 currblock
= i
->second
;
145 // Store the first block if we didn't already find one, for possible use later.
147 firstblock
= currblock
;
149 // If this is the resource we want, grab it!
151 return currblock
->name
;
153 // If this is the resource we're looking for, make a note to grab the next one.
154 if (last
== currblock
->name
)
158 // Step through the list. Break if we need to.
159 if (!forward
&& i
== world
.praymanager
.blocks
.begin()) break;
160 if (forward
) i
++; else i
--;
161 if (forward
&& i
== world
.praymanager
.blocks
.end()) break;
164 if (foundblock
&& loop
) return firstblock
->name
; // loop around to first-found block
165 else if (!foundblock
&& currblock
) return firstblock
->name
; // default to first-found block (XXX this is in direct opposition to what CAOS docs say!)
167 return ""; // yarr, failure.
171 PRAY AGTI (integer) resource (string) tag (string) default (integer)
174 using the specified resource, returns the integer value associated with the given tag,
175 or default if the tag doesn't exist
177 void caosVM::v_PRAY_AGTI() {
178 VM_PARAM_INTEGER(_default
)
180 VM_PARAM_STRING(resource
)
182 std::map
<std::string
, prayBlock
*>::iterator i
= world
.praymanager
.blocks
.find(resource
);
183 caos_assert(i
!= world
.praymanager
.blocks
.end());
185 prayBlock
*p
= i
->second
;
187 if (p
->integerValues
.find(tag
) == p
->integerValues
.end())
188 result
.setInt(_default
);
190 result
.setInt(p
->integerValues
[tag
]);
194 PRAY AGTS (string) resource (string) tag (string) default (string)
197 using the specified resource, returns the string value associated with the given tag,
198 or default if the tag doesn't exist
200 void caosVM::v_PRAY_AGTS() {
201 VM_PARAM_STRING(_default
)
203 VM_PARAM_STRING(resource
)
205 std::map
<std::string
, prayBlock
*>::iterator i
= world
.praymanager
.blocks
.find(resource
);
206 caos_assert(i
!= world
.praymanager
.blocks
.end());
208 prayBlock
*p
= i
->second
;
210 if (p
->stringValues
.find(tag
) == p
->stringValues
.end())
211 result
.setString(_default
);
213 result
.setString(p
->stringValues
[tag
]);
217 PRAY BACK (string) type (string) last (string)
220 returns the name of the resource of the specified type which is immediately previous to last
221 see PRAY PREV if you want to loop around
223 void caosVM::v_PRAY_BACK() {
224 VM_PARAM_STRING(last
)
225 VM_PARAM_STRING(type
)
227 result
.setString(findBlock(type
, last
, false, false));
231 PRAY COUN (integer) type (string)
234 return the number of resources of the specified type available
236 void caosVM::v_PRAY_COUN() {
237 VM_PARAM_STRING(type
)
239 unsigned int count
= 0;
240 for (std::map
<std::string
, prayBlock
*>::iterator i
= world
.praymanager
.blocks
.begin(); i
!= world
.praymanager
.blocks
.end(); i
++)
241 if (i
->second
->type
== type
)
244 result
.setInt(count
);
248 PRAY DEPS (integer) name (string) install (integer)
251 void caosVM::v_PRAY_DEPS() {
252 VM_PARAM_INTEGER(install
)
253 VM_PARAM_STRING(name
)
255 result
.setInt(prayInstallDeps(name
, install
!= 0));
259 PRAY EXPO (integer) type (string)
262 void caosVM::v_PRAY_EXPO() {
263 VM_PARAM_STRING(type
)
265 result
.setInt(0); // TODO
269 PRAY FILE (integer) name (integer) type (integer) install (integer)
272 install a file with given resource name and type
273 if install is 0, the install doesn't actually happen, it's just tested
274 returns 0 on success, 1 on failure
276 void caosVM::v_PRAY_FILE() {
277 VM_PARAM_INTEGER(install
)
278 VM_PARAM_INTEGER(type
)
279 VM_PARAM_STRING(name
)
281 if (prayInstall(name
, type
, (install
!= 0)))
288 PRAY FORE (string) type (string) last (string)
291 returns the name of the resource of the specified type which is immediately after last
292 see PRAY NEXT if you want to loop around
294 void caosVM::v_PRAY_FORE() {
295 VM_PARAM_STRING(last
)
296 VM_PARAM_STRING(type
)
298 result
.setString(findBlock(type
, last
, true, false));
302 PRAY GARB (command) force (integer)
305 if force is 0, make the pray manager garbage-collect resources
306 otherwise, make the pray manager empty its cache entirely
308 recommended to be called after intensive PRAY usage, eg agent installation
310 void caosVM::c_PRAY_GARB() {
311 VM_PARAM_INTEGER(force
)
317 PRAY IMPO (integer) moniker (string) doit (integer) keepfile (integer)
320 void caosVM::v_PRAY_IMPO() {
321 VM_PARAM_INTEGER(keepfile
)
322 VM_PARAM_INTEGER(doit
)
323 VM_PARAM_STRING(moniker
)
325 result
.setInt(4); // TODO
329 PRAY INJT (integer) name (string) install (integer) report (variable)
332 void caosVM::v_PRAY_INJT() {
333 VM_PARAM_VARIABLE(report
)
334 VM_PARAM_INTEGER(install
)
335 VM_PARAM_STRING(name
)
337 // Try installing the dependencies.
338 int r
= prayInstallDeps(name
, install
!= 0);
345 // Now grab the relevant block..
346 std::map
<std::string
, prayBlock
*>::iterator i
= world
.praymanager
.blocks
.find(name
);
347 caos_assert(i
!= world
.praymanager
.blocks
.end());
348 prayBlock
*p
= i
->second
;
351 // .. grab the script count ..
352 std::map
<std::string
, int>::iterator j
= p
->integerValues
.find("Script Count");
353 if (j
== p
->integerValues
.end()) {
354 result
.setInt(-3); // TODO: this isn't really a dependency fail, what do I do here?
357 int noscripts
= j
->second
; caos_assert(noscripts
>= 0);
359 // .. and iterate over the scripts.
360 for (int z
= 1; z
<= noscripts
; z
++) {
361 // First, retrieve the script.
362 std::string scriptname
= boost::str(boost::format("Script %d") % z
);
363 std::map
<std::string
, std::string
>::iterator k
= p
->stringValues
.find(scriptname
);
364 if (k
== p
->stringValues
.end()) {
366 report
->setString(scriptname
);
369 std::string script
= k
->second
;
371 if (!install
) continue;
374 caosVM
*vm
= world
.getVM(NULL
);
376 std::istringstream
iss(script
);
377 caosScript
script(world
.gametype
, name
+ " - PRAY " + scriptname
);
379 script
.installScripts();
381 vm
->runEntirely(script
.installer
);
382 } catch (std::exception
&e
) {
385 report
->setString(scriptname
+ " error: " + e
.what());
386 std::cerr
<< "PRAY INJT caught exception trying to inject " << name
<< " - PRAY " << scriptname
<< ": " << e
.what() << std::endl
;
396 PRAY KILL (integer) resource (string)
399 deletes from disk the file containing the given resource
401 returns 1 upon success, or 0 upon failure (typically no such resource)
403 void caosVM::v_PRAY_KILL() {
404 VM_PARAM_STRING(resource
)
406 result
.setInt(0); // TODO
410 PRAY MAKE (integer) journalspot (integer) journalname (string) prayspot (integer) name (string) report (variable)
413 void caosVM::v_PRAY_MAKE() {
414 VM_PARAM_VARIABLE(report
)
415 VM_PARAM_STRING(name
)
416 VM_PARAM_INTEGER(prayspot
)
417 VM_PARAM_STRING(journalname
)
418 VM_PARAM_INTEGER(journalspot
)
420 result
.setInt(1); // TODO
421 report
->setString("hat u");
425 NET: MAKE (integer) journalspot (integer) journalname (integer) user (string) report (variable)
428 Networking is not supported in openc2e, so conveniently fails.
430 void caosVM::v_NET_MAKE() {
431 VM_PARAM_VARIABLE(report
)
432 VM_PARAM_STRING(user
)
433 VM_PARAM_STRING(journalname
)
434 VM_PARAM_INTEGER(journalspot
)
437 report
->setString("Networking unsupported.");
441 PRAY NEXT (string) type (string) last (string)
444 returns the name of the resource of the specified type which is immediately after last
445 see PRAY FORE if you don't want to loop around
447 void caosVM::v_PRAY_NEXT() {
448 VM_PARAM_STRING(last
)
449 VM_PARAM_STRING(type
)
451 result
.setString(findBlock(type
, last
, true, true));
455 PRAY PREV (string) type (string) last (string)
458 returns the name of the resource of the specified type which is immediately previous to last
459 see PRAY BACK if you don't want to loop around
461 void caosVM::v_PRAY_PREV() {
462 VM_PARAM_STRING(last
)
463 VM_PARAM_STRING(type
)
465 result
.setString(findBlock(type
, last
, false, true));
472 make the pray manager check for deleted/new files in the resource directory
474 void caosVM::c_PRAY_REFR() {
475 world
.praymanager
.update();
479 PRAY TEST (integer) name (string)
482 void caosVM::v_PRAY_TEST() {
483 VM_PARAM_STRING(name
)
485 std::map
<std::string
, prayBlock
*>::iterator i
= world
.praymanager
.blocks
.find(name
);
486 if (i
== world
.praymanager
.blocks
.end())
489 prayBlock
*p
= i
->second
;
492 else if (p
->isCompressed())