Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

  • Days Won


hplus0603 last won the day on April 15

hplus0603 had the most liked content!

Community Reputation

11483 Excellent


About hplus0603

  • Rank
    Moderator - Multiplayer and Network Programming

Personal Information

  • Role
    Technical Director
  • Interests


  • Twitter
  • Github

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. I could help with that, or you could just post a new message!
  2. First, you seldom want to have your game servers talk directly to database servers. Typically, you'll want your game (simulation/network) servers to talk to an application server, which in turn talks to some database. This lets you scale simulation separately from back-end. Plus, if a game server is "owned" by hacking, the hacker can't just do "select * from users" to get all email addresses and hashed passwords. Presumably, your application servers aren't directly exposed to the greater internet (only to game servers,) and don't have a "return all players" function/request, so the potential attacker would then have to break the app server, after breaking the game server, to get at the full data. Second, you typically don't want to do anything synchronous in a game. You want everything to be optimistically assumed to succeed, send an asynchronous request, and when it actually succeeds or fails, you go ahead and deal with that as a follow-up resolution. This goes for anything from client-side hit detection to the loot case you talk about. Let the game server tell the client that the item was looted, queue a RPC through some queue to give the object to the player, and when that completes, mark the item as "actually complete." You may be able to show the item, but not actually use it, until it's actually complete, for example. Third, what is the actual measured latency? You should see maybe 50 milliseconds from east to west coast between data centers. This is not a very large amount of latency. If your game has a ninja looting problem where the database needs to be involved and 50 milliseconds of looting latency more or less, matters, then your game has a HUGE FRICKING DESIGN PROBLEM that you probably should be addressing using other means than shaving milliseconds ūüôā Fourth, most games don't actually send every single request through the database. Instead, the game server caches the result in RAM, and occasionally checkpoints the state back to persistent storage. This may be done in a streaming fashion (say, write update events back through a message queue) or in a single-checkpoint fashion (say, fork the process and write all object state into some durable database.) If the game server crashes between you looting the item, and the checkpoint happening, you lose the item. Sucks, but hopefully your servers don't crash that often! (And if you stream out updates to persistent storage, you can actually get around that problem, too.) Presumably, the real arbiter of "who gets the item" when looting is the game server, not the database -- having a case where player A in Australia using server A is competing against player B in Washington State on server B, would be inherently bad for a number of other reasons, not the least of which is that syncing state between distant servers in real time is in itself causing a bunch of lag.
  3. hplus0603

    peer to peer mobile design

    Two things: 1) Firebase claims: "Data is stored as JSON and synchronized in realtime to every connected client." This may sound convenient, but it means that every client will be able to see every state of every game. If that doesn't matter to you, then that's fine. If secrecy matters (say, a poker game,) you may need to take additional steps to make sure people can't cheat. 2) A public IP address alone only identifies a network interface. As you suggest, for a typical device, this will be the network interface of your firewall/NAT gateway. To identify a particular "service" or "application instance," you need an IP address plus a port. Thus, you need to store IP address and port in the database. Then you need to make sure that that port stays the same. You do this by keeping the connection alive; for TCP by not closing it, and for UDP by keeping a stream of messages going. But a public IP + port just identifies a connection, not a player. If player 3 wants to challenge some other player, you really need a unique player ID. Then perhaps you can have a look-up from player ID to current connection. However, connections, in turn, only work client-to-server, unless you also establish peer-to-peer connections, and to establish peer-to-peer connections, you need an introducer to do NAT punch-through. You can either roll this on your own using UDP sockets and some central server as the coordinator/matchmaker (this doesn't seem to be built into Firebase,) or you can use existing STUN/TURN servers and infrastructure to set this up. In general, "serverless" platforms like Firebase often end up being a poor match for interactive multiplayer games on the internet, because games often have unique requirements. Sometimes, you can use them, but you will pay a higher overhead than you'd pay for a custom game-specific solution. Sometimes, that overhead is OK, and othertimes, you really do need to develop your own infrastructure from lower-level primitives.
  4. The development process is very different, for the obvious reason that Node.js/ws is generally a Linux ecosystem thing developing in JavaScript or TypeScript and your-favorite-editor-plus-NPM, and ASP.NET/SignalR is generally a Windows ecosystem thing developing in C# and Visual Studio. If you're most comfortable with Visual Studio and Windows SQL Server, use ASP.NET/SignalR. If you're most comfortable with vim/npm and MySQL or Postgresql, use Node.js/ws. For performance, there is not a big difference between the systems. (Yes, you can build a benchmark to prove anything, but the order of magnitude is the same.)
  5. SignalR uses .NET and languages like C#. Also, it's mostly an API on top of ASP.NET -- it needs the rest of the Microsoft web server stack. Node.js uses JavaScript or compatible languages like TypeScript. It's a self-contained web server, but needs a library from npm to actually support websockets. One way of looking at it: SignalR is like the "ws" package for Node.js. Node.js is to "ws" what ASP.NET is to SignalR. If you're a developer used to .NET and used to deploying applications on Windows, using SignalR will feel comfortable. If you're a developer used to JavaScript and used to deploying applications on Linux, use Node.js will feel comfortable. Both can be used to build a web app with game logic. Also, you CAN deploy Node.js on Windows if you have to. But doing that is "fighting against the stream."
  6. The reason there aren't any "decent tutorials" is that this is a very big topic. The specific solutions you end up with depend a lot on the needs of your game. To start a server, bind() your socket to a port, and listen()/accept() connections on that port. To open that server up to the internet, make sure any firewall you have is set to forward incoming traffic on your port to the machine running the server, and make sure there's a domain name pointing at the address your external firewall is assigned. If you want to support "server chooser" type features, such as game lobby, or world shard/instance, then you need to separate "login" from "connect to game." However, if there's just one single game instance that everyone plays in at the same time, you don't need to separate login server from game server. However, once you have more than a hundred or a few hundred players in a single level/world, you're going to need to start breaking up game serving on many machines, which may mean many different servers (from the point of view of the external world seeing an IP address and port) or not -- again, depending on what makes sense for your game and infrastructure.
  7. hplus0603

    Anyone knowledgeable with DirectPlay8?

    Please don't discuss copyright law in a game development forum. That being said, I'm not sure anything in the original post request is particularly related to copyright. In fact, I don't even see a clear question in the post -- what technical question do you want an answer to? That being said, network protocols are often not covered by copyright, and only seldom covered by patent rights, so discussion about network protocols is alright as far as I can tell. There is also the DMCA for those who work in the US, where reverse engineering might be restricted if it's specifically for a DRM technology, so that might be something to watch out for. For the separate question of "could I distribute versions of this client?" that's a two part question, as in "would it be technically legal" (which you should ask a lawyer about) and "would I get caught and what would happen if I was?" which you'd have to figure out for yourself. (Hint: a game development website is not the best place to figure this out.) It may be that the best way to revive that client is to build a separate DLL that implements the DirectPlay8 interface, and make it do whatever you need to do in the functions used by the program, rather than trying to Now, if you want to create an actual business, you're probably much better off just re-building whatever it was that you liked about this game in a modern framework, and ship it. Ideally, on mobile, too, which is a bigger market than PC, and these kinds of games always want as big a network effect as possible. But if it's just for education and research, try injecting yourself as a DLL and see where that goes.
  8. There are tons of algorithms that can generate a one-byte checksum. Algorithms include: Checksums: add up all the bytes (or some permutation of the bytes) and perhaps perturb the result CRC: calculate an 8-bit CRC, or some bigger CRC and drop all but 8 bits of the value. XOR: take the XOR of all values, potentially with a rotation in between each byte Linear congruential generators: Each step, multiply your seed with one prime, and add the value of the next byte Any other hash function, where you end up dropping all but 8 bits (or 7 bits, even.) Without the source code of the application, you have to make guesses about what could be going on, and verify those guesses against that data that you have. Sometimes, writing code that tests various parameters against various algorithms and sees how close it can get may be helpful. There really is no "magic bullet" here. To get you started: If you start with the first value (0x7D) and subtract all the other values, you get 0x10. Do you get that same result for all other data packets you have? If so, you have the algorithm there.
  9. You can take two routes: 1) Don't use threads. Instead, set the UDP socket to non-blocking mode, and at the beginning of each tick, read from the UDP socket until it returns "no more data." (The kernel will buffer a fair amount; you can control how much with a socket option.) No threads needed! 2) Use threads, and add a lock around the "swap global for local" operation. Specifically, when you add to the local list, you need to hold the lock while inserting into the list. When you call into the receiver object from your main thread, grab the lock, clear the global list, swap the global and local list variables, release the lock, and return the global list (which is now full of what's been received.) EIther system will work. Also, you don't need async/await at all in this code, because the reading thread can just block in the UDP socket receive function.
  10. hplus0603

    Auth tokens

    There are two kinds of tokens: 1) Purely random IDs, used to look up everything (user name, privileges, etc) in a server-side database. The only important thing here is that the token is hard to guess (strong randomness of enough bits!) These tokens are generally quite secure, can be revoked on an individual token basis, but require a look-up when presented. This is the "web session cookie" kind of token. 2) Information bearing tokens, containing user name, privileges, and other information. These tokens need to be time limited (so you can't steal one and use it forever,) and need to be signed using a key shared between token issuer, and token user (if you have a login server separate from game server, for example.) These tokens have the benefit that no database look-up is needed, but they are harder to implement, and can't be individually revoked -- you basically have to change the signing key, revoking all tokens, if you believe some token has been compromised. This is the "kerberos ticket" kind of token. I strongly recommend token kind 1) unless you have a very specific reason to need kind 2). ObjectId is very bad for kind 1) tokens. They are almost 100% deterministic, and very easy to guess given a few examples of valid tokens and knowing when the token in question was supposed to have been generated.
  11. hplus0603

    Auth tokens

    The best way to do token security is to generate a fully random value, rather than trying to generate a value using hashing. Store the username and the random value locally, and on the client. (If you're in a browser, localStorage might be a good place to store this.) This random token will typically work as "session token" and could be the value of a cookie and such, too. 16 bytes of random data should be plenty. Just make sure it's a quality random source, such as /dev/urandom on Linux, or the crypto random provider on Windows. (Java likely has some API for accessing these; I don't know off-hand what it is.) The next question is, once this token is lost, how does the same user use the same username again? Is the username lost forever? Do you also require an email address, so you can mail a new token or token-factory link to the user?
  12. hplus0603

    First Timer

    I would recommend an existing MUD construction toolkit/language/library. Try Evennia or perhaps Ranier? http://www.evennia.com/ http://ranviermud.com/ Regarding hosting, you can sign up for the free one-year trial of Amazon Web Services Ealistic Compute Cloud (EC2) and get a T.micro instance to install Linux on and run your MUD.
  13. hplus0603

    ECS and Networking?

    You can write your own component to expose whatever state you want to whatever library you want. There's a LOT of heavy lifting involved there, which the Unity-native code gives you "for free," though, so it's not a super popular route. Exactly how you'd go about this depends on what your networking needs are. If you have a few dozen objects moving around based on physics, with mainly staticly displayed meshes (or client-driven animations, like walk animations,) then a simple protocol with "create entity of type," "update entity position/heading," and "delete entity" would be enough, and generating appropriate data for that out of the ECS is not hard.
  14. Is the problem that you get a full state of the game, then time passes, then you get another full state of the game? If so, you have to write code to detect what changed between these states. If some player has more cards, animate cards to that player. If some player has less chips, animate those chips going away. And, so forth. If you want to make it a little simpler on yourself, you'd include the command that led to the new state, in the state update you receive. Thus, "player 3 raises by 50; new state is ..." would tell the game to animate 50 chips from player 3 to pot, and separately it knows what the pot is. Btw, just because it's turn-based, doesn't mean that you can't use real-time networking, or at least real-time-ish networking, to send the events to the players as soon as they happen. Exactly how you do this is up to you, as there are many variables (networking consumption, battery consumption, server capabilities, protocols used, and so forth.)
  15. Yup! And the main reason for "running slow" on the client would be that the latency to the server increased. This will typically happen if the user is on some kind of mobile internet and moving around, so it's not super common. Yes! And when you're too far out of sync, you may need to "snap" the current time offset, and then figure out how to recover the correct new state of objects being simulated. The "really large snap" case will typically only happen during game start-up, or when a computer is having trouble like hibernate/sleep, suddenly paging to disk, or other extreme timing events.
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!