Networking woes

Update: I changed the frequency that the messages are sent to my server. The message is in my update loop, controlled to update 26 times per second. I changed it to 10/sec, which significantly helped the lag… at first. Over a fairly brief time, the lag gets worse and worse.

@ulfgur said: Like what? I mean, I regularly back stuff up, but is there a program that will do that for me? Today's breakage was fairly unusual for me, because I'm pretty paranoid about backing it up... but then, safety nets are for the exception, not the rule.

CVS, SVN, GIT, etc. etc. etc… SVN may be the easiest to get used to. GIT is more modern but more complicated, especially if you’ve never used a version control system before.

@ulfgur said: Blocking my listeners?

By that do you mean slowing them down, or turning them off? I’ve got a couple for-loops inside the message listener that’s causing the lag. Would that cause the problem?

something like this?

[pseudocode]
for(all my players)
{
room = player(a).getControl.getRoom();
name = player(a).getControl.getName();
if((room = message.room)&&(name != message.name))
{
message.setReliable(false);
server.broadcast(Filters.in( server.getClient(matches player a), message));
}

}
[/pseudocode]

Well, the loop is very inefficient anyway… like why broadcast a message if you are only going to send it to one player anyway? Just send it to that player.

If your player list keeps increasing because you never remove any then your loop will take longer and longer and longer each time.

It would be better to just loop over the server connections. But the pseudo code looks very strange anyway. Not sure where getClient() is coming from. It would be easier to help if I saw actual code.

@ulfgur said: Update: I changed the frequency that the messages are sent to my server. The message is in my update loop, controlled to update 26 times per second. I changed it to 10/sec, which significantly helped the lag... at first. Over a fairly brief time, the lag gets worse and worse.

I can’t help further without seeing the actual code.

This will probably also look a little strange, so I’ll try to explain: My game will take place over a series of rooms. These will be self-contained little boxes, so it doesn’t make sense to send continual location updates to players in different rooms. I only want to update the location of players in the same room.

So, here is what I do:

1: check if a player room has changed. If it has, everyone needs to know, broadcast the message everywhere.

2: check the message again. Send it to everyone in the same room who is NOT the original sender.

Because I have a list of players, the only way I could think to do this was through a for-loop. So far, I am only capable of testing with two players.

[java]if (message instanceof MoveMessage)//…and it is a move message,…
{
//…assign the message a name for reference,…
MoveMessage dictate = (MoveMessage) message;
System.out.println("move " + dictate.getName());
//if the player location has changed, send it to all the clients:
for(int b = 0; b < players.size(); b++)
{
String fetchedLoc = players.get(b).getControl(playerControl.class).getLoc();//get the player location.
String fetchedNam = players.get(b).getControl(playerControl.class).getPName();//get the player name.
if(fetchedNam.equals(dictate.getName()))//if the messageName is the same as the playerName,…
{
if(!players.get(b).getControl(playerControl.class).getLoc().equals(dictate.getRoom()))//…and the room has changed,…
{
players.get(b).getControl(playerControl.class).setLoc(dictate.getRoom());
dictate.setReliable(true);//send a reliable message to all the players
server.broadcast(dictate);
}
}
}

            for(int a = 0; a &lt; players.size(); a++)//for all the players,
            {
                String fetchedLoc = players.get(a).getControl(playerControl.class).getLoc();//get the player location.
                String fetchedNam = players.get(a).getControl(playerControl.class).getPName();//get the player name.
                if((fetchedLoc.equals(dictate.getRoom()))&amp;&amp;(!fetchedNam.equals(dictate.getName())))//if the client is in the same room as the player, and is not the player,
                {
                    dictate.setReliable(false);
                    server.broadcast( Filters.in( server.getConnection(a) ), dictate );//rebroadcast the message.
                }
           }
            dictate = null;
        }[/java]

This:
server.broadcast( Filters.in( server.getConnection(a) ), dictate );

Is the same as:
server.getConnection(a).send(dictate);

…but really you could do with some proper data structures. Like I don’t know why your not keeping your rooms in a Map with a list of players in the room or whatever.

Anyway, none of this is the problem really. Unless your player size keeps growing every time (and you’d be able to check that with a simple debug log) then this will operate in pretty much constant time and the messages will not backup.

Since I see you are using controls even on the server then it may be a matter of how you are handling threading and so on. (starts record player)“Writing network games is the hardest kind of game development… not to be attempted by those without a decent knowledge of data structures and threading…”

Conclusion: the problem is not in the code posted and the problem is not in SpiderMonkey.

The fact that your player list index directly matches the client ID does tend to reenforce my guess that your player list keeps growing and growing. Each new connection will get a new client ID.

In general, keeping these indexes the same is very fragile and unnecessary. You can store data right on the connection object and there is no reason to go through these extra steps.

@pspeed...and the problem is not in SpiderMonkey.
Never said it was.
@pspeed said: This:...Like I don't know why your not keeping your rooms in a Map with a list of players in the room or whatever...
Yeah, that specifically was one of my next steps. But I've got to reanimate a corpse before I build a working Frankenstein... I'll clean up my data handling and see if that works.

Hey, I’ve got another stupid problem that I can’t seem to fix.

My goal is to cast a ray from one node to a characterNode, then see if the first collisionResult is a characterNode. When I run the program, it does not give me the specified output that indicates my test was sucessful.

I know that there is nothing between the two nodes, and that it should return the proper value.

My math skills are not very strong, so I’m hoping it’s a dumb mistake in that area that’s easily fixed. :wink:
[java]
Node currentMonk = monks.get(a);//this is inside a loop, so get the current subject,…
AIControl currentControl = currentMonk.getControl(AIControl.class);//…,then get the control
Vector3f offset = playerLocation.subtract(currentControl.getPhysicsLocation()); // subtract 2 locations to get direction
CollisionResults results = new CollisionResults();//results
Ray ray = new Ray(currentControl.getPhysicsLocation(), offset);//cast the ray
rootNode.collideWith(ray, results);//get the collision
if (results.size() > 0)//if it collides,…
{
if(results.getClosestCollision().getGeometry().getParent().equals(characterNode))//and there is a characterNode,…
{
System.out.print(“1”);//…alert me.
}
}[/java]

  1. this doesn’t have anything to do with networking so a bunch of people probably won’t even look.

  2. I’m confused about whether you see the “1” or not.

Seeing what you’ve actually hit is pretty easy and a basic debugging skill.

OK, rebuilt in a more relevant spot.

http://hub.jmonkeyengine.org/forum/topic/help-a-noob/

@ulfgur said: OK, rebuilt in a more relevant spot.

http://hub.jmonkeyengine.org/forum/topic/help-a-noob/

More advice: next time you may want to pick a post title that is descriptive. 60-70% of the posts here could be technically titled “Help a noob” but it wouldn’t be very helpful to people skimming posts.

Will do.