diff --git a/@AttendanceTracker.7z b/@AttendanceTracker.7z deleted file mode 100644 index add65da..0000000 Binary files a/@AttendanceTracker.7z and /dev/null differ diff --git a/@AttendanceTracker/addons/AttendanceTracker.pbo b/@AttendanceTracker/addons/AttendanceTracker.pbo index 8ee6545..2c04dde 100644 Binary files a/@AttendanceTracker/addons/AttendanceTracker.pbo and b/@AttendanceTracker/addons/AttendanceTracker.pbo differ diff --git a/@AttendanceTracker/addons/AttendanceTracker/config.cpp b/@AttendanceTracker/addons/AttendanceTracker/config.cpp index c93dd66..128ee5d 100644 --- a/@AttendanceTracker/addons/AttendanceTracker/config.cpp +++ b/@AttendanceTracker/addons/AttendanceTracker/config.cpp @@ -23,6 +23,7 @@ class CfgFunctions { class timestamp {}; class getMissionHash {}; class getWorldInfo {}; + class missionLoaded {}; }; }; }; \ No newline at end of file diff --git a/@AttendanceTracker/addons/AttendanceTracker/functions/fn_callbackHandler.sqf b/@AttendanceTracker/addons/AttendanceTracker/functions/fn_callbackHandler.sqf index 9e5f076..3d957d2 100644 --- a/@AttendanceTracker/addons/AttendanceTracker/functions/fn_callbackHandler.sqf +++ b/@AttendanceTracker/addons/AttendanceTracker/functions/fn_callbackHandler.sqf @@ -21,11 +21,16 @@ addMissionEventHandler ["ExtensionCallback", { false; }; + diag_log format ["Raw callback: %1: %2", _function, _data]; + // Parse response from string array private "_response"; try { // diag_log format ["Raw callback: %1: %2", _function, _data]; _response = parseSimpleArray _data; + if (_response isEqualTo []) then { + throw "Failed to parse response as array"; + }; } catch { [ format ["Callback invalid data: %1: %2: %3", _function, _data, _exception], @@ -66,8 +71,12 @@ addMissionEventHandler ["ExtensionCallback", { }; case "writeAttendance": { if (_response#0 == "ATT_LOG") then { - _response params ["_netId", "_rowId"]; - ((AttendanceTracker getVariable ["allUsers", createHashMap]) get _netId) append _rowID; + (_response#1) params ["_eventType", "_netId", "_rowId"]; + private _storeIndex = ["SERVER", "MISSION"] find _eventType; + ((AttendanceTracker getVariable ["rowIds", createHashMap]) getOrDefault [ + _netId, + [nil, nil] + ]) set [_storeIndex, _rowId]; }; }; default { diff --git a/@AttendanceTracker/addons/AttendanceTracker/functions/fn_eventHandlers.sqf b/@AttendanceTracker/addons/AttendanceTracker/functions/fn_eventHandlers.sqf index 55b399d..98a3546 100644 --- a/@AttendanceTracker/addons/AttendanceTracker/functions/fn_eventHandlers.sqf +++ b/@AttendanceTracker/addons/AttendanceTracker/functions/fn_eventHandlers.sqf @@ -15,6 +15,7 @@ }; (AttendanceTracker getVariable ["allUsers", createHashMap]) set [_networkId, _userInfo]; + (AttendanceTracker getVariable ["rowIds", createHashMap]) set [_networkId, [nil, nil]]; // reset rowId on connect [ "Server", _playerID, @@ -30,16 +31,25 @@ [format ["(EventHandler) OnUserDisconnected fired: %1", _this], "DEBUG"] call attendanceTracker_fnc_log; + if !(call attendanceTracker_fnc_missionLoaded) exitWith { + [format ["(EventHandler) OnUserDisconnected: Server is in Mission Asked, likely mission selection state. Skipping.."], "DEBUG"] call attendanceTracker_fnc_log; + }; + private _userInfo = (AttendanceTracker getVariable ["allUsers", createHashMap]) get _networkId; if (isNil "_userInfo") exitWith { [format ["(EventHandler) OnUserDisconnected: No user info found for %1", _networkId], "DEBUG"] call attendanceTracker_fnc_log; }; - _userInfo params ["_playerID", "_ownerId", "_playerUID", "_profileName", "_displayName", "_steamName", "_clientState", "_isHC", "_adminState", "_networkInfo", "_unit", "_rowId"]; + _userInfo params ["_playerID", "_ownerId", "_playerUID", "_profileName", "_displayName", "_steamName", "_clientState", "_isHC", "_adminState", "_networkInfo", "_unit"]; if (_isHC) exitWith { [format ["(EventHandler) OnUserDisconnected: %1 is HC, skipping", _playerID], "DEBUG"] call attendanceTracker_fnc_log; }; + private _rowId = ((AttendanceTracker getVariable ["rowIds", createHashMap]) getOrDefault [ + _networkId, + [nil, nil] + ]) select 0; + [ "Server", _playerID, @@ -54,6 +64,10 @@ [format ["(EventHandler) PlayerConnected fired: %1", _this], "DEBUG"] call attendanceTracker_fnc_log; + if !(call attendanceTracker_fnc_missionLoaded) exitWith { + [format ["(EventHandler) PlayerConnected: Server is in Mission Asked, likely mission selection state. Skipping.."], "DEBUG"] call attendanceTracker_fnc_log; + }; + private _userInfo = (getUserInfo _idstr); if (isNil "_userInfo") exitWith { [format ["(EventHandler) PlayerConnected: No user info found for %1", _idstr], "DEBUG"] call attendanceTracker_fnc_log; @@ -82,6 +96,10 @@ [format ["(EventHandler) HandleDisconnect fired: %1", _this], "DEBUG"] call attendanceTracker_fnc_log; + if !(call attendanceTracker_fnc_missionLoaded) exitWith { + [format ["(EventHandler) HandleDisconnect: Server is in Mission Asked, likely mission selection state. Skipping.."], "DEBUG"] call attendanceTracker_fnc_log; + }; + private _userInfo = (AttendanceTracker getVariable ["allUsers", createHashMap]) get _idstr; if (isNil "_userInfo") exitWith { [format ["(EventHandler) HandleDisconnect: No user info found for %1", _idstr], "DEBUG"] call attendanceTracker_fnc_log; @@ -91,6 +109,11 @@ if (_isHC) exitWith { [format ["(EventHandler) HandleDisconnect: %1 is HC, skipping", _playerID], "DEBUG"] call attendanceTracker_fnc_log; }; + + private _rowId = ((AttendanceTracker getVariable ["rowIds", createHashMap]) getOrDefault [ + _idstr, + [nil, nil] + ]) select 1; [ "Mission", @@ -105,5 +128,53 @@ false; + }], + ["OnUserKicked", { + params ["_networkId", "_kickTypeNumber", "_kickType", "_kickReason", "_kickMessageIncReason"]; + + [format ["(EventHandler) OnUserKicked fired: %1", _this], "DEBUG"] call attendanceTracker_fnc_log; + + if !(call attendanceTracker_fnc_missionLoaded) exitWith { + [format ["(EventHandler) OnUserKicked: Server is in Mission Asked, likely mission selection state. Skipping.."], "DEBUG"] call attendanceTracker_fnc_log; + }; + + private _userInfo = (AttendanceTracker getVariable ["allUsers", createHashMap]) get _networkId; + if (isNil "_userInfo") exitWith { + [format ["(EventHandler) OnUserKicked: No user info found for %1", _networkId], "DEBUG"] call attendanceTracker_fnc_log; + }; + + _userInfo params ["_playerID", "_ownerId", "_playerUID", "_profileName", "_displayName", "_steamName", "_clientState", "_isHC", "_adminState", "_networkInfo", "_unit"]; + + if (_isHC) exitWith { + [format ["(EventHandler) OnUserKicked: %1 is HC, skipping", _playerID], "DEBUG"] call attendanceTracker_fnc_log; + }; + + private _rowId = ((AttendanceTracker getVariable ["rowIds", createHashMap]) getOrDefault [ + _networkId, + [nil, nil] + ]) select 0; + + [ + "Server", + _playerID, + _playerUID, + _profileName, + _steamName, + (if (!isNil "_rowId") then {_rowId} else {nil}) // send rowId on d/c only + ] call attendanceTracker_fnc_logServerEvent; + + + private _rowId = ((AttendanceTracker getVariable ["rowIds", createHashMap]) getOrDefault [ + _networkId, + [nil, nil] + ]) select 1; + [ + "Mission", + _playerID, + _playerUID, + _profileName, + _steamName, + nil // send rowId on d/c only + ] call attendanceTracker_fnc_logMissionEvent; }] ]; \ No newline at end of file diff --git a/@AttendanceTracker/addons/AttendanceTracker/functions/fn_missionLoaded.sqf b/@AttendanceTracker/addons/AttendanceTracker/functions/fn_missionLoaded.sqf new file mode 100644 index 0000000..b526f86 --- /dev/null +++ b/@AttendanceTracker/addons/AttendanceTracker/functions/fn_missionLoaded.sqf @@ -0,0 +1 @@ +!(getClientStateNumber <= 5 || getClientStateNumber isEqualTo 11); \ No newline at end of file diff --git a/@AttendanceTracker/addons/AttendanceTracker/functions/fn_postInit.sqf b/@AttendanceTracker/addons/AttendanceTracker/functions/fn_postInit.sqf index e635bb4..bc7d4e4 100644 --- a/@AttendanceTracker/addons/AttendanceTracker/functions/fn_postInit.sqf +++ b/@AttendanceTracker/addons/AttendanceTracker/functions/fn_postInit.sqf @@ -22,6 +22,7 @@ AttendanceTracker setVariable ["missionContext", createHashMapFromArray [ // store all user details in a hash when they connect so we can reference it in disconnect events AttendanceTracker setVariable ["allUsers", createHashMap]; +AttendanceTracker setVariable ["rowIds", createHashMap]; missionNamespace setVariable ["AttendanceTracker_debug", false]; call attendanceTracker_fnc_connectDB; diff --git a/extension/AttendanceTracker_x64.dll b/extension/AttendanceTracker_x64.dll index 53c41e5..e4ec5d4 100644 Binary files a/extension/AttendanceTracker_x64.dll and b/extension/AttendanceTracker_x64.dll differ diff --git a/extension/main.go b/extension/main.go index 2d4cf52..e4907f1 100644 --- a/extension/main.go +++ b/extension/main.go @@ -179,7 +179,7 @@ type WorldInfo struct { func writeWorldInfo(worldInfo string) { functionName := "writeWorldInfo" - writeLog(functionName, fmt.Sprintf(`["%s", "DEBUG"]`, worldInfo)) + // writeLog(functionName, fmt.Sprintf(`["%s", "DEBUG"]`, worldInfo)) // worldInfo is json, parse it var wi WorldInfo fixedString := fixEscapeQuotes(trimQuotes(worldInfo)) @@ -188,8 +188,8 @@ func writeWorldInfo(worldInfo string) { writeLog(functionName, fmt.Sprintf(`["%s", "ERROR"]`, err)) return } - // write to log - writeLog(functionName, fmt.Sprintf(`["Author:%s WorkshopID:%s DisplayName:%s WorldName:%s WorldNameOriginal:%s WorldSize:%d Latitude:%f Longitude:%f", "INFO"]`, wi.Author, wi.WorkshopID, wi.DisplayName, wi.WorldName, wi.WorldNameOriginal, wi.WorldSize, wi.Latitude, wi.Longitude)) + // write to log as json + // writeLog(functionName, fmt.Sprintf(`["%s", "DEBUG"]`, json.Marshal(wi))) // write to database // check if world exists @@ -273,8 +273,8 @@ func writeMissionInfo(missionInfo string) { // get MySQL friendly datetime - // write to log - writeLog(functionName, fmt.Sprintf(`["MissionName:%s BriefingName:%s MissionNameSource:%s OnLoadName:%s Author:%s ServerName:%s ServerProfile:%s MissionStart:%s MissionHash:%s", "INFO"]`, mi.MissionName, mi.BriefingName, mi.MissionNameSource, mi.OnLoadName, mi.Author, mi.ServerName, mi.ServerProfile, mi.MissionStart, mi.MissionHash)) + // write to log as json + // writeLog(functionName, fmt.Sprintf(`["%s", "DEBUG"]`, mi)) // write to database // every mission is unique, so insert it @@ -364,13 +364,17 @@ func writeAttendance(data string) { } writeLog(functionName, fmt.Sprintf(`["Saved attendance for %s to row id %d", "INFO"]`, event.ProfileName, id)) - writeLog(functionName, fmt.Sprintf(`["ATT_LOG", ["%s", "%d"]]`, event.PlayerId, id)) + if event.EventType == "Server" { + writeLog(functionName, fmt.Sprintf(`["ATT_LOG", ["SERVER", "%s", "%d"]]`, event.PlayerId, id)) + } else if event.EventType == "Mission" { + writeLog(functionName, fmt.Sprintf(`["ATT_LOG", ["MISSION", "%s", "%d"]]`, event.PlayerId, id)) + } } type DisconnectItem struct { PlayerId string `json:"playerId"` - RowId int64 `json:"rowId"` + RowId string `json:"rowId"` } func writeDisconnectEvent(data string) { @@ -416,7 +420,7 @@ func writeDisconnectEvent(data string) { } if rowsAffected == 1 { - writeLog(functionName, fmt.Sprintf(`["Saved disconnect event for %s to row id %d", "INFO"]`, event.PlayerId, event.RowId)) + writeLog(functionName, fmt.Sprintf(`["Saved disconnect event for %s to row id %s", "INFO"]`, event.PlayerId, event.RowId)) } }