SteelSeries / gamesense-sdk

472 stars 146 forks source link

SSE not responding/crashing when rapidly sending events #32

Closed arxae closed 5 years ago

arxae commented 7 years ago

I'll give a description on what i'm working on first:

I am intercepting the calls Overwatch makes, and redirecting them to SSE. There is a list of colors that makes up the effect. I am assuming index 0 = A, index 1 = B and so on.

The following steps are taken:

The 2 effects i know 100% that should occur:

  1. On the main menu, the entire keyboard should be the same color (the gold/orange OW uses)
  2. When changing characters in the character screen, a wave should run accros the keyboard (with the character specific color)

They either don't happen, or only partially. And it seems to crash SSE3. Since randomly during the color changes, they keyboard leds don't change anymore. And when i try to configure the game, i get a message saying there are no products connected. If i try to change a preset from a device, nothing happens. When i restart SSE, everything pops responds again as expected.

I also tried to just using the function-keys zone using a single handler. And while not having the desired effect, they do flicker as they should have.

So this tells me that i'm sending too much data in a too rapid pace. But i would like to figure this out how to do this optimal. Since there is no need to allow the user to customize the colors, is there a way to just set keys a certain colors witouth all the bindings and such?

And the added bonus, Overwatch support for Gamesense, someting a lot of people want :P

I have attached a log of what i'm sending and such, if needed i can host my code as well.

RazerInterceptor.txt

davidtibbetts commented 7 years ago

Hi arxae, really great to hear what you're doing, and we certainly would love to help! Per-key event binding is way more than you need to do. It would be much simpler to just send events with values and use the SSE GUI to put those events on groups of keys. Have you tried using some of the default groups, like 'main-keyboard'? I'll talk with the other guys about this on Monday morning. If you are willing to share your project's code somewhere, that would also help us understand more about the frequency and amount of data you're sending, so we can at least make sure SSE won't crash from heavy amounts of data. Thanks!!

arxae commented 7 years ago

The data coming in from the razer calls is just a list of colors. They just need to be assigned to each key. I am assuming it's just a sequential list of usb HIDs. So user customization is out of the question.

I am aware of 4 different type of effects they are using:

But from the razer side, it's just arrays and arrays of colors (in BGR format). They don't differentiate between these 3 types. If i understand the razer documentation correctly, they can just setup keyboard "animations" and then just trigger them. This sends out the "frames" of the animation directly to the keyboard and the razer libraries handle the display and "playback"

This video shows the effects https://www.youtube.com/watch?v=j5oA7yHVHm0

I tried using the function-keys zone and i assume the main-keyboard zone will have the same effect. But the entire zone flickers with the ripple colors (just not in a ripple). So they flicker in several intensities with the color of the passing ripple.

The frequency is not set. It receives a single blanket color when the game has startup. During character selection it receives several frames in a very short period. Then during gameplay it depends on the actions. Unless the ultimate ability is active, then it's a bit more variable again.

The size of the data is always consistent however (~25kb). But again, it's just a array of data. I will include 1 event here and will host the current code as-is on github here.

data.txt

arxae commented 7 years ago

I added the code here: https://github.com/arxae/Gamesense.Overwatch

Build it and place the resulting dll in System32. The log files go to the userprofile folder.

It's a bit messy, but it was still more in the prototype stage. Overwatch is very finicky. If you touch the memory or try to inject the dll, OW crashes. I usually use Newtonsoft JSON.NET library for serialization and such, but if i try to use it, OW crashes.

davidtibbetts commented 7 years ago

Please be aware of OW's anti-cheat policies. Messing w/ memory or attaching a debugger is likely to get you banned. This goes for most games w/ anti-cheat policies. We'll take a look at your GameSense.Overwatch repo tomorrow. Thanks for posting it.

arxae commented 7 years ago

I am aware of that. But attaching a debugger or injecting a dll immediately crashes the game (most likely on purpose). I am not the one that did the testing :P

But the Razer dll i'm replacing, is not part of overwatch itself. I'm not touching Overwatch in fact.

ToadKing commented 7 years ago

First thing I notice: You should not be creating new events outside of initialization. Every time you bind a new event the GameSense environment has to re-initialize, and that constant re-initialization might be causing a crash in Engine. Instead of creating new event handlers for each frame, you should use a custom handler written in GoLisp and use that instead. You can look at the audio visualizer example in this repo for where to start, along with the newer API for loading custom handlers:

https://github.com/SteelSeries/gamesense-sdk/blob/master/doc/api/writing-handlers-in-golisp.md#getting-started

https://github.com/SteelSeries/gamesense-sdk/blob/master/doc/tutorials/audiovisualizer_tutorial.md

GameSense API calls should also be synchronous. You should always wait for the HTTP request to return before sending another one.

However Engine should not crash regardless of how often you bind events. If you have logs for when Engine crashes, that would also be useful for us to fix it. Logs should be in %PROGRAMDATA%\SteelSeries\SteelSeries Engine 3\Logs

arxae commented 7 years ago

The ConfigureAwait(true) makes the calls synchronous. It tells the call to wait until the async task completes before continuing.

I deleted all logs and ran OW again. So i can confirm the following happen

During this period, keyboard functionality is not impaired, just the LEDs. Here are the logs that pop back up after starting SSE, running OW and restarting SSE again.

Maybe handy to note, i'm using a Apex M800.

stdout.txt errorlog.txt nw-log.txt

I was hoping to avoid Lisp (i absolutely dislike the language), but if this is the best solution, i might take a look at it. Will update here

ToadKing commented 7 years ago

GoLisp is definitely the way to go here. You should be able to avoid most of the computation in GoLisp though if you just format everything properly from your code before sending it off and make most of your work just a call to on-device

ToadKing commented 7 years ago

This GoLisp code should do what you want and color a full keyboard:

(handler "TEST"
  (lambda (data)
    (let* ((hids (take 124 (hids: data)))
          (colors (take 124 (colors: data))))
      (on-device "rgb-per-key-zones" show-on-keys: hids colors))))

(add-event-per-key-zone-use "TEST" "all")

The (take 124 ...) parts are to make sure you don't send more keys than the M800 can handle. With this code your event payload should look like this:


{
  "game": "OVERWATCH",
  "event": "TEST",
  "data": {
    "hids": [1, 2, 3, 4],
    "colors": [
      [0, 0, 0],
      [255, 0, 0],
      [0, 255, 0],
      [0, 0, 255]
    ]
  }
}
arxae commented 7 years ago

Thanks for the lisp code, i can never get my head around lisp. Good news, SSE3 doesn't crash anymore. Bad news, Overwatch FPS tanks and it doesn't work, as in, the keyboard clears/gets 1 color, then doesn't update. But i think it's probably on my end. Maybe the events come in too fast or so.

Going to let it rest for a bit since i don't have a lot of time in the near future to work on it. But not going to quit!

ToadKing commented 7 years ago

My guess for Overwatch being show is it expects the Razer SDK calls to be asynchronous, while GameSense calls wait for the colors to be deployed to the device. Having the GameSense work done on a worker thread might fix that.

arxae commented 7 years ago

That might be a possibility yes. But the worker thread, you mean on SSE side? Or on my side?

ToadKing commented 7 years ago

On your side.

Leogio360 commented 5 years ago

ehi @arxae did you managed to solve the problem?

arxae commented 5 years ago

Yeah, throttling updates sent to SSE did resolve the issue. Forgot this issue was still open actually. Sorry about that