# script_info_dummy.cpp

Go to the documentation of this file.

    00001 /* $Id: script_info_dummy.cpp 24776 2012-12-01 13:12:39Z alberth $ */
    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 }