Comments on "Script functions documentation"

Discussion in 'Server and Client Scripting' started by Mystra, Sep 8, 2010.

Thread Status:
Not open for further replies.
  1. TheUnknownOne

    TheUnknownOne Member

    Joined:
    Mar 28, 2011
    Messages:
    988
    Likes Received:
    3
    Ok.

    Also for making dirs:
    PHP:
    1.  
    2. function mkdir (dirname) {
    3. sys.system("mkdir "+dirname);
    4. }
    5. function mkdir_in_dir (dirname,dir) {
    6. sys.system("cd "+dirname+" && mkdir "+dir);
    7. }
    8.  
    seems to work. Most servers have safe scripts off but some don't, so you can't rely on it :/
     
  2. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    Make them create dirs manually or through batch file :} You don't even need more directories, since one can have large amount of files. File access is already a mess, considering it does not sandbox you to some path under PO control :\ I'd wish someone fixed this before expanding it.
     
  3. Garma

    Garma Member

    Joined:
    Nov 23, 2011
    Messages:
    80
    Likes Received:
    0
    sys.sendAll() will make a client flash if the players name is posted into the servers main chat; sys.sendHtmlAll() will not. You can only do that with sys.sendHtmlMessage(sys.id(playername), '<ping />bla bla'). A message which is sent only to one specific player with sys.sendHtmlMessage() will also not make the client flash.

    Does this work like it was planned or is it a bug?
     
    Last edited: Dec 28, 2011
  4. Lamperi

    Lamperi I see what you did there

    Joined:
    Apr 25, 2010
    Messages:
    2,647
    Likes Received:
    11
    Flashing is client side feature, not server side. The name check is only performed for plain text messages.
     
  5. TheUnknownOne

    TheUnknownOne Member

    Joined:
    Mar 28, 2011
    Messages:
    988
    Likes Received:
    3
    I decided to make some functions (although most of them are from source code xd), because C++ seems doable by just looking at it. This is also my first c++ code so inb4 errors lol.

    scriptengine.cpp
    Code (cpp):
    1. void ScriptEngine::endBattle(int battleId)
    2. {
    3.         BattleSituation * battle = myserver->getBattle(battleId);
    4.         if (battle) {
    5.             myserver->removeBattle(battleId);
    6.         }
    7.         else {
    8.             warn("endBattle", "No battle with battleId "+battleId+" existing.");
    9.         }
    10. }
    11.  
    12. bool ScriptEngine:isPasswordProtected()
    13. {
    14.     return myserver->isPasswordProtected();
    15. }
    16.  
    17. void ScriptEngine::quickCall(const QScriptValue &func, int delay)
    18. {
    19.     if (delay <= 0) return;
    20.     if (func.isFunction()) {
    21.         QTimer *t = new QTimer(this);
    22.         timerEventsFunc[t] = func;
    23.         t->setSingleShot(true);
    24.         t->start(delay);
    25.         connect(t, SIGNAL(timeout()), SLOT(timerFunc()));
    26.     }
    27. }
    28.  
    29. bool ScriptEngine::banned(const QString &name)
    30. {
    31.     if (!SecurityManager::exist(name)) {
    32.          warn("banned", "No such player named "+name);
    33.          return false;
    34.     }
    35.    
    36.     else
    37.          return SecurityManager::banned(name);
    38. }  
    39.  
    40. bool ScriptEngine::bannedIP(const QString &ip)
    41. {
    42.     return SecurityManager::bannedIP(ip);
    43.  
    44. }
    45.  
    46. void ScriptEngine::reloadConfig()
    47. {
    48.     QSettings s("config", QSettings::IniFormat);
    49.     myserver->serverName = s.value("server_name").toString();
    50.     myserver->serverDesc = s.value("server_description").toString();
    51.     myserver->serverAnnouncement = s.value("server_announcement").toString();
    52.     myserver->serverPlayerMax = quint16(s.value("server_maxplayers").toInt());
    53.     myserver->serverPrivate = quint16(s.value("server_private").toInt());
    54.     myserver->lowTCPDelay = quint16(s.value("low_TCP_delay").toBool());
    55.     myserver->safeScripts = s.value("safe_scripts").toBool();
    56.     myserver->proxyServers = s.value("proxyservers").toString().split(",");
    57.     myserver->passwordProtected = s.value("require_password").toBool();
    58.     myserver->serverPassword = s.value("server_password").toString();
    59.     myserver->showTrayPopup = s.value("show_tray_popup").toBool();
    60.     myserver->minimizeToTray = s.value("minimize_to_tray").toBool();
    61.     myserver->showLogMessages = s.value("show_log_messages").toBool();
    62.     TierMachine::obj()->loadDecaySettings();
    63. }
    64.  
    65. bool ScriptEngine::safeScripts()
    66. {
    67.     return myserver->isSafeScripts();
    68.    
    69. }
    70.  
    71. void ScriptEngine::changeDescription(const QString &html)
    72. {
    73.     if (myserver->serverDesc == html) {
    74.          warn("changeDescription", "Server Description is the same as new description.");
    75.          return;
    76.     }
    77.    
    78.      QSettings s("config", QSettings::IniFormat);
    79.      s.setValue("server_description", html);
    80.      myserver->regDescChanged(html);
    81. }
    82.  
    83. void ScriptEngine::changeServerName(const QString &newname)
    84. {
    85.     if(myserver->serverName == newname) {
    86.          warn("changeServerName","newname is the same as server name");
    87.          return;
    88.     }
    89.    
    90.      QSettings s("config", QSettings::IniFormat);
    91.      s.setValue("server_name", newname);   
    92.      myserver->regNameChanged(newname);
    93.  
    94. }
    95.  
    96. void ScriptEngine::makeDir(const QString &dir)
    97. {
    98.     /*  requires: #include <QDir> */
    99.     QDir newdir;
    100.     newdir.mkdir(dir);
    101. }
    102.  
    103.  
    scriptengine.h
    Code (cpp):
    1. Q_INVOKEABLE void endBattle(int battleid);
    2. Q_INVOKEABLE bool isPasswordProtected();
    3. Q_INVOKEABLE void quickCall(const QScriptValue &func, int delay);
    4. Q_INVOKEABLE bool banned(const QString &name);
    5. Q_INVOKEABLE bool bannedIP(const QString &ip);
    6. Q_INVOKEABLE void reloadConfig();
    7. Q_INVOKEABLE bool safeScripts();
    8. Q_INVOKEABLE void changeDescription(const QString &html);
    9. Q_INVOKEABLE void changeServerName(const QString &newname);
    10. Q_INVOKEABLE void makeDir(const QString &dir);
    11.  
     
    Last edited: Jan 3, 2012
  6. Lamperi

    Lamperi I see what you did there

    Joined:
    Apr 25, 2010
    Messages:
    2,647
    Likes Received:
    11
    Did you test those? Many of them seem to work but what about reloadConfig... I don't think it really reloads all the variables, as in changes the announcement or settings really.

    Look at ServerWidget::OpenConfig. There are the functions you should call.
    Try
    Code (text):
    1. myserver->regNameChanged(s.value("server_name").toString())
    and calling those other functions too. They will have the neccesary side effects too.
     
    Last edited: Jan 3, 2012
  7. TheUnknownOne

    TheUnknownOne Member

    Joined:
    Mar 28, 2011
    Messages:
    988
    Likes Received:
    3
    I'm not sure if i can test them at all. I don't have libraries installed, only QtCreator.

    ---
    Lutra and I have been brainstorming about what's possible. I'll make a thread with the functions soon.
     
    Last edited: Jan 4, 2012
  8. Garma

    Garma Member

    Joined:
    Nov 23, 2011
    Messages:
    80
    Likes Received:
    0
    sys.getColor() returns #000000 if a user has no name color chosen by himself. Is there any way that can/will be fixed? I modified the standard message to have rank icons and bb codes but when trying to get the users name color with sys.getColor() every user with no specified color is shown black ... :S
     
  9. Lamperi

    Lamperi I see what you did there

    Joined:
    Apr 25, 2010
    Messages:
    2,647
    Likes Received:
    11
    It is theme dependant. You can't get the exact behaviour with Html directly, but you can check:

    Themes/Classic/client/chat_colors.txt

    The color for players with color #000000 is chosen this way:
    Code (text):
    1.  
    2. var colors = sys.getFileContent("Themes/Classic/client/chat_colors.txt").split(/\n/);
    3. function user_color(id) {
    4.     var color = sys.getColor(id);
    5.     if (color != "#000000")
    6.         return color;
    7.     else
    8.         return colors[id % colors.length];
    9. }
    10.  
    This will work for people who use themes which do not have modified chat_colors.txt
     
  10. Garma

    Garma Member

    Joined:
    Nov 23, 2011
    Messages:
    80
    Likes Received:
    0
    Script Error line 59: TypeError: Result of expression 'sys.getFileContent("Themes/Classic/client/chat_colors.txt")' [undefined] is not an object.

    Server can't find that path :x
     
  11. Lamperi

    Lamperi I see what you did there

    Joined:
    Apr 25, 2010
    Messages:
    2,647
    Likes Received:
    11
    copy it from client installation
     
  12. Garma

    Garma Member

    Joined:
    Nov 23, 2011
    Messages:
    80
    Likes Received:
    0
    Yep, this works. Thanks.
     
  13. Kalashnikov

    Kalashnikov Despite the code quality

    Joined:
    Apr 4, 2011
    Messages:
    434
    Likes Received:
    0
    How exactly does import (require) work?
    Assuming test.js has nothing but var a = 'test';
    Code (javascript):
    1.  
    2. var b = sys.require('test.js');
    3. sys.print(a);   // Fails with ReferenceError: Can't find variable: a
    4. sys.print(b);   // Fails with SyntaxError: too few arguments in call to print(); (b is undefined)
    5.  
     
  14. Lamperi

    Lamperi I see what you did there

    Joined:
    Apr 25, 2010
    Messages:
    2,647
    Likes Received:
    11
    There is no require?
     
  15. Kalashnikov

    Kalashnikov Despite the code quality

    Joined:
    Apr 4, 2011
    Messages:
    434
    Likes Received:
    0
    Well, I mean:
    Code (javascript):
    1.  
    2. sys.require = sys['import']     // hack, should be fixed in the next release
    3.  
     
  16. Lamperi

    Lamperi I see what you did there

    Joined:
    Apr 25, 2010
    Messages:
    2,647
    Likes Received:
    11
    I'm trying to implement proper module system modeled after commonJS's require-thing.

    http://valssi.fixme.fi/~lamperi/pokemononline/ScriptTest.zip here is a small testing project with proper require-function. It still needs to be able to require relativele, ie. first require modules/channels/mafia.js which then includes "staff.js", which is also in modules/channels/.... or should it?
     
  17. Kalashnikov

    Kalashnikov Despite the code quality

    Joined:
    Apr 4, 2011
    Messages:
    434
    Likes Received:
    0
    Hmm, so it's not possible to return something from required script or define some functions/variables/classes there in current (.53) implementation?

    Maybe in that example you should import staff.js before importing mafia.js and channels.js so they can use the same instance (wait, can required scripts access main scope?) while leaving the possibility for them to import their own staff.js which will not intersect.

    P.S. Qt's eval is kinda strange, it seems it evaluates the code in some different scope, even this won't work
    Code (javascript):
    1.  
    2. sys.eval('var a = "test"');
    3. sys.sendAll(a);    // undefined variable
    4.  
     
  18. Lamperi

    Lamperi I see what you did there

    Joined:
    Apr 25, 2010
    Messages:
    2,647
    Likes Received:
    11
    Currently sys["import"]("foo.js") is same as eval(sys.getFileContent("scripts/foo.js") ... I'm not even sure why it is there in it's current form.Evaluating a script (sys.eval, sys["import"], plain old eval) just return the last value defined in the script. Otherwise the local scope is lost, as it is evaluated in it's own scope.

    Note: eval("var a = 1+1") returns undefined, as var statement returns undefined. eval("a = 1+1") returns 2. So, to return a value from plain evaluated script, make last line contain the object you want to return
    (even if the line is just mafia)

    edit: Actually sys.eval and eval are different. Only eval evaluates in the current context, so that
    Code (text):
    1.  
    2. eval("var a = 1+3"); print(a)
    3.  
    works like you though, but
    Code (text):
    1.  
    2. sys.eval("var a = 1+3"); print(a)
    3.  
    does not.
     
  19. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    Why do you need sys.eval if you can do eval() instead? (@_@)
     
  20. Kalashnikov

    Kalashnikov Despite the code quality

    Joined:
    Apr 4, 2011
    Messages:
    434
    Likes Received:
    0
    I didn't even know there's native eval, I thought they incapsulated it in sys.eval making it safer or something...
    And imo getting rid of eval is better than using either of them anyway.
     
  21. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    Well, Javascript itself supposed to have eval() :} I use it to make MOVE_* variables. Quite handy. Although if you can do something without eval() and not write 9999 lines in the process… then yes, it's better.
     
  22. Lamperi

    Lamperi I see what you did there

    Joined:
    Apr 25, 2010
    Messages:
    2,647
    Likes Received:
    11
    You can always assign using this["MOVE_FIRE_FANG"] in global context to avoid eval. Then use as MOVE_FIRE_FANG :x
     
  23. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    >this
    >Javascript

    The less I see that the better XD
     
  24. Lamperi

    Lamperi I see what you did there

    Joined:
    Apr 25, 2010
    Messages:
    2,647
    Likes Received:
    11
    Well it's not eval >_>
     
  25. Garma

    Garma Member

    Joined:
    Nov 23, 2011
    Messages:
    80
    Likes Received:
    0
    Is it possible that sys.putInChannel calls the ChannelJoin() event? My /invite player:channel command works fine, but I can't give access to the Team Channel to non-auth users and I think forcing someone to join a channel should put that player into the selected channel, no matter what beforeChannelJoin event does :x
     
  26. Lamperi

    Lamperi I see what you did there

    Joined:
    Apr 25, 2010
    Messages:
    2,647
    Likes Received:
    11
    Yes, beforeChannelJoin will be done after putInChannel. you can see PO scripts how to make invite system (basically, just carry a invite list per channel to bypass limits on beforeChannelJoin)
     
  27. Garma

    Garma Member

    Joined:
    Nov 23, 2011
    Messages:
    80
    Likes Received:
    0
    Hm ok, I'll do it that way then.
     
  28. The Lightining

    The Lightining New Member

    Joined:
    Mar 13, 2012
    Messages:
    11
    Likes Received:
    0
    Yes wht is the differance between them
     
  29. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    Note. Currently nothing much is done here since CHANGES CHANGES EVERYWHERE. Well, in some places at least, but that's enough of a reason. Nobody likes to do the same thing twice :}
     
  30. Manectric-Rang

    Manectric-Rang Unown-Ç ftw

    Joined:
    Mar 21, 2012
    Messages:
    60
    Likes Received:
    0
    Feature request

    Well, just a suggestion:

    sys.teamRestore(player_id) → Restores player's team to the team it had on the teambuilder. This would be useful if that team was modified by scripts.
     
    Last edited: Apr 2, 2012
  31. Lamperi

    Lamperi I see what you did there

    Joined:
    Apr 25, 2010
    Messages:
    2,647
    Likes Received:
    11
    You can make scripts to track the changes. There is currently no code in the server which would make that easier to implement server C++ side than Javascript side.
     
  32. Manectric-Rang

    Manectric-Rang Unown-Ç ftw

    Joined:
    Mar 21, 2012
    Messages:
    60
    Likes Received:
    0
    That is not so easy if scripts change a team completely, including EVs and IVs. But I hope 20 teams or so are nothing for a RAM.

    Thanks!
     
  33. [ƦЄ]Blade

    [ƦЄ]Blade Not sure.

    Joined:
    Mar 6, 2011
    Messages:
    75
    Likes Received:
    0
    The team files are tiny...
    I don't even think 200 teams are a problem for RAM.
    Hey, can someone teach me how to use sys.callLater?
    Everytime I try to use it, the string I call happens immediately, instead of the time I put.
     
  34. Kalashnikov

    Kalashnikov Despite the code quality

    Joined:
    Apr 4, 2011
    Messages:
    434
    Likes Received:
    0
    You can't access files, so you'll have to save all the data along changing it with sys.changeTeamPoke* which might be pretty tedious.

    Haven't you forgot the second parameter?
     
  35. [ƦЄ]Blade

    [ƦЄ]Blade Not sure.

    Joined:
    Mar 6, 2011
    Messages:
    75
    Likes Received:
    0
    I did have the second parameter. I tested something like
    Code (text):
    1. sys.callLater(sys.sendMessage(src, "Hi."), 5);
    with eval and it'd appear immediately ._.

    EDIT: Nevermind, I figured it out.
     
    Last edited: Apr 3, 2012
  36. Mystra

    Mystra Active Member

    Joined:
    Jul 12, 2010
    Messages:
    1,389
    Likes Received:
    4
    Is there anything that prevents saving and restoring manually with JS? I did part of that in my own server and it worked.
     
  37. Manectric-Rang

    Manectric-Rang Unown-Ç ftw

    Joined:
    Mar 21, 2012
    Messages:
    60
    Likes Received:
    0
    Feature request

    This is not a function but an event.

    afterBattleEnded(winner, loser, result, battle_id, score, turns) → Could this event return the score of the battle (6-0, 1-0, etc...) and the number of turns it took?
     
Thread Status:
Not open for further replies.