Features you'd like to see.

Started by ., Mar 23, 2016, 09:00 PM

Previous topic - Next topic

.

I'd like to ask people what features do you think are missing from the official Squirrel plug-in so that I could implement them in the one that I'm working on.

Speak your mind here about situations where certain things would've made your life easier and you think would make sense to have in a scripting plug-in.

Keep in mind that your suggestion is open for debate. And if that feature already exists I'll give you an example of it. And if it's planed for later then I'll discuss the way I thought to implement it.

I'll be waiting for your feedback.


NOTE: This plug-in might be obsolete in near future since the devs are working on something else. This is for those that want to stick with Squirrel because that's what they've got used to.
.

Mötley

Well no clue as to "is this for a in particular plug-in" if not hear is what would make my life easier and possibly others.

:: A plug-in that will have a method of reloading the script every 6 squirrel [hour] or somewhere in that line of work as ReloadScripts(); does not work properly with function onScriptUnload() This could be very helpful with maintaining the server performance. If you know of any methods that could help a servers performance, This would help Aid the owners servers from lagging out from to much data in the memory,  preventing any possible issues, possible even a crash or future lag as the memory begins to build up, ??? Just posting what would make it easier on myself,.

.

#2
Quote from: Mr_Motley on Mar 23, 2016, 10:05 PM:: A plug-in that will have a method of reloading the script every 6 squirrel [hour]

Not really sure how this would improve the performance in any way to be honest. I haven't implemented the reload functionality directly yet but I've left room to easily add it later.

But if this is really a necessary thing, it could be achieved using a routine:
SqRoutine.Create(getroottable(), function(
    SqCore.Reload(true);
), SqTime.Hours(6).MillisecondsRaw, 1).SetTag("AutoReload");

The 'false' argument tells the plugin to reload the scripts before processing any data during the next frame event. Where as 'true' would process data during the next frame events and then reload the scripts. Because the scripts are never reloaded in the middle of the execution.

The 'true' argument tells the plugin to reload the scripts at the end of the current execution. Where as 'false' would disable the reloading if it was enabled before. SqCore.Reloading() returns the boolean value that tells if reloading was enabled.

Also notice that I'm not saving that timer which is why I've gave it a tag so that I can later retrieve it and stop it or modify it if I want to.
SqRoutine.FindByTag("AutoReload").Terminate();
Otherwise I'd have no possibility of stopping/modifying that timer.
.

Mötley

#3
Understanding..

Unfortuntly I wanted to create an error and test it in a cmd build and was capable of fixing it even though I feel it is still an error but data is still written to the account etc

  if (cmd == "reset" || cmd == "restartserver") {
    if (admin[player.ID] < 1) {
      AdminCommand(player);
      return true;
    }
    (onScriptUnload() || ReloadScripts());
    return true;
  }

//part of an 5 minute timer
  if (Date["hour"] == 6 && Date["min"] == 0) {
  (onScriptUnload() || ReloadScripts());
  }
Sorry for the inconvenience as I was going to delete the post

aXXo

Will existing squirrel scripts be fully(or semi) compatible with the new plugin or everything will need a complete re-write?



The onPlayerMove() function is unusable, it should be removed. In most cases this function is used to detect when a player enters/exits an area. Could we have something that can be used without causing lag?

Example:
[CZone] CreateZone( [float] minX, [float] minY, [float] minZ, [float] maxX, [float] maxY, [float] maxZ )
It should accept null parameters to make it possible to create 2D or 1D zones.

CZone Properties:
.ID
.minX, .minY, .minZ,
.maxX, .maxY, .maxZ
.Remove()

onPlayerEnterZone( player, zoneID )
onPlayerExitZone( player, zoneID )



The GetWeaponName() needs improvement. GetWeaponName( "stormeus" ) should not return "Stubby Shotgun". 8)



Script extensions:
This might not be in scope of the squirrel plugin, but I'll suggest it here:
If possible, the server should look for a directory called "extensions" in the directory. The plugin should automatically dofile() every .nut in this directory, without the scripter calling it in their main script file.

The extensions directory could have further sub directory called libraries. NUT files inside <extensions/libraries/> should be automatically compiled before the script file specified in server.cfg. (highest priority)
NUT files inside <extensions/> should be executed after all the other files are compiled.

This would make sharing squirrel code much easier.



Appending/Attaching functions(hooking)
local myVehicleFunc = function( player, vehicle ) {}

myVehicleFunc.attach( "onPlayerEnterVehicle" )
Will attach the new function to VCMP's event. Hence, every time onPlayerEnterVehicle is called, myVehicleFunc is also called.
Together with script extensions idea suggested above, sending code to noobs will simply be drag-dropping files in folders.

.

#5
Quote from: aXXo on Mar 24, 2016, 12:44 AMWill existing squirrel scripts be fully(or semi) compatible with the new plugin or everything will need a complete re-write?

If I had kept most of the implementation similar then it wouldn't be any different than the plugin we have already. What I've kept was mostly the naming style. Scripts will require a partial re-write. You'll most likely end up ditching most of the redundant code because the plugin tries to replace repetitive code.



Quote from: aXXo on Mar 24, 2016, 12:44 AMThe onPlayerMove() function is unusable, it should be removed. In most cases this function is used to detect when a player enters/exits an area. Could we have something that can be used without causing lag?

Example:
[CZone] CreateZone( [float] minX, [float] minY, [float] minZ, [float] maxX, [float] maxY, [float] maxZ )
It should accept null parameters to make it possible to create 2D or 1D zones.

CZone Properties:
.ID
.minX, .minY, .minZ,
.maxX, .maxY, .maxZ
.Remove()

onPlayerEnterZone( player, zoneID )
onPlayerExitZone( player, zoneID )

Yes this is something that I am currently thinking about. The onMove event is still exposed to the server because it has to be there in case anyone needs it. And trust me, there are situations where you need such callback.

As for the zone thing I can't say much right now because I haven't yet figured out the full implementation. Once I get something started I'll be sure to post it here or in the main thread.



Quote from: aXXo on Mar 24, 2016, 12:44 AMThe GetWeaponName() needs improvement. GetWeaponName( "stormeus" ) should not return "Stubby Shotgun". 8)
Well, that's probably because the function doesn't need the full name to retrieve a name. But I think you mean the GetWeaponID function, right? Because GetWeaponName takes an ID and returns the name. Whereas GetWeaponID takes a name and returns a weapon ID.

Let's have the following code:

local id = GetWeaponID("stormeus");
print( GetWeaponName(id) );

Let me explain why this happens. This is the code that does it:
        // [S]crewdriver
        // [S]ilenced Ingram
        // [S]niper Rifle
        // [S]PAS-12 Shotgun
        // [S]tubby Shotgun
        // [S]uicide
        case 's':
            // [Sc]rewdriver
            if (b == 'c') return SQMOD_WEAPON_SCREWDRIVER;
            // [Si]lenced Ingram
            else if (b == 'i') return SQMOD_WEAPON_INGRAM;
            // [Sn]iper Rifle
            else if (b == 'n') return SQMOD_WEAPON_SNIPER;
            // [SP]AS-12 Shotgun
            else if (b == 'p') return SQMOD_WEAPON_SPAS12;
            // [St]ubby Shotgun
            else if (b == 't') return SQMOD_WEAPON_STUBBY;
            // [Su]icide
            else if (b == 'u') return SQMOD_WEAPON_SUICIDE;
            // Default to unknwon
            else return SQMOD_UNKNOWN;

The function takes the first 3 significant characters from the name in 3 variables "a", "b", "c" and the the last character in another variable named "d"

First it sees that the first letter was 's' (the "a" variable) so then it looks for weapon candidates that begin with the letter 's'. Then it checks for the second character which is 't' and since none of the weapons that begin with the character 's' have a second character 't' except stubby. It assumes that's what you want.

In reality all you need to pas is "st" and you'd still get stubby. You could pass "stupid" and you'd still get stubby. Because only the first 2 characters are required for this weapon.

In cases where collisions could occur you probably need to specify more characters and sometimes even the last character is used to tell which weapon was requested. Example is the weapon names that have a similar name except the last character.

And the same applies for vehicle and skin names.



Quote from: aXXo on Mar 24, 2016, 12:44 AMScript extensions:
This might not be in scope of the squirrel plugin, but I'll suggest it here:
If possible, the server should look for a directory called "extensions" in the directory. The plugin should automatically dofile() every .nut in this directory, without the scripter calling it in their main script file.

The extensions directory could have further sub directory called libraries. NUT files inside <extensions/libraries/> should be automatically compiled before the script file specified in server.cfg. (highest priority)
NUT files inside <extensions/> should be executed after all the other files are compiled.

This would make sharing squirrel code much easier.

You can't really use this approach because of the order of execution. In your directory, scripts will be executed alphabetically.

Let's say that you have script A.nut which has:
print(Test.Value);
And then script B.nut which has:
enum Test
{
    Value = 1
};

The code from script A.nut needs to be compiled after the code from B.nut. But because they're compiled alphabetically, you're going to have an issue there.

What the plugin allows you to do is to specify as many scripts as you want in the configuration file:
[Scripts]
Source=addons/B.nut
Source=scripts/A.nut
#Source=utils/C.nut

They're executed in the order that you add them. The third one is commended out so it's never executed.



Quote from: aXXo on Mar 24, 2016, 12:44 AMAppending/Attaching functions(hooking)
local myVehicleFunc = function( player, vehicle ) {}

myVehicleFunc.attach( "onPlayerEnterVehicle" )
Will attach the new function to VCMP's event. Hence, every time onPlayerEnterVehicle is called, myVehicleFunc is also called.
Together with script extensions idea suggested above, sending code to noobs will simply be drag-dropping files in folders.

This feature is already implemented. Because the plugin was developed with OOP in mind. You can attach to events of a certain player/vehicle/pickup etc. And you'll receive events only from that player/vehicle/pickup etc.

And example will be added here soon.
.

KAKAN

I want something like this, it's somewhat same to @aXXo's request.
oh no

.

Quote from: KAKAN on Mar 24, 2016, 02:29 AMI want something like this, it's somewhat same to @aXXo's request.

Already planned to be a part of the standard plugin library. I was waiting to have at least a beta first to see how I should implement it. I'll post the example code in this post as soon as I have something working.
.

aXXo

Quote from: S.L.C on Mar 24, 2016, 01:52 AMIn reality all you need to pas is "st" and you'd still get stubby. You could pass "stupid" and you'd still get stubby. Because only the first 2 characters are required for this weapon.
It is a minor discrepancy, which occurs when a player is trying to send "steroids" but ends up getting a stubby to the face #ArgoDrugDealsGoneWrong.
Of course it is easy to fix with a small workaround and a simple check, but I still prefer if the GetWeaponID() checks if the argument passed in the function is a sub-string of the intended weapon before returning the weapon ID. It will take a performance hit, but will be more accurate.

Quote from: S.L.C on Mar 24, 2016, 01:52 AMYou can't really use this approach because of the order of execution. In your directory, scripts will be executed alphabetically.

Let's say that you have script A.nut which has:
print(Test.Value);
And then script B.nut which has:
enum Test
{
    Value = 1
};

The code from script A.nut needs to be compiled after the code from B.nut. But because they're compiled alphabetically, you're going to have an issue there.

What the plugin allows you to do is to specify as many scripts as you want in the configuration file:
[Scripts]
Source=addons/B.nut
Source=scripts/A.nut
#Source=utils/C.nut

They're executed in the order that you add them. The third one is commended out so it's never executed.

Yes, that's the reason I mentioned 2 directories:
  • /extensions/
  • /extensions/libraries/
Flow of compilation:
- Squirrel plugin loads.
- Squirrel plugin checks if the /extensions/ directory exists
- If found, Squirrel plugin checks if the /extensions/libraries/ directory exists.
- If found, all the .nut files inside /extensions/libraries/ should be compiled first.
- Then proceed with the normal flow and compile the files that are specified inside the configuration file, server.cfg
[Scripts]
Source=addons/B.nut
Source=scripts/A.nut
#Source=utils/C.nut
- Then compile all the .nut files inside the /extensions/ directory.

In your example, the B.nut which has the enum will be placed inside the /extensions/libraries/ directory. So, it is forced to be compiled before A.nut which is located in the /extensions/ directory.

The objective here is to make sharing code easy. It allows someone to release a snippet and organize the script files by packing them into the /extensions/ and /extensions/libraries directory. The author should take care that the stuff that needs pre-compilation(like enums or other function definitions) need to go inside /extensions/libraries/.

So, if someone needs to implement the release in their server, all they need to do is unzip the contents in their server directory and it should be ready to go. No need to edit server.cfg or add dofile() statements.

.

#9
@aXXo Is it ok if I just implement the feature that KAKAN mentioned and allow the user to implement his own function that loads scripts from a directory? That way we can make the feature optional and be easy for the user to customize. For example, execute libraries that begin with "Critical..." first and those that begin with "Latent..." after. And those that begin with "Dev" only during development. Would have the same desired effect except it allows the user to customize.
.

Xmair

Make a CreateMovableGate like seby suggested once.

Credits to Boystang!

VU Full Member | VCDC 6 Coordinator & Scripter | EG A/D Contributor | Developer of VCCNR | Developer of KTB | Ex-Scripter of EAD

EK.IceFlake

RestartServer();
player.AcceptKeys(int keyid, bool accept);

aXXo

Quote from: S.L.C on Mar 24, 2016, 04:52 AM@aXXo Is it ok if I just implement the feature that KAKAN mentioned and allow the user to implement his own function that loads scripts from a directory? That way we can make the feature optional and be easy for the user to customize. For example, execute libraries that begin with "Critical..." first and those that begin with "Latent..." after. And those that begin with "Dev" only during development. Would have the same desired effect except it allows the user to customize.
Yes, that would definitely work. But it won't be of much help to the type of users I'm trying to target here.
I prefer if people could just drag and drop .nut files in their folders and the plugin loads the scripts automatically. In kakan's suggestion, they would still need to use the GetFileList() function and dofile them in a loop in their main script.
The people I'm trying to target are guys who dont't even want to look at code or have a text editor. Guys who map objects, fetch coordinates or test custom object,weps,skins etc.
Guys who just want to host a private TDM script at their home PC and play with their friends to practice for an upcoming clan war.
It would also help with newbie scripters who ask "Where do I place this code?" or "this code does not work for me!" because they fail to incorporate copy-pasted stuff in their existing scripts.

KAKAN

#13
This thing is kinda impossible, but I want a way to stream more than 3000 vehicles, objects etc( already in SAMP ).

And also, this thing is impossible via scripts, still then, can you give it a try? The things are NPC's. It's the most awaited feature in VCMP( I think ).( @Stormeus can add this functionality using the client. Currently, we can only use objects for NPC, but it would use a shit use of onPlayerMove in-case we want the NPC function correctly. So, I want you to add this :D )

And also, this is impossible too, but we want GUI. Make some functions for it then we may request @Stormeus to add GUI functionality in the client :)



Quote from: aXXo on Mar 24, 2016, 04:39 PMYes, that would definitely work. But it won't be of much help to the type of users I'm trying to target here.
I prefer if people could just drag and drop .nut files in their folders and the plugin loads the scripts automatically. In kakan's suggestion, they would still need to use the GetFileList() function and dofile them in a loop in their main script.
The people I'm trying to target are guys who dont't even want to look at code or have a text editor. Guys who map objects, fetch coordinates or test custom object,weps,skins etc.
Guys who just want to host a private TDM script at their home PC and play with their friends to practice for an upcoming clan war.
It would also help with newbie scripters who ask "Where do I place this code?" or "this code does not work for me!" because they fail to incorporate copy-pasted stuff in their existing scripts.
True dat. Hope SLC agrees here. Anyways, I wanted the GetFileList for some other purpose. Your suggestion is great too, helpful for newbies. We can create an INI file which would store that Boolean value. If it's true, then it would compile all the scripts present in that folder.( 'that'/path to the folder is to be defined in the INI file )



Quote from: NE.CrystalBlue on Mar 24, 2016, 12:14 PMRestartServer();
player.AcceptKeys(int keyid, bool accept);
What would RestartServer do? We already got ReloadScripts function. Just a bit editing to the onScriptLoad part would make it perfect.

player.AcceptKeys? need some more information on this.
oh no

.

#14
Guys come on? MP3 Sounds? This is not something I can possibly implement.



NPC? Again, how could  possibly implement this on a scripting plugin? If the server had the options to create NPC, then I could probably write the AI system for them to help out the user. But nothing more than that.



GUI? Again, not something I could implement. I could implement wrappers and helpers to interact with it but nothing more than that. There are things that I simply cannot create. Not not that I wouldn't know to do it. I just simply can't do it without a messed up way of using it.



Restart Server? I could possibly create a function that retrieves the server process PID and then you can create your own restart utility which you can call with with the system() function.

system(format("restart.exe -p %d -e \"%s\"",
                GetServerProcessPID(),
                SqSysPath.With(SqSysPath.Current(), "server.exe").String));

Then your "restart.exe" kills the process with the specified PID and starts the one at the specified path. That utility can even be a python script or something simple.

@Stormeus Can you update ShutdownServer() to take an arbitrary integer as the return code? So that we can have our ways of communicating with the scripts that start our server?



Drag and Drop?

Again... I will never implement such thing directly. However, I could implement script callbacks that you can attach to and listen to the dropped files directly. That way, you can filter the files you want and execute or place them where you want. For example if you see you dropped a .png file you can copy that to the storage directory. If you see a .xml file was dropped and has the name "Objects" you can scan it for objects you want to create.

Like I said, I will never implement such features directly. Because they seem finical and particular to one person. I am trying to cover a broader range of scripters without imposing certain implementations on them.



CreateMovableGate? Again, this is something that could be implemented in script and seems particular to a certain person. Which is why I will create helpers to achieve this more easily but never enforce such thing on the scripter.



I hope I was quite clear that I don't want to impose features on scripters. I will only create helpers to help him create what he needs or someone else to create it and he just has to copy that script and and add a path in the config file. If that's too hard, then perhaps scripting is not for him.
.