Jump to content
Eternal Lands Official Forums
Wytter

Modularization of elc

Recommended Posts

Greetings,

 

I have given some thought into the modularization of elc that we have talked about before. I think that it would be wise to modularize ELC in order to reduce code duplication between different parts of EL (and even different forks).

In order to do this I decided to split up elc into 5 main components: core, gui, init, load and network. The code in core and load will easily be shared between different forks/parts of elc, while gui, init and network are implementation dependant.

By dividing the elc into these different components, we will make sure that all clients/the map editor based on elc benifits from the improvements done to the core renderer and loading engine, hence encouraging more cooperation between the different elc forks.

  • elc
    • core
      • Contains the core renderer
      • Contains the window manager
      • Contains the widgets - the single widgets will be in an additional directory, with one file per widget
      • Contains the core sound engine
      • Contains the timers for updating the scenery (animations etc.)
      • Contains a main thread checking the update queue, containing data from the network thread (or map editor or single-player engine)
      • Contains the functions for initiating OpenGL, creating the windows etc.

      [*]gui

      • Contains the different windows for the client.
      • Contains the HUD
      • Contains the command callbacks (both #command and hotkeys), which will manipulate states in the core or call commands found in network.

      [*]init

      • Initiates the client - calls the functions for loading configuration files etc. All functions for GL initiation are in core
      • Contains the command list for the client
      • Contains the configuration init (add_var()...) for the client

      [*]load

      • Map loading/saving. Contains the different versions of the map formats for each of EL's forks
      • Object loading/(saving - for i.e. particles)
      • Texture loading
      • Configuration/saved data file loading
      • Language file loading
      • Music/sound loading

      [*]network

      • Contains the functions for network interaction: Recieving and pre-processing (before displaying) and sending.
      • The package reciever will run in a seperate thread like in the current thread implementation. The reciever would parse the network data, and then send a pointer to the parsed data to the renderer through a queue. This way we could easily remove the network and replace it with a single-player engine.

    [*]map_editor2

    • init
      • Initiates the map_editor. Calls the functions from elc/core for initiating GL.
      • Contains the command list for the map_editor
      • Contains the configuration init (add_var()...) for the map_editor

      [*]gui

      • Contains the windows used in the map_editor
      • Contains the HUD for the map editor
      • Contains the command callbacks (both #command and hotkeys), which will manipulate states in the core/call functions in load.

    [*]Imaginary single-player EL

    • init
      • Can possibly use most of the functions from elc/init, but also needs to initiate the single-player engine, script loader etc.

      [*]gui

      • Additional GUI files + commands + hotkeys for the single-player game

      [*]engine

      • Works sort of like the network in the client, interacting with the core through a queue structure.
      • Contains support for the scripting language of choice

Please give me some comments on this structure.

Share this post


Link to post
Share on other sites

I havent done any coding for elc yet so far. So my opinion is like a spacefart.

But i have seen .. ALOT project (trying) being split like this.

I KNOW its 99% (trying) to understand the code by, stepin, stepin, stepout... Structure it up.. Seems like a good idea, but i've never seen it work in reality, and everyone knows its gonna be 99,9% (stepin, stepin, stepout) in .. maybe a year.. But let it be so, please, because thats programming. Its starting to get so big that no-one can understand the whole picture, and I know u cant either! (period)!

 

Best Regards

Share this post


Link to post
Share on other sites

There has been a bunch of talk about this before, For me, This will be great, clearly defined areas of ELC means the eventual possibility of assigned managers to those areas. So bugs can go to the right people.

 

Also means things like droping the global.h are more likely to happen. I found when testing that patch, it made a faster and smaller ELC.

 

Will make life easyer trying to find gear in the source for coders who are keen on joining the project too.

Share this post


Link to post
Share on other sites

I'd also suggest that all non-trivial data structures have their own tree in there. stuff like linked lists, the queue, anything else like that. it makes sence to only ever include the tools once, and have them all in one place

 

'load' might need a better name to show that it's load & save if you use that in the tree

personally, with all the widgets we have, I'd have them as their own tree (there's probably more code in widgets that init, for example)

Contains the functions for initiating OpenGL, creating the windows etc.
core should call the functions for init, not contain them

 

as to the idea itself... well... it sounds good, but with our shortage on coders it'll mean that feature coding will be pretty much on hold.

on the other hand, we really do need a feature freeze while we clean up ELC (preferably after waiting patches have been evaluated and added or rejected, otherwise they'll all need to be rewritten in a major way for the new structure)

the code is suffering from peicemeal patching, and does need to be cleaned up. just doing this without any other code changes may give us a performance boost... and going through all the old code gives us the chance to see things that can be removed or fixed

at the same time, we should do away with as many -D options as practical. some shouldn't be removed, sure, but there are a lot at current that people might not even use (or always use)

 

if we have enough coders willing to spend time on this, then I'm all for it (and I'll do a bunch of coding for this)

oh, and that can be any coder, really, you don't even need to know much C to be able to copy'n'paste code, or see duplicated work... it helps, of course, but people who'd like to start on ELC coding are still going to be able to join in

Share this post


Link to post
Share on other sites

Sounds like a good idea, because I would like to use the EL engine for a stand alone game (in the future).

Just don't use classes and C++ like code with function pointers and stuff :P

 

However, I think a better split would be to keep the Eternal Lands code separated from the engine itself. The Eternal Lands code is the networking code and the GUI.

Share this post


Link to post
Share on other sites

Gravito: I have already proven that it is possible to share a lot of the base code in map_editor2, this is just taking it to the next step.

 

ttl: I think that i.e. the queue should be a part of the core functions. Could be in a tools directory, but not sure how necissary that should be...

As for init... I follow you, but thing is that I don't want code duplication, and the functions for setting up GL are needed in any of the games based on ELC, while the init functions for each game will be slightly different (loading an ini-file different than el.ini etc.)

 

Entropy: Yes, I have been thinking about that as well. Simply creating a new module for the core engine containing the core and load directories, and then have a network, init and gui directory in the elc module would work fine, and probably cause less confusion. The code will not really be changed, and especially not in that way; they will become a bit more generic though, such as functions for reading el.ini would have to be called with the name of the el.ini you wish to read (that can be "el.ini", "mapedit.ini" etc.) and in functions for creating the window would get the window name, window icon specified.

 

I have a week off uni in late january, during that week I can put most of the ideas into place. However, it should not happen at the same time as the update since there may be introduced some new bugs. So we'll have to coordinate that.

Edited by Wytter

Share this post


Link to post
Share on other sites

ttl: I think that i.e. the queue should be a part of the core functions. Could be in a tools directory, but not sure how necissary that should be...

we have queue and linked list in the client so far, we might add something else at a later stage, hence why I suggested having that sort of thing seperate. if anyone needs a new data structure or to change one, they should do it there rather than in their own files (handling stuff as you put it in/out is done locally, of course)

more orderly and saves effort

As for init... I follow you, but thing is that I don't want code duplication, and the functions for setting up GL are needed in any of the games based on ELC, while the init functions for each game will be slightly different (loading an ini-file different than el.ini etc.)

ahh, okay... well if we split the engine out then this is a moot point anyway

I have a week off uni in late january, during that week I can put most of the ideas into place.

I'm on holidays until about march, so I have plenty of time to work on EL :)

However, it should not happen at the same time as the update since there may be introduced some new bugs. So we'll have to coordinate that.

well, how about we start a feature freeze a bit before the update, and have only bug fixes and such then, go through outstanding patches to clean that list up, and then after a week or whatever once it looks like there are no serious bugs, we start reorganising and cleaning everything up (and the feature freeze continues while this happens)

Share this post


Link to post
Share on other sites

we have queue and linked list in the client so far, we might add something else at a later stage, hence why I suggested having that sort of thing seperate.

Actually, we also have all the stuff in asc.c, and sort.c as well, and probably some other stuff I'm overlooking.

Share this post


Link to post
Share on other sites

We kind of are into a feature freeze right now (at least for the 3D part of the game). Small things can get in, but not OpenGL stuff (unless specifically asked).

We plan the update on 15 January (or around that date).

 

I want to make an X-Com like game with the EL engine (I will work at it a little every day, in parallel with the normal EL development).

So I did some thinking about splitting the client.

 

The way I see it is to keep the stuff such as the actors and their drawing, 3d objects, 2d objects, shadows, reflections, particles, and everything graphic/sound related and various help files such as asc.c and stuff. But no GUI related stuff as that should be game specific.

The network code, of course, should dissapear from the main engine, as it is not really usefull for anything but EL.

The config functions can stay in the engine, as many of them deal with configuration of stuff.

So should the console and text display, with the mention that some console commands must dissapear.

 

If we do this split we might want to also rename the files, the EL specific files should have the _el prefix.

Share this post


Link to post
Share on other sites

Yes, that's what it says Radu :P

 

The reason why I want i.e. load in a different directory is that we might want to later on create external tools that don't use the renderer but just loads the files. They can still use the code that are in the load directory but don't have to depend on the core renderer. The cal3d actors could also be put in an additional sub-directory of the renderer, since we could have support for several formats in the engine.

 

As for the configuration, the game-specific configuration options and functions should be in the game's own directory. However the higher level functions for i.e. adding a configuration, parsing the configuration files etc. is a part of the engine.

 

The functions in gui should call high-level network functions that set the protocol and then use a send_tcp_message(Uint8 type, Uint8 * data, Uint32 data_length), where the lower-level function handles the package structure. This way the lower-level function could for instance pack messages together, choose not to have a length parameter on some functions with fixed lengths (hence saving bandwidth), etc. (Will be a lot easier to maintain like this)

Only the high level network functions should call the low-level network function. Example (pseudo code):

 

gui:
struct recipe_struct {
	Uint8 pos;
	Uint16 qty;
} manu_recipe;

int mix_clicked()
{
	mix_items(manu_recipe);
	return 1;
}

high-level network:
int mix_items(recipe_struct * recipe)
{
   char data[MAX_RECIPE*(sizeof(Uint8)+sizeof(Uint16))];
   int i;

   for(i=0;i<MAX_RECIPE;i++){
		 data[i*sizeof(recipe_struct)]=recipe[i].pos;
		 Write_Uint16(&data[i*sizeof(recipe_struct)+sizeof(Uint8)],recipe[i].qty);
   }

   send_tcp_data(MIX, data, sizeof(data));
}

low-level network:
int send_tcp_data(Uint8 type, Uint8 * data, Uint32 size)
{
	 char out_data[MAX_OUT_DATA];
	 Uint16 out_size = size+sizeof(Uint8)+sizeof(Uint16);//type (Uint8) + length (Uint16) + data length (size)

	 out_data[0]=type;
	 Write_Uint16(out_data+1, out_size); 
	 memcpy(out_data, data, size);

	return SDL_send(out_data, out_size);//Yea whatever, I don't recall the name of the func;-)
}

 

I believe that in the core renderer, all debugging functions should follow an assert-like pattern:

 

int add_character(actor *act)
{
  if(actor_is_null(act == NULL)) return;
...
}

static __inline__ int actor_is_null(int true)
{
	  if(true){
#ifdef DEBUG
			log_error("Tried to add a NULL actor");
#endif
			return 1;
	  } 
	  return 0;
}

 

These debugging functions would then be put in a .h, so they can be more easily maintained and not pollute the renderer with tons of #ifdef DEBUG's.

Edited by Wytter

Share this post


Link to post
Share on other sites

I don't think the network should be part of the engine, high or low level.

Most of the game simplement their very own totally specific networking subsystem (some use TCP, some use UDP, some use both, some use neither, etc.).

Share this post


Link to post
Share on other sites

No, that was for the elc implementation of the network. If someone comes and wants to just replace the networking part (either with a single-player engine or make it use a different network protocol etc.), that can easily be done by just rewriting the network if the gui only calls high-level network functions, hence all changes that are done in the gui will still be done in his part, as he only replaced the networking. It will lead to a lot less maintaining, and more development.

Edited by Wytter

Share this post


Link to post
Share on other sites

I think we should replace the stuff with event handles, rather than networking stuff.

For example, the eye icon should triger an look_at() event, which in the EL case will send the look at command, but an independent game can do something else, like outputing a text, etc.

Same with the walk and other stuff.

Share this post


Link to post
Share on other sites

Hmm, yes - we could have an event queue for that. That way it can be send in a different thread, hence networking delays will not have an effect on the renderer.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×