Wednesday, June 11, 2014

Server Replication

I have been spending the past two weeks re-factoring the server for our game - Starbound Aces. It is in an attempt to move to a more authoritative server model for the game to prevent cheating and game-play issues due to players being out of sync. The biggest improvement I have made is translating and rotating object on the server and sending the new positions to the players. With the aid of the LWJGL and the Apache Math3 API, I was able to imitate the original Unity C# scripts we had for movement onto the server in Java.

Here is the source code for that:

package com.gspteama.gamedriver;
import org.apache.commons.math3.geometry.euclidean.threed.Rotation;
import org.apache.commons.math3.geometry.euclidean.threed.RotationOrder;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;
import org.lwjgl.util.vector.Vector4f;
public class Movement{
    public float Velocity;
    public float Acceleration;
    
    private float maxVelocity;
    
    protected Vector3f position = new Vector3f();
    protected Vector3f rotation = new Vector3f();
    protected Vector4f quaternion = new Vector4f();
    
    protected static final Vector3f UP = new Vector3f(0.0f, 1.0f, 0.0f);
    protected static final Vector3f LEFT = new Vector3f(-1.0f, 0.0f, 0.0f);
    protected static final Vector3f FORWARD = new Vector3f(0.0f,0.0f, 1.0f);
    
    protected Matrix4f transform = new Matrix4f();
    
    public void onUpdate(float deltaTime){
        Velocity = Velocity + Acceleration * deltaTime;
        if(Velocity >= maxVelocity){
            Velocity = maxVelocity;
        }
        
        Rotation rotator = new Rotation(RotationOrder.XYZ, rotation.getX(),
                rotation.getY(),
                rotation.getZ());
        quaternion = new Vector4f((float)rotator.getQ0(),
                (float)rotator.getQ1(),
                (float)rotator.getQ2(),
                (float)rotator.getQ3());
        
        transform.setIdentity();
        
        transform = transform.translate(position);
        transform = transform.rotate(rotation.getY(), UP);
        transform = transform.rotate(rotation.getX(), LEFT);
        transform = transform.rotate(rotation.getZ(), FORWARD);
        transform = transform.scale(new Vector3f(1.0f, 1.0f, 1.0f));
        
        //to row major
        transform.transpose();
        
        //get the forward vector
        Vector3f forward = new Vector3f(transform.m20,
                                        transform.m21,
                                        transform.m22);
        forward.normalise();
                                        
        Vector3f forwardVel = new Vector3f(forward.getX() * Velocity,
                                            forward.getY() * Velocity,
                                            forward.getZ() * Velocity);
        
        position = Vector3f.add(position, forwardVel, position);
    }
    public Movement(float maxVelocity){
        this.maxVelocity = maxVelocity;
        Velocity = 0.0f;
        Acceleration = 0.0f;
        transform.setIdentity();
    }
    
    public void onLeft(float value){//A
        rotation.y += value;
    }
    
    public void onRight(float value){//D
        onLeft(value);
    }
    
    public void onUp(float value){//W
        Acceleration += value;
    }
    
    public void onDown(float value){//S
        Acceleration -= value;
    }
    
    public void onHorizontal(float value){//MouseX
        rotation.z += value;
    }
    
    public void onVertical(float value){//MouseY
        rotation.x += value;
    }
    
    public float[] getPosition(){
        return new float[]{position.getX(),
            position.getY(),
            position.getZ()
        };
    }
    
    public float[] getQuaternion(){
        return new float[]{quaternion.getX(),
            quaternion.getY(),
            quaternion.getZ(),
            quaternion.getW()
        };
    }
}

No comments:

Post a Comment