Skip to content

Commit

Permalink
add new experimental loading
Browse files Browse the repository at this point in the history
  • Loading branch information
FabianTerhorst committed Jun 18, 2021
1 parent 3e12217 commit 200572a
Show file tree
Hide file tree
Showing 10 changed files with 247 additions and 25 deletions.
13 changes: 13 additions & 0 deletions api/AltV.Net.Async/DefaultAsyncResource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace AltV.Net.Async
{
public class DefaultAsyncResource : AsyncResource
{
public override void OnStart()
{
}

public override void OnStop()
{
}
}
}
3 changes: 2 additions & 1 deletion api/AltV.Net.EntitySync.Entities/BlipEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

namespace AltV.Net.EntitySync.Entities
{
//TODO: add entity events to entity sync that only trigger one time for each entity on stream in
//TODO: add entity events to entity sync that only trigger one time for each entity on stream in,
//TODO: maybe that can be done by data and then resetData and setData on method call with method and parameters, maybe doesnt even work
public class BlipEntity : Entity
{
private int Sprite
Expand Down
49 changes: 48 additions & 1 deletion api/AltV.Net.EntitySync/SpatialPartitions/SortedLimitedList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ namespace AltV.Net.EntitySync.SpatialPartitions
[Serializable]
[System.Runtime.CompilerServices.TypeForwardedFrom("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class SortedLimitedList<TKey, TValue> :
IDictionary<TKey, TValue>, IDictionary, IReadOnlyDictionary<TKey, TValue> where TKey : notnull
IDictionary<TKey, TValue>, IDictionary, IReadOnlyDictionary<TKey, TValue>, IList<TValue> where TKey : notnull
{
private TKey[] keys; // Do not rename (binary serialization)
private TValue[] values; // Do not rename (binary serialization)
Expand Down Expand Up @@ -1234,5 +1234,52 @@ public void RemoveAt(int index)
throw new NotSupportedException("SR.NotSupported_SortedListNestedWrite");
}
}


// IList implementation

IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator()
{
// Only used for testing
return Values.GetEnumerator();
}

public void Add(TValue item)
{
throw new NotImplementedException();
}

public bool Contains(TValue item)
{
throw new NotImplementedException();
}

public void CopyTo(TValue[] array, int arrayIndex)
{
throw new NotImplementedException();
}

public bool Remove(TValue item)
{
throw new NotImplementedException();
}

public bool IsReadOnly => throw new NotImplementedException();

public int IndexOf(TValue item)
{
throw new NotImplementedException();
}

public void Insert(int index, TValue item)
{
throw new NotImplementedException();
}

public TValue this[int index]
{
get => GetByIndex(index);
set => throw new NotImplementedException();
}
}
}
14 changes: 14 additions & 0 deletions api/AltV.Net.Example/MyPlayerFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using AltV.Net.Elements.Entities;

namespace AltV.Net.Example
{
[EntityFactory(BaseObjectType.Player)]
public class MyPlayerFactory : IEntityFactory<IPlayer>
{
public IPlayer Create(IntPtr playerPointer, ushort id)
{
return new MyPlayer(playerPointer, id);
}
}
}
13 changes: 13 additions & 0 deletions api/AltV.Net/DefaultResource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace AltV.Net
{
public class DefaultResource : Resource
{
public override void OnStart()
{
}

public override void OnStop()
{
}
}
}
16 changes: 16 additions & 0 deletions api/AltV.Net/EntityFactoryAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using AltV.Net.Elements.Entities;

namespace AltV.Net
{
[AttributeUsage(AttributeTargets.Class)]
public sealed class EntityFactoryAttribute : Attribute
{
private readonly BaseObjectType baseObjectType;

public EntityFactoryAttribute(BaseObjectType baseObjectType)
{
this.baseObjectType = baseObjectType;
}
}
}
4 changes: 4 additions & 0 deletions api/AltV.Net/IResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,9 @@ Module GetModule(IServer server,
IBaseObjectPool<IVoiceChannel> voiceChannelPool,
IBaseObjectPool<IColShape> colShapePool,
INativeResourcePool resourcePool);

IScript[] GetScripts();

IModule[] GetModules();
}
}
66 changes: 51 additions & 15 deletions api/AltV.Net/ModuleWrapper.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Loader;
using AltV.Net.Data;
using AltV.Net.Elements.Entities;
using AltV.Net.Elements.Factories;
using AltV.Net.ResourceLoaders;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
Expand All @@ -25,29 +27,58 @@ internal static class ModuleWrapper
private static void OnStartResource(IntPtr serverPointer, IntPtr resourcePointer, string resourceName,
string entryPoint)
{
foreach (var module in _modules)
{
module.OnScriptsStarted(_scripts);
}

_resource.OnStart();
}

//TODO: optimize assembly looping with single assembly loop otherwise module startup time is to slow for large projects,
//TODO: also can we reduce iterations by some assembies, e.g. only assemblies interested for us
//TODO: make optional resource startup time improvements for specifying IScript and IModules manually in IResource so module doesnt has to search them
public static void MainWithAssembly(IntPtr serverPointer, IntPtr resourcePointer,
AssemblyLoadContext assemblyLoadContext)
{
if (!AssemblyLoader.FindType(assemblyLoadContext.Assemblies, out _resource))
var defaultResource = !AssemblyLoader.FindType(assemblyLoadContext.Assemblies, out _resource);
if (defaultResource)
{
return;
}
var altVNetAsyncAssembly = assemblyLoadContext.LoadFromAssemblyName(new AssemblyName("AltV.Net.Async"));
try
{
foreach (var type in altVNetAsyncAssembly.GetTypes())
{
if (type.Name != "DefaultAsyncResource") continue;
var constructor =
type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,
null,
Type.EmptyTypes, null);
_resource = (IResource) constructor?.Invoke(null);
break;
}
}
catch
{
// ignored
}

var playerFactory = _resource.GetPlayerFactory();
var vehicleFactory = _resource.GetVehicleFactory();
var blipFactory = _resource.GetBlipFactory();
var checkpointFactory = _resource.GetCheckpointFactory();
var voiceChannelFactory = _resource.GetVoiceChannelFactory();
var colShapeFactory = _resource.GetColShapeFactory();
var nativeResourceFactory = _resource.GetNativeResourceFactory();
_resource ??= new DefaultResource();
}

//var entityFactories = AssemblyLoader.FindAllTypesWithAttribute<IEntityFactory<IEntity>, EntityFactoryAttribute>(assemblyLoadContext.Assemblies);
//var baseObjectFactories = AssemblyLoader.FindAllTypesWithAttribute<IBaseObjectFactory<IBaseObject>, EntityFactoryAttribute>(assemblyLoadContext.Assemblies);

//TODO: when resource has entity factories overwritten dont loop assemblies because of performance

//TODO: when not default resource and entity factory was found and none default resource has entity factory overwritten by not returning null throw exception

//TODO: check

//TODO: do the same with the pools

var playerFactory = _resource.GetPlayerFactory() ?? new PlayerFactory();
var vehicleFactory = _resource.GetVehicleFactory() ?? new VehicleFactory();
var blipFactory = _resource.GetBlipFactory() ?? new BlipFactory();
var checkpointFactory = _resource.GetCheckpointFactory() ?? new CheckpointFactory();
var voiceChannelFactory = _resource.GetVoiceChannelFactory() ?? new VoiceChannelFactory();
var colShapeFactory = _resource.GetColShapeFactory() ?? new ColShapeFactory();
var nativeResourceFactory = _resource.GetNativeResourceFactory() ?? new NativeResourceFactory();
var playerPool = _resource.GetPlayerPool(playerFactory);
var vehiclePool = _resource.GetVehiclePool(vehicleFactory);
var blipPool = _resource.GetBlipPool(blipFactory);
Expand Down Expand Up @@ -86,9 +117,14 @@ public static void MainWithAssembly(IntPtr serverPointer, IntPtr resourcePointer
"IScript must not be a IResource for type:" + script.GetType());
}
}

_module.OnScriptsLoaded(_scripts);
_modules = AssemblyLoader.FindAllTypes<IModule>(assemblyLoadContext.Assemblies);
_module.OnModulesLoaded(_modules);
foreach (var module in _modules)
{
module.OnScriptsStarted(_scripts);
}

AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
}
Expand Down
24 changes: 17 additions & 7 deletions api/AltV.Net/Resource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,37 +74,37 @@ public virtual INativeResourcePool GetNativeResourcePool(INativeResourceFactory

public virtual IEntityFactory<IPlayer> GetPlayerFactory()
{
return new PlayerFactory();
return null;
}

public virtual IEntityFactory<IVehicle> GetVehicleFactory()
{
return new VehicleFactory();
return null;
}

public virtual IBaseObjectFactory<IBlip> GetBlipFactory()
{
return new BlipFactory();
return null;
}

public virtual IBaseObjectFactory<ICheckpoint> GetCheckpointFactory()
{
return new CheckpointFactory();
return null;
}

public virtual IBaseObjectFactory<IVoiceChannel> GetVoiceChannelFactory()
{
return new VoiceChannelFactory();
return null;
}

public virtual IBaseObjectFactory<IColShape> GetColShapeFactory()
{
return new ColShapeFactory();
return null;
}

public virtual INativeResourceFactory GetNativeResourceFactory()
{
return new NativeResourceFactory();
return null;
}

public virtual Module GetModule(IServer server,
Expand All @@ -120,5 +120,15 @@ public virtual Module GetModule(IServer server,
return new Module(server, assemblyLoadContext, cSharpNativeResource, baseBaseObjectPool, baseEntityPool, playerPool, vehiclePool,
blipPool, checkpointPool, voiceChannelPool, colShapePool, nativeResourcePool);
}

public IScript[] GetScripts()
{
return null;
}

public IModule[] GetModules()
{
return null;
}
}
}
70 changes: 69 additions & 1 deletion api/AltV.Net/ResourceLoaders/AssemblyLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public T[] FindAllTypes<T>()
return typesFound.ToArray();
}*/

public static T[] FindAllTypes<T>(IEnumerable<Assembly> assemblies)
{
var typeToFind = typeof(T);
Expand Down Expand Up @@ -158,6 +158,74 @@ public static T[] FindAllTypes<T>(IEnumerable<Assembly> assemblies)
return typesFound.ToArray();
}

public static (T, TAttribute)[] FindAllTypesWithAttribute<T, TAttribute>(IEnumerable<Assembly> assemblies)
where TAttribute : Attribute
{
var typeToFind = typeof(T);
var typesFound = new LinkedList<(T, TAttribute)>();
foreach (var assembly in assemblies)
{
Type[] types;
try
{
types = assembly.GetTypes();
}
catch (Exception e)
{
Console.WriteLine(
$"{assembly.Location}: Threw a exception while looking in assembly '{assembly.FullName}': {e}");

if (!(e is ReflectionTypeLoadException reflectionException)) continue;
Console.WriteLine("---");

foreach (var exception in reflectionException.LoaderExceptions)
{
Console.WriteLine($"Exception: {exception}");
}

Console.WriteLine("---");

continue;
}

foreach (var type in types)
{
if (type.IsClass == false || type.IsAbstract ||
typeToFind.IsAssignableFrom(type) == false)
{
continue;
}

var customAttribute = type.GetCustomAttributes<TAttribute>().FirstOrDefault();

if (customAttribute == null) continue;

var constructor =
type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null,
Type.EmptyTypes, null);

if (constructor == null)
{
Console.WriteLine(
$"Possible {typeToFind} \"{type}\" found, but no constructor without parameters available");

continue;
}

try
{
typesFound.AddFirst(((T) constructor.Invoke(null), customAttribute));
}
catch (Exception e)
{
Console.WriteLine($"Threw a exception while executing constructor: + {e}");
}
}
}

return typesFound.ToArray();
}

public static bool FindType<T>(IEnumerable<Assembly> assemblies, out T t)
{
foreach (var assembly in assemblies)
Expand Down

0 comments on commit 200572a

Please sign in to comment.