Inventory reimplementation (from MonsterShop). Top panel is temporarily broken
This commit is contained in:
parent
a9fb1864a5
commit
29899842e4
|
|
@ -19,7 +19,7 @@ public class ResourceDrawer : PropertyDrawer
|
||||||
|
|
||||||
private static void Initialize()
|
private static void Initialize()
|
||||||
{
|
{
|
||||||
resources = ResourceStorage.RegisteredResources;
|
resources = ResourceRegistry.Instance.Items;
|
||||||
// if (resourceTypes == null)
|
// if (resourceTypes == null)
|
||||||
// {
|
// {
|
||||||
// resourceTypes = AppDomain
|
// resourceTypes = AppDomain
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ GameObject:
|
||||||
- component: {fileID: 819912288095587636}
|
- component: {fileID: 819912288095587636}
|
||||||
- component: {fileID: 1421388845701231023}
|
- component: {fileID: 1421388845701231023}
|
||||||
- component: {fileID: 4527755210678078285}
|
- component: {fileID: 4527755210678078285}
|
||||||
|
- component: {fileID: 7057847397855985585}
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: MetalMine
|
m_Name: MetalMine
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
|
|
@ -112,14 +113,14 @@ MonoBehaviour:
|
||||||
m_Script: {fileID: 11500000, guid: c06e7972b6bac34468cda352d1c07c7a, type: 3}
|
m_Script: {fileID: 11500000, guid: c06e7972b6bac34468cda352d1c07c7a, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::ResourceSource
|
m_EditorClassIdentifier: Assembly-CSharp::ResourceSource
|
||||||
<Label>k__BackingField: Placeholder
|
|
||||||
Resource:
|
Resource:
|
||||||
rid: -2
|
rid: 7834219818361815538
|
||||||
references:
|
references:
|
||||||
version: 2
|
version: 2
|
||||||
RefIds:
|
RefIds:
|
||||||
- rid: -2
|
- rid: 7834219818361815538
|
||||||
type: {class: , ns: , asm: }
|
type: {class: Metal, ns: , asm: Assembly-CSharp}
|
||||||
|
data:
|
||||||
--- !u!114 &5492169477648969604
|
--- !u!114 &5492169477648969604
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
|
@ -217,3 +218,17 @@ MonoBehaviour:
|
||||||
m_EditorClassIdentifier: Assembly-CSharp::ResourceGenerator
|
m_EditorClassIdentifier: Assembly-CSharp::ResourceGenerator
|
||||||
Interval: 2000
|
Interval: 2000
|
||||||
Power: 3
|
Power: 3
|
||||||
|
<TargetInventory>k__BackingField: {fileID: 7057847397855985585}
|
||||||
|
--- !u!114 &7057847397855985585
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 558136326881420228}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: b6e85c222b8627a4287c8dc63bf5cfe6, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::InventoryHolder
|
||||||
|
name:
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,7 @@ PrefabInstance:
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4019719181363577730, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
- target: {fileID: 4019719181363577730, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
||||||
propertyPath: Resource
|
propertyPath: Resource
|
||||||
value: 7834219818361815171
|
value: 7834219818361815541
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4019719181363577730, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
- target: {fileID: 4019719181363577730, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
||||||
propertyPath: resource
|
propertyPath: resource
|
||||||
|
|
@ -183,6 +183,10 @@ PrefabInstance:
|
||||||
propertyPath: 'managedReferences[7834219818361815171]'
|
propertyPath: 'managedReferences[7834219818361815171]'
|
||||||
value: Assembly-CSharp Energy
|
value: Assembly-CSharp Energy
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4019719181363577730, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
||||||
|
propertyPath: 'managedReferences[7834219818361815541]'
|
||||||
|
value: Assembly-CSharp Energy
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4527755210678078285, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
- target: {fileID: 4527755210678078285, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
||||||
propertyPath: Power
|
propertyPath: Power
|
||||||
value: 7
|
value: 7
|
||||||
|
|
@ -239,6 +243,10 @@ PrefabInstance:
|
||||||
propertyPath: m_PanelSettings
|
propertyPath: m_PanelSettings
|
||||||
value:
|
value:
|
||||||
objectReference: {fileID: 11400000, guid: 464fb977c513b5d488444b538340160f, type: 2}
|
objectReference: {fileID: 11400000, guid: 464fb977c513b5d488444b538340160f, type: 2}
|
||||||
|
- target: {fileID: 7057847397855985585, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
||||||
|
propertyPath: name
|
||||||
|
value: Power Plant
|
||||||
|
objectReference: {fileID: 0}
|
||||||
m_RemovedComponents: []
|
m_RemovedComponents: []
|
||||||
m_RemovedGameObjects: []
|
m_RemovedGameObjects: []
|
||||||
m_AddedGameObjects: []
|
m_AddedGameObjects: []
|
||||||
|
|
@ -318,6 +326,8 @@ MonoBehaviour:
|
||||||
m_Script: {fileID: 11500000, guid: 0015370abb0b1af488c2de94bf042002, type: 3}
|
m_Script: {fileID: 11500000, guid: 0015370abb0b1af488c2de94bf042002, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier: '::'
|
m_EditorClassIdentifier: '::'
|
||||||
|
name:
|
||||||
|
Capacity: -1
|
||||||
--- !u!114 &403904198
|
--- !u!114 &403904198
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
|
@ -529,7 +539,7 @@ PrefabInstance:
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4019719181363577730, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
- target: {fileID: 4019719181363577730, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
||||||
propertyPath: Resource
|
propertyPath: Resource
|
||||||
value: 7834219818361815172
|
value: 7834219818361815539
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4019719181363577730, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
- target: {fileID: 4019719181363577730, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
||||||
propertyPath: resource
|
propertyPath: resource
|
||||||
|
|
@ -555,6 +565,10 @@ PrefabInstance:
|
||||||
propertyPath: 'managedReferences[7834219818361815172]'
|
propertyPath: 'managedReferences[7834219818361815172]'
|
||||||
value: Assembly-CSharp Electronics
|
value: Assembly-CSharp Electronics
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4019719181363577730, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
||||||
|
propertyPath: 'managedReferences[7834219818361815539]'
|
||||||
|
value: Assembly-CSharp Electronics
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4527755210678078285, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
- target: {fileID: 4527755210678078285, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
||||||
propertyPath: Interval
|
propertyPath: Interval
|
||||||
value: 0
|
value: 0
|
||||||
|
|
@ -599,6 +613,10 @@ PrefabInstance:
|
||||||
propertyPath: m_LocalEulerAnglesHint.z
|
propertyPath: m_LocalEulerAnglesHint.z
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 7057847397855985585, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
||||||
|
propertyPath: name
|
||||||
|
value: Electronics Factory
|
||||||
|
objectReference: {fileID: 0}
|
||||||
m_RemovedComponents:
|
m_RemovedComponents:
|
||||||
- {fileID: 5975817771934886021, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
- {fileID: 5975817771934886021, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
||||||
m_RemovedGameObjects: []
|
m_RemovedGameObjects: []
|
||||||
|
|
@ -799,7 +817,7 @@ PrefabInstance:
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4019719181363577730, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
- target: {fileID: 4019719181363577730, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
||||||
propertyPath: Resource
|
propertyPath: Resource
|
||||||
value: 7834219818361815173
|
value: 7834219818361815540
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4019719181363577730, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
- target: {fileID: 4019719181363577730, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
||||||
propertyPath: resource
|
propertyPath: resource
|
||||||
|
|
@ -825,6 +843,10 @@ PrefabInstance:
|
||||||
propertyPath: 'managedReferences[7834219818361815173]'
|
propertyPath: 'managedReferences[7834219818361815173]'
|
||||||
value: Assembly-CSharp Metal
|
value: Assembly-CSharp Metal
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 4019719181363577730, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
||||||
|
propertyPath: 'managedReferences[7834219818361815540]'
|
||||||
|
value: Assembly-CSharp Metal
|
||||||
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4851214142334336292, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
- target: {fileID: 4851214142334336292, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
||||||
propertyPath: m_LocalPosition.x
|
propertyPath: m_LocalPosition.x
|
||||||
value: 0
|
value: 0
|
||||||
|
|
@ -869,6 +891,14 @@ PrefabInstance:
|
||||||
propertyPath: m_LocalEulerAnglesHint.z
|
propertyPath: m_LocalEulerAnglesHint.z
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 7057847397855985585, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
||||||
|
propertyPath: name
|
||||||
|
value: Metal Mine
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 7057847397855985585, guid: cd4f08f126f359d48ba53df6ace98e6c, type: 3}
|
||||||
|
propertyPath: Capacity
|
||||||
|
value: 50
|
||||||
|
objectReference: {fileID: 0}
|
||||||
m_RemovedComponents: []
|
m_RemovedComponents: []
|
||||||
m_RemovedGameObjects: []
|
m_RemovedGameObjects: []
|
||||||
m_AddedGameObjects: []
|
m_AddedGameObjects: []
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5e26b3cd5dd6654499bc1a6836fa4142
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3f1c7553ca7b3bb4399eab9e93b9a6ff
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
public class GameData
|
||||||
|
{
|
||||||
|
public long lastUpdated;
|
||||||
|
|
||||||
|
public PlayerData player = new PlayerData();
|
||||||
|
|
||||||
|
public StorageData storage = new StorageData();
|
||||||
|
|
||||||
|
public List<ShelfData> shelves = new List<ShelfData>();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 89cbdf7a2dcd8ab40a929072c7493273
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
public class InventoryData
|
||||||
|
{
|
||||||
|
public float capacity = 0;
|
||||||
|
|
||||||
|
public SerializableDictionary<string, float> items =
|
||||||
|
new SerializableDictionary<string, float>();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3bcd40c816f3fb24a8aa90a6438d53a0
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
public class PlayerData
|
||||||
|
{
|
||||||
|
public InventoryData inventory = new InventoryData();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ff587676af26ad344af1761388bb9016
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
public class ShelfData
|
||||||
|
{
|
||||||
|
public string type = "shelf";
|
||||||
|
public Vector2 location = Vector2.zero;
|
||||||
|
public float angle = 0;
|
||||||
|
public InventoryData inventory = new InventoryData();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e220bc2634b66924c99448f4bd3a824c
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
public class StorageData
|
||||||
|
{
|
||||||
|
public InventoryData inventory = new InventoryData();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9691713479005104ea634e90c3338df3
|
||||||
|
|
@ -0,0 +1,169 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
|
public class DataPersistenceManager : MonoBehaviour
|
||||||
|
{
|
||||||
|
// [Header("Debugging")]
|
||||||
|
// [SerializeField] private bool initializeDataIfNull = false;
|
||||||
|
|
||||||
|
[Header("File Storage Config")]
|
||||||
|
[SerializeField]
|
||||||
|
private string fileName;
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
private bool useEncryption;
|
||||||
|
|
||||||
|
[Header("Auto Saving Configuration")]
|
||||||
|
[SerializeField]
|
||||||
|
private float autoSaveTimeSeconds = 60f;
|
||||||
|
|
||||||
|
private GameData gameData = new GameData();
|
||||||
|
private List<IDataPersistence<GameData>> dataPersistenceObjects;
|
||||||
|
private FileDataHandler dataHandler;
|
||||||
|
|
||||||
|
private Coroutine autoSaveCoroutine;
|
||||||
|
|
||||||
|
public static DataPersistenceManager instance { get; private set; }
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
if (instance != null)
|
||||||
|
{
|
||||||
|
Debug.Log(
|
||||||
|
"Found more than one Data Persistence Manager in the scene. Destroying the newest one."
|
||||||
|
);
|
||||||
|
Destroy(this.gameObject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
instance = this;
|
||||||
|
DontDestroyOnLoad(this.gameObject);
|
||||||
|
|
||||||
|
this.dataHandler = new FileDataHandler(
|
||||||
|
Application.persistentDataPath,
|
||||||
|
fileName,
|
||||||
|
useEncryption
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
SceneManager.sceneLoaded += OnSceneLoaded;
|
||||||
|
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDisable()
|
||||||
|
{
|
||||||
|
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
||||||
|
{
|
||||||
|
// Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Initialize()
|
||||||
|
{
|
||||||
|
LoadGame();
|
||||||
|
|
||||||
|
// start up the auto saving coroutine
|
||||||
|
if (autoSaveCoroutine != null)
|
||||||
|
{
|
||||||
|
StopCoroutine(autoSaveCoroutine);
|
||||||
|
}
|
||||||
|
autoSaveCoroutine = StartCoroutine(AutoSave());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void NewGame()
|
||||||
|
{
|
||||||
|
Debug.Log("new game");
|
||||||
|
this.gameData = new GameData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadGame()
|
||||||
|
{
|
||||||
|
Debug.Log("Loading game");
|
||||||
|
|
||||||
|
this.dataPersistenceObjects = FindAllDataPersistenceObjects();
|
||||||
|
|
||||||
|
// load any saved data from a file using the data handler
|
||||||
|
this.gameData = dataHandler.Load();
|
||||||
|
|
||||||
|
// start a new game if the data is null and we're configured to initialize data for debugging purposes
|
||||||
|
if (this.gameData == null)
|
||||||
|
{
|
||||||
|
NewGame();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no data can be loaded, don't continue
|
||||||
|
// if (this.gameData == null)
|
||||||
|
// {
|
||||||
|
// Debug.Log("No data was found. A New Game needs to be started before data can be loaded.");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// push the loaded data to all other scripts that need it
|
||||||
|
foreach (IDataPersistence<GameData> dataPersistenceObj in dataPersistenceObjects)
|
||||||
|
{
|
||||||
|
dataPersistenceObj.LoadData(gameData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveGame()
|
||||||
|
{
|
||||||
|
Debug.Log("Saving game");
|
||||||
|
|
||||||
|
this.dataPersistenceObjects = FindAllDataPersistenceObjects();
|
||||||
|
|
||||||
|
// if we don't have any data to save, log a warning here
|
||||||
|
if (this.gameData == null)
|
||||||
|
{
|
||||||
|
Debug.LogWarning(
|
||||||
|
"No data was found. A New Game needs to be started before data can be saved."
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pass the data to other scripts so they can update it
|
||||||
|
foreach (IDataPersistence<GameData> dataPersistenceObj in dataPersistenceObjects)
|
||||||
|
{
|
||||||
|
dataPersistenceObj.SaveData(gameData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// timestamp the data so we know when it was last saved
|
||||||
|
gameData.lastUpdated = System.DateTime.Now.ToBinary();
|
||||||
|
|
||||||
|
// save that data to a file using the data handler
|
||||||
|
dataHandler.Save(gameData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnApplicationQuit()
|
||||||
|
{
|
||||||
|
SaveGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<IDataPersistence<GameData>> FindAllDataPersistenceObjects()
|
||||||
|
{
|
||||||
|
// FindObjectsofType takes in an optional boolean to include inactive gameobjects
|
||||||
|
IEnumerable<IDataPersistence<GameData>> dataPersistenceObjects =
|
||||||
|
FindObjectsByType<MonoBehaviour>(FindObjectsSortMode.None)
|
||||||
|
.OfType<IDataPersistence<GameData>>();
|
||||||
|
|
||||||
|
var list = new List<IDataPersistence<GameData>>(dataPersistenceObjects);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator AutoSave()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
yield return new WaitForSeconds(autoSaveTimeSeconds);
|
||||||
|
SaveGame();
|
||||||
|
Debug.Log("Auto Saved Game");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a43c513eda07bf94db46b159ebbc8b51
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,185 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
public class FileDataHandler
|
||||||
|
{
|
||||||
|
private string dataDirPath = "";
|
||||||
|
private string dataFileName = "";
|
||||||
|
private bool useEncryption = false;
|
||||||
|
private readonly string encryptionCodeWord = "word";
|
||||||
|
private readonly string backupExtension = ".bak";
|
||||||
|
|
||||||
|
public FileDataHandler(string dataDirPath, string dataFileName, bool useEncryption)
|
||||||
|
{
|
||||||
|
this.dataDirPath = dataDirPath;
|
||||||
|
this.dataFileName = dataFileName;
|
||||||
|
this.useEncryption = useEncryption;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameData Load(bool allowRestoreFromBackup = true)
|
||||||
|
{
|
||||||
|
// use Path.Combine to account for different OS's having different path separators
|
||||||
|
string fullPath = Path.Combine(dataDirPath, dataFileName);
|
||||||
|
GameData loadedData = null;
|
||||||
|
if (File.Exists(fullPath))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// load the serialized data from the file
|
||||||
|
string dataToLoad = "";
|
||||||
|
using (FileStream stream = new FileStream(fullPath, FileMode.Open))
|
||||||
|
{
|
||||||
|
using (StreamReader reader = new StreamReader(stream))
|
||||||
|
{
|
||||||
|
dataToLoad = reader.ReadToEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// optionally decrypt the data
|
||||||
|
if (useEncryption)
|
||||||
|
{
|
||||||
|
dataToLoad = EncryptDecrypt(dataToLoad);
|
||||||
|
}
|
||||||
|
|
||||||
|
// deserialize the data from Json back into the C# object
|
||||||
|
loadedData = JsonUtility.FromJson<GameData>(dataToLoad);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// since we're calling Load(..) recursively, we need to account for the case where
|
||||||
|
// the rollback succeeds, but data is still failing to load for some other reason,
|
||||||
|
// which without this check may cause an infinite recursion loop.
|
||||||
|
if (allowRestoreFromBackup)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Failed to load data file. Attempting to roll back.\n" + e);
|
||||||
|
bool rollbackSuccess = AttemptRollback(fullPath);
|
||||||
|
if (rollbackSuccess)
|
||||||
|
{
|
||||||
|
// try to load again recursively
|
||||||
|
loadedData = Load(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if we hit this else block, one possibility is that the backup file is also corrupt
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError("Error occured when trying to load file at path: "
|
||||||
|
+ fullPath + " and backup did not work.\n" + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return loadedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save(GameData data)
|
||||||
|
{
|
||||||
|
// use Path.Combine to account for different OS's having different path separators
|
||||||
|
string fullPath = Path.Combine(dataDirPath, dataFileName);
|
||||||
|
Debug.Log("Saving to " + fullPath);
|
||||||
|
string backupFilePath = fullPath + backupExtension;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// create the directory the file will be written to if it doesn't already exist
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(fullPath));
|
||||||
|
|
||||||
|
// serialize the C# game data object into Json
|
||||||
|
string dataToStore = JsonUtility.ToJson(data, true);
|
||||||
|
|
||||||
|
// optionally encrypt the data
|
||||||
|
if (useEncryption)
|
||||||
|
{
|
||||||
|
dataToStore = EncryptDecrypt(dataToStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
// write the serialized data to the file
|
||||||
|
using (FileStream stream = new FileStream(fullPath, FileMode.Create))
|
||||||
|
{
|
||||||
|
using (StreamWriter writer = new StreamWriter(stream))
|
||||||
|
{
|
||||||
|
writer.Write(dataToStore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify the newly saved file can be loaded successfully
|
||||||
|
GameData verifiedGameData = Load();
|
||||||
|
// if the data can be verified, back it up
|
||||||
|
if (verifiedGameData != null)
|
||||||
|
{
|
||||||
|
File.Copy(fullPath, backupFilePath, true);
|
||||||
|
}
|
||||||
|
// otherwise, something went wrong and we should throw an exception
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("Save file could not be verified and backup could not be created.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError("Error occured when trying to save data to file: " + fullPath + "\n" + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Delete()
|
||||||
|
{
|
||||||
|
string fullPath = Path.Combine(dataDirPath, dataFileName);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// ensure the data file exists at this path before deleting the directory
|
||||||
|
if (File.Exists(fullPath))
|
||||||
|
{
|
||||||
|
// delete the profile folder and everything within it
|
||||||
|
Directory.Delete(Path.GetDirectoryName(fullPath), true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Tried to delete profile data, but data was not found at path: " + fullPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError("Failed to delete data at path: " + fullPath + "\n" + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the below is a simple implementation of XOR encryption
|
||||||
|
private string EncryptDecrypt(string data)
|
||||||
|
{
|
||||||
|
string modifiedData = "";
|
||||||
|
for (int i = 0; i < data.Length; i++)
|
||||||
|
{
|
||||||
|
modifiedData += (char) (data[i] ^ encryptionCodeWord[i % encryptionCodeWord.Length]);
|
||||||
|
}
|
||||||
|
return modifiedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool AttemptRollback(string fullPath)
|
||||||
|
{
|
||||||
|
bool success = false;
|
||||||
|
string backupFilePath = fullPath + backupExtension;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// if the file exists, attempt to roll back to it by overwriting the original file
|
||||||
|
if (File.Exists(backupFilePath))
|
||||||
|
{
|
||||||
|
File.Copy(backupFilePath, fullPath, true);
|
||||||
|
success = true;
|
||||||
|
Debug.LogWarning("Had to roll back to backup file at: " + backupFilePath);
|
||||||
|
}
|
||||||
|
// otherwise, we don't yet have a backup file - so there's nothing to roll back to
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("Tried to roll back, but no backup file exists to roll back to.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError("Error occured when trying to roll back to backup file at: "
|
||||||
|
+ backupFilePath + "\n" + e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c4d960248b76a174e8de8eb7d18afdb5
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public interface IDataPersistenceBase { }
|
||||||
|
|
||||||
|
public interface IDataPersistence<TData> : IDataPersistenceBase
|
||||||
|
{
|
||||||
|
void LoadData(TData data);
|
||||||
|
|
||||||
|
// The 'ref' keyword was removed from here as it is not needed.
|
||||||
|
// In C#, non-primitive types are automatically passed by reference.
|
||||||
|
void SaveData(TData data);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: dadb1cc8e7af5394ca73356b1c0f1289
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e335e31db871f2246b93b4540f64cb92
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Unity.Collections;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
public class SerializableDictionaryEntry<TKey, TValue>
|
||||||
|
{
|
||||||
|
public TKey key;
|
||||||
|
public TValue value;
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Serializable]
|
||||||
|
public class SerializableDictionary<TKey, TValue>
|
||||||
|
: Dictionary<TKey, TValue>,
|
||||||
|
ISerializationCallbackReceiver
|
||||||
|
{
|
||||||
|
[SerializeField]
|
||||||
|
private List<SerializableDictionaryEntry<TKey, TValue>> entries =
|
||||||
|
new List<SerializableDictionaryEntry<TKey, TValue>>();
|
||||||
|
|
||||||
|
public SerializableDictionary() { }
|
||||||
|
|
||||||
|
public SerializableDictionary(Dictionary<TKey, TValue> source)
|
||||||
|
{
|
||||||
|
foreach (var item in source)
|
||||||
|
Add(item.Key, item.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnBeforeSerialize()
|
||||||
|
{
|
||||||
|
entries.Clear();
|
||||||
|
foreach (KeyValuePair<TKey, TValue> pair in this)
|
||||||
|
{
|
||||||
|
entries.Add(
|
||||||
|
new SerializableDictionaryEntry<TKey, TValue>()
|
||||||
|
{
|
||||||
|
key = pair.Key,
|
||||||
|
value = pair.Value,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// load the dictionary from lists
|
||||||
|
public void OnAfterDeserialize()
|
||||||
|
{
|
||||||
|
this.Clear();
|
||||||
|
|
||||||
|
foreach (SerializableDictionaryEntry<TKey, TValue> entry in entries)
|
||||||
|
{
|
||||||
|
this.Add(entry.key, entry.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9dc07c3462db23d45a4aa37b7d15244c
|
||||||
|
|
@ -27,11 +27,13 @@ public class FactoryInfo : MonoBehaviour
|
||||||
private new Collider2D collider;
|
private new Collider2D collider;
|
||||||
private ResourceSource source;
|
private ResourceSource source;
|
||||||
private ResourceGenerator generator;
|
private ResourceGenerator generator;
|
||||||
|
private InventoryHolder inventory;
|
||||||
private UIDocument uiDocument;
|
private UIDocument uiDocument;
|
||||||
private VisualElement rootElement;
|
private VisualElement rootElement;
|
||||||
private VisualElement panelElement;
|
private VisualElement panelElement;
|
||||||
private Label titleLabel;
|
private Label titleLabel;
|
||||||
private ProgressBar progressBar;
|
private ProgressBar progressBar;
|
||||||
|
private ProgressBar storagLoadBar;
|
||||||
|
|
||||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||||
void Start()
|
void Start()
|
||||||
|
|
@ -39,6 +41,7 @@ public class FactoryInfo : MonoBehaviour
|
||||||
collider = GetComponent<Collider2D>();
|
collider = GetComponent<Collider2D>();
|
||||||
source = GetComponent<ResourceSource>();
|
source = GetComponent<ResourceSource>();
|
||||||
generator = GetComponent<ResourceGenerator>();
|
generator = GetComponent<ResourceGenerator>();
|
||||||
|
inventory = GetComponent<InventoryHolder>();
|
||||||
|
|
||||||
uiDocument = GetComponent<UIDocument>();
|
uiDocument = GetComponent<UIDocument>();
|
||||||
rootElement = uiDocument.rootVisualElement;
|
rootElement = uiDocument.rootVisualElement;
|
||||||
|
|
@ -46,6 +49,7 @@ public class FactoryInfo : MonoBehaviour
|
||||||
panelElement = rootElement.Q<VisualElement>("Panel");
|
panelElement = rootElement.Q<VisualElement>("Panel");
|
||||||
titleLabel = rootElement.Q<Label>("Title");
|
titleLabel = rootElement.Q<Label>("Title");
|
||||||
progressBar = rootElement.Q<ProgressBar>("Progress");
|
progressBar = rootElement.Q<ProgressBar>("Progress");
|
||||||
|
storagLoadBar = rootElement.Q<ProgressBar>("StorageLoad");
|
||||||
}
|
}
|
||||||
|
|
||||||
[ExecuteInEditMode]
|
[ExecuteInEditMode]
|
||||||
|
|
@ -61,7 +65,18 @@ public class FactoryInfo : MonoBehaviour
|
||||||
Debug.Log("No panel");
|
Debug.Log("No panel");
|
||||||
|
|
||||||
titleLabel.text = title;
|
titleLabel.text = title;
|
||||||
|
|
||||||
progressBar.title = source?.Resource.Name;
|
progressBar.title = source?.Resource.Name;
|
||||||
progressBar.value = generator.Progress * 100;
|
progressBar.value = generator.Progress * 100;
|
||||||
|
|
||||||
|
if (inventory != null)
|
||||||
|
{
|
||||||
|
storagLoadBar.style.display = DisplayStyle.Flex;
|
||||||
|
var inv = inventory.Inventory;
|
||||||
|
storagLoadBar.title = $"{inv.Load}/{inv.Capacity}";
|
||||||
|
storagLoadBar.value = inv.Load / inv.Capacity * 100;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
storagLoadBar.style.display = DisplayStyle.None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,188 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityEditor.Tilemaps;
|
||||||
|
|
||||||
|
public delegate string NameCallback();
|
||||||
|
|
||||||
|
public abstract class IInventory
|
||||||
|
{
|
||||||
|
private List<Action> changeCallbacks = new List<Action>();
|
||||||
|
|
||||||
|
public abstract string Name { get; }
|
||||||
|
|
||||||
|
public abstract IReadOnlyDictionary<string, float> Items { get; }
|
||||||
|
|
||||||
|
public abstract float Capacity { get; set; }
|
||||||
|
|
||||||
|
public float Load => Items.Sum(kvp => kvp.Value);
|
||||||
|
|
||||||
|
public float Free => Capacity < 0 ? int.MaxValue : Capacity - Load;
|
||||||
|
|
||||||
|
public abstract float GetAmount(string item);
|
||||||
|
|
||||||
|
protected abstract int DoClear();
|
||||||
|
protected abstract float DoAdd(string item, float amount, bool allowPartialAdd = false);
|
||||||
|
protected abstract float DoRemove(string item, float amount, bool allowPartialRemoval = false);
|
||||||
|
|
||||||
|
public float Clear()
|
||||||
|
{
|
||||||
|
var cleared = DoClear();
|
||||||
|
if (cleared > 0)
|
||||||
|
InvokeOnChange();
|
||||||
|
return cleared;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Add(string item, float amount, bool allowPartialAdd = false)
|
||||||
|
{
|
||||||
|
var added = DoAdd(item, amount, allowPartialAdd);
|
||||||
|
if (added > 0)
|
||||||
|
InvokeOnChange();
|
||||||
|
return added;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Remove(string item, float amount, bool allowPartialRemoval = false)
|
||||||
|
{
|
||||||
|
var removed = DoRemove(item, amount, allowPartialRemoval);
|
||||||
|
if (removed > 0)
|
||||||
|
InvokeOnChange();
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegisterOnChangeCallback(Action callback)
|
||||||
|
{
|
||||||
|
changeCallbacks.Add(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnregisterOnChangeCallback(Action callback)
|
||||||
|
{
|
||||||
|
changeCallbacks.Remove(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InvokeOnChange()
|
||||||
|
{
|
||||||
|
// Debug.Log(
|
||||||
|
// $"Resources: {String.Join("; ", resources.Values.ToArray().Select(r => r.Resource.Name + "=" + r.Amount + (r.Unlocked ? "" : "(locked)")))}"
|
||||||
|
// );
|
||||||
|
|
||||||
|
changeCallbacks.ForEach(a =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
a.Invoke();
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class Inventory2 : IInventory, IDataPersistence<InventoryData>
|
||||||
|
{
|
||||||
|
private NameCallback nameCallback;
|
||||||
|
private Dictionary<string, float> items = new Dictionary<string, float>();
|
||||||
|
|
||||||
|
public Inventory2(float capacity, NameCallback nameCallback)
|
||||||
|
{
|
||||||
|
this.nameCallback = nameCallback;
|
||||||
|
_capacity = capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IReadOnlyDictionary<string, float> Items => items;
|
||||||
|
|
||||||
|
private float _capacity;
|
||||||
|
|
||||||
|
public override string Name => nameCallback();
|
||||||
|
|
||||||
|
public override float Capacity
|
||||||
|
{
|
||||||
|
get { return _capacity; }
|
||||||
|
set { _capacity = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return this.ToString(Environment.NewLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ToString(string delimiter = "\n")
|
||||||
|
{
|
||||||
|
string text = string.Join(delimiter, items);
|
||||||
|
text += delimiter + $"Занято {Load}";
|
||||||
|
if (Capacity >= 0)
|
||||||
|
text += $", свободно {Capacity - Load}";
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override float GetAmount(string item)
|
||||||
|
{
|
||||||
|
return items.ContainsKey(item) ? items[item] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override int DoClear()
|
||||||
|
{
|
||||||
|
var itemCount = items.Count;
|
||||||
|
items.Clear();
|
||||||
|
return itemCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override float DoAdd(string item, float amount, bool allowPartialAdd = false)
|
||||||
|
{
|
||||||
|
if (!allowPartialAdd && (Capacity >= 0) && (Capacity < Load + amount))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
amount = Math.Min(amount, Free);
|
||||||
|
|
||||||
|
if (items.ContainsKey(item))
|
||||||
|
items[item] += amount;
|
||||||
|
else
|
||||||
|
items[item] = amount;
|
||||||
|
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override float DoRemove(string item, float amount, bool allowPartialRemoval = false)
|
||||||
|
{
|
||||||
|
var presentAmount = GetAmount(item);
|
||||||
|
|
||||||
|
if (!allowPartialRemoval && presentAmount < amount)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
amount = Math.Min(amount, presentAmount);
|
||||||
|
|
||||||
|
items[item] -= amount;
|
||||||
|
if (items[item] == 0)
|
||||||
|
items.Remove(item);
|
||||||
|
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadData(InventoryData data)
|
||||||
|
{
|
||||||
|
items = data.items;
|
||||||
|
_capacity = data.capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveData(InventoryData data)
|
||||||
|
{
|
||||||
|
data.items = new SerializableDictionary<string, float>(items);
|
||||||
|
data.capacity = _capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Inventory2 Clone()
|
||||||
|
{
|
||||||
|
var clone = new Inventory2(Capacity, nameCallback);
|
||||||
|
foreach (var kvp in items)
|
||||||
|
clone.items.Add(kvp.Key, kvp.Value);
|
||||||
|
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OverrideItemsFrom(Inventory2 source)
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
foreach (var kvp in source.Items)
|
||||||
|
items.Add(kvp.Key, kvp.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 336b8a407440c5441a9570eb1b5776d0
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
// class, not interface so Unity shows fields in Editor
|
||||||
|
public class InventoryHolder : MonoBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField]
|
||||||
|
private new string name;
|
||||||
|
|
||||||
|
public readonly IInventory Inventory;
|
||||||
|
|
||||||
|
public string Name => name == null || name == "" ? gameObject.name : name;
|
||||||
|
|
||||||
|
public float Capacity;
|
||||||
|
|
||||||
|
public InventoryHolder()
|
||||||
|
{
|
||||||
|
Inventory = new Inventory2(0, () => Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
Inventory.Capacity = Capacity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b6e85c222b8627a4287c8dc63bf5cfe6
|
||||||
|
|
@ -6,7 +6,10 @@ public class ResourceGenerator : MonoBehaviour
|
||||||
{
|
{
|
||||||
public int Interval;
|
public int Interval;
|
||||||
|
|
||||||
public int Power = 0;
|
public float Power = 0;
|
||||||
|
|
||||||
|
[field: SerializeField]
|
||||||
|
public InventoryHolder TargetInventory { get; private set; }
|
||||||
|
|
||||||
private ResourceSource source;
|
private ResourceSource source;
|
||||||
private long lastTime;
|
private long lastTime;
|
||||||
|
|
@ -76,6 +79,12 @@ public class ResourceGenerator : MonoBehaviour
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (TargetInventory.Inventory.Free == 0)
|
||||||
|
{
|
||||||
|
lastTime = time;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Debug.Log($"{time} - {lastTime} = {delta} since last generation");
|
// Debug.Log($"{time} - {lastTime} = {delta} since last generation");
|
||||||
|
|
||||||
long times = delta / Interval;
|
long times = delta / Interval;
|
||||||
|
|
@ -89,7 +98,8 @@ public class ResourceGenerator : MonoBehaviour
|
||||||
private void Generate(int times)
|
private void Generate(int times)
|
||||||
{
|
{
|
||||||
// Debug.Log($"+{Power}x{times} {source.Resource.Name}");
|
// Debug.Log($"+{Power}x{times} {source.Resource.Name}");
|
||||||
ResourceStorage.Instance.AddResource(source.Resource, Power * times);
|
if (TargetInventory)
|
||||||
|
TargetInventory.Inventory.Add(source.Resource.Name, Power * times, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float Progress
|
public float Progress
|
||||||
|
|
|
||||||
|
|
@ -4,123 +4,42 @@ using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UIElements;
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
public class StoredResource
|
public class ResourceRegistry
|
||||||
{
|
{
|
||||||
public Resource Resource { get; private set; }
|
public static ResourceRegistry Instance { get; private set; }
|
||||||
public int Amount { get; internal set; }
|
|
||||||
public bool Unlocked { get; internal set; }
|
|
||||||
|
|
||||||
public StoredResource(Resource resource)
|
private readonly List<Resource> _items = new List<Resource>();
|
||||||
|
|
||||||
|
public Resource[] Items => _items.ToArray();
|
||||||
|
|
||||||
|
public readonly Metal Metal = new Metal();
|
||||||
|
public readonly Electronics Electronics = new Electronics();
|
||||||
|
public readonly Energy Energy = new Energy();
|
||||||
|
public readonly Money Money = new Money();
|
||||||
|
|
||||||
|
static ResourceRegistry()
|
||||||
{
|
{
|
||||||
Resource = resource;
|
Instance = new ResourceRegistry();
|
||||||
Amount = 0;
|
}
|
||||||
Unlocked = false;
|
|
||||||
|
private ResourceRegistry()
|
||||||
|
{
|
||||||
|
RegisterResource(Metal, true);
|
||||||
|
RegisterResource(Electronics, true); // TODO lock back
|
||||||
|
RegisterResource(Energy, true); // TODO lock back
|
||||||
|
RegisterResource(Money, true); // TODO lock back
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RegisterResource(Resource resource, bool unlocked = false)
|
||||||
|
{
|
||||||
|
_items.Add(resource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ResourceStorage : MonoBehaviour
|
public class ResourceStorage : InventoryHolder
|
||||||
{
|
{
|
||||||
public static ResourceStorage Instance { get; private set; }
|
|
||||||
|
|
||||||
private Dictionary<string, StoredResource> resources = new Dictionary<string, StoredResource>();
|
|
||||||
|
|
||||||
private List<Action> changeCallbacks = new List<Action>();
|
|
||||||
|
|
||||||
public static readonly Metal Metal = new Metal();
|
|
||||||
public static readonly Electronics Electronics = new Electronics();
|
|
||||||
public static readonly Energy Energy = new Energy();
|
|
||||||
public static readonly Money Money = new Money();
|
|
||||||
|
|
||||||
public static Resource[] RegisteredResources
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var list = new List<Resource>();
|
|
||||||
list.Add(Metal);
|
|
||||||
list.Add(Electronics);
|
|
||||||
list.Add(Energy);
|
|
||||||
list.Add(Money);
|
|
||||||
|
|
||||||
return list.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Type[] RegisteredResourceTypes =>
|
|
||||||
RegisteredResources.Select(r => r.GetType()).ToArray();
|
|
||||||
|
|
||||||
public ResourceStorage()
|
public ResourceStorage()
|
||||||
{
|
{
|
||||||
AddResource(Metal, true);
|
Capacity = -1;
|
||||||
AddResource(Electronics, true); // TODO lock back
|
|
||||||
AddResource(Energy, true); // TODO lock back
|
|
||||||
AddResource(Money, true); // TODO lock back
|
|
||||||
|
|
||||||
Instance = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddResource(Resource resource, bool unlocked = false)
|
|
||||||
{
|
|
||||||
resources.Add(resource.Name, new StoredResource(resource) { Unlocked = unlocked });
|
|
||||||
}
|
|
||||||
|
|
||||||
public StoredResource GetResource(Resource resource)
|
|
||||||
{
|
|
||||||
return resources[resource.Name];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddResource(Resource resource, int amount)
|
|
||||||
{
|
|
||||||
var res = GetResource(resource);
|
|
||||||
if (res != null)
|
|
||||||
{
|
|
||||||
res.Amount += amount;
|
|
||||||
InvokeOnChange();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveResource(Resource resource, int amount)
|
|
||||||
{
|
|
||||||
var res = GetResource(resource);
|
|
||||||
if (res != null && res.Amount >= amount)
|
|
||||||
{
|
|
||||||
res.Amount -= amount;
|
|
||||||
InvokeOnChange();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UnlockResource(Resource resource)
|
|
||||||
{
|
|
||||||
var res = GetResource(resource);
|
|
||||||
if (res != null)
|
|
||||||
{
|
|
||||||
res.Unlocked = true;
|
|
||||||
InvokeOnChange();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InvokeOnChange()
|
|
||||||
{
|
|
||||||
// Debug.Log(
|
|
||||||
// $"Resources: {String.Join("; ", resources.Values.ToArray().Select(r => r.Resource.Name + "=" + r.Amount + (r.Unlocked ? "" : "(locked)")))}"
|
|
||||||
// );
|
|
||||||
|
|
||||||
changeCallbacks.ForEach(a =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
a.Invoke();
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RegisterOnChangeCallback(Action callback)
|
|
||||||
{
|
|
||||||
changeCallbacks.Add(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UnregisterOnChangeCallback(Action callback)
|
|
||||||
{
|
|
||||||
changeCallbacks.Remove(callback);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,12 @@ public class ResourceStorageView : MonoBehaviour
|
||||||
void OnEnable()
|
void OnEnable()
|
||||||
{
|
{
|
||||||
storage = GetComponent<ResourceStorage>();
|
storage = GetComponent<ResourceStorage>();
|
||||||
storage.RegisterOnChangeCallback(OnStorageChange);
|
storage.Inventory.RegisterOnChangeCallback(OnStorageChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnDisable()
|
void OnDisable()
|
||||||
{
|
{
|
||||||
storage.UnregisterOnChangeCallback(OnStorageChange);
|
storage.Inventory.UnregisterOnChangeCallback(OnStorageChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStorageChange()
|
private void OnStorageChange()
|
||||||
|
|
@ -58,15 +58,28 @@ public class ResourceStorageView : MonoBehaviour
|
||||||
|
|
||||||
private void UpdateVisuals()
|
private void UpdateVisuals()
|
||||||
{
|
{
|
||||||
UpdateSlotVisuals(metalSlot, storage.GetResource(ResourceStorage.Metal));
|
UpdateSlotVisuals(
|
||||||
UpdateSlotVisuals(electronicsSlot, storage.GetResource(ResourceStorage.Electronics));
|
metalSlot,
|
||||||
UpdateSlotVisuals(energySlot, storage.GetResource(ResourceStorage.Energy));
|
storage.Inventory.GetAmount(ResourceRegistry.Instance.Metal.Name)
|
||||||
UpdateSlotVisuals(moneySlot, storage.GetResource(ResourceStorage.Money));
|
);
|
||||||
|
UpdateSlotVisuals(
|
||||||
|
electronicsSlot,
|
||||||
|
storage.Inventory.GetAmount(ResourceRegistry.Instance.Electronics.Name)
|
||||||
|
);
|
||||||
|
UpdateSlotVisuals(
|
||||||
|
energySlot,
|
||||||
|
storage.Inventory.GetAmount(ResourceRegistry.Instance.Energy.Name)
|
||||||
|
);
|
||||||
|
UpdateSlotVisuals(
|
||||||
|
moneySlot,
|
||||||
|
storage.Inventory.GetAmount(ResourceRegistry.Instance.Money.Name)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateSlotVisuals(SlotInfo slot, StoredResource resource)
|
private void UpdateSlotVisuals(SlotInfo slot, float amount)
|
||||||
{
|
{
|
||||||
slot.slotElement.style.display = resource.Unlocked ? DisplayStyle.Flex : DisplayStyle.None;
|
slot.slotElement.style.display = DisplayStyle.Flex;
|
||||||
slot.amountLabel.text = resource.Amount.ToString();
|
// slot.slotElement.style.display = resource.Unlocked ? DisplayStyle.Flex : DisplayStyle.None;
|
||||||
|
slot.amountLabel.text = amount.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@
|
||||||
<ui:VisualElement picking-mode="Ignore" name="Panel" style="flex-grow: 1; opacity: 1; width: 10%; position: absolute; left: auto;">
|
<ui:VisualElement picking-mode="Ignore" name="Panel" style="flex-grow: 1; opacity: 1; width: 10%; position: absolute; left: auto;">
|
||||||
<ui:VisualElement picking-mode="Position" name="InnerPanel" style="flex-grow: 1; opacity: 1; width: 100%; position: absolute; left: -50%; bottom: 100%; font-size: 100%;">
|
<ui:VisualElement picking-mode="Position" name="InnerPanel" style="flex-grow: 1; opacity: 1; width: 100%; position: absolute; left: -50%; bottom: 100%; font-size: 100%;">
|
||||||
<ui:Label text="Label" name="Title" style="-unity-text-align: middle-center; font-size: 14px;"/>
|
<ui:Label text="Label" name="Title" style="-unity-text-align: middle-center; font-size: 14px;"/>
|
||||||
<ui:ProgressBar value="22" title="" name="Progress" style="font-size: 12px;"/>
|
<ui:ProgressBar value="0" title="" name="Progress" style="font-size: 12px;"/>
|
||||||
|
<ui:ProgressBar value="0" title="" name="StorageLoad" style="font-size: 12px;"/>
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
</ui:UXML>
|
</ui:UXML>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue