SRL Archive - General

New extra system.


Gu3st...

2011-01-20 18:27:36

I present to you; The new Extra system!

This system makes it possible for users to activate/deactivate extras on-fly if they want to, and it will allow Extra writers to take advantage of the include.
It's also possible to add activate/deactivate form to the MSI Form.
It's still possible to use the old "system" even though we have this system, but with this system, the user is allowed to do much more advanced things, and will make the job of making extras work with the include much easier!

With this system, extras can be loaded into memory using the variable MSI_Extras, which is an array of TExtra:
type
TExtra = record
Name, Author, Version : String;
Setup : function: Boolean;
Enabled : Boolean;
PointerCount, Constant : Integer;
Pointers : TPointerArray;
end;
As you can see, TExtra has information about the name of the extra, the author, the version, what function it uses to initialize the extra, if it's enabled or not (user setting) and Constant and some other stuff (PointerCount, Pointers).

All those things that I listed there except PointerCount and Pointers are self-explanatory. Pointers is an array of TPointer:
type
TPointer = record
Constant : Integer;
FunctionCall : function: Integer;
end;
TPointer has two variables. Constant can be MSI_onMSIWalkCall, MSI_onMSIDebugCall and so on and FunctionCall is the function to call when the function associated with the proper Constant (MSI_onFunctionXCall) is called.

This means scripters can make their Extra do stuff when MSI calls functions. This can be very helpful in some cases (One example is MSI_Walk. It would benefit a WorldWalker to hook that function).

Now we'll get to the new Extras.simba. In this function MSI will call the function LoadAllExtras:
procedure MSI_LoadAllExtras;
var
Extras : TStringArray;
H, I : Integer;
V : TVariantArray;
NotUsing : Boolean;
begin
Extras := GetFiles(PATH_EXTRAS, 'simba');

SetArrayLength(MSI_Extras, Length(Extras));
if Length(Extras) = 0 then Exit;
H := High(Extras);
for I := 0 to H do
Delete(Extras[I], Pos('.', Extras[I]), Length(Extras[I]));

H := High(MSI_Extras);
for I := 0 to H do
begin
CurrentExtra := I;

NotUsing := False;
try
CallProc(Extras[CurrentExtra] + '_Attach', V);
WriteLn('Using Extra ''' + MSI_Extras[CurrentExtra].Name + ''' by ' + MSI_Extras[CurrentExtra].Author + ', v ' + MSI_Extras[CurrentExtra].Version + '.');
except
NotUsing := True;
end;
if NotUsing then
begin
WriteLn('Not using Extra ''' + Extras[CurrentExtra] + '''. Attach function not found.');
Continue;
end;

if MSI_Extras[CurrentExtra].Setup <> nil then
begin
if MSI_Extras[CurrentExtra].Setup() then
begin
MSI_Extras[CurrentExtra].Constant := CurrentExtra;
MSI_Extras[CurrentExtra].Enabled := True;
end;
end else
begin
WriteLn('Not using Extra ''' + Extras[CurrentExtra] + '''. Setup function not found.');
Continue;
end;

if MSI_Extras[CurrentExtra].PointerCount > 0 then
begin
H := High(MSI_Extras[CurrentExtra].Pointers);
if H <> 0 then
for I := 0 to H do
begin

WriteLn([CurrentExtra, I, H]);

if MSI_Pointers[MSI_Extras[CurrentExtra].Pointers[I].Constant].FunctionCall <> nil then
begin
WriteLn('Pointer already used! Turning off ' + MSI_Extras[CurrentExtra].Name + '...');
MSI_Extras[CurrentExtra].Enabled := False; // There's a bug here. Will fix later!
Break;
end else
begin
MSI_Pointers[MSI_Extras[CurrentExtra].Pointers[I].Constant].FunctionCall := MSI_Extras[CurrentExtra].Pointers[I].FunctionCall;
WriteLn('Pointer used: ' + IntToStr(MSI_Extras[CurrentExtra].Pointers[I].Constant) + '.');
end;

end;
end;

end;
end;

What this procedure does is to check all the files in the Extra folder for a function named *Extra_Name*_Attach, and if found it'll try calling that function. If the function cannot be called, that means that either 1. The file is not included in Setup.simba, or 2. It's included but it has {$DEFINE} tags around it.

All we (Devs) have to do is to add functionality to the procedures and function we want the user to be able to hook with (Obviously we don't want scripters to be able to hook SetupMSI and stuff like that). We'll do this by adding this:
if MSI_Pointers[MSI_on_FunctionHere_Cal].FunctionCall <> nil then
case MSI_Pointers[MSI_on_FunctionHere_Call].FunctionCall() of
EXTRA_CONTINUE: ;
EXTRA_EXIT: Exit;
end;
To the function and procedures that we want the scripters to be able to hook, and replace "FunctionHere" with the name of the function (I.E MSI_Walk).

The difference between this system and the old one, is that we don't have to edit a lot of code in order for it to work. With the old one, if a user wanted to use cstrike's WorldWalker, (s)he'd have to locate MSI_Walk and add it in, now we can make the Extra do that itself, meaning less work for us, and less work for scripters. :) Win win!


On a side-note; I'd like to have a name-change. Extra -> Plugin
And someone please make a new sub-forum in MSI for Extras (/Plugins)? :)


I will be adding an example later. It wont take me long to write on up for you though :)

Coh3n

2011-01-20 18:46:49

You really should have made this thread before actually committing so we could have planned it out and discussed it first as it is a pretty major change. I'm not mad, but for next time, when making a huge change, you should make a thread. ;)

I don't like how it writes "This is called before MSI_Debug!" as that would get extremely annoying and make the debug look horrible.

I have to go now. I'm not sure how I feel about this yet as I don't really see how it's any better than what we had. Before it only compiled the extras that were being used. This way, everything is compiled. There could be a dozen extras that aren't used, but are compiled and don't need to be.

I'll be able to write a better response later.

Gu3st...

2011-01-21 02:48:23

From: Coh3n
You really should have made this thread before actually committing so we could have planned it out and discussed it first as it is a pretty major change. I'm not mad, but for next time, when making a huge change, you should make a thread. ;)
I know that, but since this doesn't break anything/does anything bad I was thinking that it didn't matter that much

From: Coh3n
I don't like how it writes "This is called before MSI_Debug!" as that would get extremely annoying and make the debug look horrible.
That extra merely an example on how many doors this can open for other people… I was hoping you'd understand that.
I'll make a new, better example later today :)

From: Coh3n
I have to go now. I'm not sure how I feel about this yet as I don't really see how it's any better than what we had. Before it only compiled the extras that were being used. This way, everything is compiled. There could be a dozen extras that aren't used, but are compiled and don't need to be.

I'll be able to write a better response later.
Wrong. It will only compile the extras we're using.


Note to self: Stop releasing things just before bed-time. I'll re-make the first post when I get home from school (In 6 hours).

Coh3n

2011-01-21 02:50:51

Please explain how it doesn't compile what you aren't using. There is no way of doing that without using defines as far as I know. And I have to say I don't like your attitude in that post. You just state I'm completely wrong without proving it? Not a very good argument.

Gu3st...

2011-01-21 02:58:29

From: Coh3n
Please explain how it doesn't compile what you aren't using. There is no way of doing that without using defines as far as I know. And I have to say I don't like your attitude in that post. You just state I'm completely wrong without proving it? Not a very good argument.
I'm sorry, I'm in a hurry right now, I didn't mean to be rude

Imo, the extras we don't use shouldn't be included. And if they aren't included then they wont be compiled either.

Using defines is still possible… I didn't say that it weren't?

Coh3n

2011-01-21 11:23:53

Then I'm not sure I understand the advantages. :o The point of extras was so the user could decide which they wanted to use by simple commenting or uncommenting the define in the Extras.simba file. I just think you need to better explain why you think it's better to use your idea.

Actually, just rereading your example, I think I have an idea; however, I'd still like you to explain it better if you don't mind. :) If I'm understanding it correctly, I like it, but we'll need to figure out the best way to organize it so it's still easy for the user.

Wizzup?

2011-01-21 11:55:42

Reminds me of my multiminer, sort of.

Gu3st...

2011-01-21 18:37:06

From: Coh3n
Then I'm not sure I understand the advantages. :o The point of extras was so the user could decide which they wanted to use by simple commenting or uncommenting the define in the Extras.simba file. I just think you need to better explain why you think it's better to use your idea.

Actually, just rereading your example, I think I have an idea; however, I'd still like you to explain it better if you don't mind. :) If I'm understanding it correctly, I like it, but we'll need to figure out the best way to organize it so it's still easy for the user.
Yeah, you will understand the advantages when I've re-written it :)
With this system, the user can decide what extra to use by checking/un-checking a check-box in the MSI Form ;) that is if you've compiled the extra. If not (If you haven't defined it or not included it) then it wont get used anyways…

From: Wizzup?
Reminds me of my multiminer, sort of.
Nice :) I'm surprised anyone actually understood what I was trying to explain in that post…. :redface:


EDIT: Updated first post. Hopefully more understandable now…

Coh3n

2011-01-21 18:40:02

From: Zyt3x
Yeah, you will understand the advantages when I've re-written it :)
With this system, the user can decide what extra to use by checking/un-checking a check-box in the MSI Form ;) that is if you've compiled the extra. If not (If you haven't defined it or not included it) then it wont get used anyways…

This part I don't like (it's not your idea as it would be the same regardless). If someone doesn't want to include/use a plugin then they have to modify code. I would like to completely avoid that. Remember, we have to make it as easy as possible for every user to setup.

I don't want to have to compile all the plugins we don't use, but it may be necessary.

Gu3st...

2011-01-21 19:03:23

From: Coh3n
This part I don't like (it's not your idea as it would be the same regardless). If someone doesn't want to include/use a plugin then they have to modify code. I would like to completely avoid that. Remember, we have to make it as easy as possible for every user to setup.

I don't want to have to compile all the plugins we don't use, but it may be necessary.
Yeah, it would be best that they weren't compiled, but does it really matter that much? I mean.. It's like what, 5-50 kB? :) Can't be that harmful.

Coh3n

2011-01-23 17:13:21

From: Zyt3x

All we (Devs) have to do is to add functionality to the procedures and function we want the user to be able to hook with (Obviously we don't want scripters to be able to hook SetupMSI and stuff like that). We'll do this by adding this:
if MSI_Pointers[MSI_on_FunctionHere_Cal].FunctionCall <> nil then
case MSI_Pointers[MSI_on_FunctionHere_Call].FunctionCall() of
EXTRA_CONTINUE: ;
EXTRA_EXIT: Exit;
end;
To the function and procedures that we want the scripters to be able to hook, and replace "FunctionHere" with the name of the function (I.E MSI_Walk).

Why the case? We could just do

if MSI_Pointers[MSI_on_FunctionHere_Cal].FunctionCall <> nil then
begin
Result := MSI_Pointers[MSI_on_FunctionHere_Call].FunctionCall();
Exit;
end;

Everything else looks great as far as I can see. I'm actually starting to really like this now that I understand it more. :)

From: Zyt3x
Yeah, it would be best that they weren't compiled, but does it really matter that much? I mean.. It's like what, 5-50 kB? :) Can't be that harmful.

Yeah, now, but what happens if we get dozens of extras?

I don't want to have the users to have to comment/uncomment defines AND set which extras they want to use as it's just redundant. If only we could do

if (MSI_Extras[].Enabled) then
{$DEFINE EXTRA_ZYT3X_WORLDWALKER}
:rolleyes:

I would eventually like to quicken the compiling time significantly because there is a lot of things being compiled that, in most cases, the user doesn't use (this includes the loading of our global variables).

Gu3st...

2011-01-23 18:02:39

From: Coh3n
Why the case? We could just do

if MSI_Pointers[MSI_on_FunctionHere_Cal].FunctionCall <> nil then
begin
Result := MSI_Pointers[MSI_on_FunctionHere_Call].FunctionCall();
Exit;
end;

Everything else looks great as far as I can see. I'm actually starting to really like this now that I understand it more. :)
I added the case there in case the scripter wants to continue the original function. I'd like to do that if (I.E) my world walker failed, so that MSI can have it's try instead of just logging out.
And that's great! :D I just have to work some more on it, and it'll be great :)

From: Coh3n

Yeah, now, but what happens if we get dozens of extras?

I don't want to have the users to have to comment/uncomment defines AND set which extras they want to use as it's just redundant. If only we could do

if (MSI_Extras[].Enabled) then
{$DEFINE EXTRA_ZYT3X_WORLDWALKER}
:rolleyes:

I would eventually like to quicken the compiling time significantly because there is a lot of things being compiled that, in most cases, the user doesn't use (this includes the loading of our global variables).
I get your point… hmm..
We can just make it so that it's not defined by default.
The extra is set to enabled if it's defined atm, btw :)
I'm soon finished with my world walker now :)

Coh3n

2011-01-23 22:00:35

Awesome. :)

Gu3st...

2011-01-24 14:10:29

Great :redface:

Coh3n

2011-02-09 01:06:30

Okay so I finally had time to really look into what you've written, and… I really like it! :) You seem to have covered any concerns I had such as having more than one extra use the same pointer. I do have a couple suggestions, though.
  1. We need a global array (maybe include it in MSI_SetupVars) so that the user can choose which extras they would like to use. This, in turn, could allow us to load only the extras that are enabled, rather than all of them.
  2. I don't really like the case in each pointed function, but I do like the idea behind it. It's really not that big a deal, but if there was a way to avoid using a case, I think that would be easier so every pointed function didn't need updating if a constant was to be added. I'm talking about the case here.

  3. if MSI_Pointers[MSI_on_FunctionHere_Cal].FunctionCall <> nil then
    case MSI_Pointers[MSI_on_FunctionHere_Call].FunctionCall() of
    EXTRA_CONTINUE: ;
    EXTRA_EXIT: Exit;
    end;
    Probably wouldn't need EXTRA_CONTINUE in the case since the function would just continue anyway. I actually can't think of another option we would need. Maybe that would help us get rid of the case?
  4. What if there's more than on Extra that could be pointed to the same function without messing up that function? For example, Bobzilla's stats grabber would just save the stats, what if someone else made an Extra that did something else during player setup. Both Extras could, and should be pointed to MSI_SetupPlayer. That being said, I think we should worry about that when/if the time comes. :p
  5. What's the bug mentioned here?

  6. MSI_Extras[CurrentExtra].Enabled := False; // There's a bug here. Will fix later!
  7. Also, what do you think about having defines for each of the extras at the top of Extras.simba anyway? They'll all be defined by default, but that will allow us (as developers) to disable them easily if for some reason one was to become outdated and caused compiling issues. I don't think it would hurt.
  8. Last but not least, replace the Writeln's with MSI_Debug's and add documentation. :p
I may try to add Bob's stats Extra this week, in case anyone was wondering. :)

Gu3st...

2011-02-09 04:40:43

First of all: Thanks :) There's still some updates I haven't committed yet, but when I've worked it all out and made everything compile and work good enough, I'll commit it :)

1. Yes, that would be good
2. Believe me, I have been trying to figure out something other than that for days now (!), and unfortunately I can't really think of any other way of doing it :( The reason I made it a case loop is because we might add other cases (EXTRA_LOGOUT or something..) but I'm not sure if we'd want that nor if it would be of any use to have more than EXTRA_EXIT & EXTRA_CONTINUE..
3. I've been trying to figure this out too, but just as you, I though "That being said, I think we should worry about that when/if the time comes." too.. :) :P
4. The bug is that when the extra is disabled, I haven't made it so that it frees the other pointers used… I have fixed this though, and will be committing the fix later
5. Yeah! Good idea :)
6. Of course ;) I think I'll re-write the function too… It's messy and I think it could be made shorter

I have also made it so that the functions allows parameters (which will open up even more doors for scripters, and make they're life much easier). Basically, I just turned FunctionCall : function : Integer; into String; and turned "case MSI_Pointers[MSI_on_FunctionHere_Call].FunctionCall() of" into "case CallFunc(blah.FunctionCall) of".

I'm at school now, but when I get home I'll work on this and commit the changes :)

E: I'm also working on the announcement thread and a tutorial. After I've posted those I'll move this thread to public, so others can comment and suggest changes

Coh3n

2011-02-09 13:00:44

Fantastic. :)

Gu3st...

2011-02-11 14:23:56

This week has been super busy for me, and I haven't gotten to work on this at all.
I hope I'll get some time to work on this and commit it on Sunday, but I'm unsure if I'll get time to do it at all this week.

Sorry about the delay :/

Coh3n

2011-02-11 14:43:42

From: Zyt3x
This week has been super busy for me, and I haven't gotten to work on this at all.
I hope I'll get some time to work on this and commit it on Sunday, but I'm unsure if I'll get time to do it at all this week.

Sorry about the delay :/

No worries, everyone gets busy now and then. :)

Coh3n

2011-02-13 20:42:46

Just noticed something.. Do you even need to use the var CurrentExtra? Like does it need to be global?

Sir R. M8gic1an

2011-02-13 20:45:55

properly read the first post. Great job.

~RM

Gu3st...

2011-02-14 09:52:18

From: Coh3n
Just noticed something.. Do you even need to use the var CurrentExtra? Like does it need to be global?
Yes, it's needed for if not MSI_Extras[CurrentExtra].Active then Exit;

From: Sir R. M8gic1an
properly read the first post. Great job.

~RM
Thanks :D

Coh3n

2011-02-14 19:38:42

From: Zyt3x
Yes, it's needed for if not MSI_Extras[CurrentExtra].Active then Exit;

Yes, but is it necessary to use it for that purpose. I mean, CurrentPlayer/CurrentScript/CurrentSpell would be changed several times throughout runtime, and unless only one Extra would be used at one time, I don't see how it would be used in the same way.

Gu3st...

2011-02-15 02:50:36

From: Coh3n
Yes, but is it necessary to use it for that purpose. I mean, CurrentPlayer/CurrentScript/CurrentSpell would be changed several times throughout runtime, and unless only one Extra would be used at one time, I don't see how it would be used in the same way.
It wont be used in the same way, thats true, but we still need a global variable. I'll show you when I get home from school :)

Coh3n

2011-02-15 03:08:48

From: Zyt3x
It wont be used in the same way, thats true, but we still need a global variable. I'll show you when I get home from school :)

Just try to explain it here. Chances are you'll be in bed when I'm available.

Gu3st...

2011-02-15 03:58:29

From: Coh3n
Just try to explain it here. Chances are you'll be in bed when I'm available.
Yes, of course ;)

E: Each time an extra has hooked a function, MSI has to check if that extra is enabled, and to do that we could either do MSI_Extra[MSI_Pointer[CurrentPointer].UsedBy].Enabled (UsedBy isn't in the public MSI yet) or do MSI_Extra[CurrentExtra].Enabled. I figured it would be better to do CurrentExtra, so that the user can (Inside his functions) do stuff like WriteLn('Hooked function MSI_WriteRemote: ' + MSI_Extra[CurrentExtra].Name); and stuff like that.

Gu3st...

2011-02-19 09:11:16

Oh great. I actually managed to delete all my progress.. Today when I wanted to test MSI to fin the code:8 error, I figured I might want the new extensions and simba, so I downloaded everything, and enabled the new extensions, everything was going great and I updated SRL and Reflection, later on I saw the debug box saying "Successfully updated MSI!". I forgot to uncheck the automatically update MSI… I feel like an idiot now >_<

I think I know what I've changed though, so it wont take long before I can commit them, but this will take some more time…

Coh3n

2011-02-19 12:24:57

From: Zyt3x
Oh great. I actually managed to delete all my progress.. Today when I wanted to test MSI to fin the code:8 error, I figured I might want the new extensions and simba, so I downloaded everything, and enabled the new extensions, everything was going great and I updated SRL and Reflection, later on I saw the debug box saying "Successfully updated MSI!". I forgot to uncheck the automatically update MSI… I feel like an idiot now >_<

I think I know what I've changed though, so it wont take long before I can commit them, but this will take some more time…

That's why you push any of your changes to your fork of MSI. ;)

You also could have created a new branch based on the MSI main repository, and tested from there.

But anyway, in my experience, when you write something a second time, it tends to be better than the first. :p

Gu3st...

2011-02-19 13:09:39

From: Coh3n
But anyway, in my experience, when you write something a second time, it tends to be better than the first. :p
I agree 100% with this one :P
After I figured out I had deleted all the code I had wrote, I went to take a shower and when I did that ideas just flew into my mind. I felt like Beethoven or something.. Now I'm writing it once more, and I can tell it's already much better :p

Coh3n

2011-02-19 13:12:00

From: Zyt3x
I agree 100% with this one :P
After I figured out I had deleted all the code I had wrote, I went to take a shower and when I did that ideas just flew into my mind. I felt like Beethoven or something.. Now I'm writing it once more, and I can tell it's already much better :p

Glad to hear it. :)