Spawning Players

06/06/2011 10:34 Santa#1
Alright. So this is driving me insane.

My problem: When Player A is off the screen of Player B then jumping onto the Screen of player B Player A can see B but player B cannot see A. The same thing happens when walking.

I have double check the Player Spawn packet, and jump packet so those are correct. I use the same method i did to spawn player B to A as i do to spawn player A to B.

What i think is wrong is the order in which i'm sending the packets to Player B. I'm fairly sure I've tried all the different combinations, some of which crash the client. So if there a certain order?

This is my order atm:
PHP Code:
                        C.Send(Packets.GeneralData(C.UIDToXToYFromXFromY133));
                        
Collections.Maps[C.Map].MovePlayer(CC.CreatePoint(ToXToY));
                        
C.toScreen(Packets.GeneralData(C.UIDToXToYFromXFromY133)); 
And this is how I spawn to each other:
PHP Code:
            foreach (Client G in MapClients.Values)
            {
                if (
OnScreen(WhereG.CreatePoint(G.XG.Y)))
                {
                    if (!
G.LocalClients.ContainsKey(C.UID))
                    {
                        
G.LocalClients.Add(C.UIDC);
                        
G.Send(Packets.PlayerSpawn(C));
                        
Console.WriteLine("Adding Player " C.Name " to the Local Clients of: " G.Name " At: " C."," C.Y);
                    }
                    if (!
C.LocalClients.ContainsKey(C.UID))
                    {
                        
Console.WriteLine("Adding Player " G.Name " to the Local Clients of: " C.Name " At: " G.+","+G.Y); 
                        
C.LocalClients.Add(G.UIDG);
                        
C.Send(Packets.PlayerSpawn(G));
                    }
            } 
This is my toScreen Method:
PHP Code:
        public void toScreen(byte[] Data)
        {
            try
            {
                foreach (
Client G in this.LocalClients.Values)
                {
                    if (
Collections.Clients.ContainsKey(G.UID))
                    {
                        if (
this.UID == G.UID)
                            return;
                        
G.Send(Data);
                    }
                }
            }
            catch { }
        } 
06/06/2011 11:00 { Angelius }#2
how about

Quote:
C.LocalClients.Remove(G.UID);
G.LocalClients.Remove(C.UID);
cus you are checking if the player was not in the other player dic than spawn it so the way you are doing it its gonna spawn them to each other only one time and than every check is gonna read that yes they are both added to the dic which mean there is not spawning


EDIT:

actually i think i have a better way to do it .

lets see

first thing you need to store the player old x/y every time they jump/walk .

so in your jump/walk handler and before you update the player with the new x/y
client.prevX = client.X;
client.prevY = client.Y;

and than update the clinet.x/client.y

and than in your spawn void you are gonna do something like this


Quote:
int cansee = (int)(18 - Math.Max(Math.Abs(client.PrevX - client.X), Math.Abs(client.PrevY - client.Y)));
var NewSpawns = from C in MapClients.Values where (Math.Max(Math.Abs(C.X - Client.X), Math.Abs(C.Y - Client.Y))) > cansee && !(Math.Max(Math.Abs(C.X - Client.PreviousX), Math.Abs(C.Y - Client.PreviousY)) < 18) select C;
foreach (Character P in NewSpawns)
{
Client.Send(Packets.PlayerSpawn(P));
P.Send(Packets.PlayerSpawn(Client));
}
thats it thought and clients should be able to see each other no adding/removing and if you need to pull the local clients Linq's is a better option

also general data 10010 has a subtype of (case 102) to spawn clients/mobs/npc's and its being done way better than that try to figure it out :)

Good luck .
06/07/2011 10:53 Santa#3
Why would Linq be better for pulling players?
06/07/2011 12:46 pro4never#4
You can use ling to just say

Pull from map where dist < 18 and !inLocals

It's what the example I showed you used. I could write out a dumbed down version if you really wanted.
06/08/2011 08:04 Santa#5
Quote:
Originally Posted by pro4never View Post
You can use ling to just say

Pull from map where dist < 18 and !inLocals

It's what the example I showed you used. I could write out a dumbed down version if you really wanted.
The only benefit to it is that it looks organized cause its not any faster, depending on the number of entries its actually slower :S
06/08/2011 10:14 Korvacs#6
In all cases LINQ is slower unless your are using it in conjunction with a database to fill datasets and things.

A few things to note, you need to write your in the same order for both sends in the spawning code, the way you have it written now (this is based on not seeing the rest of your code) you could have it happen that the client attempts to add a target player, the console tells you that its happened, but then a silent exception is thrown somewhere and it doesnt complete, so ideally you would want that to be shown last like in your other handling.
06/09/2011 08:22 Santa#7
Quote:
Originally Posted by Korvacs View Post
In all cases LINQ is slower unless your are using it in conjunction with a database to fill datasets and things.

A few things to note, you need to write your in the same order for both sends in the spawning code, the way you have it written now (this is based on not seeing the rest of your code) you could have it happen that the client attempts to add a target player, the console tells you that its happened, but then a silent exception is thrown somewhere and it doesnt complete, so ideally you would want that to be shown last like in your other handling.
Yeah, just after i posted this i switch that up and put a try/catch to see if anything was thrown, but there wasn't anything. I decided to try something, It worked. And I have no idea why/how. Could you maybe explain. I changed my original toScreen method to the following.
PHP Code:
        public void toScreen(byte[] DataClient S)
        {
            try
            {
                foreach (
KeyValuePair<uintClientClient in S.LocalClients)
                    if (
S.UID != Client.Value.UID)
                        
Client.Value.Send(Data);
            }
            catch { }
        } 
06/09/2011 14:57 nTL3fTy#8
Quote:
Originally Posted by StarBucks View Post
Yeah, just after i posted this i switch that up and put a try/catch to see if anything was thrown, but there wasn't anything. I decided to try something, It worked. And I have no idea why/how. Could you maybe explain. I changed my original toScreen method to the following.
PHP Code:
        public void toScreen(byte[] DataClient S)
        {
            try
            {
                foreach (
KeyValuePair<uintClientClient in S.LocalClients)
                    if (
S.UID != Client.Value.UID)
                        
Client.Value.Send(Data);
            }
            catch { }
        } 
From looking at the method, I'm assuming your encryption occurs within the Send method. If that's the case, and you aren't duplicating that buffer, it's probably being encrypted once and sent, then encrypted again and sent again, etc. That results in a malformed packet being sent to the client.
06/10/2011 00:24 Santa#9
Quote:
Originally Posted by nTL3fTy View Post
From looking at the method, I'm assuming your encryption occurs within the Send method. If that's the case, and you aren't duplicating that buffer, it's probably being encrypted once and sent, then encrypted again and sent again, etc. That results in a malformed packet being sent to the client.
Thats interesting. Thanks for the tip.
06/10/2011 07:20 samehvan#10
have another look at this line

if (!C.LocalClients.ContainsKey(C.UID))

i am sure it needs to be

if (!C.LocalClients.ContainsKey(G.UID))
06/10/2011 13:46 nTL3fTy#11
Quote:
Originally Posted by StarBucks View Post
Thats interesting. Thanks for the tip.
Here's a simplistic example of what I described:
Code:
class Program
{
    private static readonly Action<byte[]> EncryptFunc = buf =>
    {
        for (var i = 0; i < buf.Length; i++)
        {
            buf[i] *= 10;
        }
    };

    static void Main(string[] args)
    {
        // create our "packet"
        var buffer = new byte[] { 1, 2, 3, 4, 5 };

        // simulates sending to multiple clients
        for (var i = 0; i < 5; i++)
        {
            Send(buffer);
        }

        Console.ReadLine();
    }

    static void Send(byte[] buffer)
    {
        EncryptFunc(buffer);
        foreach (var t in buffer) Console.Write("{0}\t", t);
        Console.WriteLine();
    }
}
Which results in:
Code:
10      20      30      40      50
100     200     44      144     244
232     208     184     160     136
16      32      48      64      80
160     64      224     128     32
06/10/2011 23:06 Santa#12
Wow. Thats amazing. I would have NEVER thought of that to ever be a problem. Thanks.