Skip to content

Commit 14028d3

Browse files
Initial Commit
1 parent 3aaffbf commit 14028d3

19 files changed

+1340
-1
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -398,3 +398,4 @@ FodyWeavers.xsd
398398

399399
# JetBrains Rider
400400
*.sln.iml
401+
REPOStats-Mod/Packaged/*

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
# repostats
1+
# REPOStats-Mod

REPOStats-Mod/REPOStats-Mod.sln

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.13.35818.85 d17.13
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "REPOStats-Mod", "REPOStats-Mod\REPOStats-Mod.csproj", "{7538CA20-15B2-4B34-BCFF-E03659D520AF}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{7538CA20-15B2-4B34-BCFF-E03659D520AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{7538CA20-15B2-4B34-BCFF-E03659D520AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{7538CA20-15B2-4B34-BCFF-E03659D520AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{7538CA20-15B2-4B34-BCFF-E03659D520AF}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {51DEF90B-7B2F-4DB1-9D0E-1ED28645D81E}
24+
EndGlobalSection
25+
EndGlobal
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Runtime.Serialization;
4+
using System.Text;
5+
6+
namespace REPOStats_Mod.Data
7+
{
8+
[DataContract]
9+
public class DanosDeathContainer
10+
{
11+
[DataMember]
12+
public string CauseOfDeath { get; set; } = "";
13+
[DataMember]
14+
public long DeathTime { get; set; }
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace REPOStats_Mod.Data
6+
{
7+
public class DanosPatchConfiguration
8+
{
9+
public string TargetClass { get; set; }
10+
public string TargetMethod { get; set; }
11+
public string PostfixMethod { get; set; }
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace REPOStats_Mod.Data
6+
{
7+
public static class DanosPatchManager
8+
{
9+
public static List<DanosPatchConfiguration> GetPatchConfigurations()
10+
{
11+
// Example: Hard-coded patch configurations
12+
// In future, replace this with JSON or external config loading
13+
return new List<DanosPatchConfiguration>
14+
{
15+
16+
};
17+
}
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Runtime.Serialization;
4+
using System.Text;
5+
6+
namespace REPOStats_Mod.Data
7+
{
8+
[DataContract]
9+
public class DanosRunStats
10+
{
11+
[DataMember]
12+
public int extractions_completed { get; set; } = 0;
13+
[DataMember]
14+
public int extractions_on_map { get; set; } = 0;
15+
[DataMember]
16+
public bool failed { get; set; } = false;
17+
[DataMember]
18+
public int top_extraction_target { get; set; } = 0;
19+
[DataMember]
20+
public int take_home_money { get; set; } = 0;
21+
[DataMember]
22+
public int total_money { get; set; } = 0;
23+
[DataMember]
24+
public int completed_levels { get; set; } = 0;
25+
26+
[DataMember]
27+
public string extraction_goals_csv { get; set; } = "";
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.IO;
5+
using System.Net.Http;
6+
using System.Net.Http.Headers;
7+
using System.Runtime.Serialization;
8+
using System.Runtime.Serialization.Json;
9+
using System.Text;
10+
using System.Threading.Tasks;
11+
using UnityEngine;
12+
13+
namespace REPOStats_Mod.Data
14+
{
15+
public class DanosStatSender : MonoBehaviour
16+
{
17+
private static DanosStatSender _instance;
18+
19+
public static DanosStatSender Instance
20+
{
21+
get
22+
{
23+
if (_instance == null)
24+
{
25+
//Check if a gameobject with the same name exists
26+
_instance = FindObjectOfType<DanosStatSender>();
27+
if (_instance != null)
28+
{
29+
return _instance;
30+
}
31+
32+
33+
GameObject obj = new GameObject("DanosStatSender");
34+
_instance = obj.AddComponent<DanosStatSender>();
35+
DontDestroyOnLoad(obj);
36+
}
37+
return _instance;
38+
}
39+
}
40+
41+
public void SendStats(DanosStatsStore stats)
42+
{
43+
StartCoroutine(PostStatsCoroutine(stats));
44+
}
45+
46+
private IEnumerator PostStatsCoroutine(DanosStatsStore stats)
47+
{
48+
Debug.Log("Posting stats to API");
49+
50+
string encodedUrl = "aHR0cHM6Ly9yZXBvLWFwaS5zcGxpdHN0YXRzLmlvL2FwaS9wb3N0Z2FtZS9zZW5kc3RhdHM=";
51+
string apiUrl = Encoding.UTF8.GetString(Convert.FromBase64String(encodedUrl));
52+
53+
//#if DEBUG
54+
// apiUrl = "https://localhost:7018/api/postgame/sendstats";
55+
//#endif
56+
57+
string json = SerializeToJson(stats);
58+
using (HttpClient client = new HttpClient())
59+
{
60+
client.DefaultRequestHeaders.Accept.Clear();
61+
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
62+
client.DefaultRequestHeaders.Add("XAuthCode", "cmVwb3N0YXRzbGt0b3A0MzI=");
63+
64+
HttpContent content = new StringContent(json, Encoding.UTF8, "application/json");
65+
66+
// Start the async request and store the task
67+
Task<HttpResponseMessage> requestTask = client.PostAsync(apiUrl, content);
68+
69+
// Yield until the request is done (does not block main thread)
70+
yield return new WaitUntil(() => requestTask.IsCompleted);
71+
72+
}
73+
74+
yield break;
75+
}
76+
77+
78+
private string SerializeToJson(DanosStatsStore stats)
79+
{
80+
using (MemoryStream stream = new MemoryStream())
81+
{
82+
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(DanosStatsStore));
83+
serializer.WriteObject(stream, stats);
84+
return Encoding.UTF8.GetString(stream.ToArray());
85+
}
86+
}
87+
}
88+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Runtime.Serialization;
4+
using UnityEngine;
5+
6+
namespace REPOStats_Mod.Data
7+
{
8+
public static class DanosStaticStore
9+
{
10+
public static long lastSentStats = 0;
11+
public static DanosStatsStore statsStore = new DanosStatsStore();
12+
13+
14+
15+
public static void SendStatsToAPI()
16+
{
17+
if (CheckStatsStore())
18+
{
19+
Debug.Log("Sending stats to API");
20+
DanosStatSender.Instance.SendStats(statsStore);
21+
}
22+
23+
Debug.Log("Resetting stats store");
24+
ResetStatsStore();
25+
lastSentStats = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
26+
}
27+
28+
public static bool CheckStatsStore()
29+
{
30+
if (statsStore == null) return false;
31+
if (statsStore.MySteamId <= 1000) return false;
32+
if (statsStore.RoundStarted <= 0) return false;
33+
if (statsStore.RoundEnded <= 0) return false;
34+
if (statsStore.RoundEnded < statsStore.RoundStarted) return false;
35+
36+
return true;
37+
}
38+
39+
public static void ResetStatsStore()
40+
{
41+
statsStore = new DanosStatsStore();
42+
}
43+
44+
public static void InitializeStatsStore()
45+
{
46+
ResetStatsStore();
47+
string MySteamId = DanosUtils.GetMySteamID();
48+
if (string.IsNullOrEmpty(MySteamId))
49+
{
50+
Debug.LogError("Could not get my steam id");
51+
return;
52+
}
53+
54+
//Try parse the steam id as a long
55+
if (!long.TryParse(MySteamId, out long steamId))
56+
{
57+
Debug.LogError("Could not parse steam id as long");
58+
return;
59+
}
60+
61+
//Do the same for the host id
62+
string HostSteamId = DanosUtils.GetHostSteamID();
63+
Debug.Log("Host: " + HostSteamId);
64+
if (string.IsNullOrEmpty(HostSteamId))
65+
{
66+
Debug.LogError("Could not get host steam id");
67+
return;
68+
}
69+
70+
if (!long.TryParse(HostSteamId, out long hostSteamId))
71+
{
72+
Debug.LogError("Could not parse host steam id as long");
73+
return;
74+
}
75+
76+
statsStore.MySteamId = steamId;
77+
statsStore.LobbyHash = DanosUtils.GetLobbyHash();
78+
statsStore.isHost = steamId == hostSteamId;
79+
80+
81+
82+
statsStore.RoundStarted = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
83+
statsStore.Deaths = new List<DanosDeathContainer>();
84+
statsStore.RunStats = new();
85+
86+
RunManager runManager = RunManager.instance;
87+
if (runManager != null)
88+
{
89+
statsStore.LevelName = runManager.levelCurrent.name;
90+
}
91+
92+
93+
94+
}
95+
}
96+
97+
98+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Runtime.Serialization;
4+
using System.Text;
5+
6+
namespace REPOStats_Mod.Data
7+
{
8+
//Class to store the stats of the player for serialization to the API
9+
[DataContract]
10+
public class DanosStatsStore
11+
{
12+
[DataMember]
13+
public long RoundStarted { get; set; } = 0;
14+
[DataMember]
15+
public long RoundEnded { get; set; } = 0;
16+
[DataMember]
17+
public string LevelName { get; set; } = "";
18+
19+
[DataMember]
20+
public string LobbyHash { get; set; } = "";
21+
22+
[DataMember]
23+
public string ModVersion { get; set; } = DanosRepoStatsPluginInfo.PLUGIN_VERSION;
24+
[DataMember]
25+
public string GameVersion { get; set; } = "Unknown";
26+
[DataMember]
27+
public string RunEndReason { get; set; } = "";
28+
[DataMember]
29+
public long MySteamId { get; set; } = 0;
30+
[DataMember]
31+
public bool isHost { get; set; } = false;
32+
33+
[DataMember]
34+
public List<DanosDeathContainer> Deaths { get; set; } = new List<DanosDeathContainer>();
35+
36+
[DataMember]
37+
public DanosRunStats RunStats { get; set; } = new();
38+
39+
}
40+
}

0 commit comments

Comments
 (0)