Skip to content

The RaceRoom Racing Experience Broadcast Web Overlay allows you to create a web page that is superimposed on the in-game spectator gameplay.

License

Notifications You must be signed in to change notification settings

sector3studios/r3e-spectator-overlay

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

59 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

R3E

Spectator Web Overlay

The RaceRoom Racing Experience Broadcast Web Overlay allows you to create a web page that is superimposed on the in-game spectator gameplay.

How get started with development

  • Create a basic .html file
  • Include r3e.js in your page and you should be good to get started
  • Put it on a publicly hosted server
  • If you are looking for a basic example take a look at example-overlay.html or the API reference below.

How to use in game

  1. Download RaceRoom Racing Experience from Steam
  2. Go into the game's Properties in the Steam client and change "SET LAUNCH OPTIONS..." to:
  • Start RaceRoom Racing Experience
  • Enter the Multiplayer server list though the game menus
  • Join the server you want to spectate
    • There are no requirements to own the content used on the server

API

r3e.getVehicleInfo

Get vehicle related data based on the slotId passed.

r3e.getVehicleInfo({
    'slotId': 0
}, function(vehicleInfo) {
    /*
    // vehicleInfo
    {
        "slotId": "int",
        "rpm": "int",
        "gear": "int",
        "speed": "int", //km per h
        "drsLeft": "int",
        "drsTotal": "int",
        "drsEnabled": "bool"
    }
    */
});

r3e.getPitInfo

Get "pit" related data based on the slotId passed.

r3e.getPitInfo({
    'slotId': 0
}, function(pitInfo) {
    /*
    // pitInfo
    {
        "slotId": "int",
        "inPitlane": "bool",
        "isPitting": "bool",
        "numPitstops": "int",
        "servedMandatoryPitstop": "bool",
        "tyreType": "string",
        "damage": {
            "engine": "int", // 0 - 100
            "transmission": "int", // 0 - 100
            "frontAero": "int", // 0 - 100
            "rearAero": "int" // 0 - 100
        }
    }
    */
});

r3e.getPushToPassInfo

Get push to pass related data based on the slotId passed.

r3e.getPushToPassInfo({
    'slotId': 0
}, function(pushToPassInfo) {
    /*
    // pushToPassInfo
    {
        "active": "bool",
        "allowed": "bool",
        "amountLeft": "int",
        "durationTimer": "int",
        "slotId": "int",
        "waitTimer": "int"
    }
    */
});

r3e.getExtendedInfo

Get extended driver related data based on the slotId passed.

r3e.getExtendedInfo({
    'slotId': 0
}, function(extendedInfo) {
    /*
    // extendedInfo
    {
        "slotId": "int",
        "currentSector": "int",
        "currentLapInfo": {
            "valid": "bool",
            "sector1": "int", // milliseconds, -1 if not set
            "sector2": "int", // milliseconds, -1 if not set
            "sector3": "int" // milliseconds, -1 if not set
        },
        "lastTenLapsInfo": [
            {
                "valid": "bool",
                "sector1": "int", // milliseconds, -1 if not set
                "sector2": "int", // milliseconds, -1 if not set
                "sector3": "int" // milliseconds, -1 if not set
            }
        ]
    }
    */
});

r3e.getDriverInfo

Get driver related data based on the slotId passed.

r3e.getDriverInfo({
    'slotId': 0
}, function(driverInfo) {
    /*
    // driverInfo
    {
        "name": "string",
        "slotId": "int",
        "portalId": "int",
        "teamId": "int",
        "classId": "int",
        "manufacturerId": "int",
        "liveryId": "int",
        "performanceIndex": "int",
        "mandatoryPitstopPerformed": "int",
        "scoreInfo": {
            "positionOverall": "int",
            "positionRaceGridClass": "int",
            "positionClass": "int",
            "laps": "int",
            "distanceTravelled": "int", //meters
            "currentLapTime": "int", //milliseconds
            "bestLapInfo": {
                "valid": "bool",
                "sector1": "int", //milliseconds, -1 if not set
                "sector2": "int", //milliseconds, -1 if not set
                "sector3": "int" //milliseconds, -1 if not set
            },
            "distanceDiff": "int", //meters
            "timeDiff": "int", //milliseconds
            "lapDiff": "int",
            "flagInfo": {
                "black": "int",
                "blue": "int",
                "yellow": "int",
                "causedYellow": "bool"
            }
        }
    }
    */
});

r3e.getDriversInfo

Get driver related data for all drivers on the server.

r3e.getDriversInfo(function(driversInfo) {
    /*
    // driversInfo
    [
        {
            "name": "string",
            "slotId": "int",
            "portalId": "int",
            "teamId": "int",
            "classId": "int",
            "manufacturerId": "int",
            "liveryId": "int",
            "performanceIndex": "int",
            "mandatoryPitstopPerformed": "int",
            "scoreInfo": {
                "positionOverall": "int",
                "positionRaceGridClass": "int",
                "positionClass": "int",
                "laps": "int",
                "distanceTravelled": "int", //meters
                "currentLapTime": "int", //milliseconds
                "bestLapInfo": {
                    "valid": "bool",
                    "sector1": "int", //milliseconds, -1 if not set
                    "sector2": "int", //milliseconds, -1 if not set
                    "sector3": "int" //milliseconds, -1 if not set
                },
                "distanceDiff": "int", //meters
                "timeDiff": "int", //milliseconds
                "lapDiff": "int",
                "flagInfo": {
                    "black": "int",
                    "blue": "int",
                    "yellow": "int",
                    "causedYellow": "bool"
                }
            }
        },
        ...
    ]
    */
});

r3e.getSessionInfo

Get the current session data.

r3e.getSessionInfo(function(sessionInfo) {
    /*
    // type can be:
    'Unknown',
    'Practice',
    'Qualify',
    'Warmup',
    'Race 1',
    'Race 2',
    'Race 3',
    'Event Results'

    // phase can be:
    'START',
    'WALKTHROUGH',
    'GARAGE',
    'FORMATION',
    'COUNTDOWN',
    'GREEN',
    'CHECKERED',
    'END'

    // sessionInfo
    {
        "type": "string",
        "phase": "string",
        "timeTotal": "int", //seconds
        "timeLeft": "int" //seconds
    }
    */
});

r3e.getEventInfo

Get the current event data.

r3e.getEventInfo(function(eventInfo) {
    /*
    // eventInfo
    {
        "serverName": "string",
        "metric": "bool",
        "trackId": "int",
        "trackName": "string",
        "layoutId": "int",
        "layoutName": "string",
        "length": "int",
        "weatherInfo": {
            "ambientTemp": "int",
            "trackTemp": "int",
            "windSpeed": "int",
            "conditions": "string",
            "forecast": "string"
        }
    }
    */
});

r3e.showCursor

Enables or disables the in game cursor.

r3e.showCursor({
    "show": "bool"
});

Cameras

Set the focused driver and which camera should be used.

nosecam

r3e.setCamera.nosecam({'slotId': 0})

cockpit

r3e.setCamera.cockpit({'slotId': 0})

swingman

r3e.setCamera.swingman({'slotId': 0})

onboard

r3e.setCamera.onboard({'slotId': 0})

trackside

r3e.setCamera.trackside({'slotId': 0})

onboard1

r3e.setCamera.onboard1({'slotId': 0})

onboard2

r3e.setCamera.onboard2({'slotId': 0})

frontCam

r3e.setCamera.frontCam({'slotId': 0})

rearCam

r3e.setCamera.rearCam({'slotId': 0})

flFront

r3e.setCamera.flFront({'slotId': 0})

frFront

r3e.setCamera.frFront({'slotId': 0})

rlRear

r3e.setCamera.rlRear({'slotId': 0})

rrRear

r3e.setCamera.rrRear({'slotId': 0})

rlFront

r3e.setCamera.rlFront({'slotId': 0})

rrFront

r3e.setCamera.rrFront({'slotId': 0})

exhaust

r3e.setCamera.exhaust({'slotId': 0})

wing

r3e.setCamera.wing({'slotId': 0})

r3e.waitOnResults

If you want to handle showing results running this will put you in charge of triggering the "proceed" trigger.

r3e.waitOnResults({'wait': true})

r3e.goToNextEvent

If you ran r3e.waitOnResults you should trigger r3e.goToNextEvent when you are done showing the results. Otherwise the game will just stay idle and not connect to the next event on the mp server.

Make sure you don't run this too soon after r3e.on.resultsUpdate. Then you might experience connection issues as the server needs time to start a new event.

Default values when not using r3e.waitOnResults is 30 seceonds. 20+ should be fine.

r3e.goToNextEvent()

r3e.exit

Takes you back to multiplayer menus.

r3e.exit()

r3e.on.resultsUpdate

Pass r3e.on.resultsUpdate a callback which will get executed when the game client has results to show.

This only gets called at the end of a race session.

r3e.on.resultsUpdate(function(results) {
    /*
    // results
    {
        "Results": [
            {
                "name": "string",
                "portalId": "int",
                "teamId": "int",
                "classId": "int",
                "manufacturerId": "int",
                "liveryId": "int",
                "positionOverall": "int",
                "positionClass": "int",
                "finishStatus": "string",
                "totalTime": "int", // milliseconds
                "lapsBehind": "int",
                "penaltyTime": "int",
                "penaltyWeight": "int",
                "bestLapInfo": {
                    "valid": "bool",
                    "sector1": "int", // milliseconds, -1 if not set
                    "sector2": "int", // milliseconds, -1 if not set
                    "sector3": "int" // milliseconds, -1 if not set
                }
            },
            ...
        ]
    }
    */
});

r3e.on.eventOccurred

Pass r3e.on.eventOccurred a callback which will get executed when the game client has an event to show.

r3e.on.eventOccurred(function(event) {
    /*
    // event
    {
        "slotId": "int",

        // DriveThrough = 0,
        // StopAndGo = 1,
        // Pitstop = 2,
        // Time = 3,
        // Slowdown = 4,
        // Disqualify = 5,
        // Misc = 6,
        "type": "int",

        // Based on the type you can assume the reason is:
        // DriveThroughPenaltyInvalid = 0,
        // DriveThroughPenaltyCutTrack = 1,
        // DriveThroughPenaltyPitSpeeding = 2,
        // DriveThroughPenaltyFalseStart = 3,
        // DriveThroughPenaltyIgnoredBlue = 4,
        // DriveThroughPenaltyDrivingTooSlow = 5,
        // DriveThroughPenaltyIllegallyPassedBeforeGreen = 6,
        // DriveThroughPenaltyIllegallyPassedBeforeFinish = 7,
        // DriveThroughPenaltyIllegallyPassedBeforePitEntrance = 8,
        // DriveThroughPenaltyIgnoredSlowDown = 9,
        // DriveThroughPenaltyMax = 10

        // StopAndGoPenaltyInvalid = 0,
        // StopAndGoPenaltyCutTrack1st = 1,
        // StopAndGoPenaltyCutTrackMult = 2,
        // StopAndGoPenaltyYellowFlagOvertake = 3,
        // StopAndGoPenaltyMax = 4

        // PitstopPenaltyInvalid = 0,
        // PitstopPenaltyIgnoredPitstopWindow = 1,
        // PitstopPenaltyMax = 2

        // ServableTimePenaltyInvalid = 0,
        // ServableTimePenaltyServedMandatoryPitstopLate = 1,
        // ServableTimePenaltyIgnoredMinimumPitstopDuration = 2,
        // ServableTimePenaltyMax = 3

        // SlowDownPenaltyInvalid = 0,
        // SlowDownPenaltyCutTrack1st = 1,
        // SlowDownPenaltyCutTrackMult = 2,
        // SlowDownPenaltyMax = 3

        // DisqualifyPenaltyInvalid = -1,
        // DisqualifyPenaltyFalseStart = 0,
        // DisqualifyPenaltyPitlaneSpeeding = 1,
        // DisqualifyPenaltyWrongWay = 2,
        // DisqualifyPenaltyEnteringPitsUnderRed = 3,
        // DisqualifyPenaltyExitingPitsUnderRed = 4,
        // DisqualifyPenaltyFailedDriverChange = 5,
        // DisqualifyPenaltyThreeDriveThroughsInLap = 6,
        // DisqualifyPenaltyLappedFieldMultipleTimes = 7,
        // DisqualifyPenaltyIgnoredDriveThroughPenalty = 8,
        // DisqualifyPenaltyIgnoredStopAndGoPenalty = 9,
        // DisqualifyPenaltyIgnoredPitStopPenalty = 10,
        // DisqualifyPenaltyIgnoredTimePenalty = 11,
        // DisqualifyPenaltyExcessiveCutting = 12,
        // DisqualifyPenaltyIgnoredBlueFlag = 13,
        // DisqualifyPenaltyMax = 14

        // MiscClassLeaderPitting = 0
        // MiscClassNewLeader = 1
        // MiscClassNewFastestLap = 2
        // MiscClassNewFastestSector = 3
        // MiscCollision = 4
        // MiscOffTrack = 5
        // MiscStationary = 6
        // MiscLostControl = 7
        // MiscCriticalDamage = 8
        // MiscPuncture = 9

        "reason": "int"
    }
    */
});

Handy to know

  • To use Chromium debugger

    • Put devtools_resources.pak in Game folder
    • Start with -webdev -broadcastUrl=<url>
    • Go to http://localhost:8080 using Chrome
  • The overlay page will be reloaded between each session.

  • How do I fetch the livery renders based on liveryId?

  • How can I get user information from portalId?

  • How can I get relevant information based on teamId, manufacturerId, liveryId, classId?

    • For that you will have to include r3e-data.js which is a part of this repo. It contains data for the corresponding ids.

Known issues/things to think about

  • When joining in race session timeleft will be incorrect.
  • The CEF message loop updates at 60Hz so callbacks for retrieving data might take a while to trigger.
  • Triggering too many API calls will affect game performance.
  • Using Chromium 33.0.1750.58

Support

Please visit our support forum thread.

License

See LICENSE.

About

The RaceRoom Racing Experience Broadcast Web Overlay allows you to create a web page that is superimposed on the in-game spectator gameplay.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published