package uno.mloluyu.network; import com.badlogic.gdx.Gdx; import java.util.HashMap; import java.util.Map; public class NetworkManager { private static NetworkManager instance; private ConnectServer server; private ConnectClient client; private boolean isHost = false; private String localPlayerId; private String localCharacter; private final Map playerPositions = new HashMap<>(); private final Map playerCharacters = new HashMap<>(); // 存储远程玩家的攻击类型(attackType) private final Map playerAttacks = new HashMap<>(); // 伤害事件:targetId -> 累积伤害(本帧内可能多次) private final Map damageEvents = new HashMap<>(); private final Map respawnEvents = new HashMap<>(); public static NetworkManager getInstance() { if (instance == null) { instance = new NetworkManager(); } return instance; } public void setLocalPlayerId(String id) { this.localPlayerId = id; } public String getLocalPlayerId() { return localPlayerId; } public void createRoom() {// 创建房间 isHost = true; server = new ConnectServer(11455); new Thread(server).start(); Gdx.app.log("Network", "房主模式:服务器已启动"); } public void joinRoom(String ip) {// 加入房间 isHost = false; client = new ConnectClient(ip, 11455); Gdx.app.log("Network", "客户端模式:连接到房主 " + ip); } public void sendPosition(float x, float y) {// 发送位置消息 String msg = "POS:" + localPlayerId + "," + x + "," + y; if (isHost && server != null) { server.broadcastToOthers(null, msg); receiveMessage(msg); } else if (client != null) { client.sendMessage(msg); } } public void sendCharacterSelection(String character) {// 发送角色选择消息 this.localCharacter = character; String msg = "SELECT:" + localPlayerId + "," + character; if (isHost && server != null) { server.broadcastToOthers(null, msg); receiveMessage(msg); } else if (client != null) { client.sendMessage(msg); } } public void receiveMessage(String message) {// 解析消息 if (message.startsWith("POS:")) { String[] parts = message.substring(4).split(","); if (parts.length == 3) { String playerId = parts[0]; try { float x = Float.parseFloat(parts[1]); float y = Float.parseFloat(parts[2]); playerPositions.put(playerId, new float[] { x, y }); } catch (NumberFormatException e) { Gdx.app.error("Network", "位置解析失败: " + message); } } else { Gdx.app.error("Network", "位置消息格式错误: " + message); } } else if (message.startsWith("SELECT:")) { String[] parts = message.substring(7).split(","); if (parts.length == 2) { String playerId = parts[0]; String character = parts[1]; playerCharacters.put(playerId, character); Gdx.app.log("Network", "角色选择: " + playerId + " -> " + character); } else { Gdx.app.error("Network", "角色选择消息格式错误: " + message); } } else if (message.equals("READY")) { Gdx.app.log("Network", "收到准备信号"); } else if (message.startsWith("ATTACK:")) { String[] parts = message.substring(7).split(","); if (parts.length == 2) { String playerId = parts[0]; String attackType = parts[1]; playerAttacks.put(playerId, attackType); Gdx.app.log("Network", "攻击同步: " + playerId + " -> " + attackType); } else { Gdx.app.error("Network", "攻击消息格式错误: " + message); } } else if (message.startsWith("DAMAGE:")) { // DAMAGE:targetId,amount,(dir) String[] parts = message.substring(7).split(","); if (parts.length >= 2) { String targetId = parts[0]; try { int amount = Integer.parseInt(parts[1]); damageEvents.merge(targetId, amount, Integer::sum); // 第三个参数方向目前不存储,只为击退逻辑可扩展 Gdx.app.log("Network", "收到伤害: " + targetId + " -" + amount + (parts.length >= 3 ? (" dir=" + parts[2]) : "")); } catch (NumberFormatException e) { Gdx.app.error("Network", "伤害数值解析失败: " + message); } } else { Gdx.app.error("Network", "伤害消息格式错误: " + message); } } else if (message.startsWith("RESPAWN:")) { // RESPAWN:playerId,x,y String[] parts = message.substring(8).split(","); if (parts.length == 3) { try { String pid = parts[0]; float x = Float.parseFloat(parts[1]); float y = Float.parseFloat(parts[2]); respawnEvents.put(pid, new float[] { x, y }); Gdx.app.log("Network", "收到重生: " + pid + " -> (" + x + "," + y + ")"); } catch (NumberFormatException e) { Gdx.app.error("Network", "重生坐标解析失败: " + message); } } else { Gdx.app.error("Network", "重生消息格式错误: " + message); } } else { Gdx.app.log("Network", "未知消息类型: " + message); } } public Map getPlayerPositions() { return playerPositions; } /** * 获取远程玩家的未处理攻击类型映射 */ public Map getPlayerAttacks() { return playerAttacks; } /** * 发送攻击消息给其他玩家 */ public void sendAttack(String attackType) { if (localPlayerId == null) return; String msg = "ATTACK:" + localPlayerId + "," + attackType; Gdx.app.log("Network", "发送攻击消息: " + msg); if (isHost && server != null) { server.broadcastToOthers(null, msg); receiveMessage(msg); } else if (client != null) { client.sendMessage(msg); } } public Map getPlayerCharacters() { return playerCharacters; } public Map getDamageEvents() { return damageEvents; } public void sendDamage(String targetId, int amount) { String msg = "DAMAGE:" + targetId + "," + amount; // 不含方向 if (isHost && server != null) { server.broadcastToOthers(null, msg); receiveMessage(msg); // 本地也应用 } else if (client != null) { client.sendMessage(msg); } } public void sendRespawn(String playerId, float x, float y) { String msg = "RESPAWN:" + playerId + "," + x + "," + y; if (isHost && server != null) { server.broadcastToOthers(null, msg); receiveMessage(msg); } } public Map getRespawnEvents() { return respawnEvents; } public boolean isHost() { return isHost; } public boolean isConnected() { return server != null || client != null; } public void disconnect() { if (server != null) { server.dispose(); server = null; } if (client != null) { client.disconnect(); client = null; } playerPositions.clear(); playerCharacters.clear(); Gdx.app.log("Network", "已断开连接"); } }