Snippets

B4T Games Epic Roller Coasters Telemetry Receiver

Created by Lennon R. Bisolo last modified
class EpicRollerCoasters_Telemetry
{
    // Launch Options: -telemetry network
    // Launch Options: -telemetry network -port 7701
    // Launch Options: -telemetry network -ip 127.0.0.1 -port 7701

    // Default port: 7701
    private static int port = 7701;

    private static UdpClient client;
    private static IPEndPoint anyIP;

    public static string lastReceivedUDPPacket = "";

    static void Main(string[] args)
    {
        anyIP = new IPEndPoint(IPAddress.Any, 0);
        client = new UdpClient(port);

        Thread receiveThread = new Thread(new ThreadStart(ReceiveData));
        receiveThread.IsBackground = true;
        receiveThread.Start();

        // Holds the MainThread while looking for data
        receiveThread.Join();
    }

    private static void ReceiveData()
    {
        while (true)
        {
            try
            {
                byte[] data = client.Receive(ref anyIP);

                string text = Encoding.UTF8.GetString(data);

                // Latest UDPPacket
                lastReceivedUDPPacket = text;
                //Console.WriteLine(">> " + lastReceivedUDPPacket);

                // UDPPacket output example:
                // S[005.001]V[023.729]F[008.801]Y[173.541]P[000.049]R[000.052]H[000.000]W[000.004]U[005.001]A[000.119]I[-000.001]O[000.000]N[00]C[00]G[00]
                // S[026.953]V[044.193]F[016.940]Y[159.710]P[001.965]R[-003.653]H[000.182]W[000.170]U[026.952]A[000.480]I[000.541]O[-000.098]N[11]C[19]G[05]

                float speed = GetNumber("S", lastReceivedUDPPacket);
                float vibrationIntensity = GetNumber("V", lastReceivedUDPPacket);
                float vibrationFrequency = GetNumber("F", lastReceivedUDPPacket);
                float yaw = GetNumber("Y", lastReceivedUDPPacket);
                float pitch = GetNumber("P", lastReceivedUDPPacket);
                float roll = GetNumber("R", lastReceivedUDPPacket);
                float heave = GetNumber("H", lastReceivedUDPPacket);
                float sway = GetNumber("W", lastReceivedUDPPacket);
                float surge = GetNumber("U", lastReceivedUDPPacket);
                float yawVel = GetNumber("A", lastReceivedUDPPacket);
                float pitchVel = GetNumber("I", lastReceivedUDPPacket);
                float rollVel = GetNumber("O", lastReceivedUDPPacket);
                float rideIndex = GetInt("N", lastReceivedUDPPacket);
                float carIndex = GetInt("C", lastReceivedUDPPacket);
                float gunIndex = GetInt("G", lastReceivedUDPPacket);

                string rideName = ((RideType)rideIndex).ToString();
                string carName = ((CartType)carIndex).ToString();
                string gunName = ((GunType)gunIndex).ToString();

                Console.WriteLine(">> Speed: {0}, Yaw: {1}, Pitch: {2}, Roll: {3}, Heave: {4}, Sway: {5}, Surge: {6}, YawVelocity: {7}, PitchVelocity: {8}, RollVelocity: {9}, RideName: {10}, CarName: {11}, GunName: {12}, VibrationIntensity: {13}, VibrationFrequency: {14}",
                    speed, yaw, pitch, roll, heave, sway, surge, yawVel, pitchVel, rollVel, rideName, carName, gunName, vibrationIntensity, vibrationFrequency);
            }
            catch (Exception err)
            {
                Console.WriteLine("[UDPReceive] Error: " + err.ToString());
            }
        }
    }

    // Parse the packats
    private float GetNumber(string prefix, string data)
    {
        string numberRx = @"\-*\d{3}\.\d{3}";
        string dataBlockRx = @"\[" + numberRx + @"\]";

        string value = new Regex(prefix + dataBlockRx).Match(data).Value;
        float number = float.Parse(new Regex(numberRx).Match(value).Value, CultureInfo.InvariantCulture);

        return number;
    }

    private int GetInt(string prefix, string data)
    {
        string intRx = @"\-*\d{2}";
        string dataBlockRx = @"\[" + intRx + @"\]";

        string value = new Regex(prefix + dataBlockRx).Match(data).Value;
        int number = int.Parse(new Regex(intRx).Match(value).Value, CultureInfo.InvariantCulture);

        return number;
    }

    // Enums
    public enum RideType
    {
        NONE = 0,
        ROCK_FALLS = 1,
        TREX_KINGDOM = 2,
        WYVERN_SIEGE = 3,
        SNOW_LAND = 4,
        NEON_RIDER = 5,
        HALLOWEEN = 6,
        ARMAGEDDON = 7,
        LOST_FOREST = 8,
        DREAD_BLOOD = 9,
        TUWHENA_VOLCANO = 10,
        TROPICAL_ISLAND = 11,
        NORTH_POLE = 12,
        TWILIGHT = 13,
        HAUNTED_CASTLE = 14,
        OASIS = 15,
        GREAT_CANYON = 16,
        SPACE_STATION = 17,
        SECRET_CAVE = 18,
        TUTORIAL = 19,
        LOBBY = 20
    }

    public enum CartType
    {
        RockFalls = 0,
        TRexKingdom = 1,
        WyvernSiege = 2,
        Snowland = 3,
        NeonRider = 4,
        Halloween = 5,
        Armageddon = 6,
        LostForest = 7,
        DreadBlood = 8,
        TuwhenaVolcano = 9,
        None = 10,
        TropicalIsland = 11,
        NorthPole = 12,
        Twilight = 13,
        HauntedCastle = 14,
        Oasis = 15,
        GreatCanyon = 16,
        SpaceStation = 17,
        SecretCave = 18,
        Skate = 19
    }

    public enum GunType
    {
        NONE = 0,
        SLINGSHOT = 1,
        DART = 2,
        CROSSBOW = 3,
        SNOW_GUN = 4,
        LASER_GUN = 5,
        TOILET_GUN = 6,
        CAL50 = 7,
        WAND = 8,
        SHOTGUN = 9,
        TUWHENA_VOLCANO = 10,
        TROPICAL_ISLAND = 11,
        NORTH_POLE = 12,
        TWILIGHT = 13,
        HAUNTED_CASTLE = 14,
        OASIS = 15,
        GREAT_CANYON = 16,
        SPACE_STATION = 17,
        SECRET_CAVE = 18,
        CAL50_SUPRESSED = 19,
    }
}

Comments (3)

  1. Abel Condori Malmaceda

    Hi Lennon, I have a question. What is the range of each value? maximum and minimum

  2. Lennon R. Bisolo

    Hi Abel, we can’t know for sure because it varies from each ride and game mode, but you can measure by yourself. Sim Racing Studio do that for racing games for example, so you can calibrate the chair tilt angle based on each cart and track.
    Here are some informations that may help you:

    1. The speed are in meters per second
    2. Pitch, Yaw and Roll are in degrees
    3. Heave, Sway and Surge are G-Force based
    4. Pitch, Yaw and Roll Velocities are the angular velocity for each axis in meters per seconds
    5. Ride, Cart and Gun indexes are the enumerations in the code.

    All the best,

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.