我有一个小问题。我是多人游戏编程新手。我的问题是,只发送一个数据包会被发送到最后一个客户端。它可以轻松支持2名玩家,但是3名玩家并不能完全发挥作用。登录和断开数据包有效,但移动数据包无效。你能告诉我我失踪或需要删除的东西吗?
客户端:
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());
}
}
服务器:
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);
}
}
编辑:所以我发现我需要将Server类中的addPlayer方法更改为:
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());
}
}
答案 0 :(得分:1)
添加播放器时,会覆盖所有现有播放器的IP和端口
// 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);
}
}
}