Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
unknown committed Dec 3, 2020
1 parent 21ef898 commit b147216
Show file tree
Hide file tree
Showing 10 changed files with 919 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Build
*.sln
.vs
obj/
bin/
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# Vina-Framework
Vina Framework is developed to help creating high quality C# FiveM resources. The framework handle & abstract basic stuff that most resource need.
Vina Framework is developed to help creating high quality C# FiveM resources.
The framework handle & abstract basic stuff that most resource need.
237 changes: 237 additions & 0 deletions VinaFrameworkClient/Core/BaseClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

using CitizenFX.Core;
using CitizenFX.Core.Native;

namespace VinaFrameworkClient.Core
{
/// <summary>
/// Extend your Client script with this class and add modules to your constructor
/// </summary>
public abstract class BaseClient : BaseScript
{
/// <summary>
/// This current client resource name
/// </summary>
public static string Name { get; private set; }

/// <summary>
/// This current client resource name
/// </summary>
public string ResourceName { get { return Name; } }

private List<Module> modules;

/// <summary>
/// Extend your Client script with this class and add modules to your constructor
/// </summary>
public BaseClient()
{
Name = API.GetCurrentResourceName();
modules = new List<Module>();

Debug.WriteLine("============================================================");
Log($"Initializing...");

Tick += initialize;
}

#region Base Events

private async Task initialize()
{
Tick -= initialize;

await Delay(0);

Log($"Initialized!");
TriggerServerEvent($"internal:{Name}:onPlayerClientInitialized");
}

#endregion

#region Methods

/// <summary>
/// Verify if the module has been loaded.
/// </summary>
/// <param name="moduleType">The module class type. Ex: typeof(MyModule)</param>
/// <returns></returns>
public bool HasModule(Type moduleType)
{
foreach (Module module in modules)
{
if (module.GetType() == moduleType)
{
return true;
}
}

return false;
}

/// <summary>
/// Add module by referencing the type of your module class.
/// </summary>
/// <param name="moduleType">The module class type. Ex: typeof(MyModule)</param>
public void AddModule(Type moduleType)
{
bool error = false;
foreach (Module _module in modules)
{
if (_module.GetType() == moduleType)
{
error = true;
LogError(new Exception($"Trying to add existing module {moduleType.Name}!"));
}
}

if (error) return;

try
{
if (!moduleType.IsSubclassOf(typeof(Module)))
throw new Exception($"Trying to add class {moduleType.Name} that is not a subclass of Module!");

Module module = (Module)Activator.CreateInstance(moduleType, this);
modules.Add(module);
}
catch (Exception exception)
{
LogError(exception, $" in {moduleType.Name} > Constructor");
}
}

/// <summary>
/// Get a module instance from anywhere, cannot be called inside a module constructor.
/// </summary>
/// <typeparam name="T">The module class type.</typeparam>
/// <returns>Return the module or throw an exception if the module is not found.</returns>
public T GetModule<T>()
{
foreach (Module module in modules)
{
if (module.GetType() == typeof(T))
{
return (T)Convert.ChangeType(module, typeof(T));
}
}

throw new Exception($"Module {typeof(T)} doesn't exist!");
}

/// <summary>
/// Register an event.
/// </summary>
/// <param name="eventName">The event name to register.</param>
/// <param name="action">The event delegate to register.</param>
public void RegisterEvent(string eventName, Delegate action)
{
EventHandlers[eventName] += action;
Log($"Event {eventName} registered!");
}

/// <summary>
/// Un-register an event.
/// </summary>
/// <param name="eventName">The event name to un-register.</param>
/// <param name="action">The event delegate to un-register.</param>
public void UnregisterEvent(string eventName, Delegate action)
{
EventHandlers[eventName] -= action;
Log($"Event {eventName} deregistered!");
}

/// <summary>
/// Add a tick to the resource.
/// </summary>
/// <param name="action">The tick delegate to add.</param>
public void AddTick(Func<Task> action)
{
Tick += action;
Log($"{action.Method.DeclaringType.Name} added Tick {action.Method.Name}!");
}

/// <summary>
/// Remove a tick from the resource.
/// </summary>
/// <param name="action">The tick delegate to remove.</param>
public void RemoveTick(Func<Task> action)
{
Tick -= action;
Log($"{action.Method.DeclaringType.Name} removed Tick {action.Method.Name}!");
}

/// <summary>
/// Un-register an event.
/// </summary>
/// <param name="eventName">The event name to un-register.</param>
/// <param name="action">The event delegate to un-register.</param>
internal void AddInternalTick(Func<Task> action)
{
Tick += action;
}

/// <summary>
/// Remove a tick from the resource.
/// </summary>
/// <param name="action">The tick delegate to remove.</param>
internal void RemoveInternalTick(Func<Task> action)
{
Tick -= action;
}

/// <summary>
/// Get the ExportDictionary.
/// </summary>
/// <returns>Return the ExportDictionary.</returns>
public ExportDictionary GetExports()
{
return Exports;
}

/// <summary>
/// Get a specific Export from a resource.
/// </summary>
/// <param name="resourceName"></param>
/// <returns>Return the dynamic export.</returns>
public dynamic GetExport(string resourceName)
{
return Exports[resourceName];
}

/// <summary>
/// Set an Export from this resource.
/// </summary>
/// <param name="name">The name of the Exported method.</param>
/// <param name="method">The delegate of the Exported method.</param>
public void SetExport(string name, Delegate method)
{
Exports.Add(name, method);
}

/// <summary>
/// Log a message.
/// </summary>
/// <param name="message">The message to log.</param>
public void Log(string message)
{
Debug.WriteLine($"{DateTime.Now.ToLongTimeString()} [INFO] {ResourceName.ToUpper()}: {message}");
}

/// <summary>
/// Log an exception.
/// </summary>
/// <param name="exception">The Exception to log.</param>
/// <param name="prefix">Some text to add before the log message.</param>
public void LogError(Exception exception, string prefix = "")
{
string pre = (prefix != "") ? $" {prefix}" : "";
Debug.WriteLine($"{DateTime.Now.ToLongTimeString()} [ERROR] {ResourceName.ToUpper()}{pre}: {exception.Message}\n{exception.StackTrace}");
}

#endregion
}
}
90 changes: 90 additions & 0 deletions VinaFrameworkClient/Core/Module.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using System;
using System.Threading.Tasks;

using CitizenFX.Core;

namespace VinaFrameworkClient.Core
{
/// <summary>
/// Extend your module class with this class and add it to your client constructor.
/// </summary>
public abstract class Module
{
/// <summary>
/// This current module name.
/// </summary>
protected string Name { get; }

/// <summary>
/// Read-only reference to the client instance.
/// </summary>
protected BaseClient client { get; }

/// <summary>
/// Extend your module class with this class and add it to your client constructor.
/// </summary>
/// <param name="client"></param>
public Module(BaseClient client)
{
Name = this.GetType().Name;
this.client = client;
client.AddInternalTick(initialize);
Log($"Instance created!");
}

private async Task initialize()
{
Log($"Initializing...");

client.RemoveInternalTick(initialize);

await BaseClient.Delay(0);

try
{
OnModuleInitialized();
}
catch (Exception exception)
{
LogError(exception, " in OnModuleInitialized");
}
}

/// <summary>
/// Overridable method that run on first tick only. You can get other module from here.
/// </summary>
protected virtual void OnModuleInitialized()
{
Log($"Initialized!");
}

/// <summary>
///
/// </summary>
/// <param name="msecs"></param>
public static Task Delay(int msecs)
{
return BaseClient.Delay(msecs);
}

/// <summary>
/// Log a message from this module.
/// </summary>
/// <param name="message">The message to log.</param>
protected void Log(string message)
{
Debug.WriteLine($"{DateTime.Now.ToLongTimeString()} [INFO] {client.ResourceName.ToUpper()} > {Name.ToUpper()}: {message}");
}

/// <summary>
/// Log an exception from this module.
/// </summary>
/// <param name="exception">The Exception to log.</param>
/// <param name="prefix">Some text to add before the log message.</param>
protected void LogError(Exception exception, string prefix = "")
{
string pre = (prefix != "") ? $" {prefix}" : "";
Debug.WriteLine($"{DateTime.Now.ToLongTimeString()} [ERROR] {client.ResourceName.ToUpper()} > {Name.ToUpper()}{pre}: {exception.Message}\n{exception.StackTrace}");
}
}
}
36 changes: 36 additions & 0 deletions VinaFrameworkClient/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("VinaFramework")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("VinaFrameworkClient")]
[assembly: AssemblyCopyright("Copyright © VinaStar 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("6b2efafa-b162-4b97-b837-6d8a8e5162cd")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Loading

0 comments on commit b147216

Please sign in to comment.