JGN FlagRush Tutorial to FPS Migration Networking issue

Hi All,

I have migrated FlagRush to FPS (with other Player model + Node). I have changed:

FlagRushTestServer - changed Vehicle to Player object

FlagRushTestClient - changed Vehicle to Player object

FlagRushTest - changed Vehicle to Player and change buildRemotePlayer



When running server and client,they got connected but player is not replicated on client side I got:



Unable to find object: 1 on Client



another strange message on client is:



WARNING: message is not a playermessage: com.captiveimagination.jgn.synchronizat

ion.message.SynchronizeRequestIDMessage@8c2f76



I try some debugging in JGN and checked that on client side,message doesn't contain player(or are empty)

here is my code:

changes in Server&Client are cosmetic, so only Player and FlagRushTest:



Player

import java.util.concurrent.Callable;
import java.util.concurrent.Future;


import com.captiveimagination.jgn.synchronization.SyncObjectManager;
import com.captiveimagination.jgn.synchronization.message.SynchronizeCreateMessage;
import com.captiveimagination.jgn.synchronization.message.SynchronizeRemoveMessage;
import com.captiveimagination.jmenet.flagrush.fps.Player;
import com.jme.bounding.BoundingCapsule;
import com.jme.math.Vector3f;
import com.jme.renderer.Renderer;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.util.GameTaskQueueManager;
import com.jme.util.export.binary.BinaryImporter;
import com.jmex.model.converters.MilkToJme;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import jmetest.intersection.TestPick;

public abstract class FlagRushTest implements SyncObjectManager {
   private Node scene;
   
   public void setScene(Node scene) {
      this.scene = scene;
   }
   
   public Object create(SynchronizeCreateMessage scm) {
      System.out.println("CREATING PLAYER!");
      return buildRemotePlayer();
   }

   public boolean remove(SynchronizeRemoveMessage srm, Object obj) {
      return removeRemotePlayer((Player)obj);
   }
   
   private Player buildRemotePlayer() {
      Future<Player> future = GameTaskQueueManager.getManager().update(new Callable<Player> () {
         public Player call() throws Exception {
                Spatial model = null;
                MilkToJme converter = new MilkToJme();
                URL MSFile = TestPick.class.getClassLoader().getResource(
                        "jmetest/data/model/msascii/run.ms3d");
                ByteArrayOutputStream BO = new ByteArrayOutputStream();

                try {
                    converter.convert(MSFile.openStream(), BO);
                } catch (IOException e) {
                    e.printStackTrace();
                    System.exit(0);
                }
                model = null;
                try {
                    model = (Node)BinaryImporter.getInstance().load(new ByteArrayInputStream(BO
                            .toByteArray()));
                    model.setModelBound(new BoundingCapsule());
                    model.updateModelBound();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                //((JointController) model.getController(0)).setActive(false);

                //model.setLocalScale(.002f);
              Player player = new Player();
                player.setModel(model);
              player.setLocalTranslation(new Vector3f(100,0, 100));
                scene.attachChild(player);
                scene.updateGeometricState(0, true);
                player.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
                scene.updateRenderState();
                return player;

         }
      });
      try {
         return future.get();
      } catch(Exception exc) {
         exc.printStackTrace();
      }
      return null;
   }
   
   private boolean removeRemotePlayer(Player player) {
      return player.removeFromParent();
   }
}



Player:

import java.util.Random;

import com.jme.animation.SpatialTransformer;
import com.jme.bounding.BoundingCapsule;
import com.jme.input.InputHandler;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.input.MouseInput;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.scene.CameraNode;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.system.DisplaySystem;
import com.jme.util.Timer;
import com.jme.util.export.binary.BinaryImporter;
import com.jmex.model.converters.MilkToJme;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import jmetest.intersection.TestPick;

/**
 *
 * @author vlad
 */
public class Player extends Node{

    private static int i = 1;

    private static float maxHealth = 3000;

    public static int playerBulletGroundHitSamples = 3;

    private static int playerDeadEvent = 2;

    private static int playerHitEvent = 1;

    private static Random r = new Random();

    /**
     * @return Returns the maxHealth.
     */
    public static float getMaxHealth()
    {
        return maxHealth;
    }

    /**
     * @param maxHealth
     *            The maxHealth to set.
     */
    public static void setMaxHealth(float maxHealth)
    {
        Player.maxHealth = maxHealth;
    }

    private int attachedWeapon;

    /**
     * has our camera and our gun
     */
    private CameraNode camNode;

    private float currentHealth;

    /**
     * our bullet action
     */
    private FireBullet fireBullet;

    /**
     * has our laser gun
     */
    private Node gunLaser;

    /**
     * has our MP5 gun
     */
    private Node gunMP5;

    private float hitPlayTime = 0.2f;

    /**
     * is player alive ?!
     */
    private boolean isAlive;

    private boolean isHit;

    /**
     * handles all keyboard commands
     */
    private KeyBindingManager keyboard;
    private Quaternion origRot = new Quaternion();

    public int[] playerBulletEventsArray;

    public int[] playerBulletSamplesArray;

    public int playerBulletSoundNode;

    private int playerDeadSample;

    /**
     * amount of bullets the player was hit
     */
    private int playerHits = 0;

    private int playerHitSample;

    private int playerSoundNode;

    private Quaternion rot = new Quaternion();

    private Node target;

    private Spatial model;
    /**
     * mouse input
     */
    private MouseInput thisMouse;

    private MySpatialTransformer trans = new MySpatialTransformer(1);

    /**
     * creates a new Player and attaches a gun to the camNode
     *
     * @param camNode
     * @param input
     * @param target
     * @param timer
     */
    public Player(CameraNode camNode, InputHandler input, Node target,
            Timer timer)
    {
        super("Player");
        this.camNode = camNode;
        this.target = target;
        currentHealth = maxHealth;
        initGuns();
        // set controls
        setControlBindings("LWJGL", input, timer);
        isHit = false;
        isAlive = true;

        buildPlayerModel();
    }

    public Player(){
        super("Player");
        currentHealth = maxHealth;
        //buildPlayerModel();
        //initGunsRemote();
        // set controls
        isHit = false;
        isAlive = true;

       
    }
    /**
     * change to the specified gun
     *
     * @param type
     */
    public void changeGun(int type)
    {
        camNode.detachAllChildren();
        if (type == WeaponMachineGun.MP5)
        {
            camNode.attachChild(gunMP5);
            attachedWeapon = WeaponMachineGun.MP5;
            fireBullet.setAttachedWeapon(attachedWeapon);
        }
        if (type == WeaponLaser.LASER)
        {
            camNode.attachChild(gunLaser);
            attachedWeapon = WeaponLaser.LASER;
            fireBullet.setAttachedWeapon(attachedWeapon);
        }
        camNode.updateGeometricState(0.0f, true);
        camNode.updateRenderState();
    }

    /**
     * check if a specified key is pressed or any specified mouse action occured
     * and performs the specified action should be called every frame in
     * simpleUpdate
     */
    public void checkInput()
    {
        if (isAlive)
        {
            if (keyboard.isValidCommand("changeToLaser", true))
            {
                changeGun(WeaponLaser.LASER);
            }
            if (keyboard.isValidCommand("changeToMP5", true))
            {
                changeGun(WeaponMachineGun.MP5);
            }
            if (keyboard.isValidCommand("altFire", true))
            {
                fireBullet.setAltFire(true);
                fireBullet.setThirdFire(false);
                fireBullet.performAction(null);
            }
            if (keyboard.isValidCommand("fire", true))
            {
                fireBullet.setAltFire(false);
                fireBullet.setThirdFire(false);
                fireBullet.performAction(null);
            }
            if (keyboard.isValidCommand("thirdFire", true))
            {
                fireBullet.setAltFire(false);
                fireBullet.setThirdFire(true);
                fireBullet.performAction(null);
            }

            int test = thisMouse.getWheelDelta();
            if (test < 0 || test > 0)
            {
                if (attachedWeapon == WeaponMachineGun.MP5)
                {
                    changeGun(WeaponLaser.LASER);
                }
                else if (attachedWeapon == WeaponLaser.LASER)
                {
                    changeGun(WeaponMachineGun.MP5);
                }
            }
            if (thisMouse.isButtonDown(0))
            {
                fireBullet.setAltFire(false);
                fireBullet.setThirdFire(false);
                fireBullet.performAction(null);
            }
            // second fire mode
            if (thisMouse.isButtonDown(1))
            {
                fireBullet.setAltFire(true);
                fireBullet.setThirdFire(false);
                fireBullet.performAction(null);
            }
            // third fire mode
            if (thisMouse.isButtonDown(2))
            {
                fireBullet.setAltFire(false);
                fireBullet.setThirdFire(true);
                fireBullet.performAction(null);
            }
        }       
        if (keyboard.isValidCommand("takeScreenShot", false))
        {
            DisplaySystem.getDisplaySystem().getRenderer().takeScreenShot("screenshots/screen" + i);
            i++;
        }

    }

    /**
     * should be called when the player died
     */
    public void die()
    {
        isAlive = false;
        // last cry here ;D
        Vector3f pos = camNode.getWorldTranslation();
    }

    public int getAttachedWeapon()
    {
        return attachedWeapon;
    }

    /**
     * @return Returns the currentHealth.
     */
    public float getCurrentHealth()
    {
        return currentHealth;
    }

    /**
     * @return Returns the currentHealth.
     */
    public float getCurrentHealthInPercent()
    {
        return (currentHealth / maxHealth) * 100;
    }

    /**
     * @return Returns the hitPlayTime.
     */
    public float getHitPlayTime()
    {
        return hitPlayTime;
    }

    /**
     * @return Returns the playerHits.
     */
    public int getPlayerHits()
    {
        return playerHits;
    }

    /**
     * gets a random sample identifier of the specified sample identifier amount
     *
     * @param amountOfSamples
     * @return
     */
    public int getRandomSample(int amountOfSamples)
    {
        return r.nextInt(amountOfSamples);
    }

    /**
     * load a new gun at startup
     */
    private void initGuns()
    {
        gunMP5 = WeaponMachineGun.createMP5();
        gunMP5.setName("MP5Node");

        gunLaser = WeaponLaser.createLaser();
        gunLaser.setName("LaserNode");
        attachedWeapon = WeaponLaser.LASER;
        // reset cam
        camNode.getCamera().setLocation(new Vector3f(0, 0, 0));
        camNode.setLocalTranslation(new Vector3f(0, 0, 0));
        // attach first Weapon
        camNode.attachChild(gunLaser);
    }

    private void initGunsRemote()
    {
        gunMP5 = WeaponMachineGun.createMP5();
        gunMP5.setName("MP5Node");

        gunLaser = WeaponLaser.createLaser();
        gunLaser.setName("LaserNode");
        attachedWeapon = WeaponLaser.LASER;
        // reset cam
      
        //model.attachChild(gunLaser);
    }
    /**
     * @return Returns the isAlive.
     */
    public boolean isAlive()
    {
        return isAlive;
    }

    /**
     * @return Returns the isHit.
     */
    public boolean isHit()
    {
        return isHit;
    }

    /**
     * should be called when the player is hit
     */
    public void playerHit()
    {
        playerHits++;

        // play a blood particle effect ;O
        /*ParticleMesh manager = ExplosionFactory.getHitEffect();

        manager.setLocalScale(0.65f);
        manager.setLocalTranslation(new Vector3f(camNode.getLocalTranslation()));
        manager.forceRespawn();
        camNode.getParent().attachChild(manager);
        manager.setCullHint(Spatial.CullHint.Never);*/
        //manager.setForceView(true);

        // cry here ;D
        Vector3f pos = camNode.getWorldTranslation();

        playHitAnimation();

    }

    /**
     * shakes the camera ;D
     */
    private void playHitAnimation()
    {
        // is player is hit again although the animation hasn't fully played
        trans.setActive(false);
        camNode.removeController(trans);
        camNode.setLocalRotation(origRot);
        // only use this if you don'T use removeController();
        origRot = camNode.getWorldRotation();

        trans = new MySpatialTransformer(1);

        //        origRot = camNode.getWorldRotation();

        trans.setObject(camNode, 0, -1);

        // rot up-down
        rot.fromAngleAxis(FastMath.DEG_TO_RAD * (r.nextInt(20) - 10),
                new Vector3f(1, 0, 0));
        trans.setRotation(0, 0, origRot.mult(rot));

        // rot left-right
        rot.fromAngleAxis(FastMath.DEG_TO_RAD * (r.nextInt(20) - 10),
                new Vector3f(0, 1, 0));
        trans.setRotation(0, hitPlayTime / 2, origRot.mult(rot));

        // set back to orig rotation
        trans.setRotation(0, hitPlayTime, origRot);

        trans.interpolateMissing();
        trans.setRepeatType(SpatialTransformer.RT_CLAMP);
        camNode.addController(trans);
        isHit = true;
    }

    /**
     * remove all controls
     * @param input
     */
    public void removeControlBindings(InputHandler input)
    {
        keyboard.remove("changeToLaser");
        keyboard.remove("changeToMP5");
        keyboard.remove("fire");
        keyboard.remove("altFire");
        keyboard.remove("thirdFire");
//        keyboard.remove("cheatOn");
//        keyboard.remove("cheatOff");
        input.removeAction(fireBullet);

        // clears all
//        input.clearKeyboardActions();
//        input.clearMouseActions();

    }

    /**
     * removes the controller when from the hit animation
     */
    public void removeController()
    {
        trans.setActive(false);
        camNode.removeController(trans);
        // should be set new here only cause the isHit method could be called
        // again
        // although the animation is not over yet...here it is over
        // and the controller can also be removed...
        origRot = camNode.getWorldRotation();
    }

    /**
     * @param isAlive
     *            The isAlive to set.
     */
    public void setAlive(boolean isAlive)
    {
        this.isAlive = isAlive;
    }

    /**
     * set all control bindings
     */
    private void setControlBindings(String api, InputHandler input, Timer timer)
    {
        keyboard = KeyBindingManager.getKeyBindingManager();
        //        InputSystem.createInputSystem(api);

        keyboard.set("changeToLaser", KeyInput.KEY_1);
        keyboard.set("changeToMP5", KeyInput.KEY_2);
        keyboard.set("fire", KeyInput.KEY_F);
        keyboard.set("altFire", KeyInput.KEY_R);
        keyboard.set("thirdFire", KeyInput.KEY_G);    
        keyboard.set("takeScreenShot", KeyInput.KEY_F9);

        /**
         * Set the action called "firebullet", bound to KEY_Space, to
         * performAction FireBullet
         */
        fireBullet = new FireBullet(camNode, timer, target);
        input.addAction(fireBullet,"firebullet",true);

        // set mouse input
        thisMouse = MouseInput.get();

    }

    /**
     * @param currentHealth
     *            The currentHealth to set.
     */
    public void setCurrentHealth(float currentHealth)
    {
        this.currentHealth = currentHealth;
    }

    /**
     * @param isHit
     *            The isHit to set.
     */
    public void setHit(boolean isHit)
    {
        this.isHit = isHit;
    }

    private void buildPlayerModel(){
        MilkToJme converter = new MilkToJme();
      URL MSFile = TestPick.class.getClassLoader().getResource(
            "jmetest/data/model/msascii/run.ms3d");
      ByteArrayOutputStream BO = new ByteArrayOutputStream();

      try {
         converter.convert(MSFile.openStream(), BO);
      } catch (IOException e) {
         e.printStackTrace();
         System.exit(0);
      }
      model = null;
      try {
         model = (Node)BinaryImporter.getInstance().load(new ByteArrayInputStream(BO
               .toByteArray()));
            model.setModelBound(new BoundingCapsule());
            model.updateModelBound();
      } catch (IOException e) {
         e.printStackTrace();
      }
      //((JointController) model.getController(0)).setActive(false);
        //camNode.attachChild(model);
    }

    public void setModel(Spatial model){
        this.model = model;
    }
}

It works just fine with the original FlagRush networking example?

yes it did.

That is the amazing thingy, the change is really insignificant - just new class instead of Vehicle plus some minor changes and it fail.