Skip to content

Commit

Permalink
Lua console (#60)
Browse files Browse the repository at this point in the history
* Starting on LuaConsole

* Lua Console (LuaConsole) working

* Lua Console added. Possible to execute lua snippets.
* Removed @func from lua
* Added support for developer settings
* Renamed command modules to end with ...InsightAPI so that they are easily distinguished when looking at environment

* Version bump
  • Loading branch information
jdahlblom authored Jan 25, 2024
1 parent 73e76bb commit 1b4f225
Show file tree
Hide file tree
Showing 83 changed files with 518 additions and 306 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -400,3 +400,4 @@ FodyWeavers.xsd
# JetBrains Rider
*.sln.iml
*.bak
src/server/Scripts/DCS-INSIGHT/ServerSettingsDevelopment.lua
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"[lua]": {
"editor.defaultFormatter": "JohnnyMorganz.stylua"
},
"stylua.targetReleaseVersion": "v0.17.0",
"stylua.targetReleaseVersion": "latest",
"Lua.runtime.version": "Lua 5.1",
"Lua.workspace.library": [
"DCS_API_defs.lua"
Expand Down
2 changes: 1 addition & 1 deletion src/client/DCSInsight/DCSInsight.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<!-- for WinForms -->
<AssemblyName>dcs-insight</AssemblyName>
<Version>1.0.0</Version>
<AssemblyVersion>1.8.6</AssemblyVersion>
<AssemblyVersion>1.8.7</AssemblyVersion>
<ApplicationIcon>Images\Magnifier_icon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
Expand Down
11 changes: 11 additions & 0 deletions src/client/DCSInsight/Misc/Common.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using NLog;

namespace DCSInsight.Misc
Expand Down Expand Up @@ -61,5 +62,15 @@ public static Tuple<bool, bool> CheckJSONDirectory(string jsonDirectory)

return new Tuple<bool, bool>(true, jsonFound);
}

public static void UIElement_OnMouseEnter(object sender, MouseEventArgs e)
{
Mouse.OverrideCursor = Cursors.Hand;
}

public static void UIElement_OnMouseLeave(object sender, MouseEventArgs e)
{
Mouse.OverrideCursor = Cursors.Arrow;
}
}
}
7 changes: 7 additions & 0 deletions src/client/DCSInsight/Misc/Constants.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace DCSInsight.Misc
{
internal static class Constants
{
internal const string ListEnvironmentSnippet = "local keys = {}\r\nfor k, v in pairs(_G) do\r\n\tkeys[#keys+1] = k \r\nend\r\nreturn keys";
}
}
1 change: 1 addition & 0 deletions src/client/DCSInsight/UserControls/UserControlAPI.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

<StackPanel Grid.Column="0" Grid.Row="1" Margin="5,5,5,5">
<TextBox Name="TextBoxSyntax" Text="GetDevice(device_id):SetCommand(command_id, new_value)" FontSize="15" FontStyle="Normal" IsReadOnly="True" Background="WhiteSmoke" BorderThickness="0" FontFamily="consolas" Margin="5,5,5,5" MouseEnter="TextBoxSyntax_OnMouseEnter" MouseLeave="TextBoxSyntax_OnMouseLeave" PreviewMouseDown="TextBoxSyntax_OnPreviewMouseDown"></TextBox>
<StackPanel Name="StackPanelLinks" Orientation="Horizontal"/>
</StackPanel>

<ItemsControl Name="ItemsControlParameters" Grid.Column="0" Grid.Row="2" KeyboardNavigation.TabNavigation="Cycle" Margin="5,5,5,5">
Expand Down
66 changes: 62 additions & 4 deletions src/client/DCSInsight/UserControls/UserControlAPI.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using DCSInsight.Events;
using DCSInsight.JSON;
using DCSInsight.Misc;
Expand Down Expand Up @@ -44,7 +45,7 @@ protected override void SetFormState()
{
ButtonSend.IsEnabled = !TextBoxParameterList.Any(o => string.IsNullOrEmpty(o.Text)) && IsConnected;

if (DCSAPI.ReturnsData)
if (DCSAPI.ReturnsData && !IsLuaConsole)
{
CheckBoxPolling.IsEnabled = ButtonSend.IsEnabled;
ComboBoxPollTimes.IsEnabled = CheckBoxPolling.IsChecked == false;
Expand Down Expand Up @@ -89,6 +90,63 @@ protected override void BuildUI()
IsTabStop = true
};

if (IsLuaConsole)
{
textBox.TextWrapping = TextWrapping.Wrap;
textBox.AcceptsReturn = true;
textBox.AcceptsTab = true;
textBox.MinWidth = 500;
textBox.MinHeight = 150;
textBox.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;

var labelConsoleWarning = new Label
{
Content = "[warning]",
Foreground = (SolidColorBrush)new BrushConverter().ConvertFromString("#0000FF"),
};
labelConsoleWarning.MouseEnter += Common.UIElement_OnMouseEnter;
labelConsoleWarning.MouseLeave += Common.UIElement_OnMouseLeave;
labelConsoleWarning.MouseDown += LabelConsoleWarningOnMouseDown;

void LabelConsoleWarningOnMouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("WARNING! This function enables arbitrary lua code to be\r\nexecuted on your computer, including calls to package os (Operating System).\r\nDo NOT enable unless your are firewalled.", "Warning", MessageBoxButton.OK);
}

labelConsoleWarning.Tag = textBox;
StackPanelLinks.Children.Add(labelConsoleWarning);

var labelDefaultLua = new Label
{
Content = "[list environment]",
Foreground = (SolidColorBrush)new BrushConverter().ConvertFromString("#0000FF"),
};
labelDefaultLua.MouseEnter += Common.UIElement_OnMouseEnter;
labelDefaultLua.MouseLeave += Common.UIElement_OnMouseLeave;
labelDefaultLua.MouseDown += LabelDefaultLuaOnMouseDown;

void LabelDefaultLuaOnMouseDown(object sender, MouseButtonEventArgs e)
{
try
{
var callingTextBox = (TextBox)((Label)sender).Tag;
callingTextBox.Text = Constants.ListEnvironmentSnippet;
SetFormState();
if (ButtonSend.IsEnabled)
{
SendCommand();
}
}
catch (Exception ex)
{
Common.ShowErrorMessageBox(ex);
}
}

labelDefaultLua.Tag = textBox;
StackPanelLinks.Children.Add(labelDefaultLua);
}

if (dcsAPIParameterType.Type == ParameterTypeEnum.number)
{
textBox.KeyDown += TextBoxParameter_OnKeyDown_Number;
Expand All @@ -110,7 +168,7 @@ protected override void BuildUI()
ButtonSend.Click += ButtonSend_OnClick;
controlList.Add(ButtonSend);

if (DCSAPI.ReturnsData)
if (DCSAPI.ReturnsData && !IsLuaConsole)
{
LabelKeepResults = new Label
{
Expand Down Expand Up @@ -191,8 +249,8 @@ public override void SetResult(DCSAPI dcsApi)
{
Dispatcher?.BeginInvoke((Action)(() => LabelResult.Content = $"Result ({dcsApi.ResultType})"));

var result = dcsApi.ErrorThrown ? dcsApi.ErrorMessage : (string.IsNullOrEmpty(dcsApi.Result) ? "nil" : dcsApi.Result);
var result = dcsApi.ErrorThrown ? dcsApi.ErrorMessage : string.IsNullOrEmpty(dcsApi.Result) ? "nil" : dcsApi.Result;

AutoResetEventPolling.Set();

if (result == DCSAPI.Result)
Expand Down
3 changes: 3 additions & 0 deletions src/client/DCSInsight/UserControls/UserControlAPIBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public abstract partial class UserControlAPIBase : UserControl, IDisposable, IAs
protected Label LabelPollingInterval;
protected ComboBox ComboBoxPollTimes;
protected static readonly AutoResetEvent AutoResetEventPolling = new(false);
private const string LuaConsole = "LuaConsole";
protected bool IsLuaConsole;

public int Id { get; protected set; }
protected abstract void BuildUI();
Expand All @@ -44,6 +46,7 @@ public abstract partial class UserControlAPIBase : UserControl, IDisposable, IAs
protected UserControlAPIBase(DCSAPI dcsAPI, bool isConnected)
{
DCSAPI = dcsAPI;
IsLuaConsole = DCSAPI.Syntax == LuaConsole;
Id = DCSAPI.Id;
IsConnected = isConnected;
PollingTimer = new Timer(PollingTimerCallback);
Expand Down
1 change: 1 addition & 0 deletions src/client/DCSInsight/Windows/WindowRangeTest.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public WindowRangeTest(List<DCSAPI> dcsAPIList)
{
InitializeComponent();
_dcsAPIList = dcsAPIList;
_dcsAPIList.RemoveAll(o => o.Syntax == "LuaConsole");
ICEventHandler.AttachErrorListener(this);
ICEventHandler.AttachConnectionListener(this);
ICEventHandler.AttachDataListener(this);
Expand Down
5 changes: 5 additions & 0 deletions src/server/Scripts/DCS-INSIGHT/ServerSettings.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,9 @@ ServerSettings.TCP_port = 7790
-- Log incoming and outgoing JSON
ServerSettings.Log_JSON = false

-- WARNING! This function enables arbitrary lua code to be
-- executed on your computer, including calls to package os (Operating System).
-- Do NOT enable unless your are firewalled.
ServerSettings.EnableLuaConsole = false

return ServerSettings
41 changes: 33 additions & 8 deletions src/server/Scripts/DCS-INSIGHT/lib/APIHandler.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
module("APIHandler", package.seeall)

local Log = require("Scripts.DCS-INSIGHT.lib.common.Log")
local ServerSettings = require("Scripts.DCS-INSIGHT.ServerSettings")
local CommonInsight = require("Scripts.DCS-INSIGHT.lib.common.Common")

local LoadStringAPI = require("Scripts.DCS-INSIGHT.lib.commands.LoadStringAPI")
local GetArgumentValueAPI = require("Scripts.DCS-INSIGHT.lib.commands.GetArgumentValueAPI")
local SetArgumentValueAPI = require("Scripts.DCS-INSIGHT.lib.commands.SetArgumentValueAPI")
local SetCommandAPI = require("Scripts.DCS-INSIGHT.lib.commands.SetCommandAPI")
Expand Down Expand Up @@ -69,7 +72,7 @@ local LoCoordinatesToGeoCoordinatesAPI = require("Scripts.DCS-INSIGHT.lib.comman
--- @field public apiTable table<APIInfo>
local APIHandler = {}

--- @func Returns new APIHandler
--- Returns new APIHandler
function APIHandler:new()
--- @type APIHandler
local o = {
Expand All @@ -87,7 +90,22 @@ local function counter()
return id
end

--- @func Fills the commands and api table with APIs having device_id as parameter
--- Adds the lua console
function APIHandler:addLuaConsole()
Log:log_simple(0)
if CommonInsight:tryRequire("Scripts.DCS-INSIGHT.ServerSettingsDevelopment") then
local ServerSettingsDevelopment = require("Scripts.DCS-INSIGHT.ServerSettingsDevelopment")
if ServerSettingsDevelopment.EnableLuaConsole then
self.commandsTable[#self.commandsTable + 1] = LoadStringAPI:new(nil, counter())
self.apiTable[#self.apiTable + 1] = self.commandsTable[#self.commandsTable].apiInfo
end
elseif ServerSettings.EnableLuaConsole then
self.commandsTable[#self.commandsTable + 1] = LoadStringAPI:new(nil, counter())
self.apiTable[#self.apiTable + 1] = self.commandsTable[#self.commandsTable].apiInfo
end
end

--- Fills the commands and api table with APIs having device_id as parameter
function APIHandler:addDeviceAPIs()
self.commandsTable[#self.commandsTable + 1] = GetArgumentValueAPI:new(nil, counter())
self.apiTable[#self.apiTable + 1] = self.commandsTable[#self.commandsTable].apiInfo
Expand All @@ -111,7 +129,7 @@ function APIHandler:addDeviceAPIs()
self.apiTable[#self.apiTable + 1] = self.commandsTable[#self.commandsTable].apiInfo
end

--- @func Fills the commands and api table with APIs taking parameters but not device_id
--- Fills the commands and api table with APIs taking parameters but not device_id
function APIHandler:addParameterAPIs()
self.commandsTable[#self.commandsTable + 1] = LoGetAircraftDrawArgumentValueAPI:new(nil, counter())
self.apiTable[#self.apiTable + 1] = self.commandsTable[#self.commandsTable].apiInfo
Expand All @@ -135,7 +153,7 @@ function APIHandler:addParameterAPIs()
self.apiTable[#self.apiTable + 1] = self.commandsTable[#self.commandsTable].apiInfo
end

--- @func Fills the commands and api table with APIs not taking parameters
--- Fills the commands and api table with APIs not taking parameters
function APIHandler:addParameterlessAPIs()
self.commandsTable[#self.commandsTable + 1] = ListCockpitParamsAPI:new(nil, counter())
self.apiTable[#self.apiTable + 1] = self.commandsTable[#self.commandsTable].apiInfo
Expand Down Expand Up @@ -278,21 +296,28 @@ function APIHandler:addParameterlessAPIs()
self.apiTable[#self.apiTable + 1] = self.commandsTable[#self.commandsTable].apiInfo
end

--- @func Fills the commands and api table
--- Fills the commands and api table
function APIHandler:init()
self:addLuaConsole()
self:addDeviceAPIs()
self:addParameterAPIs()
self:addParameterlessAPIs()
self:verify_entries()
end

--- @func Executes the command and returns a command containing the result
--- Executes the command and returns a command containing the result
--- @param api APIInfo
function APIHandler:execute(api)
for k, v in pairs(self.commandsTable) do
if api.id == v.id then
local result_code, result = pcall(v.execute, v, api) -- = v:execute(api)
if result_code == true then

if api.error_thrown then
if api.error_message == nil then
api.error_message = "Error but no error message"
end
return result
elseif result_code == true then
result.error_thrown = false
result.error_message = ""
return result
Expand All @@ -315,7 +340,7 @@ function APIHandler:execute(api)
end
end

--- @func Performs checks on registered api
--- Performs checks on registered api
--- @return boolean
function APIHandler:verify_entries()
local message = "Following api have been loaded :\n"
Expand Down
8 changes: 4 additions & 4 deletions src/server/Scripts/DCS-INSIGHT/lib/DCSInsight.lua
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ function LuaExportAfterNextFrame()
local currentTime = LoGetModelTime()

if currentTime >= lastStepTime then
local bool, err = pcall(step)
err = err or "something failed"
if not bool then
Log:log_simple("Listener.step() failed: " .. err)
local result_code, result = pcall(step)
result = result or "something failed"
if not result_code then
Log:log_simple("Listener.step() failed: " .. result)
end
lastStepTime = currentTime + 0.1
end
Expand Down
4 changes: 2 additions & 2 deletions src/server/Scripts/DCS-INSIGHT/lib/Listener.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ local ServerSettings = require("Scripts.DCS-INSIGHT.ServerSettings")
--- @field public ReadClientData function
local Listener = {}

--- @func Returns new Listener
--- Returns new Listener
--- @return Listener
function Listener:new(host, port, APIHandler)
local o = {
Expand Down Expand Up @@ -66,7 +66,7 @@ Listener.ReadClientData = function(str)
end
end

--- @func Initializes the TCPServer and APIHandler
--- Initializes the TCPServer and APIHandler
function Listener:init()
self.APIHandler:init()
self.tcpServer = TCPServer:new(self.host, self.port, socket, self.ReadClientData)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module("GetArgumentValueAPI", package.seeall)
module("GetArgumentValueInsightAPI", package.seeall)

local APIBase = require("Scripts.DCS-INSIGHT.lib.commands.common.APIBase")
local ParamName = require("Scripts.DCS-INSIGHT.lib.commands.common.ParamName")
Expand All @@ -9,7 +9,7 @@ local ParamType = require("Scripts.DCS-INSIGHT.lib.commands.common.ParamType")
--- @field apiInfo APIInfo
local GetArgumentValueAPI = APIBase:new()

--- @func Returns new GetArgumentValueAPI
--- Returns new GetArgumentValueAPI
--- @param o table|nil Parent
--- @param apiId integer API ID, must be unique
--- @return APIBase
Expand All @@ -24,10 +24,10 @@ function GetArgumentValueAPI:new(o, apiId)
return o
end

--- @func Inits with internal data
--- Inits with internal data
function GetArgumentValueAPI:init() end

--- @func Executes sent api and returns the same api containing a result field
--- Executes sent api and returns the same api containing a result field
--- @param api APIInfo
function GetArgumentValueAPI:execute(api)
local result_code, message = self:verify_params()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module("GetFrequencyAPI", package.seeall)
module("GetFrequencyInsightAPI", package.seeall)

local APIBase = require("Scripts.DCS-INSIGHT.lib.commands.common.APIBase")
local ParamName = require("Scripts.DCS-INSIGHT.lib.commands.common.ParamName")
Expand All @@ -9,7 +9,7 @@ local ParamType = require("Scripts.DCS-INSIGHT.lib.commands.common.ParamType")
--- @field apiInfo APIInfo
local GetFrequencyAPI = APIBase:new()

--- @func Returns new GetFrequencyAPI
--- Returns new GetFrequencyAPI
--- @param o table|nil Parent
--- @param apiId integer API ID, must be unique
--- @return APIBase
Expand All @@ -24,10 +24,10 @@ function GetFrequencyAPI:new(o, apiId)
return o
end

--- @func Inits with internal data
--- Inits with internal data
function GetFrequencyAPI:init() end

--- @func Executes sent api and returns the same api containing a result field
--- Executes sent api and returns the same api containing a result field
--- @param api APIInfo
function GetFrequencyAPI:execute(api)
local param0
Expand Down
Loading

0 comments on commit 1b4f225

Please sign in to comment.