1. Do you need support for Assetto Corsa Competizione? Please use the proper forum below and ALWAYS zip and attach the WHOLE "Logs" folder in your c:\users\*youruser*\AppData\Local\AC2\Saved. The "AppData" folder is hidden by default, check "Hidden items" in your Windows view properties. If you report a crash, ALWAYS zip and attach the WHOLE "Crashes" folder in the same directory.
  2. FOR ASSETTO CORSA COMPETIZIONE: If you report issues with saved games, please always zip and attach your entire User/Documents/Assetto Corsa Competizione/Savegame folder!
  3. If your game executable is missing, please add your entire Steam directory to the exceptions in your antivirus software, then run a Steam integrity check or reinstall the game altogether.

Let's talk about broadcasting (programmer's thread)

Discussion in 'ACC General Discussions' started by Minolin, Dec 12, 2018.

  1. Minolin

    Minolin Staff Member KS Dev Team

    Warning: This thread is only for modders actually programming their own broadcasting system using our new SDK.
    There is a 2nd thread for the users, like directors, commentators and streamers, so for non-programming stuff please go there.

    So welcome dear modders and coders, this is the place where we talk about the coding side of the broadcasting SDK. Given tough timelines you won't find extraordinary documentation, but I can offer you to be here and quickly respond and discuss.
    Please also keep in mind we have a 2nd thread that should contain all kinds of "end user" (=commentators, and so on) talk - you probably need to track both.


    Introduction
    So this SDK is wrapping around a UPD two way interface, where we can connect whatever you code to one or more ACC clients. The client has to be setup into broadcasting mode, basically by setting the udp port it listens to.
    Then you will receive data, and have a few options to put. I tried to do this as simple as possible, and...

    The interface
    ... that's why there is one single file in the C# project that is describing what goes over the wire:

    Code:
    steamapps\common\Assetto Corsa Competizione\sdk\broadcasting\Sources\ksBroadcastingNetwork\BroadcastingNetworkProtocol.cs
    Even if you don't speak C#, the binary serialization and deserialization is a just a chain of repetitive reads and writes. Let me get a super quick overview for non C# users:

    Incoming udp messages start at line ~92, we're passing the raw byte data to a default C# "BinaryReader" which has functions like:

    ReadInt32 - 4 byte signed integer
    ReadByte - 1 byte unsigned integer
    ReadUInt16 - 2 byte unsigned integer

    The only special things are
    a) ReadString - is a frequently used function that has a 2 byte unsigned integer length first; then a byte[] of this length which can be interpreted as UTF8 string.
    b) ReadLap - just to remove code duplication, the content is actually straight forward

    All kinds of enum types I can see are 1 byte unsigned ints, to be more readable I started to convert them to the types found in BroadcastingEnums.cs.

    The first byte always describes the message type, which branches into what content we expect.

    Arrays are usually described by one byte for the entry count, then we do whatever we look for in a for(i < entryCount).


    Below the reading functions, we have the writers - equal to "send this ACC connection a request to do X". They mirror the BinaryReader concept, so it shouldn't be much of a problem to follow this.
    In general, those commands are just requests without response, so if you for example request TV cam17, it's likely that ACC just turns on this TV camera set, but on cam13. Just use the live feedback to display the state, and users will understand what's going on without making things too complicated.

    <more to come>
     
    Last edited: Dec 13, 2018
    Ischemica and Lambo16 like this.

  2. Similar Threads
    Forum Title Date
    Chit Chat Room Let's talk about Sim Dream modding Jun 20, 2020
    ACC General Discussions Let's talk about broadcasting (user's thread) Dec 12, 2018
    Console Lounge Let's talk vote to kick Mar 18, 2017
    Console Lounge Quick race weekend (let's talk abou it Vol.1) Feb 24, 2017
    Chit Chat Room Let's talk Lotus 98T Feb 17, 2017
    Console Lounge Porsche Cayman GT4 - Let's talk gearing Jan 16, 2017
    Console Lounge Let's talk about rage quitters... Dec 9, 2016
    Chit Chat Room 935/78 - Let's talk setup and driving Oct 30, 2016
    Console Lounge Let's talk about braking Oct 6, 2016
    Suggestions Let's talk weather (I am not asking for rain). Aug 15, 2016
    Chit Chat Room Let's talk wheels...again. why not? Aug 27, 2014
    ACC General Discussions Let's get acquainted? Nov 28, 2019
    ACC General Discussions POLL! Let's buy this game again every year to support Assetto Corsa guys! Jul 20, 2019
    ACC Screenshots & Videos Let's Play VR (Pimax 5K +) Porsche + Spa Francorhamps :) Jul 2, 2019
    Suggestions Let's REQUEST CARS Here Jan 15, 2018

  3. Minolin

    Minolin Staff Member KS Dev Team

    reserved, will need the space
     
  4. ZioYuri78

    ZioYuri78 Hardcore Simmer

    Let me say i don't love C# (i used it only once years ago to create the Assetto Corsa Career Generator) but on reading the code looks like pretty clean and easy to understand, maybe i will try to wrap it into a plugin for UE4, would be nice and more easy use Slate/UMG for the client interface.

    I only need to figure out how to use a C# DLL with C++, maybe i only need to make it "managed" and load it with the plugin, wrap some code and expose it to UMG o_O
     
  5. Lambo16

    Lambo16 Gamer

    cool stuff. I'm not sure if I understand the whole system correctly though. is it a wrapper to connect to the server itself and get data such as drivers, lap times etc or to connect to a client of a server that's spectating to set its camera views and stuff like that?
     
  6. Lambo16

    Lambo16 Gamer

    and if it's the client, how does the client join as a spectator instead of a driver? because I just tried the test program and it changes the view as me as a driver, which means I can't drive anymore lol
     
  7. Minolin

    Minolin Staff Member KS Dev Team

    No, your external application connects to a local ACC client. The "major" connection will be the one displaying/recording; so first it's just a remote control to manipulate what you see without the need of knowing key combos, avoid cycling cars instead of jumping/cycling and so on.
    But soon, it'll become more compliacated - basically as complicated as real setups with multiple commentators etc. can get.

    Well no, the output of the whole thing is your local ACC client. So you can use this to watch a race for yourself (or record/stream it), but never drive in the same time.
     
    Dookie likes this.
  8. Lambo16

    Lambo16 Gamer

    alright, so this SDK is for remotely controlling what a broadcaster/spectator of a race sees. next question is how to connect/start a race as a spectator, so that I don't have to be a driver sitting at the side of the track and then connect the broadcasting program to start spectating
     
    baakstaff and D.Jankovic like this.
  9. angel.gavalda

    angel.gavalda Rookie

    I created some wrapper on javascript to connect to ACC broadcast api, in case somebody wants to improve it, feel free to fork it: https://github.com/angel-git/acc-broadcast-node/ For the moment you can see on browser your current speed, gear and delta time from your previous lap (at least in practice mode, didn't try the rest). Should be quite easy to extend and have the same functionality as the C# client.

    Angel
     
    Deatroy, Brado23, GRFOCO and 3 others like this.
  10. ZioYuri78

    ZioYuri78 Hardcore Simmer

    Ok, looks like load a C# dll in UE4 and use it cause more problems and instability than I thought, load the library is pretty easy but methods calls are instable as hell, now i start thinking that could be better rewrite the entire dll in C++, i don't really want to do it because rewrite something it's always prone to errors.

    We will see tomorrow morning how i will wake up :)
     
  11. Lambo16

    Lambo16 Gamer

    nice, I am going to be working on my own typescript client sokn
     
  12. Minolin

    Minolin Staff Member KS Dev Team

    Why do you want this in UE4? The entire concept of UDP interfaces is to be free :D
     
    After_Midnight likes this.
  13. ZioYuri78

    ZioYuri78 Hardcore Simmer

    Because for me is more easy and fast use Slate/UMG for graphics interface.
     
    D.Jankovic likes this.
  14. Minolin

    Minolin Staff Member KS Dev Team

    Ah you're doing a standalone app within UE - ok, that's reasonable and cool.
     
    ZioYuri78 and D.Jankovic like this.
  15. Lambo16

    Lambo16 Gamer

    could this be a mistake:

    Code:
    public void RequestInstantReplay(float startSessionTime, float durationMS, int initialFocusedCarIndex = -1, string initialCameraSet = "", string initialCamera = "")
    {
        using (var ms = new MemoryStream())
        using (var bw = new BinaryWriter(ms))
        {
            bw.Write((byte)OutboundMessageTypes.INSTANT_REPLAY_REQUEST); // First byte is always the command type
            bw.Write((int)ConnectionId);
    
            bw.Write((float)startSessionTime);
            bw.Write((float)durationMS);
            bw.Write((int)initialFocusedCarIndex);
    
            WriteString(bw, initialCameraSet);
            WriteString(bw, initialCamera);
    
            Send(ms.ToArray());
        }
    }
    you wrote
    Code:
    bw.Write((int)initialFocusedCarIndex);
    (BroadcastingNetworkProtocol.cs#472) which writes a 32 bit signed integer to the stream (according to https://referencesource.microsoft.com/#mscorlib/system/io/binarywriter.cs,276)
    but on BroadcastingNetworkProtocol.cs#155 you wrote
    Code:
    var driverIndex = br.ReadUInt16();
    which indicates that initialFocusedCarIndex should be written to the stream as
    Code:
    bw.Write((short)initialFocusedCarIndex);
    I could be wrong, I just started learning about buffers and such for this project
     
  16. Minolin

    Minolin Staff Member KS Dev Team

    good catch, but intended: the "focused carId" is int32 all way down, you also read

    Code:
    case InboundMessageTypes.REALTIME_UPDATE:
    ...
    update.FocusedCarIndex = br.ReadInt32();
    
    While a the real carIds / driverIds have an unsigned int16 range starting at 0, the focused car can be -1. This may happen when you join an empty server as spectator (= no cars to focus). Additionally it opens the theoretical possibility to unfocus, and just show stick with a TV cam to show standing overlays or such (although I'm not sure such a thing will be implemented).

    Looking at this example I'm not too sure if it wouldn't be better to use uint16 for the INSTANT_REPLAY_REQUEST anyways, as I doubt we will support non-focused instant replays. But on the other hand it may be a good idea to stick with a consistent datatype for the "focused car id"
     
  17. Lambo16

    Lambo16 Gamer

    ah right, I missed that. thank you
     
  18. Lambo16

    Lambo16 Gamer

    ok, this is my attempt: https://github.com/samjmckenzie/acc-ts-broadcaster
    apologies for any mistakes made, this is my first time truly working with udp sockets and binary data. trying to port certain things over from c# is quite confusing as well at times due to the way functions are named in node core library vs .net core and the fact that javascript only has one data type for numbers, i.e. number
    planning on adding a websocket implementation when I have time that works nicely with this. I chose typescript because when I do add the websocket implementation, a lot of the client code can be shared with the server which is very useful
     
  19. leosntone

    leosntone Rookie

    i want to use java code.
    Code:
    InetAddress host = InetAddress.getByName("127.0.0.1");
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            os.write((byte)1);
            os.write((byte)2);
            writeByte(os,"name");
            writeByte(os,"12345");
            os.write(100);
            writeByte(os,"12345");
            byte[] bytes = os.toByteArray();
            DatagramPacket request = new DatagramPacket(bytes, bytes.length, host, 9000);
            socket.send(request);
    but when i run code, game crash.
    how can i find game debug logs ?
     
  20. sps_for_race

    sps_for_race Alien

    "Logs" file generated in your "c:\users\*youruser*\AppData\Local\AC2\Saved\" path. The "AppData" folder is hidden by default, check "Hidden items" in your Windows view properties.
     
  21. leosntone

    leosntone Rookie

    thank you
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice