commit
e0530ff55b
@ -0,0 +1,5 @@
|
||||
bin/
|
||||
obj/
|
||||
/packages/
|
||||
riderModule.iml
|
||||
/_ReSharper.Caches/
|
@ -0,0 +1,13 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Rider ignored files
|
||||
/.idea.RuneSharp.iml
|
||||
/modules.xml
|
||||
/projectSettingsUpdater.xml
|
||||
/contentModel.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||
</project>
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UserContentModel">
|
||||
<attachedFolders />
|
||||
<explicitIncludes />
|
||||
<explicitExcludes />
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1,2 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=runesharp/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Silk.NET.GLFW" Version="2.20.0" />
|
||||
<PackageReference Include="Silk.NET.Input.Glfw" Version="2.20.0" />
|
||||
<PackageReference Include="Silk.NET.Maths" Version="2.20.0" />
|
||||
<PackageReference Include="Silk.NET.OpenGL" Version="2.20.0" />
|
||||
<PackageReference Include="Silk.NET.Windowing.Glfw" Version="2.20.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -0,0 +1,9 @@
|
||||
namespace RuneSharp.Application.commands;
|
||||
|
||||
[AttributeUsage( AttributeTargets.Method )]
|
||||
public class Command : Attribute {
|
||||
public required string Name { get; set; }
|
||||
|
||||
public string[] Arguments { get; set; } = Array.Empty<string>();
|
||||
|
||||
}
|
@ -0,0 +1,164 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Reflection;
|
||||
namespace RuneSharp.Application.commands;
|
||||
|
||||
public class CommandReader : ICommands {
|
||||
/// <summary>
|
||||
/// The task running the name reader
|
||||
/// </summary>
|
||||
private readonly Task _readTask;
|
||||
|
||||
private readonly Dictionary<Command, Tuple<object, MethodInfo>> _listeners = new();
|
||||
|
||||
/// <summary>
|
||||
/// Used to cancel the task
|
||||
/// </summary>
|
||||
private readonly CancellationTokenSource _tokenSource = new();
|
||||
|
||||
/// <summary>
|
||||
/// CTOR
|
||||
/// </summary>
|
||||
public CommandReader() {
|
||||
var token = _tokenSource.Token;
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
_readTask = Task.Factory.StartNew(
|
||||
() => {
|
||||
Loop( token );
|
||||
},
|
||||
token,
|
||||
TaskCreationOptions.LongRunning,
|
||||
TaskScheduler.Default
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Listen for commands
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
private void Loop( CancellationToken token ) {
|
||||
while ( !token.IsCancellationRequested ) {
|
||||
var text = Console.ReadLine();
|
||||
Do( text );
|
||||
}
|
||||
}
|
||||
|
||||
public void Do( string? text ) {
|
||||
var split = Parse( text ?? "" );
|
||||
if ( split.Count >= 1 )
|
||||
foreach (
|
||||
var pair in _listeners.ToImmutableList().Where( pair => pair.Key.Name.ToLower().Equals( split[0] ) && pair.Key.Arguments.Length <= split.Count + 1 )
|
||||
) {
|
||||
try {
|
||||
// ReSharper disable once CoVariantArrayConversion
|
||||
pair.Value.Item2.Invoke( pair.Value.Item1, split.Skip( 1 ).Take( pair.Key.Arguments.Length ).ToArray() );
|
||||
} catch ( Exception e ) {
|
||||
// TODO: CommonBackend.API.Logger.Error( $"Exception when running {pair.Key.Name}:\n{e.Message}\n{e.StackTrace}" );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use an object to listen to commands,
|
||||
/// Every method with a Command attribute is included in the commands
|
||||
/// </summary>
|
||||
/// <param name="o"> The object to receive commands </param>
|
||||
public void Add( object o ) {
|
||||
foreach ( var method in o.GetType().GetMethods() ) {
|
||||
method.GetCustomAttributes( typeof( Command ), true ).AsParallel().Where( obj => obj is Command name && method.GetParameters().Length == name.Arguments.Length ).ForAll(
|
||||
attribObject => {
|
||||
var attribute = attribObject as Command;
|
||||
if ( attribute is null ) return;
|
||||
|
||||
// TODO: CommonBackend.API.Logger?.Trace( $"Registering name {attribute.Name}" );
|
||||
_listeners[attribute!] = new Tuple<object, MethodInfo>( o, method );
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove an object from being a name listeners
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
public void Remove( object o ) {
|
||||
List<Command> keysToRemove = new List<Command>();
|
||||
|
||||
foreach ( var pair in _listeners ) {
|
||||
if ( pair.Value.Item1.Equals( o ) ) {
|
||||
keysToRemove.Add( pair.Key );
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( Command key in keysToRemove ) {
|
||||
_listeners.Remove( key );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove all name listeners
|
||||
/// </summary>
|
||||
public void Reset() {
|
||||
_listeners.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop listening for commands
|
||||
/// </summary>
|
||||
public void Stop() {
|
||||
_tokenSource.Cancel();
|
||||
_readTask.Wait();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Split quoted strings
|
||||
/// </summary>
|
||||
/// <param name="name"> Quoted string </param>
|
||||
/// <returns> Split by quotes and spaces </returns>
|
||||
private static List<string> Parse( string name ) {
|
||||
List<string> ret = new();
|
||||
|
||||
var length = name.Length;
|
||||
bool sQuote = false, dQuote = false;
|
||||
|
||||
for ( var i = 0; i < length; i++ ) {
|
||||
var start = i;
|
||||
switch ( name[i] ) {
|
||||
case '\'':
|
||||
sQuote = true;
|
||||
|
||||
break;
|
||||
case '\"':
|
||||
dQuote = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
int argLength;
|
||||
if ( dQuote ) {
|
||||
i++;
|
||||
start++;
|
||||
while ( i < length && name[i] != '\"' ) i++;
|
||||
if ( i < length ) dQuote = false;
|
||||
argLength = i - start;
|
||||
} else if ( sQuote ) {
|
||||
i++;
|
||||
start++;
|
||||
while ( i < length && name[i] != '\'' ) i++;
|
||||
if ( i < length ) sQuote = false;
|
||||
argLength = i - start;
|
||||
} else {
|
||||
while ( i < length && name[i] != ' ' ) i++;
|
||||
argLength = i - start;
|
||||
}
|
||||
|
||||
ret.Add( name.Substring( start, argLength ) );
|
||||
}
|
||||
|
||||
if ( dQuote || sQuote ) ret.Clear();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
namespace RuneSharp.Application;
|
||||
|
||||
public interface ICommands {
|
||||
public void Do( string? text );
|
||||
|
||||
/// <summary>
|
||||
/// Use an object to listen to commands,
|
||||
/// Every method with a Command attribute is included in the commands
|
||||
/// </summary>
|
||||
/// <param name="o"> The object to receive commands </param>
|
||||
public void Add( object o );
|
||||
|
||||
/// <summary>
|
||||
/// Remove an object from being a name listeners
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
public void Remove( object o );
|
||||
|
||||
/// <summary>
|
||||
/// Remove all name listeners
|
||||
/// </summary>
|
||||
public void Reset();
|
||||
|
||||
/// <summary>
|
||||
/// Stop listening for commands
|
||||
/// </summary>
|
||||
public void Stop();
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
namespace RuneSharp.Application;
|
||||
|
||||
public interface ILogger {
|
||||
public void Trace( string message );
|
||||
|
||||
public void Debug( string message );
|
||||
|
||||
public void Info( string message );
|
||||
|
||||
public void Warning( string message );
|
||||
|
||||
public void Error( string message );
|
||||
|
||||
public void Fatal( string message );
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
namespace RuneSharp.Application;
|
||||
|
||||
public class Logger : ILogger {
|
||||
private List<Logger>? _subloggers = new List<Logger>();
|
||||
|
||||
public Logger( List<Logger>? subloggers ) {
|
||||
_subloggers = subloggers;
|
||||
}
|
||||
|
||||
public void Trace( string message ) {
|
||||
Write( " TRACE ", message );
|
||||
}
|
||||
|
||||
public void Debug( string message ) {
|
||||
#if ( DEBUG )
|
||||
Write( " DEBUG ", message );
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Info( string message ) {
|
||||
Write( " INFO ", message );
|
||||
}
|
||||
|
||||
public void Warning( string message ) {
|
||||
Write( "WARNING", message );
|
||||
}
|
||||
|
||||
public void Error( string message ) {
|
||||
Write( " ERROR ", message );
|
||||
}
|
||||
|
||||
public void Fatal( string message ) {
|
||||
Write( " FATAL ", message );
|
||||
}
|
||||
|
||||
private void Write( string level, string message ) {
|
||||
Print( level, message );
|
||||
foreach ( var sublogger in _subloggers is not null ? _subloggers.ToArray() : Array.Empty<Logger>() ) {
|
||||
sublogger.Print( level, message );
|
||||
}
|
||||
}
|
||||
|
||||
protected void Print( string level, string message ) {
|
||||
Console.WriteLine( $"[ {level} ][ {DateTime.Now:MM/dd/yy hh:mm:ss tt} ] {message}" );
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
namespace RuneSharp.Application.graphics;
|
||||
|
||||
public interface IRenderer {
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
using Silk.NET.Maths;
|
||||
using Silk.NET.Windowing;
|
||||
namespace RuneSharp.Application.graphics;
|
||||
|
||||
public class Renderer : IRenderer, IDisposable {
|
||||
public readonly IWindow Window;
|
||||
|
||||
public Renderer( Vector2D<uint> resolution ) {
|
||||
var options = WindowOptions.Default;
|
||||
options.Size = resolution.As<int>();
|
||||
options.Title = "SkillQuest";
|
||||
options.WindowBorder = WindowBorder.Fixed;
|
||||
|
||||
Window = Silk.NET.Windowing.Window.Create( options );
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
Window.Dispose();
|
||||
}
|
||||
}
|
Loading…
Reference in new issue