3 import com.jme3.app.SimpleApplication;
4 import com.jme3.bullet.BulletAppState;
5 import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
6 import com.jme3.bullet.collision.shapes.CollisionShape;
7 import com.jme3.bullet.control.CharacterControl;
8 import com.jme3.bullet.control.RigidBodyControl;
9 import com.jme3.bullet.util.CollisionShapeFactory;
10 import com.jme3.input.KeyInput;
11 import com.jme3.input.controls.ActionListener;
12 import com.jme3.input.controls.KeyTrigger;
13 import com.jme3.light.AmbientLight;
14 import com.jme3.light.DirectionalLight;
15 import com.jme3.material.Material;
16 import com.jme3.math.ColorRGBA;
17 import com.jme3.math.FastMath;
18 import com.jme3.math.Vector3f;
19 import com.jme3.scene.Geometry;
20 import com.jme3.scene.Node;
21 import com.jme3.scene.Spatial;
22 import com.jme3.scene.shape.Box;
23 import com.jme3.system.AppSettings;
25 import java.io.FileNotFoundException;
26 import java.io.IOException;
27 import java.net.InetSocketAddress;
28 import java.nio.ByteBuffer;
29 import java.nio.channels.SocketChannel;
30 import java.util.HashMap;
31 import java.util.HashSet;
32 import java.util.Scanner;
33 import java.util.logging.Level;
34 import java.util.logging.Logger;
35 import forest.common.*;
36 import java.io.DataInputStream;
37 import java.io.DataOutputStream;
38 import java.net.DatagramPacket;
39 import java.net.DatagramSocket;
40 import java.net.InetAddress;
41 import java.net.Socket;
42 import java.util.ArrayList;
48 public class Main extends SimpleApplication
49 implements ActionListener {
51 private final boolean LET_ME_FLY =
false;
53 private Spatial sceneModel;
54 private BulletAppState bulletAppState;
55 private RigidBodyControl landscape;
56 private CharacterControl player;
57 private Vector3f walkDirection =
new Vector3f();
58 private static int worldSize;
59 private boolean left =
false, right =
false, up =
false, down =
false;
60 private int comtree = 1001;
61 private static String hostname;
62 private static String mapfile;
64 public static void main(String[] args) {
67 AppSettings newSetting =
new AppSettings(
true);
68 newSetting.setFrameRate(60);
69 newSetting.setTitle(
"Forest Overlay Network");
70 app.setSettings(newSetting);
72 app.setShowSettings(
false);
73 if (args.length != 5) {
74 System.out.println(
"usage: java -jar MyGame.jar hostname mapfile gridSize myIpAdr [tcp|udp]");
79 worldSize = Integer.parseInt(args[2]);
80 String myIpAdrStr = args[3];
81 myIpAdr = Forest.ipAddress(myIpAdrStr);
82 needCliProxy = args[4].equals(
"tcp");
83 java.util.logging.Logger.getLogger(
"").setLevel(Level.SEVERE);
87 public void simpleInitApp() {
89 guiNode.detachAllChildren();
92 bulletAppState =
new BulletAppState();
93 stateManager.attach(bulletAppState);
95 viewPort.setBackgroundColor(
new ColorRGBA(0.7f, 0.8f, 1f, 1f));
96 flyCam.setMoveSpeed(100);
102 Box b =
new Box(Vector3f.ZERO, 512f, 1.0f, 512f);
103 Geometry g =
new Geometry(
"Box", b);
104 g.setLocalTranslation(0,-.5f,0);
105 Material mat =
new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md");
106 mat.setColor(
"Color",
new ColorRGBA(175f/255, 194f/255, 170f/255, 1f));
109 rootNode.attachChild(g);
110 RigidBodyControl wallControl =
new RigidBodyControl(0);
111 g.addControl(wallControl);
112 bulletAppState.getPhysicsSpace().add(wallControl);
125 CapsuleCollisionShape capsuleShape =
new CapsuleCollisionShape(13f, 6f, 1);
126 player =
new CharacterControl(capsuleShape, 0.05f);
127 player.setJumpSpeed(20);
128 player.setFallSpeed(60);
129 if(LET_ME_FLY) player.setGravity(0);
130 else player.setGravity(100);
131 player.setPhysicsLocation(
new Vector3f(0, 10, 0));
138 bulletAppState.getPhysicsSpace().add(player);
141 System.out.println(
"Press enter once you've tunnelled...");
142 (
new Scanner(System.in)).nextLine();
145 chan = SocketChannel.open(
new InetSocketAddress(hostname, CP_PORT));
146 chan.configureBlocking(
false);
147 }
catch (IOException ex) {
148 System.out.println(
"Couldn't open channel to Client Proxy");
149 System.out.println(ex);
152 recentIds =
new HashSet<Integer>();
155 mySubs =
new HashSet<Integer>();
156 waiting4comtCtl =
true;
157 buf = ByteBuffer.allocate(1500);
158 now = nextTime = (int) System.nanoTime() / 1000000;
159 status =
new HashMap<Integer, AvatarGraphic>();
164 private HashMap<Integer, AvatarGraphic> status;
165 private HashSet<Integer> recentIds;
166 private int idCounter;
167 private SocketChannel chan;
168 private DatagramSocket udpSock;
169 private final int CM_PORT = 30140;
170 private final int CP_PORT = 30182;
171 private ByteBuffer buf;
172 private String uname =
"user";
173 private String pword =
"pass";
176 private int rtrIpAdr;
180 private final int GRID = 10000;
181 private final int MAXNEAR = 1000;
182 private final int STATUS_REPORT = 1;
183 private final int UPDATE_PERIOD = 50;
184 private HashSet<Integer>[] visSet;
185 private static int myIpAdr;
186 private HashSet<Integer> mySubs;
187 private HashMap<Integer, Integer> nearAvatars;
188 private HashMap<Integer, Integer> visibleAvatars;
190 private int numVisible;
191 private boolean waiting4comtCtl;
194 private int nextTime;
195 private static boolean needCliProxy;
198 private int cpForestPort;
201 private void login() {
202 System.out.println(
"got to login");
203 Socket cm_sock = null;
205 cm_sock =
new Socket(hostname, CM_PORT);
206 String portString = String.valueOf(cm_sock.getPort());
207 String strBuf = uname +
" " + pword +
" " + portString;
211 strBuf +=
" noproxy";
213 System.out.println(strBuf);
214 DataOutputStream dos =
new DataOutputStream(cm_sock.getOutputStream());
215 dos.writeInt(strBuf.length());
216 dos.writeBytes(strBuf);
217 DataInputStream dis =
new DataInputStream(cm_sock.getInputStream());
218 rtrAdr = dis.readInt();
220 System.out.println(
"Couldn't connect, negative reply");
224 myAdr = dis.readInt();
225 cpIpAdr = dis.readInt();
226 cpPort = dis.readInt();
227 cpForestPort = dis.readInt();
228 ccAdr = dis.readInt();
229 System.out.println(
"assigned client proxy ip " +
230 Forest.ip2string(cpIpAdr));
231 System.out.println(
"assigned forest address " +
232 Forest.fAdr2string(myAdr));
233 System.out.println(
"assigned client proxy port " + cpPort);
234 System.out.println(
"router address " + Forest.fAdr2string(rtrAdr));
235 System.out.println(
"comtree controller address " +
236 Forest.fAdr2string(ccAdr));
239 myAdr = dis.readInt();
240 rtrIpAdr = dis.readInt();
241 ccAdr = dis.readInt();
242 System.out.println(
"assigned address " + Forest.fAdr2string(myAdr));
243 System.out.println(
"router address " + Forest.fAdr2string(rtrAdr));
244 System.out.println(
" comtree controller address " + Forest.fAdr2string(ccAdr));
247 }
catch (Exception e) {
248 System.out.println(
"Couldn't open socket to client manager");
249 System.out.println(e);
257 private void setUpWalls() {
260 Material[] mats = {
new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md"),
261 new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md"),
262 new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md"),
263 new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md"),
264 new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md")};
267 mats[0].setColor(
"Color",
new ColorRGBA(64f/255, 63f/255, 51f/255, 1f));
269 mats[1].setColor(
"Color",
new ColorRGBA(110f/255, 117f/255, 95f/255, 1f));
271 mats[2].setColor(
"Color",
new ColorRGBA(175f/255, 194f/255, 170f/255, 1f));
273 mats[3].setColor(
"Color",
new ColorRGBA(255f/255, 222f/255, 161f/255, 1f));
275 mats[4].setColor(
"Color",
new ColorRGBA(229f/255, 76f/255, 16f/255, 1f));
278 float wallWidth = 1.0f;
279 float wallHeight = 15f;
280 float wallLength = 256f / worldSize;
281 Node walls =
new Node();
282 Scanner in =
new Scanner(
new File(mapfile));
286 Material mat =
new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md");
287 mat.setTexture(
"ColorMap", assetManager.loadTexture(
"Textures/BrickWall.jpg"));
288 RigidBodyControl wallControl;
289 while (in.hasNextLine()) {
290 String s = in.nextLine();
291 for (
int i = 0; i < s.length(); i++) {
293 char c = s.charAt(i);
295 float tx = x * 2 * wallLength - 256f;
296 float ty = y * 2 * wallLength - 256f;
300 b =
new Box(Vector3f.ZERO, wallLength, wallHeight, wallWidth);
301 g =
new Geometry(
"Box", b);
302 g.setLocalTranslation((tx + b.xExtent), b.yExtent, ty);
303 g.setMaterial(mats[Math.abs((
int)(tx*ty%5))]);
304 walls.attachChild(g);
305 wallControl =
new RigidBodyControl(0);
306 g.addControl(wallControl);
307 bulletAppState.getPhysicsSpace().add(wallControl);
309 b =
new Box(Vector3f.ZERO, wallWidth, wallHeight, wallLength);
310 g =
new Geometry(
"Box", b);
311 g.setLocalTranslation(tx, b.yExtent, (ty + b.zExtent));
312 g.setMaterial(mats[Math.abs((
int)(tx*ty%5))]);
313 walls.attachChild(g);
314 wallControl =
new RigidBodyControl(0);
315 g.addControl(wallControl);
316 bulletAppState.getPhysicsSpace().add(wallControl);
319 b =
new Box(Vector3f.ZERO, wallLength, wallHeight, wallWidth);
320 g =
new Geometry(
"Box", b);
321 g.setLocalTranslation((tx + b.xExtent), b.yExtent, ty);
322 g.setMaterial(mats[Math.abs((
int)(tx*ty%5))]);
323 walls.attachChild(g);
324 wallControl =
new RigidBodyControl(0);
325 g.addControl(wallControl);
326 bulletAppState.getPhysicsSpace().add(wallControl);
329 b =
new Box(Vector3f.ZERO, wallWidth, wallHeight, wallLength);
330 g =
new Geometry(
"Box", b);
331 g.setLocalTranslation(tx, b.yExtent, (ty + b.zExtent));
332 g.setMaterial(mats[Math.abs((
int)(tx*ty%5))]);
333 walls.attachChild(g);
334 wallControl =
new RigidBodyControl(0);
335 g.addControl(wallControl);
336 bulletAppState.getPhysicsSpace().add(wallControl);
345 b =
new Box(Vector3f.ZERO, wallWidth, wallHeight, 256);
346 g =
new Geometry(
"Box", b);
347 g.setLocalTranslation(-256, b.yExtent, 0);
349 walls.attachChild(g);
350 wallControl =
new RigidBodyControl(0);
351 g.addControl(wallControl);
352 bulletAppState.getPhysicsSpace().add(wallControl);
354 b =
new Box(Vector3f.ZERO, wallWidth, wallHeight, 256);
355 g =
new Geometry(
"Box", b);
356 g.setLocalTranslation(256, b.yExtent, 0);
358 walls.attachChild(g);
359 wallControl =
new RigidBodyControl(0);
360 g.addControl(wallControl);
361 bulletAppState.getPhysicsSpace().add(wallControl);
363 b =
new Box(Vector3f.ZERO, 256, wallHeight, wallWidth);
364 g =
new Geometry(
"Box", b);
365 g.setLocalTranslation(0, b.yExtent, -256);
367 walls.attachChild(g);
368 wallControl =
new RigidBodyControl(0);
369 g.addControl(wallControl);
370 bulletAppState.getPhysicsSpace().add(wallControl);
372 b =
new Box(Vector3f.ZERO, 256, wallHeight, wallWidth);
373 g =
new Geometry(
"Box", b);
374 g.setLocalTranslation(0, b.yExtent, 256);
376 walls.attachChild(g);
377 wallControl =
new RigidBodyControl(0);
378 g.addControl(wallControl);
379 bulletAppState.getPhysicsSpace().add(wallControl);
381 rootNode.attachChild(walls);
382 }
catch (FileNotFoundException ex) {
383 Logger.getLogger(
Main.class.getName()).log(Level.SEVERE, null, ex);
389 private void setUpLight() {
391 AmbientLight al =
new AmbientLight();
392 al.setColor(ColorRGBA.White.mult(1.3f));
393 rootNode.addLight(al);
395 DirectionalLight dl =
new DirectionalLight();
396 dl.setColor(ColorRGBA.White);
397 dl.setDirection(
new Vector3f(2.8f, -2.8f, -2.8f).normalizeLocal());
398 rootNode.addLight(dl);
404 inputManager.addMapping(
"Left",
new KeyTrigger(KeyInput.KEY_A));
405 inputManager.addMapping(
"Right",
new KeyTrigger(KeyInput.KEY_D));
406 inputManager.addMapping(
"Up",
new KeyTrigger(KeyInput.KEY_W));
407 inputManager.addMapping(
"Down",
new KeyTrigger(KeyInput.KEY_S));
408 inputManager.addListener(
this,
"Left");
409 inputManager.addListener(
this,
"Right");
410 inputManager.addListener(
this,
"Up");
411 inputManager.addListener(
this,
"Down");
416 public void onAction(String binding,
boolean value,
float tpf) {
417 if (binding.equals(
"Left")) {
419 }
else if (binding.equals(
"Right")) {
421 }
else if (binding.equals(
"Up")) {
423 }
else if (binding.equals(
"Down")) {
434 Vector3f camDir = cam.getDirection().clone().multLocal(1.5f);
435 Vector3f camLeft = cam.getLeft().clone().multLocal(1.5f);
436 walkDirection.set(0, 0, 0);
438 walkDirection.addLocal(camLeft);
441 walkDirection.addLocal(camLeft.negate());
444 walkDirection.addLocal(camDir);
447 walkDirection.addLocal(camDir.negate());
449 if(!LET_ME_FLY) walkDirection.y = 0;
450 player.setWalkDirection(walkDirection);
452 cam.setLocation(player.getPhysicsLocation());
454 now = (int) System.nanoTime() / 1000000;
455 if (!waiting4comtCtl) {
459 idCounter = (++idCounter)%5;
461 HashSet<Integer> tmp =
new HashSet<Integer>();
462 for(Integer i : status.keySet())
463 if(!recentIds.contains(i)) tmp.add(i);
465 for(Integer i : tmp) {
466 status.get(i).remove(rootNode);
472 while ((b =
receive()) != null) {
473 PktHeader h =
new PktHeader();
475 Forest.PktTyp ptyp = h.getPtype();
476 if (!waiting4comtCtl && ptyp == Forest.PktTyp.CLIENT_DATA) {
479 }
else if (waiting4comtCtl && ptyp == Forest.PktTyp.CLIENT_SIG) {
480 CtlPkt cp =
new CtlPkt();
482 if (cp.getCpType() == CpTyp.CLIENT_JOIN_COMTREE
483 && cp.getRrType() == CtlPkt.CpRrTyp.POS_REPLY) {
484 waiting4comtCtl =
false;
485 }
else if (cp.getCpType() == CpTyp.CLIENT_LEAVE_COMTREE
486 && cp.getRrType() == CtlPkt.CpRrTyp.POS_REPLY) {
492 if (!waiting4comtCtl) {
495 now = (int) System.nanoTime() / 1000000;
496 int delay = nextTime - now;
497 if (delay < (1 << 31)) {
500 }
catch (InterruptedException ex) {
501 Logger.getLogger(
Main.class.getName()).log(Level.SEVERE, null, ex);
504 nextTime = now + 1000 * UPDATE_PERIOD;
512 Forest.PktBuffer b =
new Forest.PktBuffer();
513 PktHeader h =
new PktHeader();
514 h.setLength(4 * (5 + 8));
515 h.setPtype(Forest.PktTyp.CLIENT_DATA);
516 h.setFlags((
short) 0);
517 h.setComtree(comtree);
519 h.setDstAdr(-
groupNum(getX(), getY()));
522 b.set(Forest.HDR_LENG/4 , STATUS_REPORT);
523 b.set(Forest.HDR_LENG/4 + 1, now);
524 b.set(Forest.HDR_LENG/4 + 2, getX());
525 b.set(Forest.HDR_LENG/4 + 3, getY());
527 b.set(Forest.HDR_LENG/4 + 5, 0);
528 b.set(Forest.HDR_LENG/4 + 6, numNear);
529 b.set(Forest.HDR_LENG/4 + 7, numVisible);
530 send(b, h.getLength());
538 Forest.PktBuffer b =
new Forest.PktBuffer();
542 int nbytes = chan.read(buf);
546 int length = buf.getInt(0);
549 while (buf.position() != buf.limit()) {
552 for (
int i = 0; i < length / 4; i++) {
553 b.set(i, buf.getInt(i * 4));
555 }
catch (IOException ex) {
556 System.out.println(
"I/O exception when reading");
557 System.out.println(ex);
563 byte[] buff =
new byte[1500];
564 Forest.PktBuffer b =
new Forest.PktBuffer();
565 DatagramPacket p =
new DatagramPacket(buff,1500);
568 for(
int i = 0; i < p.getLength(); i+=4) {
569 int k = (buff[i] << 24) | (buff[i+1] << 16) |
570 (buff[i+2] << 8) | (buff[i+3]);
573 }
catch (IOException ex) {
574 System.out.println(
"I/O exception when reading");
575 System.out.println(ex);
585 Forest.PktBuffer buff =
new Forest.PktBuffer();
586 PktHeader h =
new PktHeader();
587 h.setLength(4 * (5 + 1));
588 h.setPtype(Forest.PktTyp.CONNECT);
589 h.setFlags((
short) 0);
590 h.setComtree(Forest.CLIENT_CON_COMT);
594 send(buff, h.getLength());
600 Forest.PktBuffer buff =
new Forest.PktBuffer();
601 PktHeader h =
new PktHeader();
602 h.setLength(4 * (5 + 1));
603 h.setPtype(Forest.PktTyp.DISCONNECT);
604 h.setFlags((
short) 0);
605 h.setComtree(Forest.CLIENT_CON_COMT);
609 send(buff, h.getLength());
616 public void send(Forest.PktBuffer b,
int length) {
619 b.put2BytBuf(buf, length);
622 chan.socket().getOutputStream().flush();
623 }
catch (IOException ex) {
624 System.out.println(
"Could not send tcp packet");
625 System.out.println(ex);
630 byte[] pkt = b.toByteArray(length);
631 InetAddress ip = InetAddress.getByAddress(Forest.ip2byteArr(rtrIpAdr));
632 udpSock.send(
new DatagramPacket(pkt,pkt.length,ip,Forest.ROUTER_PORT));
633 }
catch (Exception ex) {
634 System.out.println(
"Could not send datagram packet");
635 System.out.println(ex);
646 Forest.PktBuffer buff =
new Forest.PktBuffer();
647 CpTyp cpType = (join ? CpTyp.CLIENT_JOIN_COMTREE : CpTyp.CLIENT_LEAVE_COMTREE);
648 CtlPkt cp =
new CtlPkt(cpType, CtlPkt.CpRrTyp.REQUEST, seqNum++);
649 cp.setAttr(CpAttr.COMTREE_NUM, comt);
650 cp.setAttr(CpAttr.CLIENT_IP, needCliProxy ? cpIpAdr : myIpAdr);
651 cp.setAttr(CpAttr.CLIENT_PORT, needCliProxy ? cpForestPort : udpSock.getLocalPort());
652 int leng = cp.pack(buff);
654 System.out.println(
"Couldn't pack control packt");
657 PktHeader h =
new PktHeader();
658 h.setLength(Forest.OVERHEAD + leng);
659 h.setPtype(Forest.PktTyp.CLIENT_SIG);
660 h.setComtree(Forest.CLIENT_SIG_COMT);
664 send(buff, Forest.OVERHEAD + leng);
672 public boolean isVis(
int g1,
int g2) {
673 int region1 = g1 - 1;
int region2 = g2 - 1;
674 int[] region1xs =
new int[4];
675 int[] region1ys =
new int[4];
676 int[] region2xs =
new int[4];
677 int[] region2ys =
new int[4];
679 int row1 = region1 / worldSize;
680 int col1 = region1 % worldSize;
681 int row2 = region2 / worldSize;
682 int col2 = region2 % worldSize;
684 region1xs[0] = region1xs[2] = col1 * GRID + 1;
685 region1ys[0] = region1ys[1] = (row1 + 1) * GRID - 1;
686 region1xs[1] = region1xs[3] = (col1 + 1) * GRID - 1;
687 region1ys[2] = region1ys[3] = row1 * GRID + 1;
688 region2xs[0] = region2xs[2] = col2 * GRID + 1;
689 region2ys[0] = region2ys[1] = (row2 + 1) * GRID - 1;
690 region2xs[1] = region2xs[3] = (col2 + 1) * GRID - 1;
691 region2ys[2] = region2ys[3] = row2 * GRID + 1;
693 int minRow = Math.min(row1, row2);
694 int maxRow = Math.max(row1, row2);
695 int minCol = Math.min(col1, col2);
696 int maxCol = Math.max(col1, col2);
698 for (
int i = 0; i < 4; i++) {
699 for (
int j = 0; j < 4; j++) {
700 boolean canSee =
true;
701 double ax = (double) region1xs[i];
702 double ay = (double) region1ys[i];
703 double bx = (double) region2xs[j];
704 double by = (double) region2ys[j];
707 for (
int y = minRow; y <= maxRow; y++) {
708 for (
int z = minCol; z <= maxCol; z++) {
709 double cx = (double) z * GRID;
710 double cy = (double) (y + 1) * GRID;
712 int k = y * worldSize + z;
713 if (walls[k] == 1 || walls[k] == 3) {
717 double dy = cy - GRID;
725 if (walls[k] == 2 || walls[k] == 3) {
728 double dx = cx + GRID;
762 double cx,
double cy,
double dx,
double dy) {
763 double epsilon = .0001;
766 if (Math.abs(ax - bx) < epsilon && Math.abs(cx - dx) < epsilon) {
767 return Math.abs(ax - cx) < epsilon && Math.max(ay, by) >= Math.min(cy, dy)
768 && Math.min(ay, by) <= Math.max(cy, dy);
771 if (Math.abs(ax - bx) < epsilon) {
772 double s2 = (dy - cy) / (dx - cx);
773 double i2 = cy - s2 * cx;
774 double y = s2 * ax + i2;
775 return (y >= Math.min(ay, by) && y <= Math.max(ay, by)
776 && y >= Math.min(cy, dy) && y <= Math.max(cy, dy));
778 if (Math.abs(cx - dx) < epsilon) {
779 double s1 = (by - ay) / (bx - ax);
780 double i1 = ay - s1 * ax;
781 double y = s1 * cx + i1;
782 return (y >= Math.min(ay, by) && y <= Math.max(ay, by)
783 && y >= Math.min(cy, dy) && y <= Math.max(cy, dy));
785 double s1 = (by - ay) / (bx - ax);
786 double i1 = ay - s1 * ax;
787 double s2 = (dy - cy) / (dx - cx);
788 double i2 = cy - s2 * cx;
793 if (Math.abs(s1) + Math.abs(s2) <= epsilon
794 || Math.abs(s1 - s2) / (Math.abs(s1) + Math.abs(s2)) < epsilon) {
795 return (Math.abs(i1 - i2) < epsilon
796 && Math.min(ax, bx) <= Math.max(cx, dx)
797 && Math.max(ax, bx) >= Math.min(cx, dx));
800 double x = (i2 - i1) / (s1 - s2);
802 return (x >= Math.min(ax, bx) && x <= Math.max(ax, bx)
803 && x >= Math.min(cx, dx) && x <= Math.max(cx, dx));
809 walls =
new int[worldSize * worldSize];
812 in =
new Scanner(
new File(mapfile));
813 }
catch (FileNotFoundException ex) {
814 System.out.println(
"couldn't read mapfile");
820 line = in.nextLine();
821 if (line.length() < worldSize) {
822 System.out.println(
"format error, all lines must have same length");
825 for (
int i = 0; i < worldSize; i++) {
826 if (line.charAt(i) ==
'+') {
827 walls[(worldSize - lineCnt) * worldSize + i] = 3;
828 }
else if (line.charAt(i) ==
'-') {
829 walls[(worldSize - lineCnt) * worldSize + i] = 2;
830 }
else if (line.charAt(i) ==
'|') {
831 walls[(worldSize - lineCnt) * worldSize + i] = 1;
832 }
else if (line.charAt(i) ==
' ') {
833 walls[(worldSize - lineCnt) * worldSize + i] = 0;
835 System.out.println(
"Unrecognized symbol in map file!");
839 if (lineCnt == worldSize) {
851 visSet =
new HashSet[worldSize * worldSize + 1];
852 for(
int i = 0; i <= worldSize * worldSize; i++) {
853 visSet[i] =
new HashSet<Integer>();
855 for (
int x1 = 0; x1 < worldSize; x1++) {
856 for (
int y1 = 0; y1 < worldSize; y1++) {
857 int g1 = 1 + x1 + y1 * worldSize;
859 for (
int d = 1; d < worldSize; d++) {
861 for (
int x2 = x1; x2 <= Math.min(x1 + d, worldSize - 1); x2++) {
862 int y2 = d + y1 - (x2 - x1);
863 if (y2 >= worldSize)
continue;
864 int g2 = 1 + x2 + y2 * worldSize;
873 for (
int d = 1; d < worldSize; d++) {
875 for (
int x2 = x1; x2 >= Math.max(0, x1 - d); x2--) {
876 int y2 = d + y1 - (x1 - x2);
877 if (y2 >= worldSize)
continue;
878 int g2 = 1 + x2 + y2 * worldSize;
887 for (
int d = 1; d < worldSize; d++) {
889 for (
int x2 = x1; x2 >= Math.max(0, x1 - d); x2--) {
890 int y2 = (x1 - x2) + y1 - d;
891 if (y2 < 0)
continue;
892 int g2 = 1 + x2 + y2 * worldSize;
901 for (
int d = 1; d < worldSize; d++) {
903 for (
int x2 = x1; x2 <= Math.min(x1 + d, worldSize - 1); x2++) {
904 int y2 = (x2 - x1) + y1 - d;
905 if (y2 < 0)
continue;
906 int g2 = 1 + x2 + y2 * worldSize;
916 int maxVis = 0;
int totVis = 0;
917 for(
int g = 1; g <= worldSize*worldSize; g++) {
918 int vis = visSet[g].size();
919 maxVis = Math.max(vis,maxVis); totVis += vis;
921 System.out.println(
"avg visible: " + totVis/(worldSize*worldSize) +
922 " max visible: " + maxVis);
931 return (1 + x1 / GRID) + (y1 / GRID) * worldSize;
937 if(glist.isEmpty())
return;
938 PktHeader h =
new PktHeader();
939 Forest.PktBuffer b =
new Forest.PktBuffer();
941 for (Integer g : glist) {
944 b.set(Forest.HDR_LENG/4 , 0);
945 b.set(Forest.HDR_LENG/4 + 1, nunsub - 1);
946 h.setLength(Forest.OVERHEAD + 4 * (2 + nunsub));
947 h.setPtype(Forest.PktTyp.SUB_UNSUB);
948 h.setFlags((
short) 0);
949 h.setComtree(comtree);
953 send(b, h.getLength());
955 b.set(Forest.HDR_LENG/4 + nunsub + 1, -g);
957 b.set(Forest.HDR_LENG/4 , 0);
958 b.set(Forest.HDR_LENG/4 + 1, nunsub);
960 h.setLength(Forest.OVERHEAD + 4 * (2 + nunsub));
961 h.setPtype(Forest.PktTyp.SUB_UNSUB);
962 h.setFlags((
short) 0);
963 h.setComtree(comtree);
967 send(b, h.getLength());
972 public void subscribe(ArrayList<Integer> glist) {
973 if(glist.isEmpty())
return;
974 PktHeader h =
new PktHeader();
975 Forest.PktBuffer b =
new Forest.PktBuffer();
977 for (Integer g : glist) {
980 b.set(Forest.HDR_LENG/4, nsub - 1);
981 b.set(Forest.HDR_LENG/4 + nsub, 0);
982 h.setLength(Forest.OVERHEAD + 4 * (2 + nsub));
983 h.setPtype(Forest.PktTyp.SUB_UNSUB);
984 h.setFlags((
short) 0);
985 h.setComtree(comtree);
989 send(b, h.getLength());
991 b.set(Forest.HDR_LENG/4 + nsub, -g);
993 b.set(Forest.HDR_LENG/4 , nsub);
994 b.set(Forest.HDR_LENG/4 + nsub + 1, 0);
995 h.setLength(Forest.OVERHEAD + 4 * (2 + nsub));
996 h.setPtype(Forest.PktTyp.SUB_UNSUB);
997 h.setFlags((
short) 0);
998 h.setComtree(comtree);
1000 h.setDstAdr(rtrAdr);
1002 send(b, h.getLength());
1007 public void updateSubs() {
1008 int myGroup =
groupNum(getX(), getY());
1009 ArrayList<Integer> glist =
new ArrayList<Integer>();
1010 for (Integer g : mySubs) {
1011 if (!visSet[myGroup].contains(g)) {
1015 mySubs.removeAll(glist);
1020 for (Integer g : visSet[myGroup]) {
1021 if (!mySubs.contains(g)) {
1031 public void draw(Forest.PktBuffer b) {
1032 PktHeader h =
new PktHeader();
1034 AvatarStatus as =
new AvatarStatus();
1035 as.id = h.getSrcAdr();
1036 as.when = b.get(Forest.HDR_LENG/4 + 1);
1037 as.x = b.get(Forest.HDR_LENG/4 + 2);
1038 as.x = (as.x / (GRID * worldSize) * 512 - 256);
1039 as.y = b.get(Forest.HDR_LENG/4 + 3);
1040 as.y = -1 * (as.y / (GRID * worldSize) * 512 - 256);
1041 as.dir = b.get(Forest.HDR_LENG/4 + 4);
1042 as.numNear = b.get(Forest.HDR_LENG/4 + 6);
1043 as.numVisible = b.get(Forest.HDR_LENG/4 + 7);
1045 recentIds.add(as.id);
1046 AvatarGraphic ag = status.get(as.id);
1048 ag =
new AvatarGraphic(as,assetManager,rootNode);
1049 status.put(as.id, ag);
1050 }
else ag.update(as);
1056 public void updateNearby(Forest.PktBuffer b) {
1057 PktHeader h =
new PktHeader();
1059 if (b.get(0) != STATUS_REPORT) {
1063 int x1 = b.get(Forest.HDR_LENG/4 + 2);
1064 int y1 = b.get(Forest.HDR_LENG/4 + 3);
1065 int key = h.getSrcAdr();
1066 if (!nearAvatars.containsKey(key)) {
1067 if (numNear <= MAXNEAR) {
1068 nearAvatars.put(key, ++numNear);
1071 boolean canSee =
true;
1072 for (
int i = 0; i < worldSize * worldSize; i++) {
1073 if (walls[i] == 1 || walls[i] == 3) {
1074 int l2x1 = (i % worldSize) * GRID;
1076 int l2y1 = (i / worldSize) * GRID;
1077 int l2y2 = l2y1 + GRID;
1078 if (
linesIntersect(x1, y1, getX(), getY(), l2x1, l2y1, l2x2, l2y2)) {
1083 if (walls[i] == 2 || walls[i] == 3) {
1084 int l2x1 = (i % worldSize) * GRID;
1085 int l2x2 = l2x1 + GRID;
1086 int l2y1 = (i / worldSize) * GRID + GRID;
1088 if (
linesIntersect(x1, y1, getX(), getY(), l2x1, l2y1, l2x2, l2y2)) {
1095 if (!visibleAvatars.containsKey(key)) {
1096 if (numVisible <= MAXNEAR) {
1097 visibleAvatars.put(key, ++numVisible);
1106 return (
int) (((player.getPhysicsLocation().x + 256) / 512.0) * worldSize * GRID);
1112 return ((
int) (((-1*player.getPhysicsLocation().z + 256) / 512.0) * worldSize * GRID));
1119 float atan = FastMath.atan2(player.getWalkDirection().x, player.getWalkDirection().z);
1120 return (
int) (atan * (180 / Math.PI));