Quote:
Originally Posted by PawnHunter
Because PAWN is not object oriented, PAWN is simple, PAWN is outdated (the version SAMP uses is probably 10 years old), and more ..
I didn't "fail", I've been testing PAWN limits for months now, and I'm saying there is no way to process with a REAL modular design, yeah you could shit yourself and make some files called "callbacks, commands, header" separate then include to main file, but this isn't modular. I'm not just a beginner scripter, it's just the language that lacks the required features to make it modular. Adding some hooks and functions in different files, isn't what Modular design is. Anyways, that's my last reply here, I've said what I wanted to.
|
No, having hooks and functions in separate files is not modular design at all, if you have a file called "callbacks" anywhere in your hierarchy you are probably doing it wrong, no wonder you gave up - that is not "real" at all. However, if you do it properly it is very easy to get good modular design, even in PAWN (and I've been testing its limits for years now).
Hooks, functions, macros, variables etc. should be kept together in one file when they are for the same logical part of code (semantics - meaning, instead of syntax - appearance). If you have a variable storing the owner of a vehicle, and a function to sell a vehicle - put them in the same file, named something like "VehicleOwnership.pwn". If you have another variable storing the last person to kill someone, that has probably got nothing at all to do with vehicle ownership and should go in a totally separate file. Yes, they are both variables. Yes, they might look very similar, so you can do:
PHP Code:
new gVehicleOwner;
new gLastKillerID;
But they are totally unrelated and things should not be split up by what looks nice (though once split correctly, appearance does help).
The best way I have found to keep things modular is static variables. Make all the globals in one file "static" and only provide access through a function API:
PHP Code:
static
gVehicleOwner[MAX_VEHICLES] = { INVALID_PLAYER_ID, ... };
bool:VO_SetOwner(vehicleid, playerid)
{
// Already owned.
if (gVehicleOwner[vehicleid] != INVALID_PLAYER_ID)
return false;
gVehicleOwner[vehicleid] = playerid;
return true;
}
VO_GetOwner(vehicleid)
{
return gVehicleOwner[vehicleid];
}
NEVER let another file see the "gVehicleOwner" variable. This way you can keep all the restrictions on it in one place. If you decide to use a linked list of vehicles people own instead, you can just change this one file and not break any other code anywhere:
PHP Code:
static
Iterator:gOwnedVehicles<MAX_PLAYERS, MAX_VEHICLES>;
bool:VO_SetOwner(vehicleid, playerid)
{
// Already owned.
if (Iter_Contains(gOwnedVehicles<>, vehicleid))
return false;
Iter_Add(gOwnedVehicles<playerid>, vehicleid);
return true;
}
VO_GetOwner(vehicleid)
{
new
ret = Iter_GetMulti(gOwnedVehicles<>, vehicleid);
return (ret == -1) ? INVALID_PLAYER_ID : ret;
}
Totally different internal implementation, no different external API - still just "VO_SetOwner" and "VO_GetOwner"; and because the variables involved were all static you know that no other code in the mode can access them directly or will need updating in any way.
Some good examples of modular modes and includes:
YSI (obviously). Look through that and take a guess at what "y_inline.inc", "y_foreach.inc", and "y_commands.inc" do. They do often have a second file of (say) "y_commands/impl.inc", but it is always just "impl.inc" (short for "implementation") and never split up further in to variables and functions in separate files, because then you can't use statics, and then you can't KNOW that no-one else is directly accessing your private internal state. Even the tests don't (usually) have access to internal state, because they test the external API ("VO_SetOwner" and "VO_GetOwner" above), not the implementation (again, usually).
https://github.com/Zeex/amx_assembly Designed very purely, so actually has very little global state (variables) at all anywhere.
https://github.com/Southclaws/ScavengeSurvive Already mentioned, but worth repeating. Again, see how all the files are named for the gamemode system they implement, not what the code in them looks like. A file for macros, another file for functions, that's just totally useless - like classifying vehicles by their colour because a red van and a red car have a superficially similar appearance (as functions do to other functions), instead of by use.