package com.zombie.game.server; import com.sun.net.httpserver.*; import com.google.gson.Gson; import com.zombie.game.model.MapData; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.OutputStream; import java.net.InetSocketAddress; import java.util.List; import java.util.Map; /** * 地图设计器 HTTP API 服务器 * * 提供REST API用于地图的保存、加载和列表查询 */ public class MapDesignerApiServer { private static final Logger logger = LoggerFactory.getLogger(MapDesignerApiServer.class); private static final int PORT = 8081; private static final String MAPS_ENDPOINT = "/api/maps"; private static final String MAP_ID_ENDPOINT = "/api/maps/"; private final HttpServer server; private final Gson gson; private final MapStorage mapStorage; public MapDesignerApiServer(MapStorage mapStorage) throws IOException { this.mapStorage = mapStorage; this.gson = new Gson(); this.server = HttpServer.create(new InetSocketAddress(PORT), 0); } public void start() { server.createContext(MAPS_ENDPOINT, new MapsHandler()); server.createContext(MAP_ID_ENDPOINT, new MapIdHandler()); server.setExecutor(null); server.start(); logger.info("Map Designer API Server started on port {}", PORT); } public void stop() { server.stop(0); logger.info("Map Designer API Server stopped"); } private class MapsHandler implements HttpHandler { @Override public void handle(HttpExchange exchange) throws IOException { if ("OPTIONS".equals(exchange.getRequestMethod())) { sendResponse(exchange, 200, "{\"ok\":true}"); return; } String method = exchange.getRequestMethod(); try { switch (method) { case "GET": handleList(exchange); break; case "POST": handleSave(exchange); break; default: sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); } } catch (Exception e) { logger.error("Error handling request", e); sendResponse(exchange, 500, "{\"error\":\"" + e.getMessage() + "\"}"); } } } private class MapIdHandler implements HttpHandler { @Override public void handle(HttpExchange exchange) throws IOException { String path = exchange.getRequestURI().getPath(); String id = path.substring(MAP_ID_ENDPOINT.length()); if ("OPTIONS".equals(exchange.getRequestMethod())) { sendResponse(exchange, 200, "{\"ok\":true}"); return; } String method = exchange.getRequestMethod(); try { switch (method) { case "GET": handleLoad(exchange, id); break; case "DELETE": handleDelete(exchange, id); break; default: sendResponse(exchange, 405, "{\"error\":\"Method not allowed\"}"); } } catch (Exception e) { logger.error("Error handling request", e); sendResponse(exchange, 500, "{\"error\":\"" + e.getMessage() + "\"}"); } } } private void handleList(HttpExchange exchange) throws IOException { List maps = mapStorage.listMaps(); String response = gson.toJson(Map.of("maps", maps)); sendJson(exchange, 200, response); } private void handleSave(HttpExchange exchange) throws IOException { java.io.Reader reader = new java.io.InputStreamReader(exchange.getRequestBody()); MapData mapData = gson.fromJson(reader, MapData.class); MapData saved = mapStorage.save(mapData); sendJson(exchange, 201, gson.toJson(Map.of("id", saved.getId(), "ok", true))); } private void handleLoad(HttpExchange exchange, String id) throws IOException { MapData mapData = mapStorage.load(id); if (mapData == null) { sendResponse(exchange, 404, "{\"error\":\"Map not found\"}"); } else { sendJson(exchange, 200, gson.toJson(mapData)); } } private void handleDelete(HttpExchange exchange, String id) throws IOException { boolean deleted = mapStorage.delete(id); if (deleted) { sendResponse(exchange, 200, "{\"ok\":true}"); } else { sendResponse(exchange, 404, "{\"error\":\"Map not found\"}"); } } private void sendJson(HttpExchange exchange, int statusCode, String json) throws IOException { exchange.getResponseHeaders().set("Content-Type", "application/json"); exchange.getResponseHeaders().set("Access-Control-Allow-Origin", "*"); exchange.getResponseHeaders().set("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS"); exchange.getResponseHeaders().set("Access-Control-Allow-Headers", "Content-Type"); byte[] bytes = json.getBytes("UTF-8"); exchange.sendResponseHeaders(statusCode, bytes.length); try (OutputStream os = exchange.getResponseBody()) { os.write(bytes); } } private void sendResponse(HttpExchange exchange, int statusCode, String response) throws IOException { byte[] bytes = response.getBytes("UTF-8"); exchange.getResponseHeaders().set("Content-Type", "application/json"); exchange.getResponseHeaders().set("Access-Control-Allow-Origin", "*"); exchange.sendResponseHeaders(statusCode, bytes.length); try (OutputStream os = exchange.getResponseBody()) { os.write(bytes); } } }