76 Commits

Author SHA1 Message Date
VladMordock
255eb35e7f Merge pull request #14 from szporwolik/dev
v8.0.0 release move to master branch
2019-10-19 11:30:26 +02:00
VladMordock
22168d281f Merge branch 'master' into dev 2019-10-19 11:27:47 +02:00
szporowolik
1438e55686 v8.0 build 2019-10-19 11:24:12 +02:00
szporowolik
fd92b1c287 Updated readme - added information about db structure and multiinstance support within one database 2019-10-17 17:34:18 +02:00
szporowolik
548281a3d7 Updated lua script for v0.8 2019-10-17 17:27:58 +02:00
VladMordock
e8d3338d9b Update README.md
Minor update of the formatting
2019-10-17 17:24:13 +02:00
VladMordock
40302fed4b Update README.md
Added information about command line arguments
2019-10-17 17:17:24 +02:00
VladMordock
edc1133023 Update README.md
Updated readme to match v0.8
2019-10-17 17:06:13 +02:00
VladMordock
bdb89a4bf9 Update README.md
.NET Framework upgrade to 4.8
2019-10-17 16:57:39 +02:00
VladMordock
0bb396eae4 Update README.md
Updated data flow
2019-10-17 16:49:38 +02:00
VladMordock
f58c24be74 Update README.md
Flow chart update for TCP
2019-10-17 16:49:00 +02:00
VladMordock
a58eced7bf Update README.md
Updates to match v0.8 release
2019-10-17 16:39:17 +02:00
VladMordock
22d87b8a62 Update m1081_perun.sql 2019-10-17 16:36:23 +02:00
VladMordock
ff9ae98887 Update m1081_perun.sql
Sync with current status of the development database
2019-10-17 16:35:01 +02:00
szporowolik
44da46083e Added command line support for srs and lotatc 2019-10-04 14:48:29 +02:00
szporowolik
5916ccedb3 Debug only - check performance 2019-10-04 14:43:43 +02:00
szporowolik
35d63d072c Clean up 2019-10-04 14:21:21 +02:00
szporowolik
09d379d611 Added support for command line arguments 2019-10-04 14:17:15 +02:00
szporowolik
fcb189a4cd Reconnecting issue solved 2019-09-13 15:56:56 +02:00
szporowolik
9d42ccc1d4 General cleanup 2019-09-13 15:13:12 +02:00
szporowolik
238f6e29ae Working mysql connection icon 2019-09-13 13:31:03 +02:00
szporowolik
ddb2527eb8 Added icon resources 2019-09-13 13:30:44 +02:00
szporowolik
97a4c0aa45 Added connection status icons 2019-09-13 12:43:57 +02:00
szporowolik
4b975b1892 Added tango theme 2019-09-13 12:43:36 +02:00
szporowolik
74e227ae27 VS projecy update to 8.0.0 2019-09-13 12:32:05 +02:00
szporowolik
69501b4623 WIP 2019-09-13 12:28:40 +02:00
szporowolik
36c713ba3f Updated perun.lua for 8.0.0 2019-09-12 18:14:05 +02:00
szporowolik
17a2905b14 Readme update 2019-09-12 17:57:46 +02:00
szporowolik
df7155f061 Switched to TCP 2019-09-12 17:48:41 +02:00
szporowolik
52ecfda6c5 WIP - main form change 2019-09-12 16:00:53 +02:00
szporowolik
4900ef4888 WIP 2019-09-12 15:22:16 +02:00
szporowolik
150a9ab502 Added actual nuget references 2019-09-12 14:55:09 +02:00
szporowolik
d3ba6c008a Switched to .net 4.8.0 2019-09-12 14:34:37 +02:00
VladMordock
f1eb4b64d1 Added 5 minut time limit to remove spawn deads from mission stats 2019-08-28 01:05:04 +02:00
Szymon Porwolik
976feec650 Quick fix related to exception handler thrown while LotATC or SRS data cannot be usd. 2019-08-25 19:09:52 +02:00
Szymon Porwolik
073b9a72e2 Added support for 2 instances. 2019-08-24 22:03:32 +02:00
Szymon Porwolik
ad299b227b Changed MOTD dla gildia.org 2019-03-25 00:41:03 +01:00
Szymon Porwolik
7d3b99c1fd Fixed missing raw data when long slot list. 2019-03-25 00:38:32 +01:00
VladMordock
57771d94b7 Update Perun.lua
Fix for friendly fire not being properly logged
2019-03-15 10:26:31 +01:00
Szymon Porwolik
d1bedf3e1c Hotfix after changing db structure. 2019-03-11 23:25:44 +01:00
VladMordock
c4eb824c32 Update m1081_perun.sql
Updated to v0.5.4
2019-03-11 21:16:47 +01:00
Szymon Porwolik
ab1e19b340 Fixed for Fortification 2019-03-11 21:01:44 +01:00
VladMordock
ba646a6c22 Update DatabaseController.cs
- removed redundancy with slot type names
- removed DEBUG fields for DCS and Perun stats
2019-03-11 15:12:07 +01:00
VladMordock
7e8b01c2aa Update DatabaseController.cs
Added support for "Fortification" kill category.
2019-03-11 13:04:10 +01:00
VladMordock
7b907190f9 Update Perun.lua
Added support for "Fortification" kill category.
2019-03-11 13:04:06 +01:00
VladMordock
7f484bc1a1 Update Perun.lua
Sync
2019-03-11 01:58:01 +01:00
Szymon Porwolik
c053d5d461 - Fixed self_kills with colistion couted as teamkills.
-Added Landing_Other stat fild
2019-03-10 23:42:29 +01:00
Szymon Porwolik
5b3d19e134 Added OTHER_LANDINDS stats and fixed PvP kill counter 2019-03-10 22:48:51 +01:00
VladMordock
d885d2cd90 Update Perun.lua
Fixed landing at FARPs and SHIPs
2019-03-10 15:58:15 +01:00
Szymon Porwolik
9f50bb1397 Hotfix for Kill event 2019-03-10 15:19:53 +01:00
Szymon Porwolik
f7f688d1a5 Modified event log 2019-03-10 00:48:32 +01:00
Szymon Porwolik
81ff34014a Added stats support 2019-03-10 00:48:32 +01:00
Szymon Porwolik
9e0c515af0 Added stats support 2019-03-10 00:48:32 +01:00
Szymon Porwolik
9391d8778f Added stats suport 2019-03-10 00:48:32 +01:00
Szymon Porwolik
1cfe5a1ea9 Added stats support 2019-03-10 00:48:32 +01:00
Szymon Porwolik
8d1835f6f5 - MOTD will be send only to player who is joining
- after mission end mission hash will be set to ""
2019-03-10 00:48:32 +01:00
Szymon Porwolik
3be5a8765f v0.4.1 Lua and DB modification to support multiple instances od DCS World 2019-03-03 15:38:18 +01:00
VladMordock
0f01624380 Update README.md 2019-03-03 13:23:49 +01:00
Szymon Porwolik
3ff2fff728 v0.4.0 major code cleanup 2019-03-01 02:09:06 +01:00
Szymon Porwolik
f383f3c056 Added #4 - only one instance will be allowed to run 2019-03-01 02:09:06 +01:00
Szymon Porwolik
69f995bd6d Basic error proofing for UDP (port al;ready in use) and MySQL (connection/access issues). 2019-03-01 02:09:06 +01:00
Szymon Porwolik
64a550e8e8 Project cleanup 2019-03-01 02:09:06 +01:00
Szymon Porwolik
31ed9ee875 Updated MySQL DB to v0.4.0 2019-03-01 02:09:06 +01:00
Szymon Porwolik
0722a9ca26 Updated README 2019-03-01 02:09:06 +01:00
Szymon Porwolik
a21bbd4459 Version updated to v0.4.0 2019-03-01 02:09:06 +01:00
Szymon Porwolik
4ff546b105 Improved, fixed #3 2019-03-01 02:09:06 +01:00
Szymon Porwolik
2463d4267d Fixed #10 2019-03-01 02:09:06 +01:00
Szymon Porwolik
6b37b05dbf Fixed #6 2019-03-01 02:09:06 +01:00
Szymon Porwolik
d34fdf00b3 Fixed formatting on sending Mission start/Mission end event 2019-02-28 19:49:26 +01:00
simpo
37543ec167 Fixed #8
Fixed polish characters, code clean up
2019-02-27 09:32:00 +01:00
simpo
7dda6a224d Update README.md 2019-02-27 08:38:53 +01:00
simpo
993ae2a755 Rename perun_export.json to perun_status_data.json 2019-02-27 01:51:23 +01:00
simpo
c79dc039e6 Fixed #7
For one mission lua2net keeps crashing - no possiblity for full lua2json export
2019-02-27 01:50:51 +01:00
simpo
a26c9d8f08 Update README.md 2019-02-26 23:27:43 +01:00
simpo
f55a117051 Fixed #1, #7
Additionaly diagostic package will carry total players connected as well.
2019-02-26 23:24:10 +01:00
simpo
e05cee514c Update Perun.lua
Fixed bug with JSON file not being generated.
2019-02-25 23:20:43 +01:00
33 changed files with 2018 additions and 1002 deletions

View File

@@ -1,40 +1,132 @@
-- Perun for DCS World https://github.com/szporwolik/perun -> DCS Hook component -- Perun for DCS World https://github.com/szporwolik/perun -> DCS Hook component
-- Initial init -- Initial init
local Perun = {} local Perun = {}
package.path = package.path..";"..lfs.currentdir().."/LuaSocket/?.lua" package.path = package.path..";"..lfs.currentdir().."/LuaSocket/?.lua"
package.cpath = package.cpath..";"..lfs.currentdir().."/LuaSocket/?.dll" package.cpath = package.cpath..";"..lfs.currentdir().."/LuaSocket/?.dll"
-- ########### SETTINGS ########### -- ###################### SETTINGS - DO NOT MODIFY OUTSIDE THIS SECTION #############################
Perun.RefreshStatus = 15 -- base refresh rate in seconds to send status update (values lower than 60 may affect performance!) Perun.RefreshStatus = 15 -- (int) base refresh rate in seconds to send status update (values lower than 60 may affect performance!)
Perun.RefreshMission = 60 -- refresh rate in seconds to send mission information (values lower than 60 may affect performance!) Perun.RefreshMission = 60 -- (int) refresh rate in seconds to send mission information (values lower than 60 may affect performance!)
Perun.JsonLocation = "Scripts\\Json\\perun_export.json" -- relatve do user's SaveGames DCS folder Perun.TCPTargetPort = 48621 -- (int) TCP port to send data to
Perun.UDPTargetPort = 48620 -- UDP port to send data to Perun.TCPPerunHost = "localhost" -- (string) IP adress of the Perun instance or "localhost"
Perun.MOTD_L1 = "Witamy na serwerze Gildia.org !" -- Message send to players connecting the server - Line 1 Perun.Instance = 1 -- (int) Id number of instance (if multiple DCS instances are to run at the same PC)
Perun.MOTD_L2 = "Wymagamy obecnosci na 255Mhz (DCS SRS)" -- Message send to players connecting the server - Line 2 Perun.JsonStatusLocation = "Scripts\\Json\\" -- (string) folder relative do user's SaveGames DCS folder -> status file updated each RefreshMission
Perun.MOTD_L1 = "Welcome to our server!" -- (string) Message send to players connecting the server - Line 1
Perun.MOTD_L2 = "Please use SRS radio." -- (string) Message send to players connecting the server - Line 2
-- ###################### END OF SETTINGS - DO NOT MODIFY OUTSIDE THIS SECTION ######################
-- ########### END OF SETTINGS ###########
-- Variable init -- Variable init
Perun.Version = "v0.3.6" Perun.Version = "v0.8.0"
Perun.StatusData = {} Perun.StatusData = {}
Perun.SlotsData = {} Perun.SlotsData = {}
Perun.MissionData = {} Perun.MissionData = {}
Perun.VersionData = {} Perun.ServerData = {}
Perun.MissionHash="" Perun.StatData = {}
Perun.lastSentStatus =0 Perun.StatDataLastType = {}
Perun.lastSentMission =0 Perun.MissionHash=""
Perun.JsonLocation = lfs.writedir() .. Perun.JsonLocation Perun.lastSentStatus =0
Perun.socket = require("socket") Perun.lastSentMission =0
Perun.UDP = assert(Perun.socket.udp()) Perun.JsonStatusLocation = lfs.writedir() .. Perun.JsonStatusLocation
Perun.UDP:settimeout(0) Perun.socket = require("socket")
Perun.UDP:setsockname("*", 48621) Perun.IsServer = true --DCS.isServer( ) -- TBD looks like DCS API error, always returning True
Perun.UDP:setpeername("127.0.0.1",Perun.UDPTargetPort) Perun.TCPSourcePort = Perun.TCPTargetPort + 10 + Perun.Instance - 1
-- Function definition -- ########### Helper function definitions ###########
Perun.GetCategory = function(id) function stripChars(str)
-- via https://pastebin.com/GUAXrd2U -- remove accents characters from string
-- via https://stackoverflow.com/questions/50459102/replace-accented-characters-in-string-to-standard-with-lua TBD: rewrite
tableAccents = {}
tableAccents["à"] = "a"
tableAccents["á"] = "a"
tableAccents["â"] = "a"
tableAccents["ã"] = "a"
tableAccents["ä"] = "a"
tableAccents["ç"] = "c"
tableAccents["è"] = "e"
tableAccents["é"] = "e"
tableAccents["ê"] = "e"
tableAccents["ë"] = "e"
tableAccents["ì"] = "i"
tableAccents["í"] = "i"
tableAccents["î"] = "i"
tableAccents["ï"] = "i"
tableAccents["ñ"] = "n"
tableAccents["ò"] = "o"
tableAccents["ó"] = "o"
tableAccents["ô"] = "o"
tableAccents["õ"] = "o"
tableAccents["ö"] = "o"
tableAccents["ù"] = "u"
tableAccents["ú"] = "u"
tableAccents["û"] = "u"
tableAccents["ü"] = "u"
tableAccents["ý"] = "y"
tableAccents["ÿ"] = "y"
tableAccents["À"] = "A"
tableAccents["Á"] = "A"
tableAccents["Â"] = "A"
tableAccents["Ã"] = "A"
tableAccents["Ä"] = "A"
tableAccents["Ç"] = "C"
tableAccents["È"] = "E"
tableAccents["É"] = "E"
tableAccents["Ê"] = "E"
tableAccents["Ë"] = "E"
tableAccents["Ì"] = "I"
tableAccents["Í"] = "I"
tableAccents["Î"] = "I"
tableAccents["Ï"] = "I"
tableAccents["Ñ"] = "N"
tableAccents["Ò"] = "O"
tableAccents["Ó"] = "O"
tableAccents["Ô"] = "O"
tableAccents["Õ"] = "O"
tableAccents["Ö"] = "O"
tableAccents["Ù"] = "U"
tableAccents["Ú"] = "U"
tableAccents["Û"] = "U"
tableAccents["Ü"] = "U"
tableAccents["Ý"] = "Y"
-- Polish accents
tableAccents["ę"] = "e"
tableAccents["Ę"] = "Ę"
tableAccents["ó"] = "o"
tableAccents["Ó"] = "O"
tableAccents["ą"] = "a"
tableAccents["Ą"] = "A"
tableAccents["ś"] = "s"
tableAccents["Ś"] = "S"
tableAccents["ć"] = "c"
tableAccents["Ć"] = "C"
tableAccents["ż"] = "z"
tableAccents["Ż"] = "Z"
tableAccents["ź"] = "z"
tableAccents["Ź"] = "Z"
tableAccents["ł"] = "l"
tableAccents["Ł"] = "L"
-- TBD additonal characters
normalizedString = ''
for strChar in string.gmatch(str, "([%z\1-\127\194-\244][\128-\191]*)") do
if tableAccents[strChar] ~= nil then
normalizedString = normalizedString..tableAccents[strChar]
else
normalizedString = normalizedString..strChar
end
end
return normalizedString
end
Perun.GetCategory = function(id)
-- Returns object category basing on ID
-- Helper function via https://pastebin.com/GUAXrd2U TBD: rewrite
local _killed_target_category = DCS.getUnitTypeAttribute(id, "category") local _killed_target_category = DCS.getUnitTypeAttribute(id, "category")
if _killed_target_category == nil then if _killed_target_category == nil then
local _killed_target_cat_check_ship = DCS.getUnitTypeAttribute(id, "DeckLevel") local _killed_target_cat_check_ship = DCS.getUnitTypeAttribute(id, "DeckLevel")
@@ -48,68 +140,99 @@
end end
end end
return _killed_target_category return _killed_target_category
end end
Perun.SideID2Name = function(id) Perun.SideID2Name = function(id)
-- Helper function -- Helper function returns side name per side (coalition) id
local sides = { local sides = {
[0] = 'SPECTATOR', [0] = 'SPECTATOR',
[1] = 'RED', [1] = 'RED',
[2] = 'BLUE', [2] = 'BLUE',
} }
return sides[id] return sides[id]
end end
Perun.AddLog = function(text) -- ########### Main code ###########
Perun.AddLog = function(text)
-- Adds logs to DCS.log file -- Adds logs to DCS.log file
net.log("Perun : ".. text) net.log("Perun : ".. text)
end end
Perun.UpdateJson = function() Perun.ConnectToPerun = function ()
-- Updates main json file Perun.AddLog("Connecting to TCP server")
Perun.TCP = assert(Perun.socket.tcp())
Perun.TCP:settimeout(2000)
_, err = Perun.TCP:connect(Perun.TCPPerunHost, Perun.TCPTargetPort)
if err then
Perun.AddLog("TCP connection error : " .. err)
else
Perun.AddLog("Connected to TCP server")
end
end
Perun.SendPacket = function (data_id,temp)
_, err = Perun.TCP:send(temp)
if err then
Perun.AddLog("Packed drop " .. data_id .. ", error: " .. err)
Perun.ConnectToPerun()
else
Perun.AddLog("Packet send " .. data_id)
end
end
Perun.UpdateJsonStatus = function()
-- Updates status json file
TempData={} TempData={}
TempData["1"]=Perun.VersionData TempData["1"]=Perun.ServerData
TempData["2"]=Perun.StatusData TempData["2"]=Perun.StatusData
TempData["3"]=Perun.SlotsData TempData["3"]=Perun.SlotsData
TempData["4"]=Perun.MissionData -- TempData["4"]=Perun.MissionData -- TBD: hangs for some large missions
TempData["debug"]=net.get_player_list()
io.open(Perun.JsonLocation,"w"):close() _temp=net.lua2json(TempData)
perun_export = io.open(Perun.JsonLocation, "w")
perun_export:write(net.lua2json(TempData) .. "\n") perun_export = io.open(Perun.JsonStatusLocation .. "perun_status_data.json", "w")
perun_export:write(_temp .. "\n")
perun_export:close() perun_export:close()
end end
Perun.Send = function(data_id, data_package) Perun.Send = function(data_id, data_package)
-- Sends data package -- Sends data package
TempData={} TempData={}
TempData["type"]=data_id TempData["type"]=data_id
TempData["payload"]=data_package TempData["payload"]=data_package
TempData["timestamp"]=os.date('%Y-%m-%d %H:%M:%S')
TempData["instance"]=Perun.Instance
temp=net.lua2json(TempData) temp=net.lua2json(TempData)
Perun.UDP:send(temp) temp=stripChars(temp)
Perun.AddLog("Packet send")
end
Perun.UpdateStatusPart = function(part_id, data_package) Perun.SendPacket(data_id,temp)
end
Perun.UpdateStatusPart = function(part_id, data_package)
-- Helper for status update container -- Helper for status update container
Perun.StatusData[part_id] = data_package Perun.StatusData[part_id] = data_package
end end
Perun.UpdateVersion = function() Perun.UpdateStatus = function()
-- Main function for debug/version information
-- Update Mission data
Perun.VersionData['v_dcs_hook']=Perun.Version
-- Send
Perun.Send(1,Perun.VersionData)
end
Perun.UpdateStatus = function()
-- Main function for status updates -- Main function for status updates
-- Update all subsections -- Diagnostic data
-- Update version data
Perun.ServerData['v_dcs_hook']=Perun.Version
-- Update server data
_table=net.get_player_list()
_count = 0
for _ in pairs(_table) do _count = _count + 1 end
Perun.ServerData['c_players']=_count
-- Send
Perun.Send(1,Perun.ServerData)
-- Status data - update all subsections
-- 1 - Mission -- 1 - Mission
temp={} temp={}
temp['name']=DCS.getMissionName() temp['name']=DCS.getMissionName()
@@ -124,17 +247,13 @@
-- 2 - Players -- 2 - Players
_temp = net.get_player_list() _temp = net.get_player_list()
_temp2={} _temp2={}
for _, i in pairs(_temp) do for k, i in ipairs(_temp) do
_temp2[i]=net.get_player_info(i) _temp2[k]=net.get_player_info(i)
end end
Perun.UpdateStatusPart("players",_temp2) Perun.UpdateStatusPart("players",_temp2)
-- Send -- Send
Perun.Send(2,Perun.StatusData) Perun.Send(2,Perun.StatusData)
end
Perun.UpdateSlots = function()
-- Main function for slot
-- Update slots data -- Update slots data
Perun.SlotsData['coalitions']=DCS.getAvailableCoalitions() Perun.SlotsData['coalitions']=DCS.getAvailableCoalitions()
@@ -142,72 +261,202 @@
for j, i in pairs(Perun.SlotsData['coalitions']) do for j, i in pairs(Perun.SlotsData['coalitions']) do
Perun.SlotsData['slots'][j]=DCS.getAvailableSlots(j) Perun.SlotsData['slots'][j]=DCS.getAvailableSlots(j)
for sj, si in pairs(Perun.SlotsData['slots'][j]) do
Perun.SlotsData['slots'][j][sj]['countryName']= nil
Perun.SlotsData['slots'][j][sj]['onboard_num']= nil
Perun.SlotsData['slots'][j][sj]['groupSize']= nil
Perun.SlotsData['slots'][j][sj]['groupName']= nil
Perun.SlotsData['slots'][j][sj]['callsign']= nil
Perun.SlotsData['slots'][j][sj]['task']= nil
Perun.SlotsData['slots'][j][sj]['airdromeId']= nil
Perun.SlotsData['slots'][j][sj]['helipadName']= nil
end
end end
-- Send -- Send
Perun.Send(3,Perun.SlotsData) Perun.Send(3,Perun.SlotsData)
end end
Perun.UpdateMission = function()
Perun.UpdateMission = function()
-- Main function for mission information updates -- Main function for mission information updates
-- Update Mission data
Perun.MissionData=DCS.getCurrentMission() Perun.MissionData=DCS.getCurrentMission()
-- Send
-- Perun.Send(4,Perun.MissionData) -- Perun.Send(4,Perun.MissionData)
end end
Perun.LogChat = function(playerID,msg,all) Perun.LogChat = function(playerID,msg,all)
-- Log chat messages -- Log chat messages
data={} data={}
data['player']= net.get_player_info(playerID, "name") data['player']= net.get_player_info(playerID, "name")
data['msg']=msg data['msg']=stripChars(msg)
data['all']=all data['all']=all
data['ucid']=net.get_player_info(playerID, 'ucid') data['ucid']=net.get_player_info(playerID, 'ucid')
data['datetime']=os.date('%Y-%m-%d %H:%M:%S') data['datetime']=os.date('%Y-%m-%d %H:%M:%S')
data['missionhash']=Perun.MissionHash data['missionhash']=Perun.MissionHash
Perun.Send(50,data) Perun.Send(50,data)
end end
Perun.LogEvent = function(log_type,log_content) Perun.LogEvent = function(log_type,log_content,log_arg_1,log_arg_2)
-- Log chat messages -- Log chat messages
data={} data={}
data['log_type']= log_type data['log_type']= log_type
data['log_arg_1']= log_arg_1
data['log_arg_2']= log_arg_2
data['log_content']=log_content data['log_content']=log_content
data['log_datetime']=os.date('%Y-%m-%d %H:%M:%S') data['log_datetime']=os.date('%Y-%m-%d %H:%M:%S')
data['log_missionhash']=Perun.MissionHash data['log_missionhash']=Perun.MissionHash
Perun.Send(51,data) Perun.Send(51,data)
end
Perun.LogStatsCount = function(argPlayerID,argAction,argType)
-- Creates or updates Perun statistics array
_ucid=net.get_player_info(argPlayerID, 'ucid')..argType
if Perun.StatData[_ucid] == nil then
-- Create empty element
_temp={}
_temp['ps_type'] = argType
_temp['ps_pvp'] = 0
_temp['ps_deaths'] = 0
_temp['ps_ejections'] = 0
_temp['ps_crashes'] = 0
_temp['ps_teamkills'] = 0
_temp['ps_kills_planes'] = 0
_temp['ps_kills_helicopters'] = 0
_temp['ps_kills_air_defense'] = 0
_temp['ps_kills_armor'] = 0
_temp['ps_kills_unarmed'] = 0
_temp['ps_kills_infantry'] = 0
_temp['ps_kills_ships'] = 0
_temp['ps_kills_fortification'] = 0
_temp['ps_kills_other'] = 0
_temp['ps_airfield_takeoffs'] = 0
_temp['ps_airfield_landings'] = 0
_temp['ps_ship_takeoffs'] = 0
_temp['ps_ship_landings'] = 0
_temp['ps_farp_takeoffs'] = 0
_temp['ps_farp_landings'] = 0
_temp['ps_other_takeoffs'] = 0
_temp['ps_other_landings'] = 0
Perun.StatData[_ucid]=_temp
end end
Perun.LogStats = function(playerID) if argType ~= nil then
Perun.StatData[_ucid]['ps_type']=argType;
Perun.StatDataLastType[net.get_player_info(argPlayerID, 'ucid')]=_ucid
else
-- Do nothing
end
if argAction == "eject" then
Perun.StatData[_ucid]['ps_ejections']=Perun.StatData[_ucid]['ps_ejections']+1
elseif argAction == "pilot_death" then
if DCS.getModelTime() > 300 then
Perun.StatData[_ucid]['ps_deaths']=Perun.StatData[_ucid]['ps_deaths']+1
end
elseif argAction == "friendly_fire" then
Perun.StatData[_ucid]['ps_teamkills']=Perun.StatData[_ucid]['ps_teamkills']+1
elseif argAction == "crash" then
Perun.StatData[_ucid]['ps_crashes']=Perun.StatData[_ucid]['ps_crashes']+1
elseif argAction == "landing_FARP" then
Perun.StatData[_ucid]['ps_farp_landings']=Perun.StatData[_ucid]['ps_farp_landings']+1
elseif argAction == "landing_SHIP" then
Perun.StatData[_ucid]['ps_ship_landings']=Perun.StatData[_ucid]['ps_ship_landings']+1
elseif argAction == "landing_AIRFIELD" then
Perun.StatData[_ucid]['ps_airfield_landings']=Perun.StatData[_ucid]['ps_airfield_landings']+1
elseif argAction == "tookoff_FARP" then
Perun.StatData[_ucid]['ps_farp_takeoffs']=Perun.StatData[_ucid]['ps_farp_takeoffs']+1
elseif argAction == "tookoff_SHIP" then
Perun.StatData[_ucid]['ps_ship_takeoffs']=Perun.StatData[_ucid]['ps_ship_takeoffs']+1
elseif argAction == "tookoff_AIRFIELD" then
Perun.StatData[_ucid]['ps_airfield_takeoffs']=Perun.StatData[_ucid]['ps_airfield_takeoffs']+1
elseif argAction == "kill_Planes" then
Perun.StatData[_ucid]['ps_kills_planes']=Perun.StatData[_ucid]['ps_kills_planes']+1
elseif argAction == "kill_Helicopters" then
Perun.StatData[_ucid]['ps_kills_helicopters']=Perun.StatData[_ucid]['ps_kills_helicopters']+1
elseif argAction == "kill_Ships" then
Perun.StatData[_ucid]['ps_kills_ships']=Perun.StatData[_ucid]['ps_kills_ships']+1
elseif argAction == "kill_Air_Defence" then
Perun.StatData[_ucid]['ps_kills_air_defense']=Perun.StatData[_ucid]['ps_kills_air_defense']+1
elseif argAction == "kill_Unarmed" then
Perun.StatData[_ucid]['ps_kills_unarmed']=Perun.StatData[_ucid]['ps_kills_unarmed']+1
elseif argAction == "kill_Armor" then
Perun.StatData[_ucid]['ps_kills_armor']=Perun.StatData[_ucid]['ps_kills_armor']+1
elseif argAction == "kill_Infantry" then
Perun.StatData[_ucid]['ps_kills_infantry']=Perun.StatData[_ucid]['ps_kills_infantry']+1
elseif argAction == "kill_Fortification" then
Perun.StatData[_ucid]['ps_kills_fortification']=Perun.StatData[_ucid]['ps_kills_fortification']+1
elseif argAction == "kill_Other" then
Perun.StatData[_ucid]['ps_kills_other']=Perun.StatData[_ucid]['ps_kills_other']+1
elseif argAction == "kill_PvP" then
Perun.StatData[_ucid]['ps_pvp']=Perun.StatData[_ucid]['ps_pvp']+1
elseif argAction == "landing_OTHER" then
Perun.StatData[_ucid]['ps_other_landings']=Perun.StatData[_ucid]['ps_other_landings']+1
elseif argAction == "tookoff_OTHER" then
Perun.StatData[_ucid]['ps_other_takeoffs']=Perun.StatData[_ucid]['ps_other_takeoffs']+1
end
Perun.LogStats(argPlayerID);
end
Perun.LogStatsGet = function(playerID)
-- Gets Perun statistics array per player
local next = next
if next(Perun.StatDataLastType) == nil then
_ucid=net.get_player_info(playerID, 'ucid')..DCS.getUnitType(playerID)
elseif Perun.StatDataLastType[net.get_player_info(playerID, 'ucid')]== nil then
_ucid=net.get_player_info(playerID, 'ucid')..DCS.getUnitType(playerID)
else
_ucid=Perun.StatDataLastType[net.get_player_info(playerID, 'ucid')]
end
local next = next
if next(Perun.StatData) == nil then
Perun.LogStatsCount(playerID,'init')
end
if Perun.StatData[_ucid]== nil then
Perun.LogStatsCount(playerID,'init')
end
return Perun.StatData[_ucid];
end
Perun.LogStats = function(playerID)
-- Log player status -- Log player status
-- TBD : not working at the moment WIP -- TBD : DCS stats not working at the moment WIP
p_stats={} p_stats_dcs={}
p_stats['PS_CAR']=net.get_stat(playerID,2) p_stats_dcs['PS_CAR']=net.get_stat(playerID,2)
p_stats['PS_PLANE']=net.get_stat(playerID,3) p_stats_dcs['PS_PLANE']=net.get_stat(playerID,3)
p_stats['PS_SHIP']=net.get_stat(playerID,4) p_stats_dcs['PS_SHIP']=net.get_stat(playerID,4)
p_stats['PS_SCORE']=net.get_stat(playerID,5) p_stats_dcs['PS_SCORE']=net.get_stat(playerID,5)
p_stats['PS_LAND']=net.get_stat(playerID,6) p_stats_dcs['PS_LAND']=net.get_stat(playerID,6)
p_stats['PS_PING']=net.get_stat(playerID,0) p_stats_dcs['PS_PING']=net.get_stat(playerID,0)
p_stats['PS_CRASH']=net.get_stat(playerID,1) p_stats_dcs['PS_CRASH']=net.get_stat(playerID,1)
p_stats['PS_EJECT']=net.get_stat(playerID,7) p_stats_dcs['PS_EJECT']=net.get_stat(playerID,7)
p_stats['debug']="ok"
_temp=Perun.LogStatsGet(playerID)
data={} data={}
data['stat_data']=p_stats data['stat_data_dcs']=p_stats_dcs
data['stat_data_perun']=_temp
data['stat_data_type']=_temp['ps_type'];
data['stat_ucid']=net.get_player_info(playerID, 'ucid') data['stat_ucid']=net.get_player_info(playerID, 'ucid')
data['stat_datetime']=os.date('%Y-%m-%d %H:%M:%S') data['stat_datetime']=os.date('%Y-%m-%d %H:%M:%S')
data['stat_missionhash']=Perun.MissionHash data['stat_missionhash']=Perun.MissionHash
Perun.Send(52,data) Perun.Send(52,data)
end end
Perun.LogLogin = function(playerID) Perun.LogLogin = function(playerID)
-- Player logged in -- Player logged in
data={} data={}
@@ -217,99 +466,134 @@
data['login_datetime']=os.date('%Y-%m-%d %H:%M:%S') data['login_datetime']=os.date('%Y-%m-%d %H:%M:%S')
Perun.Send(53,data) Perun.Send(53,data)
end end
--- Event callbacks --- ########### Event callbacks ###########
Perun.onSimulationStart = function() Perun.onSimulationStart = function()
Perun.MissionHash=DCS.getMissionName( ).."@"..os.date('%Y%m%d_%H%M%S'); Perun.MissionHash=DCS.getMissionName( ).."@".. Perun.Instance .. "@"..os.date('%Y%m%d_%H%M%S');
Perun.LogEvent("SimStart","Mission" .. Perun.MissionHash .. " started"); Perun.LogEvent("SimStart","Mission " .. Perun.MissionHash .. " started",nil,nil);
end Perun.StatData = {}
Perun.StatDataLastType = {}
end
Perun.onSimulationStop = function() Perun.onSimulationStop = function()
Perun.LogEvent("SimStop","Mission" .. Perun.MissionHash .. " finished"); Perun.LogEvent("SimStop","Mission " .. Perun.MissionHash .. " finished",nil,nil);
end Perun.MissionHash="";
Perun.StatData = {}
Perun.StatDataLastType = {}
end
Perun.onPlayerDisconnect= function(id, err_code) Perun.onPlayerDisconnect = function(id, err_code)
Perun.LogEvent("disconnect", "Player " .. net.get_player_info(id, "name") .. " disconnected; " .. err_code); Perun.LogEvent("disconnect", "Player " .. net.get_player_info(id, "name") .. " disconnected; " .. err_code,net.get_player_info(id, "name"),err_code);
end end
Perun.onSimulationFrame = function() Perun.onSimulationFrame = function()
local _now = DCS.getRealTime() local _now = DCS.getRealTime()
-- First run
if Perun.lastSentMission ==0 and Perun.lastSentStatus ==0 then
Perun.UpdateMission()
end
-- Send mission update and update JSON
if _now > Perun.lastSentMission + Perun.RefreshMission then
Perun.lastSentMission = _now
Perun.UpdateMission()
Perun.UpdateJsonStatus()
end
-- Send status update -- Send status update
if _now > Perun.lastSentStatus + Perun.RefreshStatus then if _now > Perun.lastSentStatus + Perun.RefreshStatus then
Perun.lastSentStatus = _now Perun.lastSentStatus = _now
Perun.UpdateStatus() Perun.UpdateStatus()
Perun.UpdateJson()
end end
end
-- Send mission update Perun.onPlayerStart = function (id)
if _now > Perun.lastSentMission + Perun.RefreshMission then net.send_chat_to(Perun.MOTD_L1, id);
Perun.lastSentMission = _now net.send_chat_to(Perun.MOTD_L2, id);
end
Perun.UpdateSlots() Perun.onPlayerTrySendChat = function (playerID, msg, all)
Perun.UpdateMission()
Perun.UpdateJson()
end
end
Perun.onMissionLoadEnd = function()
Perun.UpdateMission()
Perun.UpdateSlots()
Perun.UpdateVersion()
Perun.UpdateJson()
end
Perun.onPlayerStart = function (id)
net.send_chat(Perun.MOTD_L1, id);
net.send_chat(Perun.MOTD_L2, id);
end
Perun.onPlayerTrySendChat = function (playerID, msg, all)
if msg~=Perun.MOTD_L1 and msg~=Perun.MOTD_L2 then if msg~=Perun.MOTD_L1 and msg~=Perun.MOTD_L2 then
Perun.LogChat(playerID,msg,all) Perun.LogChat(playerID,msg,all)
end end
return msg return msg
end end
Perun.onGameEvent = function (eventName,arg1,arg2,arg3,arg4,arg5,arg6,arg7)
Perun.onGameEvent = function (eventName,arg1,arg2,arg3,arg4,arg5,arg6,arg7)
if eventName == "friendly_fire" then if eventName == "friendly_fire" then
--"friendly_fire", playerID, weaponName, victimPlayerID --"friendly_fire", playerID, weaponName, victimPlayerID
Perun.LogEvent(eventName,Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name").." killed friendy " .. net.get_player_info(arg3, "name") .. " using " .. arg2); if arg2 == "" then
Perun.LogStats(arg1); arg2 = "Cannon"
end
Perun.LogEvent(eventName,Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name").." killed friendy " .. net.get_player_info(arg3, "name") .. " using " .. arg2,nil,nil);
if arg1 ~= arg3 then
-- Perun.LogStatsCount(arg1,"friendly_fire",DCS.getUnitType(net.get_player_info(arg1 , 'slot')))
end
elseif eventName == "mission_end" then elseif eventName == "mission_end" then
--"mission_end", winner, msg --"mission_end", winner, msg
Perun.LogEvent(eventName,"Mission finished, winner " .. arg1 .. " message: " .. arg2); Perun.LogEvent(eventName,"Mission finished, winner " .. arg1 .. " message: " .. arg2,nil,nil);
elseif eventName == "kill" then elseif eventName == "kill" then
--"kill", killerPlayerID, killerUnitType, killerSide, victimPlayerID, victimUnitType, victimSide, weaponName --"kill", killerPlayerID, killerUnitType, killerSide, victimPlayerID, victimUnitType, victimSide, weaponName
_tempX=""
if net.get_player_info(arg4, "name") ~= nil then if net.get_player_info(arg4, "name") ~= nil then
_temp = " player ".. net.get_player_info(arg4, "name") .." "; _tempX = " player ".. net.get_player_info(arg4, "name") .." ";
Perun.LogStats(arg4); Perun.LogStats(arg4);
else else
_temp = " AI "; _tempX = " AI ";
end end
if net.get_player_info(arg1, "name") ~= nil then if net.get_player_info(arg1, "name") ~= nil then
_temp2 = " player ".. net.get_player_info(arg1, "name") .." "; _temp2 = " player ".. net.get_player_info(arg1, "name") .." ";
Perun.LogStats(arg1); if Perun.GetCategory(arg5) == "Planes" then
Perun.LogStatsCount(arg1,"kill_Planes",arg2)
elseif Perun.GetCategory(arg5) == "Helicopters" then
Perun.LogStatsCount(arg1,"kill_Helicopters",arg2)
elseif Perun.GetCategory(arg5) == "Ships" then
Perun.LogStatsCount(arg1,"kill_Ships",arg2)
elseif Perun.GetCategory(arg5) == "Air Defence" then
Perun.LogStatsCount(arg1,"kill_Air_Defence",arg2)
elseif Perun.GetCategory(arg5) == "Unarmed" then
Perun.LogStatsCount(arg1,"kill_Unarmed",arg2)
elseif Perun.GetCategory(arg5) == "Armor" then
Perun.LogStatsCount(arg1,"kill_Armor",arg2)
elseif Perun.GetCategory(arg5) == "Infantry" then
Perun.LogStatsCount(arg1,"kill_Infantry",arg2)
elseif Perun.GetCategory(arg5) == "Fortification" then
Perun.LogStatsCount(arg1,"kill_Fortification",arg2)
else
Perun.LogStatsCount(arg1,"kill_Other",arg2)
end
if net.get_player_info(arg4, "name") ~= nil and arg3 ~= arg6 then
Perun.LogStatsCount(arg1,"kill_PvP",arg2)
end
if arg3 == arg6 then
Perun.LogStatsCount(arg1,"friendly_fire",arg2)
end
else else
_temp2 = " AI "; _temp2 = " AI ";
end end
Perun.LogEvent(eventName,Perun.SideID2Name(arg3) .. _temp2 .. " in " .. arg2 .. " killed " .. Perun.SideID2Name(arg6) .. _temp .. " in " .. arg5 .. " using " .. arg7 .. " [".. Perun.GetCategory(arg5).."]"); if arg7 == "" then
arg7 = "Cannon"
end
Perun.LogEvent(eventName,Perun.SideID2Name(arg3) .. _temp2 .. " in " .. arg2 .. " killed " .. Perun.SideID2Name(arg6) .. _tempX .. " in " .. arg5 .. " using " .. arg7 .. " [".. Perun.GetCategory(arg5).."]",arg7,Perun.GetCategory(arg5));
elseif eventName == "self_kill" then elseif eventName == "self_kill" then
--"self_kill", playerID --"self_kill", playerID
Perun.LogEvent(eventName,net.get_player_info(arg1, "name") .. " killed himself"); Perun.LogEvent(eventName,net.get_player_info(arg1, "name") .. " killed himself",nil,nil);
Perun.LogStats(arg1); Perun.LogStats(arg1);
elseif eventName == "change_slot" then elseif eventName == "change_slot" then
@@ -321,60 +605,81 @@
_temp = "SPECTATOR"; _temp = "SPECTATOR";
end end
Perun.LogEvent(eventName,Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name") .. " changed slot to " .. _temp); Perun.LogEvent(eventName,Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name") .. " changed slot to " .. _temp,nil,nil);
Perun.LogStats(arg1); Perun.LogStatsCount(arg1,"init",_temp)
elseif eventName == "connect" then elseif eventName == "connect" then
--"connect", playerID, name --"connect", playerID, name
Perun.LogLogin(arg1); Perun.LogLogin(arg1);
Perun.LogEvent(eventName,"Player "..net.get_player_info(arg1, "name") .. " connected"); Perun.LogEvent(eventName,"Player "..net.get_player_info(arg1, "name") .. " connected",nil,nil);
elseif eventName == "disconnect" then elseif eventName == "disconnect" then
--"disconnect", playerID, name, playerSide, reason_code --"disconnect", playerID, name, playerSide, reason_code
Perun.LogEvent(eventName, Perun.SideID2Name(arg3) .. " player " ..net.get_player_info(arg1, "name") .. " disconnected"); Perun.LogEvent(eventName, Perun.SideID2Name(arg3) .. " player " ..net.get_player_info(arg1, "name") .. " disconnected",nil,nil);
Perun.LogStats(arg1); Perun.LogStats(arg1);
elseif eventName == "crash" then elseif eventName == "crash" then
--"crash", playerID, unit_missionID --"crash", playerID, unit_missionID
Perun.LogEvent(eventName, Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name") .. " crashed in " .. DCS.getUnitType(arg2)); Perun.LogEvent(eventName, Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name") .. " crashed in " .. DCS.getUnitType(arg2),nil,nil);
Perun.LogStats(arg1); Perun.LogStatsCount(arg1,"crash",DCS.getUnitType(arg2))
elseif eventName == "eject" then elseif eventName == "eject" then
--"eject", playerID, unit_missionID --"eject", playerID, unit_missionID
Perun.LogEvent(eventName, Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name") .. " ejected " .. DCS.getUnitType(arg2)); Perun.LogEvent(eventName, Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name") .. " ejected " .. DCS.getUnitType(arg2),nil,nil);
Perun.LogStats(arg1); Perun.LogStatsCount(arg1,"eject",DCS.getUnitType(arg2));
elseif eventName == "takeoff" then elseif eventName == "takeoff" then
--"takeoff", playerID, unit_missionID, airdromeName --"takeoff", playerID, unit_missionID, airdromeName
if arg3 then if arg3 ~= "" then
_temp = " from " .. arg3; _temp = " from " .. arg3;
else else
_temp = ""; _temp = "";
end end
Perun.LogEvent(eventName, Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name") .. " took off in ".. DCS.getUnitType(arg2) .. _temp); Perun.LogEvent(eventName, Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name") .. " took off in ".. DCS.getUnitType(arg2) .. _temp,arg3,nil);
Perun.LogStats(arg1);
if string.find(arg3, "FARP",1,true) then
Perun.LogStatsCount(arg1,"tookoff_FARP",DCS.getUnitType(arg2))
elseif string.find(arg3, "CVN-74 John C. Stennis",1,true) or string.find(arg3, "LHA-1 Tarawa",1,true) then
Perun.LogStatsCount(arg1,"tookoff_SHIP",DCS.getUnitType(arg2))
elseif arg3 ~= "" then
Perun.LogStatsCount(arg1,"tookoff_AIRFIELD",DCS.getUnitType(arg2))
else
Perun.LogStatsCount(arg1,"tookoff_OTHER",DCS.getUnitType(arg2))
end
elseif eventName == "landing" then elseif eventName == "landing" then
--"landing", playerID, unit_missionID, airdromeName --"landing", playerID, unit_missionID, airdromeName
if arg3 then if arg3 ~= "" then
_temp = " at " .. arg3; _temp = " at " .. arg3;
else else
_temp =""; _temp ="";
end end
Perun.LogEvent(eventName, Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name") .. " landed in " .. DCS.getUnitType(arg2).. _temp); Perun.LogEvent(eventName, Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name") .. " landed in " .. DCS.getUnitType(arg2).. _temp,arg3,nil);
Perun.LogStats(arg1);
if string.find(arg3, "FARP",1,true) then
Perun.LogStatsCount(arg1,"landing_FARP",DCS.getUnitType(arg2))
elseif string.find(arg3, "CVN-74 John C. Stennis",1,true) or string.find(arg3, "LHA-1 Tarawa",1,true) then
Perun.LogStatsCount(arg1,"landing_SHIP",DCS.getUnitType(arg2))
elseif arg3 ~= "" then
Perun.LogStatsCount(arg1,"landing_AIRFIELD",DCS.getUnitType(arg2))
else
Perun.LogStatsCount(arg1,"landing_OTHER",DCS.getUnitType(arg2))
end
elseif eventName == "pilot_death" then elseif eventName == "pilot_death" then
--"pilot_death", playerID, unit_missionID --"pilot_death", playerID, unit_missionID
Perun.LogEvent(eventName, Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name") .. " in " .. DCS.getUnitType(arg2) .. " died"); Perun.LogEvent(eventName, Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name") .. " in " .. DCS.getUnitType(arg2) .. " died",nil,nil);
Perun.LogStats(arg1); Perun.LogStatsCount(arg1,"pilot_death",DCS.getUnitType(arg2))
else else
Perun.LogEvent(eventName,"Unknown event type"); Perun.LogEvent(eventName,"Unknown event type",nil,nil);
end end
end end
-- Finalize and set callbacks -- ########### Finalize and set callbacks ###########
if Perun.IsServer then
DCS.setUserCallbacks(Perun) DCS.setUserCallbacks(Perun)
net.log("Loaded - Perun - VladMordock - " .. Perun.Version ) net.log("Perun by VladMordock was loaded: " .. Perun.Version )
Perun.ConnectToPerun()
end

View File

@@ -0,0 +1 @@
[]

View File

@@ -1,7 +1,7 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio Version 16
VisualStudioVersion = 15.0.28307.421 VisualStudioVersion = 16.0.29306.81
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perun_v1", "Perun_v1\Perun_v1.csproj", "{5A710507-92E9-4664-9B91-918B8B82F107}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perun_v1", "Perun_v1\Perun_v1.csproj", "{5A710507-92E9-4664-9B91-918B8B82F107}"
EndProject EndProject

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Google.Protobuf" version="3.5.1" targetFramework="net461" />
<package id="MySql.Data" version="8.0.15" targetFramework="net461" />
<package id="Newtonsoft.Json" version="12.0.1" targetFramework="net461" />
</packages>

View File

@@ -0,0 +1,143 @@
// This class handles MySQL communication
using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using System;
public class DatabaseController
{
public string strMySQLConnectionString; // MySQL connection string
public MySqlConnection connMySQL;
public bool bStatus;
public void SendToMySql(string strRawUDPFrame)
{
// Main function to send data to mysql
dynamic strUDPFrame = JsonConvert.DeserializeObject(strRawUDPFrame); // Deserialize raw data
string strUDPFrameType = strUDPFrame.type;
string strUDPFrameTimestamp = strUDPFrame.timestamp;
string strUDPFrameInstance = strUDPFrame.instance;
string strUDPFramePayload;
string strUDPFramePayload_Perun;
string strSQLQueryTxt;
// Some frames may come without timestamp, use database currrent timestampe then
if (strUDPFrameTimestamp != null)
{
strUDPFrameTimestamp = "'" + strUDPFrameTimestamp + "'";
}
else
{
strUDPFrameTimestamp = "CURRENT_TIMESTAMP()";
}
// Modify specific types
if (strUDPFrameType == "1")
{
strUDPFrame.payload["v_win"] = "v" + Globals.strPerunVersion; // Inject app version information
}
// Specific SQL
if (strUDPFrameType == "50")
{
// Add entry to chat log
strSQLQueryTxt = "INSERT INTO `pe_DataPlayers` (`pe_DataPlayers_ucid`) SELECT '" + strUDPFrame.payload.ucid + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataPlayers` where `pe_DataPlayers_ucid` = '" + strUDPFrame.payload.ucid + "' );";
strSQLQueryTxt += "UPDATE `pe_DataPlayers` SET `pe_DataPlayers_updated` = " + strUDPFrameTimestamp + ",`pe_DataPlayers_lastname`='" + strUDPFrame.payload.player + "' WHERE `pe_DataPlayers_ucid`='" + strUDPFrame.payload.ucid + "' ;";
strSQLQueryTxt += "INSERT INTO `pe_DataMissionHashes` (`pe_DataMissionHashes_hash`,`pe_DataMissionHashes_instance`) SELECT '" + strUDPFrame.payload.missionhash + "','" + strUDPFrameInstance + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataMissionHashes` where `pe_DataMissionHashes_hash` ='" + strUDPFrame.payload.missionhash + "' AND `pe_DataMissionHashes_instance`="+ strUDPFrameInstance + ");";
strSQLQueryTxt += "UPDATE `pe_DataMissionHashes` SET `pe_DataMissionHashes_datetime` = " + strUDPFrameTimestamp + " WHERE `pe_DataMissionHashes_hash` = '" + strUDPFrame.payload.missionhash + "' AND `pe_DataMissionHashes_instance`=" + strUDPFrameInstance + " ;";
strSQLQueryTxt += "INSERT INTO `pe_LogChat` (`pe_LogChat_id`,`pe_LogChat_datetime`, `pe_LogChat_playerid`, `pe_LogChat_msg`, `pe_LogChat_all`,`pe_LogChat_missionhash_id`) VALUES (NULL,'" + strUDPFrame.payload.datetime + "', (SELECT `pe_DataPlayers_id` from `pe_DataPlayers` WHERE `pe_DataPlayers_ucid` = '" + strUDPFrame.payload.ucid + "'), '" + strUDPFrame.payload.msg + "', '" + strUDPFrame.payload.all + "',(SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + strUDPFrame.payload.missionhash + "'));";
}
else if (strUDPFrameType == "51")
{
// Add entry to event log
strSQLQueryTxt = "INSERT INTO `pe_DataMissionHashes` (`pe_DataMissionHashes_hash`,`pe_DataMissionHashes_instance`) SELECT '" + strUDPFrame.payload.log_missionhash + "','" + strUDPFrameInstance + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataMissionHashes` where `pe_DataMissionHashes_hash` = '" + strUDPFrame.payload.log_missionhash + "' AND `pe_DataMissionHashes_instance`=" + strUDPFrameInstance + ");";
strSQLQueryTxt += "UPDATE `pe_DataMissionHashes` SET `pe_DataMissionHashes_datetime` = " + strUDPFrameTimestamp + " WHERE `pe_DataMissionHashes_hash` = '" + strUDPFrame.payload.log_missionhash + "' AND `pe_DataMissionHashes_instance`=" + strUDPFrameInstance + ";";
strSQLQueryTxt += "INSERT INTO `pe_LogEvent` (`pe_LogEvent_arg1`,`pe_LogEvent_arg2`,`pe_LogEvent_id`, `pe_LogEvent_datetime`, `pe_LogEvent_type`, `pe_LogEvent_content`,`pe_LogEvent_missionhash_id`) VALUES ('"+ strUDPFrame.payload.log_arg_1 + "','"+ strUDPFrame.payload.log_arg_2 + "', NULL, '" + strUDPFrame.payload.log_datetime + "', '" + strUDPFrame.payload.log_type + "', '" + strUDPFrame.payload.log_content + "', (SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + strUDPFrame.payload.log_missionhash + "'));";
}
else if (strUDPFrameType == "52")
{
// Update user stats
strUDPFramePayload = JsonConvert.SerializeObject(strUDPFrame.payload.stat_data_dcs); // Deserialize payload
strUDPFramePayload_Perun = JsonConvert.SerializeObject(strUDPFrame.payload.stat_data_perun); // Deserialize payload
strSQLQueryTxt = "INSERT INTO `pe_DataMissionHashes` (`pe_DataMissionHashes_hash`,`pe_DataMissionHashes_instance`) SELECT '" + strUDPFrame.payload.stat_missionhash + "','" + strUDPFrameInstance + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataMissionHashes` where `pe_DataMissionHashes_hash` = '" + strUDPFrame.payload.stat_missionhash + "' AND `pe_DataMissionHashes_instance`=" + strUDPFrameInstance + ");";
strSQLQueryTxt += "UPDATE `pe_DataMissionHashes` SET `pe_DataMissionHashes_datetime` = " + strUDPFrameTimestamp + " WHERE `pe_DataMissionHashes_hash` = '" + strUDPFrame.payload.stat_missionhash + "' AND `pe_DataMissionHashes_instance`=" + strUDPFrameInstance + " ;";
strSQLQueryTxt += "INSERT INTO `pe_DataPlayers` (`pe_DataPlayers_ucid`) SELECT '" + strUDPFrame.payload.stat_ucid + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataPlayers` where `pe_DataPlayers_ucid` = '" + strUDPFrame.payload.stat_ucid + "');";
strSQLQueryTxt += "UPDATE `pe_DataPlayers` SET `pe_DataPlayers_updated`=" + strUDPFrameTimestamp + " WHERE `pe_DataPlayers_ucid`='" + strUDPFrame.payload.stat_ucid + "';";
strSQLQueryTxt += "INSERT INTO `pe_DataTypes` (`pe_DataTypes_name`) SELECT '" + strUDPFrame.payload.stat_data_type + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataTypes` where `pe_DataTypes_name` = '" + strUDPFrame.payload.stat_data_type + "');";
strSQLQueryTxt += "INSERT INTO `pe_LogStats` (`pe_LogStats_playerid`,`pe_LogStats_missionhash_id`,`pe_LogStats_typeid`) SELECT (SELECT `pe_DataPlayers_id` from `pe_DataPlayers` WHERE `pe_DataPlayers_ucid` = '" + strUDPFrame.payload.stat_ucid + "'), (SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + strUDPFrame.payload.stat_missionhash + "'), (SELECT pe_DataTypes_id FROM `pe_DataTypes` where `pe_DataTypes_name` = '" + strUDPFrame.payload.stat_data_type + "') FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_LogStats` WHERE `pe_LogStats_missionhash_id`=(SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + strUDPFrame.payload.stat_missionhash + "') AND `pe_LogStats_playerid` = (SELECT `pe_DataPlayers_id` from `pe_DataPlayers` WHERE `pe_DataPlayers_ucid` = '" + strUDPFrame.payload.stat_ucid + "') AND `pe_LogStats_typeid`= (SELECT pe_DataTypes_id FROM `pe_DataTypes` where `pe_DataTypes_name` = '" + strUDPFrame.payload.stat_data_type + "'));";
strSQLQueryTxt += "UPDATE `pe_LogStats` SET `ps_kills_fortification`=" + strUDPFrame.payload.stat_data_perun.ps_kills_fortification + ",`ps_other_landings`=" + strUDPFrame.payload.stat_data_perun.ps_other_landings + ",`ps_other_takeoffs`=" + strUDPFrame.payload.stat_data_perun.ps_other_takeoffs + ",`ps_pvp`=" + strUDPFrame.payload.stat_data_perun.ps_pvp + ",`ps_deaths`=" + strUDPFrame.payload.stat_data_perun.ps_deaths + ",`ps_ejections`=" + strUDPFrame.payload.stat_data_perun.ps_ejections + ",`ps_crashes`=" + strUDPFrame.payload.stat_data_perun.ps_crashes + ",`ps_teamkills`=" + strUDPFrame.payload.stat_data_perun.ps_teamkills + ",`ps_kills_planes`=" + strUDPFrame.payload.stat_data_perun.ps_kills_planes + ",`ps_kills_helicopters`=" + strUDPFrame.payload.stat_data_perun.ps_kills_helicopters + ",`ps_kills_air_defense`=" + strUDPFrame.payload.stat_data_perun.ps_kills_air_defense + ",`ps_kills_armor`=" + strUDPFrame.payload.stat_data_perun.ps_kills_armor + ",`ps_kills_unarmed`=" + strUDPFrame.payload.stat_data_perun.ps_kills_unarmed + ",`ps_kills_infantry`=" + strUDPFrame.payload.stat_data_perun.ps_kills_infantry + ",`ps_kills_ships`=" + strUDPFrame.payload.stat_data_perun.ps_kills_ships + ",`ps_kills_other`=" + strUDPFrame.payload.stat_data_perun.ps_kills_other + ",`ps_airfield_takeoffs`=" + strUDPFrame.payload.stat_data_perun.ps_airfield_takeoffs + ",`ps_airfield_landings`=" + strUDPFrame.payload.stat_data_perun.ps_airfield_landings + ",`ps_ship_takeoffs`=" + strUDPFrame.payload.stat_data_perun.ps_ship_takeoffs + ",`ps_ship_landings`=" + strUDPFrame.payload.stat_data_perun.ps_ship_landings + ",`ps_farp_takeoffs`=" + strUDPFrame.payload.stat_data_perun.ps_farp_takeoffs + ",`ps_farp_landings`=" + strUDPFrame.payload.stat_data_perun.ps_farp_landings + ", `pe_LogStats_datetime`='" + strUDPFrame.payload.stat_datetime + "',`pe_LogStats_playerid` = (SELECT `pe_DataPlayers_id` from `pe_DataPlayers` WHERE `pe_DataPlayers_ucid` = '" + strUDPFrame.payload.stat_ucid + "'),`pe_LogStats_missionhash_id`=(SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + strUDPFrame.payload.stat_missionhash + "') WHERE `pe_LogStats_missionhash_id`=(SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + strUDPFrame.payload.stat_missionhash + "') AND `pe_LogStats_playerid` = (SELECT `pe_DataPlayers_id` from `pe_DataPlayers` WHERE `pe_DataPlayers_ucid` = '" + strUDPFrame.payload.stat_ucid + "') AND `pe_LogStats_typeid`=(SELECT pe_DataTypes_id FROM `pe_DataTypes` where `pe_DataTypes_name` = '" + strUDPFrame.payload.stat_data_type + "');";
}
else if (strUDPFrameType == "53")
{
// User logged in to DCS server
strSQLQueryTxt = "INSERT INTO `pe_DataPlayers` (`pe_DataPlayers_ucid`) SELECT '" + strUDPFrame.payload.login_ucid + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataPlayers` where pe_DataPlayers_ucid='" + strUDPFrame.payload.login_ucid + "');";
strSQLQueryTxt += "UPDATE `pe_DataPlayers` SET pe_DataPlayers_lastip='" + strUDPFrame.payload.login_ipaddr + "', pe_DataPlayers_lastname='" + strUDPFrame.payload.login_name + "',pe_DataPlayers_updated='" + strUDPFrame.payload.login_datetime + "' WHERE `pe_DataPlayers_ucid`= '" + strUDPFrame.payload.login_ucid + "';";
strSQLQueryTxt += "INSERT INTO `pe_LogLogins` (`pe_LogLogins_datetime`, `pe_LogLogins_playerid`, `pe_LogLogins_name`, `pe_LogLogins_ip`,`pe_LogLogins_instance`) VALUES ('" + strUDPFrame.payload.login_datetime + "', (SELECT pe_DataPlayers_id from pe_DataPlayers WHERE pe_DataPlayers_ucid = '" + strUDPFrame.payload.login_ucid + "'), '" + strUDPFrame.payload.login_name + "', '" + strUDPFrame.payload.login_ipaddr + "','"+ strUDPFrameInstance + "');";
}
else
{
// General definition used for 1-10 type packets
strUDPFramePayload = JsonConvert.SerializeObject(strUDPFrame.payload); // Deserialize payload
strSQLQueryTxt = "INSERT INTO `pe_DataRaw` (`pe_dataraw_type`,`pe_dataraw_instance`) SELECT '" + strUDPFrameType + "','"+ strUDPFrameInstance + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataRaw` WHERE `pe_dataraw_type` = '" + strUDPFrameType + "' AND `pe_dataraw_instance` = " + strUDPFrameInstance + ");";
strSQLQueryTxt += "UPDATE `pe_DataRaw` SET `pe_dataraw_payload` = JSON_QUOTE('" + strUDPFramePayload + "'), `pe_dataraw_updated`=" + strUDPFrameTimestamp + " WHERE `pe_dataraw_type`=" + strUDPFrameType + " AND `pe_dataraw_instance` = "+ strUDPFrameInstance + ";";
}
// Connect to mysql and execute sql
try
{
connMySQL = new MySqlConnection(strMySQLConnectionString);
try
{
Console.WriteLine("Sending data to MySQL - Begin");
connMySQL.Open();
bStatus = true;
MySqlCommand cmdMySQL = new MySqlCommand(strSQLQueryTxt, connMySQL);
MySqlDataReader rdrMySQL = cmdMySQL.ExecuteReader();
while (rdrMySQL.Read())
{
Console.WriteLine(rdrMySQL[0] + " -- " + rdrMySQL[1]);
}
rdrMySQL.Close();
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#" + strUDPFrameInstance + " > MySQL updated, package type: " + strUDPFrameType);
}
catch (ArgumentException a_ex)
{
// General exception found
Console.WriteLine(a_ex.ToString());
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - package type: " + strUDPFrameType);
bStatus = false;
}
catch (MySqlException m_ex)
{
// MySQL exception found
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - package type: " + strUDPFrameType);
switch (m_ex.Number)
{
case 1042: // Unable to connect to any of the specified MySQL hosts (Check Server,Port)
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - unable to connect");
break;
case 0: // Access denied (Check DB name,username,password)
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - access denied");
break;
default:
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - " + m_ex.Number);
break;
}
bStatus = false;
}
connMySQL.Close();
Console.WriteLine("Sending data to MySQL - Done");
}
catch (ArgumentException)
{
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - wrong connection parameters");
}
}
}

View File

@@ -0,0 +1,10 @@
// This class gathers all global variable
using MySql.Data.MySqlClient;
internal class Globals
{
public static string strPerunVersion = "DEBUG"; // Helper for pulling version definition
public static string[] arrLogHistory = new string[10]; // Log history for GUI
public static string strPerunTitleText = "";
}

View File

@@ -0,0 +1,13 @@
// This class just wraps some Win32 stuff that we're going to use for blocking of multiple instances
using System;
using System.Runtime.InteropServices;
internal class NativeMethods
{
public const int HWND_BROADCAST = 0xffff;
public static readonly int WM_SHOWME = RegisterWindowMessage("WM_SHOWME");
[DllImport("user32")]
public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
[DllImport("user32")]
public static extern int RegisterWindowMessage(string message);
}

View File

@@ -0,0 +1,26 @@
// This class gathers all helper functions
using System;
internal class PerunHelper
{
public static void LogHistoryAdd(ref string[] arrLogHistory, string strEntryToAdd)
{
// Add entry to log history and rotate
for (int i = 0; i < arrLogHistory.Length - 1; i++)
{
arrLogHistory[i] = arrLogHistory[i + 1]; // Shift one down
}
arrLogHistory[arrLogHistory.Length - 1] = DateTime.Now.ToString("HH:mm:ss") + " > " + strEntryToAdd; // Add entry at the last position
}
public static string GetAppVersion(string strBeginning)
{
// Gets build version
if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed)
{
System.Deployment.Application.ApplicationDeployment cd = System.Deployment.Application.ApplicationDeployment.CurrentDeployment;
Globals.strPerunVersion = cd.CurrentVersion.ToString();
}
return strBeginning+"v" + Globals.strPerunVersion;
}
}

View File

@@ -1,32 +1,31 @@
using System; using System;
using System.Threading;
using System.Windows.Forms; using System.Windows.Forms;
namespace Perun_v1 namespace Perun_v1
{ {
static class Program static class Program
{ {
/// <summary> /// <summary>
/// Główny punkt wejścia dla aplikacji. /// Main entry point to app
/// </summary> /// </summary>
[STAThread]
// Mutex to block multiple instances
//static Mutex mutex = new Mutex(true, "{5a710507-92e9-4664-9b91-918b8b82f107}");
[STAThread]
static void Main() static void Main()
{ {
Application.EnableVisualStyles(); Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); Application.SetCompatibleTextRenderingDefault(false);
Application.ApplicationExit += new EventHandler(Application_ApplicationExit); Application.ApplicationExit += new EventHandler(Application_ApplicationExit);
void Application_ApplicationExit(object sender, EventArgs e) void Application_ApplicationExit(object sender, EventArgs e)
{ {
Properties.Settings.Default.Save(); Properties.Settings.Default.Save(); // We will save settings on exit
} }
Application.Run(new form_Main()); // Run main form
Application.Run(new form_Main());
} }
} }
} }

View File

@@ -0,0 +1,146 @@
// This class handles TCP communication
using Newtonsoft.Json;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
public class TCPController
{
// Main class for TCP listener
public int intListenPort; // Port to connect to
public bool bDone; // Helper to exit main loop without killing thread
public string[] arrLogHistory; // Log history for GUI
public string[] arrSendBuffer; // Mysql send buffer
public Thread thrTCPListener; // Seperate thread for TCP
public bool bStatus; // TCP connecion status
public void Create(int par_intListenPort, ref string[] par_arrLogHistory, ref string[] par_arrSendBuffer)
{
// Create class
intListenPort = par_intListenPort;
arrLogHistory = par_arrLogHistory;
arrSendBuffer = par_arrSendBuffer;
bDone = false;
bStatus = false;
}
public void StopListen()
{
// Finish listening
bDone = true;
bStatus = false;
for (int i = 0; i < arrSendBuffer.Length - 1; i++)
{
arrSendBuffer[i] = null;
}
}
public void StartListen()
{
NetworkStream ns=null;
TcpClient tcpClient=null;
while (!bDone)
{
Console.WriteLine("TCP Listen start");
TcpListener tcpServer = new TcpListener(IPAddress.Any, intListenPort); ; // Listener object
try
{
// Start listening to TCP
string strReceivedData;
// Start the main loop
tcpServer.Start();
bStatus = true;
while (!bDone)
{
// Start listening
Console.WriteLine("TCP: Waiting for packet");
tcpClient = tcpServer.AcceptTcpClient(); //if a connection exists, the server will accept it
ns = tcpClient.GetStream(); //networkstream is used to send/receive messages
//ns.ReadTimeout = 100;
while (tcpClient.Connected && !bDone) //while the client is connected, we look for incoming messages
{
StringBuilder CompleteMessage = new StringBuilder();
if (ns.CanRead)
{
byte[] ReadBuffer = new byte[1024];
CompleteMessage = new StringBuilder();
int numberOfBytesRead = 0;
// Incoming message may be larger than the buffer size.
do
{
numberOfBytesRead = ns.Read(ReadBuffer, 0, ReadBuffer.Length);
CompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(ReadBuffer, 0, numberOfBytesRead));
}
while (ns.DataAvailable && !bDone);
}
strReceivedData = CompleteMessage.ToString();
Console.WriteLine("Sender: {0} Payload: {1}", null, strReceivedData);
try
{
dynamic dynamicRawTCPFrame = JsonConvert.DeserializeObject(strReceivedData); // Deserialize received frame
string strRawTCPFrameType = dynamicRawTCPFrame.type;
PerunHelper.LogHistoryAdd(ref arrLogHistory, "TCP packet received, type: " + strRawTCPFrameType);
// Add to mySQL send buffer (find first empty slot)
for (int i = 0; i < arrSendBuffer.Length - 1; i++)
{
if (arrSendBuffer[i] == null)
{
arrSendBuffer[i] = strReceivedData;
break;
}
}
}
catch(Exception e)
{
Console.WriteLine(e.ToString());
PerunHelper.LogHistoryAdd(ref arrLogHistory, "TCP ERROR incorrect JSON");
}
}
}
tcpServer.Stop();
bStatus = false;
}
catch (Exception e)
{
// General exception found
if (e.HResult != -2147467259)
{
Console.WriteLine(e.ToString());
PerunHelper.LogHistoryAdd(ref arrLogHistory, "TCP error - connection closed or port in use");
}
}
if (!(ns is null))
{
ns.Flush();
ns.Close();
}
if (!(tcpClient is null))
{
tcpClient.Close();
}
if (!(tcpServer is null))
{
tcpServer.Stop();
}
bStatus = false;
Console.WriteLine("TCP listen stop");
}
}
}

View File

@@ -58,9 +58,25 @@
this.openFileDialog_SRS = new System.Windows.Forms.OpenFileDialog(); this.openFileDialog_SRS = new System.Windows.Forms.OpenFileDialog();
this.openFileDialog_LotATC = new System.Windows.Forms.OpenFileDialog(); this.openFileDialog_LotATC = new System.Windows.Forms.OpenFileDialog();
this.tim_10000ms = new System.Windows.Forms.Timer(this.components); this.tim_10000ms = new System.Windows.Forms.Timer(this.components);
this.tim_200ms = new System.Windows.Forms.Timer(this.components);
this.notifyIcon1 = new System.Windows.Forms.NotifyIcon(this.components);
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.label8 = new System.Windows.Forms.Label();
this.con_txt_dcs_instance = new System.Windows.Forms.MaskedTextBox();
this.label7 = new System.Windows.Forms.Label();
this.con_txt_dcs_server_port = new System.Windows.Forms.MaskedTextBox();
this.con_img_lotATC = new System.Windows.Forms.PictureBox();
this.con_img_srs = new System.Windows.Forms.PictureBox();
this.con_img_dcs = new System.Windows.Forms.PictureBox();
this.con_img_db = new System.Windows.Forms.PictureBox();
this.con_GroupBox_1.SuspendLayout(); this.con_GroupBox_1.SuspendLayout();
this.con_GroupBox_2.SuspendLayout(); this.con_GroupBox_2.SuspendLayout();
this.con_GroupBox_3.SuspendLayout(); this.con_GroupBox_3.SuspendLayout();
this.groupBox1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.con_img_lotATC)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.con_img_srs)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.con_img_dcs)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.con_img_db)).BeginInit();
this.SuspendLayout(); this.SuspendLayout();
// //
// con_List_Received // con_List_Received
@@ -68,51 +84,42 @@
this.con_List_Received.Enabled = false; this.con_List_Received.Enabled = false;
this.con_List_Received.FormattingEnabled = true; this.con_List_Received.FormattingEnabled = true;
this.con_List_Received.Items.AddRange(new object[] { this.con_List_Received.Items.AddRange(new object[] {
"Loading", "Not connected"});
"Loading",
"Loading",
"Loading",
"Loading",
"Loading",
"Loading",
"Loading",
"Loading",
"Loading"});
this.con_List_Received.Location = new System.Drawing.Point(6, 19); this.con_List_Received.Location = new System.Drawing.Point(6, 19);
this.con_List_Received.Name = "con_List_Received"; this.con_List_Received.Name = "con_List_Received";
this.con_List_Received.Size = new System.Drawing.Size(307, 134); this.con_List_Received.Size = new System.Drawing.Size(307, 147);
this.con_List_Received.TabIndex = 0; this.con_List_Received.TabIndex = 0;
// //
// con_Button_Listen_ON // con_Button_Listen_ON
// //
this.con_Button_Listen_ON.Location = new System.Drawing.Point(12, 434); this.con_Button_Listen_ON.Location = new System.Drawing.Point(12, 553);
this.con_Button_Listen_ON.Name = "con_Button_Listen_ON"; this.con_Button_Listen_ON.Name = "con_Button_Listen_ON";
this.con_Button_Listen_ON.Size = new System.Drawing.Size(86, 39); this.con_Button_Listen_ON.Size = new System.Drawing.Size(86, 39);
this.con_Button_Listen_ON.TabIndex = 2; this.con_Button_Listen_ON.TabIndex = 2;
this.con_Button_Listen_ON.Text = "Connect"; this.con_Button_Listen_ON.Text = "Start";
this.con_Button_Listen_ON.UseVisualStyleBackColor = true; this.con_Button_Listen_ON.UseVisualStyleBackColor = true;
this.con_Button_Listen_ON.Click += new System.EventHandler(this.con_Button_Listen_ON_Click); this.con_Button_Listen_ON.Click += new System.EventHandler(this.con_Button_Listen_ON_Click);
// //
// con_Button_Listen_OFF // con_Button_Listen_OFF
// //
this.con_Button_Listen_OFF.Enabled = false; this.con_Button_Listen_OFF.Enabled = false;
this.con_Button_Listen_OFF.Location = new System.Drawing.Point(104, 434); this.con_Button_Listen_OFF.Location = new System.Drawing.Point(104, 553);
this.con_Button_Listen_OFF.Name = "con_Button_Listen_OFF"; this.con_Button_Listen_OFF.Name = "con_Button_Listen_OFF";
this.con_Button_Listen_OFF.Size = new System.Drawing.Size(86, 39); this.con_Button_Listen_OFF.Size = new System.Drawing.Size(86, 39);
this.con_Button_Listen_OFF.TabIndex = 3; this.con_Button_Listen_OFF.TabIndex = 3;
this.con_Button_Listen_OFF.Text = "Disconnect"; this.con_Button_Listen_OFF.Text = "Stop";
this.con_Button_Listen_OFF.UseVisualStyleBackColor = true; this.con_Button_Listen_OFF.UseVisualStyleBackColor = true;
this.con_Button_Listen_OFF.Click += new System.EventHandler(this.con_Button_Listen_OFF_Click); this.con_Button_Listen_OFF.Click += new System.EventHandler(this.con_Button_Listen_OFF_Click);
// //
// con_GroupBox_1 // con_GroupBox_1
// //
this.con_GroupBox_1.Controls.Add(this.con_List_Received); this.con_GroupBox_1.Controls.Add(this.con_List_Received);
this.con_GroupBox_1.Location = new System.Drawing.Point(12, 261); this.con_GroupBox_1.Location = new System.Drawing.Point(12, 369);
this.con_GroupBox_1.Name = "con_GroupBox_1"; this.con_GroupBox_1.Name = "con_GroupBox_1";
this.con_GroupBox_1.Size = new System.Drawing.Size(324, 167); this.con_GroupBox_1.Size = new System.Drawing.Size(324, 176);
this.con_GroupBox_1.TabIndex = 4; this.con_GroupBox_1.TabIndex = 4;
this.con_GroupBox_1.TabStop = false; this.con_GroupBox_1.TabStop = false;
this.con_GroupBox_1.Text = "UDP log"; this.con_GroupBox_1.Text = "Data log";
// //
// tim_1000ms // tim_1000ms
// //
@@ -225,12 +232,12 @@
this.con_GroupBox_3.Controls.Add(this.con_txt_3rd_srs); this.con_GroupBox_3.Controls.Add(this.con_txt_3rd_srs);
this.con_GroupBox_3.Controls.Add(this.con_check_3rd_lotatc); this.con_GroupBox_3.Controls.Add(this.con_check_3rd_lotatc);
this.con_GroupBox_3.Controls.Add(this.con_check_3rd_srs); this.con_GroupBox_3.Controls.Add(this.con_check_3rd_srs);
this.con_GroupBox_3.Location = new System.Drawing.Point(12, 187); this.con_GroupBox_3.Location = new System.Drawing.Point(12, 261);
this.con_GroupBox_3.Name = "con_GroupBox_3"; this.con_GroupBox_3.Name = "con_GroupBox_3";
this.con_GroupBox_3.Size = new System.Drawing.Size(324, 68); this.con_GroupBox_3.Size = new System.Drawing.Size(324, 68);
this.con_GroupBox_3.TabIndex = 6; this.con_GroupBox_3.TabIndex = 6;
this.con_GroupBox_3.TabStop = false; this.con_GroupBox_3.TabStop = false;
this.con_GroupBox_3.Text = "3rd Party"; this.con_GroupBox_3.Text = "3rd party";
// //
// con_txt_3rd_lotatc // con_txt_3rd_lotatc
// //
@@ -270,7 +277,7 @@
// //
// con_Button_Quit // con_Button_Quit
// //
this.con_Button_Quit.Location = new System.Drawing.Point(250, 434); this.con_Button_Quit.Location = new System.Drawing.Point(251, 553);
this.con_Button_Quit.Name = "con_Button_Quit"; this.con_Button_Quit.Name = "con_Button_Quit";
this.con_Button_Quit.Size = new System.Drawing.Size(86, 39); this.con_Button_Quit.Size = new System.Drawing.Size(86, 39);
this.con_Button_Quit.TabIndex = 7; this.con_Button_Quit.TabIndex = 7;
@@ -321,15 +328,111 @@
this.tim_10000ms.Interval = 30000; this.tim_10000ms.Interval = 30000;
this.tim_10000ms.Tick += new System.EventHandler(this.tim_10000ms_Tick); this.tim_10000ms.Tick += new System.EventHandler(this.tim_10000ms_Tick);
// //
// tim_200ms
//
this.tim_200ms.Tick += new System.EventHandler(this.tim_200ms_Tick);
//
// notifyIcon1
//
this.notifyIcon1.Text = "notifyIcon1";
this.notifyIcon1.Visible = true;
//
// groupBox1
//
this.groupBox1.Controls.Add(this.label8);
this.groupBox1.Controls.Add(this.con_txt_dcs_instance);
this.groupBox1.Controls.Add(this.label7);
this.groupBox1.Controls.Add(this.con_txt_dcs_server_port);
this.groupBox1.Location = new System.Drawing.Point(12, 187);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(324, 68);
this.groupBox1.TabIndex = 7;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "DCS Connection";
//
// label8
//
this.label8.AutoSize = true;
this.label8.Location = new System.Drawing.Point(41, 45);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(62, 13);
this.label8.TabIndex = 12;
this.label8.Text = "Instance ID";
//
// con_txt_dcs_instance
//
this.con_txt_dcs_instance.Location = new System.Drawing.Point(106, 42);
this.con_txt_dcs_instance.Name = "con_txt_dcs_instance";
this.con_txt_dcs_instance.Size = new System.Drawing.Size(207, 20);
this.con_txt_dcs_instance.TabIndex = 11;
//
// label7
//
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(41, 19);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(59, 13);
this.label7.TabIndex = 10;
this.label7.Text = "Server port";
//
// con_txt_dcs_server_port
//
this.con_txt_dcs_server_port.Location = new System.Drawing.Point(106, 16);
this.con_txt_dcs_server_port.Name = "con_txt_dcs_server_port";
this.con_txt_dcs_server_port.Size = new System.Drawing.Size(207, 20);
this.con_txt_dcs_server_port.TabIndex = 3;
//
// con_img_lotATC
//
this.con_img_lotATC.Location = new System.Drawing.Point(307, 335);
this.con_img_lotATC.Name = "con_img_lotATC";
this.con_img_lotATC.Size = new System.Drawing.Size(29, 28);
this.con_img_lotATC.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.con_img_lotATC.TabIndex = 13;
this.con_img_lotATC.TabStop = false;
//
// con_img_srs
//
this.con_img_srs.Location = new System.Drawing.Point(272, 335);
this.con_img_srs.Name = "con_img_srs";
this.con_img_srs.Size = new System.Drawing.Size(29, 28);
this.con_img_srs.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.con_img_srs.TabIndex = 12;
this.con_img_srs.TabStop = false;
//
// con_img_dcs
//
this.con_img_dcs.Location = new System.Drawing.Point(237, 335);
this.con_img_dcs.Name = "con_img_dcs";
this.con_img_dcs.Size = new System.Drawing.Size(29, 28);
this.con_img_dcs.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.con_img_dcs.TabIndex = 11;
this.con_img_dcs.TabStop = false;
//
// con_img_db
//
this.con_img_db.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
this.con_img_db.Location = new System.Drawing.Point(202, 335);
this.con_img_db.Name = "con_img_db";
this.con_img_db.Size = new System.Drawing.Size(29, 28);
this.con_img_db.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.con_img_db.TabIndex = 10;
this.con_img_db.TabStop = false;
//
// form_Main // form_Main
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(349, 483); this.ClientSize = new System.Drawing.Size(349, 604);
this.Controls.Add(this.con_img_lotATC);
this.Controls.Add(this.con_img_srs);
this.Controls.Add(this.con_img_dcs);
this.Controls.Add(this.con_img_db);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.con_GroupBox_3);
this.Controls.Add(this.label5); this.Controls.Add(this.label5);
this.Controls.Add(this.con_lab_github); this.Controls.Add(this.con_lab_github);
this.Controls.Add(this.con_Button_Quit); this.Controls.Add(this.con_Button_Quit);
this.Controls.Add(this.con_GroupBox_3);
this.Controls.Add(this.con_GroupBox_2); this.Controls.Add(this.con_GroupBox_2);
this.Controls.Add(this.con_GroupBox_1); this.Controls.Add(this.con_GroupBox_1);
this.Controls.Add(this.con_Button_Listen_OFF); this.Controls.Add(this.con_Button_Listen_OFF);
@@ -348,6 +451,12 @@
this.con_GroupBox_2.PerformLayout(); this.con_GroupBox_2.PerformLayout();
this.con_GroupBox_3.ResumeLayout(false); this.con_GroupBox_3.ResumeLayout(false);
this.con_GroupBox_3.PerformLayout(); this.con_GroupBox_3.PerformLayout();
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.con_img_lotATC)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.con_img_srs)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.con_img_dcs)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.con_img_db)).EndInit();
this.ResumeLayout(false); this.ResumeLayout(false);
this.PerformLayout(); this.PerformLayout();
@@ -383,6 +492,17 @@
private System.Windows.Forms.Timer tim_10000ms; private System.Windows.Forms.Timer tim_10000ms;
private System.Windows.Forms.Label label6; private System.Windows.Forms.Label label6;
private System.Windows.Forms.TextBox con_txt_mysql_port; private System.Windows.Forms.TextBox con_txt_mysql_port;
private System.Windows.Forms.Timer tim_200ms;
private System.Windows.Forms.NotifyIcon notifyIcon1;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.MaskedTextBox con_txt_dcs_server_port;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.MaskedTextBox con_txt_dcs_instance;
private System.Windows.Forms.PictureBox con_img_db;
private System.Windows.Forms.PictureBox con_img_dcs;
private System.Windows.Forms.PictureBox con_img_srs;
private System.Windows.Forms.PictureBox con_img_lotATC;
} }
} }

View File

@@ -0,0 +1,499 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
using Newtonsoft.Json;
namespace Perun_v1
{
public partial class form_Main : Form
{
// Variable definitions
public string[] arrSendBuffer = new string[65534]; // MySQL send buffer
public bool bLetMeOut = false; // Helper to handle system tray
public DatabaseController dcConnection = new DatabaseController(); // MySQL controller
public TCPController tcpcServer=new TCPController(); // TCP controller
public bool bSRSStatus; // Use empty/default SRS status
public bool bLotATCStatus; // Use empty/default LotATC status
// ################################ Main ################################
private void form_Main_Load(object sender, EventArgs e)
{
// Form loaded - fill controls with default values
Globals.arrLogHistory[0] = DateTime.Now.ToString("HH:mm:ss") + " > " + "Perun started";
Globals.strPerunTitleText = PerunHelper.GetAppVersion(this.Text + " - "); // Display build version in title bar
this.Text = Globals.strPerunTitleText;
form_Main_LoadSettings(); // Load settings
// Use command line parameters
string[] args = Environment.GetCommandLineArgs();
if (args.Length > 1)
{
// server port
if (args[1] != null)
{
con_txt_dcs_server_port.Text = args[1];
}
}
if (args.Length > 2)
{
// instance id
if (args[2] != null)
{
con_txt_dcs_instance.Text = args[2];
}
}
if (args.Length > 3)
{
// srs
if (args[3] != null)
{
con_txt_3rd_srs.Text = args[3];
con_check_3rd_srs.Checked = true;
}
}
if (args.Length > 4)
{
// lotatc
if (args[4] != null)
{
con_txt_3rd_lotatc.Text = args[4];
con_check_3rd_lotatc.Checked = true;
}
}
}
public form_Main()
{
// Form init
InitializeComponent();
}
// ################################ Helpers ################################
private void form_Main_LoadSettings()
{
// Loads settings
con_txt_mysql_database.Text = Properties.Settings.Default.MYSQL_DB;
con_txt_mysql_username.Text = Properties.Settings.Default.MYSQL_User;
con_txt_mysql_password.Text = Properties.Settings.Default.MYSQL_Password;
con_txt_mysql_server.Text = Properties.Settings.Default.MYSQL_Server;
con_txt_mysql_port.Text = Properties.Settings.Default.MYSQL_Port;
con_txt_3rd_lotatc.Text = Properties.Settings.Default.OTHER_LOTATC_FILE;
con_txt_3rd_srs.Text = Properties.Settings.Default.OTHER_SRS_FILE;
con_check_3rd_lotatc.Checked = Properties.Settings.Default.OTHER_LOTATC_USE;
con_check_3rd_srs.Checked = Properties.Settings.Default.OTHER_SRS_USE;
con_txt_dcs_server_port.Text = Properties.Settings.Default.DCS_Server_Port.ToString();
con_txt_dcs_instance.Text = Properties.Settings.Default.DCS_Instance.ToString();
}
private void form_Main_SaveSettings()
{
// Saves settings
Properties.Settings.Default.MYSQL_Server = con_txt_mysql_database.Text;
Properties.Settings.Default.MYSQL_DB = con_txt_mysql_database.Text;
Properties.Settings.Default.MYSQL_User = con_txt_mysql_username.Text;
Properties.Settings.Default.MYSQL_Password = con_txt_mysql_password.Text;
Properties.Settings.Default.MYSQL_Port = con_txt_mysql_port.Text;
Properties.Settings.Default.MYSQL_Server = con_txt_mysql_server.Text;
Properties.Settings.Default.MYSQL_Port = con_txt_mysql_port.Text;
Properties.Settings.Default.OTHER_LOTATC_FILE = con_txt_3rd_lotatc.Text;
Properties.Settings.Default.OTHER_SRS_FILE = con_txt_3rd_srs.Text;
Properties.Settings.Default.OTHER_LOTATC_USE = con_check_3rd_lotatc.Checked;
Properties.Settings.Default.OTHER_SRS_USE = con_check_3rd_srs.Checked;
Properties.Settings.Default.DCS_Server_Port = Int32.Parse(con_txt_dcs_server_port.Text);
Properties.Settings.Default.DCS_Instance = Int32.Parse(con_txt_dcs_instance.Text);
Properties.Settings.Default.Save();
}
private void form_Main_DisableControls()
{
// Disables controls
con_Button_Listen_ON.Enabled = false;
con_Button_Listen_OFF.Enabled = true;
con_txt_mysql_database.Enabled = false;
con_txt_mysql_username.Enabled = false;
con_txt_mysql_password.Enabled = false;
con_txt_mysql_server.Enabled = false;
con_txt_mysql_port.Enabled = false;
con_txt_3rd_lotatc.Enabled = false;
con_txt_3rd_srs.Enabled = false;
con_check_3rd_lotatc.Enabled = false;
con_check_3rd_srs.Enabled = false;
con_txt_dcs_server_port.Enabled = false;
con_txt_dcs_instance.Enabled = false;
}
private void form_Main_EnableControls()
{
// Enables controls
con_Button_Listen_ON.Enabled = true;
con_Button_Listen_OFF.Enabled = false;
con_txt_mysql_database.Enabled = true;
con_txt_mysql_username.Enabled = true;
con_txt_mysql_password.Enabled = true;
con_txt_mysql_port.Enabled = true;
con_txt_mysql_server.Enabled = true;
con_txt_3rd_lotatc.Enabled = true;
con_txt_3rd_srs.Enabled = true;
con_check_3rd_lotatc.Enabled = true;
con_check_3rd_srs.Enabled = true;
con_txt_dcs_server_port.Enabled = true;
con_txt_dcs_instance.Enabled = true;
}
// ################################ User input ################################
private void con_Button_Listen_ON_Click(object sender, EventArgs e)
{
// Start listening
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "Opening connections");
tcpcServer.Create(Int32.Parse(con_txt_dcs_server_port.Text), ref Globals.arrLogHistory, ref arrSendBuffer);
tcpcServer.thrTCPListener = new Thread(tcpcServer.StartListen);
tcpcServer.thrTCPListener.Start();
tcpcServer.thrTCPListener.Name = "TCPThread";
form_Main_DisableControls(); // Disable controlls
form_Main_SaveSettings(); // Save settings
// Prepare connection string
dcConnection.strMySQLConnectionString = "server=" + con_txt_mysql_server.Text + ";user=" + con_txt_mysql_username.Text + ";database=" + con_txt_mysql_database.Text + ";port=" + con_txt_mysql_port.Text + ";password=" + con_txt_mysql_password.Text;
// Start timmers
tim_200ms.Enabled = true;
tim_1000ms.Enabled = true;
tim_10000ms.Enabled = true;
// Send initial data
tim_10000ms_Tick(null, null);
// Set title bar
this.Text = "[#"+ con_txt_dcs_instance.Text + "] " + Globals.strPerunTitleText;
}
private void con_Button_Listen_OFF_Click(object sender, EventArgs e)
{
// Stop listening
// Display information
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "Closing connections");
con_Button_Listen_OFF.Enabled = false;
timer1_Tick(null, null);
this.Refresh();
Application.DoEvents();
try
{
tcpcServer.StopListen();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
while (tcpcServer.thrTCPListener.IsAlive)
{
Thread.Sleep(100); //ms
}
form_Main_EnableControls(); // Enable controls
con_img_db.Image = null;
con_img_dcs.Image = null;
con_img_lotATC.Image = null;
con_img_srs.Image = null;
// Stop timmers
tim_1000ms.Enabled = false;
tim_10000ms.Enabled = false;
tim_200ms.Enabled = false;
// Display information about closed connections
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "Connections closed");
timer1_Tick(null, null);
// Set title bar
this.Text = Globals.strPerunTitleText;
}
private void con_lab_github_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
// Open default browser with link to Perun repo
ProcessStartInfo sInfo = new ProcessStartInfo("https://github.com/szporwolik/perun");
Process.Start(sInfo);
}
private void con_txt_3rd_srs_Click(object sender, MouseEventArgs e)
{
// Chose SRS Json file
if (openFileDialog_SRS.ShowDialog() == DialogResult.OK)
{
con_txt_3rd_srs.Text = openFileDialog_SRS.FileName;
con_check_3rd_srs.Checked = true;
}
else
{
con_txt_3rd_srs.Text = "";
con_check_3rd_srs.Checked = false;
}
}
private void con_txt_3rd_lotatc_Click(object sender, MouseEventArgs e)
{
// Chose LotATC Json file
if (openFileDialog_LotATC.ShowDialog() == DialogResult.OK)
{
con_txt_3rd_lotatc.Text = openFileDialog_LotATC.FileName;
con_check_3rd_lotatc.Checked = true;
}
else
{
con_txt_3rd_lotatc.Text = "";
con_check_3rd_lotatc.Checked = false;
}
}
// ################################ Form state ################################
private void con_Button_Quit_Click(object sender, EventArgs e)
{
// Close app
DialogResult dialogResult = MessageBox.Show("Are you sure to exit Perun?", "Question", MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question);
if (dialogResult == DialogResult.Yes)
{
form_Main_SaveSettings();
bLetMeOut = true; // Save settings on exit
this.Close(); // Allow to exit application
}
else if (dialogResult == DialogResult.No)
{
//do nothing
}
}
protected override void WndProc(ref Message m)
{
// Try to run of 2nd instance
if (m.Msg == NativeMethods.WM_SHOWME)
{
form_Main_BringFromTray();
}
base.WndProc(ref m);
}
private void form_Main_SendToTray()
{
// Sends app to system tray
trayIconMain.Visible = true;
this.WindowState = FormWindowState.Minimized;
this.ShowInTaskbar = false;
}
private void form_Main_BringFromTray()
{
// Sends app from system tray
trayIconMain.Visible = false;
this.WindowState = FormWindowState.Normal;
this.ShowInTaskbar = true;
if (WindowState == FormWindowState.Minimized)
{
WindowState = FormWindowState.Normal;
}
// get our current "TopMost" value (ours will always be false though)
bool top = TopMost;
// make our form jump to the top of everything
TopMost = true;
// set it back to whatever it was
TopMost = top;
}
private void form_Main_FormClosing(object sender, FormClosingEventArgs e)
{
// Minimize to try on clicking "X"
if (e.CloseReason == CloseReason.UserClosing && !bLetMeOut)
{
e.Cancel = true;
form_Main_SendToTray(); // Send app to system tray
}
}
private void trayIconMain_MouseDoubleClick(object sender, MouseEventArgs e)
{
// Maximize from tray
form_Main_BringFromTray(); // Bring app from system tray
}
// ################################ Timers ################################
private void timer1_Tick(object sender, EventArgs e)
{
// Main timer to sync GUI with background tasks and flush buffers
// Refresh Log Window
con_List_Received.Items.Clear();
foreach (string i in Globals.arrLogHistory)
{
if (i != null)
{
con_List_Received.Items.Add(i);
}
}
}
private void tim_200ms_Tick(object sender, EventArgs e)
{
// Send buffer to MySQL
for (int i = 0; i < arrSendBuffer.Length - 1; i++)
{
if (arrSendBuffer[i] != null)
{
dcConnection.SendToMySql(arrSendBuffer[i]);
arrSendBuffer[i] = null;
}
}
// Update status icons at main form
if (dcConnection.bStatus)
{
con_img_db.Image = (Image)Properties.Resources.ResourceManager.GetObject("ico_db");
} else
{
con_img_db.Image = (Image)Properties.Resources.ResourceManager.GetObject("ico_error");
}
if (tcpcServer.bStatus)
{
con_img_dcs.Image = (Image)Properties.Resources.ResourceManager.GetObject("ico_game");
}
else
{
con_img_dcs.Image = (Image)Properties.Resources.ResourceManager.GetObject("ico_error");
}
if (bSRSStatus)
{
con_img_srs.Image = (Image)Properties.Resources.ResourceManager.GetObject("ico_srs");
}
else
{
con_img_srs.Image = (Image)Properties.Resources.ResourceManager.GetObject("ico_error");
}
if (bLotATCStatus)
{
con_img_lotATC.Image = (Image)Properties.Resources.ResourceManager.GetObject("ico_lotatc");
}
else
{
con_img_lotATC.Image = (Image)Properties.Resources.ResourceManager.GetObject("ico_error");
}
}
private void tim_10000ms_Tick(object sender, EventArgs e)
{
// Main timer to send JSON files to MySQL
string strSRSJson = "";
string strLotATCJson = "";
bool boolSRSdefault = true;
bool boolLotATCdefault = true;
// Handle SRS
if (con_check_3rd_srs.Checked)
{
try
{
strSRSJson = System.IO.File.ReadAllText(con_txt_3rd_srs.Text);
dynamic raw_lotatc = JsonConvert.DeserializeObject(strSRSJson);
for (int i = 0; i < raw_lotatc.Count; i++)
{
if (raw_lotatc[i].RadioInfo != null)
{
int temp = raw_lotatc[i].RadioInfo.radios.Count - 1;
for (int j = temp; j >= 0; j--)
{
raw_lotatc[i].RadioInfo.radios[j].enc.Parent.Remove();
raw_lotatc[i].RadioInfo.radios[j].encKey.Parent.Remove();
raw_lotatc[i].RadioInfo.radios[j].encMode.Parent.Remove();
raw_lotatc[i].RadioInfo.radios[j].freqMax.Parent.Remove();
raw_lotatc[i].RadioInfo.radios[j].freqMin.Parent.Remove();
raw_lotatc[i].RadioInfo.radios[j].modulation.Parent.Remove();
raw_lotatc[i].RadioInfo.radios[j].freqMode.Parent.Remove();
raw_lotatc[i].RadioInfo.radios[j].volMode.Parent.Remove();
raw_lotatc[i].RadioInfo.radios[j].expansion.Parent.Remove();
raw_lotatc[i].RadioInfo.radios[j].channel.Parent.Remove();
raw_lotatc[i].RadioInfo.radios[j].simul.Parent.Remove();
if (raw_lotatc[i].RadioInfo.radios[j].name == "No Radio")
{
raw_lotatc[i].RadioInfo.radios[j].Remove();
}
}
raw_lotatc[i].ClientChannelId.Parent.Remove();
raw_lotatc[i].RadioInfo.simultaneousTransmission.Parent.Remove();
}
}
if (raw_lotatc.Count > 0)
{
strSRSJson = JsonConvert.SerializeObject(raw_lotatc);
strSRSJson = "{'type':'100','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':'" + strSRSJson + "'}";
}
else
{
strSRSJson = "{'type':'100','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':{'ignore':'false'}}"; // No SRS clients connected
}
boolSRSdefault = false;
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#" + Int32.Parse(con_txt_dcs_instance.Text) + " > SRS data loaded");
bSRSStatus = true;
}
catch
{
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#" + Int32.Parse(con_txt_dcs_instance.Text) + " > SRS data ERROR");
bSRSStatus = false;
}
}
if (boolSRSdefault)
{
strSRSJson = "{'type':'100','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':{'ignore':'true'}}";
}
dcConnection.SendToMySql(strSRSJson);
// Handle LotATC
if (con_check_3rd_lotatc.Checked)
{
try
{
strLotATCJson = System.IO.File.ReadAllText(con_txt_3rd_lotatc.Text);
dynamic raw_srs = JsonConvert.DeserializeObject(strLotATCJson);
strLotATCJson = "{'type':'101','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':'" + strLotATCJson + "'}";
boolLotATCdefault = false;
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#" + Int32.Parse(con_txt_dcs_instance.Text) + " > LotATC data loaded");
bLotATCStatus = true;
}
catch
{
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#" + Int32.Parse(con_txt_dcs_instance.Text) + " > LotATC data ERROR");
bLotATCStatus = false;
}
}
if (boolLotATCdefault)
{
strLotATCJson = "{'type':'101','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':{'ignore':'true'}}"; // No LotATC controller connected
}
dcConnection.SendToMySql(strLotATCJson);
}
}
}

View File

@@ -416,6 +416,12 @@
<metadata name="tim_10000ms.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="tim_10000ms.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>563, 19</value> <value>563, 19</value>
</metadata> </metadata>
<metadata name="tim_200ms.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>687, 19</value>
</metadata>
<metadata name="notifyIcon1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>797, 19</value>
</metadata>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
AAABAAEAQD8AAAEAIAAgQQAAFgAAACgAAABAAAAAfgAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAABAAEAQD8AAAEAIAAgQQAAFgAAACgAAABAAAAAfgAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -8,11 +8,12 @@
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<RootNamespace>Perun_v1</RootNamespace> <RootNamespace>Perun_v1</RootNamespace>
<AssemblyName>Perun</AssemblyName> <AssemblyName>Perun</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic> <Deterministic>true</Deterministic>
<IsWebBootstrapper>true</IsWebBootstrapper> <IsWebBootstrapper>true</IsWebBootstrapper>
<TargetFrameworkProfile />
<PublishUrl>ftp://s18.mydevil.net/perun/</PublishUrl> <PublishUrl>ftp://s18.mydevil.net/perun/</PublishUrl>
<Install>true</Install> <Install>true</Install>
<InstallFrom>Web</InstallFrom> <InstallFrom>Web</InstallFrom>
@@ -33,7 +34,7 @@
<CreateWebPageOnPublish>true</CreateWebPageOnPublish> <CreateWebPageOnPublish>true</CreateWebPageOnPublish>
<WebPage>Perun.htm</WebPage> <WebPage>Perun.htm</WebPage>
<ApplicationRevision>0</ApplicationRevision> <ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>0.3.6.%2a</ApplicationVersion> <ApplicationVersion>0.8.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust> <UseApplicationTrust>false</UseApplicationTrust>
<CreateDesktopShortcut>true</CreateDesktopShortcut> <CreateDesktopShortcut>true</CreateDesktopShortcut>
<PublishWizardCompleted>true</PublishWizardCompleted> <PublishWizardCompleted>true</PublishWizardCompleted>
@@ -61,7 +62,7 @@
</DocumentationFile> </DocumentationFile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<ApplicationIcon>perun_logo.ico</ApplicationIcon> <ApplicationIcon>03_Resources\perun_logo.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<ManifestCertificateThumbprint>2ACE4C8C2C325A04CA5986B1CD76744B4B03755D</ManifestCertificateThumbprint> <ManifestCertificateThumbprint>2ACE4C8C2C325A04CA5986B1CD76744B4B03755D</ManifestCertificateThumbprint>
@@ -74,7 +75,7 @@
<GenerateManifests>true</GenerateManifests> <GenerateManifests>true</GenerateManifests>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<SignManifests>true</SignManifests> <SignManifests>false</SignManifests>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<SignAssembly>false</SignAssembly> <SignAssembly>false</SignAssembly>
@@ -87,14 +88,20 @@
<ApplicationManifest>Properties\app.manifest</ApplicationManifest> <ApplicationManifest>Properties\app.manifest</ApplicationManifest>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Google.Protobuf, Version=3.5.1.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL"> <Reference Include="BouncyCastle.Crypto, Version=1.8.3.0, Culture=neutral, PublicKeyToken=0e99375e54769942">
<HintPath>..\packages\Google.Protobuf.3.5.1\lib\net45\Google.Protobuf.dll</HintPath> <HintPath>..\packages\BouncyCastle.1.8.3.1\lib\BouncyCastle.Crypto.dll</HintPath>
</Reference> </Reference>
<Reference Include="MySql.Data, Version=8.0.15.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL"> <Reference Include="Google.Protobuf, Version=3.6.1.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<HintPath>..\packages\MySql.Data.8.0.15\lib\net452\MySql.Data.dll</HintPath> <HintPath>..\packages\Google.Protobuf.3.6.1\lib\net45\Google.Protobuf.dll</HintPath>
</Reference>
<Reference Include="MySql.Data, Version=8.0.17.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
<HintPath>..\packages\MySql.Data.8.0.17\lib\net452\MySql.Data.dll</HintPath>
</Reference> </Reference>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> <HintPath>..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Renci.SshNet, Version=2016.1.0.0, Culture=neutral, PublicKeyToken=1cee9f8bde3db106, processorArchitecture=MSIL">
<HintPath>..\packages\SSH.NET.2016.1.0\lib\net40\Renci.SshNet.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.ComponentModel" /> <Reference Include="System.ComponentModel" />
@@ -116,15 +123,20 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="form_Main.cs"> <Compile Include="01_Classes\TCPController.cs" />
<Compile Include="01_Classes\Globals.cs" />
<Compile Include="01_Classes\DatabaseController.cs" />
<Compile Include="01_Classes\PerunHelper.cs" />
<Compile Include="01_Classes\NativeMethods.cs" />
<Compile Include="02_Forms\form_Main.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
<Compile Include="form_Main.Designer.cs"> <Compile Include="02_Forms\form_Main.Designer.cs">
<DependentUpon>form_Main.cs</DependentUpon> <DependentUpon>form_Main.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Program.cs" /> <Compile Include="01_Classes\Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="form_Main.resx"> <EmbeddedResource Include="02_Forms\form_Main.resx">
<DependentUpon>form_Main.cs</DependentUpon> <DependentUpon>form_Main.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx"> <EmbeddedResource Include="Properties\Resources.resx">
@@ -137,8 +149,10 @@
<DependentUpon>Resources.resx</DependentUpon> <DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
</Compile> </Compile>
<None Include="00_Config\packages.config" />
<None Include="00_Config\Perun_v1_TemporaryKey.pfx" />
<None Include="app.config" />
<None Include="packages.config" /> <None Include="packages.config" />
<None Include="Perun_v1_TemporaryKey.pfx" />
<None Include="Properties\app.manifest" /> <None Include="Properties\app.manifest" />
<None Include="Properties\Settings.settings"> <None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator> <Generator>SettingsSingleFileGenerator</Generator>
@@ -151,12 +165,12 @@
</Compile> </Compile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="App.config" /> <None Include="00_Config\App.config" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.6.1"> <BootstrapperPackage Include=".NETFramework,Version=v4.6.1">
<Visible>False</Visible> <Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.6.1 %28x86 i x64%29</ProductName> <ProductName>Microsoft .NET Framework 4.6.1 %28x86 and x64%29</ProductName>
<Install>true</Install> <Install>true</Install>
</BootstrapperPackage> </BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1"> <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
@@ -166,10 +180,14 @@
</BootstrapperPackage> </BootstrapperPackage>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="perun_logo.ico" /> <Content Include="03_Resources\perun_logo.ico" />
</ItemGroup> <None Include="Resources\ico_error.png" />
<ItemGroup> <None Include="Resources\ico_srs.png" />
<Folder Include="Resources\" /> <None Include="Resources\ico_lotatc.png" />
<None Include="Resources\ico_game.png" />
<None Include="Resources\ico_db.png" />
<None Include="Resources\img_db.png" />
</ItemGroup> </ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>

View File

@@ -33,7 +33,7 @@ using System.Runtime.InteropServices;
// Możesz określić wszystkie wartości lub użyć domyślnych numerów kompilacji i poprawki // Możesz określić wszystkie wartości lub użyć domyślnych numerów kompilacji i poprawki
// przy użyciu symbolu „*”, tak jak pokazano poniżej: // przy użyciu symbolu „*”, tak jak pokazano poniżej:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.3.6.0")] [assembly: AssemblyVersion("0.8.0.0")]
[assembly: AssemblyFileVersion("0.3.6.0")] [assembly: AssemblyFileVersion("0.8.0.0")]
[assembly: NeutralResourcesLanguage("en")] [assembly: NeutralResourcesLanguage("en")]

View File

@@ -1,10 +1,10 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// Ten kod został wygenerowany przez narzędzie. // This code was generated by a tool.
// Wersja wykonawcza:4.0.30319.42000 // Runtime Version:4.0.30319.42000
// //
// Zmiany w tym pliku mogą spowodować nieprawidłowe zachowanie i zostaną utracone, jeśli // Changes to this file may cause incorrect behavior and will be lost if
// kod zostanie ponownie wygenerowany. // the code is regenerated.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -13,13 +13,13 @@ namespace Perun_v1.Properties {
/// <summary> /// <summary>
/// Klasa zasobu wymagająca zdefiniowania typu do wyszukiwania zlokalizowanych ciągów itd. /// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary> /// </summary>
// Ta klasa została automatycznie wygenerowana za pomocą klasy StronglyTypedResourceBuilder // This class was auto-generated by the StronglyTypedResourceBuilder
// przez narzędzie, takie jak ResGen lub Visual Studio. // class via a tool like ResGen or Visual Studio.
// Aby dodać lub usunąć składową, edytuj plik ResX, a następnie ponownie uruchom narzędzie ResGen // To add or remove a member, edit your .ResX file then rerun ResGen
// z opcją /str lub ponownie utwórz projekt VS. // with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources { internal class Resources {
@@ -33,7 +33,7 @@ namespace Perun_v1.Properties {
} }
/// <summary> /// <summary>
/// Zwraca buforowane wystąpienie ResourceManager używane przez tę klasę. /// Returns the cached ResourceManager instance used by this class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager { internal static global::System.Resources.ResourceManager ResourceManager {
@@ -47,8 +47,8 @@ namespace Perun_v1.Properties {
} }
/// <summary> /// <summary>
/// Przesłania właściwość CurrentUICulture bieżącego wątku dla wszystkich /// Overrides the current thread's CurrentUICulture property for all
/// przypadków przeszukiwania zasobów za pomocą tej klasy zasobów wymagającej zdefiniowania typu. /// resource lookups using this strongly typed resource class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture { internal static global::System.Globalization.CultureInfo Culture {
@@ -59,5 +59,55 @@ namespace Perun_v1.Properties {
resourceCulture = value; resourceCulture = value;
} }
} }
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ico_db {
get {
object obj = ResourceManager.GetObject("ico_db", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ico_error {
get {
object obj = ResourceManager.GetObject("ico_error", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ico_game {
get {
object obj = ResourceManager.GetObject("ico_game", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ico_lotatc {
get {
object obj = ResourceManager.GetObject("ico_lotatc", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ico_srs {
get {
object obj = ResourceManager.GetObject("ico_srs", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
} }
} }

View File

@@ -117,4 +117,20 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="ico_db" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ico_db.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="ico_error" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ico_error.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="ico_game" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ico_game.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="ico_lotatc" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ico_lotatc.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="ico_srs" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ico_srs.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root> </root>

View File

@@ -1,10 +1,10 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// Ten kod został wygenerowany przez narzędzie. // This code was generated by a tool.
// Wersja wykonawcza:4.0.30319.42000 // Runtime Version:4.0.30319.42000
// //
// Zmiany w tym pliku mogą spowodować nieprawidłowe zachowanie i zostaną utracone, jeśli // Changes to this file may cause incorrect behavior and will be lost if
// kod zostanie ponownie wygenerowany. // the code is regenerated.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -12,7 +12,7 @@ namespace Perun_v1.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.2.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@@ -130,5 +130,29 @@ namespace Perun_v1.Properties {
this["MYSQL_Port"] = value; this["MYSQL_Port"] = value;
} }
} }
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("48620")]
public int DCS_Server_Port {
get {
return ((int)(this["DCS_Server_Port"]));
}
set {
this["DCS_Server_Port"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("1")]
public int DCS_Instance {
get {
return ((int)(this["DCS_Instance"]));
}
set {
this["DCS_Instance"] = value;
}
}
} }
} }

View File

@@ -29,5 +29,11 @@
<Setting Name="MYSQL_Port" Type="System.String" Scope="User"> <Setting Name="MYSQL_Port" Type="System.String" Scope="User">
<Value Profile="(Default)">3306</Value> <Value Profile="(Default)">3306</Value>
</Setting> </Setting>
<Setting Name="DCS_Server_Port" Type="System.Int32" Scope="User">
<Value Profile="(Default)">48620</Value>
</Setting>
<Setting Name="DCS_Instance" Type="System.Int32" Scope="User">
<Value Profile="(Default)">1</Value>
</Setting>
</Settings> </Settings>
</SettingsFile> </SettingsFile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="Perun_v1.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
</sectionGroup>
</configSections>
<userSettings>
<Perun_v1.Properties.Settings>
<setting name="MYSQL_Server" serializeAs="String">
<value />
</setting>
<setting name="MYSQL_User" serializeAs="String">
<value />
</setting>
<setting name="MYSQL_Password" serializeAs="String">
<value />
</setting>
<setting name="MYSQL_DB" serializeAs="String">
<value />
</setting>
<setting name="OTHER_LOTATC_FILE" serializeAs="String">
<value />
</setting>
<setting name="OTHER_SRS_FILE" serializeAs="String">
<value />
</setting>
<setting name="OTHER_LOTATC_USE" serializeAs="String">
<value>False</value>
</setting>
<setting name="OTHER_SRS_USE" serializeAs="String">
<value>False</value>
</setting>
<setting name="MYSQL_Port" serializeAs="String">
<value>3306</value>
</setting>
<setting name="DCS_Server_Port" serializeAs="String">
<value>48620</value>
</setting>
<setting name="DCS_Instance" serializeAs="String">
<value>1</value>
</setting>
</Perun_v1.Properties.Settings>
</userSettings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>

View File

@@ -1,494 +0,0 @@
using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Perun_v1
{
public partial class form_Main : Form
{
// Variable definitions
public Thread thread_UDPListener; // Seperate thread for UDP
public class_UDPListener UDPListener; // Helper class for UDP comunication
public string[] LogHistory = new string[10]; // Log history for GUI
public string[] SendBuffer = new string[10]; // Mysql send buffer
public bool LetMeOut = false; // Helper to handle system tray
public string MySql_connStr; // MySQL connection string
public string publishVersion = "DEBUG"; // Helper for pulling version definition
public static void LogHistoryAdd(ref string[] LogHistory, string Comment)
{
// Add to log history and rotate
for (int i = 0; i < LogHistory.Length - 1; i++)
{
LogHistory[i] = LogHistory[i + 1];
}
LogHistory[9] = DateTime.Now.ToString("HH:mm:ss") + " > " + Comment;
}
public void SendToMySql(string raw_udp_frame)
{
// Main function to send data to mysql
dynamic udp_frame = JsonConvert.DeserializeObject(raw_udp_frame);
// Cut raw data to type and paylod for proper mysql insert
string type = udp_frame.type;
string payload = "";
string sql = "";
// Modify specific
if (type == "1") // Inject app version information
{
udp_frame.payload["v_win"] = "v" + publishVersion;
}
// Specific SQL
if (type == "50")
{
// Add entry to chat log
sql = "INSERT INTO `pe_DataPlayers` (`pe_DataPlayers_ucid`) VALUES ('" + udp_frame.payload.ucid + "') ON DUPLICATE KEY UPDATE pe_DataPlayers_updated=CURRENT_TIMESTAMP(),pe_DataPlayers_lastname='"+ udp_frame.payload.player + "';";
sql = sql + "INSERT INTO `pe_DataMissionHashes` (`pe_DataMissionHashes_hash`) VALUES ('" + udp_frame.payload.missionhash + "') ON DUPLICATE KEY UPDATE pe_DataMissionHashes_datetime=CURRENT_TIMESTAMP();";
sql = sql+ "INSERT INTO `pe_LogChat` (`pe_LogChat_id`,`pe_LogChat_datetime`, `pe_LogChat_playerid`, `pe_LogChat_msg`, `pe_LogChat_all`,`pe_LogChat_missionhash_id`) VALUES (NULL,'" + udp_frame.payload.datetime + "', (SELECT pe_DataPlayers_id from pe_DataPlayers WHERE pe_DataPlayers_ucid = '"+ udp_frame.payload.ucid + "'), '" + udp_frame.payload.msg + "', '" + udp_frame.payload.all + "',(SELECT pe_DataMissionHashes_id FROM pe_DataMissionHashes WHERE pe_DataMissionHashes_hash = '" + udp_frame.payload.missionhash + "'));";
}
else if (type == "51")
{
// Add entry to event log
sql = "INSERT INTO `pe_DataMissionHashes` (`pe_DataMissionHashes_hash`) VALUES ('" + udp_frame.payload.log_missionhash + "') ON DUPLICATE KEY UPDATE pe_DataMissionHashes_datetime=CURRENT_TIMESTAMP();";
sql = sql + "INSERT INTO `pe_LogEvent` (`pe_LogEvent_id`, `pe_LogEvent_datetime`, `pe_LogEvent_type`, `pe_LogEvent_content`,`pe_LogEvent_missionhash_id`) VALUES ( NULL, '" + udp_frame.payload.log_datetime + "', '" + udp_frame.payload.log_type + "', '" + udp_frame.payload.log_content + "', (SELECT pe_DataMissionHashes_id FROM pe_DataMissionHashes WHERE pe_DataMissionHashes_hash = '" + udp_frame.payload.log_missionhash + "'));";
}
else if (type == "52")
{
// Update user stats
payload = JsonConvert.SerializeObject(udp_frame.payload.stat_data);
sql = "INSERT INTO `pe_DataMissionHashes` (`pe_DataMissionHashes_hash`) VALUES ('" + udp_frame.payload.stat_missionhash + "') ON DUPLICATE KEY UPDATE pe_DataMissionHashes_datetime=CURRENT_TIMESTAMP();";
sql = sql + "INSERT INTO `pe_DataPlayers` (`pe_DataPlayers_ucid`) VALUES ('" + udp_frame.payload.stat_ucid + "') ON DUPLICATE KEY UPDATE pe_DataPlayers_updated=CURRENT_TIMESTAMP();";
sql = sql+ "INSERT INTO `pe_LogStats` (`pe_LogStats_datetime`, `pe_LogStats_playerid`, `pe_LogStats_debug`,`pe_LogStats_missionhash_id`) VALUES ('" + udp_frame.payload.stat_datetime + "', (SELECT pe_DataPlayers_id from pe_DataPlayers WHERE pe_DataPlayers_ucid = '" + udp_frame.payload.stat_ucid + "'), JSON_QUOTE('" + payload + "'), (SELECT pe_DataMissionHashes_id FROM pe_DataMissionHashes WHERE pe_DataMissionHashes_hash = '" + udp_frame.payload.stat_missionhash + "')) ON DUPLICATE KEY UPDATE pe_LogStats_datetime='" + udp_frame.payload.stat_datetime + "',pe_LogStats_playerid = (SELECT pe_DataPlayers_id from pe_DataPlayers WHERE pe_DataPlayers_ucid = '" + udp_frame.payload.stat_ucid + "'), pe_LogStats_debug=JSON_QUOTE('" + payload + "'), pe_LogStats_missionhash_id=(SELECT pe_DataMissionHashes_id FROM pe_DataMissionHashes WHERE pe_DataMissionHashes_hash = '" + udp_frame.payload.stat_missionhash + "')";
}
else if (type == "53")
{
// User logged in to DCS server
payload = JsonConvert.SerializeObject(udp_frame.payload.stat_data);
sql = "INSERT INTO `pe_DataPlayers` (`pe_DataPlayers_id`, `pe_DataPlayers_ucid`, `pe_DataPlayers_lastip`, `pe_DataPlayers_lastname`, `pe_DataPlayers_updated`) VALUES (NULL, '" + udp_frame.payload.login_ucid + "', '" + udp_frame.payload.login_ipaddr + "', '" + udp_frame.payload.login_name + "', '" + udp_frame.payload.login_datetime + "') ON DUPLICATE KEY UPDATE pe_DataPlayers_lastip='" + udp_frame.payload.login_ipaddr + "',pe_DataPlayers_lastname='" + udp_frame.payload.login_name + "',pe_DataPlayers_updated='" + udp_frame.payload.login_datetime + "';";
sql = sql + "INSERT INTO `pe_LogLogins` (`pe_LogLogins_datetime`, `pe_LogLogins_playerid`, `pe_LogLogins_name`, `pe_LogLogins_ip`) VALUES ('" + udp_frame.payload.login_datetime + "', (SELECT pe_DataPlayers_id from pe_DataPlayers WHERE pe_DataPlayers_ucid = '" + udp_frame.payload.login_ucid + "'), '" + udp_frame.payload.login_name + "', '" + udp_frame.payload.login_ipaddr + "');";
}
else
{
// General definition used for 1-10 packets
payload = JsonConvert.SerializeObject(udp_frame.payload);
sql = "INSERT INTO pe_DataRaw(pe_dataraw_type,pe_dataraw_payload) VALUES (" + type + ",JSON_QUOTE('" + payload + "')) ON DUPLICATE KEY UPDATE pe_dataraw_payload = JSON_QUOTE('" + payload + "')";
}
// Connect to mysql and execute sql
MySqlConnection conn = new MySqlConnection(MySql_connStr);
try
{
Console.WriteLine("Sending data to MySQL - Begin");
conn.Open();
MySqlCommand cmd = new MySqlCommand(sql, conn);
MySqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
Console.WriteLine(rdr[0] + " -- " + rdr[1]);
}
rdr.Close();
LogHistoryAdd(ref LogHistory, "MySQL updated, package type: " + type);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
LogHistoryAdd(ref LogHistory, "ERROR MySQL: type " + type);
}
conn.Close();
Console.WriteLine("Sending data to MySQL - Done");
}
public class class_UDPListener
{
// Main class for UDP listener
int listenPort; // Port to listen at
public bool done; // Helper to exit main loop without killing thread
public UdpClient listener; // Listener object
public string[] LogHistory; // Log history for GUI
public string[] SendBuffer; // Mysql send buffer
public class_UDPListener(int port, ref string[] LogHistory, ref string[] SendBuffer)
{
// Create clas - NOTE that there is reference passing
this.listenPort = port;
this.LogHistory = LogHistory;
this.SendBuffer = SendBuffer;
}
public void StartListen()
{
// Start listening to UDP
this.done = false;
listener = new UdpClient(listenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Loopback, listenPort);
string received_data;
byte[] receive_byte_array;
Console.WriteLine("UDP Listen start");
try
{
while (!done)
{
Console.WriteLine("UDP: Waiting for packet");
receive_byte_array = listener.Receive(ref groupEP);
received_data = Encoding.ASCII.GetString(receive_byte_array, 0, receive_byte_array.Length);
Console.WriteLine("Sender: {0} Payload: {1}", groupEP.ToString(), received_data);
// Add to log history and rotate
dynamic udp_frame = JsonConvert.DeserializeObject(received_data);
string type = udp_frame.type;
LogHistoryAdd(ref LogHistory, "UDP packet received, type: " + type);
// Add to mySQL send buffer and rotate
for (int i = 0; i < SendBuffer.Length - 1; i++)
{
SendBuffer[i] = SendBuffer[i + 1];
}
SendBuffer[9] = received_data;
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("UDP listen stop");
listener.Close();
}
}
public form_Main()
{
// Form init
InitializeComponent();
}
private void form_Main_Load(object sender, EventArgs e)
{
// Form loaded - fill controls with default values
LogHistory[0] = DateTime.Now.ToString("HH:mm:ss") + " > " + "Perun loaded...";
// Load settings
con_txt_mysql_database.Text = Properties.Settings.Default.MYSQL_DB;
con_txt_mysql_username.Text = Properties.Settings.Default.MYSQL_User;
con_txt_mysql_password.Text = Properties.Settings.Default.MYSQL_Password;
con_txt_mysql_server.Text = Properties.Settings.Default.MYSQL_Server;
con_txt_mysql_port.Text = Properties.Settings.Default.MYSQL_Port;
con_txt_3rd_lotatc.Text = Properties.Settings.Default.OTHER_LOTATC_FILE;
con_txt_3rd_srs.Text = Properties.Settings.Default.OTHER_SRS_FILE;
con_check_3rd_lotatc.Checked = Properties.Settings.Default.OTHER_LOTATC_USE;
con_check_3rd_srs.Checked = Properties.Settings.Default.OTHER_SRS_USE;
// Version to title header
if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed)
{
System.Deployment.Application.ApplicationDeployment cd = System.Deployment.Application.ApplicationDeployment.CurrentDeployment;
publishVersion = cd.CurrentVersion.ToString();
}
this.Text = this.Text + " - v" + publishVersion;
}
private void con_Button_Listen_ON_Click(object sender, EventArgs e)
{
// Start listening
UDPListener = new class_UDPListener(48620, ref LogHistory, ref SendBuffer);
thread_UDPListener = new Thread(UDPListener.StartListen);
thread_UDPListener.Start();
// Update form controls
con_Button_Listen_ON.Enabled = false;
con_Button_Listen_OFF.Enabled = true;
con_txt_mysql_database.Enabled = false;
con_txt_mysql_username.Enabled = false;
con_txt_mysql_password.Enabled = false;
con_txt_mysql_server.Enabled = false;
con_txt_mysql_port.Enabled = false;
con_txt_3rd_lotatc.Enabled = false;
con_txt_3rd_srs.Enabled = false;
con_check_3rd_lotatc.Enabled = false;
con_check_3rd_srs.Enabled = false;
// Save settings
Properties.Settings.Default.MYSQL_Server = con_txt_mysql_database.Text;
Properties.Settings.Default.MYSQL_DB = con_txt_mysql_database.Text;
Properties.Settings.Default.MYSQL_User = con_txt_mysql_username.Text;
Properties.Settings.Default.MYSQL_Password = con_txt_mysql_password.Text;
Properties.Settings.Default.MYSQL_Port = con_txt_mysql_port.Text;
Properties.Settings.Default.MYSQL_Server = con_txt_mysql_server.Text;
Properties.Settings.Default.MYSQL_Port = con_txt_mysql_port.Text;
Properties.Settings.Default.OTHER_LOTATC_FILE = con_txt_3rd_lotatc.Text;
Properties.Settings.Default.OTHER_SRS_FILE = con_txt_3rd_srs.Text;
Properties.Settings.Default.OTHER_LOTATC_USE = con_check_3rd_lotatc.Checked;
Properties.Settings.Default.OTHER_SRS_USE = con_check_3rd_srs.Checked;
// Prepare connection string
MySql_connStr = "server=" + con_txt_mysql_server.Text + ";user=" + con_txt_mysql_username.Text + ";database=" + con_txt_mysql_database.Text + ";port=" + con_txt_mysql_port.Text + ";password=" + con_txt_mysql_password.Text;
// Start timmers
tim_1000ms.Enabled = true;
tim_10000ms.Enabled = true;
}
private void con_Button_Listen_OFF_Click(object sender, EventArgs e)
{
// Stop listening
UDPListener.listener.Close();
// Update form controls
con_Button_Listen_ON.Enabled = true;
con_Button_Listen_OFF.Enabled = false;
con_txt_mysql_database.Enabled = true;
con_txt_mysql_username.Enabled = true;
con_txt_mysql_password.Enabled = true;
con_txt_mysql_port.Enabled = true;
con_txt_mysql_server.Enabled = true;
con_txt_3rd_lotatc.Enabled = true;
con_txt_3rd_srs.Enabled = true;
con_check_3rd_lotatc.Enabled = true;
con_check_3rd_srs.Enabled = true;
// Stop timmers
tim_1000ms.Enabled = false;
tim_10000ms.Enabled = false;
}
private void timer1_Tick(object sender, EventArgs e)
{
// Main timer to sync GUI with background tasks and flush buffers
// Refresh Log Window
con_List_Received.Items.Clear();
foreach (string i in LogHistory)
{
if (i != null)
{
con_List_Received.Items.Add(i);
}
}
// Send buffer to MySQL
for (int i = 0; i < SendBuffer.Length - 1; i++)
{
if (SendBuffer[i] != null)
{
SendToMySql(SendBuffer[i]);
SendBuffer[i] = null;
}
}
}
private void con_lab_github_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
// Open default browser with link to Perun repo
ProcessStartInfo sInfo = new ProcessStartInfo("https://github.com/szporwolik/perun");
Process.Start(sInfo);
}
private void con_Button_Quit_Click(object sender, EventArgs e)
{
// Close app
DialogResult dialogResult = MessageBox.Show("Are you sure to exit Perun?", "Question", MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question);
if (dialogResult == DialogResult.Yes)
{
// Save settings on exit
Properties.Settings.Default.MYSQL_Server = con_txt_mysql_database.Text;
Properties.Settings.Default.MYSQL_DB = con_txt_mysql_database.Text;
Properties.Settings.Default.MYSQL_User = con_txt_mysql_username.Text;
Properties.Settings.Default.MYSQL_Password = con_txt_mysql_password.Text;
Properties.Settings.Default.MYSQL_Port = con_txt_mysql_port.Text;
Properties.Settings.Default.MYSQL_Server = con_txt_mysql_server.Text;
Properties.Settings.Default.MYSQL_Port = con_txt_mysql_port.Text;
Properties.Settings.Default.OTHER_LOTATC_FILE = con_txt_3rd_lotatc.Text;
Properties.Settings.Default.OTHER_SRS_FILE = con_txt_3rd_srs.Text;
Properties.Settings.Default.OTHER_LOTATC_USE = con_check_3rd_lotatc.Checked;
Properties.Settings.Default.OTHER_SRS_USE = con_check_3rd_srs.Checked;
Properties.Settings.Default.Save();
LetMeOut = true;
this.Close();
}
else if (dialogResult == DialogResult.No)
{
//do nothing
}
}
private void form_Main_FormClosing(object sender, FormClosingEventArgs e)
{
// Minimize to try
if (e.CloseReason == CloseReason.UserClosing && !LetMeOut)
{
e.Cancel = true;
trayIconMain.Visible = true;
this.WindowState = FormWindowState.Minimized;
this.ShowInTaskbar = false;
//this.Hide();
}
}
private void trayIconMain_MouseDoubleClick(object sender, MouseEventArgs e)
{
// Maximize from try
trayIconMain.Visible = false;
this.WindowState = FormWindowState.Normal;
this.ShowInTaskbar = true;
}
private void con_txt_3rd_srs_Click(object sender, MouseEventArgs e)
{
// Chose SRS Json file
if (openFileDialog_SRS.ShowDialog() == DialogResult.OK)
{
con_txt_3rd_srs.Text = openFileDialog_SRS.FileName;
con_check_3rd_srs.Checked = true;
}
else
{
con_txt_3rd_srs.Text = "";
con_check_3rd_srs.Checked = false;
}
}
private void con_txt_3rd_lotatc_Click(object sender, MouseEventArgs e)
{
// Chose LotATC Json file
if (openFileDialog_LotATC.ShowDialog() == DialogResult.OK)
{
con_txt_3rd_lotatc.Text = openFileDialog_LotATC.FileName;
con_check_3rd_lotatc.Checked = true;
}
else
{
con_txt_3rd_lotatc.Text = "";
con_check_3rd_lotatc.Checked = false;
}
}
private void tim_10000ms_Tick(object sender, EventArgs e)
{
// Main timer to send JSON files to MySQL
string strSRSJson = "";
string strLotATCJson = "";
bool SRSdefault = true;
bool LotATCdefault = true;
// Handle SRS
if (con_check_3rd_srs.Checked)
{
try
{
strSRSJson = System.IO.File.ReadAllText(con_txt_3rd_srs.Text);
dynamic raw_lotatc = JsonConvert.DeserializeObject(strSRSJson);
for (int i = 0; i < raw_lotatc.Count; i++)
{
if (raw_lotatc[i].RadioInfo != null)
{
int temp = raw_lotatc[i].RadioInfo.radios.Count - 1;
for (int j = temp; j >= 0; j--)
{
raw_lotatc[i].RadioInfo.radios[j].enc.Parent.Remove();
raw_lotatc[i].RadioInfo.radios[j].encKey.Parent.Remove();
raw_lotatc[i].RadioInfo.radios[j].encMode.Parent.Remove();
raw_lotatc[i].RadioInfo.radios[j].freqMax.Parent.Remove();
raw_lotatc[i].RadioInfo.radios[j].freqMin.Parent.Remove();
raw_lotatc[i].RadioInfo.radios[j].modulation.Parent.Remove();
raw_lotatc[i].RadioInfo.radios[j].freqMode.Parent.Remove();
raw_lotatc[i].RadioInfo.radios[j].volMode.Parent.Remove();
raw_lotatc[i].RadioInfo.radios[j].expansion.Parent.Remove();
raw_lotatc[i].RadioInfo.radios[j].channel.Parent.Remove();
raw_lotatc[i].RadioInfo.radios[j].simul.Parent.Remove();
if (raw_lotatc[i].RadioInfo.radios[j].name == "No Radio")
{
raw_lotatc[i].RadioInfo.radios[j].Remove();
}
}
raw_lotatc[i].ClientChannelId.Parent.Remove();
raw_lotatc[i].RadioInfo.simultaneousTransmission.Parent.Remove();
}
}
if (raw_lotatc.Count > 0)
{
strSRSJson = JsonConvert.SerializeObject(raw_lotatc);
strSRSJson = "{'type':'100','payload':'" + strSRSJson + "'}";
}
else
{
strSRSJson = "{'type':'100','payload':{'ignore':'false'}}";
}
SRSdefault = false;
LogHistoryAdd(ref LogHistory, "SRS data loaded");
}
catch
{
LogHistoryAdd(ref LogHistory, "SRS data ERROR");
}
}
if (SRSdefault)
{
strSRSJson = "{'type':'100','payload':{'ignore':'true'}}";
}
SendToMySql(strSRSJson);
// Handle LotATC
if (con_check_3rd_lotatc.Checked)
{
try
{
strLotATCJson = System.IO.File.ReadAllText(con_txt_3rd_lotatc.Text);
dynamic raw_srs = JsonConvert.DeserializeObject(strLotATCJson);
strLotATCJson = "{'type':'101','payload':'" + strLotATCJson + "'}";
LotATCdefault = false;
LogHistoryAdd(ref LogHistory, "LotATC data loaded");
}
catch
{
LogHistoryAdd(ref LogHistory, "LotATC data ERROR");
}
}
if (LotATCdefault)
{
strLotATCJson = "{'type':'101','payload':{'ignore':'true'}}";
}
SendToMySql(strLotATCJson);
}
}
}

View File

@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Google.Protobuf" version="3.5.1" targetFramework="net461" /> <package id="BouncyCastle" version="1.8.3.1" targetFramework="net48" />
<package id="MySql.Data" version="8.0.15" targetFramework="net461" /> <package id="Google.Protobuf" version="3.6.1" targetFramework="net48" />
<package id="Newtonsoft.Json" version="12.0.1" targetFramework="net461" /> <package id="MySql.Data" version="8.0.17" targetFramework="net48" />
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net48" />
<package id="SSH.NET" version="2016.1.0" targetFramework="net48" />
</packages> </packages>

View File

@@ -1,73 +1,53 @@
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0; SET AUTOCOMMIT = 0;
START TRANSACTION; START TRANSACTION;
SET time_zone = "+00:00"; SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */; /*!40101 SET NAMES utf8mb4 */;
--
-- Baza danych: `m1081_perun`
--
CREATE DATABASE IF NOT EXISTS `m1081_perun` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USE `m1081_perun`;
-- --------------------------------------------------------
--
-- Struktura tabeli dla tabeli `pe_DataMissionHashes`
--
DROP TABLE IF EXISTS `pe_DataMissionHashes`; DROP TABLE IF EXISTS `pe_DataMissionHashes`;
CREATE TABLE IF NOT EXISTS `pe_DataMissionHashes` ( CREATE TABLE IF NOT EXISTS `pe_DataMissionHashes` (
`pe_DataMissionHashes_id` bigint(20) NOT NULL AUTO_INCREMENT, `pe_DataMissionHashes_id` bigint(20) NOT NULL AUTO_INCREMENT,
`pe_DataMissionHashes_instance` smallint(5) UNSIGNED NOT NULL,
`pe_DataMissionHashes_hash` varchar(150) NOT NULL, `pe_DataMissionHashes_hash` varchar(150) NOT NULL,
`pe_DataMissionHashes_datetime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `pe_DataMissionHashes_datetime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`pe_DataMissionHashes_id`), PRIMARY KEY (`pe_DataMissionHashes_id`),
UNIQUE KEY `UNIQUE_hash` (`pe_DataMissionHashes_hash`) UNIQUE KEY `UNIQUE_hash` (`pe_DataMissionHashes_hash`),
KEY `pe_DataMissionHashes_instance` (`pe_DataMissionHashes_instance`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Struktura tabeli dla tabeli `pe_DataPlayers`
--
DROP TABLE IF EXISTS `pe_DataPlayers`; DROP TABLE IF EXISTS `pe_DataPlayers`;
CREATE TABLE IF NOT EXISTS `pe_DataPlayers` ( CREATE TABLE IF NOT EXISTS `pe_DataPlayers` (
`pe_DataPlayers_id` bigint(20) NOT NULL AUTO_INCREMENT, `pe_DataPlayers_id` bigint(20) NOT NULL AUTO_INCREMENT,
`pe_DataPlayers_ucid` varchar(150) NOT NULL, `pe_DataPlayers_ucid` varchar(150) NOT NULL,
`pe_DataPlayers_lastip` varchar(100) NOT NULL,
`pe_DataPlayers_lastname` varchar(150) NOT NULL, `pe_DataPlayers_lastname` varchar(150) NOT NULL,
`pe_DataPlayers_lastip` varchar(100) NOT NULL,
`pe_DataPlayers_updated` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `pe_DataPlayers_updated` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`pe_DataPlayers_id`), PRIMARY KEY (`pe_DataPlayers_id`),
UNIQUE KEY `UNIQUE_UCID` (`pe_DataPlayers_ucid`) UNIQUE KEY `UNIQUE_UCID` (`pe_DataPlayers_ucid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Struktura tabeli dla tabeli `pe_DataRaw`
--
DROP TABLE IF EXISTS `pe_DataRaw`; DROP TABLE IF EXISTS `pe_DataRaw`;
CREATE TABLE IF NOT EXISTS `pe_DataRaw` ( CREATE TABLE IF NOT EXISTS `pe_DataRaw` (
`pe_dataraw_type` tinyint(4) NOT NULL AUTO_INCREMENT, `pe_dataraw_type` tinyint(4) NOT NULL,
`pe_dataraw_instance` smallint(5) UNSIGNED NOT NULL,
`pe_dataraw_payload` text NOT NULL, `pe_dataraw_payload` text NOT NULL,
`pe_dataraw_updated` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `pe_dataraw_updated` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`pe_dataraw_type`) PRIMARY KEY (`pe_dataraw_type`,`pe_dataraw_instance`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- -------------------------------------------------------- DROP TABLE IF EXISTS `pe_DataTypes`;
CREATE TABLE IF NOT EXISTS `pe_DataTypes` (
-- `pe_DataTypes_id` int(11) NOT NULL AUTO_INCREMENT,
-- Struktura tabeli dla tabeli `pe_LogChat` `pe_DataTypes_name` varchar(100) NOT NULL,
-- `pe_DataTypes_update` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`pe_DataTypes_id`),
UNIQUE KEY `UNIQUE_TYPE_NAME` (`pe_DataTypes_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `pe_LogChat`; DROP TABLE IF EXISTS `pe_LogChat`;
CREATE TABLE IF NOT EXISTS `pe_LogChat` ( CREATE TABLE IF NOT EXISTS `pe_LogChat` (
@@ -77,57 +57,114 @@ CREATE TABLE IF NOT EXISTS `pe_LogChat` (
`pe_LogChat_playerid` varchar(100) NOT NULL, `pe_LogChat_playerid` varchar(100) NOT NULL,
`pe_LogChat_msg` text NOT NULL, `pe_LogChat_msg` text NOT NULL,
`pe_LogChat_all` varchar(10) NOT NULL, `pe_LogChat_all` varchar(10) NOT NULL,
PRIMARY KEY (`pe_LogChat_id`) PRIMARY KEY (`pe_LogChat_id`),
KEY `pe_LogChat_missionhash_id` (`pe_LogChat_missionhash_id`),
KEY `pe_LogChat_playerid` (`pe_LogChat_playerid`),
KEY `pe_LogChat_datetime` (`pe_LogChat_datetime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Struktura tabeli dla tabeli `pe_LogEvent`
--
DROP TABLE IF EXISTS `pe_LogEvent`; DROP TABLE IF EXISTS `pe_LogEvent`;
CREATE TABLE IF NOT EXISTS `pe_LogEvent` ( CREATE TABLE IF NOT EXISTS `pe_LogEvent` (
`pe_LogEvent_id` bigint(20) NOT NULL AUTO_INCREMENT, `pe_LogEvent_id` bigint(20) NOT NULL AUTO_INCREMENT,
`pe_LogEvent_missionhash_id` bigint(20) DEFAULT NULL,
`pe_LogEvent_datetime` datetime DEFAULT CURRENT_TIMESTAMP, `pe_LogEvent_datetime` datetime DEFAULT CURRENT_TIMESTAMP,
`pe_LogEvent_missionhash_id` bigint(20) DEFAULT NULL,
`pe_LogEvent_type` varchar(100) NOT NULL, `pe_LogEvent_type` varchar(100) NOT NULL,
`pe_LogEvent_content` text NOT NULL, `pe_LogEvent_content` text NOT NULL,
PRIMARY KEY (`pe_LogEvent_id`) `pe_LogEvent_arg1` varchar(150) DEFAULT NULL,
`pe_LogEvent_arg2` varchar(150) DEFAULT NULL,
PRIMARY KEY (`pe_LogEvent_id`),
KEY `pe_LogEvent_missionhash_id` (`pe_LogEvent_missionhash_id`),
KEY `pe_LogEvent_datetime` (`pe_LogEvent_datetime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Struktura tabeli dla tabeli `pe_LogLogins`
--
DROP TABLE IF EXISTS `pe_LogLogins`; DROP TABLE IF EXISTS `pe_LogLogins`;
CREATE TABLE IF NOT EXISTS `pe_LogLogins` ( CREATE TABLE IF NOT EXISTS `pe_LogLogins` (
`pe_LogLogins_id` bigint(20) NOT NULL AUTO_INCREMENT, `pe_LogLogins_id` bigint(20) NOT NULL AUTO_INCREMENT,
`pe_LogLogins_datetime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `pe_LogLogins_datetime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`pe_LogLogins_instance` smallint(5) UNSIGNED NOT NULL,
`pe_LogLogins_playerid` bigint(20) DEFAULT NULL, `pe_LogLogins_playerid` bigint(20) DEFAULT NULL,
`pe_LogLogins_name` varchar(150) NOT NULL, `pe_LogLogins_name` varchar(150) NOT NULL,
`pe_LogLogins_ip` varchar(100) NOT NULL, `pe_LogLogins_ip` varchar(100) NOT NULL,
PRIMARY KEY (`pe_LogLogins_id`) PRIMARY KEY (`pe_LogLogins_id`),
KEY `pe_LogLogins_playerid` (`pe_LogLogins_playerid`),
KEY `pe_LogLogins_datetime` (`pe_LogLogins_datetime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Struktura tabeli dla tabeli `pe_LogStats`
--
DROP TABLE IF EXISTS `pe_LogStats`; DROP TABLE IF EXISTS `pe_LogStats`;
CREATE TABLE IF NOT EXISTS `pe_LogStats` ( CREATE TABLE IF NOT EXISTS `pe_LogStats` (
`pe_LogStats_id` bigint(20) NOT NULL AUTO_INCREMENT, `pe_LogStats_id` bigint(20) NOT NULL AUTO_INCREMENT,
`pe_LogStats_missionhash_id` bigint(20) DEFAULT NULL,
`pe_LogStats_datetime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `pe_LogStats_datetime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`pe_LogStats_missionhash_id` bigint(20) DEFAULT NULL,
`pe_LogStats_playerid` bigint(20) DEFAULT NULL, `pe_LogStats_playerid` bigint(20) DEFAULT NULL,
`pe_LogStats_debug` text, `pe_LogStats_typeid` int(11) DEFAULT NULL,
`ps_kills` int(11) UNSIGNED NOT NULL DEFAULT '0',
`ps_pvp` int(11) UNSIGNED NOT NULL DEFAULT '0',
`ps_deaths` int(11) UNSIGNED NOT NULL DEFAULT '0',
`ps_ejections` int(11) UNSIGNED NOT NULL DEFAULT '0',
`ps_crashes` int(11) UNSIGNED NOT NULL DEFAULT '0',
`ps_teamkills` int(11) UNSIGNED NOT NULL DEFAULT '0',
`ps_kills_planes` int(11) UNSIGNED NOT NULL DEFAULT '0',
`ps_kills_helicopters` int(11) UNSIGNED NOT NULL DEFAULT '0',
`ps_kills_air_defense` int(11) UNSIGNED NOT NULL DEFAULT '0',
`ps_kills_armor` int(11) UNSIGNED NOT NULL DEFAULT '0',
`ps_kills_unarmed` int(11) UNSIGNED NOT NULL DEFAULT '0',
`ps_kills_infantry` int(11) UNSIGNED NOT NULL DEFAULT '0',
`ps_kills_ships` int(11) UNSIGNED NOT NULL DEFAULT '0',
`ps_kills_fortification` int(10) UNSIGNED NOT NULL DEFAULT '0',
`ps_kills_other` int(11) UNSIGNED NOT NULL DEFAULT '0',
`ps_airfield_takeoffs` int(11) UNSIGNED NOT NULL DEFAULT '0',
`ps_airfield_landings` int(11) UNSIGNED NOT NULL DEFAULT '0',
`ps_ship_takeoffs` int(11) UNSIGNED NOT NULL DEFAULT '0',
`ps_ship_landings` int(11) UNSIGNED NOT NULL DEFAULT '0',
`ps_farp_takeoffs` int(11) UNSIGNED NOT NULL DEFAULT '0',
`ps_farp_landings` int(11) UNSIGNED NOT NULL DEFAULT '0',
`ps_other_landings` int(10) UNSIGNED NOT NULL DEFAULT '0',
`ps_other_takeoffs` int(10) UNSIGNED NOT NULL DEFAULT '0',
`pe_LogStats_mstatus` enum('?','RTB','MIA','KIA') DEFAULT NULL,
`ps_takeoffs` int(10) UNSIGNED DEFAULT '0',
`ps_landings` int(10) UNSIGNED DEFAULT '0',
`ps_kills_AA` int(10) UNSIGNED DEFAULT '0',
`ps_kills_AG` int(10) UNSIGNED DEFAULT '0',
`ps_kills_AS` int(10) UNSIGNED DEFAULT '0',
`ps_kills_AAA` int(10) UNSIGNED DEFAULT '0',
PRIMARY KEY (`pe_LogStats_id`), PRIMARY KEY (`pe_LogStats_id`),
UNIQUE KEY `UNIQUE_STATS_PER_MISSION_AND_UCID` (`pe_LogStats_playerid`,`pe_LogStats_missionhash_id`) USING BTREE UNIQUE KEY `UNIQUE_STATS_PER_MISSION_AND_UCID_AND_TYPE` (`pe_LogStats_playerid`,`pe_LogStats_missionhash_id`,`pe_LogStats_typeid`) USING BTREE,
KEY `pe_LogStats_missionhash_id` (`pe_LogStats_missionhash_id`),
KEY `pe_LogStats_playerid` (`pe_LogStats_playerid`),
KEY `pe_LogStats_typeid` (`pe_LogStats_typeid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TRIGGER IF EXISTS `pe_LogStats_UPDATE`;
DELIMITER $$
CREATE TRIGGER `pe_LogStats_UPDATE` BEFORE UPDATE ON `pe_LogStats` FOR EACH ROW BEGIN
SET NEW.ps_takeoffs = NEW.ps_airfield_takeoffs + NEW.ps_farp_takeoffs + NEW.ps_other_takeoffs + NEW.ps_ship_takeoffs;
SET NEW.ps_landings = NEW.ps_airfield_landings + NEW.ps_farp_landings + NEW.ps_other_landings + NEW.ps_ship_landings;
SET NEW.ps_kills_AA = NEW.ps_kills_planes + NEW.ps_kills_helicopters;
SET NEW.ps_kills_AG = NEW.ps_kills_armor + NEW.ps_kills_unarmed + NEW.ps_kills_fortification;
SET NEW.ps_kills_AS = NEW.ps_kills_ships;
SET NEW.ps_kills_AAA = NEW.ps_kills_air_defense;
IF NEW.ps_ejections > 0 THEN
SET NEW.pe_LogStats_mstatus = "MIA";
ELSEIF NEW.ps_deaths > 0 THEN
SET NEW.pe_LogStats_mstatus = "KIA";
ELSEIF NEW.ps_landings >= NEW.ps_takeoffs THEN
IF NEW.ps_takeoffs > 0 or NEW.ps_landings > 0 THEN
SET NEW.pe_LogStats_mstatus = "RTB";
ELSE
SET NEW.pe_LogStats_mstatus = "?";
END IF;
ELSEIF NEW.ps_takeoffs > NEW.ps_landings and NEW.ps_ejections=0 and NEW.ps_deaths=0 THEN
SET NEW.pe_LogStats_mstatus = "MIA";
ELSE
SET NEW.pe_LogStats_mstatus = "?";
END IF;
END
$$
DELIMITER ;
ALTER TABLE `pe_DataPlayers` ADD FULLTEXT KEY `pe_DataPlayers_ucid` (`pe_DataPlayers_ucid`);
COMMIT; COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;

View File

@@ -1,61 +1,99 @@
![alt text](https://img.shields.io/github/license/szporwolik/perun.svg "MIT")
![alt text](https://img.shields.io/github/release-pre/szporwolik/perun.svg "Latest release")
![alt text](https://img.shields.io/github/release-date-pre/szporwolik/perun.svg "Latest release date")
# Perun for DCS World # Perun for DCS World
This toolset extracts data from DCS World server and sends information to the local Json file and UDP port. Included lua script extracts data from DCS World multiplayer server and sends information to TCP port and JSON file for further processing.
Provided windows app puts JSON data to MySQL database. Additionaly Perun windows app can be used to merge LotATC and DCS SRS data in one database making Perun for DCS World wannabe ultimate integration tool for the server admins. Provided windows app puts received TCP packets to MySQL database; additionaly Perun windows application can be used to merge LotATC and DCS SRS data in one database making Perun for DCS World wannabe ultimate integration tool for the server admins.
However this software is intended to be used by experienced users - the output is data Json and MySQL; you will need to process/display it yourself. However, this software is intended to be used by experienced users - the output is MySQL data and/or JSON file; you will need to process/display it yourself.
![Perun in action](https://i.imgur.com/ougQMPq.png) ![Perun in action](https://i.imgur.com/vHw8Xu5.png)
![Data flow](https://i.imgur.com/sHDQoLM.png) ![Data flow](https://i.imgur.com/JbNu77l.png)
### Prerequisites ## Prerequisites
Core: Core:
* For JSON Export: * For JSON Export:
* DCS World stable or DCS World beta * DCS World stable or DCS World beta
* **(Optional)** For MySQL Export: * **(Optional)** For MySQL Export:
* MySQL server with read/write access * MySQL database with read/write access (tested with v5.7.21)
* .NET Framework 4.8.0
3rd party support: 3rd party applications support:
* for [DCS SRS](https://github.com/ciribob/DCS-SimpleRadioStandalone/releases) integration location of the clients-list.json file will be required (by default: SRS Server folder), "Auto Export List" option has to be enabled - see [SRS documentation](https://github.com/ciribob/DCS-SimpleRadioStandalone/wiki) * for [DCS SRS](https://github.com/ciribob/DCS-SimpleRadioStandalone/releases) integration location of the clients-list.json file will be required (by default: SRS Server folder), "Auto Export List" option has to be enabled - see [SRS documentation](https://github.com/ciribob/DCS-SimpleRadioStandalone/wiki)
* for [LotATC](https://www.lotatc.com/) you will need location of stats.json file and proper LotATC configuration with JSON data export enabled - see [LotATC documentation](https://www.lotatc.com/documentation/server_configuration.html) * for [LotATC](https://www.lotatc.com/) you will need location of stats.json file and proper LotATC configuration with JSON data export enabled - see [LotATC documentation](https://www.lotatc.com/documentation/server_configuration.html)
### Installing ## Installing
* Download latest [release](https://github.com/szporwolik/perun/releases), **optionaly** together with Win32 binary file for MySQL export - [DOWNLOAD](http://share.porwolik.com/ftp/perun/Perun.htm) * Download latest [release](https://github.com/szporwolik/perun/releases)
* Copy contents of [01_DCS](https://github.com/szporwolik/perun/tree/master/01_DCS) to your \Scripts folder (located inside DCS folder in your Saved Games) * Copy contents of [01_DCS](https://github.com/szporwolik/perun/tree/master/01_DCS) to your \Scripts folder (located inside DCS folder in your Saved Games)
* **optionaly** Create MySQL server using SQL script located in [03_MySQL](https://github.com/szporwolik/perun/tree/master/03_MySQL) * **optionaly** create MySQL database using SQL script located in [03_MySQL](https://github.com/szporwolik/perun/tree/master/03_MySQL); note that you need just a one database per DCS server machine - multiple instances pushing data to the one database are supported
* **optionaly** Run the Win32 application
* set MySQL connection data ## Running
* point LotATC json file location
* point DCS SRS json file location
* click connect and leave the app running in the background
* Start DCS World and host multiplayer session * Start DCS World and host multiplayer session
* by default the JSON is written into Scripts\Json folder located in your Saved Games DCS folder tree * by default the JSON is written into Scripts\Json folder located in your Saved Games DCS folder tree
* by default the UDP port 48620 is in use as target port * by default the TCP port 48620 is in use as target port
* **optionaly** run the Win32 application
* set MySQL connection data
* **optionaly** point LotATC json file location
* **optionaly** point DCS SRS json file location
* click connect and leave the app running in the background
* **data shall now be filling your MySQL database**
## Data packets ### Windows APP - command line arguments (for expert users)
* ID: 1, contains version information Windows app supports command line arguments, what may be handy in case of multiple instance of DCS servers running at the same machine.
* ID: 2, contains status data in the following sections
* mission - minimal information The following arguments are accepted (keep the order!):
* server port (shall be the same as in the lua file!)
* instance ID (shall be the same as in the lua file!)
* path to SRS client-list.json
* path to LotATC stats.json
Example for windows shortcut:
```
C:\Perun_v1\Perun.exe 48621 1 "G:\DCS SRS\clients-list.json" "C:\Users\DCS\Saved Games\DCS\Mods\tech\LotAtc\stats.json"
```
# API documentation (for expert users)
## MySQL database structure
* table: pe_DataMissionHashes - holds mission hashes, unique hashes created per each mission start at server
* table: pe_DataPlayers - holds players UCIDs together with last login information
* table: pe_DataRaw - holds raw data received from perun windows app, containing debug/version information together with DCS SRS and LotATC data
* table: pe_DataTypes - names of all model depende class names detected in DCS
* table: pe_LogChat - holds chat history
* table: pe_LogEvent - holds event history
* table: pe_LogLogins - holds login to server event history
* table: pe_LogStats - holds static information
## Data packets - send from lua to TCP port
* ```ID: 1```, contains version/diagnostic information
* ```ID: 2```, contains status data in the following sections
* mission - minimal information about mission
* players - connected players * players - connected players
* ID: 3, available slots list and coalitions * ```ID: 3```, available slots list and coalitions
* coalitions - available coalitions * coalitions - available coalitions
* slots - available slots * slots - available slots
* ID: 4, stores mission data **ONLY JSON FILE** * ```ID: 4```, stores mission data
* ID: 50, chat event * ```ID: 50```, chat event
* ID: 51, game event * ```ID: 51```, game event
* ID: 52, player stats * ```ID: 52```, player stats
* ID: 53, player login to DCS server * ```ID: 53```, player login to DCS server
* ID: 100, DCS SRS's client-list.json * ```ID: 100```, DCS SRS's client-list.json
* ID: 101, LotATC's stats.json * ```ID: 101```, LotATC's stats.json
# Project information
## Built With ## Built With
* [VisualStudio 2017 Community](https://visualstudio.microsoft.com/vs/community/) * [VisualStudio 2017 Community](https://visualstudio.microsoft.com/vs/community/)
* [Notepad++](https://notepad-plus-plus.org/) * [Notepad++](https://notepad-plus-plus.org/)
* [TortoiseGit](https://tortoisegit.org/)
## used 3rd party resources
* [Tango Icon Library](http://tango.freedesktop.org/Tango_Icon_Library)
## Contributing ## Contributing