Files
Nathaniel Cosford 062dfab2cd Patched
2025-05-30 01:04:40 +09:30

2001 lines
85 KiB
C#

using Audio;
using InControl;
using Platform;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using static InvGameItem;
public class RebirthManager
{
private static RebirthManager instance = null;
public static bool HasInstance => instance != null;
//HIRES: VARIABLES
public static bool loadedHires = false;
private const string hiresSaveFile = "HiresManagerRebirth.dat";
private static ThreadManager.ThreadInfo dataSaveThreadInfo;
public static List<hireInfo> playerHires = new List<hireInfo>();
public static List<chunkObservers> observers = new List<chunkObservers>();
private static float hiresUpdateCheck = 0f;
private static float hiresUpdateTick = 10f;
//BLOCK CHANGES: VARIABLES
private static float blockChangesUpdateCheck = 0f;
private static float blockChangesUpdateTick = 2f;
//OUTBREAK: VARIABLES
private static float outbreakUpdateCheck = 0f;
private static float outbreakUpdateTick = 60f;
//GAMESTAGE: VARIABLES
private static float gamestageUpdateTick = 30f;
private static float generalGroupsUpdateTick = 600f;
private static float biomeGroupsUpdateTick = 1200f;
private static float bloodMoonGroupsUpdateTick = 2400f;
private static float gamestageUpdateCheck = 0f;
private static float generalGroupsUpdateCheck = 0f;
private static float biomeGroupsUpdateCheck = 0f;
private static float bloodMoonGroupsUpdateCheck = 0f;
//EVENTS: VARIABLES
public static List<eventInfo> playerEvents = new List<eventInfo>();
private static bool loadedEvents = false;
public static int nextFeralSenseDay = 0;
public static int nextFeralSensePeriod = 0;
public static int nextScreamerNight = 0;
public static bool isScreamerEventActivated = false;
private static float eventUpdateTick = 60f;
private static float eventUpdateCheck = 0f;
public static float eventUpdateTickCheckScreamer = 90f;
//SCENARIOS: VARIABLES
private static string SaveDataPath = "";
private static string ModPath = "";
private static float prefabUpdateTick = 1f;
private static float prefabUpdateCheck = 0f;
private static float cleanupUpdateTick = 300f;
private static float cleanupUpdateCheck = 0f;
public static List<PurgeKills> purgeKills = new List<PurgeKills>();
public static List<PrefabInfo> ClearedPrefabs = new List<PrefabInfo>();
public static List<PrefabInfo> DiscoveredPrefabs = new List<PrefabInfo>();
public static List<DynamicPrefab> dynamicPrefabs = new List<DynamicPrefab>();
public static List<int> ClearedBiomes = new List<int>();
public static bool dynamicPrefabsLoaded = false;
public static bool processingDynamicPrefabs = false;
//HIRES: CLASSES
public class chunkObservers
{
public int entityID;
public ChunkManager.ChunkObserver observerRef;
public chunkObservers()
{
}
public chunkObservers(int entityID, ChunkManager.ChunkObserver observerRef)
{
this.entityID = entityID;
this.observerRef = observerRef;
}
}
public class hireInfo
{
public int playerID;
public int hireID;
public string name;
public string className;
public Vector3 spawnPosition;
public Vector3 spawnRotation;
public Vector3 reSpawnPosition;
public Vector3 reSpawnRotation;
public int numKills;
public int numMine;
public int order;
public bool playerSpawned;
//eventually add backpack and toolbelt content
public hireInfo()
{
}
public hireInfo(int playerID,
int hireID,
string name,
string className,
Vector3 spawnPosition,
Vector3 spawnRotation,
Vector3 reSpawnPosition,
Vector3 reSpawnRotation,
int numKills,
int numMine,
int order,
bool playerSpawned = false
)
{
this.playerID = playerID;
this.hireID = hireID;
this.name = name;
this.className = className;
this.spawnPosition = spawnPosition;
this.spawnRotation = spawnRotation;
this.reSpawnPosition = reSpawnPosition;
this.reSpawnRotation = reSpawnRotation;
this.numKills = numKills;
this.numMine = numMine;
this.order = order;
this.playerSpawned = playerSpawned;
}
}
//EVENTS: CLASSES
public class eventInfo
{
public int playerID;
public float eventCheckScreamer;
public float eventCheckEntity;
public float eventCheckEvent;
public eventInfo()
{
}
public eventInfo(int _playerID,
float _eventCheckScreamer,
float _eventCheckEntity,
float _eventCheckEvent
)
{
this.playerID = _playerID;
this.eventCheckScreamer = _eventCheckScreamer;
this.eventCheckEntity = _eventCheckEntity;
this.eventCheckEvent = _eventCheckEvent;
}
}
//SCENARIOS: CLASSES
public class DynamicPrefab
{
public string PrefabName { get; set; }
public Vector3 Position { get; set; }
public Vector3 Size { get; set; }
public int Difficulty { get; set; }
public string Biome { get; set; }
public string Tags { get; set; }
public DynamicPrefab(string prefabName, Vector3 position, Vector3 size, int difficulty, string biome, string tags)
{
PrefabName = prefabName;
Position = position;
Size = size;
Difficulty = difficulty;
Biome = biome;
Tags = tags;
}
}
public class PlayerKillInfo
{
public int PlayerID { get; set; }
public int Kills { get; set; }
public bool Redeemed { get; set; }
}
public class KillInfo
{
public int Kills { get; set; }
public bool Redeemed { get; set; }
}
public class PurgeKills
{
public string Name { get; set; }
public Vector3 Position { get; set; }
public Dictionary<int, KillInfo> Players { get; set; } = new Dictionary<int, KillInfo>(); // Player ID as key, Kills as value
}
public class PrefabInfo
{
public string Name { get; set; }
public Vector3 Position { get; set; }
public Vector3 Size { get; set; }
public int Difficulty { get; set; }
public int EntitiesCleared { get; set; }
public Dictionary<int, string> Players { get; set; } // Player ID as key, player name as value
public string PlayerName { get; set; }
public string Biome { get; set; }
}
public static RebirthManager Instance
{
get
{
return instance;
}
}
public static void Init()
{
RebirthManager.instance = new RebirthManager();
Log.Out("Starting Rebirth Manager");
//HIRES
LoadHires();
loadedHires = true;
//OUTBREAK
RebirthVariables.isHerd = false;
RebirthVariables.stopWHSpawns = true;
RebirthVariables.herdDuration = 0f;
// EVENTS
loadedEvents = true;
int minimum = 2;
if (!GameManager.Instance.World.IsDaytime())
{
minimum = 3;
}
if (nextScreamerNight == 0)
{
nextScreamerNight = GameUtils.WorldTimeToDays(GameManager.Instance.World.worldTime) + Manager.random.RandomRange(minimum, 7);
//Log.Out("EventsManagerRebirth-Init nextScreamerNight: " + nextScreamerNight);
}
if (nextFeralSenseDay == 0)
{
nextFeralSenseDay = GameUtils.WorldTimeToDays(GameManager.Instance.World.worldTime) + Manager.random.RandomRange(minimum, 7);
nextFeralSensePeriod = Manager.random.RandomRange(0, 3);
}
// SCENARIOS
var mod = ModManager.GetMod("zzz_REBIRTH__Utils", true);
ModPath = mod.Path;
SaveDataPath = SaveDataPath = GameIO.GetUserGameDataDir() + "/RebirthData/Scenarios";
Directory.CreateDirectory(SaveDataPath);
if (RebirthVariables.customScenario == "hive")
{
ClearedBiomes = new List<int>();
}
else if (RebirthVariables.customScenario == "purge")
{
ClearedPrefabs = new List<PrefabInfo>();
DiscoveredPrefabs = new List<PrefabInfo>();
foreach (KeyValuePair<int, string> biome in RebirthVariables.biomes)
{
int key = biome.Key; // The int key (0, 1, 2, etc.)
string value = biome.Value; // The string value ("pine_forest", "desert", etc.)
RebirthUtilities.AddPurgeBiome(value, 0);
}
}
//Log.Out("RebirthManager-Init RebirthVariables.purgeBiomes.Count: " + RebirthVariables.purgeBiomes.Count);
if (RebirthVariables.customScenario == "hive")
{
LoadScenario("hive");
}
else if (RebirthVariables.customScenario == "purge")
{
LoadScenario("purge");
if ((SingletonMonoBehaviour<ConnectionManager>.Instance.IsServer && !GameManager.IsDedicatedServer) || SingletonMonoBehaviour<ConnectionManager>.Instance.IsSinglePlayer)
{
foreach (var prefab in RebirthManager.ClearedPrefabs)
{
//Log.Out("RebirthManager-Init SCENARIO Purged prefab.Name: " + prefab.Name);
Vector3 vector = new Vector3(prefab.Position.x + prefab.Size.x / 2f, prefab.Position.y, prefab.Position.z + prefab.Size.z / 2f);
NavObject navPurged = NavObjectManager.Instance.RegisterNavObject("purge_waypoint", vector, "purge_waypoint");
if (navPurged != null)
{
navPurged.TrackedPosition = vector;
}
navPurged.trackedPosition = vector;
//navPurged.ForceDisabled = true;
//navPurged.IsActive = false;
}
foreach (var prefab in RebirthManager.DiscoveredPrefabs)
{
//Log.Out("RebirthManager-Init SCENARIO Discovered prefab.Name: " + prefab.Name);
Vector3 vector = new Vector3(prefab.Position.x + prefab.Size.x / 2f, prefab.Position.y, prefab.Position.z + prefab.Size.z / 2f);
NavObject navDiscovered = NavObjectManager.Instance.RegisterNavObject("discovered_waypoint_" + prefab.Difficulty, vector, "discovered_waypoint_" + prefab.Difficulty);
if (navDiscovered != null)
{
navDiscovered.TrackedPosition = vector;
}
navDiscovered.trackedPosition = vector;
}
}
}
ModEvents.GameUpdate.RegisterHandler(Update);
}
//EVENTS
public static void AddEvent(int _playerID,
float _eventCheckScreamer,
float _eventCheckEntity,
float _eventCheckEvent
)
{
//Log.Out("EventsManagerRebirth-AddEvent START");
bool foundEvent = false;
foreach (eventInfo eventData in playerEvents)
{
if (eventData.playerID == _playerID)
{
foundEvent = true;
break;
}
}
if (!foundEvent)
{
eventInfo newEvent = new eventInfo();
newEvent.playerID = _playerID;
newEvent.eventCheckScreamer = _eventCheckScreamer;
newEvent.eventCheckEntity = _eventCheckEntity;
newEvent.eventCheckEvent = _eventCheckEvent;
playerEvents.Add(newEvent);
}
}
//SCENARIOS
public static bool IsIgnoredPrefab(string prefabName)
{
// Check if the prefabName exists in the ignorePrefabs XML (case-insensitive)
return RebirthVariables.ignorePrefabs
.Descendants("prefab")
.Any(p => p.Attribute("name")?.Value.ToLower() == prefabName.ToLower());
}
public static List<PrefabInfo> GetIgnoredDiscoveredPrefabs()
{
// Create an empty list to hold the matching PrefabInfo objects
List<PrefabInfo> ignoredPrefabs = new List<PrefabInfo>();
// Get the list of prefab names from the ignorePrefabs XML
var ignoredNames = RebirthVariables.ignorePrefabs
.Descendants("prefab")
.Select(p => p.Attribute("name")?.Value)
.Where(n => !string.IsNullOrEmpty(n))
.ToList();
// Filter the DiscoveredPrefabs based on the prefab names in ignorePrefabs
foreach (var prefab in DiscoveredPrefabs)
{
if (ignoredNames.Contains(prefab.Name))
{
//Log.Out("ScenarioManager-Update ignoredPrefabs CLEANUP, prefab.Name: " + prefab.Name);
//Log.Out("ScenarioManager-Update ignoredPrefabs CLEANUP, prefab.Position: " + prefab.Position);
ignoredPrefabs.Add(prefab);
}
}
return ignoredPrefabs;
}
public static void Update()
{
if (GameUtils.IsPlaytesting())
{
return;
}
bool isHordeNight = RebirthUtilities.IsHordeNight();
bool canExecute = SingletonMonoBehaviour<ConnectionManager>.Instance.IsServer && !GameManager.Instance.isEditMode;
//Log.Out("RebirthManager-Update canExecute: " + canExecute);
//HIRES
/*if (canExecute && !isHordeNight && (Time.time - hiresUpdateCheck) > hiresUpdateTick)
{
//Log.Out("RebirthManager-Update HIRES UPDATE START");
hiresUpdateCheck = Time.time;
GameManager.Instance.StartCoroutine(RebirthUtilities.CheckHires());
}*/
//BLOCK CHANGES
/*if ((Time.time - blockChangesUpdateCheck) > blockChangesUpdateTick &&
RebirthVariables.blockChanges.Count > 0 &&
!RebirthVariables.updatingBlocks)
{
blockChangesUpdateCheck = Time.time;
GameManager.Instance.StartCoroutine(RebirthUtilities.UpdateBlocks());
}*/
//OUTBREAK
if (canExecute && !isHordeNight)
{
if ((Time.time - outbreakUpdateCheck) > outbreakUpdateTick)
{
//Log.Out("RebirthManager-Update OUTBREAK TICK");
outbreakUpdateCheck = Time.time;
GameManager.Instance.StartCoroutine(RebirthUtilities.CheckOutbreak());
}
}
else
{
//Log.Out("OutbreakManagerRebirth-Update HORDE NIGHT, STOP WANDERING HORDE");
RebirthVariables.isHerd = false;
RebirthVariables.stopWHSpawns = true;
RebirthVariables.herdDuration = 0f;
}
//GAMESTAGE
if (RebirthUtilities.sleepersLow.Count == 0 || (Time.time - gamestageUpdateCheck) > gamestageUpdateTick)
{
//Log.Out("RebirthManager-Update GAMESTAGE START");
gamestageUpdateCheck = Time.time;
if (RebirthUtilities.sleepersLow.Count == 0)
{
//Log.Out("GamestageManagerRebirth-Update 1");
GameManager.Instance.StartCoroutine(RebirthUtilities.BuildGamestageSpawnGroups());
}
//Log.Out("GamestageManagerRebirth-Update time to process: " + watch.ElapsedMilliseconds + " ms");
//Build Bandit Groups and Survivor Groups
// Build weapon categories based on what the npc's bagitem property
}
if (!isHordeNight)
{
if ((Time.time - generalGroupsUpdateCheck) > generalGroupsUpdateTick)
{
generalGroupsUpdateCheck = Time.time;
if (RebirthUtilities.sleepersLow.Count > 0)
{
GameManager.Instance.StartCoroutine(RebirthUtilities.BuildSpecificSpawnGroup(1));
//RebirthUtilities.BuildSpecificEntityGroups(ref RebirthUtilities.generalGroups);
}
}
if ((Time.time - biomeGroupsUpdateCheck) > biomeGroupsUpdateTick)
{
biomeGroupsUpdateCheck = Time.time;
if (RebirthUtilities.sleepersLow.Count > 0)
{
GameManager.Instance.StartCoroutine(RebirthUtilities.BuildSpecificSpawnGroup(2));
//RebirthUtilities.BuildSpecificEntityGroups(ref RebirthUtilities.biomeGroups, true);
}
}
if ((Time.time - bloodMoonGroupsUpdateCheck) > bloodMoonGroupsUpdateTick)
{
bloodMoonGroupsUpdateCheck = Time.time;
if (RebirthUtilities.sleepersLow.Count > 0)
{
GameManager.Instance.StartCoroutine(RebirthUtilities.BuildSpecificSpawnGroup(3));
//RebirthUtilities.BuildSpecificEntityGroups(ref RebirthUtilities.bloodMoonGroups, false, true);
}
}
}
//EVENTS
if (canExecute && !isHordeNight && (Time.time - eventUpdateCheck) > eventUpdateTick)
{
//Log.Out("RebirthManager-Update EVENTS TICK");
eventUpdateCheck = Time.time;
GameManager.Instance.StartCoroutine(RebirthUtilities.CheckEvents());
}
//SCENARIOS
if (canExecute && RebirthVariables.customScenario == "purge" && (Time.time - cleanupUpdateCheck) > cleanupUpdateTick)
{
//Log.Out("RebirthManager-Update SCENARIOS TICK");
cleanupUpdateCheck = Time.time;
GameManager.Instance.StartCoroutine(RebirthUtilities.CleanupPurgePrefabs());
}
if (canExecute && RebirthVariables.customScenario == "purge" && (Time.time - prefabUpdateCheck) > prefabUpdateTick)
{
//Log.Out("RebirthManager-Update PURGE TICK");
prefabUpdateCheck = Time.time;
GameManager.Instance.StartCoroutine(RebirthUtilities.UpdatePurgePrefabs());
}
}
//HIRES: FUNCTIONS
public static bool hasHire(int playerID, int hireID)
{
return playerHires.Any(hire => hire.playerID == playerID && hire.hireID == hireID);
}
public static void RemoveHire(int entityID, bool removeObserver = false)
{
//Log.Out("RebirthManager-RemoveHire entityID: " + entityID);
bool foundHire = false;
for (int i = 0; i < playerHires.Count; i++)
{
//Log.Out("RebirthManager-RemoveHire 2, playerHires[i].hireID: " + playerHires[i].hireID);
if (playerHires[i].hireID == entityID)
{
foundHire = true;
//Log.Out("RebirthManager-RemoveHire 3");
if (SingletonMonoBehaviour<ConnectionManager>.Instance.IsServer)
{
//Log.Out("RebirthManager-RemoveHire IS SERVER");
if (RebirthUtilities.SendToClient(playerHires[i].playerID))
{
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage(NetPackageManager.GetPackage<NetPackageRemoveHireRebirth>().Setup(entityID
), false, playerHires[i].playerID, -1, -1, null, 192);
//Log.Out("RebirthManager-RemoveHire SENT TO CLIENT");
}
playerHires.RemoveAt(i);
if (removeObserver)
{
//Log.Out("RebirthManager-RemoveHire 4");
for (int j = 0; j < observers.Count; j++)
{
if (observers[j].entityID == entityID)
{
//Log.Out("RebirthManager-RemoveHire REMOVED OBSERVER, hire: " + entityID);
GameManager.Instance.RemoveChunkObserver(observers[j].observerRef);
observers.RemoveAt(j);
break;
}
}
}
SaveCurrent();
}
else
{
SingletonMonoBehaviour<ConnectionManager>.Instance.SendToServer(NetPackageManager.GetPackage<NetPackageRemoveHireRebirth>().Setup(entityID
), false);
playerHires.RemoveAt(i);
//Log.Out("RebirthManager-RemoveHire SENT TO SERVER");
}
//Log.Out("RebirthManager-RemoveHire Removed Hire: " + entityID);
break;
}
}
if (!foundHire)
{
//Log.Out("RebirthManager-RemoveHire COULD NOT FIND HIRE");
if (SingletonMonoBehaviour<ConnectionManager>.Instance.IsClient)
{
//Log.Out("RebirthManager-RemoveHire IS CLIENT");
SingletonMonoBehaviour<ConnectionManager>.Instance.SendToServer(NetPackageManager.GetPackage<NetPackageRemoveHireRebirth>().Setup(entityID
), false);
}
}
}
public static void AddHire(int playerID,
int hireID,
string name,
string className,
Vector3 spawnPosition,
Vector3 spawnRotation,
Vector3 reSpawnPosition,
Vector3 reSpawnRotation,
int numKills,
int numMine,
int order,
bool playerSpawned
)
{
bool foundHire = false;
foreach (hireInfo hire in playerHires)
{
if (hire.playerID == playerID && hire.hireID == hireID)
{
foundHire = true;
break;
}
}
if (!foundHire)
{
hireInfo newHire = new hireInfo();
newHire.playerID = playerID;
newHire.hireID = hireID;
newHire.name = name;
newHire.className = className;
newHire.spawnPosition = spawnPosition;
newHire.spawnRotation = spawnRotation;
newHire.reSpawnPosition = reSpawnPosition;
newHire.reSpawnRotation = reSpawnRotation;
newHire.numMine = numKills;
newHire.numKills = numMine;
newHire.order = order;
newHire.playerSpawned = playerSpawned;
playerHires.Add(newHire);
EntityAlive entity = GameManager.Instance.World.GetEntity(hireID) as EntityAlive;
if (entity != null)
{
entity.Buffs.SetCustomVar("$Leader", playerID);
}
}
if (SingletonMonoBehaviour<ConnectionManager>.Instance.IsServer)
{
SaveCurrent();
if (RebirthUtilities.SendToClient(playerID))
{
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage(NetPackageManager.GetPackage<NetPackageAddHireRebirth>().Setup(playerID,
hireID,
name,
className,
spawnPosition,
spawnRotation,
reSpawnPosition,
reSpawnRotation,
numKills,
numMine,
order,
playerSpawned
), false, playerID, -1, -1, null, 192);
//Log.Out("RebirthManager-AddHire SENT TO CLIENT");
}
}
else
{
SingletonMonoBehaviour<ConnectionManager>.Instance.SendToServer(NetPackageManager.GetPackage<NetPackageAddHireRebirth>().Setup(playerID,
hireID,
name,
className,
spawnPosition,
spawnRotation,
reSpawnPosition,
reSpawnRotation,
numKills,
numMine,
order,
playerSpawned
), false);
//Log.Out("RebirthManager-AddHire SENT TO SERVER");
}
//Log.Out("RebirthManager-AddHire Added Hire: " + hireID);
}
public static void UpdateHireInfo(int hiredID, string action, string value, string position = "", string rotation = "", int newhiredID = -1)
{
//Log.Out("RebirthManager-UpdateHireInfo START");
//Log.Out("RebirthManager-UpdateHireInfo hireID: " + hiredID);
//Log.Out("RebirthManager-UpdateHireInfo action: " + action);
//Log.Out("RebirthManager-UpdateHireInfo value: " + value);
//Log.Out("RebirthManager-UpdateHireInfo position: " + position);
//Log.Out("RebirthManager-UpdateHireInfo rotation: " + rotation);
//Log.Out("RebirthManager-UpdateHireInfo newhiredID: " + newhiredID);
foreach (hireInfo hire in playerHires)
{
if (hire.hireID == hiredID || hire.hireID == newhiredID)
{
//Log.Out("RebirthManager-UpdateHireInfo FOUND HIRE");
bool changed = false;
bool addObserver = false;
if (action == "newid")
{
changed = true;
}
else if (action == "order")
{
//Log.Out("RebirthManager-UpdateHireInfo order value: " + value);
if (value == "follow")
{
hire.order = 0;
changed = true;
for (int j = 0; j < observers.Count; j++)
{
if (observers[j].entityID == hire.hireID)
{
//Log.Out("RebirthManager-RemoveHire REMOVED OBSERVER, hire: " + entityID);
GameManager.Instance.RemoveChunkObserver(observers[j].observerRef);
observers.RemoveAt(j);
break;
}
}
}
else if (value == "stay")
{
hire.order = 1;
hire.spawnPosition = StringParsers.ParseVector3(position);
hire.spawnRotation = StringParsers.ParseVector3(rotation);
changed = true;
addObserver = true;
}
else if (value == "guard")
{
hire.order = 2;
hire.spawnPosition = StringParsers.ParseVector3(position);
hire.spawnRotation = StringParsers.ParseVector3(rotation);
changed = true;
addObserver = true;
}
if (addObserver)
{
bool foundHire = false;
foreach (chunkObservers observer in observers)
{
if (observer.entityID == hire.hireID)
{
foundHire = true;
break;
}
}
if (!foundHire)
{
ChunkManager.ChunkObserver observerRef = GameManager.Instance.AddChunkObserver(hire.spawnPosition, false, 3, -1);
observers.Add(new chunkObservers(hire.hireID, observerRef));
}
}
}
else if (action == "reSpawnPosition")
{
//Log.Out("RebirthManager-UpdateHireInfo reSpawnPosition: " + position);
//Log.Out("RebirthManager-UpdateHireInfo reSpawnRotation: " + rotation);
hire.reSpawnPosition = StringParsers.ParseVector3(position);
hire.reSpawnRotation = StringParsers.ParseVector3(rotation);
hire.spawnPosition = StringParsers.ParseVector3(position);
hire.spawnRotation = StringParsers.ParseVector3(rotation);
changed = true;
}
if (changed)
{
//Log.Out("RebirthManager-UpdateHireInfo CHANGE HIRE INFO");
if (SingletonMonoBehaviour<ConnectionManager>.Instance.IsServer)
{
SaveCurrent();
bool sendToClient = RebirthUtilities.SendToClient(hire.playerID);
//Log.Out("RebirthManager-UpdateHireInfo sendToClient: " + sendToClient);
if (sendToClient)
{
//Log.Out("RebirthManager-UpdateHireInfo current ID: " + hiredID);
//Log.Out("RebirthManager-UpdateHireInfo new ID: " + newhiredID);
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage(NetPackageManager.GetPackage<NetPackageChangeHireInfoRebirth>().Setup(hire.playerID,
hiredID,
hire.name,
hire.spawnPosition,
hire.spawnRotation,
hire.reSpawnPosition,
hire.reSpawnRotation,
hire.numKills,
hire.numMine,
hire.order,
hire.playerSpawned,
action,
value,
newhiredID
), false, hire.playerID, -1, -1, null, 192);
//Log.Out("RebirthManager-UpdateHireInfo SENT TO CLIENT");
}
}
else
{
SingletonMonoBehaviour<ConnectionManager>.Instance.SendToServer(NetPackageManager.GetPackage<NetPackageChangeHireInfoRebirth>().Setup(hire.playerID,
hiredID,
hire.name,
hire.spawnPosition,
hire.spawnRotation,
hire.reSpawnPosition,
hire.reSpawnRotation,
hire.numKills,
hire.numMine,
hire.order,
hire.playerSpawned,
action,
value,
newhiredID
), false);
//Log.Out("RebirthManager-UpdateHireInfo SENT TO SERVER");
}
}
}
}
}
public static bool CheckHires(int playerID, int hireID)
{
EntityPlayer player = GameManager.Instance.World.GetEntity(playerID) as EntityPlayer;
if (player == null)
{
return true;
}
if (!player.IsSpawned())
{
return true;
}
Chunk chunkPlayer = (Chunk)GameManager.Instance.World.GetChunkFromWorldPos((int)player.position.x, (int)player.position.z);
//Log.Out("RebirthManager-CheckHires START");
foreach (hireInfo hire in playerHires)
{
if (hire.playerID == playerID && hire.hireID == hireID && hire.playerSpawned)
{
if (SingletonMonoBehaviour<ConnectionManager>.Instance.IsServer)
{
bool addObserver = false;
//Log.Out("RebirthManager-CheckHires playerID: " + playerID + " / hireID: " + hireID);*/
Vector3 position = player.position;
Vector3 rotation = player.rotation;
bool setPosition = false;
if (hire.order == 1 || hire.order == 2 && hire.spawnPosition != new Vector3(0, 0, 0))
{
position = hire.spawnPosition;
rotation = hire.spawnRotation;
setPosition = true;
//Log.Out("RebirthManager-CheckHires SPAWN WHERE THEY LAST STAYED: " + position);
}
if (hire.reSpawnPosition != new Vector3(0, 0, 0))
{
position = hire.reSpawnPosition;
rotation = hire.reSpawnRotation;
hire.order = 1;
setPosition = true;
//Log.Out("RebirthManager-CheckHires SPAWNING AT REGROUP POINT: " + position);
}
if (!setPosition)
{
SpawnPosition spawnPoint = RebirthUtilities.GetSpawnPoint(player);
if (!spawnPoint.IsUndef() && spawnPoint.position != new Vector3(0, 0, 0))
{
position = spawnPoint.position;
rotation = player.rotation;
hire.order = 1;
setPosition = true;
//Log.Out("RebirthManager-CheckHires SPAWNING AT BEDROLL: " + position);
}
else
{
//Log.Out("RebirthManager-CheckHires SPAWNING AT PLAYER LOCATION: " + position);
}
}
Chunk chunkHire = (Chunk)GameManager.Instance.World.GetChunkFromWorldPos((int)position.x, (int)position.z);
if (chunkHire != null)
{
//Log.Out("RebirthManager-CheckHires chunkHire pos: " + chunkHire.ChunkPos);
//Log.Out("RebirthManager-CheckHires chunkPlayer pos: " + chunkPlayer.ChunkPos);
}
if (chunkHire != null)
{
Entity entity = GameManager.Instance.World.GetEntity(hire.hireID) as Entity;
if (entity == null)
{
bool skipEntity = true; // false;
if (!skipEntity)
{
////Log.Out("RebirthManager-CheckHires Couldn't find owned entity in the world");
//Log.Out("RebirthManager-CheckHires Created Missing Hire: " + hireID + " / " + hire.className + " / " + hire.name);
EntityNPCRebirth NewEntity = EntityFactory.CreateEntity(EntityClass.FromString(hire.className), position, rotation) as EntityNPCRebirth;
NewEntity.SetSpawnerSource(EnumSpawnerSource.StaticSpawner);
NewEntity._strMyName = hire.name;
RebirthUtilities.SetLeaderAndOwner(NewEntity.entityId, player.entityId);
NewEntity.IsEntityUpdatedInUnloadedChunk = true;
NewEntity.bWillRespawn = true;
NewEntity.bIsChunkObserver = true;
NewEntity.belongsPlayerId = playerID;
NewEntity.guardPosition = position;
if (hire.order == (int)EntityUtilities.Orders.None)
{
//Log.Out("RebirthManager-Update SET TO FOLLOW B");
NewEntity.Buffs.SetCustomVar("CurrentOrder", (int)EntityUtilities.Orders.Follow);
}
else if (hire.order == (int)EntityUtilities.Orders.Follow)
{
//Log.Out("RebirthManager-Update SET TO STAY B");
NewEntity.Buffs.SetCustomVar("CurrentOrder", (int)EntityUtilities.Orders.Stay);
addObserver = true;
}
else
{
//Log.Out("RebirthManager-Update SET TO STAY (GUARD) B");
NewEntity.Buffs.SetCustomVar("CurrentOrder", (int)EntityUtilities.Orders.Stay);
addObserver = true;
}
GameManager.Instance.World.SpawnEntityInWorld(NewEntity);
hire.hireID = NewEntity.entityId;
RebirthUtilities.SetLeaderAndOwner(NewEntity.entityId, player.entityId);
bool foundObserver = false;
for (int i = 0; i < observers.Count; i++)
{
if (observers[i].entityID == hireID)
{
//Log.Out("RebirthManager-CheckHires UPDATED OBSERVER, hire: " + hireID);
observers[i].entityID = NewEntity.entityId;
foundObserver = true;
break;
}
}
float flMode = player.Buffs.GetCustomVar("varNPCModMode");
float flHalt = player.Buffs.GetCustomVar("varNPCModStopAttacking");
if (flMode == 0)
{
NewEntity.Buffs.AddBuff("buffNPCModFullControlMode");
}
else
{
NewEntity.Buffs.RemoveBuff("buffNPCModFullControlMode");
}
if (flHalt == 1)
{
NewEntity.Buffs.AddBuff("buffNPCModStopAttacking");
}
else
{
NewEntity.Buffs.RemoveBuff("buffNPCModStopAttacking");
}
if (addObserver && !foundObserver)
{
//Log.Out("RebirthManager-CheckHires ADDED CHUNK OBSERVER, hire: " + hireID);
ChunkManager.ChunkObserver observerRef = GameManager.Instance.AddChunkObserver(position, false, 3, -1);
observers.Add(new chunkObservers(NewEntity.entityId, observerRef));
}
return true;
}
}
}
else
{
//Log.Out("RebirthManager-CheckHires CAN'T LOAD HIRE CHUNK: " + position);
return true;
}
}
}
}
return false;
}
public static void Write(BinaryWriter _bw)
{
//Log.Out("RebirthManager-Write playerHires.Count: " + playerHires.Count);
foreach (hireInfo hire in playerHires)
{
//Log.Out("RebirthManager-Write hire.playerID: " + hire.playerID);
//Log.Out("RebirthManager-Write hire.hireID: " + hire.hireID);
//Log.Out("RebirthManager-Write hire.name: " + hire.name);
_bw.Write(hire.playerID.ToString());
_bw.Write(hire.hireID.ToString());
_bw.Write(hire.name);
_bw.Write(hire.className);
_bw.Write(hire.spawnPosition.ToString());
_bw.Write(hire.spawnRotation.ToString());
_bw.Write(hire.reSpawnPosition.ToString());
_bw.Write(hire.reSpawnRotation.ToString());
_bw.Write(hire.numKills.ToString());
_bw.Write(hire.numMine.ToString());
_bw.Write(hire.order.ToString());
_bw.Write(hire.playerSpawned);
}
}
public static void Read(BinaryReader _br)
{
//Log.Out("RebirthManager-Read START");
while (_br.BaseStream.Position != _br.BaseStream.Length)
{
hireInfo hire = new hireInfo();
hire.playerID = int.Parse(_br.ReadString());
hire.hireID = int.Parse(_br.ReadString());
hire.name = _br.ReadString();
hire.className = _br.ReadString();
hire.spawnPosition = StringParsers.ParseVector3(_br.ReadString());
hire.spawnRotation = StringParsers.ParseVector3(_br.ReadString());
hire.reSpawnPosition = StringParsers.ParseVector3(_br.ReadString());
hire.reSpawnRotation = StringParsers.ParseVector3(_br.ReadString());
hire.numKills = int.Parse(_br.ReadString());
hire.numMine = int.Parse(_br.ReadString());
hire.order = int.Parse(_br.ReadString());
hire.playerSpawned = _br.ReadBoolean();
playerHires.Add(hire);
//Log.Out("NetPackageGetHiresRebirth-Read Added playerID: " + hire.playerID);
//Log.Out("NetPackageGetHiresRebirth-Read Added hire: " + hire.hireID);
//Log.Out("NetPackageGetHiresRebirth-Read Added name: " + hire.name);
//Log.Out("NetPackageGetHiresRebirth-Read hire.order: " + hire.order);
////Log.Out("NetPackageGetHiresRebirth-Read GameManager.IsDedicatedServer: " + GameManager.IsDedicatedServer);
}
}
private static int saveDataThreaded(ThreadManager.ThreadInfo _threadInfo)
{
//Log.Out("RebirthManager-saveDataThreaded START");
PooledExpandableMemoryStream pooledExpandableMemoryStream = (PooledExpandableMemoryStream)_threadInfo.parameter;
string text = string.Format("{0}/{1}", GameIO.GetSaveGameDir(), hiresSaveFile);
if (!Directory.Exists(GameIO.GetSaveGameDir()))
{
Directory.CreateDirectory(GameIO.GetSaveGameDir());
}
if (File.Exists(text))
{
File.Copy(text, string.Format("{0}/{1}", GameIO.GetSaveGameDir(), $"{hiresSaveFile}.bak"), true);
}
pooledExpandableMemoryStream.Position = 0L;
StreamUtils.WriteStreamToFile(pooledExpandableMemoryStream, text);
pooledExpandableMemoryStream.Dispose();
////Log.Out($"Broadcast Manager {text} Saving: {Broadcastmap.Count}");
return -1;
}
public static void Save()
{
//Log.Out("RebirthManager-Save START");
if (dataSaveThreadInfo == null || !ThreadManager.ActiveThreads.ContainsKey("silent_HiresManagerDataSave"))
{
PooledExpandableMemoryStream pooledExpandableMemoryStream = MemoryPools.poolMemoryStream.AllocSync(true);
using (PooledBinaryWriter pooledBinaryWriter = MemoryPools.poolBinaryWriter.AllocSync(false))
{
pooledBinaryWriter.SetBaseStream(pooledExpandableMemoryStream);
Write(pooledBinaryWriter);
}
dataSaveThreadInfo = ThreadManager.StartThread("silent_HiresManagerDataSave", null, new ThreadManager.ThreadFunctionLoopDelegate(saveDataThreaded), null, System.Threading.ThreadPriority.Normal, pooledExpandableMemoryStream, null, false);
}
}
public static void LoadHires()
{
//Log.Out("RebirthManager-Load START");
string path = string.Format("{0}/{1}", GameIO.GetSaveGameDir(), hiresSaveFile);
//Log.Out("RebirthManager-Load GameIO.GetSaveGameDir(): " + GameIO.GetSaveGameDir());
//Log.Out("RebirthManager-Load saveFile: " + hiresSaveFile);
if (Directory.Exists(GameIO.GetSaveGameDir()) && File.Exists(path))
{
//Log.Out("RebirthManager-Load 1");
try
{
using (FileStream fileStream = File.OpenRead(path))
{
using (PooledBinaryReader pooledBinaryReader = MemoryPools.poolBinaryReader.AllocSync(false))
{
//Log.Out("RebirthManager-Load 2");
pooledBinaryReader.SetBaseStream(fileStream);
Read(pooledBinaryReader);
}
}
}
catch (Exception)
{
path = string.Format("{0}/{1}", GameIO.GetSaveGameDir(), $"{hiresSaveFile}.bak");
if (File.Exists(path))
{
//Log.Out("RebirthManager-Load 3");
using (FileStream fileStream2 = File.OpenRead(path))
{
using (PooledBinaryReader pooledBinaryReader2 = MemoryPools.poolBinaryReader.AllocSync(false))
{
//Log.Out("RebirthManager-Load 4");
pooledBinaryReader2.SetBaseStream(fileStream2);
Read(pooledBinaryReader2);
}
}
}
}
}
}
private static void WaitOnSave()
{
if (dataSaveThreadInfo != null)
{
dataSaveThreadInfo.WaitForEnd();
dataSaveThreadInfo = null;
}
}
public static void Cleanup()
{
if (instance != null)
{
SaveAndClear();
}
}
public static void SaveCurrent()
{
//Log.Out("RebirthManager-SaveCurrent SAVED CURRENT");
//WaitOnSave();
Save();
//WaitOnSave();
}
private static void SaveAndClear()
{
//WaitOnSave();
Save();
//WaitOnSave();
playerHires.Clear();
observers.Clear();
instance = null;
//Log.Out("Hires Manager stopped");
}
//SCENARIOS: FUNCTIONS
public static void AddDynamicPrefab(DynamicPrefab prefab)
{
dynamicPrefabs.Add(prefab);
}
// Remove from the list using prefabName and position
public static bool RemoveDynamicPrefab(string prefabName, Vector3 position)
{
var prefabToRemove = dynamicPrefabs.Find(p => p.PrefabName == prefabName && p.Position == position);
if (prefabToRemove != null)
{
dynamicPrefabs.Remove(prefabToRemove);
return true;
}
return false;
}
// Retrieve the first entry for a given difficulty and biome
public static DynamicPrefab RetrieveDynamicPrefab(int difficulty, string biome)
{
return dynamicPrefabs.Find(p => p.Difficulty == difficulty && p.Biome == biome);
}
public static DynamicPrefab RetrieveDynamicPrefab(List<DynamicPrefab> tempDynamicPrefabs, int difficulty, string biome)
{
return tempDynamicPrefabs.Find(p => p.Difficulty == difficulty && p.Biome == biome);
}
public static List<DynamicPrefab> RetrieveDynamicPrefabs(string biome)
{
// Filter prefabs based on the biome provided
List<DynamicPrefab> filteredPrefabs = dynamicPrefabs.FindAll(prefab => prefab.Biome == biome);
return filteredPrefabs;
}
public static List<DynamicPrefab> RetrieveDynamicPrefabsFromDistance(string biome, Vector3 playerPosition, float distance, int difficulty)
{
List<DynamicPrefab> filteredPrefabs = dynamicPrefabs.FindAll(prefab => prefab.Biome == biome && prefab.Difficulty == difficulty);
foreach (var prefab in dynamicPrefabs)
{
// Calculate the distance between the prefab position and the player's position
Vector3 location = new Vector3(prefab.Position.x + prefab.Size.x / 2f, prefab.Position.y, prefab.Position.z + prefab.Size.z / 2f);
float distanceToPrefab = Vector3.Distance(location, playerPosition);
// Check if the prefab is within the specified distance
if (distanceToPrefab > distance)
{
filteredPrefabs.Remove(prefab);
}
}
return filteredPrefabs;
}
public static int RetrieveTotalBiomePrefabs(string biome, int difficulty)
{
List<DynamicPrefab> filteredPrefabs = dynamicPrefabs.FindAll(prefab => prefab.Biome == biome && prefab.Difficulty == difficulty);
//Log.Out("RebirthManager-RetrieveTotalBiomePrefabs filteredPrefabs.Count: " + filteredPrefabs.Count);
return filteredPrefabs.Count;
}
private static void LoadScenario(string scenario)
{
string scenarioPath = $"{SaveDataPath}/{GamePrefs.GetString(EnumGamePrefs.GameWorld)}/{GamePrefs.GetString(EnumGamePrefs.GameName)}";
Directory.CreateDirectory(scenarioPath);
string scenarioFilePath = $"{scenarioPath}/" + scenario + ".xml";
string discoveredFilePath = $"{scenarioPath}/discoveredPrefabs.xml";
string purgeKillsFilePath = $"{scenarioPath}/purgeKillsInfo.xml";
bool exists = System.IO.File.Exists(scenarioFilePath);
bool createNew = false;
if (exists)
{
//Log.Out("RebirthManager-LoadScenario SCENARIO FILE EXISTS");
int currentDay = GameUtils.WorldTimeToDays(GameManager.Instance.World.worldTime);
//Log.Out("RebirthManager-LoadScenario currentDay: " + currentDay);
float currentTimeOfDayHours = GameUtils.WorldTimeToHours(GameManager.Instance.World.worldTime);
//Log.Out("RebirthManager-LoadScenario currentTimeOfDayHours: " + currentTimeOfDayHours);
float currentTimeOfDayMinutes = GameUtils.WorldTimeToMinutes(GameManager.Instance.World.worldTime);
//Log.Out("RebirthManager-LoadScenario currentTimeOfDayMinutes: " + currentTimeOfDayMinutes);
if (currentDay == 1 && currentTimeOfDayHours == 7 && currentTimeOfDayMinutes < 20)
{
//Log.Out("RebirthManager-LoadScenario EARLY MORNING");
try
{
Directory.Delete(scenarioFilePath);
}
catch { }
if (scenario == "purge")
{
try
{
Directory.Delete(purgeKillsFilePath);
}
catch { }
}
createNew = true;
}
}
else
{
//Log.Out("RebirthManager-LoadScenario SCENARIO FILE DOES NOT EXIST");
createNew = true;
}
if (createNew)
{
//Log.Out("RebirthManager-LoadScenario CREATE NEW FILE");
SaveScenario(scenario); // Save an empty file if it doesn't exist
SaveDiscovered();
if (scenario == "purge")
{
SavePurgeKills();
}
return;
}
//Log.Out("RebirthManager-LoadScenario LOAD EXISTING FILE");
if (scenario == "hive")
{
}
else if (scenario == "purge")
{
XDocument xmlDoc = XDocument.Load(scenarioFilePath);
ClearedPrefabs = (from prefab in xmlDoc.Root.Elements("Prefab")
select new PrefabInfo
{
Name = prefab.Element("Name").Value,
Position = new Vector3(
float.Parse(prefab.Element("Position").Element("X").Value),
float.Parse(prefab.Element("Position").Element("Y").Value),
float.Parse(prefab.Element("Position").Element("Z").Value)),
Size = new Vector3(
float.Parse(prefab.Element("Size").Element("X").Value),
float.Parse(prefab.Element("Size").Element("Y").Value),
float.Parse(prefab.Element("Size").Element("Z").Value)),
Difficulty = int.Parse(prefab.Element("Difficulty").Value),
EntitiesCleared = int.Parse(prefab.Element("EntitiesCleared").Value),
Players = prefab.Element("Players").Elements("Player")
.ToDictionary(p => int.Parse(p.Element("ID").Value), p => p.Element("Name").Value),
Biome = prefab.Element("Biome").Value
}).ToList();
if (File.Exists(discoveredFilePath))
{
xmlDoc = XDocument.Load(discoveredFilePath);
DiscoveredPrefabs = (from prefab in xmlDoc.Root.Elements("Prefab")
select new PrefabInfo
{
Name = prefab.Element("Name").Value,
Position = new Vector3(
float.Parse(prefab.Element("Position").Element("X").Value),
float.Parse(prefab.Element("Position").Element("Y").Value),
float.Parse(prefab.Element("Position").Element("Z").Value)),
Size = new Vector3(
float.Parse(prefab.Element("Size").Element("X").Value),
float.Parse(prefab.Element("Size").Element("Y").Value),
float.Parse(prefab.Element("Size").Element("Z").Value)),
Difficulty = int.Parse(prefab.Element("Difficulty").Value),
EntitiesCleared = int.Parse(prefab.Element("EntitiesCleared").Value),
Players = prefab.Element("Players").Elements("Player")
.ToDictionary(p => int.Parse(p.Element("ID").Value), p => p.Element("Name").Value),
Biome = prefab.Element("Biome").Value
}).ToList();
}
if (File.Exists(purgeKillsFilePath))
{
xmlDoc = XDocument.Load(purgeKillsFilePath);
purgeKills = (from purgeKill in xmlDoc.Root.Elements("PurgeKill")
select new PurgeKills
{
Name = purgeKill.Element("Name").Value,
Position = new Vector3(
float.Parse(purgeKill.Element("Position").Element("X").Value),
float.Parse(purgeKill.Element("Position").Element("Y").Value),
float.Parse(purgeKill.Element("Position").Element("Z").Value)),
Players = purgeKill.Element("Players").Elements("Player")
.ToDictionary(p => int.Parse(p.Element("ID").Value), p => new KillInfo
{
Kills = int.Parse(p.Element("Kills").Value),
Redeemed = bool.Parse(p.Element("Redeemed").Value) // Load Redeemed value
})
}).ToList();
}
}
}
public static void SaveScenario(string scenario)
{
string scenarioPath = $"{SaveDataPath}/{GamePrefs.GetString(EnumGamePrefs.GameWorld)}/{GamePrefs.GetString(EnumGamePrefs.GameName)}";
Directory.CreateDirectory(scenarioPath);
string scenarioFilePath = $"{scenarioPath}/" + scenario + ".xml";
if (scenario == "hive")
{
//XDocument xmlDoc = new XDocument();
//xmlDoc.Save(scenarioFilePath);
}
else if (scenario == "purge")
{
XElement root = new XElement("Prefabs",
from prefab in ClearedPrefabs
select new XElement("Prefab",
new XElement("Name", prefab.Name),
new XElement("Position",
new XElement("X", prefab.Position.x),
new XElement("Y", prefab.Position.y),
new XElement("Z", prefab.Position.z)),
new XElement("Size",
new XElement("X", prefab.Size.x),
new XElement("Y", prefab.Size.y),
new XElement("Z", prefab.Size.z)),
new XElement("Difficulty", prefab.Difficulty),
new XElement("EntitiesCleared", prefab.EntitiesCleared),
new XElement("Players",
from player in prefab.Players
select new XElement("Player",
new XElement("ID", player.Key),
new XElement("Name", player.Value))),
new XElement("Biome", prefab.Biome)
));
XDocument xmlDoc = new XDocument(root);
xmlDoc.Save(scenarioFilePath);
}
}
public static void SaveDiscovered()
{
string scenarioPath = $"{SaveDataPath}/{GamePrefs.GetString(EnumGamePrefs.GameWorld)}/{GamePrefs.GetString(EnumGamePrefs.GameName)}";
Directory.CreateDirectory(scenarioPath);
string filePath = $"{scenarioPath}/discoveredPrefabs.xml";
XElement root = new XElement("Prefabs",
from prefab in DiscoveredPrefabs
select new XElement("Prefab",
new XElement("Name", prefab.Name),
new XElement("Position",
new XElement("X", prefab.Position.x),
new XElement("Y", prefab.Position.y),
new XElement("Z", prefab.Position.z)),
new XElement("Size",
new XElement("X", prefab.Size.x),
new XElement("Y", prefab.Size.y),
new XElement("Z", prefab.Size.z)),
new XElement("Difficulty", prefab.Difficulty),
new XElement("EntitiesCleared", prefab.EntitiesCleared),
new XElement("Players",
from player in prefab.Players
select new XElement("Player",
new XElement("ID", player.Key),
new XElement("Name", player.Value))),
new XElement("Biome", prefab.Biome)
));
XDocument xmlDoc = new XDocument(root);
xmlDoc.Save(filePath);
}
// PURGE KILLS HELPERS
public static int GetTotalPurgeKills(string name, Vector3 position)
{
// Get the list of players from the GetPurgeKillPlayers function
var players = GetPurgeKillPlayers(name, position);
// Sum the total kills of all players
return players.Sum(p => p.Kills);
}
public static List<PlayerKillInfo> GetPurgeKillPlayers(string name, Vector3 position)
{
var purgeKill = GetPurgeKillEntry(name, position);
if (purgeKill != null)
{
// Convert the Players dictionary to a list of PlayerKillInfo
return purgeKill.Players.Select(p => new PlayerKillInfo
{
PlayerID = p.Key,
Kills = p.Value.Kills, // Access kills from KillInfo
Redeemed = p.Value.Redeemed // Access redeemed status from KillInfo
}).ToList();
}
return new List<PlayerKillInfo>(); // Return an empty list if no matching PurgeKill entry is found
}
public static List<PurgeKills> GetPurgeKillEntries(int playerID)
{
return purgeKills.Where(pk => pk.Players.ContainsKey(playerID)).ToList();
}
private static PurgeKills GetPurgeKillEntry(string name, Vector3 position)
{
return purgeKills.FirstOrDefault(pk => pk.Name == name && pk.Position == position);
}
private static bool PurgeKillExists(string name, Vector3 position)
{
return purgeKills.Any(pk => pk.Name == name && pk.Position == position);
}
public static int GetTotalKills(int playerID)
{
// Sum the total kills for the playerID across all PurgeKills entries
int totalKills = purgeKills
.Where(purgeKill => purgeKill.Players.ContainsKey(playerID)) // Filter entries that have this playerID
.Sum(purgeKill => purgeKill.Players[playerID].Kills); // Sum the kills for this playerID
return totalKills;
}
public static List<PurgeKills> GetKills(string name, Vector3 position, int playerID)
{
return purgeKills.Where(pk => pk.Name == name && pk.Position == position && pk.Players.ContainsKey(playerID)).ToList();
}
public static bool RemoveKills(string name, Vector3 position, int playerID)
{
var purgeKill = GetPurgeKillEntry(name, position);
if (purgeKill != null && purgeKill.Players.ContainsKey(playerID))
{
purgeKill.Players.Remove(playerID);
if (purgeKill.Players.Count == 0)
{
purgeKills.Remove(purgeKill);
}
SavePurgeKills();
return true;
}
return false;
}
public static (int numKills, int numRedeemableKills) AddKill(string name, Vector3 position, int playerID)
{
var purgeKill = GetPurgeKillEntry(name, position);
if (purgeKill == null)
{
purgeKill = new PurgeKills
{
Name = name,
Position = position
};
purgeKills.Add(purgeKill);
}
if (!purgeKill.Players.ContainsKey(playerID))
{
purgeKill.Players[playerID] = new KillInfo { Kills = 0, Redeemed = false }; // Initialize with default values
}
purgeKill.Players[playerID].Kills++;
SavePurgeKills();
int numKills = GetCurrentPurgeKills(playerID);
int numRedeemableKills = GetCurrentRedeemablePurgeKills(playerID);
//Log.Out("RebirthManager-AddKill numKills: " + numKills);
//Log.Out("RebirthManager-AddKill numRedeemableKills: " + numRedeemableKills);
return (numKills, numRedeemableKills);
}
public static bool RedeemKills(string name, Vector3 position, int playerID)
{
// Find the matching PurgeKill entry
var purgeKill = GetPurgeKillEntry(name, position);
if (purgeKill != null && purgeKill.Players.ContainsKey(playerID))
{
// Check if the player has any kills
var killInfo = purgeKill.Players[playerID];
if (killInfo != null && !killInfo.Redeemed) // If not already redeemed
{
killInfo.Redeemed = true; // Mark as redeemed
SavePurgeKills(); // Save the updated kills
return true; // Return true if the operation was successful
}
}
return false; // Return false if the operation failed
}
public static int AutoRedeemKills(int playerID)
{
int totalKills = 0;
// Loop through all purge kills
foreach (var purgeKill in purgeKills)
{
// Check if the player is in the current PurgeKill entry
if (purgeKill.Players.ContainsKey(playerID) && IsPrefabCleared(purgeKill.Name, purgeKill.Position))
{
var killInfo = purgeKill.Players[playerID];
// If the kill entry was redeemed, reset it and add kills to total
if (!killInfo.Redeemed)
{
killInfo.Redeemed = true; // Reset the redeemed flag
totalKills += killInfo.Kills; // Add kills to the total count
}
}
}
// Save updated data
SavePurgeKills();
return totalKills; // Return total number of kills that were updated
}
public static int GetCurrentPurgeKills(int playerID)
{
int totalKills = 0;
// Loop through all purge kills
foreach (var purgeKill in purgeKills)
{
// Check if the player is in the current PurgeKill entry
if (purgeKill.Players.ContainsKey(playerID))
{
var killInfo = purgeKill.Players[playerID];
// If the kill entry was redeemed, reset it and add kills to total
if (!killInfo.Redeemed)
{
totalKills += killInfo.Kills; // Add kills to the total count
}
}
}
return totalKills;
}
public static int GetCurrentRedeemablePurgeKills(int playerID)
{
int totalKills = 0;
// Loop through all purge kills
foreach (var purgeKill in purgeKills)
{
// Check if the player is in the current PurgeKill entry
if (purgeKill.Players.ContainsKey(playerID) && !IsPrefabCleared(purgeKill.Name, purgeKill.Position))
{
var killInfo = purgeKill.Players[playerID];
// If the kill entry was redeemed, reset it and add kills to total
if (!killInfo.Redeemed)
{
totalKills += killInfo.Kills; // Add kills to the total count
}
}
}
return totalKills;
}
private static void SavePurgeKills()
{
if (GameManager.Instance.World.IsEditor())
{
return;
}
string scenarioPath = $"{SaveDataPath}/{GamePrefs.GetString(EnumGamePrefs.GameWorld)}/{GamePrefs.GetString(EnumGamePrefs.GameName)}";
string purgeKillsFilePath = $"{scenarioPath}/purgeKillsInfo.xml";
XElement root = new XElement("PurgeKills",
from purgeKill in purgeKills
select new XElement("PurgeKill",
new XElement("Name", purgeKill.Name),
new XElement("Position",
new XElement("X", purgeKill.Position.x),
new XElement("Y", purgeKill.Position.y),
new XElement("Z", purgeKill.Position.z)),
new XElement("Players",
from player in purgeKill.Players
select new XElement("Player",
new XElement("ID", player.Key),
new XElement("Kills", player.Value.Kills), // Save kills
new XElement("Redeemed", player.Value.Redeemed) // Save redeemed status
))
));
XDocument xmlDoc = new XDocument(root);
xmlDoc.Save(purgeKillsFilePath);
}
// PREFAB INFO HELPERS
public static string GetFirstPlayerName(PrefabInfo prefabInfo)
{
if (prefabInfo.Players != null && prefabInfo.Players.Count > 0)
{
// Get the first player's name (the first value from the dictionary)
return prefabInfo.Players.Values.First();
}
return null; // Return null if the dictionary is empty or not set
}
public static void AddPrefab(string name, Vector3 position, Vector3 size, int difficulty, int entitiesCleared, Dictionary<int, string> players, string biome)
{
if (IsPrefabCleared(name, position))
{
return;
}
PrefabInfo newPrefab = new PrefabInfo
{
Name = name,
Position = position,
Size = size,
Difficulty = difficulty,
EntitiesCleared = entitiesCleared,
Players = players,
Biome = biome
};
Vector3 vector = new Vector3(newPrefab.Position.x + newPrefab.Size.x / 2f, newPrefab.Position.y, newPrefab.Position.z + newPrefab.Size.z / 2f);
ClearedPrefabs.Add(newPrefab);
int clearedPrefabs = GetTotalClearedPrefabCount(biome);
int totalPrefabs = RebirthUtilities.GetTotalSpawnedPrefab(biome);
//Log.Out($"RebirthManager-AddPrefab biome: {biome} / clearedPrefabs: {clearedPrefabs} of {totalPrefabs}");
SaveScenario("purge"); // Automatically save after adding
// remove prefab from discovered
RemoveDiscoveredPrefab(name, position, vector);
RemoveDynamicPrefab(name, position);
//Debug.Log($"Prefab: {newPrefab.Name} / position: {newPrefab.Position} / size: {newPrefab.Size} / Difficulty: {newPrefab.Difficulty} / Entities Cleared: {newPrefab.EntitiesCleared} / Reported By: {players} / Biome: {newPrefab.Biome}");
bool reportLocal = false;
string report = string.Format(Localization.Get("PurgePurgedReport"), GetFirstPlayerName(newPrefab), entitiesCleared, Localization.Get(name), Localization.Get("biome_" + biome));
string sound = "purge_discovered";
if (SingletonMonoBehaviour<ConnectionManager>.Instance.IsSinglePlayer)
{
reportLocal = true;
RebirthVariables.purgeDisplayPercentage = ((float)clearedPrefabs / totalPrefabs) * 100;
int numPrefabs = clearedPrefabs;
if (clearedPrefabs > totalPrefabs)
{
numPrefabs = totalPrefabs;
}
RebirthVariables.purgeLabel = numPrefabs + "/" + totalPrefabs;
}
else
{
if (!GameManager.IsDedicatedServer)
{
reportLocal = true;
RebirthVariables.purgeDisplayPercentage = ((float)clearedPrefabs / totalPrefabs) * 100;
int numPrefabs = clearedPrefabs;
if (clearedPrefabs > totalPrefabs)
{
numPrefabs = totalPrefabs;
}
RebirthVariables.purgeLabel = numPrefabs + "/" + totalPrefabs;
}
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage(NetPackageManager.GetPackage<NetPackageRegisterPrefabNavIcon>().Setup("purge_waypoint", vector.x, vector.y, vector.z, report, sound));
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage(NetPackageManager.GetPackage<NetPackageUpdatePurgeDisplay>().Setup(name, position.x, position.y, position.z, 0, 0, 0, 0, 0, 0, 0), false);
}
if (reportLocal)
{
NavObject navPurged = NavObjectManager.Instance.RegisterNavObject("purge_waypoint", vector, "purge_waypoint");
if (navPurged != null)
{
navPurged.trackedPosition = vector;
}
EntityPlayerLocal primaryPlayer = GameManager.Instance.World.GetPrimaryPlayer();
if (primaryPlayer != null)
{
if (sound != "")
{
Manager.PlayInsidePlayerHead(sound);
}
//Log.Out("RebirthManager-AddPrefab report: " + report);
GameManager.ShowTooltip(primaryPlayer, report, string.Empty);
}
}
}
public static void AddDiscoveredPrefab(string name, Vector3 position, Vector3 size, int difficulty, int entitiesCleared, Dictionary<int, string> players, string biome)
{
//Log.Out("RebirthManager-AddDiscoveredPrefab START");
PrefabInfo newPrefab = new PrefabInfo
{
Name = name,
Position = position,
Size = size,
Difficulty = difficulty,
EntitiesCleared = entitiesCleared,
Players = players,
Biome = biome
};
//Log.Out($"Prefab: {newPrefab.Name} / position: {newPrefab.Position} / size: {newPrefab.Size} / Difficulty: {newPrefab.Difficulty} / Entities Cleared: {newPrefab.EntitiesCleared} / Reported By: {players} / Biome: {newPrefab.Biome}");
if (IsPrefabDiscovered(name, position))
{
//Log.Out("RebirthManager-AddDiscoveredPrefab ALREADY DISCOVERED");
return;
}
DiscoveredPrefabs.Add(newPrefab);
SaveDiscovered();
Vector3 vector = new Vector3(newPrefab.Position.x + newPrefab.Size.x / 2f, newPrefab.Position.y, newPrefab.Position.z + newPrefab.Size.z / 2f);
bool reportLocal = false;
string report = string.Format(Localization.Get("PurgeDiscoveryReport"), GetFirstPlayerName(newPrefab), Localization.Get(name), Localization.Get("biome_" + biome));
string sound = "purge_cleared";
if (SingletonMonoBehaviour<ConnectionManager>.Instance.IsSinglePlayer)
{
reportLocal = true;
}
else
{
if (!GameManager.IsDedicatedServer)
{
reportLocal = true;
}
if (players.ContainsKey(-1))
{
report = "";
}
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage(NetPackageManager.GetPackage<NetPackageScenarioAddDiscoveredPrefab>().Setup("discovered_waypoint_" + difficulty, vector.x, vector.y, vector.z, report, sound));
}
if (reportLocal)
{
//Log.Out("RebirthManager-AddDiscoveredPrefab navobject: " + "discovered_waypoint_" + difficulty);
//Log.Out("RebirthManager-AddDiscoveredPrefab vector: " + vector);
NavObject navDiscovered = NavObjectManager.Instance.RegisterNavObject("discovered_waypoint_" + difficulty, vector, "discovered_waypoint_" + difficulty);
if (navDiscovered != null)
{
navDiscovered.trackedPosition = vector;
}
if (!players.ContainsKey(-1))
{
EntityPlayerLocal primaryPlayer = GameManager.Instance.World.GetPrimaryPlayer();
if (primaryPlayer != null)
{
if (sound != "")
{
Manager.PlayInsidePlayerHead(sound);
}
//Log.Out("RebirthManager-AddDiscoveredPrefab report: " + report);
GameManager.ShowTooltip(primaryPlayer, report, string.Empty);
}
}
}
}
// Check if a prefab is cleared by its name and position
public static bool IsPrefabCleared(string name, Vector3 position)
{
return ClearedPrefabs.Any(p => p.Name == name && p.Position == position);
}
public static bool IsPrefabDiscovered(string name, Vector3 position)
{
return DiscoveredPrefabs.Any(p => p.Name == name && p.Position == position && p.Difficulty != -1);
}
// Remove a prefab from the cleared list
public static void RemovePrefab(string name, Vector3 position)
{
var prefabToRemove = ClearedPrefabs.FirstOrDefault(p => p.Name == name && p.Position == position);
if (prefabToRemove != null)
{
ClearedPrefabs.Remove(prefabToRemove);
SaveScenario("purge");
}
else
{
Debug.LogWarning("Prefab not found.");
}
}
public static void UpdateDiscoveredPrefab(string name, Vector3 position, int entitiesCleared)
{
var prefab = DiscoveredPrefabs.FirstOrDefault(p => p.Name == name && p.Position == position);
// If the prefab is found, update the EntitiesCleared value
if (prefab != null)
{
prefab.EntitiesCleared = entitiesCleared;
}
}
public static int GetDiscoveredPrefabEntitiesCleared(string name, Vector3 position)
{
// Find the prefab in the list that matches the name and position
var prefab = DiscoveredPrefabs.FirstOrDefault(p => p.Name == name && p.Position == position);
// Return the EntitiesCleared value if the prefab is found, otherwise return a default value
return prefab != null ? prefab.EntitiesCleared : -1; // Return -1 if not found
}
public static void RemoveDiscoveredPrefab(string name, Vector3 position, Vector3 location)
{
//Log.Out("RebirthManager-RemoveDiscoveredPrefab START");
var prefabToRemove = DiscoveredPrefabs.FirstOrDefault(p => p.Name == name && p.Position == position);
if (prefabToRemove != null)
{
//Log.Out("RebirthManager-RemoveDiscoveredPrefab 1");
DiscoveredPrefabs.Remove(prefabToRemove);
if (SingletonMonoBehaviour<ConnectionManager>.Instance.IsSinglePlayer)
{
//Log.Out("RebirthManager-RemoveDiscoveredPrefab UNREGISTER LOCAL NAV OBJECT: " + "discovered_waypoint_" + prefabToRemove.Difficulty);
//Log.Out("RebirthManager-RemoveDiscoveredPrefab position: " + position);
//Log.Out("RebirthManager-RemoveDiscoveredPrefab location: " + location);
NavObjectManager.Instance.UnRegisterNavObjectByPosition(location, "discovered_waypoint_" + prefabToRemove.Difficulty);
}
else
{
if (!GameManager.IsDedicatedServer)
{
NavObjectManager.Instance.UnRegisterNavObjectByPosition(location, "discovered_waypoint_" + prefabToRemove.Difficulty);
}
//Log.Out("RebirthManager-RemoveDiscoveredPrefab SEND UNREGISTER TO CLIENTS");
SingletonMonoBehaviour<ConnectionManager>.Instance.SendPackage((NetPackage)NetPackageManager.GetPackage<NetPackageUnregisterNavObject>().Setup("discovered_waypoint_" + prefabToRemove.Difficulty, location.x, location.y, location.z), false);
}
SaveDiscovered();
}
else
{
Debug.LogWarning("Prefab not found.");
}
}
// Retrieve prefabs by player name
public static List<PrefabInfo> GetPrefabsByPlayer(string playerName)
{
return ClearedPrefabs.Where(p => p.PlayerName == playerName).ToList();
}
// Retrieve prefabs by name
public static List<PrefabInfo> GetPrefabsByName(string prefabName)
{
return ClearedPrefabs.Where(p => p.Name == prefabName).ToList();
}
// Retrieve prefabs by position
public static List<PrefabInfo> GetPrefabsByPosition(Vector3 position)
{
return ClearedPrefabs.Where(p => p.Position == position).ToList();
}
// Retrieve prefabs by difficulty
public static List<PrefabInfo> GetPrefabsByDifficulty(int difficulty)
{
return ClearedPrefabs.Where(p => p.Difficulty == difficulty).ToList();
}
// Retrieve prefabs by biome
public static List<PrefabInfo> GetPrefabsByBiome(string biome)
{
return ClearedPrefabs.Where(p => p.Biome == biome).ToList();
}
public static int GetClearedPrefabCount(string biome, int difficulty)
{
return ClearedPrefabs.Count(p => p.Biome == biome && p.Difficulty == difficulty);
}
public static int GetTotalClearedPrefabCount(string biome)
{
return ClearedPrefabs.Count(p => p.Biome == biome);
}
}