Event handling in component based game engine design - oop

I imagine this question or variations of it get passed around a lot, so if what I'm saying is a duplicate, and the answers lie elsewhere, please inform me.
I have been researching game engine designs and have come across the component-based entity model. It sounds promising, but I'm still working out its implementation.
I'm considering a system where the engine is arranged of several "subsystems," which manage some aspect, like rendering, sound, health, AI, etc. Each subsystem has a component type associated with it, like a health component for the health subsystem. An "entity," for example an NPC, a door, some visual effect, or the player, is simply composed of one or more components, that when together give the entity its functionality.
I identified four main channels of information passing: a component can broadcast to all components in its current entity, a component can broadcast to its subsystem, a subsystem can broadcast to its components, and a subsystem can broadcast to other subsystems.
For example, if the user wanted to move their characters, they would press a key. This key press would be picked up by input subsystem, which then broadcasts the event and would be picked up by the player subsystem. The player subsystem then sends this event to all player components (and thus the entities those components compose), and those player components would communicate to its own entity's position component to go ahead and move.
All of this for a key press seems a bit winded, and I am certainly open to improvements to this architecture. But anyway, my main question still follows.
As for the events themselves, I considered where an event behaves as in the visitor pattern. The importance of what I want is that if an event comes across a component it doesn't support (as in a move event has nothing directly to do with AI or health), it would ignore the component. If an event doesn't find the component it's going after, it doesn't matter.
The visitor pattern almost works. However, it would require that I have virtual functions for every type of component (i.e. visitHealthComponent, visitPositionComponent, etc.) even if it doesn't have anything to do with them. I could leave these functions empty (so if it did come across those components, it would be ignored), but I would have to add another function every time I add a component.
My hopes were that I would be able to add a component without necessarily adding stuff to other places, and add an event without messing with other stuff.
So, my two questions:
Are there any improvements my design could allow, in terms of efficiency, flexibility, etc.?
What would be the optimal way to handle events?

I have been thinking about using entity systems for one of my own projects and have gone through a similar thought process. My initial thought was to use an Observer pattern to deal with events - I too, originally considered some kind of visitor pattern, but decided against it for the very reasons you bring up.
My thoughts are that the subsystems will provide a subsystem specific publish/subscribe interface, and thus subsystem dependencies will be resolved in a "semi-loosely" coupled fashion. Any subsystem that depends on events from another subsystem will know of the subscriber interface to that subsystem and thus can effectively make use of it.
Unfortunately, how these subscribers get handles to their publishers is still somewhat of an issue in my mind. At this point, I am favoring some kind of dynamic creation where each subsystem is instantiated, and then a second phase is used to resolve the dependencies and put all the subsystems into a "ready state".
Anyway, I am very interested in what worked out for you and any problems you encountered on your project :)

Use an event bus, aka event aggregator. What you want is an event mechanism that requires no coupling between subsystems, and an event bus will do just that.
http://martinfowler.com/eaaDev/EventAggregator.html
http://stackoverflow.com/questions/2343980/event-aggregator-implementation-sample-best-practices
etc

this architecture described here http://members.cox.net/jplummer/Writings/Thesis_with_Appendix.pdf
There are at least three problems I encountered implementing this in a real project:
systems aren't notified when something happen - only way is to ask about it - player is dead? wall isn't visible? and so on - to avoid this you can use simple MVC instead of observer pattern.
what if your object is a composit (i.e. consists of objects)? system will traverse through all hierarchy and asking about component state.
And main disadvantage is that this architecture mixes all together -for e.g why do player need to know that you pressed a key?
i think that answer is layered architectures with abstracted representation...

Excuse my bad English.
I am writing a flexible and scalable java 3d Game Engine based on Entity-Component System. I have finished some basic parts of it.
First i want to say something about ECS architecture, I don't agree that a component can communicate with other components in a same entity. Components should only store data and systems process them.
In event handling part, I think the basic input handling should not be included in a ECS. Instead, I have a System called Intent System and have a Component called Intent Component which contains many intents. A intent means a entity wants to do something toward a entity.
the Intent System process all the intents, When it processes a intent, it broadcasts the corresponding information to other systems or add other components to the entity.
I also write a interface called Intent Generator. In local game, you can implement a Keyboard Input or Mouse Input Generator and in multiple-player game, you can implement network intent generator. In AI system, you can also generate intents.
You may think the Intent System processes too many things in the game. But in fact, it shares many processing to other systems And I also write a Script System. For specific special entity it has a script component doing special things.
Originally when I develop something, I always want to make a great architecture which includes every thing. But for game developing sometimes it is very inefficient. Different game object may have completely different functions. ECS is great as data-oriented programming system. but we can not include every thing in it for a complete game.
By the way, Our ECS-based game engine will be open source in near future, then you can read it. If u are interested in it, I also invite u to join us.

Related

Angular 6 - Why use #ngrx/store rather than service injection

I am recently learning Angular 6 with #ngrx/store while one of the tutorial is to use #ngrx/store for state management, however I don't understand the benefit of using #ngrx/store behind the scene.
For example, for a simple login and signup action, previously by using the service(Let's call it AuthService) we might use it to call the backend api, store "userInfo" or "token" in the AuthService, redirect user to "HOME" page and we can inject AuthService in any component where we need to get the userInfo by using DI, which simply that one file AuthService handles everything.
Now if we are using #ngrx/store, we need to define the Action/State/Reducer/Effects/Selector which probably need to write in 4 or 5 files to handle above action or event, then sometimes still we need to call backend api using service, which seems much much more complicated and redundant...
In some other scenario, I even see some page uses #ngrx/store to store the object or list of object like grid data., is that for some kind of in-memory store usage?
So back to the question, why are we using #ngrx/store over service registration store here in Angular project? I know it's for "STATE MANAGEMENT" usage, but what exactly is the "STATE MANAGEMENT"? Is that something like transaction log and When do we need it? Why would we manage it on the front end? Please feel free to share your suggestion or experience in the #ngrx/store area!
I think you should read those two posts about Ngrx store:
Angular Service Layers: Redux, RxJs and Ngrx Store - When to Use a Store And Why?
Ngrx Store - An Architecture Guide
If the first one explains the main issues solved by Ngrx Store, it also quote this statement from the React How-To "that seems to apply equally to original Flux, Redux, Ngrx Store or any store solution in general":
You’ll know when you need Flux. If you aren’t sure if you need it, you don’t need it.
To me Ngrx store solves multiple issues. For example when you have to deal with observables and when responsability for some observable data is shared between different components. In this case store actions and reducer ensure that data modifications will always be performed "the right way".
It also provides a reliable solution for http requests caching. You will be able to store the requests and their responses, so that you could verify that the request you're making has not a stored response yet.
The second post is about what made such solutions appear in the React world with Facebook's unread message counter issue.
Concerning your solution of storing non-obvervable data in services. It works fine when you're dealing with constant data. But when several components will have to update this data you will probably encounter change detection issues and improper update issues, that you could solve with:
observer pattern with private Subject public Observable and next function
Ngrx Store
I'm almost only reading about the benefits of Ngrx and other Redux like store libraries, while the (in my opinion) costly tradeoffs seem to be brushed off with far too much ease. This is often the only reason that I see given: "The only reason not to use Ngrx is if your app is small and simple". This (I would say) is simply incomplete reasoning and not good enough.
Here are my complaints about Ngrx:
You have logic split out into several different files, which makes the code hard to read and understand. This goes against basic code cohesion and locality principles. Having to jump around to different places to read how an operation is performed is mentally taxing and can lead to cognitive overload and exhaustion.
With Ngrx you have to write a lot more code, which increases the chances of bugs. More code -> more places for bugs to appear.
An Ngrx store can become a dumping ground for all things, with no rhyme or reason. It can become a global hodge podge of stuff that no one can get a coherent overview of. It can grow and grow until no one understands it any more.
I've seen a lot of unnecessary deep object cloning in Ngrx apps, which has caused real performance issues. A particular app I was assigned to work on was taking 40 ms to persist data in the store because of deep cloning of a huge store object. This is over two lost render frames if you are trying to hit a smooth 60 fps. Every interaction felt janky because of it.
Most things that Ngrx does can be done much simpler using a basic service/facade pattern that expose observables from rxjs subjects.
Just put methods on services/facades that return observables - such a method replaces the reducer, store, and selector from Ngrx. And then put other methods on the service/facade to trigger data to be pushed on these observables - these methods replace your actions and effects from Ngrx. So instead of reducers+stores+selectors you have methods that return observables. Instead of actions+effects you have methods that produce data the the observables. Where the data comes from is up to you, you can fetch something or compute something, and then just call subject.next() with the data you want to push.
The rxjs knowledge you need in order to use ngrx will already cause you to be competent in using bare rxjs yourself anyways.
If you have several components that depend on some common data, then you still don't need ngrx, as the basic service/facade pattern explicitly handles this already.
If several services depend on common data between them, then you just make a common service between these services. You still don't need ngrx. It's services all the way down, just like it is components all the way down.
For me Ngrx doesn't look so good on the bottom line.
It is essentially a bloated and over engineered Enterprise™🏢👨‍💼🤮 grade Rxjs Subject, when you could have just used the good old and trusty Rxjs Subject. Listen to me kids, life is too short for unnecessary complexity. Stick to the bare necessities. The simple bare necessities. Forget about your worries and your strife.
I've been working with NgRx for over three years now. I used it on small projects, where it was handy but unnecessary and I used it in applications where it was perfect fit. And meanwhile I had a chance to work on the project which did not use it and I must say it would profit from it.
On the current project I was responsible for designing the architecture of new FE app. I was tasked to completely refactor the existing application which for the same requirements used non NgRx way and it was buggy, difficult to understand and maintain and there was no documentation. I decided to use NgRx there and I did it because of following reasons:
The application has more than one actor over the data. Server uses
the SSE to push state updates which are independent from user
actions.
At the application start we load most of available data which are
then partially updated with SSE.
Various UI elements are enabled/disabled depending on multiple
conditions which come from BE and from user decisions.
UI has multiple variations. Events from BE can change currently
visible UI elements (texts in dialogs) and even user actions might
change how UI looks and works (recurring dialog can be replaced by
snack if user clicked some button).
State of multiple UI elements must be preserved so when user leaves
the page and goes back the same content (or updated via SSE) is
visible.
As you can see the requirements does not meet the standard CRUD operations web page. Doing it the "Angular" way brought such complexity to the code that it became super hard to maintain and what's worst by the time I joined the team the last two original members were leaving without any documentation of that custom made, non NgRx solution.
Now after the year since refactoring the app to use NgRx I think I can sum up the pros and cons.
Pros:
The app is more organized. State representation is easy to read,
grouped by purpose or data origin and is simple to extend.
We got rid of many factories, facades and abstract classes which lost
their purpose. The code is lighter, and components are 'dumber', with
less hidden tricks coming from somewhere else.
Complicated state calculations are made simple using effects and
selectors and most components can be now fully functional just by
injecting the store and dispatching the actions or selecting the
needed slice of the state while handling multiple actions at once.
Because of updated app requirements we were forced to refactor the
store already and it was mostly Ctrl + C, Ctrl + V and some renaming.
Thanks to Redux Dev Tools it is easier to debug and optimize (yep
really)
This is most important - even thought our state itself is unique the
store management we are using is not. It has support, it has
documentation and it's not impossible to find solutions to some
difficult problems on the internet.
Small perk, NgRx is another technology you can put to your CV :)
Cons:
My colleagues were new to the NgRx and it took some time for them to
adapt and fully understand it.
On some occasions we introduced the issue where some actions were
dispatched multiple times and it was difficult to find the cause of
it and fix it
Our Effects are huge, that's true. They can get messy but that's what
we have pull requests for. And if this code wasn't there it would
still end up somewhere else :)
Biggest issue? Actions are differentiated by their string type. Copy
an action, forget to rename it and boom, something different is
happening than you expect, and you have no clue why.
As a conclusion I would say that in our case the NgRx was a great choice. It is demanding at first but later everything feels natural and logical. Also, when you check the requirements, you'll notice that this is a special case. I understand the voices against NgRx and in some cases I would support them but not on this project. Could we have done it using 'Angular' way? Of course, it was done this way before, but it was a mess. It was still full of boiler plate code, things happening in different places without obvious reasons and more.
Anyone who would have the chance to compare those two versions would say the NgRx version is better.
There is also a 3rd option, having data in service and using service directly in html, for instance *ngFor="let item of userService.users". So when you update userService.users in service after add or update action is automatically rendered in html, no need for any observables or events or store.
If the data in your app is used in multiple components, then some kind of service to share the data is required. There are many ways to do this.
A moderately complex app will eventually look like a front end back end structure, with the data handling done in services, exposing the data via observables to the components.
At one point you will need to write some kind of api to your data services, how to get data in and out, queries, etc. Lots of rules like immutability of the data, and well defined single paths to modify the data. Not unlike the server backend, but much quicker and responsive than the api calls.
Your api will end up looking like one of the many state management libraries that already exist. They exist to solve difficult problems. You may not need them if your app is simple.
NGRX sometimes has a lot of files and a lot of duplicate code. Currently working on a fix for this. To make generic type classes for certain NGRX state management situations that are very common inside an Angular project like pagers and object loading from back-ends

2 separate systems, how to make them communicate

I got a DDS-system(OMG DDS) who's communicating with a ROS-node over radio. The information being received is a struct with velocity, state, longitude, latitude etc. This works well, and my DDS-client has no problem printing the information being transmitted from the node over the radio. Now, I've got a GUI-application written in Qt, who creates models and puts them on a predefined map. These modelse have defined set-information functions, which when triggered updates the map to give a smooth visualisation of the information it receives.
Now here is problem, I've no idea how to make the GUI application communicate with my DDS-client. I would rather not intertwine these two, since I've had enough trouble just making the DDS-client and sender work and compile with ROS. Ive though about a separate queue system, which can be included in the DDS-client and the GUI application, but I dont know if this could work. Ive also though about writing a SQL database, and then push new data, and pull new data when it is detected in my GUI application. Some sort of on_data_available function which triggers the pull-function. Ive heard the last one is a bad idea, since I'm working with only one set of data which is being continuously updated (the model represents one USV), and a database is then considered overkill, but I would love to get inputs here.
Im sorry if this isn't sufficient information, I can't really provide code examples for different reasons. If anyone have any inputs, shout out, would love to hear them. And if I'm not being specific enough, ill try to rewrite it as best as i can.
I've no idea how to make the GUI application communicate with my
DDS-client
Your question is not specific to DDS or your GUI application -- you essentially ask for a simple and convenient inter-process communication (IPC) mechanism. As you can see when you follow the link, there are loads of different options.
Given that you already have your data as well as the associated type definitions available in DDS, I suspect that using DDS for this task would still be the easiest way to go. You could set it up to communicate over shared memory or local loopback. DDS will do all discovery and communication under the hood, including (cross-language) de/serialization. If you choose a different mechanism, you might end up doing more work yourself.
As an alternative, some DDS implementations (commercially) support native integration with SQL databases. Those will introspect the DDS data definitions and create all required tables for you. Updates from DDS are automatically forwarded to the database, and vice-versa. You could feed your GUI off of that database.

What are common alternatives to maintaining state in a desktop application other than state machines?

I am working on a desktop application that is a few years old. The application's state (regarding what the user is currently performing (multi-step actions), what computation is being performed, the state of/permissions on the data, background jobs, etc) is maintained through many different methods (event subscription, member variables in controller classes, dependance on the internal logic/behaviour of other classes, etc...)
So my question is, what common patterns (other than explicit state machines) exist to manage the state of the application that are flexible enough to allow:
state nesting/localization to specific modules (every component's state isn't necessarily needed by every other component. A wizard, for example, would have a private/nested/local state that is exposed to any part of it but not to the entire application)
state easily exposed/shared/reachable (i.e: the selection in some view needs to be reachable/visible to a copy button and the button would also need to be aware of the context (is the user performing a multi-step operation or is some task running in the background so I can only copy and not cut))
It's a GUI application so we can depend on the hierarchical nature of the application when sharing/reaching different states.
State machines are simple enough to be understood by novice programmer, so it may be easier to find a person capable of helping with development later. Also there are few existing libraries and tools to work with state machines, so it may be easier from other aspects. You can also use more than one state machine and let them communicate via some simple pub/sub infrastructure.
Similar approach is Petri Nets. It is a bit more complicated, I have no real experience with implementation yet, but it allows multiple states to be active at once to express parallel processes. Otherwise it looks very similar to traditional finite state machine.

Entity System - Storing components in a Manager vs. in Entity

Like many aspiring designers and programmers out there, I've stumbled upon the Entity/Component System design, including various excellent articles on the subject and a few working implementations as well. And I, like many others, have taken it upon myself to implement such a system.
Conceptually an Entity is a bag of components, which are nothing more than bags of data to be handled by a series of Systems. So it would seem logical to me that an Entity object could be used to hold all components associated with it, but others' work says otherwise. Across all of my research it seems almost universally understood that an Entity is nothing more than an ID and that you must avoid at all costs falling into the trap of Object Oriented thinking. They suggest storing the components in a manager instead, but without directly addressing the advantages of such a design.
Don't both designs, components held in the entity vs. in the manager result in the same end result? Please let me know if I'm misunderstanding / missing something.
I am in no way an expert with Entity Component Systems, but here is my view on the subject from what I have read.
I think that you should never access components directly. If you do, then your components begin to rely one another, and later, when you decide that you want to change how one component behaves, all of the other components relying on the one you want to change now have to be fixed.
To avoid this problem, components should not know anything about each other. They each have one job and should only focus on that job. If some data is needed from another component (for example, you may need positional data), you should either ask another system for the data, or develop a messaging system.
Of course, once you actually start coding, it is hard to comply with this rule 100% of the time, but you get the idea.
Another reason to avoid storing components in an entity is for speed. When components are contained in systems (where all the like-components are stored together), you can process large amounts of components quickly. You have a chance to setup any data they may be reused, loop through and process each component, and then release any reused data. Not only this, but each system may (should) be able to run on a separate thread, which allows you to easily take advantage of multiple cores.
Again, in practice, this isn't always 100% true, but that is the theory of it.
In summary, keeping components in systems rather than in the entity reduces the temptation of directly accessing components, and allows for bulk updates in systems. I hope this helps, and if you have any questions, please let me know.

Protection against automation

One of our next projects is supposed to be a MS Windows based game (written in C#, with a winform GUI and an integrated DirectX display-control) for a customer who wants to give away prizes to the best players. This project is meant to run for a couple of years, with championships, ladders, tournaments, player vs. player-action and so on.
One of the main concerns here is cheating, as a player would benefit dramatically if he was able to - for instance - let a custom made bot play the game for him (more in terms of strategy-decisions than in terms of playing many hours).
So my question is: what technical possibilites do we have to detect bot activity? We can of course track the number of hours played, analyze strategies to detect anomalies and so on, but as far as this question is concerned, I would be more interested in knowing details like
how to detect if another application makes periodical screenshots?
how to detect if another application scans our process memory?
what are good ways to determine whether user input (mouse movement, keyboard input) is human-generated and not automated?
is it possible to detect if another application requests informations about controls in our application (position of controls etc)?
what other ways exist in which a cheater could gather informations about the current game state, feed those to a bot and send the determined actions back to the client?
Your feedback is highly appreciated!
I wrote d2botnet, a .net diablo 2 automation engine a while back, and something you can add to your list of things to watch out for are malformed /invalid/forged packets. I assume this game will communicate over TCP. Packet sniffing and forging are usually the first way games (online anyways) are automated. I know blizzard would detect malformed packets, somehting i tried to stay away from doing in d2botnet.
So make sure you detect invalid packets. Encrypt them. Hash them. do somethign to make sure they are valid. If you think about it, if someone can know exactly what every packet means that is sent back and forth they dont even need to run the client software, which then makes any process based detection a moot point. So you can also add in some sort of packet based challenge response that your cleint must know how to respond to.
Just an idea what if the 'cheater' runs your software in a virtual machine (like vmware) and makes screenshots of that window? I doubt you can defend against that.
You obviously can't defend against the 'analog gap', e.g. the cheater's system makes external screenshots with a high quality camera - I guess it's only a theoretical issue.
Maybe you should investigate chess sites. There is a lot of money in chess, they don't like bots either - maybe they have come up with a solution already.
The best protection against automation is to not have tasks that require grinding.
That being said, the best way to detect automation is to actively engage the user and require periodic CAPTCHA-like tests (except without the image and so forth). I'd recommend utilizing a database of several thousand simple one-off questions that get posed to the user every so often.
However, based on your question, I'd say your best bet is to not implement the anti-automation features in C#. You stand very little chance of detecting well-written hacks/bots from within managed code, especially when all the hacker has to do is simply go into ring0 to avoid detection via any standard method. I'd recommend a Warden-like approach (download-able module that you can update whenever you feel like) combined with a Kernel-Mode Driver that hooks all of the windows API functions and watches them for "inappropriate" calls. Note, however, that you're going to run into a lot of false positives, so you need to not base your banning system on your automated data. Always have a human look over it before banning.
A common method of listening to keyboard and mouse input in an application is setting a windows hook using SetWindowsHookEx.
Vendors usually try to protect their software during installation so that hacker won't automate and crack/find a serial for their application.
Google the term: "Key Loggers"...
Here's an article that describes the problem and methods to prevent it.
I have no deeper understanding on how PunkBuster and such softwar works, but this is the way I'd go:
Iintercept calls to the API functions that handle the memory stuff like ReadProcessMemory, WriteProcessMemory and so on.
You'd detect if your process is involved in the call, log it, and trampoline the call back to the original function.
This should work for the screenshot taking too, but you might want to intercept the BitBlt function.
Here's a basic tutorial concerning the function interception:
Intercepting System API Calls
You should look into what goes into Punkbuster, Valve Anti-Cheat, and some other anti-cheat stuff for some pointers.
Edit: What I mean is, look into how they do it; how they detect that stuff.
I don't know the technical details, but Intenet Chess Club's BlitzIn program seems to have integrated program switching detection. That's of course for detecting people running a chess engine on the side and not directly applicable to your case, but you may be able to extrapolate the apporach to something like if process X takes more than Z% CPU time the next Y cycles, it's probably a bot running.
That in addition to a "you must not run anything else while playing the game to be eligible for prizes" as part of the contest rules might work.
Also, a draconian "we might decide in any time for any reason that you have been using a bot and disqualify you" rule also helps with the heuristic approach above (used in prized ICC chess tournaments).
All these questions are easily solved by the rule 1 above:
* how to detect if another application makes periodical screenshots?
* how to detect if another application scans our process memory?
* what are good ways to determine whether user input (mouse movement, keyboard input) is human-generated and not automated?
* is it possible to detect if another application requests informations about controls in our application (position of controls etc)?
I think a good way to make harder the problem to the crackers is to have the only authoritative copies of the game state in your servers, only sending to and receiving updates from the clients, that way you can embed in the communication protocol itself client validation (that it hasn't been cracked and thus the detection rules are still in place). That, and actively monitoring for new weird behavior found might get you close to where you want to be.