Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expanded DB-Log plugin #185

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

Conversation

milutinke
Copy link
Contributor

@milutinke milutinke commented Mar 18, 2021

Added:

  • Tracking of total player in-game time spent on the server (PS: It's in milliseconds, Date.now() returns milliseconds, so, divide it with 1000)
  • First seen time
  • Last seen time
  • Last play session in-game time

In relation to #181

milutinke and others added 2 commits March 18, 2021 14:03
Sync the forked repo with the master
…n time, last session playtime in db-log.js plugin
@Thomas-Smyth
Copy link
Collaborator

Thomas-Smyth commented Mar 28, 2021

This looks like an ok implementation, but might it be better to store playtime as a set of sessions in a separate table? Like matches, for example, create a record with a start time when they connect and then update it with an end time when they disconnect. I think this might satisfy more use cases, e.g. to find everyone who's seeded over x hours in the past month to auto whitelist them. Of course, it should still provide the same functionality as this: first time seen, last time seen and play session length.

@milutinke
Copy link
Contributor Author

milutinke commented Mar 28, 2021

This looks like an ok implementation, but might it be better to store playtime as a set of sessions in a separate table? Like matches, for example, create a record with a start time when they connect and then update it with an end time when they disconnect. I think this might satisfy more use cases, e.g. to find everyone who's seeded over x hours in the past month to auto whitelist them. Of course, it should still provide the same functionality as this: first time seen, last time seen and play session length.

I haven't thought of that, that is an excellent idea, I will implement it.
PS: Are player connect and disconnect events called on map change, I've not checked?
If not, I will use NEW_GAME and loop through players and do the logic.

@Thomas-Smyth
Copy link
Collaborator

Thomas-Smyth commented Mar 28, 2021

This looks like an ok implementation, but might it be better to store playtime as a set of sessions in a separate table? Like matches, for example, create a record with a start time when they connect and then update it with an end time when they disconnect. I think this might satisfy more use cases, e.g. to find everyone who's seeded over x hours in the past month to auto whitelist them. Of course, it should still provide the same functionality as this: first time seen, last time seen and play session length.

I haven't thought of that, that is an excellent idea, I will implement it.
PS: Are player connect and disconnect events called on map change, I've not checked?
If not, I will use NEW_GAME and loop through players and do the logic.

I think they are only called when the player actually connects/disconnects as they use the logs and not ListPlayers which sometimes doesn't show players during a map change - worth verifying this though, especially as I didn't implement the disconnect event. If they don't behave this way then it's probably better we find a way to improve the event to solve the root cause as opposed to patching around it in the plugins.

@Hamburgergamer
Copy link

Separating the Player Sessions from the user table would definitely allow multiple use cases.
But to solve @Thomas-Smyth Seeding example, we need to do further adjustments on other tables. Right now the DBLog_Match table doesn't log if the match is in seeding Mode. This needs to be added to this table (or a separate one). It would also require to log the MatchID´s within the play session table (probably as an array).

@milutinke
Copy link
Contributor Author

milutinke commented Mar 30, 2021

I've implemented the disconnect event, but I've not paid any attention if it gets called on map switch.
A potential solution may be to wait a certain amount of time after the match starts and then list the players and then start tracking their time until the new match or until they disconnect.
As for seeing mode, we could have an option in the plugin settings for the number of players required for the match to go live and use that to determine if the match is in the setting mode.
Regarding the way of tracking the players who seeded, we could periodically check the player numbers and mark players as seeders until the live mode, and then stop marking any new players after that.
What do you think about this?

@Thomas-Smyth
Copy link
Collaborator

But to solve @Thomas-Smyth Seeding example, we need to do further adjustments on other tables. Right now the DBLog_Match table doesn't log if the match is in seeding Mode. This needs to be added to this table (or a separate one). It would also require to log the MatchID´s within the play session table (probably as an array).

A match might not be either seeding or non-seeding it could be both. For example, some seeding attempts get up to approximately the level at which they go live, a map switch occurs, and after 10 minutes of the new match, it's live for the rest of the hour-long round.

As for seeing mode, we could have an option in the plugin settings for the number of players required for the match to go live and use that to determine if the match is in the setting mode.
Regarding the way of tracking the players who seeded, we could periodically check the player numbers and mark players as seeders until the live mode, and then stop marking any new players after that.

To address both points, I think it would be possible with the session records. I'm thinking that a query could calculate the number of players online at a series of time intervals, filter out those with more than the seeding amount of players, then identify the players at that time, and finally sum up the total number of intervals they were on for. However, I'm not sure how well this would scale.

A better option might be to have a separate set of tables for the seeding use case and adopt a points-based approach. Search for points/ seeding in the contributor's channel of our Discord and you might find existing discussion surrounding it. It would be good to get an implementation of this in at some points. I believe there might be some already, but if they're not generic enough we can look to modify them as need be.

So in short, I think it's worth adding session records regardless of whether it works for the seeding use case. If it doesn't we should address that separately. Up to you whether you want to do either (or both)... if not I'll happily take this on either when I have the time as I think it's something that a lot of people would benefit from.

Updated the DB Log to have Sessions based approach to player time tracking.
@milutinke
Copy link
Contributor Author

milutinke commented Apr 3, 2021

I've updated the plugin (the commit) to store player sessions in a separate table instead of bloating the SteamUsers table and I made a Points system that gives the players N points every X seconds (default is 1 point every 5 seconds), so people can combine those two.
The points system will be added in a separate commit.

image
image
image

squad-server/plugins/db-log.js Outdated Show resolved Hide resolved
squad-server/plugins/db-log.js Show resolved Hide resolved
squad-server/plugins/db-log.js Outdated Show resolved Hide resolved
squad-server/plugins/db-log.js Outdated Show resolved Hide resolved
squad-server/plugins/db-log.js Outdated Show resolved Hide resolved
Changed the code as requested
@milutinke
Copy link
Contributor Author

I've changed the code as requested.

Comment on lines 481 to 482
for (const steamID of Object.keys(this.playerSession))
await this.startSession(steamID, this.playerSession[steamID].name, new Date());
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think I would scrap this and just track what happens whilst the plugin is mounted.

I can see issues arising because of it, e.g. if SquadJS crashes and reboots everyone is marked with a new session time,

Comment on lines 495 to 496
for (const steamID of Object.keys(this.playerSession))
await this.saveSession(steamID, new Date(), false);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same as above.

@milutinke
Copy link
Contributor Author

Yeah, I've forgotten about that, since before I had a different approach where that would not happen.
I've removed that part and I've fixed the PLAYER_DISCONNECT event.

async onPlayerConnected(info) {
if (!info || !info.player) return;

await this.startSession(info.player.steamID, info.player.name, info.time);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This method is only called once so is there much point in having it? Just move the logic from the method here I think.

async onPlayerDisconnected(info) {
if (!info || !info.player) return;

await this.saveSession(info.player.steamID, info.time);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same as line 663.

@@ -43,6 +43,7 @@ export default class DBLog extends BasePlugin {
super(server, options, connectors);

this.models = {};
this.playerSession = {};
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think there's a need for this object or any of the logic related to it?

Copy link
Contributor

@LeventHAN LeventHAN May 12, 2021

Choose a reason for hiding this comment

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

After testing without the object initialization above it would throw an error. So I believe it is needed @Thomas-Smyth

@werewolfboy13
Copy link
Collaborator

Attempted to resolve conflict but will push into write protected master branch so I am holding off on that. Conversations still need resolving as well.

@milutinke
Copy link
Contributor Author

milutinke commented Jan 3, 2023

Attempted to resolve conflict but will push into write protected master branch so I am holding off on that. Conversations still need resolving as well.

@Thomas-Smyth
I have no idea why Github did not send me notifications for this, I've completely forgot about this PR.
As for the this.playerSession = {};, if I remember correctly, it's needed to keep track of players session, there were some edge cases where the data inserted to the db would not be correct or would cause an error, can't really remember exactly, but it might have been if the player disconnected and reconnected.

@milutinke
Copy link
Contributor Author

milutinke commented Jan 3, 2023

Resolved the conflict, as far as I am considered it can be merged.
It should work from the tests I've done back in the day.

@ghost
Copy link

ghost commented Feb 13, 2023

I just went through making my own version (didn't see this pull request before i started). And i found a pretty good way for dealing with the seeding hours. You log players on a per session basis (join time, leave time) but also the time for when the server switches from seeding to live in each session and a boolean for whether the player joined during seeding.

This made for a fairly simple query for finding seeding times as you only look for sessions where the player joined during seeding, then subtract the join time from the time for end of seeding or, if that is null, their leave time (left before seeding finished).

This also works very well with how squadjs has it's current events as it just needs an update to a variable for whether the server is seeding (via the a2supdate for player count) and player connect/disconnects. To update the seed end time just requires an update to every session that does not have a leave time when the player count becomes greater than seeding threshold but the seeding variable is still true (seeding variable gets turned to false after the once through).

@milutinke
Copy link
Contributor Author

I just went through making my own version (didn't see this pull request before i started). And i found a pretty good way for dealing with the seeding hours. You log players on a per session basis (join time, leave time) but also the time for when the server switches from seeding to live in each session and a boolean for whether the player joined during seeding.

This made for a fairly simple query for finding seeding times as you only look for sessions where the player joined during seeding, then subtract the join time from the time for end of seeding or, if that is null, their leave time (left before seeding finished).

This also works very well with how squadjs has it's current events as it just needs an update to a variable for whether the server is seeding (via the a2supdate for player count) and player connect/disconnects. To update the seed end time just requires an update to every session that does not have a leave time when the player count becomes greater than seeding threshold but the seeding variable is still true (seeding variable gets turned to false after the once through).

Then I guess this PR is not needed and it can be closed.
Have you added that to this repo?

@ghost
Copy link

ghost commented Feb 15, 2023

uh, no not yet, still doing a bit of testing with it and working through some of the squad qwerks. also not exactly sure where i would add this either (in terms of the github and stuff). I am also thinking it might be good for DBLog to be separated into components like the discord stuff is as well. so people can enable/disable specific tables they don't need.

@werewolfboy13
Copy link
Collaborator

This PR may be stale due to EOS/EAC integrations. Needs validation

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

Successfully merging this pull request may close these issues.

None yet

5 participants