package com.framsticks.net.client3D; import java.io.IOException; import java.util.ArrayList; import pl.vorg.mowa.core.graphics.FloatVertexAttrib; import pl.vorg.mowa.core.graphics.Geometry; import pl.vorg.mowa.core.graphics.GeometryUtils; import pl.vorg.mowa.core.graphics.IndexBuffer; import pl.vorg.mowa.core.graphics.PrimitiveType; import pl.vorg.mowa.core.graphics.VertexStream; import com.framsticks.net.client3D.Creature.ModelType; //TODO: ACT przejscie klienta na eventHandlery (simulation start/stop, creatures, error) /** * Framstick network client. It sends requests to the server and interprets the * responses. * * @author vorg */ public class Client { private Communication comm; public Client() { } public void send(String request) { try { printResponse(sendRequest(request)); } catch (Exception e) { Log.getInstance().log("err", e.toString()); } } private ArrayList sendRequest(String request) throws IOException, CommunicationErrorException { if (comm == null) { Log.getInstance().log("wrn", "Sending request failed. You are not connected!"); return new ArrayList(); } comm.sendMessage(request); ArrayList respond = null; try { respond = comm.readMessage(); } catch (InterruptedException e) { Log.getInstance().log("err", e.getMessage()); return new ArrayList(); } return respond; } private void printResponse(ArrayList response) { if (response == null) { Log.getInstance().log("err", "Response is null"); return; } for (int i = 0; i < response.size(); i++) { Log.getInstance().log("<<<", response.get(i)); } } /** * Inits connection with the mock server. */ public void initConnectionMock() { comm = new CommunicationMock(); Log.getInstance().log("dbg", "Client.init"); try { Log.getInstance().log("dbg", "Connecting to mock"); comm.connect("127.0.0.1", 9009); } catch (Exception e) { e.printStackTrace(); } } public void initConnection(String host, int port) { comm = new Communication(); Log.getInstance().log("dbg", "Client.init"); try { Log.getInstance().log("dbg", "Connecting to " + host + ":" + port); comm.connect(host, port); } catch (Exception e) { e.printStackTrace(); } } public void closeConnection() { try { if (comm != null) { comm.disconnect(); comm = null; } } catch (IOException e) { e.printStackTrace(); } } public Creature[] readCreatures() throws IOException, CommunicationErrorException { return readCreatures(-1, -1, true); } public Creature[] readCreatures(int groupNo, int creatureNo, boolean neurons) throws IOException, CommunicationErrorException { ArrayList creatures = new ArrayList(); String request; String creatureFields = neurons ? "name,parts{x,y,z},mechparts{x,y,z},joints{p1,p2},neurodefs{p,j,d}" : "name,parts{x,y,z},mechparts{x,y,z},joints{p1,p2}"; if (groupNo == -1 || creatureNo == -1) { request = "get /simulator/populations/groups/+/creatures/+/(" + creatureFields + ")"; } else { request = "get /simulator/populations/groups/" + Integer.toString(groupNo) + "/creatures/" + Integer.toString(creatureNo) + "/(" + creatureFields + ")"; } String line = null; ArrayList response = null; response = sendRequest(request); printResponse(response); final int INIT = 0; final int PARTS = 1; final int MECHPARTS = 2; final int JOINTS = 3; final int NEURODEFS = 4; int mode = INIT; Creature creature = null; ArrayList parts = null; ArrayList mechParts = null; ArrayList joints = null; ArrayList neurodefs = null; float[] part = new float[3]; float[] mechPart = new float[3]; int[] joint = new int[2]; NeuroDef ndef = new NeuroDef(); for (int k = 0; k < response.size(); ++k) { line = response.get(k).toString(); if (line.startsWith("file")) { String groupsStr = "groups/"; int groupBegin = line.indexOf(groupsStr) + groupsStr.length(); int groupEnd = line.indexOf("/", groupBegin); if (groupBegin < 0 || groupEnd < 0) { System.out.println(line); System.out.println("groupBegin=" + groupBegin + "; groupEnd=" + groupEnd); System.out.println("request=" + request); System.out.println("groupNo=" + groupNo + "; creatureNo=" + creatureNo); } int group = Integer.parseInt(line.substring(groupBegin, groupEnd)); String creaturesStr = "creatures/"; int creatureIndexBegin = line.indexOf(creaturesStr) + creaturesStr.length(); int creatureIndexEnd = line.indexOf("/", creatureIndexBegin); int creatureIndex = Integer.parseInt(line.substring( creatureIndexBegin, creatureIndexEnd)); creature = null; for (Creature c : creatures) { if ((c.getGroup() == group) && (c.getIndex() == creatureIndex)) { creature = c; break; } } if (creature == null) { creature = new Creature("", group, creatureIndex); creatures.add(creature); } if (line.indexOf("/parts") > -1) { mode = PARTS; parts = new ArrayList(); } else if (line.indexOf("/mechparts") > -1) { mode = MECHPARTS; mechParts = new ArrayList(); } else if (line.indexOf("/joints") > -1) { mode = JOINTS; joints = new ArrayList(); } else if (line.indexOf("/neurodefs") > -1) { mode = NEURODEFS; neurodefs = new ArrayList(); } } else if (line.startsWith("x")) { float value = Float.parseFloat(line .substring(line.indexOf(":") + 1)); if (mode == PARTS) part[0] = value; else if (mode == MECHPARTS) mechPart[0] = value; } else if (line.startsWith("y")) { float value = Float.parseFloat(line .substring(line.indexOf(":") + 1)); if (mode == PARTS) part[2] = value; // y and z swap else if (mode == MECHPARTS) mechPart[2] = value; // y and z swap } else if (line.startsWith("z")) { float value = Float.parseFloat(line .substring(line.indexOf(":") + 1)); if (mode == PARTS) { part[1] = value; // z and y swap parts.add(part); part = new float[3]; } else if (mode == MECHPARTS) { mechPart[1] = value; // z and y swap mechParts.add(mechPart); mechPart = new float[3]; } } else if (line.startsWith("p1")) { int p1 = Integer .parseInt(line.substring(line.indexOf(":") + 1)); joint[0] = p1; } else if (line.startsWith("p2")) { int p2 = Integer .parseInt(line.substring(line.indexOf(":") + 1)); joint[1] = p2; joints.add(joint); joint = new int[2]; } else if ((mode == NEURODEFS) && (line.startsWith("p:"))) { int index = Integer.parseInt(line .substring(line.indexOf(":") + 1)); if (index >= 0) { ndef.locationIndex = index; ndef.locationType = NeuroDef.LocationType.Part; } } else if ((mode == NEURODEFS) && (line.startsWith("j:"))) { int index = Integer.parseInt(line .substring(line.indexOf(":") + 1)); if (index >= 0) { ndef.locationIndex = index; ndef.locationType = NeuroDef.LocationType.Joint; } } else if ((mode == NEURODEFS) && (line.startsWith("d:"))) { ndef.def = line.substring(2); neurodefs.add(ndef); ndef = new NeuroDef(); } else if (line.startsWith("eof")) { if (mode == PARTS) { creature.setParts(parts.toArray(new float[][] {}), Creature.ModelType.Parts); } else if (mode == MECHPARTS) { creature.setParts((mechParts.toArray(new float[][] {})), Creature.ModelType.MechParts); } else if (mode == JOINTS) { creature.setJoints(joints.toArray(new int[][] {})); } else if (mode == NEURODEFS) { creature.setNeuroDefs(neurodefs.toArray(new NeuroDef[] {})); } } } Log.getInstance().log("dbg", "" + creatures.size() + " creatures loaded"); ArrayList invalidCreatures = new ArrayList(); for (Creature c : creatures) { if ((c.getJoints() == null) || (c.getParts(ModelType.Parts) == null) || (c.getParts(ModelType.MechParts) == null)) { invalidCreatures.add(c); Log.getInstance().log("wrn", "Invalid creature found"); } } for (Creature c : invalidCreatures) { creatures.remove(c); } invalidCreatures.clear(); return creatures.toArray(new Creature[] {}); } public World readWorld() throws IOException, CommunicationErrorException { final int INIT = 0; final int POINTS = 1; final int FACES = 2; World world = new World(); String line = null; String request = "get /simulator/world wrldbnd,wrldwat,faces"; ArrayList response = null; response = sendRequest(request); printResponse(response); ArrayList points = new ArrayList(); ArrayList faces = new ArrayList(); PrimitiveType primitiveType = PrimitiveType.None; PrimitiveType facePrimitiveType; int mode = INIT; for (int k = 0; k < response.size(); ++k) { line = response.get(k); if (line.startsWith("wrldbnd")) { world.setBoundaries(Integer.parseInt(line.substring(line .indexOf(":") + 1))); continue; } else if (line.startsWith("wrldwat")) { world.setWaterLevel(Float.parseFloat(line.substring(line .indexOf(":") + 1))); continue; } else if (line.trim().equals("p")) { mode = POINTS; continue; } else if (line.trim().equals("f")) { mode = FACES; continue; } else if (line.trim().equals("~")) { break; } if (mode == POINTS) { String[] tokens = line.split(" "); points.add(Float.parseFloat(tokens[0])); points.add(Float.parseFloat(tokens[2])); // y and z swap points.add(Float.parseFloat(tokens[1])); // z and y swap } else if (mode == FACES) { String[] tokens = line.split(" "); if (tokens.length == 3) facePrimitiveType = PrimitiveType.Triangles; else if (tokens.length == 4) facePrimitiveType = PrimitiveType.Quads; else facePrimitiveType = PrimitiveType.None; if (primitiveType == PrimitiveType.None) { primitiveType = facePrimitiveType; } else if (primitiveType != facePrimitiveType) { Log.getInstance().log( "err", "Unsupported terrain type (" + primitiveType + "!=" + primitiveType + ")"); return world; } for (String token : tokens) { faces.add(Integer.parseInt(token)); } } } float[] positions = new float[points.size()]; for (int i = 0; i < positions.length; i++) { positions[i] = points.get(i); } int[] indices = new int[faces.size()]; for (int i = 0; i < indices.length; i++) { indices[i] = faces.get(i); } Geometry geometry = new Geometry(); VertexStream vs = new VertexStream(); geometry.setVertexStream(vs); geometry.setPrimitiveType(primitiveType); IndexBuffer ib = new IndexBuffer(); ib.setBuffer(indices); vs.setIndexBuffer(ib); FloatVertexAttrib posAttrib = new FloatVertexAttrib("pos"); posAttrib.setBuffer(positions); vs.addAttrib(posAttrib); geometry.updateBoundingBox(); GeometryUtils.generateNormals(geometry); world.setGeometry(geometry); return world; } public Boolean isConnected() { return comm.isConnected(); } }