29.12.2015, 20:23
(
Последний раз редактировалось PatrickGTR; 30.12.2015 в 13:14.
)
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).
Advantages
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
OR
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
main.pwn
What actually happens
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
What happens behind?
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).
Advantages
- Code reusability - This makes your life easier, if you're creating a new project that has similar needs your module can come handy and be re-used in this situation and saves you time! (wasting time on creating the code again from scratch).
- Code readability - Modular programming can make your code much easier to read with few lines in each modules!
- Ease of debugging and modifying - A modularized code are generally easier to debug than a code that has been done in ONE file. Why is it easier to debug? - Codes are isolated in a module and once a faulty code has been identified, fixing can be very easy. Modifying can come handy if a module has to be used once again! simple modification can be done and the module can be re-used again!
- Multiple developers - If you are working as a team, each developer can work on a different module and this leads to faster development!
- Each developer can use their expertise to work on a module! Maths, GUI, commands, arrays, checkpoints, etc...
- Variable names - each variable name should have a unique name or else it can cause warning 219: local variable "variable_name" shadows a variable at a preceding level
- A fix for this is use static to declare the variable as a local variable yet you still need to use a non-generic variable name to avoid conflicts with other modules and released includes.
- Another fix if a variable is declared locally, you can create a function if it needs to be used throughout the code.
- Proper documentation - If you are working as a team, modules should be documented thoroughly for other developers to understand the code as well. (This also goes to codes that are going to be released in forums)
- Hooking a function that is required to be re-used - This can be repetitive and hook should have a unique prefix. Writing the directives can be repetitive but this is why COPY and PASTE exists. Other solution is using y_hooks and including it every module. For y_hooks example see first 2 examples.
- San Fierro Cops and Robbers by me
- Scavenge and Survive by Southclaw
- Texture Studio by Pottus
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"
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];
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;
}
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;
}
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