Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Discussion: Big client refactor #160

Open
Hopson97 opened this issue Feb 19, 2020 · 2 comments
Open

Discussion: Big client refactor #160

Hopson97 opened this issue Feb 19, 2020 · 2 comments
Assignees
Labels
In Progress Internal/ Improvement Reporting code that could be better, or PRs that improve this code

Comments

@Hopson97
Copy link
Owner

Hopson97 commented Feb 19, 2020

What I want to do is refactor a lot of the client code.

Right now basically the entire client game is handled by a single class that can found here:client.h

This is slowly becoming/ is a God Object/ God Class, meaning it is responsible for way too much.


It works fine, and I am low key afraid to change it as right now it is pretty easy to do things, but of course this can rapidly get out of hand.

It has the following responsibilities, all to do with gameplay:

  1. Connect the client to the server
  2. Handles player input
  3. Handles incoming network packets from the server
  4. Handles sending outgoing packets to the server
  5. Loads all the shaders of the game
  6. Handles chunks
  7. Renders players of the world
  8. Renders the world itself

Although this works, I feel it is doing a bit too much and so want to find a way (if possible) to split out the responsibility a bit, as eventually, this would just become a huge multi-thousand line class.

What I propose is some kind of refactor, with the intent to be that the rendering, netcode, world code etc should be split out as their own class.

This would also make it easier to delegate responsibilities in the client lua code.

For example, right now it simply wouldn't be possible to make a button for a main menu that creates a new world*, whereas if this is done correctly it could be pretty easily done while not violating things like SOLID or whatever.


*where create a new world:

  1. Pop main menu gui
  2. Push loading GUI
  3. Starts a local server
  4. Connects the client to the server
  5. (Maybe have a callback to detect the client has successfully connected to the server?)
  6. Pop loading GUI
  7. Push HUD/In-Game GUI
  8. Etc?

The steps listed above seems like a good initial goal for this, which I am currently working on.

Definitely open to ideas on how to achieve more maintainability for the client code, which is what this issue is for :)

(And later, server code)


Other ideas/ Notes (just 1 for now lol):

Opening a chest, how could this work?

  1. Player right clicks a chest
  2. Server receives a "block interaction event"
  3. Server sees it is a chest
  4. Server sends back request to client to open the "chest GUI"
@Hopson97 Hopson97 added In Progress Internal/ Improvement Reporting code that could be better, or PRs that improve this code labels Feb 20, 2020
@Unarelith
Copy link

Unarelith commented Mar 2, 2020

Ok, I see your issue here. I'll try to explain how it works in OpenMiner to give you ideas.

Basically, your Client class is divided among multiple things.

First, the state stack:

  • gk::ApplicationStateStack handles the game states (Title screen, game, pause menu, chat, etc..)
  • gk::ApplicationState, main class for all the game states, it's an abstract class that has:
    • A constructor to init the parent
    • A virtual function onEvent() for OS events (mouse moved, key press, etc..)
    • A pure virtual function update()
    • A virtual function draw()

This allows to split the code for the different states of the game.

Next, you're interested about what is in GameState.

Basically, three main classes:

GameState also handles the shader used for 3D rendering, the camera and the HUD class (which will render the hotbar, fps counter and debug info).

It's also responsible for PlayerBox drawing (basically the other players model).

If you have any questions, just ask. :)


EDIT: Just noticed about the chest opening.

Basically in OpenMiner it works like this:

  • User right-click on a block
  • Client send BlockActivated packet to server
  • Server execute the Lua function associated to this block
  • In the Lua function (for a workbench or a furnace), a GUI is created and sent to the client
  • The client receives the GUI info and display it

@Hopson97 Hopson97 self-assigned this Mar 19, 2020
@Hopson97 Hopson97 added this to To do in Open Builder Mar 23, 2020
@Hopson97
Copy link
Owner Author

Hopson97 commented Apr 3, 2020

Hey @Unarelith

Apologies I did not reply sooner, I been looking into many ways I can do this and I realise now that you are absolutely right!

Organizing game code into a game state system is something I typically did before, but throwing Lua into the mix really confused me here, and instead I went with this weird route that game states don't exist, and the game is always there but inactive. This was pretty horrible way to do things.

Looking back at your comment here now, I now understand that's exactly what I want,, as it enables the organisation of different stages of the game, while also being more flexible with what can be done.

For example, before if I wanted to have an animated GUI (eg, Minecraft the main menu sort of rotates around a world), then I would have to awkwardly fit it in between the game logic code, which is bad for obvious reasons.

The reasons I didn't do it before is because I was way too inclined on making as much as possible done from the Lua, which led to a code spagetti soup. Instead, I should be sticking with what I know, and delegate only very specific things to the Lua code, as after all this is a game and not a game engine.

What I am thinking is having the GUIs still defined in the Lua, but don't allow to have an ability to change the game state (or whatever I was doing before). Instead, I could have a GUI defined as a root menu, and make the game switch to that from the "C++ side" when switching to a game state etc etc

But yeah thanks so much for making me realise good ways to do things! 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
In Progress Internal/ Improvement Reporting code that could be better, or PRs that improve this code
Projects
Open Builder
  
To do
Development

No branches or pull requests

2 participants