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

Add singleplayer support to the protocol #97

Open
fenhl opened this issue Dec 1, 2015 · 9 comments
Open

Add singleplayer support to the protocol #97

fenhl opened this issue Dec 1, 2015 · 9 comments

Comments

@fenhl
Copy link
Member

fenhl commented Dec 1, 2015

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.

@fenhl fenhl added this to the MC 1.8.3 Protocol milestone Dec 1, 2015
@fenhl fenhl added feature and removed enhancement labels Dec 1, 2015
@bvssvni
Copy link
Member

bvssvni commented Dec 1, 2015

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.

@RichardlL
Copy link

I agree with @bvssvni
Most computers have at least two cores these day.

  1. The first thread would host the client
  2. 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?

@fenhl
Copy link
Member Author

fenhl commented Dec 7, 2015

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.

@toqueteos
Copy link
Contributor

@fenhl Do you mind editing the issue with a ToDo list of things we want to support?

@fenhl
Copy link
Member Author

fenhl commented Dec 19, 2015

I don't have any detailed plans on how to implement this. Suggestions welcome.

@toqueteos
Copy link
Contributor

Let's see... Our shopping list, order somewhat relevant, should have:

  1. Login (online-mode=false). Done in Basic login support (online-mode=false) #40! 🎉
  2. 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)
  3. 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.
  4. A working chunk loader. Once we know where the player is we can load and unload his/her surroundings.
  5. Chat. Basically just echoing back whatever the player writes. This would allow people to start working on commands.
  6. Time handling. Having /time working would be great, also time being updated accordingly every now and then just to keep players in sync.
  7. Basic inventory handling. Moving items around in their inventory, including bottom bar.
  8. Digging mechanics. This involves actually breaking blocks and spawning entities so the player can pick them up. Quite a milestone.
  9. Dropping items. We already had the inventory working and know how to spawn entities, should be easy.
  10. 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.

@RichardlL
Copy link

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.

@fenhl
Copy link
Member Author

fenhl commented Dec 19, 2015

@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.

@toqueteos
Copy link
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants