Tweaking Multiplayer

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Tried this out with two clients locally and while it may not be done yet it still works beautifully - awesome work :)

Posted to our social outlets and wanted to put a comment in here I could reference too. For those trying:
  • Download the multiplayer build from Jenkins
  • Run the game, pick to host, create/load world normally
  • Run game from other client(s), join menu, enter server ip of other player (uses TCP port 25777 if you need to let in traffic through a router/firewall)
  • Note that most the modules are missing and some stuff doesn't work (see post above). Probably too early to give detailed feedback (as in, report bugs) / ask for stuff to help with, up to Immortius
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
Still slogging away at this, although lots of RL taking up my time recently - also my computer broke, so I need to chase that up too.

Death and respawning, and support for dropping items (thanks sdab ) are all in the current branch. As opposed to the previous implementation of death which merely put a gui screen up until you hit respawn upon which it teleported you back to the start, the new implementation actually destroys the player's character entity - this can later be changed to ragdolling that player's corpse or other such effects. It also means the player can exist without a character/body, which gives an opportunity for character selection when joining a game or similar.

There is a new version of LWJGL out - this one has their new code for OSX, so I've upgraded the multiplayer branch to use it and migrated to Java 7.

I am currently working on client identity handling, so that when a player rejoins a server the server will be able to know who they are load up their previous state. Some preliminary work to allow testing this was changing the handling of Terasology's save path - on the multiplayer branch it now saves to a home location by default (dependent on OS - for Win 7/8 it saves to the Documents/Saved Games for instance, or at least the equivalent for different languages/setups). A commandline option allows this the be overridden, allowing running Terasology with different home locations and thus configurations.

Implementing client identity, I wanted to meet the following criteria, or get as close to it as possible:
  • It needs to work without a master server. Partially to allow LAN play while disconnected from the internet, and partially so we don't have to host a central authentication server.
  • Avoids requiring password entry. Players shouldn't need to memorize a password for each server, and I would worry they'ld reuse their credentials and expose themselves to having them stolen by rogue servers.
  • Security is important. The solution should be resistant to rogue servers, rogue clients, man-in-the-middle attacks and so forth.
While it isn't complete yet, the solution I'm working towards acts as follows:
  • On first run, Terasology generates a server public/private certificate pair, used when it hosts a game. This is stored in the config.
  • When joining a server, the client receives the server's public certificate.
  • If the client has never been to the server before, it requests a certificate. The server will produce a public/private certificate pair signed by the server's certificate for the client and send it back to the player encrypted. This is the players identity on that server.
  • If a client has been to the server before, it sends its public certificate to the server, as well as an encrypted, signed data package as proof of identity (as it will show the client has the private certificate).
The workings of the certificate exchange and authentication of identity are based on TLS/SSL, as used to authenticate web sites everywhere, although some details are abridged (the certificates are not full X509 certificates, there is no negotiation of algorithms).

There are some weakness to this approach:
  • At least for the first version, all the certificates are sitting unencrypted in a config file. This means that any rogue code running on the user's machine could easily lift them. Mod sandboxing and security will help with this - mods shouldn't be able to access private keys through code, or read and write files arbitrarily, or create network connections. Having the certificate encrypted using a single, local password would help.
  • Because users have separate identities per server, cross-server bans aren't possible. Of course, since Terasology is free even with shared accounts players could just make new ones anyway, so bans need to be by IP rather than identity. Theoretically a group of related servers could share the same certificate, giving the player shared identity for those servers - but anyone running those servers could obtain any player's credentials for the whole group, so care would need to be taken.
One benefit of this approach is that it could be extended to work with a central identity server in the future (the identity server would provide certificates signed by it, and servers would accept certificates signed by it, rather than just by themself). This would have the benefit that even the server admins wouldn't have the necessary information to obtain a player's credentials.
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Very cool sounding stuff, Immortius - the certificate approach sounds great :)

Do you mean we can offer official Java 7 support now (previously a problem due to the Mac LWJGL issue) or Java 7 as a minimum requirement?
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Speaking of Java 7 - I just noticed the Jenkins multiplayer build had been failing with a Java version error (maybe provoked by setting build.gradle to expect Java compatibility 1.7 ?):

Execution failed for task ':compileJava'.
> invalid source release: 1.7

I configured a Java 7 and hooked that one job up with it and it worked again.

Everything else I set to Java 6 for now. And everything is also using GitHub push hooks now instead of Git polling, huzzah.

Also, I second having begla or somebody test on Mac, but I know he's swamped with RL work right now, boo.
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
With authentication working, I've move on to player persistence. Now when a player disconnects, their character entity is stored in a PlayerEntityStore, which is saved as a file identified by their Id. Upon reconnect this file is loaded and the entity restored. This means stuff like their position and health now carry across sessions. What isn't persisted yet is inventory - the next step will be extending the entity system with a concept of ownership, with entities able to own others, resulting in those entities being persist and restored together. This system partially exists already in multiplayer - but I think an annotation driven approach may assist. Perhaps something like:

Code:
public class InventoryComponent implements Component {
 
    @Owns
    public List<EntityRef> itemSlots = Lists.newArrayList();
 
    @Owns
    public EntityRef specialItem = EntityRef.NULL;
 
}
With the concept of storing and restoring entities at runtime the lifecycle for entities/components needs to be refined a bit - there is a different between destroying an entity/removing a component and storing one. For instance, when an inventory component is stored the items should also be stored, but when it is destroyed the items should be destroyed.

Later I think this entity store concept can be extended to link with chunk storing and restoring - when a chunk is stored its entities (as determined by their location and ownership) can be similarly stored away, and when a chunk loaded and ready its entities can be restored too.

In addition to this, I'm spending a little bit of time experimenting with the asset system. This isn't directly related to multiplayer, but will be needed for a dedicated server. The asset system we have at present has some good features, but there are some features missing that are desirable:
  • The ability to "reload" an asset. Mostly useful to aid development, where you might want to do some work on a texture or mesh and then reload it in game without restarting. Also allows procedural assets that can be regenerated at runtime.
  • Fixing asset disposal. The biggest issue here is probably the ShaderParam system, and also ensuring assets can be put in the correct state before disposal (so stopping sounds playing and so forth).
  • Adding support for mods defining asset types - might be useful for things like the blueprints.
  • Improve handling of assets composed of multiple files
  • Add support for files containing multiple assets, such as IconAtlases.
  • Add support for Asset Generators that provide procedural assets on request (when looked up by uri)
  • Add support for multiple implementations of an asset depending on what system is consuming it. We have a small example at the moment with Sounds, with them being OpenAL sounds or NullSounds depending on whether the OpenALManager or NullAudioManager is in use. This is a bit of a hack though, and needs to be made more fundamental - for a dedicated server Audio and Graphics assets both need to be some flavor of null implementation.
The big change I see needing to be made to support these features is an agnostic intermediate form for assets - "AssetData" - that sits between the current asset loaders and the assets themselves. AssetLoaders (and generators) will produce asset data by decoding and translating files, or creating it wholesale. This data is then used to create the actual assets. Reloading an asset will just be a matter of creating a new AssetData and passing it to an existing asset. Different asset factories can be plugged in to generate different asset implementations for OpenAL vs Null. And so forth.
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
The @Owns annotation has now been introduced, with the following features:
  • Can be applied to a EntityRef, List<EntityRef> or Set<EntityRef> fields in a component.
  • Owned entities are stored when the owner is stored. e.g. A player's inventory of items is stored with the player.
  • Owned entities are also marked as network-owned, for the purpose of replication that is filtered by such things. e.g. An item entity may only be replicated to the player with the item.
  • Owned entities are destroyed when the owning component is removed or owning entity destroyed. This perhaps will need some tweaking, but it should help avoiding loose entities cluttering up the entity system. e.g. When an entity with an inventory is destroyed, all the contained items are destroyed with it.
So now a player's inventory is stored and restored when they disconnect and reconnect. :)
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
This weekend spent some time tracking down bugs in multiplayer - both with the recent functionality and some longer term issues as well. I regret not writing more unit tests, though I've put some more in now.

I've also started setting up console command support for multiplayer. Along the way I am looking to improve the command and console API:
  • There is no longer a CommandProvider interface which is to be implemented by classes that provide commands. Instead commands can be added in any ComponentSystem (and thus take advantage of injection).
  • Command methods can now return a String (or any other object) - this returned value will be written directly to console.
  • Command methods can now optionally have a final EntityRef parameter - this will be provided with the Client entity that submitted the command.
  • Commands can now be marked as runOnServer (in the Command annotation). Such commands are automatically propagated to the server, run, and the resultant message propagated back (if any)
  • Messages now have a MessageType - this is used to categorise them for future filtering, and also to color them.
  • The MessageSystem has now been merged into the Console class, with its implementation changed to make use of the CircularBuffer data structure (basically a fixed size list with new entries overriding old ones once the max size has been reached).
Once this is all working I will do a pass over all of the commands, updating them to work in multiplayer and moving them into appropriate component systems.
 

UberWaffe

Member
Contributor
Design
Impressive progress. Keep it up!:thumbsup:
 

MPratt

New Member
Contributor
Spent some time today trying to get this to compile and hook into the remote branch. I will try upgrading LWJGL and java and separate the files completely from the develop branch tomorrow.
 

mkalb

Active Member
Contributor
Logistics
Do you mean we can offer official Java 7 support now (previously a problem due to the Mac LWJGL issue) or Java 7 as a minimum requirement?
Can we now move to Java 7?
If so, I would adjust the launcher.
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Can we now move to Java 7?
If so, I would adjust the launcher.
We can move toward it, yeah. Launcher isn't in widespread use so I'd say go for it whenever as long as the other launcher devs have no concerns.
 

filth

New Member
Contributor
Hi,

im new here, just discovered this forum and very interested!
Is there anything I can support you with in this multiplayer thing?

Would be great, if we can work together here...

Best
Alex
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Hi Alex! Would feel weird greeting you by your username, heh :D

If you could please go ahead and introduce yourself and share some notes on your technical experiences then we can probably get a better idea where you could help the most :)

Multiplayer branch already works and Immortius is knee-deep in code trying to pull in all the changes made in the develop branch in the meantime, that's probably not the easiest to bring additional help in for. But there are lots of other topics and the great convergence will finish sooner or later and open this field up more for collaboration :geek:
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Posted!

I'll leave Immortius to respond more specific to multiplayer, but as said I suspect it may be a while before easily delegated tasks spawn for that piece :)
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
The core multiplayer is essentially complete - all the remains is some cleanup/refactoring (which I will do after "merging" with the develop branch), rigorous testing, resultant bug fixing and optimisation. So other than the testing there's nothing really suitable for a newcomer to jump into there. Going forward there will be work ensuring new functionality works in net games, but that won't be a thing until the merge is complete and people start porting their modules over.

I guess there is still work towards dedicated server support, but that is less about networking and more about fixing our gui system and rendering architecture.

If you are interested in other tasks, then I might suggest adding support for IQM skeletal meshes, or Icon asset support. These are both reasonably self contained tasks, and I can provide more information if they are of interest. Or yeah, any of the tasks Cervator suggested.
 

filth

New Member
Contributor
Hi,

IQM would be fine for jumping in. It would be great if you could provide me some more information to get me started.
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
I would recommend working from the multiplayer branch, as the asset system has undergone some work there that will simplify things.

Essentially you would be looking to create a pair of AssetLoaders, one to load an IQM skeleton file to SkeletalMeshData, the other to load an IQM animation file to MeshAnimationData. These loaders would then need to be hooked into loading IQM files from the correct asset locations (a trivial matter) and that is pretty much that.

It might turn out that there are extra features that IQM supports that our existing MD5 support (and thus the SkeletalMesh and Animation system) doesn't cover, in which case those may need to be extended and the MD5 loaders changed to properly work with those features. That would be a second phase after the core behavior is done though.
 

filth

New Member
Contributor
ok sounds good. So basically my IQMAssetLoaders would have to return a SkeletalMeshDataand MeshAnimationData classes?
 
Top