Compare commits
12 Commits
v1.0.0-alp
...
v1.2.0
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9471d83a45 | ||
![]() |
52b225d944 | ||
![]() |
c8f0a61209 | ||
![]() |
59c3e9eb54 | ||
![]() |
d20d68b831 | ||
![]() |
cfda1f8eef | ||
![]() |
2fb222125a | ||
![]() |
c7c3c00783 | ||
![]() |
dcc130e2cf | ||
![]() |
491f3d3af4 | ||
![]() |
178fcb8164 | ||
![]() |
64f123abe9 |
@@ -1,9 +1,9 @@
|
||||
# Making a Pull Request
|
||||
* Fork this repository and make sure your local **master** branch is up to date with the main repository.
|
||||
* Create a new branch for your addition with an appropriate name, e.g. **add-restart-command**
|
||||
* Fork this repository and make sure your local **staging** branch is up to date with the main repository.
|
||||
* Create a new branch from the **staging** branch for your addition with an appropriate name, e.g. **add-restart-command**
|
||||
* PRs work by submitting the *entire* branch, so this allows you to continue work without locking up your whole repository.
|
||||
* Commit your changes to that branch, making sure that you **follow the code guidelines below**.
|
||||
* Submit your branch as a PR to be reviewed.
|
||||
* Submit your branch as a PR to be reviewed, with Torch's **staging** branch as the base.
|
||||
|
||||
## Naming Conventions
|
||||
* Types: **PascalCase**
|
||||
|
@@ -16,7 +16,7 @@ try
|
||||
tag_name=$tagName
|
||||
name="Generated $tagName"
|
||||
body=""
|
||||
draft=$FALSE
|
||||
draft=$TRUE
|
||||
prerelease=$tagName.Contains("alpha") -or $tagName.Contains("beta")
|
||||
}
|
||||
Write-Output("Creating new release " + $tagName + "...")
|
||||
|
4
Jenkinsfile
vendored
4
Jenkinsfile
vendored
@@ -59,8 +59,8 @@ node {
|
||||
gitSimpleVersion = bat(returnStdout: true, script: "@git describe --tags --abbrev=0").trim()
|
||||
if (gitVersion == gitSimpleVersion) {
|
||||
stage('Release') {
|
||||
withCredentials([usernamePassword(credentialsId: 'e771beac-b3ee-4bc9-82b7-40a6d426d508', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
|
||||
powershell "./Jenkins/release.ps1 \"https://api.github.com/repos/TorchAPI/Torch/\" \"$gitSimpleVersion\" \"$USERNAME:$PASSWORD\" @(\"bin/torch-server.zip\", \"bin/torch-client.zip\")"
|
||||
withCredentials([usernamePassword(credentialsId: 'torch-github', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
|
||||
powershell "& ./Jenkins/release.ps1 \"https://api.github.com/repos/TorchAPI/Torch/\" \"$gitSimpleVersion\" \"$USERNAME:$PASSWORD\" @(\"bin/torch-server.zip\", \"bin/torch-client.zip\")"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@ using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Threading;
|
||||
using NLog;
|
||||
using Torch.Utils;
|
||||
|
||||
@@ -84,15 +85,15 @@ quit";
|
||||
_server = new TorchServer(_config);
|
||||
_server.Init();
|
||||
|
||||
if (_config.NoGui || _config.Autostart)
|
||||
{
|
||||
new Thread(_server.Start).Start();
|
||||
}
|
||||
|
||||
if (!_config.NoGui)
|
||||
{
|
||||
new TorchUI(_server).ShowDialog();
|
||||
var ui = new TorchUI(_server);
|
||||
if (_config.Autostart)
|
||||
new Thread(_server.Start).Start();
|
||||
ui.ShowDialog();
|
||||
}
|
||||
else
|
||||
_server.Start();
|
||||
|
||||
_resolver?.Dispose();
|
||||
}
|
||||
|
@@ -131,7 +131,7 @@ namespace Torch.Server.Managers
|
||||
|
||||
public void SaveConfig()
|
||||
{
|
||||
DedicatedConfig.Save();
|
||||
DedicatedConfig.Save(Path.Combine(Torch.Config.InstancePath, CONFIG_NAME));
|
||||
Log.Info("Saved dedicated config.");
|
||||
|
||||
try
|
||||
|
@@ -10,20 +10,9 @@
|
||||
<RowDefinition/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<ListView Grid.Row="0" x:Name="ChatItems" ItemsSource="{Binding ChatHistory}" Margin="5,5,5,5">
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Disabled"/>
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<WrapPanel>
|
||||
<TextBlock Text="{Binding Timestamp}"/>
|
||||
<TextBlock Text=" "/>
|
||||
<TextBlock Text="{Binding Name}" FontWeight="Bold"/>
|
||||
<TextBlock Text=": "/>
|
||||
<TextBlock Text="{Binding Message}"/>
|
||||
</WrapPanel>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
<ScrollViewer x:Name="ChatScroller" Grid.Row="0" Margin="5,5,5,5" HorizontalScrollBarVisibility="Disabled">
|
||||
<TextBlock x:Name="ChatItems" />
|
||||
</ScrollViewer>
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition/>
|
||||
|
@@ -41,23 +41,32 @@ namespace Torch.Server
|
||||
{
|
||||
_server = (TorchBase)server;
|
||||
_multiplayer = (MultiplayerManager)server.Multiplayer;
|
||||
ChatItems.Items.Clear();
|
||||
DataContext = _multiplayer;
|
||||
|
||||
ChatItems.Inlines.Clear();
|
||||
_multiplayer.ChatHistory.ForEach(InsertMessage);
|
||||
if (_multiplayer.ChatHistory is INotifyCollectionChanged ncc)
|
||||
ncc.CollectionChanged += ChatHistory_CollectionChanged;
|
||||
ChatScroller.ScrollToBottom();
|
||||
}
|
||||
|
||||
private void ChatHistory_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
ChatItems.ScrollToItem(ChatItems.Items.Count - 1);
|
||||
/*
|
||||
if (VisualTreeHelper.GetChildrenCount(ChatItems) > 0)
|
||||
{
|
||||
foreach (IChatMessage msg in e.NewItems)
|
||||
InsertMessage(msg);
|
||||
}
|
||||
|
||||
Border border = (Border)VisualTreeHelper.GetChild(ChatItems, 0);
|
||||
ScrollViewer scrollViewer = (ScrollViewer)VisualTreeHelper.GetChild(border, 0);
|
||||
scrollViewer.ScrollToBottom();
|
||||
}*/
|
||||
private void InsertMessage(IChatMessage msg)
|
||||
{
|
||||
bool atBottom = ChatScroller.VerticalOffset + 8 > ChatScroller.ScrollableHeight;
|
||||
var span = new Span();
|
||||
span.Inlines.Add($"{msg.Timestamp} ");
|
||||
span.Inlines.Add(new Run(msg.Name) { Foreground = msg.Name == "Server" ? Brushes.DarkBlue : Brushes.Blue });
|
||||
span.Inlines.Add($": {msg.Message}");
|
||||
span.Inlines.Add(new LineBreak());
|
||||
ChatItems.Inlines.Add(span);
|
||||
if (atBottom)
|
||||
ChatScroller.ScrollToBottom();
|
||||
}
|
||||
|
||||
private void SendButton_Click(object sender, RoutedEventArgs e)
|
||||
|
@@ -23,6 +23,15 @@ namespace Torch.Utils
|
||||
/// Declaring type of the member to access. If null, inferred from the instance argument type.
|
||||
/// </summary>
|
||||
public Type Type { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Assembly qualified name of <see cref="Type"/>
|
||||
/// </summary>
|
||||
public string TypeName
|
||||
{
|
||||
get => Type?.AssemblyQualifiedName;
|
||||
set => Type = value == null ? null : Type.GetType(value, true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -93,6 +102,19 @@ namespace Torch.Utils
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public class ReflectedMethodAttribute : ReflectedMemberAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// When set the parameters types for the method are assumed to be this.
|
||||
/// </summary>
|
||||
public Type[] OverrideTypes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Assembly qualified names of <see cref="OverrideTypes"/>
|
||||
/// </summary>
|
||||
public string[] OverrideTypeNames
|
||||
{
|
||||
get => OverrideTypes.Select(x => x.AssemblyQualifiedName).ToArray();
|
||||
set => OverrideTypes = value?.Select(x => x == null ? null : Type.GetType(x)).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -232,10 +254,14 @@ namespace Torch.Utils
|
||||
trueParameterTypes = parameters.Skip(1).Select(x => x.ParameterType).ToArray();
|
||||
}
|
||||
|
||||
var invokeTypes = new Type[trueParameterTypes.Length];
|
||||
for (var i = 0; i < invokeTypes.Length; i++)
|
||||
invokeTypes[i] = attr.OverrideTypes?[i] ?? trueParameterTypes[i];
|
||||
|
||||
MethodInfo methodInstance = trueType.GetMethod(attr.Name ?? field.Name,
|
||||
(attr is ReflectedStaticMethodAttribute ? BindingFlags.Static : BindingFlags.Instance) |
|
||||
BindingFlags.Public |
|
||||
BindingFlags.NonPublic, null, CallingConventions.Any, trueParameterTypes, null);
|
||||
BindingFlags.NonPublic, null, CallingConventions.Any, invokeTypes, null);
|
||||
if (methodInstance == null)
|
||||
{
|
||||
string methodType = attr is ReflectedStaticMethodAttribute ? "static" : "instance";
|
||||
@@ -245,13 +271,38 @@ namespace Torch.Utils
|
||||
$"Unable to find {methodType} method {attr.Name ?? field.Name} in type {trueType.FullName} with parameters {methodParams}");
|
||||
}
|
||||
|
||||
|
||||
if (attr is ReflectedStaticMethodAttribute)
|
||||
{
|
||||
if (attr.OverrideTypes != null)
|
||||
{
|
||||
ParameterExpression[] paramExp =
|
||||
parameters.Select(x => Expression.Parameter(x.ParameterType)).ToArray();
|
||||
var argExp = new Expression[invokeTypes.Length];
|
||||
for (var i = 0; i < argExp.Length; i++)
|
||||
if (invokeTypes[i] != paramExp[i].Type)
|
||||
argExp[i] = Expression.Convert(paramExp[i], invokeTypes[i]);
|
||||
else
|
||||
argExp[i] = paramExp[i];
|
||||
field.SetValue(null,
|
||||
Expression.Lambda(Expression.Call(methodInstance, argExp), paramExp)
|
||||
.Compile());
|
||||
}
|
||||
else
|
||||
field.SetValue(null, Delegate.CreateDelegate(field.FieldType, methodInstance));
|
||||
}
|
||||
else
|
||||
{
|
||||
ParameterExpression[] paramExp = parameters.Select(x => Expression.Parameter(x.ParameterType)).ToArray();
|
||||
ParameterExpression[] paramExp =
|
||||
parameters.Select(x => Expression.Parameter(x.ParameterType)).ToArray();
|
||||
var argExp = new Expression[invokeTypes.Length];
|
||||
for (var i = 0; i < argExp.Length; i++)
|
||||
if (invokeTypes[i] != paramExp[i + 1].Type)
|
||||
argExp[i] = Expression.Convert(paramExp[i + 1], invokeTypes[i]);
|
||||
else
|
||||
argExp[i] = paramExp[i + 1];
|
||||
field.SetValue(null,
|
||||
Expression.Lambda(Expression.Call(paramExp[0], methodInstance, paramExp.Skip(1)), paramExp)
|
||||
Expression.Lambda(Expression.Call(paramExp[0], methodInstance, argExp), paramExp)
|
||||
.Compile());
|
||||
}
|
||||
}
|
||||
@@ -287,7 +338,7 @@ namespace Torch.Utils
|
||||
if (trueType == null && isStatic)
|
||||
throw new ArgumentException("Static field setters need their type defined", nameof(field));
|
||||
|
||||
if (!isStatic)
|
||||
if (!isStatic && trueType == null)
|
||||
trueType = parameters[0].ParameterType;
|
||||
}
|
||||
else if (attr is ReflectedGetterAttribute)
|
||||
@@ -300,7 +351,7 @@ namespace Torch.Utils
|
||||
if (trueType == null && isStatic)
|
||||
throw new ArgumentException("Static field getters need their type defined", nameof(field));
|
||||
|
||||
if (!isStatic)
|
||||
if (!isStatic && trueType == null)
|
||||
trueType = parameters[0].ParameterType;
|
||||
}
|
||||
else
|
||||
@@ -318,10 +369,15 @@ namespace Torch.Utils
|
||||
$"Unable to find field or property for {trueName} in {trueType.FullName} or its base types", nameof(field));
|
||||
|
||||
ParameterExpression[] paramExp = parameters.Select(x => Expression.Parameter(x.ParameterType)).ToArray();
|
||||
Expression instanceExpr = null;
|
||||
if (!isStatic)
|
||||
{
|
||||
instanceExpr = trueType == paramExp[0].Type ? (Expression) paramExp[0] : Expression.Convert(paramExp[0], trueType);
|
||||
}
|
||||
|
||||
MemberExpression fieldExp = sourceField != null
|
||||
? Expression.Field(isStatic ? null : paramExp[0], sourceField)
|
||||
: Expression.Property(isStatic ? null : paramExp[0], sourceProperty);
|
||||
? Expression.Field(instanceExpr, sourceField)
|
||||
: Expression.Property(instanceExpr, sourceProperty);
|
||||
Expression impl;
|
||||
if (attr is ReflectedSetterAttribute)
|
||||
{
|
||||
|
Reference in New Issue
Block a user