From e0530ff55b45c52e33bb6979354a90263fd3686f Mon Sep 17 00:00:00 2001 From: OmniSudo Date: Wed, 27 Mar 2024 07:14:12 -0500 Subject: [PATCH] Starters. --- .gitignore | 5 + .idea/.idea.RuneSharp/.idea/.gitignore | 13 ++ .idea/.idea.RuneSharp/.idea/encodings.xml | 4 + .idea/.idea.RuneSharp/.idea/indexLayout.xml | 8 + .idea/.idea.RuneSharp/.idea/vcs.xml | 6 + RuneSharp.sln | 16 ++ RuneSharp.sln.DotSettings | 2 + RuneSharp/RuneSharp.csproj | 18 ++ RuneSharp/src/client/ClientConfigLoader.cs | 46 +++++ RuneSharp/src/client/ClientLoader.cs | 16 ++ RuneSharp/src/client/Debug.cs | 13 ++ RuneSharp/src/client/RSConfig.cs | 16 ++ RuneSharp/src/client/RuneSharp.cs | 10 ++ RuneSharp/src/client/RuneSharpProperties.cs | 5 + RuneSharp/src/client/console/Command.cs | 9 + RuneSharp/src/client/console/CommandReader.cs | 164 ++++++++++++++++++ RuneSharp/src/client/console/ICommands.cs | 28 +++ RuneSharp/src/client/console/ILogger.cs | 15 ++ RuneSharp/src/client/console/Logger.cs | 46 +++++ RuneSharp/src/client/graphics/IRenderer.cs | 5 + RuneSharp/src/client/graphics/Renderer.cs | 20 +++ 21 files changed, 465 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.idea.RuneSharp/.idea/.gitignore create mode 100644 .idea/.idea.RuneSharp/.idea/encodings.xml create mode 100644 .idea/.idea.RuneSharp/.idea/indexLayout.xml create mode 100644 .idea/.idea.RuneSharp/.idea/vcs.xml create mode 100644 RuneSharp.sln create mode 100644 RuneSharp.sln.DotSettings create mode 100644 RuneSharp/RuneSharp.csproj create mode 100644 RuneSharp/src/client/ClientConfigLoader.cs create mode 100644 RuneSharp/src/client/ClientLoader.cs create mode 100644 RuneSharp/src/client/Debug.cs create mode 100644 RuneSharp/src/client/RSConfig.cs create mode 100644 RuneSharp/src/client/RuneSharp.cs create mode 100644 RuneSharp/src/client/RuneSharpProperties.cs create mode 100644 RuneSharp/src/client/console/Command.cs create mode 100644 RuneSharp/src/client/console/CommandReader.cs create mode 100644 RuneSharp/src/client/console/ICommands.cs create mode 100644 RuneSharp/src/client/console/ILogger.cs create mode 100644 RuneSharp/src/client/console/Logger.cs create mode 100644 RuneSharp/src/client/graphics/IRenderer.cs create mode 100644 RuneSharp/src/client/graphics/Renderer.cs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..add57be --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +bin/ +obj/ +/packages/ +riderModule.iml +/_ReSharper.Caches/ \ No newline at end of file diff --git a/.idea/.idea.RuneSharp/.idea/.gitignore b/.idea/.idea.RuneSharp/.idea/.gitignore new file mode 100644 index 0000000..251c78e --- /dev/null +++ b/.idea/.idea.RuneSharp/.idea/.gitignore @@ -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 diff --git a/.idea/.idea.RuneSharp/.idea/encodings.xml b/.idea/.idea.RuneSharp/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/.idea/.idea.RuneSharp/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.RuneSharp/.idea/indexLayout.xml b/.idea/.idea.RuneSharp/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.RuneSharp/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.RuneSharp/.idea/vcs.xml b/.idea/.idea.RuneSharp/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/.idea.RuneSharp/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/RuneSharp.sln b/RuneSharp.sln new file mode 100644 index 0000000..76a402d --- /dev/null +++ b/RuneSharp.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RuneSharp", "RuneSharp\RuneSharp.csproj", "{302D622E-E624-42B5-A97A-5C145FAE6BB2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {302D622E-E624-42B5-A97A-5C145FAE6BB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {302D622E-E624-42B5-A97A-5C145FAE6BB2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {302D622E-E624-42B5-A97A-5C145FAE6BB2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {302D622E-E624-42B5-A97A-5C145FAE6BB2}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/RuneSharp.sln.DotSettings b/RuneSharp.sln.DotSettings new file mode 100644 index 0000000..74afbfd --- /dev/null +++ b/RuneSharp.sln.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/RuneSharp/RuneSharp.csproj b/RuneSharp/RuneSharp.csproj new file mode 100644 index 0000000..8ee7f84 --- /dev/null +++ b/RuneSharp/RuneSharp.csproj @@ -0,0 +1,18 @@ + + + + Exe + net7.0 + enable + enable + + + + + + + + + + + diff --git a/RuneSharp/src/client/ClientConfigLoader.cs b/RuneSharp/src/client/ClientConfigLoader.cs new file mode 100644 index 0000000..6d661e7 --- /dev/null +++ b/RuneSharp/src/client/ClientConfigLoader.cs @@ -0,0 +1,46 @@ +namespace RuneSharp.client; + +public class ClientConfigLoader { + public static RSConfig Get( Uri uri ) { + var client = new HttpClient(); + + var resp = client.GetStringAsync( uri ); + resp.Wait(); + var data = resp.Result; + + var config = new RSConfig(); + + var lines = data.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); + foreach (var line in lines) { + if ( !string.IsNullOrWhiteSpace( line ) ) { + int idx = line.IndexOf('='); + + if (idx == -1) + { + continue; + } + + String s = line.Substring(0, idx); + + switch (s) + { + case "param": + var l = line.Substring(idx + 1); + idx = l.IndexOf('='); + s = l.Substring(0, idx); + + config.AppletProperties[s] = l.Substring(idx + 1); + break; + case "msg": + // ignore + break; + default: + config.ClassLoaderProperties[s] = line.Substring(idx + 1); + break; + } + } + } + + return config; + } +} diff --git a/RuneSharp/src/client/ClientLoader.cs b/RuneSharp/src/client/ClientLoader.cs new file mode 100644 index 0000000..f2019b7 --- /dev/null +++ b/RuneSharp/src/client/ClientLoader.cs @@ -0,0 +1,16 @@ +namespace RuneSharp.client; + +public class ClientLoader { + public static readonly string LOCK_FILE = Path.Combine( RuneSharp.CACHE_DIR, ".lock" ); + + public void Load() { + var config = DownloadConfig(); + + + } + + private RSConfig DownloadConfig() { + return ClientConfigLoader.Get( RuneSharpProperties.JAV_CONFIG_URI ); + // TODO: Fallback config + } +} diff --git a/RuneSharp/src/client/Debug.cs b/RuneSharp/src/client/Debug.cs new file mode 100644 index 0000000..67f4884 --- /dev/null +++ b/RuneSharp/src/client/Debug.cs @@ -0,0 +1,13 @@ +using System.Diagnostics; +namespace RuneSharp.Application.debug; + +public static class Debug { + [ DebuggerHidden ] + [ Conditional( "DEBUG" ) ] + public static void Break() { + if ( Debugger.IsAttached ) { + // Shared.API.Logger.Trace( "Reached breakpoint" ); + Debugger.Break(); + } + } +} diff --git a/RuneSharp/src/client/RSConfig.cs b/RuneSharp/src/client/RSConfig.cs new file mode 100644 index 0000000..ef7a8c3 --- /dev/null +++ b/RuneSharp/src/client/RSConfig.cs @@ -0,0 +1,16 @@ +using System.Collections.Concurrent; +namespace RuneSharp.client; + +public class RSConfig { + public ConcurrentDictionary AppletProperties = new(); + public ConcurrentDictionary ClassLoaderProperties = new(); + + public string CodeBase { + get => ClassLoaderProperties["codebase"]; + set => ClassLoaderProperties["codebase"] = value; + } + + public string InitialJar => ClassLoaderProperties["initial_jar"]; + public string InitialClass => ClassLoaderProperties["initial_class"]; + +} diff --git a/RuneSharp/src/client/RuneSharp.cs b/RuneSharp/src/client/RuneSharp.cs new file mode 100644 index 0000000..3ed9f04 --- /dev/null +++ b/RuneSharp/src/client/RuneSharp.cs @@ -0,0 +1,10 @@ +using RuneSharp.client; +namespace RuneSharp; + +public class RuneSharp { + public static readonly string RUNESHARP_DIR = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".runesharp" ); + public static readonly string CACHE_DIR = Path.Combine( RUNESHARP_DIR, "cache" ); + + public static void Main( string[] args ) { + } +} \ No newline at end of file diff --git a/RuneSharp/src/client/RuneSharpProperties.cs b/RuneSharp/src/client/RuneSharpProperties.cs new file mode 100644 index 0000000..9a3b8e6 --- /dev/null +++ b/RuneSharp/src/client/RuneSharpProperties.cs @@ -0,0 +1,5 @@ +namespace RuneSharp.client; + +public class RuneSharpProperties { + public static readonly Uri JAV_CONFIG_URI = new Uri( "https://oldschool.runescape.com/jav_config.ws" ); +} diff --git a/RuneSharp/src/client/console/Command.cs b/RuneSharp/src/client/console/Command.cs new file mode 100644 index 0000000..bed656c --- /dev/null +++ b/RuneSharp/src/client/console/Command.cs @@ -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(); + +} diff --git a/RuneSharp/src/client/console/CommandReader.cs b/RuneSharp/src/client/console/CommandReader.cs new file mode 100644 index 0000000..9bde282 --- /dev/null +++ b/RuneSharp/src/client/console/CommandReader.cs @@ -0,0 +1,164 @@ +using System.Collections.Immutable; +using System.Reflection; +namespace RuneSharp.Application.commands; + +public class CommandReader : ICommands { + /// + /// The task running the name reader + /// + private readonly Task _readTask; + + private readonly Dictionary> _listeners = new(); + + /// + /// Used to cancel the task + /// + private readonly CancellationTokenSource _tokenSource = new(); + + /// + /// CTOR + /// + public CommandReader() { + var token = _tokenSource.Token; + token.ThrowIfCancellationRequested(); + + _readTask = Task.Factory.StartNew( + () => { + Loop( token ); + }, + token, + TaskCreationOptions.LongRunning, + TaskScheduler.Default + ); + } + + /// + /// Listen for commands + /// + /// + 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}" ); + } + } + + } + + /// + /// Use an object to listen to commands, + /// Every method with a Command attribute is included in the commands + /// + /// The object to receive commands + 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( o, method ); + } + ); + } + } + + /// + /// Remove an object from being a name listeners + /// + /// + public void Remove( object o ) { + List keysToRemove = new List(); + + foreach ( var pair in _listeners ) { + if ( pair.Value.Item1.Equals( o ) ) { + keysToRemove.Add( pair.Key ); + } + } + + foreach ( Command key in keysToRemove ) { + _listeners.Remove( key ); + } + } + + /// + /// Remove all name listeners + /// + public void Reset() { + _listeners.Clear(); + } + + /// + /// Stop listening for commands + /// + public void Stop() { + _tokenSource.Cancel(); + _readTask.Wait(); + } + + /// + /// Split quoted strings + /// + /// Quoted string + /// Split by quotes and spaces + private static List Parse( string name ) { + List 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; + } + +} diff --git a/RuneSharp/src/client/console/ICommands.cs b/RuneSharp/src/client/console/ICommands.cs new file mode 100644 index 0000000..fdc6354 --- /dev/null +++ b/RuneSharp/src/client/console/ICommands.cs @@ -0,0 +1,28 @@ +namespace RuneSharp.Application; + +public interface ICommands { + public void Do( string? text ); + + /// + /// Use an object to listen to commands, + /// Every method with a Command attribute is included in the commands + /// + /// The object to receive commands + public void Add( object o ); + + /// + /// Remove an object from being a name listeners + /// + /// + public void Remove( object o ); + + /// + /// Remove all name listeners + /// + public void Reset(); + + /// + /// Stop listening for commands + /// + public void Stop(); +} diff --git a/RuneSharp/src/client/console/ILogger.cs b/RuneSharp/src/client/console/ILogger.cs new file mode 100644 index 0000000..0dfa1bd --- /dev/null +++ b/RuneSharp/src/client/console/ILogger.cs @@ -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 ); +} diff --git a/RuneSharp/src/client/console/Logger.cs b/RuneSharp/src/client/console/Logger.cs new file mode 100644 index 0000000..8f06d1a --- /dev/null +++ b/RuneSharp/src/client/console/Logger.cs @@ -0,0 +1,46 @@ +namespace RuneSharp.Application; + +public class Logger : ILogger { + private List? _subloggers = new List(); + + public Logger( List? 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() ) { + sublogger.Print( level, message ); + } + } + + protected void Print( string level, string message ) { + Console.WriteLine( $"[ {level} ][ {DateTime.Now:MM/dd/yy hh:mm:ss tt} ] {message}" ); + } +} diff --git a/RuneSharp/src/client/graphics/IRenderer.cs b/RuneSharp/src/client/graphics/IRenderer.cs new file mode 100644 index 0000000..16ceb90 --- /dev/null +++ b/RuneSharp/src/client/graphics/IRenderer.cs @@ -0,0 +1,5 @@ +namespace RuneSharp.Application.graphics; + +public interface IRenderer { + +} diff --git a/RuneSharp/src/client/graphics/Renderer.cs b/RuneSharp/src/client/graphics/Renderer.cs new file mode 100644 index 0000000..254210c --- /dev/null +++ b/RuneSharp/src/client/graphics/Renderer.cs @@ -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 resolution ) { + var options = WindowOptions.Default; + options.Size = resolution.As(); + options.Title = "SkillQuest"; + options.WindowBorder = WindowBorder.Fixed; + + Window = Silk.NET.Windowing.Window.Create( options ); + } + + public void Dispose() { + Window.Dispose(); + } +}