Add singleplayer support to the protocol
In order to support singleplayer mode (which is a big step towards getting this integrated into the client), the protocol API needs to be redesigned in such a way that would allow a local client to share the memory representing the data structures used in the protocol, removing encoding/decoding overhead.
I have occasionally been hacking at this in the past few months, but so far haven't been able to come up with a good API design.
The question is whether the overhead is acceptable or not. If gameplay is fast enough for multi-player, then it might be an idea to just use a server with a single player in single-player mode.
I agree with @bvssvni Most computers have at least two cores these day.
- The first thread would host the client
- The other would host the server.
If thread 1 can communicate encode with an remote server, it can communicate with a local one.
If the processor can handle thread 1, it can handle thread two. Running a minecraft server alone with a single remote client is less resource intensive than running a client connected to a remote server
The only use case for this optimization would be:
- A processor with 2 or more cores
- That fast enough it can run the official server with one client
- But not fast enough it can handle a client connected to a remote server
- has less than 250 mb of free ram (tecnically, you could just optimize this out by telling the server not to cache chunks if its a local game, and just having the client do it)
So hypothetically, this person would only be able to connect locally, but not be capable enough to connect to server for this optimization to be applicable.
Sure it's useless encoding/decoding, but
- It simplifies the code base.
- It would be beneficial to make it as close to original minecraft as possible, so the hematite client should be designed to be compatible with the official server API
- And the server would be compatible with the official client API
- Focuses resources better
This will spur adoption, and allow both projects to be developed independently of each other. They will also end up compatible with each other.
Honestly seems like a case of premature optimization to me.
I say just stick with the official Protocol, sure it sucks, but its still official
Any reason we are targeting 1.8.3 instead of 1.8.8?
1.8.3 was the latest release when we started working on stuff. We should be targeting 1.8.8 now (although there haven't been any significant changes to the protocol).
Note that I am not proposing any modifications to how Hematite implements the protocol itself, the Hematite client would still communicate normally with all servers, including Hematite servers. The only change would be for singleplayer. If done correctly, this could improve both tick speed and memory usage in singleplayer mode, without any added code complexity. This is very similar to how Notchian implements singleplayer, except without the risks of data races because of Rust's guarantees.
@fenhl Do you mind editing the issue with a ToDo list of things we want to support?
I don't have any detailed plans on how to implement this. Suggestions welcome.
Let's see... Our shopping list, order somewhat relevant, should have:
- Login (online-mode=false). Done in #40! :tada:
- Implement concept of world. Dimensions ticking in sync! Example: http://is.gd/oGH1Yr (this is example code, a real version wouldn't clone every world on every tick ofc)
-
Keep track of entity positions. Just the player's position with some simple checks (moving too fast, send Disconnect packet) should be enough to get going. Example:
HashMap<String, Position>which will come handy when we start adding more entities. - A working chunk loader. Once we know where the player is we can load and unload his/her surroundings.
- Chat. Basically just echoing back whatever the player writes. This would allow people to start working on commands.
-
Time handling. Having
/timeworking would be great, also time being updated accordingly every now and then just to keep players in sync. - Basic inventory handling. Moving items around in their inventory, including bottom bar.
- Digging mechanics. This involves actually breaking blocks and spawning entities so the player can pick them up. Quite a milestone.
- Dropping items. We already had the inventory working and know how to spawn entities, should be easy.
- Illumination. If we start breaking blocks, we should update lighting accordingly?
This seems like a good start unless I'm missing something.
EDIT: Go to #109 if you want to talk about any of these, this issue is NOT about single player functionality.
We could use a plan for world ownership.
We could possibly spawn a thread for each core deviding it up between threads.
As in #100, but this might be a simpler way to implement it.
The master would manage a Hash-map/index of chunks, which corresponds to transmitters.
All player threads would have access to the hash-map through a read lock. For unloaded chunks, the players would send the request to the master thread, which could decide which thread to delegate the new chunk to.
If an action in one chunk affected another, one chunk would message the other.
For example, if Toqueteos causes a tnt explosion on edge of chunk A,
Toqueteos's thread would look up in the hashmap chunk A's channel, notify chunk A's thread, and chunk A thread could notify any surrounding chunks if needed.
Updates could be managed by the chunk thread notifying players that have it loaded.
This would make the requests a-sync, but It could be added on top of another library if we wanted map generation/computation to be also.
@toqueteos those are all out of scope for this issue. I'm simply trying to add an API to the protocol which uses shared memory instead of TCP.
Woops, seems like I totally missunderstood this issue. I've opened #109 so we can track functionality and future contributors can help on our next steps.