script_info_dummy.cpp

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #include <squirrel.h>
00013 #include "../stdafx.h"
00014 
00015 #include "../string_func.h"
00016 #include "../strings_func.h"
00017 
00018 /* The reason this exists in C++, is that a user can trash his ai/ or game/ dir,
00019  *  leaving no Scripts available. The complexity to solve this is insane, and
00020  *  therefore the alternative is used, and make sure there is always a Script
00021  *  available, no matter what the situation is. By defining it in C++, there
00022  *  is simply no way a user can delete it, and therefore safe to use. It has
00023  *  to be noted that this Script is complete invisible for the user, and impossible
00024  *  to select manual. It is a fail-over in case no Scripts are available.
00025  */
00026 
00028 void Script_CreateDummyInfo(HSQUIRRELVM vm, const char *type, const char *dir)
00029 {
00030   char dummy_script[4096];
00031   char *dp = dummy_script;
00032   dp += seprintf(dp, lastof(dummy_script), "class Dummy%s extends %sInfo {\n", type, type);
00033   dp += seprintf(dp, lastof(dummy_script), "function GetAuthor()      { return \"OpenTTD Developers Team\"; }\n");
00034   dp += seprintf(dp, lastof(dummy_script), "function GetName()        { return \"Dummy%s\"; }\n", type);
00035   dp += seprintf(dp, lastof(dummy_script), "function GetShortName()   { return \"DUMM\"; }\n");
00036   dp += seprintf(dp, lastof(dummy_script), "function GetDescription() { return \"A Dummy %s that is loaded when your %s/ dir is empty\"; }\n", type, dir);
00037   dp += seprintf(dp, lastof(dummy_script), "function GetVersion()     { return 1; }\n");
00038   dp += seprintf(dp, lastof(dummy_script), "function GetDate()        { return \"2008-07-26\"; }\n");
00039   dp += seprintf(dp, lastof(dummy_script), "function CreateInstance() { return \"Dummy%s\"; }\n", type);
00040   dp += seprintf(dp, lastof(dummy_script), "} RegisterDummy%s(Dummy%s());\n", type, type);
00041 
00042   const SQChar *sq_dummy_script = OTTD2SQ(dummy_script);
00043 
00044   sq_pushroottable(vm);
00045 
00046   /* Load and run the script */
00047   if (SQ_SUCCEEDED(sq_compilebuffer(vm, sq_dummy_script, scstrlen(sq_dummy_script), _SC("dummy"), SQTrue))) {
00048     sq_push(vm, -2);
00049     if (SQ_SUCCEEDED(sq_call(vm, 1, SQFalse, SQTrue))) {
00050       sq_pop(vm, 1);
00051       return;
00052     }
00053   }
00054   NOT_REACHED();
00055 }
00056 
00058 void Script_CreateDummy(HSQUIRRELVM vm, StringID string, const char *type)
00059 {
00060   /* We want to translate the error message.
00061    * We do this in three steps:
00062    * 1) We get the error message
00063    */
00064   char error_message[1024];
00065   GetString(error_message, string, lastof(error_message));
00066 
00067   /* Make escapes for all quotes and slashes. */
00068   char safe_error_message[1024];
00069   char *q = safe_error_message;
00070   for (const char *p = error_message; *p != '\0' && q < lastof(safe_error_message) - 2; p++, q++) {
00071     if (*p == '"' || *p == '\\') *q++ = '\\';
00072     *q = *p;
00073   }
00074   *q = '\0';
00075 
00076   /* 2) We construct the AI's code. This is done by merging a header, body and footer */
00077   char dummy_script[4096];
00078   char *dp = dummy_script;
00079   dp += seprintf(dp, lastof(dummy_script), "class Dummy%s extends %sController {\n  function Start()\n  {\n", type, type);
00080 
00081   /* As special trick we need to split the error message on newlines and
00082    * emit each newline as a separate error printing string. */
00083   char *newline;
00084   char *p = safe_error_message;
00085   do {
00086     newline = strchr(p, '\n');
00087     if (newline != NULL) *newline = '\0';
00088 
00089     dp += seprintf(dp, lastof(dummy_script), "    %sLog.Error(\"%s\");\n", type, p);
00090     p = newline + 1;
00091   } while (newline != NULL);
00092 
00093   dp = strecpy(dp, "  }\n}\n", lastof(dummy_script));
00094 
00095   /* 3) We translate the error message in the character format that Squirrel wants.
00096    *    We can use the fact that the wchar string printing also uses %s to print
00097    *    old style char strings, which is what was generated during the script generation. */
00098   const SQChar *sq_dummy_script = OTTD2SQ(dummy_script);
00099 
00100   /* And finally we load and run the script */
00101   sq_pushroottable(vm);
00102   if (SQ_SUCCEEDED(sq_compilebuffer(vm, sq_dummy_script, scstrlen(sq_dummy_script), _SC("dummy"), SQTrue))) {
00103     sq_push(vm, -2);
00104     if (SQ_SUCCEEDED(sq_call(vm, 1, SQFalse, SQTrue))) {
00105       sq_pop(vm, 1);
00106       return;
00107     }
00108   }
00109   NOT_REACHED();
00110 }