PistonDevelopers / hematite

A simple Minecraft written in Rust with the Piston game engine
http://hematite.piston.rs/
MIT License
1.86k stars 105 forks source link

Add application structure for Hematite #203

Open bvssvni opened 9 years ago

bvssvni commented 9 years ago

I think the main method is too large, and we should try to refactor it a bit.

One way to do that is to add an application structure which we can pass around.

RichardlL commented 8 years ago

I've started a Minecraft Server in rust https://github.com/RichardlL/Tunnul

just for fun a few days ago. I would have contributed to the Hematite's server, but I haven't made any big projects before, and I wanted to do it alone so I could learn, not be afraid to screw up, etc. Not a "serious" project. Its ugly right now, and not a good example of idiomatic code, but I'm mostly using github to backup and keep me on track. It does "work" though, you can connect, but that's it. Feel free to look at it.

But anyway back on track...

The way I'm doing it is similar to actor based. I'm not completely sure about performance benefits, (It will probably run faster with on Unix, but I believe threads are pretty expensive in windows, don't quote me) but it makes it easier to follow and design. Hematite could do the same

Hematite's client actors could be:

(This would allow for the removal of having to load minecraft save files, as hematite shouldn't be doing this anyway.)

Then hematite's server could handle all of the logic

rather than the traditional "game loop"

This would also remove unnecessary bottlenecks.

Map loading would be independent of rendering and input, so walking around would be lag-less, even connected to a server with high ping/overloaded . If map loading was taking a while, FPS would still be high, it would just take a little longer for something to appear, rather than dropping frames.

Vise-Versa would be correct to, such as case of TNT explosion or a tons of entities.

Rendering is very well developed, and the only modification would be to allow some way of sharing the map it renders, such as a mutex.

This would also allow chunks to be primed far in advance, but the render actor could decide whether to display them or not depending on fps

toqueteos commented 8 years ago

@RichardlL I like your channel-based approach to handle Keep Alives! You should change your README to use - [x] Done / - [ ] Not done syntax for the TODO list.

RichardlL commented 8 years ago

Thanks you, @toqueteos! Great to hear feedback, I was kinda getting discouraged since I was the only unique viewer of my repo (not that I deserve any, "good" ideas and unfinished github repos are a dime a dozen).

I haven't implemented the actors besides the keep alive, as I haven't got that far, I'm only a week in, and like I said, its my first big project :)

What I was "planning" on was completely removing the game loop to improve performance. (hypothetically, I didn't even expect I'd get this far)

To do this,everything needs to be designed to be blocked by I/O to responding as a trigger, rather than having a loop and checking if something has been changed. This is why the "actor" based multi-threading system makes sense.

In the regular server, Time is implemented by updating a random block in the chunk every tick, and each block takes a certain number of updates to transform. (Some don't do anything, like cobblestone, some do, like dirt -> grass, or saplings, etc.)

What I was planning on doing instead was when a "tick" or random time is needed, such as a player planting a sapling (which would be handled by the map actor), the map actor would send a request to the "update action" actor.

The "update action" actor would then sleep a random amount of time, such as 4 minutes, and then message the map actor to update that the sapling is now a tree. (which has been sleeping due to being blocked)

So basically everything will be blocked by channels or TCP until they are needed, and nothing is actively looping or being checked. (except for keep alive, which need to be sent out every minimum every 20 seconds)

This generates the same result, but completely removes the game tick system, which takes sometimes up to 90% of cpu on highly modded servers.

My planned actors:

This would be highly concurrent, and because of its design, it would remove many bottlenecks. If the server is slow, you wont lag, things will just grow slower, chunks generated slower, etc. Multiple actors of each type can also be in place to take advantage of Multi-core set-ups.

I also have plans for the map generation algorithm, but I think I've already went to far for this issue, haha.

I'm not experienced at all with rendering, but I believe that I would believe that the hematite client could work the same way (maybe the rendering would have to be a loop), and rust makes it easy.

toqueteos commented 8 years ago

@RichardlL I was actually playing with worldgen today, porting a thingy that @HeroesGrave did some time ago but unfortunately didn't finally make it into hematite :sob: making it work with the actors approach from your Tunnul's keep-alive would be pretty cool.

If I didn't missunderstand you, you are proposing making the client a dummy one that just sends inputs and the server does all the heavy lifting. It's been quite some time far away from MC world so I don't really know if that would be 100% possible but even if it isn't, doing most the work that way would be a nice thing to have.

That's why I opened https://github.com/PistonDevelopers/hematite_server/issues/100, feel free to join. I've spent part of today reading docs about mioco, tomorrow I'll try to do part of your proposal with it and see how painful it is to manage (apparently that would require us to use nightlies :-1:, which is something I would prefer not to do but...). There's also rotor, also mio based, which seems stable-ready!

RichardlL commented 8 years ago

Will do!

That's how the vanilla client works, I think since 1.4.

When you start a new world, it hosts a server, and then your client connects to it.

I was really confused, because I saw about how everything should be close to the vanilla as possible.

Doing server/client would also make it easier to develop, as you can test hematite on regular minecraft servers, and test the the server with official clients, to insure compatibility.

It also simplifies things a lot (only have to update gamelogic once, etc)

toqueteos commented 8 years ago

Development has happened in bursts and some things from the IRC weren't written here in issues so there might be lacking info about parts of the process, that's right. Anyway, the dummy client is actually on the roadmap and it's being "tracked" in https://github.com/PistonDevelopers/hematite_server/issues/97

mattico commented 8 years ago

I've been working on this a bit: https://github.com/mattico/hematite/tree/add-app-structure

Still needs some refinement.