Had a quick look through the source code. Seems like you're using MVC, is that right? Would you care to say a little bit more about the technical design aspects of it?
Sure. Well, something very close to MVC. I find the basics of the pattern maps to most software nicely, with appropriate allowances and modifications of course (such allowances may turn it into MVP, or MVVM or...you get the idea).
I cheat the pattern in a few points in this, since it wasn't written to be maintained on a long-term basis so I could afford to cut corners (same reason that there is no unit tests). Some controllers do more than they should, and should of been split down to multiple controllers. Plus I've done things a bit less cleanly here, normally I find it better to encapsulate the business logic into a services layer instead of putting it straight in the controllers. In the way I've seen and had the best experience with MVC, "model" is just DTOs and the services are the business logic, with a data access layer acting as the glue between models and services.
Considering I wrote most of this whilst on pain killers and antibiotics as a result of infected wisdom tooth, it's kinda surprising to me there's actually any structure to the code at all xD
This is what I wrote about the responsibilities of each package in my uni write-up:
---
uk.co.morleydev.ghosthunt :- The root package contains the base classes for the running of the program itself, the Main entry point and the Game as well as the ControllerStore and ViewStore used for managing the alive controllers and views
controller :- Contains the controllers for the running of the client and server, and the logical processing and updating of the game world and entities, through events, network messages or frame ticks.
The controllers are where the primary difference between the client and server lie. The key difference is in which controllers are used. The client uses predominantly reactive controllers that receive information about how to act, but do very little logic themselves aside from when user input is involved. The server’s controllers send more data, as they are responsible for collision detection between actors and informing the game of many of the possible state changes such as when the hero wins or loses, and when pellets are collected.
However, there is also an overlap of controllers used by both server and client. The physics code is the key example here, with the physics being ran each frame both remotely and locally. This allows the server to only notify the the client about the changes to the direction of actors and the client to independently process their physics, reducing the amount of communication needed between client and server.
view :- Contains the views responsible for displaying the game world to the user, displaying the appropriate entities as well as the maze and pellets that are visible to the user.
data :- Contains all data access logic, including interfaces for accessing files such as loading spritesheets and sound effects, the event queue, the message-passing client and server communication layer, the maze store and the entity-component store.
model :- Contains objects used to transfer information between different subsystems, either as parameters, through accessing the data store, through the event system or through network events.
util :- Contains generic helper classes that did not fit neatly into any other package
--
I also did a diagram that shows the network messages that are passed between the various controllers for the server and clients.
The actors in the game world (so player and ghosts) are managed via a simplistic Entity-Component System I wrote. This Entity-Component system is also hijacked to provide the simplistic UI elements, such as the text 'box' used to enter a host and port. Using an ECS for those GUI elements actually worked pretty well, all-in-all.
*digs up descriptions of Components*
---
Ghost :- The ghost entity is tagged with a ghost component. This component has one piece of information, a number that represents which of the 3 ghost sprites represent this ghost.
Player :- The player entity is tagged with the player component. This component contains no useful data, it’s presence is used to tell that the entity is a player.
Actor :- Both player and ghost have the actor component. The actor component contains a position field that stores the x and y coordinates of the entity, and a direction field that stores the velocity of the entity.
Remote :- Entities that are not being controlled by the current client, so all entities on the server and all but one entity on each client, are given the remote component. The remote component also stores a UUID that identifies that user, for when the entitiy is referred to over networking traffic, such as for the handling of MoveRemoteActorOnServer and MoveRemoteActorOnClient messages.
Local :- The entity being controlled by the current client is tagged with the Local component. This component contains no fields, but it’s presence is used to determine that the entity can be controlled by local keyboard input. It is not used by the server as a result.
There are additional components used for the user interface, such as MenuOption, Text and TextBox. These are used for GUI entities, that typically have a one-to-one mapping between the entity and component (a menu option entity only has one component, MenuOption).
MenuOption :- A series of clickable lines of text. The position and size of the text is stored in the component as a field, alongside the actual text for each line and which line is currently active (or -1 for none). This allows for the MenuOptionController and MenuOptionView to manage the menus easily, updating active menus and displaying the menus respectively, and for any controllers that need menus to create one and inspect if any of the menus are active to determine if an option has been selected.
TextBox :- A text box which, when clicked on, will take what characters are typed into the keyboard. There can also be an optional filter to limit the characters (defaults to basic ASCII printable characters), as well as a position and size for the text box. This is used by the server and client connection controllers to allow users to specify hostname and port as needed.
Text :- The simplest of GUI components, text simply has a position, size of the text and a string to display. This text is then rendered in the TextView. This is used by, for example, the server lobby to display what players are connected.[/quote]
---
This is where the player-disconnect bug occurs, as the entity tagged with the player component isn't being properly cleaned up in that scenario.