master
OmniSudo 6 months ago
commit e0530ff55b

5
.gitignore vendored

@ -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,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

@ -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,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;
}
}

@ -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
}
}

@ -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();
}
}
}

@ -0,0 +1,16 @@
using System.Collections.Concurrent;
namespace RuneSharp.client;
public class RSConfig {
public ConcurrentDictionary<string, string> AppletProperties = new();
public ConcurrentDictionary<string, string> ClassLoaderProperties = new();
public string CodeBase {
get => ClassLoaderProperties["codebase"];
set => ClassLoaderProperties["codebase"] = value;
}
public string InitialJar => ClassLoaderProperties["initial_jar"];
public string InitialClass => ClassLoaderProperties["initial_class"];
}

@ -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 ) {
}
}

@ -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" );
}

@ -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…
Cancel
Save