SA-MP Forums Archive
[Tutorial] Modular Programming - Printable Version

+- SA-MP Forums Archive (https://sampforum.blast.hk)
+-- Forum: SA-MP Scripting and Plugins (https://sampforum.blast.hk/forumdisplay.php?fid=8)
+--- Forum: Scripting Help (https://sampforum.blast.hk/forumdisplay.php?fid=12)
+---- Forum: Tutorials (https://sampforum.blast.hk/forumdisplay.php?fid=70)
+---- Thread: [Tutorial] Modular Programming (/showthread.php?tid=597338)

Pages: 1 2


Modular Programming - PatrickGTR - 29.12.2015

What is modular programming?
Modular programming is a process of breaking down a code depending on its category to make the code reusable for future projects (avoid re-inventing the wheel) as well as making the code easier to read and track down mistakes. Modular programming comes handy if you are writing big projects, there's no point of modularizing your code if it doesn't consists of 5,000 lines as this can be done in one file but once again I am not your boss therefore this could be done on short codes but I see no point of doing so (personal opinion).

AdvantagesDisadvantages Examples Editor that supports multi-tasking
Notepad++ for PAWN - Slice
Sublime Text for PAWN - Southclaw
Atom for PAWN - Kaperstone

NOTE
You have to plan how you want to lay your code out or else it will be a disaster and you will be lost.


Layout
pawn Код:
- gamemodes
    - main.pwn
        - utils
            - colour.pwn
            - math.pwn
            - string.pwn
        - core
            - player
                - core.pwn
                - account.pwn
            - server
                - core.pwn
                - vehicles.pwn
pawn Код:
#include <a_samp>

//Modules

//Utils
#include "utils/colour.pwn"
#include "utils/math.pwn"
#include "utils/string.pwn"

//Player
#include "core/player/core.pwn"
#include "core/player/account.pwn"

//Server
#include "core/server/core.pwn"
#include "core/server/vehicles.pwn"
OR

pawn Код:
- includes
    - main.pwn
        - utils
            - colour.pwn
            - math.inc
            - string.inc
        - core
            - player
                - core.inc
                - account.inc
            - server
                - core.inc
                - vehicles.inc
pawn Код:
#include <a_samp>

//Utils
#include <utils/color>
#include <utils/math>
#include <utils/string>

//Player
#include <core/player/core>
#include <core/player/account>

//Server
#include <core/server/core>
#include <core/server/vehicles>

How does it work together?

Include is a directive that binds the contents of the module/second file together and insert it into the original file although the IDE doesn't read it this way but the compiler reads it like the code is in one-file.

enums.pwn
pawn Код:
enum E_PLAYER_DATA {
    plyUsername[MAX_PLAYER_NAME],
    plyPassword[65],
    plyKills,
    plyDeaths
}

new plyData[MAX_PLAYERS][E_PLAYER_DATA];
main.pwn
pawn Код:
#include <a_samp>

#include "core/player/enums.pwn"

new
    resetPData[E_PLAYER_DATA];

public OnPlayerConnect(playerid) {
    plyData[playerid] = resetPData; //sets all the value to 0.

    //Load everything here.

    return 1;
}

public OnPlayerDisconnect(playerid, reason) {
   
    //save everything here.

    plyData[playerid] = resetPData; //sets all the value to 0.
    return 1;
}
What actually happens
pawn Код:
#include <a_samp>

//this is enums.pwn
enum E_PLAYER_DATA {
    plyUsername[MAX_PLAYER_NAME],
    plyPassword[65],
    plyKills,
    plyDeaths
}

new plyData[MAX_PLAYERS][E_PLAYER_DATA];

new
    resetPData[E_PLAYER_DATA];

public OnPlayerConnect(playerid) {
    plyData[playerid] = resetPData; //sets all the value to 0.

    //Load everything here.

    return 1;
}

public OnPlayerDisconnect(playerid, reason) {
   
    //save everything here.

    plyData[playerid] = resetPData; //sets all the value to 0.
    return 1;
}
How does hooking work?
The modules should be done in a sequence in order for it to function properly. For example you are trying to open a database in main.pwn and you want to create a table of accounts in accounts.pwn to be able to do that. You
have to hook OnGameModeInit before every module and y_hooks (if you're using y_hooks). Example shown below.

main.pwn
pawn Код:
#include <a_samp>

/* -
    How it happens behind the console
    --------------------------------------
    * OnGameModeInitEx - first
        * hooks of OnGameModeInit - second
    --------------------------------------
    "OnGameModeInitEx" will be called first to avoid crashes and confusion within the hooks.
    Everything that you have to do regarding OnGameModeInit
    You have to place them in "OnGameModeInitEx" to make sure other hooks will not mess up on start up.
*/


public OnGameModeInit()
{

    OnGameModeInitEx();

    #if defined main_OnGameModeInit
        return main_OnGameModeInit();
    #else
        return 1;
    #endif
}
#if defined _ALS_OnGameModeInit
    #undef OnGameModeInit
#else
    #define _ALS_OnGameModeInit
#endif
 
#define OnGameModeInit main_OnGameModeInit
#if defined main_OnGameModeInit
    forward main_OnGameModeInit();
#endif

#include <YSI\y_hooks> //The y_hooks hook of OnGameModeInit will be called after the hook in main.pwn is called.
 
OnGameModeInitEx()
{
    db_open("server.db");
}

//We don't need to hook this because OnGameModeExit() hooks will be called first therefore the main OnGameModeExit() will be called last and this is what we need.
public OnGameModeExit()
{
    db_close(DB:0);
    return 1;
}

What happens behind?
pawn Код:
- hook of OnGameModeInit() calling OnGameModeInitEx() in main.pwn - This will be called first all the time!
- hook of OnGameModeInit() in different modules.
    - The hooks are called depending on the suquence of the module.

    For example
    - main.pwn
    - players.pwn
    - servers.pwn
    - checkpoints.pwn

    - OnGameModeInit() hook will be called first in main.pwn
    - OnGameModeInit() hook will be called second in players after main.pwn
    - OnGameModeInit() hook will be called third in servers after players.pwn
    - OnGameModeInit() hook will be called fourth in checkpoints after servers.pwn



Re: Modular Programming - CrazyChoco - 29.12.2015

This is good. It would suit anyone who is considering the programming industry.


Re: Modular Programming - Sasino97 - 29.12.2015

Good tutorial
It would be a nice thing if people started to modular program, there are lots of good sа-mp scripters who still don't understand the advantage of dividing their project into modules, аnd thry publish huge gamemodes with 20000 lines of code


Re: Modular Programming - Pottus - 29.12.2015

This only explains the concept not the implementation 1-star from me because people will get to the end then ask "okay what do I do now?" it's like you left out 75 percent of the tutorial. It's a great start nice and neat but needs some effort to be useful.


Re: Modular Programming - Dayvison_ - 29.12.2015

PBP compiler by Slice, is a very good tool for this.


Re: Modular Programming - VincenzoDrift - 30.12.2015

Good tutorial +rep


Re: Modular Programming - PatrickGTR - 30.12.2015

Updated, explained how the modules binds together and how the hooking works in-order depending on module order.


Re: Modular Programming - [XST]O_x - 30.12.2015

This is great. I've been trying to understand how to break down a gamemode into several filterscripts instead of one large, 20k+ lines script. Thank you very much.


Re: Modular Programming - PrO.GameR - 30.12.2015

Okay this was actually really great, but I tried it and well ... obviously failed xD
I got an error not recognizing my main enum (PlayerI), If I move my enums to an include file it will be solved right ?
Oh and another question, is it better if I break down my enums into different modules or should I just put them all in one big file called header ? (because either way I should include all headers first right ?)


Re: Modular Programming - PatrickGTR - 30.12.2015

Quote:
Originally Posted by PrO.GameR
Посмотреть сообщение
Okay this was actually really great, but I tried it and well ... obviously failed xD
I got an error not recognizing my main enum (PlayerI), If I move my enums to an include file it will be solved right ?
Oh and another question, is it better if I break down my enums into different modules or should I just put them all in one big file called header ? (because either way I should include all headers first right ?)
As I said your modules should be in order and its your choice, your the coder and you choose the layout that's more comfortable to you.

For example

pawn Код:
- declarations
- macros
- functions

- server

- player



Re: Modular Programming - AndySedeyn - 01.01.2016

I'm relatively new to modular programming. Sometimes an include is not being included for some reason.

Example:
PHP Code:
#include "./AntiCheat/ac_money.pwn"
#include "./AntiCheat/ac_health.pwn"

// Inside ac_money
#if defined _ac_money_included
    #endinput
#endif
#define _ac_money_included

// Inside ac_health
#if defined _ac_health_included
    #endinput
#endif
#define _ac_health_included

// Under the #include directives in the main file
#if !defined _ac_health_included
    #error Anti health hack is not included
#endif

#if !defined _ac_money_included
    #error Anti money hack not included
#endif 
'ac_money' is included first in the example above and that will show the error: 'Anti health hack not included'.

Changing their position:
PHP Code:
#include "./AntiCheat/ac_health.pwn"
#include "./AntiCheat/ac_money.pwn" 
Now it will pop the error: "Anti money hack not included'.

Putting them together in one file works, but I don't want that obviously. Any suggestion on why that could happen? The rest of my modules get included perfectly.


Re: Modular Programming - PatrickGTR - 01.01.2016

Quote:
Originally Posted by AndySedeyn
View Post
I'm relatively new to modular programming. Sometimes an include is not being included for some reason.

Example:
PHP Code:
#include "./AntiCheat/ac_money.pwn"
#include "./AntiCheat/ac_health.pwn"
// Inside ac_money
#if defined _ac_money_included
    #endinput
#endif
#define _ac_money_included
// Inside ac_health
#if defined _ac_health_included
    #endinput
#endif
#define _ac_health_included
// Under the #include directives in the main file
#if !defined _ac_health_included
    #error Anti health hack is not included
#endif
#if !defined _ac_money_included
    #error Anti money hack not included
#endif 
'ac_money' is included first in the example above and that will show the error: 'Anti health hack not included'.

Changing their position:
PHP Code:
#include "./AntiCheat/ac_health.pwn"
#include "./AntiCheat/ac_money.pwn" 
Now it will pop the error: "Anti money hack not included'.

Putting them together in one file works, but I don't want that obviously. Any suggestion on why that could happen? The rest of my modules get included perfectly.
Is the folder inside gamemodes? If yes include them this way #include "folder/pwnfile.pwn". Also make sure you put the anti-cheat first before other modules just to make sure these hooked function functions properly. also its unnecessary to have. if !defined directive.


Re: Modular Programming - AndySedeyn - 01.01.2016

It was basically to check whether the include was included or not. They are in my gamemodes folder, yes. Including them like you advised me to gives me the same problem.


Re: Modular Programming - PatrickGTR - 01.01.2016

Quote:
Originally Posted by AndySedeyn
View Post
It was basically to check whether the include was included or not. They are in my gamemodes folder, yes. Including them like you advised me to gives me the same problem.
I've tried your code and everything seems to be working fine... I am not sure where you made your mistake but maybe taking a look at my code and you'll realize your own mistake.

ac_health.pwn
pawn Code:
#if defined _ac_health_included
    #endinput
#endif
#define _ac_health_included
ac_money.pwn
pawn Code:
#if defined _ac_money_included
    #endinput
#endif
#define _ac_money_included
main.pwn
pawn Code:
#include <a_samp>

#include "AntiCheat/ac_money.pwn"
#include "AntiCheat/ac_health.pwn"

#if !defined _ac_money_included
    #error Anti money hack not included
#endif

#if !defined _ac_health_included
    #error Anti health hack is not included
#endif



Re: Modular Programming - AndySedeyn - 01.01.2016

Will look into it. Thank you.


Re: Modular Programming - Kimble - 06.09.2016

If i include y_hooks in main do i still need to include it in every other module?


Re: Modular Programming - PrO.GameR - 06.09.2016

No you don't need to, systems are still part of the same giant structure which y_hooks is already part of it.


Re: Modular Programming - SickAttack - 06.09.2016

Quote:
Originally Posted by Kimble
View Post
If i include y_hooks in main do i still need to include it in every other module?
No, as long as you include it before the other includes.

Includes are copied and pasted into the gamemode.


Re: Modular Programming - K0P - 07.09.2016

Yes it has many advantages as ive seen in many big gamemodes which used this method especially to protect their gamemode to fully be leaked.


Re: Modular Programming - Misiur - 07.09.2016

Erm, as for y_hooks, if you are hooking callbacks in every include, then you need to include y_hooks too (in reality this will only load y_unique to make sure your callbacks are, well, unique)