Add simple save system

This commit is contained in:
Jet the Hawk 2023-03-01 17:40:26 -05:00
parent 4b9a9bb78f
commit 7e3713f02f
27 changed files with 768 additions and 2 deletions

View file

@ -65,6 +65,15 @@ namespace Core.DataManagement
instanceIdGenerator.DeclareUnused(data.InstanceId.Id);
eventDispatcher.Modify.Invoke(previous, data);
}
public void Clear()
{
while (dataElements.Count > 0)
{
TDataElement element = dataElements[0];
Remove(element);
}
}
public void Serialize(IRevisionedSerializer<TRevision> serializer, TRevision revision)
{

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0f6865ce63224944a2c0b67ea06ebb18
timeCreated: 1677710401

View file

@ -33,6 +33,8 @@ Transform:
- {fileID: 8239129150798170454}
- {fileID: 928485812074972480}
- {fileID: 5099507500598303435}
- {fileID: 2138699188567816693}
- {fileID: 3676830287291953270}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
@ -49,6 +51,68 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
worldHolder: {fileID: 11400000, guid: 6ddfb5183f8225440a5d156e7fb16747, type: 2}
--- !u!1001 &698093834370466672
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 1191197961681005175}
m_Modifications:
- target: {fileID: 1449612830529223301, guid: ade9a53a41b91964a8c35b2c35a439bf, type: 3}
propertyPath: m_RootOrder
value: 4
objectReference: {fileID: 0}
- target: {fileID: 1449612830529223301, guid: ade9a53a41b91964a8c35b2c35a439bf, type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1449612830529223301, guid: ade9a53a41b91964a8c35b2c35a439bf, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1449612830529223301, guid: ade9a53a41b91964a8c35b2c35a439bf, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1449612830529223301, guid: ade9a53a41b91964a8c35b2c35a439bf, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 1449612830529223301, guid: ade9a53a41b91964a8c35b2c35a439bf, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1449612830529223301, guid: ade9a53a41b91964a8c35b2c35a439bf, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1449612830529223301, guid: ade9a53a41b91964a8c35b2c35a439bf, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1449612830529223301, guid: ade9a53a41b91964a8c35b2c35a439bf, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1449612830529223301, guid: ade9a53a41b91964a8c35b2c35a439bf, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1449612830529223301, guid: ade9a53a41b91964a8c35b2c35a439bf, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6319085734229809466, guid: ade9a53a41b91964a8c35b2c35a439bf, type: 3}
propertyPath: m_Name
value: Computer Spawner
objectReference: {fileID: 0}
m_RemovedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: ade9a53a41b91964a8c35b2c35a439bf, type: 3}
--- !u!4 &2138699188567816693 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 1449612830529223301, guid: ade9a53a41b91964a8c35b2c35a439bf, type: 3}
m_PrefabInstance: {fileID: 698093834370466672}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &1103340872538665945
PrefabInstance:
m_ObjectHideFlags: 0
@ -297,3 +361,65 @@ Transform:
m_CorrespondingSourceObject: {fileID: 1216024012788109901, guid: 69af82d1d370d004cac6b6402915535d, type: 3}
m_PrefabInstance: {fileID: 6207429681634773126}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &8934673873687550751
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 1191197961681005175}
m_Modifications:
- target: {fileID: 5258215514604514153, guid: b54b6b94e467cc54297711bc903849b4, type: 3}
propertyPath: m_RootOrder
value: 5
objectReference: {fileID: 0}
- target: {fileID: 5258215514604514153, guid: b54b6b94e467cc54297711bc903849b4, type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5258215514604514153, guid: b54b6b94e467cc54297711bc903849b4, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5258215514604514153, guid: b54b6b94e467cc54297711bc903849b4, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5258215514604514153, guid: b54b6b94e467cc54297711bc903849b4, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 5258215514604514153, guid: b54b6b94e467cc54297711bc903849b4, type: 3}
propertyPath: m_LocalRotation.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: 5258215514604514153, guid: b54b6b94e467cc54297711bc903849b4, type: 3}
propertyPath: m_LocalRotation.y
value: -0
objectReference: {fileID: 0}
- target: {fileID: 5258215514604514153, guid: b54b6b94e467cc54297711bc903849b4, type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: 5258215514604514153, guid: b54b6b94e467cc54297711bc903849b4, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5258215514604514153, guid: b54b6b94e467cc54297711bc903849b4, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5258215514604514153, guid: b54b6b94e467cc54297711bc903849b4, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7117650841897268033, guid: b54b6b94e467cc54297711bc903849b4, type: 3}
propertyPath: m_Name
value: Game Manager
objectReference: {fileID: 0}
m_RemovedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: b54b6b94e467cc54297711bc903849b4, type: 3}
--- !u!4 &3676830287291953270 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 5258215514604514153, guid: b54b6b94e467cc54297711bc903849b4, type: 3}
m_PrefabInstance: {fileID: 8934673873687550751}
m_PrefabAsset: {fileID: 0}

View file

@ -1,12 +1,12 @@
#nullable enable
using System;
using Codice.CM.WorkspaceServer.Tree;
namespace Core.Serialization
{
public interface IDataWriter
public interface IDataWriter : IDisposable
{
void Dispose();
void Write(sbyte value);
void Write(byte value);
void Write(short value);

View file

@ -20,5 +20,12 @@ namespace Core.WorldData
{
Computers.Serialize(serializer, WorldRevision.AddedComputers);
}
public void Wipe()
{
// You must wipe the world in reverse order of how you would create or serialize it.
// This ensures proper handling of deleting objects that depend on other objects.
this.Computers.Clear();
}
}
}

View file

@ -41,5 +41,10 @@ namespace Core
var serializer = new WorldSerializer(reader);
world.Serialize(serializer);
}
public void WipeWorld()
{
this.world.Wipe();
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 92c910795af14a1f8a4fbee2e6d81a17
timeCreated: 1677704933

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e668f65f34b24362930202cdd6b15b6d
timeCreated: 1677706409

View file

@ -0,0 +1,48 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &7117650841897268033
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5258215514604514153}
- component: {fileID: 1744055403070591772}
m_Layer: 0
m_Name: Game Manager
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &5258215514604514153
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7117650841897268033}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1744055403070591772
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7117650841897268033}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ce5c48de3d5f4c77979c5f2a9372fd9a, type: 3}
m_Name:
m_EditorClassIdentifier:
holder: {fileID: 11400000, guid: de6543312575e7f4294170ad6b5ed997, type: 2}
world: {fileID: 11400000, guid: 6ddfb5183f8225440a5d156e7fb16747, type: 2}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: b54b6b94e467cc54297711bc903849b4
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,14 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: df46790bd5044983a83330422c3697d5, type: 3}
m_Name: GameManager
m_EditorClassIdentifier:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: de6543312575e7f4294170ad6b5ed997
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,214 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Core;
using Core.Serialization.Binary;
using Newtonsoft.Json;
using UnityEngine;
using Application = UnityEngine.Device.Application;
namespace GameplaySystems.GameManagement
{
public class GameManager
{
private readonly string worldFileName = "world.bin";
private readonly string playerHomeDirectoryName = "home";
private readonly string npcHomesDirectoryName = "npcs";
private readonly string paramsFileName = "params.json";
private WorldManagerHolder world;
private string? currentGamePath;
private SaveFileParameters? currentGame;
/// <summary>
/// Gets a path where all game data must be stored.
/// </summary>
public string GameDataDirectory => Application.persistentDataPath;
/// <summary>
/// Gets a path where all save files are located.
/// </summary>
public string AllSavesDirectory => Path.Combine(GameDataDirectory, "saves");
public string? CurrentGamePath => currentGamePath;
public GameManager(WorldManagerHolder world)
{
this.world = world;
}
/// <summary>
/// Enumerates all save files, returning their parameter data as a collection of
/// <see cref="SaveFileParameters"/> objects.
/// </summary>
/// <returns>An enumerable collection of save files.</returns>
public IEnumerable<SaveFileParameters> EnumerateAllSaveFiles()
{
if (!Directory.Exists(AllSavesDirectory))
{
Directory.CreateDirectory(AllSavesDirectory);
yield break;
}
foreach (string saveDirectory in Directory.GetDirectories(AllSavesDirectory))
{
string paramsPath = Path.Combine(saveDirectory, paramsFileName);
if (!File.Exists(paramsPath))
continue;
string saveId = Path.GetFileName(saveDirectory);
SaveFileParameters? parameters = null;
try
{
string json = File.ReadAllText(paramsPath);
parameters = Newtonsoft.Json.JsonConvert.DeserializeObject<SaveFileParameters>(json);
}
catch (Exception ex)
{
Debug.LogWarning($"Exception occurred while parsing {paramsPath}: {ex}");
continue;
}
if (parameters == null)
continue;
parameters.saveId = saveId;
yield return parameters;
}
}
public void StartGame(SaveFileParameters parameters)
{
ThrowIfGameActive();
if (string.IsNullOrWhiteSpace(parameters.saveId))
throw new InvalidOperationException("Cannot load the given save file parameters since the save ID is blank.");
string savePath = Path.Combine(AllSavesDirectory, parameters.saveId);
string? directoryName = Path.GetDirectoryName(savePath);
if (directoryName != AllSavesDirectory)
throw new InvalidOperationException($"Loading save files outside of the path \"{AllSavesDirectory}\" is prohibited for security reasons.");
if (!Directory.Exists(savePath))
throw new DirectoryNotFoundException(savePath);
this.currentGame = parameters;
this.currentGamePath = savePath;
SaveGameParameters();
world.Value.WipeWorld();
string worldFile = Path.Combine(currentGamePath, worldFileName);
if (!File.Exists(worldFile))
return;
using Stream stream = File.OpenRead(worldFile);
using var reader = new BinaryReader(stream, Encoding.UTF8);
using var dataReader = new BinaryDataReader(reader);
world.Value.LoadWorld(dataReader);
}
public void EndCurrentGame()
{
SaveCurrentGame();
world.Value.WipeWorld();
currentGame = null;
currentGamePath = null;
}
public void StartNewGame(string saveId, string playerName, string playerHostName)
{
ThrowIfGameActive();
string savePath = Path.Combine(AllSavesDirectory, saveId);
string? directoryName = Path.GetDirectoryName(savePath);
if (directoryName != AllSavesDirectory)
throw new InvalidOperationException($"Loading save files outside of the path \"{AllSavesDirectory}\" is prohibited for security reasons.");
if (Directory.Exists(savePath))
throw new InvalidOperationException("A save file with the same ID already exists.");
Directory.CreateDirectory(savePath);
this.currentGamePath = savePath;
this.currentGame = new SaveFileParameters
{
saveId = saveId,
playerName = playerName,
playerComputerName = playerHostName,
creationDate = DateTime.UtcNow,
lastPlayedDate = DateTime.UtcNow,
lastPlayedMissionName = string.Empty
};
world.Value.WipeWorld();
SaveCurrentGame();
}
public void SaveCurrentGame()
{
ThrowIfGameNotActive();
SaveGameParameters();
string worldFile = Path.Combine(currentGamePath!, worldFileName);
using FileStream stream = File.OpenWrite(worldFile);
using var writer = new BinaryWriter(stream, Encoding.UTF8);
using var dataWriter = new BinaryDataWriter(writer);
world.Value.SaveWorld(dataWriter);
}
private void ThrowIfGameActive()
{
if (currentGame != null)
throw new InvalidOperationException("A game is already loaded.");
}
private void ThrowIfGameNotActive()
{
if (currentGame == null)
throw new InvalidOperationException("A game is not loaded.");
}
private void SaveGameParameters()
{
ThrowIfGameNotActive();
currentGame!.lastPlayedDate = DateTime.UtcNow;
string paramsFile = Path.Combine(currentGamePath!, paramsFileName);
string json = JsonConvert.SerializeObject(currentGame!);
File.WriteAllText(paramsFile, json);
}
}
/// <summary>
/// Represents the contents of the "params.json" file found in a Socially Distant save file.
/// </summary>
public class SaveFileParameters
{
public string playerName;
public string playerComputerName;
public DateTime creationDate;
public DateTime lastPlayedDate;
public string lastPlayedMissionName;
[NonSerialized]
public string saveId;
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 156f56d30bcd44679bfb3f7aae133ec3
timeCreated: 1677706426

View file

@ -0,0 +1,22 @@
using Core;
using UnityEngine;
using Utility;
namespace GameplaySystems.GameManagement
{
public class GameManagerBootstrap : MonoBehaviour
{
[Header("Holder")]
[SerializeField]
private GameManagerHolder holder = null!;
[SerializeField]
private WorldManagerHolder world = null!;
private void Awake()
{
this.AssertAllFieldsAreSerialized(typeof(GameManagerBootstrap));
holder.Value = new GameManager(world);
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ce5c48de3d5f4c77979c5f2a9372fd9a
timeCreated: 1677706540

View file

@ -0,0 +1,11 @@
using Architecture;
using UnityEngine;
namespace GameplaySystems.GameManagement
{
[CreateAssetMenu(menuName = "ScriptableObject/Holders/Game Manager")]
public class GameManagerHolder : Holder<GameManager>
{
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: df46790bd5044983a83330422c3697d5
timeCreated: 1677706540

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6d7b71171a8c4abdbffbf7716368e696
timeCreated: 1677704949

View file

@ -0,0 +1,49 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &6319085734229809466
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1449612830529223301}
- component: {fileID: 8091683330637069133}
m_Layer: 0
m_Name: Computer Spawner
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1449612830529223301
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6319085734229809466}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &8091683330637069133
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6319085734229809466}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: df5250b084a64ae4a9720798f8ff87e5, type: 3}
m_Name:
m_EditorClassIdentifier:
world: {fileID: 11400000, guid: 6ddfb5183f8225440a5d156e7fb16747, type: 2}
deviceCoordinator: {fileID: 11400000, guid: aaa2ed62d698c314f96dbf5e0b134aad, type: 2}
computerPrefab: {fileID: 2497491040459871258, guid: 3d58f2ba5a3dd0348b1128913cc1df40, type: 3}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ade9a53a41b91964a8c35b2c35a439bf
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,48 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &6389477645046800240
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8746881451945948163}
- component: {fileID: 2497491040459871258}
m_Layer: 0
m_Name: NPC Computer
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &8746881451945948163
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6389477645046800240}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &2497491040459871258
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6389477645046800240}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 31cbbae557284cbabb3e250ed41869ba, type: 3}
m_Name:
m_EditorClassIdentifier:
world: {fileID: 11400000, guid: 6ddfb5183f8225440a5d156e7fb16747, type: 2}
deviceCoordinator: {fileID: 11400000, guid: aaa2ed62d698c314f96dbf5e0b134aad, type: 2}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3d58f2ba5a3dd0348b1128913cc1df40
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,66 @@
#nullable enable
using System;
using Architecture;
using Core;
using Core.WorldData.Data;
using OS.Devices;
using OS.FileSystems;
using UnityEngine;
using Utility;
namespace GameplaySystems.NonPlayerComputers
{
public class NonPlayerComputer :
MonoBehaviour,
IComputer
{
private WorldComputerData worldData;
private ISystemProcess initProcess = null!;
[Header("Dependencies")]
[SerializeField]
private WorldManagerHolder world = null!;
[SerializeField]
private DeviceCoordinator deviceCoordinator = null!;
/// <inheritdoc />
public string Name => worldData.HostName;
private void Awake()
{
this.AssertAllFieldsAreSerialized(typeof(NonPlayerComputer));
this.initProcess = this.deviceCoordinator.SetUpComputer(this);
}
/// <inheritdoc />
public bool FindUserById(int id, out IUser? user)
{
throw new NotImplementedException();
}
/// <inheritdoc />
public bool FindUserByName(string username, out IUser? user)
{
throw new NotImplementedException();
}
/// <inheritdoc />
public ISystemProcess? ExecuteProgram(ISystemProcess parentProcess, ITextConsole console, string programName, string[] arguments)
{
throw new NotImplementedException();
}
/// <inheritdoc />
public VirtualFileSystem GetFileSystem(IUser user)
{
throw new NotImplementedException();
}
public void UpdateWorldData(WorldComputerData data)
{
worldData = data;
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 31cbbae557284cbabb3e250ed41869ba
timeCreated: 1677705532

View file

@ -0,0 +1,91 @@
#nullable enable
using System;
using System.Collections.Generic;
using Architecture;
using Core;
using Core.DataManagement;
using Core.WorldData.Data;
using UnityEngine;
using Utility;
namespace GameplaySystems.NonPlayerComputers
{
public class NonPlayerComputerEventListener : MonoBehaviour
{
private readonly Dictionary<ObjectId, NonPlayerComputer> instances = new Dictionary<ObjectId, NonPlayerComputer>();
[Header("Dependencies")]
[SerializeField]
private WorldManagerHolder world = null!;
[SerializeField]
private DeviceCoordinator deviceCoordinator = null!;
[Header("Prefabs")]
[SerializeField]
private NonPlayerComputer computerPrefab = null!;
private void Awake()
{
this.AssertAllFieldsAreSerialized(typeof(NonPlayerComputerEventListener));
}
private void Start()
{
InstallEvents();
}
private void OnDestroy()
{
UninstallEvents();
}
private void InstallEvents()
{
this.world.Value.Callbacks.AddCreateCallback<WorldComputerData>(OnCreateComputer);
this.world.Value.Callbacks.AddModifyCallback<WorldComputerData>(OnModifyComputer);
this.world.Value.Callbacks.AddDeleteCallback<WorldComputerData>(OnDeleteComputer);
}
private void UninstallEvents()
{
this.world.Value.Callbacks.RemoveCreateCallback<WorldComputerData>(OnCreateComputer);
this.world.Value.Callbacks.RemoveModifyCallback<WorldComputerData>(OnModifyComputer);
this.world.Value.Callbacks.RemoveDeleteCallback<WorldComputerData>(OnDeleteComputer);
}
private void OnDeleteComputer(WorldComputerData subject)
{
if (!instances.TryGetValue(subject.InstanceId, out NonPlayerComputer computer))
return;
instances.Remove(subject.InstanceId);
Destroy(computer.gameObject);
}
private void OnModifyComputer(WorldComputerData subjectprevious, WorldComputerData subjectnew)
{
NonPlayerComputer computer = instances[subjectnew.InstanceId];
computer.UpdateWorldData(subjectnew);
}
private void OnCreateComputer(WorldComputerData subject)
{
var setActive = false;
if (!instances.TryGetValue(subject.InstanceId, out NonPlayerComputer computer))
{
this.computerPrefab.gameObject.SetActive(false);
computer = Instantiate(computerPrefab);
instances.Add(subject.InstanceId, computer);
setActive = true;
}
computer.UpdateWorldData(subject);
if (setActive)
computer.gameObject.SetActive(true);
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: df5250b084a64ae4a9720798f8ff87e5
timeCreated: 1677704972