2020-12-18 12:12:45 +01:00
using System.Collections ;
using System.Collections.Generic ;
using UnityEngine ;
using UnityEditor ;
//Define the system managing the clients. (Singleton)
public sealed class ClientManager : MonoBehaviour
{
2021-01-13 15:05:09 +01:00
//Singleton
private static ClientManager _instance = null ;
public static ClientManager Instance { get
{
if ( _instance is null )
Debug . LogError ( "Missing ClientManager instance" ) ;
return _instance ;
}
}
2021-01-13 13:32:24 +01:00
[HideInInspector]
public bool ready = false ; //Wether the ClientManager is initialized
2021-01-13 15:05:09 +01:00
[SerializeField]
int nbMaxClients = 1 ; //Maximum active clients
[SerializeField]
float clientSpawnTimer = 0.5f ; //Intial time before first spawn (pseudo-random after that)
[SerializeField]
float maxTimeNewClients = 2.0f ; //Longest waiting time for new clients
2020-12-18 12:12:45 +01:00
bool clientSpawnReady = false ;
2021-01-17 10:57:00 +01:00
[SerializeField]
2020-12-18 12:12:45 +01:00
string ClientRessourceFolder = "Clients" ;
private Object [ ] clients ;
2020-12-31 16:24:44 +01:00
GameObject ClientContainer = null ;
List < int > clientIDs = new List < int > ( ) ;
2020-12-18 12:12:45 +01:00
2020-12-31 12:53:02 +01:00
Vector2 spawnPoint ;
Dictionary < Vector2 , bool > targets_dict ; //Dict with target and wether they're taken by a client
2020-12-30 20:09:20 +01:00
2020-12-18 12:12:45 +01:00
//Request new client
//Return wether a new client was created
public bool clientRequest ( )
{
2020-12-31 16:24:44 +01:00
if ( clientSpawnReady & & clientIDs . Count < nbMaxClients & & targets_dict . ContainsValue ( false ) )
2020-12-18 12:12:45 +01:00
{
2020-12-31 16:24:44 +01:00
int prefabChoice = Random . Range ( 0 , clients . Length ) ;
GameObject newClient = Instantiate ( ( GameObject ) clients [ prefabChoice ] , spawnPoint , Quaternion . identity , ClientContainer . transform ) ; //Instantiate new client inside ClientManager
clientIDs . Add ( newClient . GetInstanceID ( ) ) ; //Save ID
// Debug.Log(newClient.GetInstanceID());
newClient . name = newClient . name . Split ( '(' ) [ 0 ] + clientIDs [ clientIDs . Count - 1 ] ; //Rename new client
2020-12-18 12:12:45 +01:00
clientSpawnTimer = Random . Range ( 1.0f , maxTimeNewClients ) ; //Need more random ?
clientSpawnReady = false ;
2020-12-31 16:24:44 +01:00
// Debug.Log("Spawning "+clientPrefab.name+" at "+spawnPosition);
2020-12-18 12:12:45 +01:00
return true ; //New client instantiated
}
return false ; //No new client
}
2021-01-07 14:45:19 +01:00
//TODO: Reputation
public void clientReward ( int money )
{
2021-01-12 16:55:43 +01:00
GameSystem . Instance . Gold + = money ;
2021-01-07 14:45:19 +01:00
}
2020-12-31 16:24:44 +01:00
//Destroy a client
public void clientLeave ( GameObject client )
{
clientIDs . Remove ( - int . Parse ( client . name . Split ( '-' ) [ 1 ] ) ) ;
Destroy ( client ) ;
// Debug.Log(client.name+" destroyed"+clientIDs.Count);
2021-01-13 13:32:24 +01:00
//Prevent immediate spawn of a new client after one leaving
if ( clientSpawnReady )
{
clientSpawnReady = false ;
clientSpawnTimer + = 0.5f ;
}
2020-12-31 16:24:44 +01:00
}
2021-01-12 10:20:30 +01:00
//Return a random available target. Or the Exit if Exit=True.
//prevTarget : Previous target of the client which will be available for other clients.
public Vector2 assignTarget ( Vector2 ? prevTarget = null , bool exit = false )
2020-12-30 20:09:20 +01:00
{
2020-12-31 12:53:02 +01:00
if ( prevTarget ! = null )
{
targets_dict [ ( Vector2 ) prevTarget ] = false ; //Free prevTarget
2021-01-12 10:20:30 +01:00
}
if ( exit ) //Assign Exit target
2020-12-31 12:53:02 +01:00
return spawnPoint ;
2021-01-12 10:20:30 +01:00
else
{
List < Vector2 > avail_tgt = new List < Vector2 > ( ) ;
foreach ( KeyValuePair < Vector2 , bool > tgt in targets_dict )
if ( tgt . Value is false )
avail_tgt . Add ( tgt . Key ) ;
Vector2 target = avail_tgt [ Random . Range ( 0 , avail_tgt . Count ) ] ;
targets_dict [ target ] = true ;
return target ;
2020-12-31 12:53:02 +01:00
}
2021-01-12 10:20:30 +01:00
}
//Return a random order from available consummable
2021-01-12 16:55:43 +01:00
//TODO : Check stock before assignement ?
2021-01-12 10:20:30 +01:00
public string assignOrder ( )
{
2021-01-12 16:55:43 +01:00
List < string > available_types = new List < string > ( Consumable . allowed_types ) ;
2021-01-12 10:41:48 +01:00
string order_type = available_types [ Random . Range ( 0 , available_types . Count ) ] ;
return order_type ;
2020-12-30 20:09:20 +01:00
}
2021-01-12 16:55:43 +01:00
//Awake is called when the script instance is being loaded.
void Awake ( )
2020-12-18 12:12:45 +01:00
{
2021-01-13 15:05:09 +01:00
//Singleton
if ( _instance ! = null & & _instance ! = this )
Destroy ( this . gameObject ) ;
else
_instance = this ;
2021-01-13 13:32:24 +01:00
if ( ! ready )
{
ClientContainer = GameObject . Find ( "/GameSystem/ClientManager" ) ;
if ( ClientContainer is null )
throw new System . Exception ( "No ClientManager found under GameSystem" ) ;
2020-12-31 16:24:44 +01:00
2021-01-13 13:32:24 +01:00
// Load clients prefabs //
2020-12-30 20:09:20 +01:00
2021-01-13 13:32:24 +01:00
// Find all assets labelled with 'usable' :
// string[] guids = AssetDatabase.FindAssets("", new string[] {"Assets/Prefabs/Characters/Clients"});
2020-12-18 12:12:45 +01:00
2021-01-13 13:32:24 +01:00
// foreach (string guid in guids)
// {
// Debug.Log(AssetDatabase.GUIDToAssetPath(guid));
// Instantiate(guid, spawnPosition, Quaternion.identity);
// }
2020-12-18 12:12:45 +01:00
2021-01-13 13:32:24 +01:00
clients = Resources . LoadAll ( ClientRessourceFolder ) ;
2020-12-18 12:12:45 +01:00
2021-01-13 13:32:24 +01:00
// foreach (var c in clients)
// {
// Debug.Log(gameObject.name+" : "+c.name + " loaded");
// }
if ( clients . Length < nbMaxClients )
{
Debug . LogWarning ( "ClientManager doesn't have enough client prefab to manage unique MaxClients : " + clients . Length + "/" + nbMaxClients ) ;
}
2020-12-30 20:09:20 +01:00
2021-01-13 13:32:24 +01:00
// Load Client spawn point //
GameObject spawnObj = GameObject . Find ( "/GameSystem/ClientSpawn" ) ;
if ( spawnObj is null )
throw new System . Exception ( "No ClientSpawn GameObject found under GameSystem" ) ;
spawnPoint = spawnObj . transform . position ;
2020-12-30 20:09:20 +01:00
2021-01-13 13:32:24 +01:00
// Load Client targets //
targets_dict = new Dictionary < Vector2 , bool > ( ) ;
GameObject targetsObj = GameObject . Find ( "/GameSystem/Targets" ) ;
if ( targetsObj is null )
throw new System . Exception ( "No Targets GameObject found under GameSystem" ) ;
2020-12-30 20:09:20 +01:00
2021-01-13 13:32:24 +01:00
Component [ ] targets = targetsObj . GetComponentsInChildren < Transform > ( ) ;
if ( targets ! = null )
2020-12-30 20:09:20 +01:00
{
2021-01-13 13:32:24 +01:00
foreach ( Transform target in targets )
2020-12-30 20:09:20 +01:00
{
2021-01-13 13:32:24 +01:00
if ( target . gameObject . name ! = "Targets" )
{
targets_dict . Add ( target . position , false ) ;
// Debug.Log("Client target : "+ target.gameObject.name + target.position);
}
2020-12-30 20:09:20 +01:00
}
}
2021-01-13 13:32:24 +01:00
if ( targets_dict . Count < nbMaxClients )
{
Debug . LogWarning ( "ClientManager doesn't have enough target to manage MaxClients : " + targets_dict . Count + "/" + nbMaxClients ) ;
}
ready = true ;
2020-12-31 16:24:44 +01:00
}
2020-12-18 12:12:45 +01:00
}
// Update is called once per frame
void Update ( )
{
if ( ! clientSpawnReady )
{
clientSpawnTimer - = Time . deltaTime ;
if ( clientSpawnTimer < = 0 )
clientSpawnReady = true ;
}
2020-12-31 16:24:44 +01:00
// Debug.Log("Client Spawn : "+clientSpawnTimer+" / Seat available: "+targets_dict.ContainsValue(false));
2020-12-18 12:12:45 +01:00
}
//// Singleton Implementation (https://jlambert.developpez.com/tutoriels/dotnet/implementation-pattern-singleton-csharp/#LIII) ////
2021-01-13 15:05:09 +01:00
// private ClientManager()
// {
// }
2020-12-18 12:12:45 +01:00
2021-01-13 15:05:09 +01:00
// public static ClientManager Instance { get { return Nested.instance; } }
2020-12-18 12:12:45 +01:00
2021-01-13 15:05:09 +01:00
// private class Nested
// {
// // Explicit static constructor to tell C# compiler
// // not to mark type as beforefieldinit
// static Nested()
// {
// }
// internal static readonly ClientManager instance = new GameObject("ClientManager").AddComponent<ClientManager>();
// }
2020-12-18 12:12:45 +01:00
////
}