Well, I'm not sure that I have a full idea of what your problems are, but I have several possibilities from what you have put forward so far. (Perhaps, in fact, I suggest some things that have already been done, since I'm not sure that I have enough from single-layer descriptions to fully understand.
Model
I would say that from what you described, the main thing that strikes me is that you want to start implementing common functions in a class model; you will need interfaces or base classes that you can use to get high-level objects.
This way you can process things sequentially with little extra effort. I think the idea of “architectural layers” can be useful as a first stretch of how to think about it (for example, low-level hardware, socket processing, etc.), and then mid-level material, for example, what happens in your game as well as detailed information on how game mechanics, etc., and high-level materials, such as what a PC or NPC can do, what the environment does, etc., as well as the idea that you never want to "jump" through the layers). However, when it comes to this, it’s important to just find the right abstractions for your game and keep everything organized so that you never feel that the bit of code you are working on does two completely different types of things.
So, firstly, let me accept the fact that it sounds (naturally) there are many things interacting with a world state. For something like this, it is probably beneficial to include many “things” in one class, and then basically only one class does the job. Ideally, you implement, say, messaging / messaging in your own small group, so there is no need to pollute higher-level objects using elementary processing data.
For example, you want to focus on what you are doing at a high level in objects of a higher level: in AI it is possible to “start moving to a place”, “establish my haste”, “stop moving”; and in the subsystem of the environment “start to rain”, “increase the speed of the wind”, “dim lights”; in the user class “firearms”, “sleep”, “spell spell”. But I would not want any of my high-level classes to even know about things like “send a message to the world” or “reset the thirst timer”, or “get socket data” or “checkmark for the health cycle”. (All these are just explanations, not suggestions .; D)
Developments
For example, I think that it would be useful to keep one object responsible for sending events to the world, so that you will no longer talk with everyone. Most likely, I'm just creating a set of things to handle events in general. Thus, it is possible for the EventMain and enumEvents that you use so that each type of event has a special identifier. And then use Event as the base class for certain events that need additional functions. (I mean both the identifier and the derivation model, so things like the dispatcher, which probably should know only the most basic things about the event, also don't need to know about the derived classes. The dispatcher can take part in the event and send it without need to know the internals of the derived event. This may or may not be useful, but it is good to have options.) You can also have an EventDispatcher which has an event queue for sending to other subsystems.
You need something in common to receive and send events. You can make standalone classes EventSourcer and EventSinker , which can be configured in any class that generates or receives events. Or you could instead make IEventSource and IEventSink so that you can implement a common interface for several classes, or perhaps a common EventSourceAndSink class that implements both, and which is part of your base class model, so all that may need to be handled events can simply flow from it.
I would probably do the ProtocolEncoder and ProtocolDecoder classes. You can always combine them into one object, but it can be valuable and should not cause any problems if it is performed properly so that they are two separate pieces of code. You can also have a ProtocolHelper class that separates something in common between them. The only task of coders is to receive messages from the network and include them in events for your game, which are then transmitted to EventDispatcher . The decoder class will receive events from the dispatcher, which should go online, and it will take data from them and send them.
How to get where you go
Since you have working code, I would recommend that you just start doing this when it seems natural. It can be things that bind you, or things that you notice are very similar in different places that you could do regular with a class or some other type of abstraction, then pull out the old and insert the new. After you figure out a workable first cut of the class model, this should give you ideas based on what you already have, and as you go, constantly review your model, fixing what is the problem, lather , rinse, repeat.
This should not be a lot of work, in fact, some of the most enjoyable moments that I worked on the code were that I was able to make a neat refactor that left a previously disgusting mess much better than the form, removing a lot of hard to understand code and replacing it being easier to understand in fewer lines of code, and this opened the way to my next addition, which is a pleasure instead of another “zomg i don”, Do I need to touch this code again? "moment.
We wish you good luck, here is a nominal guide to what I talked about; the first bit is more detailed, because the main class of events is one of the most important concepts, and then I try to just give a nominal overview of the classes and their interaction. I’m sure I can spend even more hours on this, but now I’ll just say: ask me if you have any questions and I will do everything in my power to give you a good answer :)
Code Ideas
Oh, one more note: I did not deal with the difficulties added if you have multiple threads; there are things from simple to complex to manage it all if you do it, but this is a different exercise. :)
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms;