Skip to content
This repository has been archived by the owner on Apr 14, 2020. It is now read-only.

AlphaConsole Local Server Proposal #2

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

amadeus
Copy link
Contributor

@amadeus amadeus commented Mar 17, 2018

Hello,

As I mentioned previously from my other PR, I chatted with Carsillas last night about some potential feature requests for AlphaConsole.

The TL;DR in all of this - is that I think it would be super awesome to have AlphaConsole setup a small WebSocket server that could emit events that occur in game. From that, people could then subscribe to this server for lots of different things.

My personal use case would be a stats tracker app that could be running while I play with detailed and live updated stats for each game as it happens. Other potential use cases would be streamers that could hook up certain special effects to their streams when they score goals, etc.

This PR is meant mostly as a proof of concept for how it could work on the electron side.

I've simply spawned a small NodeJS server from the electron process that tails a file and emits to all connected sockets when a new line is added to the file. This seemed like a nice simple hack for the C++ side of things so it doesn't have to handle any networking.

This code all works, except there's no process that appends to the file and no third party html page that could hook up to it, but I could certainly set this up if you guys would like to see the whole loop.

I would recommend we add a way to enable or disable this socket within the app so it doesn't have to be running if users aren't using it.

Notes regarding the code changes

I noticed in the main index.js file there were some funky file formatting issues which I cleaned up, and also a typo in one of the JS variable names that I fixed. Github doesn't handle displaying the changes well, so it looks a bit weird. You can also ignore the package-lock.json changes as those are updates due to adding a a couple additional npm modules to the package.json for this proof of concept.

Anyways, this PR does not in anyway address potential API ideas or anything, but I figured it was a good place to start to get this discussion going, and I would be happy to discuss further assuming you guys are open to it!

app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (wimainWindown === null) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the misspelled variable name - it could actually potentially cause a JS crash since the variable is never initialized anywhere.

@aVileBroker
Copy link

bump - I would love this. Some other people that would benefit greatly from a simple API into oft-needed game-info:

  • statisticians (detailed stats without parsing replay files)
  • casters/analysts (seeing positions of all players on a birds-eye minimap + general info that the scoreboard doesn't relate)
  • TOs (transition triggering on overlays when goals are scored)
  • coaches (orgs/teams could write their own proprietary software to show real-time info like defensiveness or double commits as an example for a leg-up over other orgs/teams)

@Carsillas
Copy link
Member

@aVileBroker If we do anything like tracking player positions we will definitely add a delay because we don't want to cross into a territory where its like a minimap (because you mentioned double commits)

@HaydenMeloche
Copy link
Member

This seems like a great idea.
@aVileBroker Not sure how I feel about a live-ish mini-map. Would be a competitive advantage.
@amadeus So correct me if I'm wrong. For each event, we would write to a text file and the watcher would broadcast that for anything watching?

@amadeus
Copy link
Contributor Author

amadeus commented Mar 17, 2018

In my mind, publishing things like player positions would be both super spammy and get into a grey area with Psyonix as well.

@HaydenMeloche exactly. One idea I thought of as well, as part of a game start event, it should wipe the file I as well, so as not to allow the file to balloon to an unreasonable size. I could add an additional API that could potentially pull the entire file as a request, so if there was some latency in the web server connecting, they could request data that goes back to the start of the game.

Gonna post a message that follows up to this with API/Event ideas.

@amadeus
Copy link
Contributor Author

amadeus commented Mar 17, 2018

As mentioned earlier, I figure basically a type of log file - just appending a new line for each event. As part of a game initialize event, it should wipe the log file and write that singular initialize event.

I figure each line could have 2 parts, a sort of snowflake like id (could just be a millisecond time stamp thing) a space, and then perhaps a json blob of the whatever the event is.

event_1521307789998 {"type": "GAME_START", data: {"players_red": [], "players_blue": []}
event_1521307824467 {"type": "TIMER_COUNTDOWN", data: {"score_blue": 0, "score_orange": 0}}

This snowflake could then easily be used by services if they had to re-connect or something, as a way to de-dupe data. I think standardizing an API on the JSON side like this would be super useful as well - so clients could ignore new types of events they don't understand, etc. It might be worth organizing the data stuff into 2 parts, perhaps "data" which is specific to the event, and then perhaps a type of "metadata" object that perhaps holds more general things - like all the players in the game, time remaining, score, etc.

{
  "id": "event_1521307824467",
  "type": "STAT_CHANGED",
  "data": {
    "player": "some_player_id",
    "stat_type": "ASSIST",
    "value": 6,
  },
  "metadata": {
    "date": 1521307824467,
    "match_time": -231,
    "players": ["list", "of", "player_ids"]
  }
}

I guess theoretically you could just make the whole line JS as well, and just put the ID within the json blob as well.

I have zero visibility into how you guys do things internally - you may already have naming conventions for things, or even potentially limits on events or what kind of data you can send, so consider this sort of how I would dream the API to be and as a starting point for discussion.

v1 Event Ideas

  • GAME_INITIALIZE
    • This could wipe the log file
  • GAME_START
  • GAME_JOIN
    • This would be for unranked if you joined a game midway through, and would fire instead of GAME_START
  • COUNTDOWN_START
    • The start of the 3-2-1 countdown
  • COUNTDOWN_END
    • When players can actually start controlling their cars
  • PLAYER_JOIN
  • PLAYER_LEAVE
  • STAT_CHANGE
    • This could be a meaty one - but basically anything like clears, goals, assists, aerials, etc.
  • GOAL_SCORED
    • Could also just be called SCORE_CHANGED or something too
  • REPLAY_START
    • Countdown start could be a way to handle REPLAY_END without needing the event
  • OVERTIME_START
  • GAME_END
    • After replay finishes?
  • SKILL_RATING_CHANGE
    • Not sure that this stat is actually called
  • TIME_REMAINING_UPDATE
    • Fire every time the clock ticks (every second)
    • Kinda spammy, but could be fun

@amadeus
Copy link
Contributor Author

amadeus commented Mar 17, 2018

Also, if you guys get something tailing to that file - here's a quick html file you can load that will connect to the socket server generated by this PR and console.log any data it receives:

https://gist.github.com/amadeus/e8fd4580b0b4a2d8f41f2616d22d3501

@Barbosicks
Copy link
Collaborator

Since the events have to come from the game anyway, I think it's better suited to have the websocket server inside the game itself. That would also allow the other apps to connect to the WS without having the alpha console UI open. That feature is already working in the current AC beta as the user never has to open the UI for the AC features work on the game. I believe it would be a great addition to AC and I'm willing to add this feature on the current beta as soon as possible.

@amadeus
Copy link
Contributor Author

amadeus commented Mar 20, 2018

@Barbosicks ooh this is awesome!

Btw, there is a way to keep the electron process running when minimized or closed to tray, we do it with Discord. I only brought this up though because of some concerns about running a websocket process in C++ potentially being a pain.

Regardless of implementation tho, when you get something working, would there be a way for me to test it somehow?

Thanks for the awesome responses and being open to doing this, I think it'll be super exciting!

@Barbosicks
Copy link
Collaborator

@amadeus yeah I think it will be great. I'll hit you up when we have something working.

@Barbosicks
Copy link
Collaborator

@amadeus I feel like I owe you an apology and an update on this. So far we were not able to make this feature work as we intend without some lose in performance or something worse.
The websocket server is being a nightmare and we're seriously considering just make it append the event to a file and let the apps read it as they wish.
Will update you as soon as we have something done.
Once again I'm sorry for the wait.

@amadeus
Copy link
Contributor Author

amadeus commented Apr 23, 2018

No worries at all on the wait. This is a side project you guys are doing in your free time, I know how that goes, so no worries there.

I think writing to a text file is totally fine and workable. I can probably do a bit of digging with the electron part of the app and see if we could still run the socket server from there even when it's closed in the tray that could then listen to the file. This could give other people a simpler API and you don't have to worry about any performance issues.

@test137E29B
Copy link
Contributor

This would potentially work better in reverse; rather than hosting the WS Server inside the DLL, creating some kind of either 'middleman' server that's hosted externally, or providing whomever with some easily modifiable Server Project. There could then just be a simple config option in the Electron UI for AC to give some connection URL if enabled.

This would also solve pretty much all of the performance issues and you could use a queue and another thread for emitting events with the WS Client.

I currently have this working with Socket IO Server written in TypeScript, and a Socket IO client in an injected DLL into Rocket League without performance loss. If you wish to talk further about it I'm interested in contributing.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants