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 #include "table/strings.h"
00018 
00019 /* The reason this exists in C++, is that a user can trash his ai/ or game/ dir,
00020  *  leaving no Scripts available. The complexity to solve this is insane, and
00021  *  therefor the alternative is used, and make sure there is always a Script
00022  *  available, no matter what the situation is. By defining it in C++, there
00023  *  is simply no way a user can delete it, and therefor safe to use. It has
00024  *  to be noted that this Script is complete invisible for the user, and impossible
00025  *  to select manual. It is a fail-over in case no Scripts are available.
00026  */
00027 
00029 void Script_CreateDummyInfo(HSQUIRRELVM vm, const char *type, const char *dir)
00030 {
00031   char dummy_script[4096];
00032   char *dp = dummy_script;
00033   dp += seprintf(dp, lastof(dummy_script), "class Dummy%s extends %sInfo {\n", type, type);
00034   dp += seprintf(dp, lastof(dummy_script), "function GetAuthor()      { return \"OpenTTD Developers Team\"; }\n");
00035   dp += seprintf(dp, lastof(dummy_script), "function GetName()        { return \"Dummy%s\"; }\n", type);
00036   dp += seprintf(dp, lastof(dummy_script), "function GetShortName()   { return \"DUMM\"; }\n");
00037   dp += seprintf(dp, lastof(dummy_script), "function GetDescription() { return \"A Dummy %s that is loaded when your %s/ dir is empty\"; }\n", type, dir);
00038   dp += seprintf(dp, lastof(dummy_script), "function GetVersion()     { return 1; }\n");
00039   dp += seprintf(dp, lastof(dummy_script), "function GetDate()        { return \"2008-07-26\"; }\n");
00040   dp += seprintf(dp, lastof(dummy_script), "function CreateInstance() { return \"Dummy%s\"; }\n", type);
00041   dp += seprintf(dp, lastof(dummy_script), "} RegisterDummy%s(Dummy%s());\n", type, type);
00042 
00043   const SQChar *sq_dummy_script = OTTD2SQ(dummy_script);
00044 
00045   sq_pushroottable(vm);
00046 
00047   /* Load and run the script */
00048   if (SQ_SUCCEEDED(sq_compilebuffer(vm, sq_dummy_script, scstrlen(sq_dummy_script), _SC("dummy"), SQTrue))) {
00049     sq_push(vm, -2);
00050     if (SQ_SUCCEEDED(sq_call(vm, 1, SQFalse, SQTrue))) {
00051       sq_pop(vm, 1);
00052       return;
00053     }
00054   }
00055   NOT_REACHED();
00056 }
00057 
00059 void Script_CreateDummy(HSQUIRRELVM vm, StringID string, const char *type)
00060 {
00061   /* We want to translate the error message.
00062    * We do this in three steps:
00063    * 1) We get the error message
00064    */
00065   char error_message[1024];
00066   GetString(error_message, string, lastof(error_message));
00067 
00068   /* Make escapes for all quotes and slashes. */
00069   char safe_error_message[1024];
00070   char *q = safe_error_message;
00071   for (const char *p = error_message; *p != '\0' && q < lastof(safe_error_message) - 2; p++, q++) {
00072     if (*p == '"' || *p == '\\') *q++ = '\\';
00073     *q = *p;
00074   }
00075   *q = '\0';
00076 
00077   /* 2) We construct the AI's code. This is done by merging a header, body and footer */
00078   char dummy_script[4096];
00079   char *dp = dummy_script;
00080   dp += seprintf(dp, lastof(dummy_script), "class Dummy%s extends %sController {\n  function Start()\n  {\n", type, type);
00081 
00082   /* As special trick we need to split the error message on newlines and
00083    * emit each newline as a separate error printing string. */
00084   char *newline;
00085   char *p = safe_error_message;
00086   do {
00087     newline = strchr(p, '\n');
00088     if (newline != NULL) *newline = '\0';
00089 
00090     dp += seprintf(dp, lastof(dummy_script), "    %sLog.Error(\"%s\");\n", type, p);
00091     p = newline + 1;
00092   } while (newline != NULL);
00093 
00094   dp = strecpy(dp, "  }\n}\n", lastof(dummy_script));
00095 
00096   /* 3) We translate the error message in the character format that Squirrel wants.
00097    *    We can use the fact that the wchar string printing also uses %s to print
00098    *    old style char strings, which is what was generated during the script generation. */
00099   const SQChar *sq_dummy_script = OTTD2SQ(dummy_script);
00100 
00101   /* And finally we load and run the script */
00102   sq_pushroottable(vm);
00103   if (SQ_SUCCEEDED(sq_compilebuffer(vm, sq_dummy_script, scstrlen(sq_dummy_script), _SC("dummy"), SQTrue))) {
00104     sq_push(vm, -2);
00105     if (SQ_SUCCEEDED(sq_call(vm, 1, SQFalse, SQTrue))) {
00106       sq_pop(vm, 1);
00107       return;
00108     }
00109   }
00110   NOT_REACHED();
00111 }