Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

192 Neutral

About Farkon

  • Rank
  1. Thanks, your two last answers is what i needed!
  2. Thank you both for taking the time to answer.      I think i understand the steps you are showing and i don't think i'm having a trouble with what i understand from this BUT I'm still wondering how variation of latency is handled here. I think it still all comes down to me not understanding the part of your implementation i'm not having !?   My big misunderstanding sums down to (warning: what i'm going to say is probably wrong but that's how i get it) : Server iterates over the client frame buffer starting from the first frame he has received from the client, and will process one frame per server loop. So once the first frame is received, that frame will define the latency for the rest of the game.   In my mind if a client is sending the first frame at high latency, since the server will take that frame as the first one to process (and after that, one per frame) i will always keep that lag even if my latency is reduced, because what i will do is just adding frames to the server buffer in a more responsive manner but the frames are still sucked at 60fps so the lag won't be eliminated, that's what i don't understand.   That was an extreme case to help me understand what i am doing wrong here. I agree that it shouldn't happen, and it actually doesn't in my case.   Thanks, i wasn't aware of rtmfp! even if it seems like it's for p2p connections, i guess i could make one client a server... that's worth digging, i'll still stick to the flash.net.Socket thingy for now though.   Thanks for that precise explanation, that's how i understand it as well. But i'm still confused about my lag variance issue (see first answer of that post).
  3. I guess i could calculate the latency (in ticks) server-side and adjust the client frame id (still server-side) dynamically...
  4.     I do but what if the client is lagging over the number of cached frames ?      How do you get offest_ticks here ?       This is action RPG-ish and if i had the choice i would go UDP but i'm using flash.       So you set a fixed buffer size, same for all clients ? And no matter the latency, if the client is over that size, he's not meeting the requirement to play that game ? If so how big usually is that buffer ?   I'm still in the mist with setting the first frame ID (client to server), let's say i'm having a 1second lag when setting the ID, no map loading, just no luck. I'm going to set frame ID 0 at t1 and the next frame ID1 2 3 4 5 ... all at once at t2, the server will increment ID 0 by server step at t1+lag, then will receive 1 2 3 4 5 ids while only incrementing ID0 to ID1 at t2+lag when the id should be way further. There's something that i'm really not getting here :S
  5.   If i'm understanding well you're describing the rewinding technique for clients, if so this is lag compensation while i'm talking about raw lag that *shouldn't* be there.     Definitely; that's something i imagined as a workaround though. I'm still a bit confused about the fact that i'm definining the lag by the first message i'm sending for the rest of the game. The server is using that ID and will increment it at server steps, so if i'm lagging more, the server will receive messages that are too late to process. I guess there is some kind of dynamic mechanism relative to the latency to make but i'm not sure how.   you is any client in this case: The client at t1 is receiving the map + player creation event, that loop takes 1 second, the client is sending first inputs. Server receives those inputs and set the first frame ID. Client is at t2 and catches up for the laggy previous frame hence spamming the server buffer with X inputs, which makes the server having longer buffers than expected. I'm aware that it's a corner case and that i can fix it but i still don't know how to set that first timestamp from which the server will iterates on (if it's ever how i should do).     I admit i didn't really visualize the scenario that way. Angus pointed out the same thing. In my mind the idea was that sometimes people are lagging so much that i make them going out of a potential infinite loop and that those cases will happen no matter what but i guess i can just say that if the number of loops have passed a certain limit i just disconnect the player or something in that respect. Which i guess is more or less what you were thinking about. This makes sense.
  6.   Thanks for your answers!   True, but lag spikes happens and i might need to recover somehow. I'm using the same framerate for both client & server and i'm not sending deltas. I'm not processing several frames by server frame, that's actually what i want to avoid. What i'm having atm is a circular frame buffer from 0 to 255 which corresponds to client IDs indexes. Whenever i receive a message from a client i put it in this buffer at array index = client frame ID. My dejitter logic is basically processing from the frame buffer at local (server) client frame ID - X, that's maybe here that i'm doing something wrong !? I'm using TCP. I could load it asynchronously but i don't really care about the lag but more about the fact that i can't recover from this, i'm not comfortable with my system not being solid since it might happen in other cases. And in my case the server logically expects the client to send inputs at that time, if i understand correctly that's more a consequence of how a fixed timestep loop is working, it doesn't mean i can't fix this. But again i'm wondering how to recover from such cases.
  7. Hello,   I'm sorry to make yet another thread about this, but i've been confused reading the threads about processing inputs.   What i've been doing until now is : clients send inputs, server is calling process(input) as soon as it receives them, which means processing several netframes per server frame. It works well for my simple physics, it's deterministic.. but it's obviously vulnerable to speedhack.   So i was looking at another way, here is what i'm doing.   Client has its own frame ID and send its inputs with the frame ID to the server. The server is caching each message by (client) frame ID. (The server sets the first client frame ID via the first client message received (client ID)) From there the server increments each client ID according to its (the server) steps. The server sets client inputs getting them from the buffer, if there is no frame, just skip it.   Using a dejitter buffer it works well but i'm not convinced that's how i should do it; here are my questions :   Here the latency is set by the first message received, how do i initialize my timestamps? What happens if the client is suddenly lagging and the server ends up skipping all the received frames ? Do you adjust this in realtime? In my game the server is sending the map & a player creation event all at once. I'm using a fixed timestep but what happens is that when the client is receiving the map and processing it, it takes around 1 second & in the same frame sends the first inputs. Next frame the fixed loop makes his job and tries to catch up from the lag introduced in the previous loop, so i end up sending X events to compensate for something the server isn't aware of which introduces a big amount of lag in the game. Still related to time, what happens if the client or the server goes out of the fixed loop aka by being prevented to enter the spiral of death?
  8. Farkon

    Processing inputs right away

    I have no idea why i thought it would be different from what i was doing, i actually had a bug when spamming an action key would cumulate latency, so i started from that and made wrong premises. Thanks putting me on the right track :3   (I actually have more questions but i'll make another thread);
  9. Farkon

    Processing inputs right away

    Thanks for the help.   I thought more about how to process MY inputs and i need a few enlightments :   The client is sending ~2 frames per packet.   What i used to do in my other projects is checking on the server if there are datas to dispatch, if so, call movePlayer() or throwArrow() and since i'm having 2 frames i was sometimes calling throwArrow() twice in a row.   But right now i'm using an entity/component architecture, the same as T=Machine where an entity can only have one component type. So when i'm receiving a client packet about throwing arrows the networkSystem would attach a CThrowArrowEvent component to my client entity and then the event would propagate through all my systems.   That's my server loop :   timerSystem.processOneGameTick(); networkSystem.processOneGameTick(); roomSystem.processOneGameTick(); inputSystem.processOneGameTick(); actionSystem.processOneGameTick(); repairSystem.processOneGameTick(); towerDetectorSystem.processOneGameTick(); towerActionSystem.processOneGameTick(); lineSystem.processOneGameTick(); energySystem.processOneGameTick(); healthSystem.processOneGameTick(); characterMovementSystem.processOneGameTick(); characterPositionSystem.processOneGameTick(); networkOutSystem.processOneGameTick();   So if i'm having two events in the same packet about throwing arrows, i can't just attach 2 events to my player entity as soon as i'm processing the packet since my entityManager structure doesn't allow it.   I would like to avoid changing my entityManager but i'm not sure what method would fit the best my architecture.   I could make one server loop per packet frame for all the players which mean that i would make two loops in a row independently of my server fps. I would still send back datas at regular interval. How does that sound ?    
  10. Hello,   I was reading some Carmack updates about the QuakeWorld development here : http://fabiensanglard.net/quakeSource/johnc-log.aug.htm   And that part made me think about how to process inputs :     In my projects I usually have a big server loop, processing all the received messages and sending back "independently" the server updates to all the players.   It works but indeed, as he said, it adds some latency if you process the messages at 30 or 60fps but I always just dealed with it; now i'm wondering how you handle cheat with this kind of architecture.   The issue being cheaters trying to speedhack by just sending packets at a different expected rate. Do you average the number of packets received from the client and try to consume them at an arbitrary rate ?   Is it a good route to take ? Any drawback ?
  11. Why don't you stick with Python using the Pygame library or Pyglet since you already started learning it ? (which is actually good for starting gamedev)
  12. I'm not sure how it's directly related to my question and maybe that's because i got your idea wrong. My issue on that example was that i couldn't reach my component easily from just an ID. From what i read of the source your SystemManager handles what system it has to update and while i don't see the link to my issue, i'm also wondering if you are gaining that much resource compare to just iterating over every System which are actually doing nothing because having nothing to iterate to. (Note that it's actually opposite to what i alluded to in my post) Ps1 : My NetworkSystem is a bit weird in that sense that it doesn't actually manage a really specific type of component, it's basically a dispatcher so the server datas could be about any component type. I'm not sure about the benefit of splitting that into NetworkPlayerSystem NetworkRocketSystem... Ps2 : I think that your comment would actually fit better for my HP issue. As for your health bar animation question, you could add an Animation Component (which you set to be the health animation) to your entity when the health changes, and have the Animation system handle that component for you, and remove it when animation is complete. [/quote] That's how i would do it as well but i guess it works only with your type of SystemManager or with mine ignoring the pseudo-too-many-systems-to-update-overhead. As far as the Health Bar being it's own entity, can two entities share a common component? If so, you could have the same CHealthBar in Player and HealthBar entities, and updating from the Player would automatically update it in the HealthBar. [/quote]That's a good idea and i might gonna use it for now. But it's a bit dangerous at some point; since i'm iterating over components and not entities if the HpSystem needs to reach CHealthbar AND CPosition handling that position for that specific system meaning the position of the healthbar i might also change the one from the player entity. Now i am not supposed to change the position from the HealthBarSystem but there might be cases where i would be stuck. Nice framework name
  13. After an extensive reading of the T-Machine articles about entity/components design i've decided to move part of my code to that. It's *working* right now but i still have some questions : Networking : Not really a problem here but i'm still wondering if i'm doing it "right", I'm currently having a NetworkSystem which is filling components with network datas and then other systems will do their job. Basically my filling-datas pattern looks like that : *New data is arriving with item ID* allNetEntities = getAllEntitiesPossessingComponent(CNet); for netEntity in allNetEntities { net = getComponent(netEntity, CNet) if net.id == itemID { pos = getComponent(netEntity, CPosition) pos.x = itemX pos.y = itemY } } I'm not into performances optimizations yet but it's a bit ugly, i guess the way to go would be add a NetworkSystem method like addNetEntity(entity, ID) populating a collection of some sort and then getting the item through that list. It seems totally logical but i'm mainly trying to see if i'm going to hit a wall of anti-e/s patterns at some point. Events : I'm not comfortable with using an event system here and i don't really know how to handle that myself. Let's say i'm having a CHealthBar component which contains hp datas and i want to add a little animation when a player is losing health. An idea that come to mind is just to update that hp data and let the system throws an animation when it detects that newHp < oldHp but it means that the system will always check for that condition. Again it looks like premature optimization but i'm more looking for nice habits. Another idea would be to play with components which might be a bit more elegant : If the client is receiving new hp data he could update the CHealthBar component and adding a new CNewHp component, which will be handled by the HealthBarSystem and then removed. i'm still having that constant check to do in my loop though. HealthBar parent/child: Still with that HealthBar i'm wondering how you attach entities together. That's what i'm doing right now. [source lang="jscript"] // Player var playerSprite = DrawableSystem.getBitmapFromFile("player_healer_walking1"); var player = this.game.em.createEntity(); this.game.em.addComponent(player, new CPosition(netx, nety)); this.game.em.addComponent(player, new CNet(id, netx, nety)); var pdrawable = this.game.em.addComponent(player, new CDrawable(playerSprite, this.game)); // Healthbar var barSprite = new Bar(0x6CF048, 50, 8); var healthbar = this.game.em.createEntity(); this.game.em.addComponent(healthbar, new CHealthBar(player)); // Reference to parent player entity this.game.em.addComponent(healthbar, new CDrawable(barSprite, pdrawable.sprite)); this.game.em.addComponent(healthbar, new CPosition(-25, -40)); [/source] Graphically : Right now my CDrawable takes two arguments, the sprite object and the parent sprite object. Here i don't really respect the rule of data-only components since the constructor is actually doing parent.addChild(child), that's an exception I made and i'm not really proud of it since i will eventually need a method to remove that component from the screen; I used to do that differently by just calling drawableSystem.addOnScreen(component), is that better ? Events/Graphic datas : Since i don't really know how to handle events i'm a bit stuck on where to put initialization code. In the snippet above i'm writing new Bar() and passing it to my CDrawable component but Adam (from T-Machine) doesn't seem to talk about sad and lonely classes going around your code. I want to put that in the component constructor since it doesn't contain any logic code and is actually *datas* even if i'm initializing stuff in it but i'm not sure about that. Or it could be a method in the system but would need to be abstracted IMO. Relationship : When the client is receiving new hp datas i need to update that component. I'm having an ID for each player so i need to reach that hp entity starting from the player entity. In my example above the player component doesn't know about the hp component whereas the hp component does know who's its owner, it works, but it's a bit weird to update that hp component. Pseudo-code : allHpComponents = getComponents(CHealthBar) for hpComponent in allHpComponents { id = getComponentFromEntity(hpComponent.parent, CNet) if id == netId { hpComponent.hp = newHp } } I'm having the same kind of code than my network one, the only workaround i can see is to have another component called CHealthBarEntity added to the player entity and redirecting to the healthBar entity, how dirty does that look ?
  14. Farkon

    Data size & circular sequences

    Ah, that's actually very elegant, thanks. Second, you probably want to run-length encode "old" data in your packets, so that you know what to do if a packet or two is dropped. This will make the data size of the packet variable, but will make it much more robust for an input-synchronous networking system.[/quote] I'm not sure i understand this part, or at least the way you do it. But i'm implementing a q3style system where i'm making delta compression against the last acked state so if i'm having a dropped packet it will get the next packet and use it instead of waiting for a RTT. Third, I'm not sure your math checks out. You need to send data about all users, to all users. That's 46 kiloBYTES per second. A 50 kbps connection only does 50 kiloBITS per second.[/quote]I meant 50kbytes/s sorry. Fourth, if you know that the update is exactly "one update of three bytes for each player in order," then each of those updates don't need type/size -- you can squish it to 3 bytes per player, and perhaps one type/length code at the front of that array.[/quote]Ah indeed ! Fifth, $50/month will buy you a small dedicated server with 10 Mbps uplink and 2 TB of bandwidth. Trying to cram more than 2 TB of bandwidth through a 10 Mbps uplink in a month is actually pretty hard, so you wouldn't really have to worry about overages. You'd probably run out of CPU or RAM before you ran out of bandwidth. [/quote]Great to know that, thanks
  15. Farkon

    Data size & circular sequences

    I don't get how this is different, or maybe i wasn't clear enough but my little piece of code shows that i wanted to know how many players the server can handle knowing the net loop rate and message size. I didn't think about fragmentation though.
  • 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!