Well...Recap - Foodopoly

This starts with my decision to create a Monopoly-type game, I thought this would showcase my C# skills, and help me gain a wide variety experience and knowledge of many different parts of the .NET framework. Well, as much as this was a coding project, I needed to decide on a theme and some other details. Here is where I had the brilliant idea of ‘Foodopoly’, a food themed version of Monopoly, because... who doesn’t like food? Next was to decide the names of the ‘foods’(properties), after this was done, I decided to store this as an XML file with the various properties that are associated with this ‘food’, i.e. its price, set and such. I took the decision to not create a database here, as this was a small immutable dataset; I want to later make this customisable for the user. As with always writing a program like this, I started by writing out some pseudo-code before getting into the nitty gritty of the code. I started with the server and soon realised I needed to create a ‘Foodopoly’ class library to store all classes and such to do with the game. Next I decided the structure of the classes, deciding the class hierarchy/family, where to put methods etc. while respecting the tenants of OOP and the SOLID principles. I decided to have both a Web API and SignalR hub on my server app, this allowed me to split up responsibilities and handle different sections of the app in the most appropriate way. Both of these both use https connections as is essential at this point. The Web API was the first port of call. The client would first send a request to the Web API to create/join a game, this would allow the WAPI to validate and create/modify the appropriate objects on the server side. I tried to make this API as RESTful as possible without overcomplicating it too much. The use of the WAPI in this way allows for growth of the app later on, i.e. I could have a lobby board, a leaderboard and it could even be used for a single sign on service which I wish to implement later using JWT bearer tokens. Once the WAPI gives the ok, the client then attempts a SignalR hub connection, this, ofcourse, needs some validation itself if someone tries to circumvent my client app and uses an alternative method to directly connect. When someone successfully connects to the SignalR hub, they are sent a copy of the game object. A copy of the game object is also sent at the start of each new turn to make sure there are no discrepancies. Moreover, if there are any errors, the client is told to disconnect and they are sent back with an error to reconnect, hence it will allow a new game object to be sent and is basically a client reset. The SignalR custom service keeps track of who's connected and these game ‘groups’ as SignalR doesn’t keep track of this inherently. To do a lot of this, I had to override some of the basic SignalR hub methods to add custom logic. For validation, I used custom authentication and authorisation policies implemented using the inbuilt structure in .NET. This could be further used to create and authenticate the JWT bearer token used in Single Sign On I mentioned earlier. To structure this app and allow reusability I created multiple services which were multilayered in a way to maximise reusability and best handle validation. Some of these services were transient and others singleton based on their needs. To prevent any complications/cheating, I used an authoritative server structure, hence the server will take charge of the actual game random logic and you can only request the server to do something which it will validate and then execute if it’s an appropriate action to take. The action will then be sent to all players in the game. To prevent any actions being executed before others, there is a number sent out with each method dictating the method number count for that turn, the validation of this still needs to be implemented. With an authoritative server, there are few disadvantages I had to consider, the first being the time taken for the server to receive and respond with the request. I will use animation to cover this hopefully small time period; also with this being a turn based I believe this was the best approach, there would be no ‘dead reckoning’. On the client side, I am building a .NET MAUI application, this allows me to build a cross platform application. However, a small downside of this is that, as .NET MAUI is relatively new, there are still some small bugs that I need to work around. This application has XAML based pages and uses a MVVM structure, this seemed most appropriate to separate content that was to be shown and how content is shown. Right now the client app only requires a temporary username and password to allow reconnection. Eventually, I would like to implement a full user system that allows the user to have their wins, game history and friends tracked; I have made it easy to add a database to this app because of this. Especially with the client app but also with the server app, I have to make use of asynchronous programming to make sure I’m not blocking any threads and making an app unresponsive. I have also created a gamebuilder class to build these game objects asynchronously and to leave possibility for customisation later. As you can imagine, I ran into a wide variety of bugs and problems while trying to program this. A significant problem I faced was that SignalR sends an object as JSON but the client was unable to rebuild it on the client side. This was due to the fact that some of the objects inside the game object were cast as their parent abstract class, I found a solution by rewriting the structure of my classes a tad, another was to solve this was to customise the JSON deserialization which may need to be considered in the future. Another tedious problem I ran into was that, during the debugging process, the https connection would not work, this was due to the fact the system saw the emulator I was using as an external system and the self signed .NET development certificate was hence not adequate. To not bore you too much, I have not included every little detail of my programming journey for this app, but I must emphasise that this is only a small part of the knowledge and experience I’ve gained while building this app. For example, I have not mentioned how much I have slimlined my code with LINQ queries, or how much easier my debugging became, when I enabled more informative logging. I have further tried a unit test driven approach to some of this project. I also want to state that this experience has made it more comfortable for me to seek help when needed, i.e. looking and asking online, or even asking ChatGPT, although I have found I need to be careful here as it often gives me outdated information on nicher modules.

Welcome

Check out these links.