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