Jump to content
  • Advertisement

WombatTurkey

Member
  • Content Count

    43
  • Joined

  • Last visited

Community Reputation

251 Neutral

About WombatTurkey

  • Rank
    Member

Personal Information

  • Interests
    Programming

Recent Profile Visitors

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

  1. This has been the hardest thing I've ever experienced while making the game. I've been stuck on this issue for nearly 3 weeks (not even exaggerating) before even making this topic. I finally got something working over the network: https://i.gyazo.com/a6249d5deca325e0d1d29bf2dda936a2.mp4 The red boxes are the server positional data, and the player (face icon) is transitioning through them (12hz tickrate, 50-60ms RTT). I finally got it to be smooth. I was moving around for 2 minutes in awe spamming WASD and noticed barely no jitter (unless lag, or this $3/year VPS has a hiccup). Will worry about that at another day, I really need a break from this dilemma and work on something else. It's a great step forward for me. Am very excited and appreciative that this forum exists, don't believe I would be where I am today without it. Thank you so much.
  2. Stumbled upon this thread: @Simmie's answer and others helped immensely. I was running into the same issue as OP in that thread, and Simmie's solution worked great. How my server is setup: (I trust the client too much, but I want to get everything working before diving into more advanced stuff). - Server tick rate is 10 times per second - Client side network tick rate (sends positional data to server), is 10 times per second Interpolation code (Godot) var realPosition = Vector2() var lastRealPosition = Vector2() var t = 0.00 func _process(delta): t += delta t = clamp(t, 0, 1) $monster.global_position = lastRealPosition.linear_interpolate(realPosition, t) When a new message is received (server, using crystal-lang) t = 0 # Resets on each positional update lastRealPosition = $monster.global_position realPosition = incoming_position # (position from server) This works great so far. The monster sprite transitions itself towards the end position very smoothly! However, there is one problem! It moves very, very slow and doesn't interpolate fast enough. Is there a way to increase this so it interpolates faster? I tried doing t+= delta * 10.00, but then the lerping tries to "catch up to the player". What could be causing that? It's hard to see, but the $monster sprite catches up to the end position, then stops.. then continues again. It's only buttery smooth if I do t += delta.
  3. Just for confirmation The client sends its local game_tick whenever a character's state is changed When the server receives this information, the server sends its game_tick value along with my game_tick value that was just sent Then, when the client receives that, calculate the difference of those (for syncing), and add it to my game client's delta to "advance time"? If I got that right? I think I'm almost there, do I just need to add that difference to my "delta" variable in the _process func? I think i'm getting it now. "if you communicate game steps in terms of step numbers, rather than times". In Godot, the _process is fixed I believe to the monitor's refresh rate, so I would need to create my own https://gafferongames.com/post/fix_your_timestep/ I'm guessing. Which should be relatively easy to convert to GDScript, then use that. Going to give this another shot today, I think i'm understanding it better and better, appreciate everyone's insights and patience as always
  4. Yea, I always think the game client is the future. I think that is where i'm struggling. Because I think "the client is sending input, so this will be something done in the future". This scrambles my brain My game is similar to treasure arena / Chronicon, but not pixelated (but has poe/d2 like system with items, skills, etc). WASD Movement is essential, so it has to be somewhat sync'd for basic collisions to trigger on the server (a fireball entity being moved across the game world, and triggering damage number updates) I was looking at treasure arena's WebSocket frames, and they are doing something similar where they send just the player's movement vector whenever they change direction, with a timestamp. The problem is, I don't know what to do when the server receives a "local" timestamp. And how that can play into effecting the delta to change game state? Do I just add the round trip / 2 to the delta value? Do I need to modify my physics loop on the server, and each player has their own latency property that acts as an accumulator to their x position? Or, does the client just need to adjust the delta based on the latency (or game_tick)? It's really confusing for me, I appreciate your patience
  5. I've been stuck on this for over 12 hours! I've been googling and reading the Valve Networking article, reddit, gamedev topics, etc. I feel like it's time I'd rather just ask for help because I'm so confused :X My game uses Crystal lang for the server, and Godot for the client. My server physics step (Default Move Speed is 200). There really isn't any "physics" stuff yet, but trying to just get the basics down to sync the x position (moving towards the right) property server_tick = 0.00 def physics_loop delta = 0.0167 # 60 fps loop do players.each do |player_id, player_obj| if player_obj.right player_obj.position.x += (DEFAULT_MOVE_SPEED * delta) end # puts player_obj.position.x end @server_tick += delta sleep delta end end Client side input sending (In Godot). I've heard JSON is not a good choice for bidirectional communication, but honestly, just using it right now because it's keeping everything simple for me. I will most likely use something else later var MSG_BUFFER_GAME = {} var player_states = {right = 0} var old_player_states = {right = 0} var game_tick = 0 var last_message_sent_game = 0 var last_message_received_game = 0 func _input(event): if event.is_action_pressed("d"): player_states.right = 1 if event.is_action_released("d"): player_states.right = 0 if old_player_states.right != player_states.right: send_to_game_server({ right = player_states.right}, "MOVE") old_player_states.right = player_states.right func send_to_game_server(message, cmd = "PING"): MSG_BUFFER_GAME.cmd = cmd MSG_BUFFER_GAME.message = message MSG_BUFFER_GAME.tick = ("%.2f" % game_tick) #print("Sending.. %s" % to_json(MSG_BUFFER_GAME)) TCP_SERVER_GAME.put_utf8_string(to_json(MSG_BUFFER_GAME)) last_message_sent_game = OS.get_ticks_msec() func _process(delta): var speed = 200 var motion = Vector2() if player_states.right: motion = Vector2(1, 0) $player.global_position += motion * (speed * delta) game_tick += delta func _on_tcp_timeout(): send_to_game_server("", "PING") # fake ping to sync game_tick from server func MessageGameHandler(msg): last_message_received_game = OS.get_ticks_msec() var json = JSON.parse(msg).result var cmd = json.cmd var new_message = json.message if cmd == "PONG": # sync local game_tick with server's game_tick = new_message The server's MOVE command just basically sets the player_obj.right to true or false. The server's PING command just sends the correct game_tick: when "PING" client.send server_tick, "PONG" end The problem is, I don't know what to with this almighty game_tick value! Because when `right` is active, the x value on the server doesn't match the x value on my client (not synced). Here is a photo (server console on right). I've read in this reddit post that I need to get the difference in the game_ticks, and "adjust accordingly"? What does that mean? Do I need to add the game_tick difference in my _process's delta on the client, or on the server's delta? (Assuming that's what that means). My mind just goes blank at this point , any help is appreciated!
  6. Hey guys. I just wanted to say after reading all the help and doing some changes, the looting feels instant! Really nailed it on the head about that asynchronous behavior. Appreciate your insight as well, Aceticon. I feel very happy I explained my situation fully to the best of my knowledge and received cordial help. Rare to see that nowadays tbh. Usually there is always someone being snarky. This forum is great!
  7. Yeah, not a ninja looting problem, I just want to make sure the player has a responsive looting experience. As you said, I guess I could update the inventory matrix (check if it fits), and then run the query asynchronously, and if anything goes wrong, we go from there. That way, they'll be able to loot instantly w/o waiting for round trip times. That sounds like a good solution, thank you. Actual latency I don't know off hand, but I just want the player who chooses the closest server to have good latency w/o the master server hindrance (waiting for round trip times). Which I believe your second paragraph is a solution to that, again, it's appreciated. @Aceticon lol yeah. I saw your previous post and was like what in the hell is going on. I got the data structure down and whatnot. Item looting works great, and I have diff modes, free for all, short allocation, etc which the party leader can choose. I was just curious how to implement/run the queries to give the illusion of quick response times. Thanks for your post as well.
  8. I was googling but couldn't really find anything related to this, so I figured i should make a diagram of my current server setup: I was curious about the mysql connectivity, because let's say the game instance servers are connected to the master mysql server. Assuming the master server is located in WA State, and someone who lives in New York connects to the New York game instance server... And when the game server drops an item (and the player loots it), the game instance will need to communicate back to WA State, then, back to the NewYork game server to tell the user the item has been successfully inserted into their inventory. Now, that's a lot of round trip time, and not fair to that player who chose a game instance server closest to their location. When a player loots an item, I can make it seem like it's inserted into their inventory (update the matrix), but I just feel like I'm doing something wrong here. Any insight/advice is appreciated
  9. WombatTurkey

    Legalities around words / phrases / names?

    That depends on where you draw your risk tolerance line. To be safest, make up your own phrases. If you don't mind risking a cease and desist order or a lawsuit, use any trademarked phrases (or any phrases that might be considered trademarked) that you like. If it was me, I'd make up my own phrases.       Thanks for the fast response. I agree and will most likely do that. It's just kind of hard as this is a simulation type of game and that kind of phrase (example "Baal Runs"), is well known. Hmm, this sucks then. Better safe than sorry though right
  10. Hey everyone,   I have a new game genre idea I was brainstorming and am curious about what we can use in terms of words / phrases.   For example: I want to use these two words "Baal Runs", which stemmed from the game Diablo 2. Is it okay to use those words together like that within my game?   Also, maybe "Greater Rifts", or "Rogue Encampment", or maybe town names, boss names?   My game will be free 2 play with microtransactions. These microtransactions ARE not bound or include any of these words.  The art for my game is completely custom and unrelated to Diablo 2 or any other game.   I am wondering where the line is drawn here.The text is also not being used to copy lore, or plagiarizing quest descriptions either. It's literally just these couple of words / phrases. Thanks in advance!
  11. WombatTurkey

    20Hz Server Performance Dilemma

    If your game depends on low latency, don't say I didn't warn you!     I think I'll just go with TCP for now, and test UDP on this OVH VPS before it expires. I mean, for movement only, I heard UDP is far better, from every single knowledgeable dev like yourself. So I am really intrigued... It's just, my lack of networking knowledge might create that "congestion" :P -- And in the end, I'll probably do more harm than good   Thanks for all your help @hplus0603. I bookmarked your site as well. So much information overload O_O
  12. WombatTurkey

    20Hz Server Performance Dilemma

        Yeah, good point. For our central server (which is basically the LB) will run around 3-4 instances.  Then, once they find a game to join or create, I load them onto a separate $5.00 VPS for game processing. They are still connected to the central server too, so private messages, log out/in notifications, etc will be over TCP (Websockets).   Then, for the $5 boxes they connect to, I can use UDP for player movement. Since electron allows me access nodes API, it will be fairly easy there.   I'm just worried I would need to have two network streams, UDP and TCP?  Because when a player drops and item, or needs 100% packet reliability, I'd rather go through TCP. But, this worries me because then that would be even more overhead for those 5 dollar VPS's :P   Maybe just ditch the UDP for now, and see how TCP goes?   Definitely right about the oversubscribed nodes. So I'm thinking even less amount of players. Probably around 100 per instance to be honest.  Although, I could just get a nice dedicated one and have game instances on different ports and just have the  players connect to those instances, instead of separate physical severs. That would probably be ideal for performance?  Quite a bit more expensive though  :(   Edit: I went ahead and created this: http://www.html5gamedevs.com/topic/23427-nodejs-networking-500-vpss-vs-1-dedicated/  I personally think the mini $5.00 VPS way is ideal here. Especially because of how nodejs works, but yeah still contemplating 
  13. WombatTurkey

    20Hz Server Performance Dilemma

        Great! I was thinking of doing UDP. I am using electron and not limited to the browser's API so I can use node to connect. I did some math (which I'm not particular good at) but, I was estimating at around 240 Messages Per Second for every 6 players. Since my game is instance based, it's limited to obviously 6 players for each game, if this even helps with performance in the end, I have no idea as the server will still spit out a ton of data (relatively speaking :P) -- (This is also assuming they are all actively moving, and counting for bi-directional communication [server receive and sending total])    Correct me if I am wrong as I am horrible at Math, but this is the algorithm I used:   6 players online = 20 * 6 = 120 * 2 (sending and receiving) = 240 Messages / s   100 players online = 20 * 100 = 2000 * 2  (sending and receiving) = 4000 Messages / s   I changed my architecture up since we last talked. I am running 1 main server that uses nginx as a custom load balancer for 3-4 node instances. This server then sends players off to $5.00 VPSs to act as game instances. They communicate with Redis to let the central server know some things, etc. -- Since node utilizes 1 core, and is single threaded, I heard about this idea from the dev who runs wilds.io and figured it would be perfect.  I did some testing on these cheap $5 boxes with the ws library (perMessageDeflate: false), one of which has the specs of:   model name      : Intel Xeon E312xx (Sandy Bridge) cpu MHz         : 2394.472 Except, I'm only allotted 1 "virtual core", but, with that said:   I got to around 10k Messages per second receiving and going out before nodejs's event loop started to poop.  I was sending around 19 Bytes per message in/out.  The wilds.io dev said he gets around 100-140 and up to 200 active players per node instance.  His data stream is probably different and other factors obviously come into play here, but I figured it's a good ballpark estimate.    So, I'm thinking in the end, 100-200 players per node at a 20Hz rate is what node is capable of, off a $5 box.  I'm curious if 4000 msgs/s is a lot in this area, and what am I capable of if I switched to lets say, a C, or C++ TCP server? I assume far more than 4k msgs/s?  I feel like nodejs is undermining me.     Edit: I looked at your fixed canonical game loop page. I'm most likely going that route once I figure all this out first, I'm what you call a, little slow  ^_^
  14. I finally found the perfect tick rate for our gameserver. 20Hz. [Example Gif] Entity interpolation seems so smooth but I am curious/worried about some things.    Right now, a way to "kind of" validate X, Y values being sent are checking the differences between a players current pos and their intended pos. (They are given x, y server value when entering the map) -- so checking from the get go they can only move so far/so fast. Otherwise they will get re-synced, or kicked.   I have clientside physics as well. So, for example when a player moves towards a block he will either not send any position (player let go of the key) or if colliding, send the position the character is in. This works great because then I don't have to run a physics server.   The problem is, this requires the server to receive data at a rate of 20Hz instead of just sending "up,left,right,down" keys. The trade off is... I don't need to run a movement timer at 20Hz on the server.  (Sure, the occasional naughty player will send weird x, y positions to make the player move 20 more pixels so they can enter inside a collision area, but that's not really a big deal to me right now)   With all this said:   A) - I could either run a basic fixed timer on the server at 20Hz and only receive the input from the client and then send the new x,y values to all the other players B) - Or, do what I am doing now and send the 20Hz of x,y values only when a player is moving that notifies all other players in that game   I feel like option B is ideal because I don't have to check for all the collision areas in the map. I let the clientside physics do that work, and send the appropriate X, Y values.  The downside is, a lot more data needs to be sent to the server.  But, you could also give the argument that if a player is spamming 'W, A, S, D' keys, that's a lot of packets being sent too... so if the player is actually moving like a wild billy goat, you could argue that the 20Hz of data being sent could be less.     Option B also has a downside of less responsiveness of player movement since it's being interpolated. For example, strafing left and right real fast will not necessarily be as fast as what you see on the client. I believe that could be fixed by increasing the 20Hz?    Also to add, option A's responsiveness factor to B would also be the same. Since the server is sending data 20Hz as well. I'm just not sure if I can get away with the client sending data at 20Hz.  I've read that 30Hz, 60Hz is even common. But you have to remember, I'm using nodejs   :rolleyes:  Anyways, I just laid out a lot of stuff so please critique if necessary, thanks!
  15. Aww. That's funny how you mentioned net.createServer(), I was just doing testing with that earlier for process communication. With raw unix sockets on some random VPS node. Sad part is, I am only getting around 9k msgs/per second which seems pretty low and am scared that would cause latency issues in the long run. But then again, the VPS I'm testing it on is around 3$ lol. (using this benchmark with setImmediate)        I totally forget they are both linked to that game instance... That's what I think was confusing me. Again, you deserve more credit for what you do here... This type of information is invaluable I really appreciate it.   Edit: I have bookmarked this thread as well so I can look back and double check stuff.
  • Advertisement
×

Important Information

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

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!