diff --git a/src/mygame/Main.java b/src/mygame/Main.java index 3f284a3..d16e86c 100644 --- a/src/mygame/Main.java +++ b/src/mygame/Main.java @@ -23,6 +23,7 @@ import mygame.server.ServerMain; import mygame.server.ServerMain.EntityMessage; import mygame.server.ServerMain.JoinMessage; import mygame.server.ServerMain.PlayerActionMessage; +import mygame.server.ServerMain.PlayerLeaveMessage; import mygame.server.ServerMain.PlayerPositionMessage; import mygame.server.ServerMain.ServerMessage; import mygame.server.ServerMain.SyncLevelMessage; @@ -44,6 +45,7 @@ public class Main extends SimpleApplication implements ClientStateListener{ client.addMessageListener(new ClientListener(), JoinMessage.class); //client.addMessageListener(new ClientListener(), PlayerJoinMessage.class); client.addMessageListener(new ClientListener(), PlayerActionMessage.class); + client.addMessageListener(new ClientListener(), PlayerLeaveMessage.class); client.addClientStateListener(this); client.start(); @@ -70,6 +72,7 @@ public class Main extends SimpleApplication implements ClientStateListener{ //flyCam.setMoveSpeed(50); level = new RunLevel("TestLevel"); stateManager.attach(level); + //stateManager.detach(level); } @Override @@ -110,6 +113,9 @@ public class Main extends SimpleApplication implements ClientStateListener{ } else if (message instanceof JoinMessage) { level.getPlayerJoinMessage((JoinMessage)message); + } else + if (message instanceof PlayerLeaveMessage) { + level.getPlayerLeaveMessage((PlayerLeaveMessage)message); } } } diff --git a/src/mygame/appstate/RunLevel.java b/src/mygame/appstate/RunLevel.java index 33bb334..3bba9df 100644 --- a/src/mygame/appstate/RunLevel.java +++ b/src/mygame/appstate/RunLevel.java @@ -34,7 +34,9 @@ import mygame.control.PlayableCharacter; import mygame.server.ServerMain.JoinMessage; import mygame.server.ServerMain.SyncLevelMessage; import mygame.server.Entity; +import mygame.server.ServerMain; import mygame.server.ServerMain.PlayerActionMessage; +import mygame.server.ServerMain.PlayerLeaveMessage; public class RunLevel extends BaseAppState @@ -50,10 +52,13 @@ public class RunLevel extends BaseAppState private List players = new ArrayList<>(); private Vector3f[] player_locations; public static List queuedPlayerActionMessages = new ArrayList<>(); + public static List queuedPlayerJoinMessages = new ArrayList<>(); + public static List queuedPlayerLeaveMessages = new ArrayList<>(); public static List queuedSyncLevelMessages = new ArrayList<>(); public static Node world; Node entityNode; public static Node networkedPlayersNode; + float timer; public RunLevel(String levelName) { //System.out.println("In here. Initialize"); @@ -94,7 +99,7 @@ public class RunLevel extends BaseAppState //DirectionalLight sceneLight = (DirectionalLight)world.getLocalLightList().get(0); Node player = (Node)assetManager.loadModel("Models/Oto/Oto.mesh.xml"); - Node playerNode = new Node(); + Node playerNode = new Node("Player"); playerNode.attachChild(player); playerNode.addControl(new PlayableCharacter()); @@ -157,7 +162,7 @@ public class RunLevel extends BaseAppState reflectedScene.attachChild(TestLevel); reflectedScene.attachChild(playerNode); reflectedScene.attachChild(SkyFactory.createSky(assetManager,"Textures/Sky/Bright/BrightSky.dds",false)); - + FilterPostProcessor fpp = new FilterPostProcessor(assetManager); //viewPort.addProcessor(fpp); Vector3f lightDir = new Vector3f(-2.9f,-1.2f,-5.8f); @@ -202,6 +207,8 @@ public class RunLevel extends BaseAppState protected void cleanup(Application app) { //TODO: clean up what you initialized in the initialize method, //e.g. remove all spatials from rootNode + //((Node)rootNode.getChild("Player")).removeControl(PlayableCharacter.class); + ((Node)rootNode.getChild("Reflected Scene")).detachAllChildren(); } //onEnable()/onDisable() can be used for managing things that should @@ -230,6 +237,30 @@ public class RunLevel extends BaseAppState createPlayers(); } queuedSyncLevelMessages.clear(); + for (JoinMessage msg : queuedPlayerJoinMessages) { + MakeNetworkPlayer(msg.getEntity().id,msg.getEntity().position); + players.add(msg.getEntity().id); + createPlayers(); + System.out.println(msg); + } + queuedPlayerJoinMessages.clear(); + for (PlayerLeaveMessage msg : queuedPlayerLeaveMessages) { + for (int i=0;i5) { + main.getStateManager().detach(this); + this.setEnabled(false); + }*/ } @Override @@ -259,9 +290,7 @@ public class RunLevel extends BaseAppState public void getPlayerJoinMessage(JoinMessage playerJoinMessage) { JoinMessage msg = playerJoinMessage; - MakeNetworkPlayer(msg.getEntity().id,msg.getEntity().position); - players.add(msg.getEntity().id); - createPlayers(); + queuedPlayerJoinMessages.add(msg); } private void MakeNetworkPlayer(int id, Vector3f pos) { @@ -290,4 +319,9 @@ public class RunLevel extends BaseAppState networkPlayer.setUserData("lastCamLeftDir", playerActionMessage.getCameraLeft()); } + public void getPlayerLeaveMessage(PlayerLeaveMessage playerLeaveMessage) { + PlayerLeaveMessage msg = playerLeaveMessage; + queuedPlayerLeaveMessages.add(msg); + } + } \ No newline at end of file diff --git a/src/mygame/control/PlayableCharacter.java b/src/mygame/control/PlayableCharacter.java index 995146c..ab5c9c7 100644 --- a/src/mygame/control/PlayableCharacter.java +++ b/src/mygame/control/PlayableCharacter.java @@ -25,6 +25,7 @@ import com.jme3.scene.Spatial; import com.jme3.scene.control.AbstractControl; import com.jme3.scene.control.Control; import java.io.IOException; +import static mygame.Main.level; import static mygame.Main.main; import mygame.server.ServerMain.PlayerActionMessage; import mygame.server.ServerMain.PlayerPositionMessage; @@ -60,34 +61,40 @@ public class PlayableCharacter extends AbstractControl implements Savable, Clone @Override public void setSpatial(Spatial spatial) { super.setSpatial(spatial); - //control = spatial.getControl(BetterCharacterControl.class); - Node myNode = (Node)spatial; - - physics = new PhysicsControl( - 0.1f, - -0.25f, - 5f - ); - myNode.addControl(physics); - - control = ((Node)spatial).getChild(0).getControl(AnimControl.class); - control.addListener(this); - channel = control.createChannel(); - channel.setAnim("stand"); - /*channel_lowerbody = control.createChannel(); - channel_lowerbody.addBone("hip.right"); - channel_lowerbody.addBone("hip.left");*/ //There is no strafing animation - - main.getInputManager().addMapping("WalkForward", new KeyTrigger(KeyInput.KEY_W)); - main.getInputManager().addMapping("WalkBackward", new KeyTrigger(KeyInput.KEY_S)); - main.getInputManager().addMapping("StrafeLeft", new KeyTrigger(KeyInput.KEY_A)); - main.getInputManager().addMapping("StrafeRight", new KeyTrigger(KeyInput.KEY_D)); - main.getInputManager().addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE)); - main.getInputManager().addListener(this, "WalkForward"); - main.getInputManager().addListener(this, "WalkBackward"); - main.getInputManager().addListener(this, "StrafeRight"); - main.getInputManager().addListener(this, "StrafeLeft"); - main.getInputManager().addListener(this, "Jump"); + if (spatial!=null) { + //control = spatial.getControl(BetterCharacterControl.class); + Node myNode = (Node)spatial; + + physics = new PhysicsControl( + 0.1f, + -0.25f, + 5f + ); + myNode.addControl(physics); + + control = (((Node)spatial).getChild(0)).getControl(AnimControl.class); + //System.out.println(control.getAnimationNames()); + control.addListener(this); + channel = control.createChannel(); + channel.setAnim("stand"); + channel.setLoopMode(LoopMode.Cycle); + /*channel_lowerbody = control.createChannel(); + channel_lowerbody.addBone("hip.right"); + channel_lowerbody.addBone("hip.left");*/ //There is no strafing animation + + main.getInputManager().addMapping("WalkForward", new KeyTrigger(KeyInput.KEY_W)); + main.getInputManager().addMapping("WalkBackward", new KeyTrigger(KeyInput.KEY_S)); + main.getInputManager().addMapping("StrafeLeft", new KeyTrigger(KeyInput.KEY_A)); + main.getInputManager().addMapping("StrafeRight", new KeyTrigger(KeyInput.KEY_D)); + main.getInputManager().addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE)); + main.getInputManager().addListener(this, "WalkForward"); + main.getInputManager().addListener(this, "WalkBackward"); + main.getInputManager().addListener(this, "StrafeRight"); + main.getInputManager().addListener(this, "StrafeLeft"); + main.getInputManager().addListener(this, "Jump"); + } else { + main.getInputManager().removeListener(this); + } } /** Implement your spatial's behaviour here. @@ -216,6 +223,7 @@ public class PlayableCharacter extends AbstractControl implements Savable, Clone switch (name) { case "Jump":{ if (isOnGround() || physics.airTime<=physics.walkOffTime) { + //System.out.println("Jump"); physics.jump(); if (!(this instanceof NetworkPlayableCharacter)) { //Only send if this is the source client. PlayerActionMessage action = new PlayerActionMessage(name,"",main.client.getId(),spatial.getLocalTranslation(),spatial.getLocalRotation(),main.getCamera().getDirection(),main.getCamera().getLeft()); diff --git a/src/mygame/server/Instance.java b/src/mygame/server/Instance.java index 0a0a8ff..0e063fa 100644 --- a/src/mygame/server/Instance.java +++ b/src/mygame/server/Instance.java @@ -27,6 +27,7 @@ public class Instance { protected HashMap lastKnownPositions = new HashMap<>(); protected List entities = new ArrayList<>(); //Entity data specific to this instance. List nullEntities = new ArrayList<>(); //A list of "null" entities. When adding new entities, these slots will be consumed first. + public int INSTANCE_ID = -1; Instance(String levelName) { this.levelName = levelName; } diff --git a/src/mygame/server/ServerMain.java b/src/mygame/server/ServerMain.java index d327808..3ff7633 100644 --- a/src/mygame/server/ServerMain.java +++ b/src/mygame/server/ServerMain.java @@ -34,6 +34,7 @@ public class ServerMain extends SimpleApplication{ int clientIDMax = 0; public static HashMap instances = new HashMap<>(); public static HashMap players = new HashMap<>(); //The last instance location this player was seen in. + public static int INSTANCE_UNIQUE_ID = 0; ServerMain() { try { @@ -51,7 +52,9 @@ public class ServerMain extends SimpleApplication{ if (players.containsKey(conn.getId())) { Instance i = players.get(conn.getId()); i.removePlayer(conn); + server.broadcast(Filters.in(i.clients),new PlayerLeaveMessage(i.levelName,conn.getId())); } + players.remove(conn.getId()); } }); @@ -61,6 +64,7 @@ public class ServerMain extends SimpleApplication{ Serializer.registerClass(JoinMessage.class); Serializer.registerClass(SyncLevelMessage.class); Serializer.registerClass(Entity.class); + Serializer.registerClass(PlayerLeaveMessage.class); //Serializer.registerClass(PlayerJoinMessage.class); Serializer.registerClass(PlayerActionMessage.class); @@ -71,6 +75,7 @@ public class ServerMain extends SimpleApplication{ server.addMessageListener(new ServerListener(), SyncLevelMessage.class); //server.addMessageListener(new ServerListener(), PlayerJoinMessage.class); server.addMessageListener(new ServerListener(), PlayerActionMessage.class); + server.addMessageListener(new ServerListener(), PlayerLeaveMessage.class); server.start(); } catch (IOException ex) { @@ -123,8 +128,11 @@ public class ServerMain extends SimpleApplication{ } else if (message instanceof PlayerPositionMessage) { System.out.println("Position update for client "+source.getId()+". Broadcasting to others."); - server.broadcast(Filters.notEqualTo(source), message); - server.broadcast(Filters.in(source), new ServerMessage("Sent an update to other clients!")); + if (players.containsKey(source.getId())) { + Instance i = players.get(source.getId()); + SendToAllButMe(i, source, message); + } + //server.broadcast(Filters.in(source), new ServerMessage("Sent an update to other clients!")); } else if (message instanceof JoinMessage) { JoinMessage msg = (JoinMessage)message; @@ -139,6 +147,7 @@ public class ServerMain extends SimpleApplication{ instance = new Instance(msg.levelName); System.out.println("Instance "+msg.levelName+" does not exist. Creating... "+instance); CreateTestObj(instance); + instance.INSTANCE_ID=INSTANCE_UNIQUE_ID++; System.out.println(instance); instances.put(msg.levelName, instance); } @@ -146,15 +155,15 @@ public class ServerMain extends SimpleApplication{ instance.addPlayer(source); SyncLevelMessage sync = new SyncLevelMessage(instance.getEntities(),instance.getPlayers(),instance.getPlayerPositions()); server.broadcast(Filters.in(source),sync); - server.broadcast(Filters.notEqualTo(source),message); + SendToAllButMe(instance, source, message); } else if (message instanceof PlayerActionMessage) { System.out.println("Received player action message: "+message); - server.broadcast(Filters.notEqualTo(source), message); PlayerActionMessage msg = (PlayerActionMessage)message; if (players.containsKey(source.getId())) { Instance i = players.get(source.getId()); i.updatePosition(source.getId(),msg.getPosition()); + SendToAllButMe(i, source, message); } } /*else if (message instanceof PlayerJoinMessage) { @@ -162,6 +171,14 @@ public class ServerMain extends SimpleApplication{ server.broadcast(Filters.notEqualTo(source), message); }*/ } + + private void SendToAllButMe(Instance i, HostedConnection source, Message message) { + for (HostedConnection conn : i.clients) { + if (conn!=source) { + server.broadcast(Filters.in(conn),message); + } + } + } } public void CreateTestObj(Instance instance) { @@ -248,6 +265,28 @@ public class ServerMain extends SimpleApplication{ } } @Serializable + public static class PlayerLeaveMessage extends AbstractMessage { + String levelName; + int id; + + public PlayerLeaveMessage() { + } + + public PlayerLeaveMessage(String levelName, int id) { + this.levelName = levelName; + this.id=id; + } + + @Override + public String toString() { + return "Client ID "+id+" left. In Instance "+levelName.toString(); + } + + public int getId() { + return id; + } + } + @Serializable public static class SyncLevelMessage extends AbstractMessage { Entity[] entities; Integer[] clients;