constexpr export function GetPSGeneratorVersion() : Int32
{
	return ( 666 + 7 ) + 5;
}

struct VirtualComponentBinder
{

	public static function Bind( game : GameInstance, entityID : EntityID, componentName : CName, psClassName : CName ) : PersistentState
	{
		var virtualPS : PersistentState;
		var psID : PersistentID;
		psID = CreatePersistentID( entityID, componentName );
		virtualPS = GameInstance.GetPersistencySystem( game ).GetConstAccessToPSObject( psID, psClassName );
		if( virtualPS )
		{
			return virtualPS;
		}
		return NULL;
	}

}

function SpawnVirtualPS( game : GameInstance, entityID : EntityID, componentName : CName, psClassName : CName ) : PersistentState
{
	return VirtualComponentBinder.Bind( game, entityID, componentName, psClassName );
}

export function GetNotSavableClasses() : array< CName >
{
	var classes : array< CName >;
	classes.PushBack( 'ElectricLightControllerPS' );
	classes.PushBack( 'LcdScreenControllerPS' );
	classes.PushBack( 'CrossingLightControllerPS' );
	classes.PushBack( 'TrafficZebraControllerPS' );
	classes.PushBack( 'TrafficLightControllerPS' );
	classes.PushBack( 'TrafficIntersectionManagerControllerPS' );
	classes.PushBack( 'BarbedWireControllerPS' );
	return classes;
}

import enum EntityNotificationType
{
	DoNotNotifyEntity,
	SendThisEventToEntity,
	SendPSChangedEventToEntity,
}

importonly abstract class IGamePersistencySystem extends IGameSystem
{
}

importonly final class GamePersistencySystem extends IGamePersistencySystem
{
	public import function EntityProxy_DisablePhysics( targetEntity : EntityID, disable : Bool );
	public import function QueueEntityEvent( targetEntity : EntityID, evt : Event );
	public import function QueuePSEvent( targetID : PersistentID, psClassName : CName, evt : Event );
	public import function GetConstAccessToPSObject( targetID : PersistentID, psClassName : CName ) : PersistentState;
	public import function ForgetObject( targetID : PersistentID, notifyEntity : Bool );
	public import function QueuePSDeviceEvent( action : DeviceAction );
	public import function GetPersistentBool( targetEntity : PersistentID, psClassName : CName, varName : CName ) : Bool;
	public import function GetPersistentInt( targetEntity : PersistentID, psClassName : CName, varName : CName ) : Int32;
	public import function GetPersistentFloat( targetEntity : PersistentID, psClassName : CName, varName : CName ) : Float;
	public import function SetPersistentBool( targetEntity : PersistentID, psClassName : CName, varName : CName, newValue : Bool );
	public import function SetPersistentInt( targetEntity : PersistentID, psClassName : CName, varName : CName, newValue : Int32 );
	public import function SetPersistentFloat( targetEntity : PersistentID, psClassName : CName, varName : CName, newValue : Float );
}

importonly abstract class PersistentState extends IScriptable
{
	public import const final function GetID() : PersistentID;
	public import const final function GetPersistencySystem() : GamePersistencySystem;
	public import const final function GetGameInstance() : GameInstance;
	public import final function ForcePersistentStateChanged();
}

importonly class GameObjectPS extends PersistentState
{
}

import class GamePuppetPS extends GameObjectPS
{
	public import const final function GetGender() : CName;
	public import const final function WasQuickHacked() : Bool;
	public import final function SetWasQuickHacked( newValue : Bool );
	public import const final function HasQuickHackBegunUpload() : Bool;
	public import final function SetHasQuickHackBegunUpload( newValue : Bool );
	public import const final function HasNPCTriggeredCombatInSecuritySystem() : Bool;
	public import final function SetHasNPCTriggeredCombatInSecuritySystem( set : Bool );
	public import final function HasAlternativeName() : Bool;
	public import final function SetCrouch( set : Bool );
	public import final function IsCrouch() : Bool;
	public import final function GetTpp() : Bool;

	public function OnNotifiedSecSysAboutCombat( evt : NotifiedSecSysAboutCombat ) : EntityNotificationType
	{
		SetHasNPCTriggeredCombatInSecuritySystem( true );
		return EntityNotificationType.DoNotNotifyEntity;
	}

}

