Raised This Month: $51 Target: $400
 12% 

Concept: Project base


Post New Thread Reply   
 
Thread Tools Display Modes
FaTony
Veteran Member
Join Date: Aug 2008
Old 12-29-2010 , 16:24   Re: Concept: Project base
Reply With Quote #51

I've only used this approach in 1 private paid plugin and my client didn't allow me to release the source. It worked great, but I've used only singletons there. But I've ended with all data in global statics, so no public data at all. Feels very C++ like. The problem with enums that technically other modules have all access to their data so you don't feel encapsulation while you code it and it creates additional lines of code if you class is not complicated enough.

Overall it was about 1000 lines of code split into sp and 8 incs, each inc being one distinct module. It was 5 times easier to debug that code because you just click on the file you think faulty and instantly find a line you need. No need to scroll through hundreds of lines hunting the function you need. Encapsulating stuff also easies the check for input anomalies of your functions because you know which ones can be called from each and don't need to handle hundreds of edge cases in order to protect your code from yourself and lame modders.
__________________

Last edited by FaTony; 12-29-2010 at 16:37.
FaTony is offline
Frenzzy
SourceMod Donor
Join Date: Jan 2007
Location: Russia
Old 07-18-2011 , 12:30   Re: Concept: Project base
Reply With Quote #52

Maybe can be done so that the project did not need to compile separately for each game?

For example something like this:
PHP Code:
stock g_CurrentGame;

enum GameMods
{
    
Game_None 0,
    
Game_CSS,
    
Game_DOD,
    
Game_HL2DM,
    
Game_TF2,
    
Game_L4D
}

GameMgr_OnPluginStart()
{
    
decl String:foldername[32];
    
Getfoldername(foldernamesizeof(foldername));
    
    if (
StrEqual(foldername"cstrike"false))
    {
        
g_CurrentGame _:Game_CSS;
    }
    else if (
StrEqual(foldername"dod"false))
    {
        
g_CurrentGame _:Game_DOD;
    }
    else if (
StrEqual(foldername"hl2mp"false))
    {
        
g_CurrentGame _:Game_HL2DM;
    }
    else if (
StrEqual(foldername"tf"false))
    {
        
g_CurrentGame _:Game_TF2;
    }
    else if (
StrEqual(foldername"left4dead"false))
    {
        
g_CurrentGame _:Game_L4D;
    }
    else
    {
        
SetFailState("[Game Manager] \"%s\" game mod is not supported."foldername);
    }
}

stock GameMods:GameMgr_GetGame()
{
    return 
GameMods:g_CurrentGame;

PHP Code:
#if defined PROJECT_GAME_CSS
    
CS_RespawnPlayer(client);
#endif

#if defined PROJECT_GAME_TF2
    
TF2_RespawnPlayer(client);
#endif 
PHP Code:
switch (GameMgr_GetGame())
{
    case 
Game_CSS:
    {
        
CS_RespawnPlayer(client);
    }
    case 
Game_TF2:
    {
        
TF2_RespawnPlayer(client);
    }

Frenzzy is offline
Send a message via ICQ to Frenzzy Send a message via MSN to Frenzzy Send a message via Skype™ to Frenzzy
rhelgeby
Veteran Member
Join Date: Oct 2008
Location: 0x4E6F72776179
Old 07-18-2011 , 14:12   Re: Concept: Project base
Reply With Quote #53

If you're making a single multimod plugin you'll need to do that. The general approach was to compile special versions for each mod. Some mods doesn't even support a features, so that version would have it removed completely.
__________________
Richard Helgeby

Zombie:Reloaded | PawnUnit | Object Library
(Please don't send private messages for support, they will be ignored. Use the forum.)
rhelgeby is offline
Send a message via MSN to rhelgeby
Greyscale
SourceMod Plugin Approver
Join Date: Dec 2007
Location: strYoMommasHouse[you];
Old 07-26-2011 , 04:06   Re: Concept: Project base
Reply With Quote #54

I think checking the game at runtime for EVERY game-specific feature would be a bad design choice when it comes to plugins that can be very different between different games.

The good thing about this base is that you can take it and modify it for your needs. So if your plugin is better off checking the game your way, nothing is stopping you from changing it.

I'd like to note that this base has been thoroughly tested at this point. No major changes should be made at this point. But I don't think it will ever be perfect and I will continue to refine it as ZR is built off of it. I've also found that pairing this with smlib is very powerful.
__________________
Greyscale is offline
ProdigySim
SourceMod Plugin Approver
Join Date: Feb 2010
Old 07-26-2011 , 12:12   Re: Concept: Project base
Reply With Quote #55

Just a note, I was working on a monolith-plugin based off of the ZR/project base design, and finally I got tired of it and started from scratch.
Building everything into one single plugin can make things faster and "easier", but it really hurts maintainability and reusability. You end up with high coupling and loose cohesion.

Something that really inspired me to make a change was ApolloRP. They have a very nice large SM project which uses multiple plugins+interfacing.

Now I'm starting from scratch, cutting dependencies, and creating a lot of useful plugins out of some once-monolith code. To tie all of my plugins together I started working on LGOFNOC, a parallel configuration manager. So far it's working well.
ProdigySim is offline
Greyscale
SourceMod Plugin Approver
Join Date: Dec 2007
Location: strYoMommasHouse[you];
Old 07-26-2011 , 14:08   Re: Concept: Project base
Reply With Quote #56

I'm not sure how it hurts maintainability and reusability, could you explain more? I agree that you end up with high coupling which is a bitch sometimes, but after hours of discussion with the other ZR dev we have come up with a lot of really awesome ideas that I think makes it worth the hassle in the end. We have modules that use functions from other modules, but may not even require that module to be compiled into the plugin. We call it interfacing because it reminds me of interface classes in C++. We basically have a wrapper function which just dynamically calls a defined function if it exists (otherwise it throws errors). This method results in a collection of "interface" functions that will basically make up the external API later on.

And loose cohesion was pretty much the goal of the base. I didn't like having everything so intertwined in a huge plugin. If multiple people were using the base, someone could literally plop one of my include files into their project, add a line of code to their .sp and project.inc and have a shiny new feature in their plugin. I could also take out one of my modules, remove all the base stuff, make it an .sp and compile it as an independent plugin. Ok..it may not be that easy, but it would be trivial.


This isn't to say that multiple plugins working together is bad or anything. It would be cool having multiple plugins work together and it doesn't require such hacky use of dynamic function calling.
__________________
Greyscale is offline
ProdigySim
SourceMod Plugin Approver
Join Date: Feb 2010
Old 07-26-2011 , 15:54   Re: Concept: Project base
Reply With Quote #57

Maintainability: Some module is exhibiting buggy behavior, or is crashing. The module cannot be isolated from the rest of the code for testing.

Reusability: If I like a chunk of your code, and want to place it in my project or use it as a standalone plugin, I either have to bring the whole project base with me or spend a lot of time trying to decipher function calls and/or execution flow to make things work on its own.
ProdigySim is offline
rhelgeby
Veteran Member
Join Date: Oct 2008
Location: 0x4E6F72776179
Old 07-26-2011 , 22:11   Re: Concept: Project base
Reply With Quote #58

We consider this base framework experimental and very few plugins use it at the moment. There are of course both advantages and disadvantages with its design. There's absolutely no documentation for it, so I understand if it's hard to learn how it works. I was confused myself when I first saw it, but once I got used to it, everything seems logical. Some documentation would probably help give a quicker and less confusing start with a guided introduction to all its features.

What I really like about this base is its framework (whether its architecture is a single plugin or many plugins doesn't really matter now). Not whether stuff gets modular and independent.

This base is more than just registering modules and forwarding events to them. It's a complete manager that takes care of, or simplifies several tasks. It's a layer of abstraction between SM and our code. Obviously, it's meant to be used in bigger and complex plugins. It's for those who make a mod/game (like ZR or THC RPG) or something bigger than a single feature. Using it for small features would just make it bloated.

In the base, modules can register dependencies so when a module is disabled, its events will be blocked. It's also recursive so dependent modules are also disabled. Events can be prioritized, blocked and filtered for individual modules. This is exactly what we need when developing Zombie:Reloaded. It perfectly suits our needs.

It would also be possible to put everything in separate plugins. The base would be a management plugin that provides natives for registering modules (plugins) and events. In addition it would need to isolate plugin collections from each other if there are two big collections enabled at once (like ZR and THC RPG), so their event priority and filtering will work properly. It would probably need to introduce some kind of plugin grouping where each module (plugin) have to identify which group it belongs to when calling every native. This design would be pretty interesting. The base is much less complex when it's all compiled to a single plugin binary, compared to dealing with multiple sets of plugins at once - and worst of all; backwards compatibility.

Quote:
Originally Posted by ProdigySim View Post
Maintainability: Some module is exhibiting buggy behavior, or is crashing. The module cannot be isolated from the rest of the code for testing.
Actually it can. Everything else can easily be entirely disabled by commenting lines in two places; where they're included, and where the OnPluginStart forward is passed to modules. When the plugin is compiled, disabled modules won't even be compiled.

The module might have dependencies (even complex ones) so it can't function without other stuff, which again may have other dependencies. Though you'd get the same problem if modules were separate plugins depending on other modules.

The only thing I agree with is crashing. If a module in our base throw an error while in a event callback, the entire event chain is killed, so other modules won't get the event. This might cause a crash cascade in worst cases.

Quote:
Originally Posted by ProdigySim View Post
Reusability: If I like a chunk of your code, and want to place it in my project or use it as a standalone plugin, I either have to bring the whole project base with me or spend a lot of time trying to decipher function calls and/or execution flow to make things work on its own.
The idea is to bring the base with you (actually building your entire plugin on the base), so features can be exchanged between such plugins. If made as a separate plugin, deciphering execution flow would be trivial because base events are pretty much equal to real forwards and event hooks. Reading a module's code is essentially the same as reading a simple plugin's code, with forwards/event hooks and other functions.

The exception is custom events within the plugin, but that's a dependency issue we can't get away with no matter what architecture we use. Initially we try to design modules (in ZR) with as few dependencies as possible. Usually the modules have optional dependencies where it detects if another module is available or not so it can function with and without it.

Porting features between plugins on different architectures obviously can't be done with a single copy and paste - but if they're on the same architecture (like both using our base) it would be quite trivial sharing features between plugins.

I don't think this base will be dominating in future SourceMod plugins, but I'm pretty sure it will be a good inspiration for designing a new architecture.

One thing I don't like about separating features in individual plugins is when they need to communicate (through natives and forwards). It's about security. The advantage is that it's very easy to extend features by hooking into their events/forwards and call their natives for commanding them to do stuff. But it's too easy mess with features like that. What if a two features need to communicate with each other (through natives), and only those two? Other plugins could call those "private" natives and mess with stuff it's not supposed to touch at all, and possibly corrupt states in features. If all features are compiled into a single plugins, it's much easier to protect features by deciding which parts to expose in the public API.

What would be really cool is if we had a common way to organize stuff in plugins so that features from other plugins could be literally copy-pasted and work. As Greyscale is explaining, that's one of the goals with this experimental base. In theory it works great, but in reality it's just not that easy.

(Sorry if I'm a bit detailed. I speak for everyone at any skill level.)
__________________
Richard Helgeby

Zombie:Reloaded | PawnUnit | Object Library
(Please don't send private messages for support, they will be ignored. Use the forum.)

Last edited by rhelgeby; 07-26-2011 at 22:46.
rhelgeby is offline
Send a message via MSN to rhelgeby
Greyscale
SourceMod Plugin Approver
Join Date: Dec 2007
Location: strYoMommasHouse[you];
Old 07-27-2011 , 03:25   Re: Concept: Project base
Reply With Quote #59

Quote:
Originally Posted by ProdigySim View Post
Maintainability: Some module is exhibiting buggy behavior, or is crashing. The module cannot be isolated from the rest of the code for testing.

Reusability: If I like a chunk of your code, and want to place it in my project or use it as a standalone plugin, I either have to bring the whole project base with me or spend a lot of time trying to decipher function calls and/or execution flow to make things work on its own.

I actually debugged a weird memory corruption bug by commenting out every single module in ZR leaving behind the one with the bug. It made it 100x easier to isolate when I'm looking through a single module. The memory corruption bug was an SM bug with dynamic memory allocation. (new String:mystr[var];)


I didn't mean to say that porting modules from the base to a project without the base would be easy. I should have specified that it's only easy to share between different projects that both use the base.

I agree with rhelgeby that there is so little documentation on this that it would be very difficult for someone to grasp everything that the base can do and what it's meant to do. I'm probably the only one who knows it well enough to actually use it to it's full potential.
__________________
Greyscale is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 16:03.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode