Architecture problem for a first player game

Hello everyone and thanks for the help in advance.

I am working on a clone of Minecraft in Rust, and I am confronted with an architecture problem.

I can gladly provide an playground to illustrate it, but a picture is probably the easiest. The diagram below just shows the references between the classes that I would like to have

I know that this is impossible in Rust, but I am not sure of what would be the idiomatic way to do this. Nothing simple comes to my mind.

  • The WorldRenderer is the OpenGL main loop. It captures keyboard events and therefore must be able to modify both the camera (position, orientation) and the world (add and delete cubes).
  • The Camera struct must be able to access the model, for instance to adapt the speed & acceleration depending on the position of some cubes (collision detection, free-fall). So it needs to have an immutable access to the world. Also, it can't be created at each render iteration because it has some internal state (eg the speed) that outlives the render iteration.
  • The World just contains a description of the world...

So, I know that the problem comes from the reference from the camera to the world, but I really don't think of a way to get ride of this one. I tried to delete the reference &World inside Camera and instead to use a callback (of type is_position_free: Box<dyn Fn([f32;3])->bool + 'a> and constructed as Camera::new(|pos| world.is_position_free(pos))) but, as I expected, it still didn't work for the same problem.

Of course I know that I can inline the code of Camera inside WorldRenderer, but it would really become nasty, and I would like a solution that respects good coding practice.

Let me know if I can provide more info (I actually have the code on my public github if it helps GitHub - arthurBricq/crafty: (the beggining of a) Minecraft clone in pure Rust with OpenGL)

Thanks in advance :pray:

You misunderstand the way references should be used. In most cases, references should not be taken as permanent, but temporary — lasting only as long as the operation that needs them. The &mut reference to the world should exist only while the world being updated, and the & reference to the world should exist only while the world is being drawn or the camera is being updated. Thus, they do not overlap in time, and thus do not create a borrow conflict.

In general, put references in your function parameters, not your structs.

Your main loop should own the world and camera, not hold references to them.

Pass a reference to the world model when you call the function that updates the camera.

6 Likes

Thanks a lot. I can't believe that I did not think about this.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.