Online Multiplayer in Monkey X?

Monkey Forums/Monkey Beginners/Online Multiplayer in Monkey X?

potato(Posted 2016) [#1]
Hi, I'm new to Monkey X and I've found it quite fun so far. I used to use Unity, and I'm appreciating the additional freedom that Monkey X offers so I'm thinking of working with it. But, the project I'm working on is an online multiplayer game, and I'm not sure if Monkey X could do that. I didn't really like using Unity very much, but Unity has multiplayer and networking in the form of UNet. I never got around to using UNet (and I have no experience with networking in general, either, sorry if I'm asking a stupid question because of that), but there are a few Unity games with online multiplayer so I'm assuming Unity can do multiplayer fairly well. I found a 'simple networking library' called mnet in the module registry, but I couldn't find any additional info about it and there don't seem to be any games made with Monkey X that have online play so I'm not sure about it. So, would it be possible to make a multiplayer game with Monkey X? If so, how would I go about doing it?


ImmutableOctet(SKNG)(Posted 2016) [#2]
Woah, hang on, don't use MNet! For the love of all that is holy, don't use it. We've moved passed the dark ages.

Well, networking-wise, anyway. Maybe not for all-in-one game networking frameworks, though. Read this post I made about a month ago. That covers the history of Monkey's networking modules (For the most part; MNet was its own abandoned thing), and why you shouldn't use anything less than what we've got.

That post is pretty clear about choices, but here's your current list:
* 'regal.networking': This is a part of the "Regal modules" project (This is my module, click for an installation guide). Documentation can be found here, or locally by rebuilding your docs. (TCP and reliable UDP; feature list)

* PushButton: A module with home grown implementations of TCP sockets and a number of useful features for game networking. The downside is, I don't think it has cohesive documentation. (TCP only, but supports WebSockets and other platforms; feature list)

* 'brl.socket': This module is the official "socket" technology for Monkey. It supports a much lower-level data/protocol oriented API, and should only be used to build a framework or other technology on top of it. Sure, you could theoretically use it directly, but you're making things really hard on yourself. If you're not making a small test program, or intend to do everything yourself, stay away from this. This module is used by 'regal.networking', but not 'PushButton' (Didn't exist when it was created).

As a side note: 'regal.networking' will probably get proper WebSocket / HTML5 support at some point, I just haven't had the time.

Anyway, I hope this helps you make the right choice for your project. If you're just starting to learn networking concepts both with and without games, a higher level solution like 'PushButton', or 'regal.networking' would be ideal. PushButton's codebase is a bit archaic, but it's at least interesting. My 'regal.networking' module follows standard API practices as closely as possible when it comes to 'brl.socket', so it's a pretty good reference right there. There's also examples with your Monkey installation, if you're interested.

I guess the moral of the story is: We don't have a game networking framework, but we have good general-purpose networking frameworks. My aforementioned forum post discusses the history of all of this. Also take note that Monkey 2 is showing up slowly but surely, so wrapping an existing networking framework may be possible. That's a good while down the road, though. Monkey 2 isn't exactly production ready, yet.


potato(Posted 2016) [#3]
Thanks for the help. I'll try using regal.networking, since it seems like the best option, but I'll probably find it difficult because I have no experience with networking. Are you familiar with any tutorials or guides that I could use to learn the basics?


ImmutableOctet(SKNG)(Posted 2016) [#4]
I'm sorry to say that I can't recommend any guides, as I started out by using higher level libraries, then worked my way down. To be specific, I wrapped one higher level library with another (Rottnet -> Blitz Play). On top of that being a pretty long while ago, I simply didn't start with the intent of a formal education in networking.

Although, you should keep in mind that 'regal.networking' is an abstract networking module. Its job is to make the idea of network transport as irrelevant as possible. So, instead of the details of things like address translation/resolution, byte order, packet encoding/formatting, or storage semantics, you simply write messages. They could be strings for all it cares. Just plug and play. For some great examples of usage in 'regal.networking', view the "Examples" provided with it. More specifically, I recommend the "Cursor_Example" file. That contains a basic networking model akin to what you would see in a game.

That being said, I could probably point you to a couple of talks regarding game networking concepts. The lower level stuff is a bit of a double edged sword, as you're starting out in Monkey. Monkey's networking is relatively new, and hasn't been talked about in length. There's the docs for 'brl.socket' if you're interested in how things plug together, but that doesn't explain the lower level ideas and technologies.

I suppose to start you off, I'll give you a run down for the lower level technologies. Please keep in mind that 'regal.networking' is abstracted from these protocols:

First, I'd like to be clear about terminology: A "packet", in lower level terms, is a message containing the required data needed to be routed across the internet to another router/modem. This is compared to the programmer's perspective of a packet (As seen in 'regal.networking'), which is simply data you wrote yourself. Writing a packet at a lower level entails writing the user-level content (Whatever you want), and later, sending it to an IP address. In the case of 'regal.networking', this is handled for you; just write whatever you want, and receive it on the other end.

An IP (Internet protocol) address is used to individually identify someone's local network, as perceived from the internet. In normal households, this is a modem. Today, we have IPV4 and IPV6, both of which require different code to work. Because of this, some of the C APIs, responsible for giving us access to these lower level features, are abstract themselves. This is once again something abstracted from you, the end user. My 'regal.networking' module depends on 'brl.socket', and its support for IPV4/IPV6. I'm not going to go into details on the difference, I'll just say that IPV4 has fewer addresses, and will eventually be abandoned. Though, IPV4 is what 90% of people are still using (Primarily).

Along with an IP address, packets hold other information for their protocol (I'll get to those in a minute), as well as a port number. The exact formatting of this extra data is dependent on the protocol, and normally handled by the operating system.

Just to get this out of the way now, when someone refers to a port, they're talking about a metaphorical line of communication. Ports on TCP and UDP (Potentially based on the IP version) are between 0 and 65535 (16-bit unsigned integer), where zero is usually reserved for system-generated port numbers. Ports basically allow you to segregate channels of information (Packets). A server hosted on port 5029 can only be reached at that port, so clients would need to connect using 5029. Local ports are a bit of a different issue, so I'm not going to talk about them. They aren't relevant to 'regal.networking', anyway.

You see, when sending a packet, you give your operating system the memory you allocated for your message. Next, a system-local service is utilized to take your data, as well as your other inputs (IP address, port, etc), and encode the final packet that it transmits. This service (Or services) is commonly known as a network stack, and it exists above a driver layer that is used to transmit data using a device in your system. This could be a wireless adapter, Ethernet (Wired) controller, or something to that effect. From there, the packet's sent to your router, and queued up, until eventually sent through your modem.

Your modem then transmits the information over lines laid by your ISP (Internet Service Provider), which goes off into as many networks as needed in the infrastructure. Excluding artificial limitations, this is what takes time on the internet; transmitting a packet through many congested layers, until eventually receiving the packet on the other end. This is excluding outside delays for certain services like web servers, such as the one you're using right now. In the same sense that web servers take time to fulfill requests, games take time to handle messages (And the packets behind them; abstracted away in 'regal.networking' and co.). Under ideal situations, this would be as little time as possible, but that's not always the case.

Now, let's talk about the technologies at play. More specifically, what we normally access from our operating systems. I'm of course talking about the 'internet transport layer', and its protocols. The 'transport layer' handles the lowest level of networking technologies you'll likely encounter. The two biggest protocols, which are also the two used in games and similar media applications, are TCP, and UDP. UDP is the most common in games, and potentially what you'd be using. TCP works fine for games when handled correctly, but it's better when used for bulk data (Web pages, etc), than real-time packet transport. Read on for details.

UDP stands for "User Datagram Protocol". UDP is commonly used for games, as it's a "write once, ask questions later" protocol. It's 'connectionless', although, there are some semantic aspects that discourage this as a concept. By 'connectionless', I mean: If you were to remove the firewalls present in modern routers, any connected device could listen on a specific port for any kind of communication (Packets). Likewise, without connections, you could send to a specific address as much as you want, and it won't matter what the other side is doing.

The biggest downside to UDP is that because there's no "connection", messages can be sent back and forth, but there's no guarantee that any message will make it across to the other end. However, UDP is commonly chosen for games and other low-latency applications, because it's fast. When I say fast, I mean fast. UDP is essentially as responsive and as quick as the user's connection gets. Now, the thing about UDP is that because it's not reliable, you'd have to build a system on top of it to handle missed packets. On top of this, if you intend to keep packet order canonically (Between multiple "sessions"; always ordered), you'd have an extra layer, adding to the delay. In practice, UDP messages come in order, but that's because games run at fixed rates. In other words, the time between each frame is usually enough to keep packets orderly. This is not guaranteed, though. In the case of 'regal.networking', packets are only guaranteed to be in order when using 'MegaPacket' objects, or using a different protocol.

Next is TCP, which stands for "Transmission Control Protocol". TCP is great for things like one way communications (Loading web pages, streaming video, etc), but it falls short when you need to communicate both ways. TCP not only handles packet reliability, but it also takes care of things like packet order, and connection stability.

Now, TCP is fantastic for smaller and less frequent messages. For example, a text-chatting application, or turn-based game, but not when it comes to real-time networking. This is because TCP is not only connection based at its core, it's also segmented between client and server behavior. This means a perfect peer-to-peer networking model (BitTorrent, for example) could never work with TCP. Well, not without opening extra connections, anyway.

Now, most people looking at TCP would be wondering why it isn't ideal, what with it being more stable than UDP, and offering much of what a game is looking for. The problem here is delays, and lots of them. Because TCP has to worry about packet order, reliability, and connection stability the entire time, it has no wiggle room. It's always queuing, and always making sure things work consistently. This adds overhead, especially on congested networks. With UDP, especially with games, you can control everything yourself. For games, this matters, as they don't always need reliable packets (Togglable in 'regal.networking'), or you don't need ordering (Different targeted objects; asynchronous in concept). In addition, game developers commonly want to handle keep-alive messages themselves, as it lets them calculate the delays between each end. With TCP, you would need to do this, and deal with the overhead of the protocol. On the bright side, for other types of applications, TCP's connection scheme is a lot more beneficial. If it wasn't obvious already, 'regal.networking' handles this itself, as well as pings.

TCP is a great choice for less time-dependent games and applications, but for a lot of games it can be a struggle. Even for more complicated games; it's possible to use TCP, but there's strict requirements. The two most pressing requirements are packet reduction and compression, two things that are potential problems for indie developers. There's also the question of the networking model used; peer-to-peer vs. server, or even client-driven. One of the most impressive uses of TCP is World of Warcraft, which gives users incredibly solid experiences, despite the limitations of its platform.

In the end, the best thing I can say to you is that abstraction is the key to networking. No matter what level you implement on, your code shouldn't touch the lower-level, or "moving parts". In other words, if you intend to implement networking in one of your programs, you should distance the details from the code using it. Likewise, even lower level networking APIs are becoming abstract, what with IPV6 support on the horizon.

No matter your protocol of choice, 'regal.networking' should be able to handle your workload. It supports both TCP and UDP, so that should tell you how much it's abstracted from 'brl.socket'. There's still issues to iron out, but it's pretty solid. Just beware of the "too many messages" phenomenon; try not to send more messages than you can receive.


Danilo(Posted 2016) [#5]
@ImmutableOctet:
You should write a book for MX(2), using all your collected and detailed explanations. ;)


Goodlookinguy(Posted 2016) [#6]
I've never seen anyone attempt to explain networking in a single post. Kudos on attempting to sum up the beast.

@OP If you have no experience in networking or network administration, you may just have to go out of your way to get in a class, get a book, or find some lengthy online articles on the topic. Networking is a ridiculously huge topic and it literally never stops expanding. Put this way, when I was taught networking, the net wasn't out of addressable IPv4 space like it is now. That's to say, now you have to lease IPv4 addresses from private companies, organizations, or governing bodies. This, of course, depending on where you live.

Now, back to my main point, the reason I say you'll want to learn it first is because, aside from whatever abstraction may have been created by ImmutableOctet, there is far more to know and consider before jumping into it. Let's take this for example; let's say someone bombards the port you likely have open on your router which routes to your computer and your game. Let's say that the packet they sent is meant specially to cause a certain action from your game and moreover, is specially manufactured to eat at your processing. It could easily DoS or overload your system. Now, I'm not attempting to scare you away from this, but people jump into making games online far too often and find themselves in a bind when it's being hacked to no end, due to their lack of knowledge on the topic.

For lack of better words, I'll tell you this from my firsthand experience, it took me over 2 years (intermittently) to feel comfortable with any level of network programming. This was after I was already experienced (7-years) with network administration. Trust me, you'll thank yourself later when you actually understand this stuff.

On a side note: nodejs is great for making cross-platform server-side game servers. If you learn enough about networking, nodejs may be the next step to get you to the end result. Alternatively, .NET/Mono libs have fairly robust implementations for networking code (but are slower in my opinion).

Edit: This should go without mention, but the attack I mentioned as an example is the lowest form of attack. There are other ones that do things like arbitrary code execution. This method is favored by people who hack game consoles usually, due to the fact that it allows you basically full access. There are also memory dump exploits and just all sorts of attacks from everywhere. What I'm trying to say is, you need to be at least somewhat educated about these for your own sake. You should also learn about encryption, hashing, verification, man-in-the-middle attacks, and just so much more...


EdzUp MkII(Posted 2016) [#7]
Personally if your serious about networking first I would write a chat program that has multiple clients then go from there rolling your own networking as you go.

I will also have to get into networking with monkey soon as I want to add networking to Star Rogue. I did create a networking module for BlitzMax but I want to get back into monkey so I can write a mass multiplayer game :)


potato(Posted 2016) [#8]
Wow, thanks for writing all that up, I didn't even expect anyone to respond to this post, let alone give this much help! For now, I'll try studying the examples in regal.networking to see what I should be doing, and make a basic online game. Again, thanks for the help.