Scene graph is not properly updated for rendering cycle update

Jul 11, 2017 4:31:02 PM com.jme3.app.Application handleError
SEVERE: Uncaught exception thrown in Thread[jME3 Main,5,main]
java.lang.IllegalStateException: Scene graph is not properly updated for rendering.
State was changed after rootNode.updateGeometricState() call.
Make sure you do not modify the scene from another thread!
Problem spatial name: Root Node

  1. Have scene model
  2. And players slots (multiplayer)

Logic:

  1. Load 3d scene

  2. Load players and add to list

  3. Update players in cycle

    /*

    • To change this template, choose Tools | Templates
    • and open the template in the editor.
      */
      package game;

    import com.jme3.app.SimpleApplication;
    import com.jme3.asset.plugins.ZipLocator;
    import com.jme3.bullet.BulletAppState;
    import com.jme3.bullet.control.RigidBodyControl;
    import com.jme3.bullet.util.CollisionShapeFactory;
    import com.jme3.input.KeyInput;
    import com.jme3.input.MouseInput;
    import com.jme3.input.controls.ActionListener;
    import com.jme3.input.controls.KeyTrigger;
    import com.jme3.input.controls.MouseButtonTrigger;
    import com.jme3.light.AmbientLight;
    import com.jme3.light.DirectionalLight;
    import com.jme3.math.ColorRGBA;
    import com.jme3.math.Quaternion;
    import com.jme3.math.Vector3f;
    import com.jme3.scene.Spatial;
    import com.jme3.system.AppSettings;
    import config.JConfig;
    import java.awt.Dimension;
    import java.awt.Toolkit;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import message.JInMessages;
    import message.JOutMessages;
    import org.json.simple.JSONArray;
    import org.json.simple.JSONObject;
    import org.json.simple.parser.JSONParser;
    import org.json.simple.parser.ParseException;
    import static windows.Interface.updateUseArea;

    /**
    *

    • @author nn
      */
      public class GameLevel extends SimpleApplication implements ActionListener {

    public static GameLevel gameLevel;

    public String state = “start”;

    /**

    • Archive of game leve
      */
      public String levelName;

    /**

    • Players array
      */
      public static Map<String, Player> players = new HashMap<String, Player>();

    /*

    • Player command, numbers - slot, latter - command
    • 1,2,3 command A
    • 4,5,6 command B
      */

    /**

    • Model paramiters
      */
      private Spatial sceneModel;

    /**
    * Local player
    */
    Player player;

    private BulletAppState bulletAppState;
    private RigidBodyControl landscape;

    private boolean left = false, right = false, up = false, down = false,lclick = false,sit = false;

    //Temporary vectors used on each frame.
    //They here to avoid instanciating new vectors on each frame
    private Vector3f camDir = new Vector3f();
    private Vector3f camLeft = new Vector3f();

    private Vector3f camOld;

    private String levelId;

    private static String localPlayerId;

    public GameLevel(String levelJson){
    //asdasd
    try {
    gameLevel = this;

          JSONParser parser       = new JSONParser();
          
          JSONObject result       = (JSONObject) parser.parse(levelJson);
          
          GameLevel.gameLevel.levelName               = (String) result.get("model");
                
          GameLevel.gameLevel.levelId                 = (String) result.get("leveId");
    
          GameLevel.gameLevel.localPlayerId           = JConfig.user_id;
          
          
          
          //levelDescription        = (String) result.get("points");
    
          // fallSpeed    = (int) result.get("fallSpeed");
          
          
          GameLevel.gameLevel.levelName = levelName;
          
          
          setShowSettings(false);
    
          
          AppSettings settings = new AppSettings(true);
    
          
          Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
          int width = (int) screenSize.getWidth();
          int height = (int) screenSize.getHeight();
          
          
          settings.setResolution(width, height);
    
          settings.setBitsPerPixel(32);
    
          setSettings(settings);
    
          
          GameLevel.gameLevel.state = "init";
          
      } catch (ParseException ex) {
          Logger.getLogger(GameLevel.class.getName()).log(Level.SEVERE, null, ex);
      }
    

    }

    public void simpleInitApp() {

     //cam.set   
     GameLevel.gameLevel.camOld = cam.getLeft();  
     
     /** Set up Physics */
     GameLevel.gameLevel.bulletAppState = new BulletAppState();
     GameLevel.gameLevel.stateManager.attach(bulletAppState);
     //bulletAppState.getPhysicsSpace().enableDebug(assetManager);
     
     
     // We re-use the flyby camera for rotation, while positioning is handled by physics
     GameLevel.gameLevel.viewPort.setBackgroundColor(new ColorRGBA(0.7f, 0.8f, 1f, 1f));
     GameLevel.gameLevel.flyCam.setMoveSpeed(0.2f);
     
     
     setUpKeys();
     setUpLight();
    
     
     // We load the scene from the zip file and adjust its size.
     //assetManager.registerLocator("Models/" + levelName + ".zip", ZipLocator.class);
    // sceneModel = assetManager.loadModel(levelName+".scene");
     
    
     GameLevel.gameLevel.sceneModel = assetManager.loadModel("Models/" + levelName + "/" + levelName + ".scene");
     
     
     GameLevel.gameLevel.sceneModel.setLocalScale(2f);
    
     // We set up collision detection for the scene by creating a
     // compound collision shape and a static RigidBodyControl with mass zero.
     com.jme3.bullet.collision.shapes.CollisionShape sceneShape =
             CollisionShapeFactory.createMeshShape(GameLevel.gameLevel.sceneModel);
     
     GameLevel.gameLevel.landscape = new RigidBodyControl(sceneShape, 0);
     GameLevel.gameLevel.sceneModel.addControl(landscape);
    
     GameLevel.gameLevel.rootNode.attachChild(sceneModel);
     
     //get Start position
     
     GameLevel.gameLevel.bulletAppState.getPhysicsSpace().add(landscape);
    
     state = "sync";
     
     synchronization();
     
     //rootNode.attachChild(characterModel);
    // bulletAppState.getPhysicsSpace().add(player);
    

    }

    private void synchronization(){

     String outMessage        =  "{\"task\":\"JGameTask\",\"user_id\":\""+ JConfig.user_id +"\",\"auth_token\":\""+JConfig.token +"\",\"scenario\":\"load_players\",\"data\":\""+ levelId +"\"}";
    
     JOutMessages outMessages = new JOutMessages(JConfig.server_ip,outMessage);
    
     outMessages.insert();
    

    }

    public static void initPlayers(JInMessages in){

      if(in.json.get("error") == null){
          
          JSONObject players  =  (JSONObject)in.json.get("players");
    
          Set<?>      playersDataSet        = players.keySet();
          Iterator<?> playerDataIterator    = playersDataSet.iterator();
          
          
          while (playerDataIterator.hasNext()) {
             String playerDataKey    = (String)     playerDataIterator.next();
             JSONObject playerJson   = (JSONObject) players.get(playerDataKey);
             
            // System.out.println(playerJson);
             addPlayer(playerJson,playerDataKey);
             
          }
          
          
         //System.out.println(in.json.get("players"));
          
      }
    

    }

    public static void connectPlayer(JInMessages in){
    if(in.json.get(“error”) == null){
    JSONObject player = (JSONObject)in.json.get(“player”);
    String id = (String) player.get(“id”);

           // System.out.print("add player " + id);
            
            addPlayer(player,id);
        }
    

    }

    private static void addPlayer(JSONObject playerJson,String key) {
    //
    //System.out.println("");
    System.out.println("add player: " + playerJson.toJSONString());

     Player player          = new Player();
     player.assetManager    = GameLevel.gameLevel.assetManager;
     
     player.camLeft         = GameLevel.gameLevel.camLeft;
     
     player.id              = key;
     
     player.setJsonKeys(playerJson);
     
     
     player.levelId         = GameLevel.gameLevel.levelId;
     
     
    // player.startLocation = gameLevel.startPosition.get(player.slot);
     
     
     player.init();
     
     
     GameLevel.gameLevel.players.put(player.id, player);
     
     
     GameLevel.gameLevel.rootNode.attachChild(player.characterModel);
     GameLevel.gameLevel.bulletAppState.getPhysicsSpace().add(player.characterControl);
    

    }

    private void setUpLight() {
    // We add light so we see the scene
    AmbientLight al = new AmbientLight();
    al.setColor(ColorRGBA.White.mult(0.8f));
    GameLevel.gameLevel.rootNode.addLight(al);

     DirectionalLight dl = new DirectionalLight();
     dl.setColor(ColorRGBA.White);
     dl.setDirection(new Vector3f(2.8f, -2.8f, -2.8f).normalizeLocal());
     GameLevel.gameLevel.rootNode.addLight(dl);
    

    }

    /** We over-write some navigational key mappings here, so we can
    * add physics-controlled walking and jumping: */
    private void setUpKeys() {
    GameLevel.gameLevel.inputManager.addMapping(“Left”, new KeyTrigger(KeyInput.KEY_A));
    GameLevel.gameLevel.inputManager.addMapping(“Right”, new KeyTrigger(KeyInput.KEY_D));
    GameLevel.gameLevel.inputManager.addMapping(“Up”, new KeyTrigger(KeyInput.KEY_W));
    GameLevel.gameLevel.inputManager.addMapping(“Down”, new KeyTrigger(KeyInput.KEY_S));
    GameLevel.gameLevel.inputManager.addMapping(“Jump”, new KeyTrigger(KeyInput.KEY_SPACE));

     GameLevel.gameLevel.inputManager.addMapping("LClick",new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
     GameLevel.gameLevel.inputManager.addMapping("Ctrl", new KeyTrigger(KeyInput.KEY_LCONTROL));
    
     //sit
     
     GameLevel.gameLevel.inputManager.addListener(this, "Left");
     GameLevel.gameLevel.inputManager.addListener(this, "Right");
     GameLevel.gameLevel.inputManager.addListener(this, "Up");
     GameLevel.gameLevel.inputManager.addListener(this, "Down");
     GameLevel.gameLevel.inputManager.addListener(this, "Jump");
     
     GameLevel.gameLevel.inputManager.addListener(this, "LClick");
     GameLevel.gameLevel.inputManager.addListener(this, "Ctrl");
    

    }

    /** These are our custom actions triggered by key presses.
    * We do not walk yet, we just keep track of the direction the user pressed. */
    public void onAction(String binding, boolean isPressed, float tpf) {

     if (binding.equals("Left")) {
       GameLevel.gameLevel.left = isPressed;
       if(isPressed){
         jsonPackKeys("Left",true,false);   
       }else{
         jsonPackKeys("Left",false,false); 
         jsonPackKeys("LeftRelease",true,false);   
       }
     } else if (binding.equals("Right")) {
         GameLevel.gameLevel.right= isPressed;
    
         if(isPressed){
             jsonPackKeys("Right",true,false); 
         }else{
             jsonPackKeys("Right",false,false); 
             jsonPackKeys("RightRelease",true,false);   
         }
    
     } else if (binding.equals("Up")) {
         GameLevel.gameLevel.up = isPressed;
         if(isPressed){
             jsonPackKeys("Up",true,false);   
         }else{
             jsonPackKeys("Up",false,false);
             jsonPackKeys("UpRelease",true,false);
         }  
     } else if (binding.equals("Down")) {
       GameLevel.gameLevel.down = isPressed;
       if(isPressed){
          jsonPackKeys("Down",true,false);   
       }else{
          jsonPackKeys("Down",false,false);   
          jsonPackKeys("DownRelease",true,false);
       }
     } else if (binding.equals("Jump")) {
       if (isPressed) {
         jsonPackKeys("Jump",true,false); 
       }else{
         jsonPackKeys("Jump",false,false); 
         jsonPackKeys("JumpRelease",true,false);   
       }
     } else if (binding.equals("LClick")){
         if(isPressed){
             jsonPackKeys("LClick",true,false);
         }else{
             jsonPackKeys("LClick",false,false);
             jsonPackKeys("LClickRelease",true,false);   
         }
     } else if(binding.equals("Ctrl")){
          if(isPressed){
              jsonPackKeys("Ctrl",true,false);
          }else{
              jsonPackKeys("Ctrl",false,false);
              jsonPackKeys("CtrlRelease",true,false);
          }
     }
    

    }

    /**
    * This is the main event loop–walking happens here.
    * We check in which direction the player is walking by interpreting
    * the camera direction forward (camDir) and to the side (camLeft).
    * The setWalkDirection() command is what lets aed player walk.
    * We also make sure here that the camera moves with physics-controllplayer.
    */
    @Override
    public void simpleUpdate(float tpf) {
    if(GameLevel.gameLevel.players.size() > 0){

             GameLevel.gameLevel.camDir.set(cam.getDirection()).multLocal(0.3f);
             GameLevel.gameLevel.camLeft.set(cam.getLeft()).multLocal(0.2f);
    
    
             Quaternion camRotation = cam.getRotation();
    
             jsonPackKeys("camRotationX",camRotation.getX(),false);
             jsonPackKeys("camRotationY",camRotation.getY(),false);
             jsonPackKeys("camRotationZ",camRotation.getZ(),false);
             jsonPackKeys("camRotationW",camRotation.getW(),false);
    
             jsonPackKeys("camDirectionX",GameLevel.gameLevel.camDir.getX(),false);
             jsonPackKeys("camDirectionY",GameLevel.gameLevel.camDir.getY(),false);
             jsonPackKeys("camDirectionZ",GameLevel.gameLevel.camDir.getZ(),false);
    
             jsonPackKeys("camLeftX",GameLevel.gameLevel.camLeft.getX(),false);
             jsonPackKeys("camLeftY",GameLevel.gameLevel.camLeft.getY(),false);
             jsonPackKeys("camLeftZ",GameLevel.gameLevel.camLeft.getZ(),true);
         
             
             try {
                  JSONParser parser = new JSONParser();
                  Object    obj = parser.parse(GameLevel.gameLevel.keyString);
                  
                  JSONObject jsonObj = (JSONObject) obj;
                  
                  JSONObject keysObject = (JSONObject) jsonObj.get("keys"); 
                  
                  
                  GameLevel.gameLevel.players.get(GameLevel.gameLevel.localPlayerId).setJsonKeys(keysObject);
                  
                  
             } catch (ParseException ex) {
                 Logger.getLogger(GameLevel.class.getName()).log(Level.SEVERE, null, ex);
             }
             
             
             // System.out.println(keyString);
              GameLevel.gameLevel.keyString = "{\"keys\" : {";
    
    
              GameLevel.gameLevel.cam.setLocation(GameLevel.gameLevel.players.get(GameLevel.gameLevel.localPlayerId).characterControl.getPhysicsLocation());
    
              
              for(String key : GameLevel.gameLevel.players.keySet()){
                 
                 GameLevel.gameLevel.players.get(key).update(tpf);
                 
                 GameLevel.gameLevel.players.get(key).tpfUpdate(); 
              }
              
         }
         
     }
     //
     public static void updatePlayerPosition(JInMessages in){
         if(in.json.get("error") == null){
          
             JSONObject player  =  (JSONObject)in.json.get("player");
    
             String id          =  (String) player.get("id");
             
             System.out.println("game level update localID " + GameLevel.gameLevel.localPlayerId + " update id " + id);
             GameLevel.gameLevel.players.get(id).setJsonKeys(player);
             
         }
     }
     
     
     /**
      * Packe keys to json string
      */
     String keyString = "{\"keys\": {";
     
     public void jsonPackKeys(String key,float value,boolean endflag){
         
        GameLevel.gameLevel.keyString += "\"" +key + "\"" + ":" + value;
        if(endflag){
            GameLevel.gameLevel.keyString += "}}";
        }else {
            GameLevel.gameLevel.keyString += ",";
        }
     }
     
     public void jsonPackKeys(String key,boolean value,boolean endflag){
        
        GameLevel.gameLevel.keyString += "\"" +key + "\"" + ":" + value;
        if(endflag){
            GameLevel.gameLevel.keyString += "}}";
        }else {
            GameLevel.gameLevel.keyString += ",";
        }
     }
    

    }

1 Like
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package game;

import com.jme3.animation.AnimChannel;
import com.jme3.animation.AnimControl;
import com.jme3.animation.LoopMode;
import com.jme3.asset.AssetManager;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.material.MatParam;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.math.Vector4f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.texture.Texture2D;
import config.JConfig;
import java.awt.Image;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import message.JOutMessages;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

/**
 *
 * @author nn
 *
 */
public class Player {
    
    public String port;
    
    JSONObject palyerJsonOld;
    //Temporary vectors used on each frame.
    //They here to avoid instanciating new vectors on each frame
    Player  playerOld;
    
    public String levelId;
    
    public Vector3f camDir;
    public Vector3f camLeft;
    public Quaternion camRotation;

    
    public JSONObject keysObject;
    
    //
    public Vector3f camLeftOld;

    public boolean localPlayer = true;

    public Vector3f walkDirection = new Vector3f();
    
    /**
     * asset manager load model
     */
    public AssetManager assetManager;
    /**
     * Player start location
     */
    public Vector3f startLocation;

    private AnimChannel rotateChannel;
    private AnimControl rotateControl;

    private AnimChannel runChannel;
    private AnimControl runControl;
    
    public CharacterControl characterControl;

    /**
     * Model folder
     */
    private String modelPath = "Models/player.j3o";
    /**
     * Player model
     */
    public Node characterModel;

    /**
     * Move
     */
    private float tpf;
    
    private Spatial moveSpatial;
    
    private Vector3f moveTarget;

    
    
    private String rotateAnimation;
    
    private String runAnimation;
    
    
    private String userName;

    
    /**
     * Capsule
     */
    CapsuleCollisionShape capsuleShape = new CapsuleCollisionShape(1.4f, 3f, 1);

    //public 
    /**
     * database id
     */
    public String id;
    
    public String ip;

    
    /**
     * Player key press
     */
    public float camRotationX = 0.0f;
    public float camRotationY = 0.0f;
    public float camRotationZ = 0.0f;
    public float camRotationW = 0.0f;

    public float camDirectionX = 0.0f;
    public float camDirectionY = 0.0f;
    public float camDirectionZ = 0.0f;
    
    public float camLeftX = 0.0f;
    public float camLeftY = 0.0f;
    public float camLeftZ = 0.0f;

    public boolean Left          = false;
    public boolean LeftRelease   = false;
    public boolean Right         = false;
    public boolean RightRelease  = false;
    public boolean Up            = false;
    public boolean UpRelease     = false;
    public boolean Down          = false;
    public boolean DownRelease   = false;
    public boolean Jump          = false;
    public boolean JumpRelease   = false;
    public boolean LClick        = false;
    public boolean LClickRelease = false;
    public boolean Sit           = false;
    public boolean SitRelease    = false;

    public boolean Ctrl          = false;
    public boolean CtrlRelease   = false;

    /**
     * Parameters
     */
    int fallSpeed = 100;
    
    float speed   = 1f;

    int jumpSpeed = 20;

    int gravity   = 60;

    /**
     * game parameters
     */
    /**
     * game hit point
     */
    int healt = 100;
    /**
     * armor
     */
    int armor = 100;
    /**
     * death or live
     */
    boolean death = false;
    /**
     * weapon damage
     */
    int damage = 100;
    
    /**
     * Level slot
     */
    public int slot = 0;
    
    /**
     * Player command, numbers - slot, latter - command
     * 1,2,3 command A
     * 4,5,6 command B
     */
    public int command = 0;
     /**
     * 
     */
    
    public boolean isBlock = false;

    /**
     * userKeyCommand
     *
     * @param userKey
     */
    public void makeCommand(JSONObject userKey) {
        //String shut = command.get("shut").toString();

    }

    /**
     * Init model
     */
    public void init() {
        
        //
        // We set up collision detection for the player by creating
        // a capsule collision shape and a CharacterControl.
        // The CharacterControl offers extra settings for
        // size, stepheight, jumping, falling, and gravity.
        // We also put the player in its starting position.
        capsuleShape     = new CapsuleCollisionShape(1.4f, 3f, 1);

        //capsuleShape.
        characterControl = new PlayerControl(capsuleShape, 0.05f);

        characterControl.setJumpSpeed(20);

        characterControl.setFallSpeed(100);
        characterControl.setGravity(60);

        // characterControl.setPhysicsLocation(new Vector3f( 0.9f,  0.02f, 0.22f));

        characterModel = (Node) assetManager.loadModel(modelPath);

        moveSpatial = characterModel.getChild("base.obj");
        
        
        
        characterModel.move(0.050779365f, -1.74886445f, 12.0f);

        characterModel.rotate(12.0f, 5.0f, 0.0f);

        moveSpatial.setLocalTranslation(new Vector3f(0, -0.2f, 0));

        AnimListener rotateListener = new AnimListener();
        AnimListener runListener = new AnimListener();

        rotateControl = characterModel.getChild("base.obj").getControl(AnimControl.class);

        rotateControl.addListener(rotateListener);

        rotateChannel = rotateControl.createChannel();
        
        

        runControl    = characterModel.getChild("base.obj").getControl(AnimControl.class);

        runControl.addListener(runListener);

        runChannel    = runControl.createChannel();

        characterControl.setPhysicsLocation(startLocation);
        
        
        //rotateChannel.setAnim("direct-left");
        runChannel.setAnim("run");
        runChannel.setSpeed(0);
        runChannel.setLoopMode(LoopMode.Loop);

        
        rotateChannel.setAnim("direct");
        rotateChannel.setSpeed(0);
        rotateChannel.setLoopMode(LoopMode.DontLoop);
        
        playerOld = this;
        
    }
    
    /**
     * Setup json key string to model
     *
     * @param keyString
     */
    public void setJsonKeys(JSONObject keysObject) {
        
        try {
            
            Set<?> set = keysObject.keySet();
            Iterator<?> iterator = set.iterator();
            
            /**
             * Init varibles from json string
             */
            while (iterator.hasNext()) {
                String key = (String) iterator.next();
                
                Object value = keysObject.get(key);
                
                
                Field field = this.getClass().getDeclaredField(key);
                
                if (field.getType().toString().equals("float")) {
                    float floatValue = Float.parseFloat(value.toString());
                    field.set(this, floatValue);
                } else if (field.getType().toString().equals("boolean")) {
                    boolean booleanValue = Boolean.parseBoolean(value.toString());
                    field.set(this, booleanValue);
                } else if(field.getType().toString().equals("int")){
                    int booleanValue = Integer.parseInt(value.toString());
                    field.set(this, booleanValue);
                }
               
                if(key.equals("startLocation")){
                  JSONObject startLocationJson = (JSONObject) value;
                   
                  float x = Float.parseFloat(startLocationJson.get("x").toString());
                  float y = Float.parseFloat(startLocationJson.get("y").toString());
                  float z = Float.parseFloat(startLocationJson.get("z").toString());
                  
                  startLocation = new Vector3f(x,y,z);
                  
                }
            }

            camLeftOld  = camLeft;

            camRotation = new Quaternion(camRotationX, camRotationY, camRotationZ, camRotationW);
            camDir      = new Vector3f(camDirectionX, camDirectionY, camDirectionZ);
            camLeft     = new Vector3f(camLeftX, camLeftY, camLeftZ);

            //System.out.println(" camLeftOld.x " + camLeftOld.x + " camLeftOld.y " +  camLeftOld.y + " camLeftOld.z " + camLeftOld.z);
            // System.out.println(" camLeft.x " + camLeft.x + " camLeft.y " +  camLeft.y + " camLeft.z " + camLeft.z);
        } catch (NoSuchFieldException ex) {
            Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SecurityException ex) {
            Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalArgumentException ex) {
            Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    
    public boolean isAnimRun     = false;
    //left
    public boolean isDirectLeft  = false;
    public boolean isLeftDirect  = false;
    //right
    public boolean isDirectRight = false;
    public boolean isRightDirect = false;

    public boolean isSit         = false;
  
    public boolean isStand       = false;

    //sit
    public boolean isSitLeft     = false;
    
    public boolean isSitRight    = false;
    
    public boolean blockMove     = false;
    
    public boolean isSitRun      = false;

    
    /**
     * Update model in app
     */
    public void update(float appTpf) {

        tpf = appTpf * 4.2f;

        if (!Ctrl) {
            standKeys();
        }

        if (Ctrl) {
            
            if (!isSit) {
                isSit   = true;
                isStand = false;
                
                
                rotateChannel.setAnim("start-sit");
                rotateChannel.setLoopMode(LoopMode.DontLoop);

                moveTarget = new Vector3f(0f, -1.2f, 0f);

                moveModel();
                speed = 0.3f;
                
                isSitLeft  = false;
                isSitRight = false;
            }
            
          
            speed = 0.0f;
        }

        if (CtrlRelease) {
            speed = 1.0f;

            CtrlRelease = false;
            
            
            if (!isStand) {
                isStand = true;
                isSit = false;


                rotateChannel.setAnim("sit-start");
                rotateChannel.setLoopMode(LoopMode.DontLoop);

                moveTarget = new Vector3f(0f, -0.2f, 0f);
                
                moveModel();

                rotateChannel.setAnim("direct");
                rotateChannel.setLoopMode(LoopMode.DontLoop);
                
                
                if(Left){
                    isDirectLeft = false;

                    if (!isDirectLeft) {
                        isDirectLeft = true;

                        isLeftDirect = false;
                        isDirectRight = false;
                        isRightDirect = false;
  
                        rotateChannel.setAnim("direct-half-left");
                        rotateChannel.setLoopMode(LoopMode.DontLoop);
                   }
                }
                
                if (Right) {
                    isDirectRight = false;

                    if (!isDirectRight) {
                        isDirectRight = true;

                        isLeftDirect = false;
                        isDirectLeft = false;
                        isRightDirect = false;

                        rotateChannel.setAnim("direct-half-right");
                        rotateChannel.setLoopMode(LoopMode.DontLoop);
                    }
                }
                speed = 1f;
            }
            
        }
        
        /**
         * Move and rotate model
         */
        walkDirection.set(0, 0, 0);

        if (Left) {
            walkDirection.addLocal(camLeft.mult(speed));
        }
        if (Right) {
            walkDirection.addLocal(camLeft.mult(speed).negate());
        }
        if (Up) {
            walkDirection.addLocal(camDir.mult(speed));
            //rotate_channel.setLoopMode(LoopMode.DontLoop);
        }
        if (Down) {
            walkDirection.addLocal(camDir.mult(speed).negate());
        }

        characterControl.setWalkDirection(walkDirection.mult(speed));

        float cX = characterControl.getPhysicsLocation().x;
        float cY = characterControl.getPhysicsLocation().y;
        float cZ = characterControl.getPhysicsLocation().z;

       // System.out.println("Location.x: " + cX + " Location.y: " + cY + " Location.z: " + cZ);
        
        float mX = characterModel.getWorldTranslation().x;
        float mZ = characterModel.getWorldTranslation().z;
        float mY = characterModel.getWorldTranslation().y;

        float difX = cX - mX;
        float difY = cY - mY;
        float difZ = cZ - mZ;

        
        characterModel.move(difX, difY - 2, difZ + 2);

        if (!camLeftOld.equals(camLeft)) {

            Quaternion localRotation = new Quaternion(-0.173f, camRotationY, camRotationZ, 0.9830f);

            characterModel.setLocalRotation(localRotation);
        }
        
        
        rotateAnimation = rotateChannel.getAnimationName();
        runAnimation    = runChannel.getAnimationName();
        
        JSONObject playerJson = toJson();
        
        //System.out.println(playerJson != palyerJsonOld);
        
        
        String outMessage        =  "{\"task\":\"JGameTask\",\"user_id\":\""+ JConfig.user_id +"\",\"auth_token\":\""+JConfig.token +"\",\"scenario\":\"send_keys\",\"data\":"+ playerJson.toJSONString() +"}";

        JOutMessages outMessages = new JOutMessages(JConfig.server_ip,outMessage);

        outMessages.insert();

    }
    
    
    public JSONObject toJson(){

           JSONObject playerJson = new JSONObject();

           playerJson.put("fallSpeed", fallSpeed);
           playerJson.put("speed", speed);
           playerJson.put("gravity", gravity);

           
           /******************/

           playerJson.put("camRotationX",camRotationX);
           playerJson.put("camRotationY",camRotationY);
           playerJson.put("camRotationZ",camRotationZ);
           playerJson.put("camRotationW",camRotationW);
           playerJson.put("camDirectionX",camDirectionX);
           playerJson.put("camDirectionY",camDirectionY);
           playerJson.put("camDirectionZ",camDirectionZ);

           playerJson.put("camLeftX",camLeftX);
           playerJson.put("camLeftY",camLeftY);
           playerJson.put("camLeftZ",camLeftZ);

           playerJson.put("Left",Left);
           playerJson.put("LeftRelease",LeftRelease);
           playerJson.put("Right",Right);
           playerJson.put("RightRelease",RightRelease);
           playerJson.put("Up",Up);
           playerJson.put("UpRelease",UpRelease);
           playerJson.put("Down",Down);
           playerJson.put("DownRelease",DownRelease);
           playerJson.put("Jump",Jump);
           playerJson.put("JumpRelease",JumpRelease);
           playerJson.put("LClick",LClick);
           playerJson.put("LClickRelease",LClickRelease);
           playerJson.put("Sit",Sit);
           playerJson.put("SitRelease",SitRelease);

           playerJson.put("Ctrl",Ctrl);
           playerJson.put("CtrlRelease",CtrlRelease);


           playerJson.put("isAnimRun",isAnimRun);

           playerJson.put("isDirectLeft",isDirectLeft);
           playerJson.put("isLeftDirect",isLeftDirect);

           playerJson.put("isDirectRight",isDirectRight);
           playerJson.put("isRightDirect",isRightDirect);

           playerJson.put("isSit",isSit);

           playerJson.put("isStand",isStand);


           playerJson.put("isSitLeft",isSitLeft);

           playerJson.put("isSitRight",isSitRight);

           playerJson.put("blockMove",blockMove);

           playerJson.put("isSitRun",isSitRun);

           playerJson.put("command", command);
           /***********************/

           playerJson.put("runAnimation", runAnimation);


           playerJson.put("rotateAnimation", rotateAnimation);

           playerJson.put("levelId", levelId);

           
           JSONObject currentPosition = new JSONObject();


           currentPosition.put("x", startLocation.x);
           currentPosition.put("y", startLocation.y);
           currentPosition.put("z", startLocation.z);

           playerJson.put("startLocation",currentPosition);

           
           return playerJson;

      }
    
    
    private void standKeys() {
        
        if (Up || Left || Right || Down) {
            if (!isAnimRun) {
                isAnimRun = true;
                runChannel.setSpeed(1);
            }
        }

        if (UpRelease || LeftRelease || RightRelease || DownRelease) {
            isAnimRun = false;
            runChannel.setSpeed(0);
        }

        if (Left && Right) {
            isAnimRun = false;
            runChannel.setSpeed(0);

            isLeftDirect = false;
            isDirectLeft = false;
            isDirectRight = false;
            isRightDirect = false;

        }

        /**
         * Set animations
         */
        //press w
        if (Up) {

        }

        //release w
        if (UpRelease) {
            UpRelease = false;

        }

        if (Down) {

        }

        if (DownRelease && Left) {
            
        }

        if (DownRelease) {
            DownRelease = false;

            if (isDirectRight) {

                isDirectLeft = false;

                isLeftDirect = false;
                isDirectRight = true;
                isRightDirect = false;

                rotateChannel.setAnim("direct-half-right");
                rotateChannel.setLoopMode(LoopMode.DontLoop);
            }

        }

        if (Down && RightRelease) {
            if (!isLeftDirect) {
                isLeftDirect = true;
                //  isDirectLeft = false;

                isDirectLeft = false;
                isDirectRight = false;
                isRightDirect = false;

                rotateChannel.setAnim("half-left-direct");
                rotateChannel.setLoopMode(LoopMode.DontLoop);
            }
        }

        if (Down && LeftRelease) {
            if (!isRightDirect) {
                isRightDirect = true;

                isLeftDirect = false;
                isDirectLeft = false;
                isDirectRight = false;

                rotateChannel.setAnim("half-right-direct");
                rotateChannel.setLoopMode(LoopMode.DontLoop);
            }
        }

        if (Down && Right) {
            if (!isDirectLeft) {
                isDirectLeft = true;
                isDirectRight = true;

                isLeftDirect = false;
                isRightDirect = false;

                rotateChannel.setAnim("direct-half-left");
                rotateChannel.setLoopMode(LoopMode.DontLoop);
            }
        }
        
        
        if (Down && Left) {
            if (!isDirectRight) {
                isDirectRight = true;
                isDirectLeft  = true;

                // isDownLeft    = true; 
                isLeftDirect  = false;
                isRightDirect = false;

                rotateChannel.setAnim("direct-half-right");
                rotateChannel.setLoopMode(LoopMode.DontLoop);
            }
        }

        if (Right && LeftRelease) {
            LeftRelease = false;

            if (!isDirectLeft) {
                isDirectLeft = true;

                isLeftDirect = false;
                isDirectRight = false;
                isRightDirect = false;

                rotateChannel.setAnim("direct-half-left");
                rotateChannel.setLoopMode(LoopMode.DontLoop);
            }

            if (!isRightDirect) {
                isRightDirect = true;

                isLeftDirect = false;
                isDirectLeft = false;
                isDirectRight = false;

                rotateChannel.setAnim("half-right-direct");
                rotateChannel.setLoopMode(LoopMode.DontLoop);
            }

        }

        if (RightRelease && Left) {
            RightRelease = false;

            if (!isDirectRight) {
                isDirectRight = true;

                isLeftDirect = false;
                isDirectLeft = false;
                isRightDirect = false;

                rotateChannel.setAnim("direct-half-left");
                rotateChannel.setLoopMode(LoopMode.DontLoop);
            }
        }

        if (Left) {
            if (!isDirectLeft) {
                isDirectLeft = true;

                isLeftDirect = false;
                isDirectRight = false;
                isRightDirect = false;

                rotateChannel.setAnim("direct-half-left");
                rotateChannel.setLoopMode(LoopMode.DontLoop);
            }
        }

        if (LeftRelease) {
            LeftRelease = false;
            //isDirectLeft = false;

            if (!isLeftDirect) {
                isLeftDirect = true;
                //  isDirectLeft = false;

                isDirectLeft = false;
                isDirectRight = false;
                isRightDirect = false;

                rotateChannel.setAnim("half-left-direct");
                rotateChannel.setLoopMode(LoopMode.DontLoop);
            }
        }

        if (Right) {
            if (!isDirectRight) {
                isDirectRight = true;

                isLeftDirect = false;
                isDirectLeft = false;
                isRightDirect = false;

                rotateChannel.setAnim("direct-half-right");
                rotateChannel.setLoopMode(LoopMode.DontLoop);
            }
        }

        if (RightRelease) {
            RightRelease = false;

            if (!isRightDirect) {
                isRightDirect = true;

                isLeftDirect = false;
                isDirectLeft = false;
                isDirectRight = false;

                rotateChannel.setAnim("half-right-direct");
                rotateChannel.setLoopMode(LoopMode.DontLoop);
            }
        }
        
        if (Jump) {
            //seryalizeTexture();
            //getStringMaterial(materialArmy);
            characterControl.jump();
        }
    }

    /**
     * //moveTarget = new Vector3f(0f, -1.5f,0f);
     *
     * //moveSpatial = characterModel.getChild("base.obj");
     *
     * //moveModel();
     */
    //private float    tpf;
    public void moveModel() {
        Vector3f start = moveSpatial.getLocalTranslation();

        float distance = moveTarget.distance(start);
        
        if (distance < 0.1f) {
            moveSpatial.setLocalTranslation(moveTarget);
            moveTarget = null;
            
        } else {
            moveSpatial.setLocalTranslation(start.interpolateLocal(moveTarget, tpf / start.distance(moveTarget)));
        }
    }
    
    public void tpfUpdate() {
        if (moveTarget != null) {
            moveModel();
        }
    }
    
    /*
    public JSONObject toJson(){

            JSONObject playerJson = new JSONObject();
            
            
         
            playerJson.put("fallSpeed", fallSpeed);
            playerJson.put("speed", speed);
            playerJson.put("gravity", gravity);

           

            playerJson.put("camRotationX",camRotationX);
            playerJson.put("camRotationY",camRotationY);
            playerJson.put("camRotationZ",camRotationZ);
            playerJson.put("camRotationW",camRotationW);
            playerJson.put("camDirectionX",camDirectionX);
            playerJson.put("camDirectionY",camDirectionY);
            playerJson.put("camDirectionZ",camDirectionZ);

            playerJson.put("camLeftX",camLeftX);
            playerJson.put("camLeftY",camLeftY);
            playerJson.put("camLeftZ",camLeftZ);

            playerJson.put("Left",Left);
            playerJson.put("LeftRelease",LeftRelease);
            playerJson.put("Right",Right);
            playerJson.put("RightRelease",RightRelease);
            playerJson.put("Up",Up);
            playerJson.put("UpRelease",UpRelease);
            playerJson.put("Down",Down);
            playerJson.put("DownRelease",DownRelease);
            playerJson.put("Jump",Jump);
            playerJson.put("JumpRelease",JumpRelease);
            playerJson.put("LClick",LClick);
            playerJson.put("LClickRelease",LClickRelease);
            playerJson.put("Sit",Sit);
            playerJson.put("SitRelease",SitRelease);

            playerJson.put("Ctrl",Ctrl);
            playerJson.put("CtrlRelease",CtrlRelease);


            playerJson.put("isAnimRun",isAnimRun);

            playerJson.put("isDirectLeft",isDirectLeft);
            playerJson.put("isLeftDirect",isLeftDirect);

            playerJson.put("isDirectRight",isDirectRight);
            playerJson.put("isRightDirect",isRightDirect);

            playerJson.put("isSit",isSit);

            playerJson.put("isStand",isStand);


            playerJson.put("isSitLeft",isSitLeft);

            playerJson.put("isSitRight",isSitRight);

            playerJson.put("blockMove",blockMove);

            playerJson.put("isSitRun",isSitRun);


            playerJson.put("runAnimation", runAnimation);


            playerJson.put("rotateAnimation", rotateAnimation);

            
            JSONObject currentPosition = new JSONObject();

            
            currentPosition.put("x", startLocation.x);
            currentPosition.put("y", startLocation.y);
            currentPosition.put("z", startLocation.z);

            playerJson.put("startLocation",currentPosition);
            
            
            return playerJson;

       }
    */
}
1 Like

Don’t modify the scene graph from another thread.

However you are doing your multiplayer needs to be properly synched with the render thread. See the articles on the wiki.

Note: updating the player position with JSON objects seems like the really slow way to go. There are fully working examples of networked games that sync player positions.

2 Likes

Note: updating the player position with JSON objects seems like the really slow way to go. There are fully working examples of networked games that sync player positions.

for example?

However you are doing your multiplayer needs to be properly synched with the render thread. See the articles on the wiki.

Which article?

Don’t modify the scene graph from another thread.

In which place?

1 Like

Networked game using SimEthereal, basic version: https://github.com/Simsilica/Examples/tree/master/sim-eth-basic
Version the uses an ES: https://github.com/Simsilica/Examples/tree/master/sim-eth-es

The one called “Multithreading” as that will be about multithreading. I googled it for you: https://jmonkeyengine.github.io/wiki/jme3/advanced/multithreading.html

It’s your code… so I don’t know. I imagine your networking code is handled by another thread?

Somewhere, you are updating the scene graph where you shouldn’t be.

2 Likes

Algorithm:

  1. I press play.
  2. Server create game and add to server level list.
  3. Add user to level at server.
  4. At client load 3d scene.
  5. Server send in message players.
  6. Client add models and add players in list.

Sync:

  1. Key press pack json
  2. Send to server json keys to level
  3. Server resend key press to all players
  4. Client install key press to model
  5. Model update

imagine your networking code is handled by another thread?

Yes:

1 Like

Recivier

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package core;


import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;
import message.JInMessages;
/**
 *
 * @author nn
 */
public class JUDPRecivier extends Thread{
     
    /**
     * server port
     */
    private final int port;
    /**
     * pool size
     */
    private final int poolSize;
    /**
     * run stop flag
     */
    public static boolean isRunning = true;
    
    public byte[] receiveData;
    
    public JUDPRecivier(int poolSize,int port){
        this.port     = port;
        this.poolSize = poolSize;
    }
    
    /**
     * Create thread poll 
     */
    @Override
    public void run() {
        try  {
            DatagramSocket serverSocket = new DatagramSocket(port);
            
            ExecutorService executor     = Executors.newFixedThreadPool(poolSize);
            
            
            while(JUDPRecivier.isRunning){
                receiveData           = new byte[2048];

                DatagramPacket receivePacket = new DatagramPacket ( receiveData, receiveData.length );
                serverSocket.receive ( receivePacket );
                
                executor.execute(
                    new JUDPRecivierHandler(serverSocket,receivePacket)
                );
                receiveData = null;
            }
            serverSocket.close();
        } catch (IOException ex) {
            
            Logger.getLogger(JUDPRecivier.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    

    /**
     * Listen user sockets 
     * send messages to message list
     * send connection to connection list
     */
    class JUDPRecivierHandler implements Runnable{
        //socket
        DatagramSocket socket;
        
        DatagramPacket receivePacket;
        
        public JUDPRecivierHandler(DatagramSocket serverSocket,DatagramPacket receivePacket) {
            this.socket        = serverSocket;
            this.receivePacket = receivePacket;
        }
        
        @Override
        public void run() {
            //String data = "";
            
            
            InetAddress inetAdress    = receivePacket.getAddress();
            String ip   = inetAdress.getHostAddress();
                        
            byte[] data = receivePacket.getData();
            
            
            
            String stringData = new String(data,0, receivePacket.getLength());
                        
            JInMessages inputSocketMessage = new JInMessages(ip,stringData);
            inputSocketMessage.insert();
            
        }
    }
}
1 Like

Sender

package core;

import config.JConfig;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;
import message.JOutMessages;

/**
 * 
 * @author padaboo I.B Aleksandrov jetananas@yandex.ru
 */
public class JUDPSender extends Thread{
    /**
     * run stop flag
     */
    public static boolean isRunning = true;
    /**
     * pool size
     */
    public int poolSize;
    /**
     * out passage
     */
    public JOutMessages message;
    /**
     * client port
     */
    public int clientPort;

    public JUDPSender(int poolSize,int clientPort){
        this.poolSize    = poolSize;
        this.clientPort  = clientPort;
    }
    
    @Override
    public void run() {
        try{
            ExecutorService executor   =  Executors.newFixedThreadPool(poolSize);
            DatagramSocket socket      =  new DatagramSocket();
            
            DatagramPacket packet;
            byte[] buffer;
            InetAddress inetAddress;
            JUDPSenderHandler handler;
            
            while(JUDPSender.isRunning){

                for (String key : JOutMessages.getKeySet()) {

                    message     =  (JOutMessages) JOutMessages.get(key);
                    

                    //System.out.println(JConfig.server_port);
                    
                    buffer      = message.json.toJSONString().getBytes("utf-8");
                    
                    
                    //System.out.println(message.json.toJSONString());
                    
                    inetAddress = InetAddress.getByName(message.ip);
                    
                    packet = new DatagramPacket(buffer, buffer.length, inetAddress, this.clientPort);
                    
                    handler = new JUDPSenderHandler(socket,packet);
                    executor.execute(handler);
                    
                    buffer = null;                                                                                                                                                                                                                                                                                                                                                                                                                                              
                } 
            }
        } catch ( SocketException ex) {
            Logger.getLogger(JUDPSender.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnknownHostException ex){
            
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(JUDPSender.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    class JUDPSenderHandler implements Runnable{

        /**
         * datagram socket
         */
        DatagramSocket socket;
        /**
         * datagram packet
         */
        DatagramPacket packet;
        
        public JUDPSenderHandler(DatagramSocket socket,DatagramPacket packet) {
            this.socket = socket;
            this.packet = packet;
        }
        
        @Override
        public void run() {
            try {
                
                socket.send(packet);
                
            } catch (IOException ex) {
                Logger.getLogger(JUDPSender.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}
1 Like

Networked game using SimEthereal, basic version: Examples/sim-eth-basic at master · Simsilica/Examples · GitHub

If JM use RPC its same.

tcp/udp + json bytes xml etc

thanks.

Where your thread update loop code? can i see. thanks

1 Like
for(String key : GameLevel.gameLevel.players.keySet()){

                GameLevel.gameLevel.players.get(key).update(tpf);

                GameLevel.gameLevel.players.get(key).tpfUpdate(); 
             }
1 Like

You want say - update models need make in separate thread?

1 Like

I’m not sure how to say this any clearer:

ALL (as in every… all, every bit) of scene graph updates (all of them. Not a single one not) must be done from the render thread. The thread that is rendering. The main thread that is rendering the scene. The one running simpleUpdate(), etc.

NOT the network thread. Not a different thread. The render thread. The one running update. It must (must always) (always) be the one updating the scene graph.

2 Likes

Understand.
If i have 100 models in Application.

How to make OOP Programming encapsulation, example:

Okay maybe this:

1 Like

I’ve provided links already.

I’ll let someone else help now because it’s kind of exhausting.

2 Likes

Yes. okay thank’s, i try.

1 Like

You should also look at the basic network wiki article.
https://jmonkeyengine.github.io/wiki/jme3/advanced/networking.html#toolbar

2 Likes

My net

1 Like

1 Like

Here’s your problem:

2 Likes

Callable and Future added to mainApp.enqueue();
Automatically executed in simpleUpdate method?

1 Like