TheKindOfGoodProgrammer TheKindOfGoodProgrammer - 7 months ago 15
Java Question

Only the last client is getting data sent

I have a small problem. I am new to multiplayer programming. My problem is that one packet that gets sent only gets sent to the last client. It can support 2 players easily, but 3 players doesn't fully work. The login and disconnect packets work, but not the move packet. Can you tell me what I'm missing or need to remove?

Client:

public class Client extends Thread{
private InetAddress ip;
private DatagramSocket dp;

public Client(String ia) {
try {
dp = new DatagramSocket();
ip = InetAddress.getByName(ia);
} catch (SocketException | UnknownHostException e) {
e.printStackTrace();
}
}

@Override
public void run() {
while (true) {
byte[] rdata = new byte[1024];
DatagramPacket dg = new DatagramPacket(rdata, rdata.length);
try {
dp.receive(dg);
} catch (IOException ex) {
ex.printStackTrace();
}
byte[] data = dg.getData();
String msg = new String(data).trim();
switch (Packet.find(msg.substring(0, 2))) {
default:
case INVALID:
break;
case LOGIN:
Login00 l = new Login00(data);
if (getPlayer(l.getUser()) == null) {
Main.visible.add(new MPlayer(100, 100, l.getUser(), dg.getAddress(), dg.getPort(), false));
System.out.println("("+dg.getAddress().getHostAddress()+":"+dg.getPort()+") > " + msg.substring(2) + " has joined!");
}
break;
case DISCONNECT:
Dis01 d = new Dis01(data);
Main.visible.remove(getPlayer(d.getUser()));
System.out.println(("+dg.getAddress().getHostAddress()+":"+dg.getPort()+") > " + d.getUser() + " has left!");
break;
case MOVE:
Move02 m = new Move02(data);
handleMove(m);
break;
}
}
}

public void sendData(byte[] data) {
try {
DatagramPacket dg = new DatagramPacket(data, data.length, ip, 1111);
dp.send(dg);
} catch (Exception ex) {
//ex.printStackTrace();
}
}



public MPlayer getPlayer(String u) {
for (Player p : Main.visible) {
if (p.user.equals(u)) {
return (MPlayer) p;
}
}
return null;
}

public int getPlayerId(String u) {
int dex = 0;
for (Player p : Main.visible) {
if (p.user.equals(u)) {
break;
}
dex++;
}
return dex;
}

private void handleMove(Move02 m) {
int dex = getPlayerId(m.getUser());
Main.visible.get(dex).moveTo(m.getX(), m.getY(), m.getUser());
}
}


Server:

public class Server extends Thread{
private DatagramSocket dp;
List<MPlayer> cplayers = new ArrayList<>();

public Server() {
try {
dp = new DatagramSocket(1111);
} catch (SocketException e) {
e.printStackTrace();
}
}

@Override
public void run() {
while (true) {
byte[] rdata = new byte[1024];
DatagramPacket dg = new DatagramPacket(rdata, rdata.length);
try {
dp.receive(dg);
} catch (IOException ex) {
}
pp(dg.getData(), dg.getAddress(), dg.getPort());
}
}

public void sendData(byte[] data, InetAddress i, int port) {
try {
DatagramPacket dg = new DatagramPacket(data, data.length, i, port);
dp.send(dg);
} catch (Exception ex) {
}
}

public void sendDataAll(byte[] data) {
for (MPlayer p : cplayers) {
sendData(data, p.ip, p.port);
}
}

private void pp(byte[] data, InetAddress address, int port) {
String msg = new String(data).trim();
types t = Packet.find(Integer.parseInt(msg.substring(0, 2)));
Packet pp;
switch (t) {
default:
case INVALID:
break;
case LOGIN:
pp = new Login00(data);
System.out.println("("+address.getHostAddress()+":"+port+") > " + ((Login00) pp).getUser() + " has joined!");
MPlayer pl = new MPlayer(100, 100, ((Login00) pp).getUser(), address, port, false);
addPlayer(pl, (Login00) pp);
break;
case DISCONNECT:
pp = new Dis01(data);
System.out.println("("+address.getHostAddress()+":"+port+") > " + ((Dis01) pp).getUser() + " has left!");
removePlayer((Dis01) pp);
break;
case MOVE:
pp = new Move02(data);
handleMove((Move02) pp);
break;
}
}

public void addPlayer(MPlayer pl, Login00 l) {
boolean ac = false;
for (MPlayer p : cplayers) {
p.ip = pl.ip;
p.port = pl.port;
if (Main.username.equalsIgnoreCase(l.getUser())) {
ac = true;
} else {
sendDataAll(l.getData());
Login00 ll = new Login00(p.user);
sendData(ll.getData(), p.ip, p.port);
}
}
if (true) {
cplayers.add(pl);
Main.visible.add(pl);
}

}

public void removePlayer(Dis01 dis) {
Main.visible.remove(getPlayer(dis.getUser()));
cplayers.remove(getPlayer(dis.getUser()));
dis.write(this);
}

public MPlayer getPlayer(String u) {
for (MPlayer p : cplayers) {
if (p.user.equals(u)) {
return p;
}
}
return null;
}

public int getPlayerId(String u) {
int dex = 0;
for (Player p : Main.visible) {
if (p.user.equals(u)) {
break;
}
dex++;
}
return dex;
}

public void handleMove(Move02 m) {
Integer dex = getPlayerId(m.getUser());
Main.visible.get(dex).moveTo(m.getX(), m.getY(), m.getUser());
m.write(this);
}
}


EDIT: So I figured out that i need to change the addPlayer method in the Server class to:

public void addPlayer(MPlayer pl, Login00 l) {
cplayers.add(pl);
Main.visible.add(pl);
for (MPlayer p : cplayers) {
sendDataAll(l.getData());
Login00 ll = new Login00(p.user);
sendDataAll(ll.getData());
}
}

Answer

When you add a player, you overwrite all existing player ip's and port's

// Server code
public void addPlayer(MPlayer pl, Login00 l) {
    boolean ac = false;
    for (MPlayer p : cplayers) {
        // At this point, you overwrite all existing player data
        p.ip = pl.ip; // overwrites existing player
        p.port = pl.port; // overwrites existing player
        if (Main.username.equalsIgnoreCase(l.getUser())) {
            ac = true;
        } else {
            sendDataAll(l.getData());
            Login00 ll = new Login00(p.user);
            sendData(ll.getData(), p.ip, p.port);
        }
    }
}
Comments