53 Commits

Author SHA1 Message Date
VladMordock
9a807834d2 Merge pull request #17 from szporwolik/dev
v0.8.3
2019-10-22 17:43:13 +02:00
szporowolik
e1cfdba2cc Database upgrade to v0.8.3 2019-10-22 17:40:20 +02:00
szporowolik
9770c26b93 Added version checking of database, dcs hook and windows app - in case of mismatch , app is terminating 2019-10-22 17:36:36 +02:00
szporowolik
a0c9a249f6 Code clean up 2019-10-22 16:30:47 +02:00
szporowolik
53aade262e Code cleanup 2019-10-22 16:13:12 +02:00
szporowolik
a78ad87312 Improved MySQL connection status; performane improvment 2019-10-22 15:12:07 +02:00
szporowolik
ab86b3bcec Fixed mysql error couter 2019-10-22 14:48:21 +02:00
szporowolik
b8087f6333 First approach for multicrew stats 2019-10-22 01:15:48 +02:00
szporowolik
83ce2bd490 Improved log files - events 2019-10-21 20:22:18 +02:00
szporowolik
1f110321b4 Not send srs/lotatc data if there is no game connection. 2019-10-21 20:21:01 +02:00
szporowolik
efc215f58a Further logging improvment 2019-10-21 18:09:23 +02:00
szporowolik
4e1456e432 Merge branch 'dev' of https://github.com/szporwolik/perun into dev 2019-10-21 17:50:14 +02:00
szporowolik
5908f8f332 Logging improvment - GUI and log file shall be much easier to read and contain more information 2019-10-21 17:50:04 +02:00
szporowolik
5889bc6ddf SRS and LotATC sending will now look better in log files 2019-10-21 16:55:44 +02:00
szporowolik
2084d88117 Keep alive information added to logs 2019-10-21 16:47:26 +02:00
szporowolik
49495ba9c4 Log file and GUI improvment 2019-10-21 16:41:10 +02:00
szporowolik
1a73404c4c Fixed logging to gui (removed date), file log will keep the log date 2019-10-21 15:34:46 +02:00
VladMordock
c66daec294 Update readme
Added gildia.org logo and perun log
2019-10-21 15:24:04 +02:00
szporowolik
38853937be Merge branch 'dev' of https://github.com/szporwolik/perun into dev 2019-10-21 15:11:36 +02:00
VladMordock
488d4dfcac Update Readme - image update and added FAQ 2019-10-21 15:05:59 +02:00
szporowolik
fb96745ede Added user marker button 2019-10-21 14:51:19 +02:00
szporowolik
9d06065d70 GUI updated, added graphical header and logo 2019-10-21 14:47:25 +02:00
szporowolik
464261f09f Fixed folder structure 2019-10-21 14:37:35 +02:00
szporowolik
9123619ad1 Updated file naming and remobed unused images 2019-10-21 14:12:12 +02:00
szporowolik
cabd8d28bb Update to v.0.8.3 of lua file 2019-10-21 01:54:43 +02:00
szporowolik
67eda5d79b v0.8.3 - hotfix for disconnections issues , further network code improvment 2019-10-21 01:53:49 +02:00
VladMordock
afb935da72 Merge pull request #16 from szporwolik/dev
v8.2.0 pull request
2019-10-20 15:11:54 +02:00
szporowolik
61e201b261 Code cleanup 2019-10-20 15:00:24 +02:00
szporowolik
fc009892f2 Code cleanup 2019-10-20 14:58:04 +02:00
szporowolik
732f8b5fce Code cleanup 2019-10-20 14:26:38 +02:00
szporowolik
ceec3a7616 Code cleanup 2019-10-20 13:44:34 +02:00
szporowolik
763e6e3314 Code clean-up 2019-10-20 13:43:44 +02:00
szporowolik
2ad1a531b8 Removed NativeMethods - not used as we allow multiple instances now; changed tray icon hover text 2019-10-20 13:40:53 +02:00
szporowolik
c35c216c78 Code cleanup 2019-10-20 13:34:23 +02:00
szporowolik
0a17fcf0b2 Code cleanup 2019-10-20 13:33:10 +02:00
szporowolik
b36127c272 Code cleanup 2019-10-20 13:30:17 +02:00
szporowolik
bd0769c997 Fixed resources namming 2019-10-20 13:26:44 +02:00
szporowolik
27c2163784 Network code improved 2019-10-20 13:25:06 +02:00
VladMordock
624347b1a0 Update to 8.2 2019-10-20 02:50:20 +02:00
VladMordock
8bbac989cd Update README.md
Update to v8.2.0
2019-10-20 02:39:34 +02:00
szporowolik
fcb007bc98 Network code improvment 2019-10-20 01:06:14 +02:00
szporowolik
2f7d2d07bb Added status icons and better connection handling 2019-10-19 23:00:54 +02:00
szporowolik
48f60abbfa New feature - added simple logging to file 2019-10-19 21:31:17 +02:00
szporowolik
20d19b2670 More information about MySQL errors wil be displayed to user 2019-10-19 18:37:24 +02:00
szporowolik
49e35bcd5e v8.2.0 configuration and first build for testing 2019-10-19 14:27:51 +02:00
VladMordock
7a8a36e91b Merge pull request #15 from szporwolik/dev
v8.1.0
2019-10-19 14:27:00 +02:00
szporowolik
a0742c8c43 Performance upgrade - icons reloading will not affect performance 2019-10-19 13:34:50 +02:00
szporowolik
666c3a859f Performance upgrade - status icons reloaded only when really needed 2019-10-19 13:22:44 +02:00
szporowolik
fb0620d178 Performance upgrae - history control update only when it's really needed 2019-10-19 13:13:20 +02:00
szporowolik
1d6b32872b Configuration change 2019-10-19 12:43:13 +02:00
szporowolik
af4bc135da Block quit button, while server is connected. 2019-10-19 12:39:29 +02:00
szporowolik
57483ad4c8 v8.1.0 2019-10-19 12:26:27 +02:00
szporowolik
fcb2f62646 Fixed version displayed in title bar 2019-10-19 12:26:18 +02:00
28 changed files with 1221 additions and 576 deletions

View File

@@ -9,18 +9,18 @@ package.cpath = package.cpath..";"..lfs.currentdir().."/LuaSocket/?.dll"
Perun.RefreshStatus = 15 -- (int) base refresh rate in seconds to send status update (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.TCPTargetPort = 48621 -- (int) TCP port to send data to
Perun.TCPTargetPort = 48622 -- (int) TCP port to send data to
Perun.TCPPerunHost = "localhost" -- (string) IP adress of the Perun instance or "localhost"
Perun.Instance = 1 -- (int) Id number of instance (if multiple DCS instances are to run at the same PC)
Perun.Instance = 2 -- (int) Id number of instance (if multiple DCS instances are to run at the same PC)
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
Perun.MOTD_L1 = "Witamy na serwerze Gildia.org !" -- (string) Message send to players connecting the server - Line 1
Perun.MOTD_L2 = "Wymagamy obecnosci DCS SRS oraz TeamSpeak - szczegoly na forum" -- (string) Message send to players connecting the server - Line 2
-- ###################### END OF SETTINGS - DO NOT MODIFY OUTSIDE THIS SECTION ######################
-- Variable init
Perun.Version = "v0.8.0"
Perun.Version = "v0.8.3"
Perun.StatusData = {}
Perun.SlotsData = {}
Perun.MissionData = {}
@@ -30,15 +30,16 @@ Perun.StatDataLastType = {}
Perun.MissionHash=""
Perun.lastSentStatus =0
Perun.lastSentMission =0
Perun.lastSentKeepAlive =0
Perun.lastReconnect = 0
Perun.JsonStatusLocation = lfs.writedir() .. Perun.JsonStatusLocation
Perun.socket = require("socket")
Perun.IsServer = true --DCS.isServer( ) -- TBD looks like DCS API error, always returning True
Perun.TCPSourcePort = Perun.TCPTargetPort + 10 + Perun.Instance - 1
-- ########### Helper function definitions ###########
function stripChars(str)
-- remove accents characters from string
-- via https://stackoverflow.com/questions/50459102/replace-accented-characters-in-string-to-standard-with-lua TBD: rewrite
-- via https://stackoverflow.com/questions/50459102/replace-accented-characters-in-string-to-standard-with-lua
tableAccents = {}
tableAccents["à"] = "a"
tableAccents["á"] = "a"
@@ -152,6 +153,11 @@ Perun.SideID2Name = function(id)
return sides[id]
end
Perun.UpdateStatusPart = function(part_id, data_package)
-- Helper for status update container
Perun.StatusData[part_id] = data_package
end
-- ########### Main code ###########
Perun.AddLog = function(text)
@@ -159,29 +165,6 @@ Perun.AddLog = function(text)
net.log("Perun : ".. text)
end
Perun.ConnectToPerun = function ()
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={}
@@ -195,10 +178,28 @@ Perun.UpdateJsonStatus = function()
perun_export = io.open(Perun.JsonStatusLocation .. "perun_status_data.json", "w")
perun_export:write(_temp .. "\n")
perun_export:close()
Perun.AddLog("Updated JSON")
end
Perun.Send = function(data_id, data_package)
-- Sends data package
Perun.ConnectToPerun = function ()
-- Connects to Perun server
Perun.AddLog("Connecting to TCP server")
Perun.TCP = assert(Perun.socket.tcp())
Perun.TCP:settimeout(5000)
_, err = Perun.TCP:connect(Perun.TCPPerunHost, Perun.TCPTargetPort)
if err then
Perun.AddLog("ERROR - TCP connection error : " .. err)
else
Perun.AddLog("Sucess - connected to TCP server")
-- Perun.TCP:setoption("keepalive")
Perun.lastReconnect = _now
end
end
Perun.SendToPerun = function(data_id, data_package)
-- Prepares and sends data package
-- Prepare data
TempData={}
TempData["type"]=data_id
TempData["payload"]=data_package
@@ -206,14 +207,26 @@ Perun.Send = function(data_id, data_package)
TempData["instance"]=Perun.Instance
temp=net.lua2json(TempData)
temp=stripChars(temp)
temp="<SOT>" .. stripChars(temp) .. "<EOT>"
Perun.SendPacket(data_id,temp)
end
Perun.UpdateStatusPart = function(part_id, data_package)
-- Helper for status update container
Perun.StatusData[part_id] = data_package
-- TCP Part - sending
intStatus = nil
intTries =0
err=nil
while intStatus == nil and intTries < 3 do
intStatus, err = Perun.TCP:send(temp)
if err then
Perun.AddLog("Packed not send : " .. data_id .. " , error: " .. err .. ", tries: " .. intTries)
Perun.ConnectToPerun()
else
Perun.AddLog("Packet send : " .. data_id .. " , tries:" .. intTries)
end
intTries=intTries+1
err = nil
end
if err then
Perun.AddLog("ERROR - packed dropped : " .. data_id)
end
end
Perun.UpdateStatus = function()
@@ -223,14 +236,14 @@ Perun.UpdateStatus = function()
-- Update version data
Perun.ServerData['v_dcs_hook']=Perun.Version
-- Update server data
-- Update clients data 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)
Perun.SendToPerun(1,Perun.ServerData)
-- Status data - update all subsections
-- 1 - Mission
@@ -253,7 +266,7 @@ Perun.UpdateStatus = function()
Perun.UpdateStatusPart("players",_temp2)
-- Send
Perun.Send(2,Perun.StatusData)
Perun.SendToPerun(2,Perun.StatusData)
-- Update slots data
Perun.SlotsData['coalitions']=DCS.getAvailableCoalitions()
@@ -275,18 +288,18 @@ Perun.UpdateStatus = function()
end
-- Send
Perun.Send(3,Perun.SlotsData)
Perun.SendToPerun(3,Perun.SlotsData)
end
Perun.UpdateMission = function()
-- Main function for mission information updates
Perun.MissionData=DCS.getCurrentMission()
-- Perun.Send(4,Perun.MissionData)
-- Perun.SendToPerun(4,Perun.MissionData) -- TBD can cause data transmission troubles
end
Perun.LogChat = function(playerID,msg,all)
-- Log chat messages
-- Logs chat messages
data={}
data['player']= net.get_player_info(playerID, "name")
@@ -296,11 +309,11 @@ Perun.LogChat = function(playerID,msg,all)
data['datetime']=os.date('%Y-%m-%d %H:%M:%S')
data['missionhash']=Perun.MissionHash
Perun.Send(50,data)
Perun.SendToPerun(50,data)
end
Perun.LogEvent = function(log_type,log_content,log_arg_1,log_arg_2)
-- Log chat messages
-- Logs events messages
data={}
data['log_type']= log_type
@@ -310,7 +323,7 @@ Perun.LogEvent = function(log_type,log_content,log_arg_1,log_arg_2)
data['log_datetime']=os.date('%Y-%m-%d %H:%M:%S')
data['log_missionhash']=Perun.MissionHash
Perun.Send(51,data)
Perun.SendToPerun(51,data)
end
Perun.LogStatsCount = function(argPlayerID,argAction,argType)
@@ -358,6 +371,7 @@ Perun.LogStatsCount = function(argPlayerID,argAction,argType)
Perun.StatData[_ucid]['ps_ejections']=Perun.StatData[_ucid]['ps_ejections']+1
elseif argAction == "pilot_death" then
if DCS.getModelTime() > 300 then
-- we do not track deaths during first 5 minutes due to spawning issues TBD
Perun.StatData[_ucid]['ps_deaths']=Perun.StatData[_ucid]['ps_deaths']+1
end
elseif argAction == "friendly_fire" then
@@ -450,10 +464,11 @@ Perun.LogStats = function(playerID)
data['stat_data_perun']=_temp
data['stat_data_type']=_temp['ps_type'];
data['stat_ucid']=net.get_player_info(playerID, 'ucid')
data['stat_name']=net.get_player_info(playerID, 'name')
data['stat_datetime']=os.date('%Y-%m-%d %H:%M:%S')
data['stat_missionhash']=Perun.MissionHash
Perun.Send(52,data)
Perun.SendToPerun(52,data)
end
Perun.LogLogin = function(playerID)
@@ -465,9 +480,50 @@ Perun.LogLogin = function(playerID)
data['login_name']=net.get_player_info(playerID, 'name')
data['login_datetime']=os.date('%Y-%m-%d %H:%M:%S')
Perun.Send(53,data)
Perun.SendToPerun(53,data)
end
Perun.CheckMulticrew = function (owner_playerID,owner_unittype)
-- Check multicrew and return list of co-player
_coplayers = {}
table.insert(_coplayers, owner_playerID)
if owner_unittype == "F-14B" or owner_unittype == "Yak-52" or owner_unittype == "L-39C" or owner_unittype == "SA342M" or owner_unittype =="SA342Minigun" or owner_unittype == "SA342Mistral" or owner_unittype == "SA342L" then -- TBD add additional multicrew model types
_owner_slot=net.get_player_info(owner_playerID, 'slot')
_owner_side=net.get_player_info(owner_playerID, 'side')
-- Check if we are co-player
_t_start, _t_end = string.find(_owner_slot, '_%d+')
_sub_slot = nil
if _t_start then
-- This is co-player
_master_slot = string.sub(_owner_slot, 0 , _t_start -1 )
_sub_slot = string.sub(_owner_slot, _t_start + 1, _t_end )
else
_master_slot = _owner_slot
end
if _master_slot ~= "" then
-- Search for all players to account for event
_all_players = net.get_player_list()
for PlayerIDIndex, playerID in ipairs(_all_players) do
local _playerDetails = net.get_player_info( playerID )
if _playerDetails.side == _owner_side and (_playerDetails.slot == _master_slot or _playerDetails.slot == _master_slot .. "_1" or _playerDetails.slot == _master_slot .. "_2") and playerID ~= owner_playerID then
-- Let's build coplayers list
table.insert(_coplayers, playerID)
else
-- No coplayers
end
end
end
end
return _coplayers
end
--- ########### Event callbacks ###########
Perun.onSimulationStart = function()
@@ -510,6 +566,12 @@ Perun.onSimulationFrame = function()
Perun.UpdateStatus()
end
-- Send keepalive
if _now > Perun.lastSentKeepAlive + 3 then
Perun.lastSentKeepAlive = _now
Perun.SendToPerun(0,nil)
end
end
Perun.onPlayerStart = function (id)
@@ -534,10 +596,6 @@ Perun.onGameEvent = function (eventName,arg1,arg2,arg3,arg4,arg5,arg6,arg7)
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
--"mission_end", winner, msg
Perun.LogEvent(eventName,"Mission finished, winner " .. arg1 .. " message: " .. arg2,nil,nil);
@@ -555,31 +613,41 @@ Perun.onGameEvent = function (eventName,arg1,arg2,arg3,arg4,arg5,arg6,arg7)
if net.get_player_info(arg1, "name") ~= nil then
_temp2 = " player ".. net.get_player_info(arg1, "name") .." ";
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)
_temp_event_type=""
if arg3 ~= arg6 then
if Perun.GetCategory(arg5) == "Planes" then
_temp_event_type="kill_Planes"
elseif Perun.GetCategory(arg5) == "Helicopters" then
_temp_event_type="kill_Helicopters"
elseif Perun.GetCategory(arg5) == "Ships" then
_temp_event_type="kill_Ships"
elseif Perun.GetCategory(arg5) == "Air Defence" then
_temp_event_type="kill_Air_Defence"
elseif Perun.GetCategory(arg5) == "Unarmed" then
_temp_event_type="kill_Unarmed"
elseif Perun.GetCategory(arg5) == "Armor" then
_temp_event_type="kill_Armor"
elseif Perun.GetCategory(arg5) == "Infantry" then
_temp_event_type="kill_Infantry"
elseif Perun.GetCategory(arg5) == "Fortification" then
_temp_event_type="kill_Fortification"
else
_temp_event_type="kill_Other"
end
if net.get_player_info(arg4, "name") ~= nil and arg3 ~= arg6 then
pilots_accounted = Perun.CheckMulticrew(arg1,arg2)
for _, pilotID in ipairs(pilots_accounted) do
Perun.LogStatsCount(pilotID,"kill_PvP",DCS.getUnitType(arg2));
end
end
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)
_temp_event_type="friendly_fire"
end
if arg3 == arg6 then
Perun.LogStatsCount(arg1,"friendly_fire",arg2)
pilots_accounted = Perun.CheckMulticrew(arg1,arg2)
for _, pilotID in ipairs(pilots_accounted) do
Perun.LogStatsCount(pilotID,_temp_event_type,DCS.getUnitType(arg2));
end
else
@@ -621,11 +689,19 @@ Perun.onGameEvent = function (eventName,arg1,arg2,arg3,arg4,arg5,arg6,arg7)
elseif eventName == "crash" then
--"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),nil,nil);
Perun.LogStatsCount(arg1,"crash",DCS.getUnitType(arg2))
pilots_accounted = Perun.CheckMulticrew(arg1,DCS.getUnitType(arg2))
for _, pilotID in ipairs(pilots_accounted) do
Perun.LogStatsCount(pilotID,"crash",DCS.getUnitType(arg2));
end
elseif eventName == "eject" then
--"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),nil,nil);
Perun.LogStatsCount(arg1,"eject",DCS.getUnitType(arg2));
pilots_accounted = Perun.CheckMulticrew(arg1,DCS.getUnitType(arg2))
for _, pilotID in ipairs(pilots_accounted) do
Perun.LogStatsCount(pilotID,"eject",DCS.getUnitType(arg2));
end
elseif eventName == "takeoff" then
--"takeoff", playerID, unit_missionID, airdromeName
@@ -637,14 +713,20 @@ Perun.onGameEvent = function (eventName,arg1,arg2,arg3,arg4,arg5,arg6,arg7)
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);
_type = ""
if string.find(arg3, "FARP",1,true) then
Perun.LogStatsCount(arg1,"tookoff_FARP",DCS.getUnitType(arg2))
_type="tookoff_FARP"
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))
_type="tookoff_SHIP"
elseif arg3 ~= "" then
Perun.LogStatsCount(arg1,"tookoff_AIRFIELD",DCS.getUnitType(arg2))
_type="tookoff_AIRFIELD"
else
Perun.LogStatsCount(arg1,"tookoff_OTHER",DCS.getUnitType(arg2))
_type="tookoff_OTHER"
end
pilots_accounted = Perun.CheckMulticrew(arg1,DCS.getUnitType(arg2))
for _, pilotID in ipairs(pilots_accounted) do
Perun.LogStatsCount(pilotID,_type,DCS.getUnitType(arg2))
end
elseif eventName == "landing" then
@@ -657,20 +739,31 @@ Perun.onGameEvent = function (eventName,arg1,arg2,arg3,arg4,arg5,arg6,arg7)
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);
_type = ""
if string.find(arg3, "FARP",1,true) then
Perun.LogStatsCount(arg1,"landing_FARP",DCS.getUnitType(arg2))
_type = "landing_FARP"
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))
_type = "landing_SHIP"
elseif arg3 ~= "" then
Perun.LogStatsCount(arg1,"landing_AIRFIELD",DCS.getUnitType(arg2))
_type = "landing_AIRFIELD"
else
Perun.LogStatsCount(arg1,"landing_OTHER",DCS.getUnitType(arg2))
_type = "landing_OTHER"
end
pilots_accounted = Perun.CheckMulticrew(arg1,DCS.getUnitType(arg2))
for _, pilotID in ipairs(pilots_accounted) do
Perun.LogStatsCount(pilotID,_type,DCS.getUnitType(arg2))
end
elseif eventName == "pilot_death" then
--"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",nil,nil);
Perun.LogStatsCount(arg1,"pilot_death",DCS.getUnitType(arg2))
pilots_accounted = Perun.CheckMulticrew(arg1,DCS.getUnitType(arg2))
for _, pilotID in ipairs(pilots_accounted) do
Perun.LogStatsCount(pilotID,"pilot_death",DCS.getUnitType(arg2))
end
else
Perun.LogEvent(eventName,"Unknown event type",nil,nil);
end

View File

@@ -5,139 +5,205 @@ using System;
public class DatabaseController
{
public string strMySQLConnectionString; // MySQL connection string
public MySqlConnection connMySQL;
public bool bStatus;
public string DatabaseConnectionString; // MySQL connection string
public MySqlConnection DatabaseConnection;
public bool DatabaseStatus;
public void SendToMySql(string strRawUDPFrame)
public int SendToMySql(string RawTCPFrame, bool CheckConnection = false)
{
// 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;
if (CheckConnection)
{
RawTCPFrame = "{\"type\": \"-1\"}";
}
dynamic TCPFrame = JsonConvert.DeserializeObject(RawTCPFrame); // Deserialize raw data
string TCPFrameType = TCPFrame.type;
string TCPFrameTimestamp = TCPFrame.timestamp;
string TCPFrameInstance = TCPFrame.instance;
string TCPFramePayload;
string TCPFramePayload_Perun;
string SQLQueryTxt;
int ReturnValue = 1;
// Some frames may come without timestamp, use database currrent timestampe then
if (strUDPFrameTimestamp != null)
if (TCPFrameTimestamp != null)
{
strUDPFrameTimestamp = "'" + strUDPFrameTimestamp + "'";
TCPFrameTimestamp = "'" + TCPFrameTimestamp + "'";
}
else
{
strUDPFrameTimestamp = "CURRENT_TIMESTAMP()";
TCPFrameTimestamp = "CURRENT_TIMESTAMP()";
}
// Modify specific types
if (strUDPFrameType == "1")
if (TCPFrameType == "1")
{
strUDPFrame.payload["v_win"] = "v" + Globals.strPerunVersion; // Inject app version information
TCPFrame.payload["v_win"] = "v" + Globals.VersionPerun; // Inject app version information
// Pull DCS hook version
Globals.VersionDCSHook = TCPFrame.payload.v_dcs_hook;
}
// Specific SQL
if (strUDPFrameType == "50")
// Specific SQL per each frame type
if (TCPFrameType == "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 + "'));";
SQLQueryTxt = "INSERT INTO `pe_DataPlayers` (`pe_DataPlayers_ucid`) SELECT '" + TCPFrame.payload.ucid + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataPlayers` where `pe_DataPlayers_ucid` = '" + TCPFrame.payload.ucid + "' );";
SQLQueryTxt += "UPDATE `pe_DataPlayers` SET `pe_DataPlayers_updated` = " + TCPFrameTimestamp + ",`pe_DataPlayers_lastname`='" + TCPFrame.payload.player + "' WHERE `pe_DataPlayers_ucid`='" + TCPFrame.payload.ucid + "' ;";
SQLQueryTxt += "INSERT INTO `pe_DataMissionHashes` (`pe_DataMissionHashes_hash`,`pe_DataMissionHashes_instance`) SELECT '" + TCPFrame.payload.missionhash + "','" + TCPFrameInstance + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataMissionHashes` where `pe_DataMissionHashes_hash` ='" + TCPFrame.payload.missionhash + "' AND `pe_DataMissionHashes_instance`=" + TCPFrameInstance + ");";
SQLQueryTxt += "UPDATE `pe_DataMissionHashes` SET `pe_DataMissionHashes_datetime` = " + TCPFrameTimestamp + " WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.missionhash + "' AND `pe_DataMissionHashes_instance`=" + TCPFrameInstance + " ;";
SQLQueryTxt += "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,'" + TCPFrame.payload.datetime + "', (SELECT `pe_DataPlayers_id` from `pe_DataPlayers` WHERE `pe_DataPlayers_ucid` = '" + TCPFrame.payload.ucid + "'), '" + TCPFrame.payload.msg + "', '" + TCPFrame.payload.all + "',(SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.missionhash + "'));";
}
else if (strUDPFrameType == "51")
else if (TCPFrameType == "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 + "'));";
SQLQueryTxt = "INSERT INTO `pe_DataMissionHashes` (`pe_DataMissionHashes_hash`,`pe_DataMissionHashes_instance`) SELECT '" + TCPFrame.payload.log_missionhash + "','" + TCPFrameInstance + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataMissionHashes` where `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.log_missionhash + "' AND `pe_DataMissionHashes_instance`=" + TCPFrameInstance + ");";
SQLQueryTxt += "UPDATE `pe_DataMissionHashes` SET `pe_DataMissionHashes_datetime` = " + TCPFrameTimestamp + " WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.log_missionhash + "' AND `pe_DataMissionHashes_instance`=" + TCPFrameInstance + ";";
SQLQueryTxt += "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 ('" + TCPFrame.payload.log_arg_1 + "','" + TCPFrame.payload.log_arg_2 + "', NULL, '" + TCPFrame.payload.log_datetime + "', '" + TCPFrame.payload.log_type + "', '" + TCPFrame.payload.log_content + "', (SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.log_missionhash + "'));";
}
else if (strUDPFrameType == "52")
else if (TCPFrameType == "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
TCPFramePayload = JsonConvert.SerializeObject(TCPFrame.payload.stat_data_dcs); // Deserialize payload
TCPFramePayload_Perun = JsonConvert.SerializeObject(TCPFrame.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 + "');";
SQLQueryTxt = "INSERT INTO `pe_DataMissionHashes` (`pe_DataMissionHashes_hash`,`pe_DataMissionHashes_instance`) SELECT '" + TCPFrame.payload.stat_missionhash + "','" + TCPFrameInstance + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataMissionHashes` where `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.stat_missionhash + "' AND `pe_DataMissionHashes_instance`=" + TCPFrameInstance + ");";
SQLQueryTxt += "UPDATE `pe_DataMissionHashes` SET `pe_DataMissionHashes_datetime` = " + TCPFrameTimestamp + " WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.stat_missionhash + "' AND `pe_DataMissionHashes_instance`=" + TCPFrameInstance + " ;";
SQLQueryTxt += "INSERT INTO `pe_DataPlayers` (`pe_DataPlayers_ucid`) SELECT '" + TCPFrame.payload.stat_ucid + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataPlayers` where `pe_DataPlayers_ucid` = '" + TCPFrame.payload.stat_ucid + "');";
SQLQueryTxt += "UPDATE `pe_DataPlayers` SET `pe_DataPlayers_updated`=" + TCPFrameTimestamp + " WHERE `pe_DataPlayers_ucid`='" + TCPFrame.payload.stat_ucid + "';";
SQLQueryTxt += "INSERT INTO `pe_DataTypes` (`pe_DataTypes_name`) SELECT '" + TCPFrame.payload.stat_data_type + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataTypes` where `pe_DataTypes_name` = '" + TCPFrame.payload.stat_data_type + "');";
SQLQueryTxt += "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` = '" + TCPFrame.payload.stat_ucid + "'), (SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.stat_missionhash + "'), (SELECT pe_DataTypes_id FROM `pe_DataTypes` where `pe_DataTypes_name` = '" + TCPFrame.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` = '" + TCPFrame.payload.stat_missionhash + "') AND `pe_LogStats_playerid` = (SELECT `pe_DataPlayers_id` from `pe_DataPlayers` WHERE `pe_DataPlayers_ucid` = '" + TCPFrame.payload.stat_ucid + "') AND `pe_LogStats_typeid`= (SELECT pe_DataTypes_id FROM `pe_DataTypes` where `pe_DataTypes_name` = '" + TCPFrame.payload.stat_data_type + "'));";
SQLQueryTxt += "UPDATE `pe_LogStats` SET `ps_kills_fortification`=" + TCPFrame.payload.stat_data_perun.ps_kills_fortification + ",`ps_other_landings`=" + TCPFrame.payload.stat_data_perun.ps_other_landings + ",`ps_other_takeoffs`=" + TCPFrame.payload.stat_data_perun.ps_other_takeoffs + ",`ps_pvp`=" + TCPFrame.payload.stat_data_perun.ps_pvp + ",`ps_deaths`=" + TCPFrame.payload.stat_data_perun.ps_deaths + ",`ps_ejections`=" + TCPFrame.payload.stat_data_perun.ps_ejections + ",`ps_crashes`=" + TCPFrame.payload.stat_data_perun.ps_crashes + ",`ps_teamkills`=" + TCPFrame.payload.stat_data_perun.ps_teamkills + ",`ps_kills_planes`=" + TCPFrame.payload.stat_data_perun.ps_kills_planes + ",`ps_kills_helicopters`=" + TCPFrame.payload.stat_data_perun.ps_kills_helicopters + ",`ps_kills_air_defense`=" + TCPFrame.payload.stat_data_perun.ps_kills_air_defense + ",`ps_kills_armor`=" + TCPFrame.payload.stat_data_perun.ps_kills_armor + ",`ps_kills_unarmed`=" + TCPFrame.payload.stat_data_perun.ps_kills_unarmed + ",`ps_kills_infantry`=" + TCPFrame.payload.stat_data_perun.ps_kills_infantry + ",`ps_kills_ships`=" + TCPFrame.payload.stat_data_perun.ps_kills_ships + ",`ps_kills_other`=" + TCPFrame.payload.stat_data_perun.ps_kills_other + ",`ps_airfield_takeoffs`=" + TCPFrame.payload.stat_data_perun.ps_airfield_takeoffs + ",`ps_airfield_landings`=" + TCPFrame.payload.stat_data_perun.ps_airfield_landings + ",`ps_ship_takeoffs`=" + TCPFrame.payload.stat_data_perun.ps_ship_takeoffs + ",`ps_ship_landings`=" + TCPFrame.payload.stat_data_perun.ps_ship_landings + ",`ps_farp_takeoffs`=" + TCPFrame.payload.stat_data_perun.ps_farp_takeoffs + ",`ps_farp_landings`=" + TCPFrame.payload.stat_data_perun.ps_farp_landings + ", `pe_LogStats_datetime`='" + TCPFrame.payload.stat_datetime + "',`pe_LogStats_playerid` = (SELECT `pe_DataPlayers_id` from `pe_DataPlayers` WHERE `pe_DataPlayers_ucid` = '" + TCPFrame.payload.stat_ucid + "'),`pe_LogStats_missionhash_id`=(SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.stat_missionhash + "') WHERE `pe_LogStats_missionhash_id`=(SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.stat_missionhash + "') AND `pe_LogStats_playerid` = (SELECT `pe_DataPlayers_id` from `pe_DataPlayers` WHERE `pe_DataPlayers_ucid` = '" + TCPFrame.payload.stat_ucid + "') AND `pe_LogStats_typeid`=(SELECT pe_DataTypes_id FROM `pe_DataTypes` where `pe_DataTypes_name` = '" + TCPFrame.payload.stat_data_type + "');";
}
else if (strUDPFrameType == "53")
else if (TCPFrameType == "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 + "');";
SQLQueryTxt = "INSERT INTO `pe_DataPlayers` (`pe_DataPlayers_ucid`) SELECT '" + TCPFrame.payload.login_ucid + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataPlayers` where pe_DataPlayers_ucid='" + TCPFrame.payload.login_ucid + "');";
SQLQueryTxt += "UPDATE `pe_DataPlayers` SET pe_DataPlayers_lastip='" + TCPFrame.payload.login_ipaddr + "', pe_DataPlayers_lastname='" + TCPFrame.payload.login_name + "',pe_DataPlayers_updated='" + TCPFrame.payload.login_datetime + "' WHERE `pe_DataPlayers_ucid`= '" + TCPFrame.payload.login_ucid + "';";
SQLQueryTxt += "INSERT INTO `pe_LogLogins` (`pe_LogLogins_datetime`, `pe_LogLogins_playerid`, `pe_LogLogins_name`, `pe_LogLogins_ip`,`pe_LogLogins_instance`) VALUES ('" + TCPFrame.payload.login_datetime + "', (SELECT pe_DataPlayers_id from pe_DataPlayers WHERE pe_DataPlayers_ucid = '" + TCPFrame.payload.login_ucid + "'), '" + TCPFrame.payload.login_name + "', '" + TCPFrame.payload.login_ipaddr + "','" + TCPFrameInstance + "');";
}
else if (TCPFrameType == "-1")
{
// Keep alive message
SQLQueryTxt = "SELECT `pe_Config_payload` FROM `pe_Config` WHERE `pe_Config_id` = 1;";
}
else
{
// General definition used for 1-10 type packets
strUDPFramePayload = JsonConvert.SerializeObject(strUDPFrame.payload); // Deserialize payload
TCPFramePayload = JsonConvert.SerializeObject(TCPFrame.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 + ";";
SQLQueryTxt = "INSERT INTO `pe_DataRaw` (`pe_dataraw_type`,`pe_dataraw_instance`) SELECT '" + TCPFrameType + "','" + TCPFrameInstance + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataRaw` WHERE `pe_dataraw_type` = '" + TCPFrameType + "' AND `pe_dataraw_instance` = " + TCPFrameInstance + ");";
SQLQueryTxt += "UPDATE `pe_DataRaw` SET `pe_dataraw_payload` = JSON_QUOTE('" + TCPFramePayload + "'), `pe_dataraw_updated`=" + TCPFrameTimestamp + " WHERE `pe_dataraw_type`=" + TCPFrameType + " AND `pe_dataraw_instance` = " + TCPFrameInstance + ";";
}
// Connect to mysql and execute sql
try
{
connMySQL = new MySqlConnection(strMySQLConnectionString);
DatabaseConnection = new MySqlConnection(DatabaseConnectionString);
try
{
Console.WriteLine("Sending data to MySQL - Begin");
connMySQL.Open();
bStatus = true;
MySqlCommand cmdMySQL = new MySqlCommand(strSQLQueryTxt, connMySQL);
MySqlDataReader rdrMySQL = cmdMySQL.ExecuteReader();
DatabaseConnection.Open();
DatabaseStatus = true;
MySqlCommand DatabaseCommand = new MySqlCommand(SQLQueryTxt, DatabaseConnection);
MySqlDataReader DatabaseReader = DatabaseCommand.ExecuteReader();
while (rdrMySQL.Read())
if (DatabaseReader.HasRows)
{
Console.WriteLine(rdrMySQL[0] + " -- " + rdrMySQL[1]);
while (DatabaseReader.Read())
{
if (TCPFrameType == "-1")
{
Globals.VersionDatabase= DatabaseReader.GetString(0);
}
}
}
rdrMySQL.Close();
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#" + strUDPFrameInstance + " > MySQL updated, package type: " + strUDPFrameType);
else
{
// Do nothing
}
DatabaseReader.Close();
switch (Int32.Parse(TCPFrameType))
{
case 1:
PerunHelper.AddLog(ref Globals.AppLogHistory, "Connected players: " + TCPFrame.payload["c_players"], 1,0,"1");
break;
case 2:
PerunHelper.AddLog(ref Globals.AppLogHistory, "Mission: \"" + TCPFrame.payload["mission"]["name"]+"\""+ ", time:" + TCPFrame.payload["mission"]["modeltime"], 1, 0, "2");
break;
case 3:
PerunHelper.AddLog(ref Globals.AppLogHistory, "Slots data updated", 1, 0, "3");
break;
case 50:
PerunHelper.AddLog(ref Globals.AppLogHistory, "Player's \""+ TCPFrame.payload.player + "\" chat message saved", 1, 0, "50");
break;
case 51:
PerunHelper.AddLog(ref Globals.AppLogHistory, "Game event: \""+ TCPFrame.payload.log_content +"\"", 1, 0, "51");
break;
case 52:
PerunHelper.AddLog(ref Globals.AppLogHistory, "Player's \""+ TCPFrame.payload.stat_name + "\" stats saved", 1, 0, "52");
break;
case 53:
PerunHelper.AddLog(ref Globals.AppLogHistory, "Player \""+ TCPFrame.payload.login_name + "\" logged in", 1, 0, "53");
break;
case 100:
PerunHelper.AddLog(ref Globals.AppLogHistory, "SRS data send", 1,0,"100");
break;
case 101:
PerunHelper.AddLog(ref Globals.AppLogHistory, "LotATC data send", 1,0,"101");
break;
case -1:
break;
default:
PerunHelper.AddLog(ref Globals.AppLogHistory, "Data send", 1,0, TCPFrameType);
break;
}
}
catch (ArgumentException a_ex)
{
// General exception found
Console.WriteLine(a_ex.ToString());
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - package type: " + strUDPFrameType);
bStatus = false;
PerunHelper.AddLog(ref Globals.AppLogHistory, "ERROR MySQL - error: " + a_ex.Message,1,1, TCPFrameType);
Globals.ErrorsGame++;
DatabaseStatus = false;
ReturnValue = 0;
}
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");
PerunHelper.AddLog(ref Globals.AppLogHistory, "ERROR MySQL - unable to connect, error: " + m_ex.Message,1,1, TCPFrameType);
break;
case 0: // Access denied (Check DB name,username,password)
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - access denied");
PerunHelper.AddLog(ref Globals.AppLogHistory, "ERROR MySQL - access denied, error: " + m_ex.Message,1,1, TCPFrameType);
break;
default:
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - " + m_ex.Number);
PerunHelper.AddLog(ref Globals.AppLogHistory, "ERROR MySQL - error id: " + m_ex.Number,1,1, TCPFrameType);
PerunHelper.AddLog(ref Globals.AppLogHistory, "ERROR MySQL - query: " + SQLQueryTxt, 1, 1, TCPFrameType);
PerunHelper.AddLog(ref Globals.AppLogHistory, "ERROR MySQL - error: " + m_ex.Message,1,1, TCPFrameType);
break;
}
bStatus = false;
Globals.ErrorsGame++;
DatabaseStatus = false;
ReturnValue = 0;
}
connMySQL.Close();
DatabaseConnection.Close();
Console.WriteLine("Sending data to MySQL - Done");
}
catch (ArgumentException)
catch (ArgumentException x_ex)
{
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - wrong connection parameters");
PerunHelper.AddLog(ref Globals.AppLogHistory, "ERROR MySQL - unable to connect, error: " + x_ex.Message,1,1, TCPFrameType);
ReturnValue = 0;
Globals.ErrorsGame++;
}
return ReturnValue;
}
}

View File

@@ -1,10 +1,26 @@
// 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 = "";
public static string[] AppLogHistory = new string[10]; // Log history for GUI
public static bool AppUpdateGUI = true; // Flag if log control requires update
public static string AppTitle = ""; // Helper to update title
public static int AppInstanceID = 0; // Kepp the instance ID
public static bool AppForceIconReload = true; // Force main window icons reload
public static bool StatusDatabase = false; // Historic db connection status
public static bool StatusSRS = false; // Historic srs connection status
public static bool StatusLotATC = false; // Historic lotatc connection status
public static bool StatusHistoryConnection = false; // Historic tcp connection status
public static bool StatusConnection = false; // Flag if is TCP connectionstill alive
public static int ErrorsDatabase = 0; // MySQL - Error counter
public static int ErrorsGame = 0; // TCP connection - Error counter
public static int ErrorsHistoryGame = 0; // TCP connection - historic value of Error counter
public static int ErrorsSRS = 0; // DCS SRS - error counter
public static int ErrorsLotATC = 0; // LotATC - error counter
public static string VersionDCSHook = ""; // Version - DCS hook
public static string VersionDatabase = ""; // Version - Database
public static string VersionPerun = "DEBUG"; // Version - Perun
}

View File

@@ -0,0 +1,45 @@
using System;
using System.IO;
class LogController
{
// TBD - done via https://stackoverflow.com/questions/20185015/how-to-write-log-file-in-c
public static void WriteLog(string strLog)
{
StreamWriter LogStreamWriter;
FileStream LogFileStream = null;
DirectoryInfo LogDirectoryInfo = null;
FileInfo LogFileInfo;
string LogFilePath = Path.Combine(Environment.ExpandEnvironmentVariables("%userprofile%"), "Documents") + "\\Perun\\";
LogFilePath = LogFilePath + "Perun_Log_" + System.DateTime.Today.ToString("yyyyddMM") + "." + "txt";
LogFileInfo = new FileInfo(LogFilePath);
LogDirectoryInfo = new DirectoryInfo(LogFileInfo.DirectoryName);
if (!LogDirectoryInfo.Exists) LogDirectoryInfo.Create();
if (!LogFileInfo.Exists)
{
LogFileStream = LogFileInfo.Create();
}
else
{
try
{
LogFileStream = new FileStream(LogFilePath, FileMode.Append);
}
catch
{
// Do nothing
}
}
try
{
LogStreamWriter = new StreamWriter(LogFileStream);
LogStreamWriter.WriteLine(strLog);
LogStreamWriter.Close();
}
catch
{
// Do nothing
}
}
}

View File

@@ -1,13 +0,0 @@
// 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

@@ -1,26 +1,94 @@
// This class gathers all helper functions
using System;
using System.Reflection;
using System.Text.RegularExpressions;
internal class PerunHelper
{
public static void LogHistoryAdd(ref string[] arrLogHistory, string strEntryToAdd)
public static void AddLog(ref string[] arrLogHistory, string strEntryToAdd, int intDirection = 0, int intMarker = 0, string strType = " ", bool bSkipGui = false)
{
// Add entry to log history and rotate
for (int i = 0; i < arrLogHistory.Length - 1; i++)
// Declare values
string LogDirection;
string LogMarker;
// Set direction marker
switch (intDirection)
{
arrLogHistory[i] = arrLogHistory[i + 1]; // Shift one down
case 1:
LogDirection = ">";
break;
case 2:
LogDirection = "<";
break;
case 3:
LogDirection = "^";
break;
default:
LogDirection = " ";
break;
}
arrLogHistory[arrLogHistory.Length - 1] = DateTime.Now.ToString("HH:mm:ss") + " > " + strEntryToAdd; // Add entry at the last position
// Set marker for user flags (markers)
LogMarker = (intMarker>0) ? "X" : " ";
// Set frame type
strType=strType.PadLeft(3, ' ');
if (!bSkipGui)
{
// Rotate log history
for (int i = 0; i < arrLogHistory.Length - 1; i++)
{
arrLogHistory[i] = arrLogHistory[i + 1]; // Shift one down
}
// Add new entry
arrLogHistory[arrLogHistory.Length - 1] = DateTime.Now.ToString("HH:mm:ss") + " " + LogDirection + " " + strEntryToAdd; // Add entry at the last position
// Update control at my window
Globals.AppUpdateGUI = true;
}
// Add the entry to log file
LogController.WriteLog(DateTime.Now.ToString("yyyy-dd-MM ") + " " + DateTime.Now.ToString("HH:mm:ss") + " | Instance: "+ Globals.AppInstanceID + " | " + LogMarker + " | "+ LogDirection + " | "+ strType + " | " + strEntryToAdd);
}
public static string GetAppVersion(string strBeginning)
{
// Gets build version
if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed)
Globals.VersionPerun = Assembly.GetExecutingAssembly().GetName().Version.ToString();
return strBeginning + "v" + Globals.VersionPerun;
}
public static int CheckVersions()
{
// Checks the versions of APP, DCS Hook and MySQL database
Match match = Regex.Match(Globals.VersionPerun, @"^\d+.\d+.\d+", RegexOptions.Compiled | RegexOptions.IgnoreCase);
string VersionApp = "v" + match.Groups[0].Value;
int ReturnValue = 1;
if (!String.IsNullOrEmpty(Globals.VersionDatabase))
{
System.Deployment.Application.ApplicationDeployment cd = System.Deployment.Application.ApplicationDeployment.CurrentDeployment;
Globals.strPerunVersion = cd.CurrentVersion.ToString();
// Check database
if(VersionApp != Globals.VersionDatabase)
{
// Incorrect database version
PerunHelper.AddLog(ref Globals.AppLogHistory, "ERROR Incorrect database revision : "+ Globals.VersionDatabase, 1, 1, "?");
Globals.ErrorsDatabase++;
ReturnValue = 0;
}
}
return strBeginning+"v" + Globals.strPerunVersion;
if (!String.IsNullOrEmpty(Globals.VersionDCSHook))
{
// Check database
if (VersionApp != Globals.VersionDCSHook)
{
// Incorrect dcs script version
PerunHelper.AddLog(ref Globals.AppLogHistory, "ERROR Incorrect DCS hook revision : " + Globals.VersionDCSHook, 2, 1, "?");
Globals.ErrorsGame++;
ReturnValue = 0;
}
}
return ReturnValue;
}
}

View File

@@ -1,5 +1,4 @@
using System;
using System.Threading;
using System.Windows.Forms;
namespace Perun_v1
@@ -10,13 +9,11 @@ namespace Perun_v1
/// Main entry point to app
/// </summary>
// Mutex to block multiple instances
//static Mutex mutex = new Mutex(true, "{5a710507-92e9-4664-9b91-918b8b82f107}");
[STAThread]
static void Main()
{
// Main entry point to the app
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.ApplicationExit += new EventHandler(Application_ApplicationExit);

View File

@@ -4,50 +4,52 @@ using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
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 int intListenPort; // Port to connect to
public bool bCloseConnection; // Helper to exit main loop without killing thread
public string[] arrGUILogHistory; // Log history for GUI
public string[] arrMySQLSendBuffer; // MySQL send buffer
public Thread thrTCPListener; // Seperate thread for TCP
public void Create(int par_intListenPort, ref string[] par_arrLogHistory, ref string[] par_arrSendBuffer)
{
// Create class
// Create class and map creation arguments to class
intListenPort = par_intListenPort;
arrLogHistory = par_arrLogHistory;
arrSendBuffer = par_arrSendBuffer;
bDone = false;
bStatus = false;
arrGUILogHistory = par_arrLogHistory;
arrMySQLSendBuffer = par_arrSendBuffer;
bCloseConnection = false;
}
public void StopListen()
{
// Finish listening
bDone = true;
bStatus = false;
// Stop listening
bCloseConnection = true;
for (int i = 0; i < arrSendBuffer.Length - 1; i++)
// Clear send buffer
for (int i = 0; i < arrMySQLSendBuffer.Length - 1; i++)
{
arrSendBuffer[i] = null;
arrMySQLSendBuffer[i] = null;
}
}
public void StartListen()
{
NetworkStream ns=null;
TcpClient tcpClient=null;
// Start listening
NetworkStream nsReadStream = null;
TcpClient tcpClient = null;
bool bTCPConnectionOnline = false;
string strReceiveBuffer;
while (!bDone)
// Main loop - do until diconnect button is clicked
while (!bCloseConnection)
{
Console.WriteLine("TCP Listen start");
TcpListener tcpServer = new TcpListener(IPAddress.Any, intListenPort); ; // Listener object
TcpListener tcpServer = new TcpListener(IPAddress.Any, intListenPort); ; // Create listener object
try
{
@@ -56,80 +58,139 @@ public class TCPController
// Start the main loop
tcpServer.Start();
bStatus = true;
while (!bDone)
// While user do not clicked Disconnect button
while (!bCloseConnection)
{
// Start listening
Console.WriteLine("TCP: Waiting for connection");
Globals.StatusConnection = false;
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
// Wait for pending connection
if (tcpServer.Pending())
{
StringBuilder CompleteMessage = new StringBuilder();
Console.WriteLine("TCP: Connected");
bTCPConnectionOnline = true;
tcpClient = tcpServer.AcceptTcpClient(); //if a connection exists, the server will accept it
nsReadStream = tcpClient.GetStream(); //networkstream is used to send/receive messages
nsReadStream.ReadTimeout = 10000;
tcpClient.ReceiveTimeout = 10000;
if (ns.CanRead)
while (tcpClient.Connected && !bCloseConnection && bTCPConnectionOnline) //while the client is connected, we look for incoming messages
{
byte[] ReadBuffer = new byte[1024];
CompleteMessage = new StringBuilder();
int numberOfBytesRead = 0;
StringBuilder CompleteMessage = new StringBuilder();
Globals.StatusConnection = true;
// Incoming message may be larger than the buffer size.
do
if (nsReadStream.CanRead)
{
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);
Console.WriteLine("TCP: Can read");
byte[] ReadBuffer = new byte[1024];
CompleteMessage = new StringBuilder();
int numberOfBytesRead = 0;
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)
// Incoming message may be larger than the buffer size.
do
{
arrSendBuffer[i] = strReceivedData;
break;
Console.WriteLine("TCP: Read");
numberOfBytesRead = nsReadStream.Read(ReadBuffer, 0, ReadBuffer.Length);
CompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(ReadBuffer, 0, numberOfBytesRead));
if (numberOfBytesRead == 0)
{
break;
}
}
while (nsReadStream.DataAvailable && nsReadStream.CanRead && tcpClient.Connected);
}
strReceivedData = CompleteMessage.ToString();
Console.WriteLine("Sender: {0} Payload: {1}", null, strReceivedData);
string pattern = @"(\<SOT\>)+?.*?(\<EOT\>)+?";
foreach (Match match in Regex.Matches(strReceivedData, pattern))
{
strReceiveBuffer = match.Value;
Console.WriteLine("Found '{0}' at position {1} end {2}",match.Value, match.Index,match.Length);
Console.WriteLine("Prepared {0}", strReceiveBuffer.Substring(5, match.Length-10));
strReceivedData = strReceiveBuffer.Substring(5, match.Length - 10);
try
{
if (strReceivedData != "")
{
dynamic dynamicRawTCPFrame = JsonConvert.DeserializeObject(strReceivedData); // Deserialize received frame
string strRawTCPFrameType = dynamicRawTCPFrame.type;
// Check if this is NOT keep alive
if (Int32.Parse(strRawTCPFrameType) != 0)
{
// Add to mySQL send buffer (find first empty slot)
PerunHelper.AddLog(ref arrGUILogHistory, "Packet received" , 2,0, strRawTCPFrameType,true);
bool AddedDataToBuffer = false;
for (int i = 0; i < arrMySQLSendBuffer.Length - 1; i++)
{
if (arrMySQLSendBuffer[i] == null)
{
arrMySQLSendBuffer[i] = strReceivedData;
AddedDataToBuffer = true;
break;
}
}
if (!AddedDataToBuffer)
{
PerunHelper.AddLog(ref arrGUILogHistory, "ERROR package was dropped", 1, 1, strRawTCPFrameType);
}
} else
{
// Keep alive
PerunHelper.AddLog(ref arrGUILogHistory, "Keep-alive received", 2,0,"0",true);
}
}
else
{
bTCPConnectionOnline = false;
}
}
catch (Exception e)
{
Globals.ErrorsGame++;
Console.WriteLine(e.ToString());
PerunHelper.AddLog(ref arrGUILogHistory, "ERROR while message parsing , error: " + e.Message,2,1,"?");
bTCPConnectionOnline = false;
}
// Send empty byte to check if connection is still alive
try
{
tcpClient.Client.Send(new byte[] { 0 }, 1, 0);
}
catch (SocketException e)
{
Console.WriteLine(e.ToString());
PerunHelper.AddLog(ref arrGUILogHistory, "TCP ERROR cannot check connection, error: " + e.Message,2,1,"?");
}
}
}
catch(Exception e)
{
Console.WriteLine(e.ToString());
PerunHelper.LogHistoryAdd(ref arrLogHistory, "TCP ERROR incorrect JSON");
}
}
System.Threading.Thread.Sleep(500);
}
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");
}
Globals.ErrorsGame++;
Console.WriteLine(e.ToString());
PerunHelper.AddLog(ref arrGUILogHistory, "TCP error - connection closed or port in use, error: " + e.Message,1,1,"?");
bTCPConnectionOnline = false;
}
if (!(ns is null))
// Clean up and prepare for next connection
if (!(nsReadStream is null))
{
ns.Flush();
ns.Close();
nsReadStream.Flush();
nsReadStream.Close();
}
if (!(tcpClient is null))
{
@@ -139,7 +200,6 @@ public class TCPController
{
tcpServer.Stop();
}
bStatus = false;
Console.WriteLine("TCP listen stop");
}
}

View File

@@ -34,7 +34,7 @@
this.con_Button_Listen_ON = new System.Windows.Forms.Button();
this.con_Button_Listen_OFF = new System.Windows.Forms.Button();
this.con_GroupBox_1 = new System.Windows.Forms.GroupBox();
this.tim_1000ms = new System.Windows.Forms.Timer(this.components);
this.tim_GUI = new System.Windows.Forms.Timer(this.components);
this.con_GroupBox_2 = new System.Windows.Forms.GroupBox();
this.label6 = new System.Windows.Forms.Label();
this.con_txt_mysql_port = new System.Windows.Forms.TextBox();
@@ -57,22 +57,31 @@
this.trayIconMain = new System.Windows.Forms.NotifyIcon(this.components);
this.openFileDialog_SRS = 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_200ms = new System.Windows.Forms.Timer(this.components);
this.notifyIcon1 = new System.Windows.Forms.NotifyIcon(this.components);
this.tim_3rdparties = new System.Windows.Forms.Timer(this.components);
this.tim_MySQL = new System.Windows.Forms.Timer(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.label9 = new System.Windows.Forms.Label();
this.label10 = new System.Windows.Forms.Label();
this.label11 = new System.Windows.Forms.Label();
this.label12 = new System.Windows.Forms.Label();
this.con_Button_Reset_Flags = new System.Windows.Forms.Button();
this.label13 = new System.Windows.Forms.Label();
this.label14 = new System.Windows.Forms.Label();
this.con_img_logo = new System.Windows.Forms.PictureBox();
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_Button_Add_Marker = new System.Windows.Forms.Button();
this.con_GroupBox_1.SuspendLayout();
this.con_GroupBox_2.SuspendLayout();
this.con_GroupBox_3.SuspendLayout();
this.groupBox1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.con_img_logo)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.con_img_lotATC)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.con_img_srs)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.con_img_dcs)).BeginInit();
@@ -85,14 +94,14 @@
this.con_List_Received.FormattingEnabled = true;
this.con_List_Received.Items.AddRange(new object[] {
"Not connected"});
this.con_List_Received.Location = new System.Drawing.Point(6, 19);
this.con_List_Received.Location = new System.Drawing.Point(11, 19);
this.con_List_Received.Name = "con_List_Received";
this.con_List_Received.Size = new System.Drawing.Size(307, 147);
this.con_List_Received.Size = new System.Drawing.Size(307, 134);
this.con_List_Received.TabIndex = 0;
//
// con_Button_Listen_ON
//
this.con_Button_Listen_ON.Location = new System.Drawing.Point(12, 553);
this.con_Button_Listen_ON.Location = new System.Drawing.Point(12, 602);
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.TabIndex = 2;
@@ -103,7 +112,7 @@
// con_Button_Listen_OFF
//
this.con_Button_Listen_OFF.Enabled = false;
this.con_Button_Listen_OFF.Location = new System.Drawing.Point(104, 553);
this.con_Button_Listen_OFF.Location = new System.Drawing.Point(104, 602);
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.TabIndex = 3;
@@ -114,17 +123,17 @@
// con_GroupBox_1
//
this.con_GroupBox_1.Controls.Add(this.con_List_Received);
this.con_GroupBox_1.Location = new System.Drawing.Point(12, 369);
this.con_GroupBox_1.Location = new System.Drawing.Point(12, 434);
this.con_GroupBox_1.Name = "con_GroupBox_1";
this.con_GroupBox_1.Size = new System.Drawing.Size(324, 176);
this.con_GroupBox_1.Size = new System.Drawing.Size(324, 162);
this.con_GroupBox_1.TabIndex = 4;
this.con_GroupBox_1.TabStop = false;
this.con_GroupBox_1.Text = "Data log";
//
// tim_1000ms
// tim_GUI
//
this.tim_1000ms.Interval = 1000;
this.tim_1000ms.Tick += new System.EventHandler(this.timer1_Tick);
this.tim_GUI.Interval = 200;
this.tim_GUI.Tick += new System.EventHandler(this.Tim_GUI_Tick);
//
// con_GroupBox_2
//
@@ -138,7 +147,7 @@
this.con_GroupBox_2.Controls.Add(this.con_txt_mysql_database);
this.con_GroupBox_2.Controls.Add(this.con_txt_mysql_server);
this.con_GroupBox_2.Controls.Add(this.con_txt_mysql_password);
this.con_GroupBox_2.Location = new System.Drawing.Point(12, 27);
this.con_GroupBox_2.Location = new System.Drawing.Point(14, 54);
this.con_GroupBox_2.Name = "con_GroupBox_2";
this.con_GroupBox_2.Size = new System.Drawing.Size(324, 154);
this.con_GroupBox_2.TabIndex = 5;
@@ -232,7 +241,7 @@
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_srs);
this.con_GroupBox_3.Location = new System.Drawing.Point(12, 261);
this.con_GroupBox_3.Location = new System.Drawing.Point(14, 288);
this.con_GroupBox_3.Name = "con_GroupBox_3";
this.con_GroupBox_3.Size = new System.Drawing.Size(324, 68);
this.con_GroupBox_3.TabIndex = 6;
@@ -277,7 +286,7 @@
//
// con_Button_Quit
//
this.con_Button_Quit.Location = new System.Drawing.Point(251, 553);
this.con_Button_Quit.Location = new System.Drawing.Point(251, 602);
this.con_Button_Quit.Name = "con_Button_Quit";
this.con_Button_Quit.Size = new System.Drawing.Size(86, 39);
this.con_Button_Quit.TabIndex = 7;
@@ -288,9 +297,10 @@
// con_lab_github
//
this.con_lab_github.AutoSize = true;
this.con_lab_github.Location = new System.Drawing.Point(141, 9);
this.con_lab_github.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.con_lab_github.Location = new System.Drawing.Point(183, 39);
this.con_lab_github.Name = "con_lab_github";
this.con_lab_github.Size = new System.Drawing.Size(181, 13);
this.con_lab_github.Size = new System.Drawing.Size(155, 12);
this.con_lab_github.TabIndex = 8;
this.con_lab_github.TabStop = true;
this.con_lab_github.Text = "https://github.com/szporwolik/perun";
@@ -299,9 +309,10 @@
// label5
//
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(15, 9);
this.label5.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label5.Location = new System.Drawing.Point(183, 27);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(120, 13);
this.label5.Size = new System.Drawing.Size(102, 12);
this.label5.TabIndex = 9;
this.label5.Text = "Manual and bugtracker:";
//
@@ -323,19 +334,14 @@
//
this.openFileDialog_LotATC.FileName = "openFileDialog1";
//
// tim_10000ms
// tim_3rdparties
//
this.tim_10000ms.Interval = 30000;
this.tim_10000ms.Tick += new System.EventHandler(this.tim_10000ms_Tick);
this.tim_3rdparties.Interval = 30000;
this.tim_3rdparties.Tick += new System.EventHandler(this.tim_3rdparties_Tick);
//
// tim_200ms
// tim_MySQL
//
this.tim_200ms.Tick += new System.EventHandler(this.tim_200ms_Tick);
//
// notifyIcon1
//
this.notifyIcon1.Text = "notifyIcon1";
this.notifyIcon1.Visible = true;
this.tim_MySQL.Tick += new System.EventHandler(this.Tim_MySQL_Tick);
//
// groupBox1
//
@@ -343,7 +349,7 @@
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.Location = new System.Drawing.Point(14, 214);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(324, 68);
this.groupBox1.TabIndex = 7;
@@ -382,9 +388,96 @@
this.con_txt_dcs_server_port.Size = new System.Drawing.Size(207, 20);
this.con_txt_dcs_server_port.TabIndex = 3;
//
// label9
//
this.label9.AutoSize = true;
this.label9.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.label9.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label9.Location = new System.Drawing.Point(21, 396);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(61, 13);
this.label9.TabIndex = 1;
this.label9.Text = "Database";
//
// label10
//
this.label10.AutoSize = true;
this.label10.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.label10.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label10.Location = new System.Drawing.Point(117, 396);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(39, 13);
this.label10.TabIndex = 14;
this.label10.Text = "Game";
//
// label11
//
this.label11.AutoSize = true;
this.label11.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.label11.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label11.Location = new System.Drawing.Point(205, 396);
this.label11.Name = "label11";
this.label11.Size = new System.Drawing.Size(32, 13);
this.label11.TabIndex = 15;
this.label11.Text = "SRS";
//
// label12
//
this.label12.AutoSize = true;
this.label12.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.label12.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label12.Location = new System.Drawing.Point(282, 396);
this.label12.Name = "label12";
this.label12.Size = new System.Drawing.Size(49, 13);
this.label12.TabIndex = 16;
this.label12.Text = "LotATC";
//
// con_Button_Reset_Flags
//
this.con_Button_Reset_Flags.Enabled = false;
this.con_Button_Reset_Flags.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.con_Button_Reset_Flags.Location = new System.Drawing.Point(224, 414);
this.con_Button_Reset_Flags.Name = "con_Button_Reset_Flags";
this.con_Button_Reset_Flags.Size = new System.Drawing.Size(114, 20);
this.con_Button_Reset_Flags.TabIndex = 17;
this.con_Button_Reset_Flags.Text = "Reset error flags";
this.con_Button_Reset_Flags.UseVisualStyleBackColor = true;
this.con_Button_Reset_Flags.Click += new System.EventHandler(this.con_Button_Reset_Flags_Click);
//
// label13
//
this.label13.AutoSize = true;
this.label13.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label13.Location = new System.Drawing.Point(63, 7);
this.label13.Name = "label13";
this.label13.Size = new System.Drawing.Size(74, 25);
this.label13.TabIndex = 19;
this.label13.Text = "Perun";
//
// label14
//
this.label14.AutoSize = true;
this.label14.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label14.Location = new System.Drawing.Point(65, 32);
this.label14.Name = "label14";
this.label14.Size = new System.Drawing.Size(88, 13);
this.label14.TabIndex = 20;
this.label14.Text = "for DCS World";
//
// con_img_logo
//
this.con_img_logo.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
this.con_img_logo.Image = global::Perun_v1.Properties.Resources.perun_logo;
this.con_img_logo.Location = new System.Drawing.Point(12, 7);
this.con_img_logo.Name = "con_img_logo";
this.con_img_logo.Size = new System.Drawing.Size(45, 41);
this.con_img_logo.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.con_img_logo.TabIndex = 18;
this.con_img_logo.TabStop = false;
//
// con_img_lotATC
//
this.con_img_lotATC.Location = new System.Drawing.Point(307, 335);
this.con_img_lotATC.Location = new System.Drawing.Point(292, 362);
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;
@@ -393,7 +486,7 @@
//
// con_img_srs
//
this.con_img_srs.Location = new System.Drawing.Point(272, 335);
this.con_img_srs.Location = new System.Drawing.Point(207, 362);
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;
@@ -402,7 +495,7 @@
//
// con_img_dcs
//
this.con_img_dcs.Location = new System.Drawing.Point(237, 335);
this.con_img_dcs.Location = new System.Drawing.Point(122, 362);
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;
@@ -412,18 +505,39 @@
// 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.Location = new System.Drawing.Point(37, 362);
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;
//
// con_Button_Add_Marker
//
this.con_Button_Add_Marker.Enabled = false;
this.con_Button_Add_Marker.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.con_Button_Add_Marker.Location = new System.Drawing.Point(12, 414);
this.con_Button_Add_Marker.Name = "con_Button_Add_Marker";
this.con_Button_Add_Marker.Size = new System.Drawing.Size(114, 20);
this.con_Button_Add_Marker.TabIndex = 21;
this.con_Button_Add_Marker.Text = "Add log marker";
this.con_Button_Add_Marker.UseVisualStyleBackColor = true;
this.con_Button_Add_Marker.Click += new System.EventHandler(this.con_Button_Add_Marker_Click);
//
// form_Main
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(349, 604);
this.ClientSize = new System.Drawing.Size(349, 653);
this.Controls.Add(this.con_Button_Add_Marker);
this.Controls.Add(this.label14);
this.Controls.Add(this.label13);
this.Controls.Add(this.con_img_logo);
this.Controls.Add(this.con_Button_Reset_Flags);
this.Controls.Add(this.label12);
this.Controls.Add(this.label11);
this.Controls.Add(this.label10);
this.Controls.Add(this.label9);
this.Controls.Add(this.con_img_lotATC);
this.Controls.Add(this.con_img_srs);
this.Controls.Add(this.con_img_dcs);
@@ -440,10 +554,9 @@
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "form_Main";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Perun for DCS World";
this.Text = "Perun for DCS";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.form_Main_FormClosing);
this.Load += new System.EventHandler(this.form_Main_Load);
this.con_GroupBox_1.ResumeLayout(false);
@@ -453,6 +566,7 @@
this.con_GroupBox_3.PerformLayout();
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.con_img_logo)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.con_img_lotATC)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.con_img_srs)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.con_img_dcs)).EndInit();
@@ -468,7 +582,7 @@
private System.Windows.Forms.Button con_Button_Listen_ON;
private System.Windows.Forms.Button con_Button_Listen_OFF;
private System.Windows.Forms.GroupBox con_GroupBox_1;
private System.Windows.Forms.Timer tim_1000ms;
private System.Windows.Forms.Timer tim_GUI;
private System.Windows.Forms.GroupBox con_GroupBox_2;
private System.Windows.Forms.GroupBox con_GroupBox_3;
private System.Windows.Forms.TextBox con_txt_mysql_database;
@@ -489,11 +603,10 @@
private System.Windows.Forms.NotifyIcon trayIconMain;
private System.Windows.Forms.OpenFileDialog openFileDialog_SRS;
private System.Windows.Forms.OpenFileDialog openFileDialog_LotATC;
private System.Windows.Forms.Timer tim_10000ms;
private System.Windows.Forms.Timer tim_3rdparties;
private System.Windows.Forms.Label label6;
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.Timer tim_MySQL;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.MaskedTextBox con_txt_dcs_server_port;
private System.Windows.Forms.Label label7;
@@ -503,6 +616,15 @@
private System.Windows.Forms.PictureBox con_img_dcs;
private System.Windows.Forms.PictureBox con_img_srs;
private System.Windows.Forms.PictureBox con_img_lotATC;
private System.Windows.Forms.Label label9;
private System.Windows.Forms.Label label10;
private System.Windows.Forms.Label label11;
private System.Windows.Forms.Label label12;
private System.Windows.Forms.Button con_Button_Reset_Flags;
private System.Windows.Forms.PictureBox con_img_logo;
private System.Windows.Forms.Label label13;
private System.Windows.Forms.Label label14;
private System.Windows.Forms.Button con_Button_Add_Marker;
}
}

View File

@@ -1,40 +1,40 @@
using System;
using Newtonsoft.Json;
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 string[] DatabaseSendBuffer = new string[50]; // MySQL send buffer
public bool AppCanClose = false; // Helper to handle system tray - true needed to quit the app
public DatabaseController dcConnection = new DatabaseController(); // MySQL controller
public TCPController tcpcServer=new TCPController(); // TCP controller
public DatabaseController DatabaseConnection = new DatabaseController(); // Main MySQL controller
public TCPController TCPServer = new TCPController(); // Main TCP controller
public bool bSRSStatus; // Use empty/default SRS status
public bool bLotATCStatus; // Use empty/default LotATC status
public bool ExtSRSStatus; // True if to use empty/default SRS status
public bool ExtLotATCStatus; // True if to 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";
// Form loaded
Globals.AppLogHistory[0] = DateTime.Now.ToString("HH:mm:ss") + " > " + "Perun started"; // Add information to the log control
form_Main_LoadSettings(); // Load settings from registry
Globals.strPerunTitleText = PerunHelper.GetAppVersion(this.Text + " - "); // Display build version in title bar
this.Text = Globals.strPerunTitleText;
form_Main_LoadSettings(); // Load settings
// Display build version in title bar
Globals.AppTitle = PerunHelper.GetAppVersion(this.Text + " - ");
this.Text = Globals.AppTitle;
// Use command line parameters
string[] args = Environment.GetCommandLineArgs();
if (args.Length > 1)
{
// server port
// Get argument server port
if (args[1] != null)
{
con_txt_dcs_server_port.Text = args[1];
@@ -42,7 +42,7 @@ namespace Perun_v1
}
if (args.Length > 2)
{
// instance id
// Get argument instance id
if (args[2] != null)
{
con_txt_dcs_instance.Text = args[2];
@@ -50,7 +50,7 @@ namespace Perun_v1
}
if (args.Length > 3)
{
// srs
// Get argument DCS SRS file path
if (args[3] != null)
{
con_txt_3rd_srs.Text = args[3];
@@ -59,13 +59,19 @@ namespace Perun_v1
}
if (args.Length > 4)
{
// lotatc
// Get argument lotATC file path
if (args[4] != null)
{
con_txt_3rd_lotatc.Text = args[4];
con_check_3rd_lotatc.Checked = true;
}
}
// Initialize controls
con_img_db.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_disconnected");
con_img_dcs.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_disconnected");
con_img_lotATC.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_disconnected");
con_img_srs.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_disconnected");
}
public form_Main()
@@ -77,7 +83,7 @@ namespace Perun_v1
// ################################ Helpers ################################
private void form_Main_LoadSettings()
{
// Loads settings
// Loads registry 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;
@@ -89,12 +95,11 @@ namespace Perun_v1
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
// Saves registry 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;
@@ -112,11 +117,14 @@ namespace Perun_v1
Properties.Settings.Default.Save();
}
private void form_Main_DisableControls()
private void form_Main_SetControlsToConnected()
{
// Disables controls
con_Button_Listen_ON.Enabled = false;
con_Button_Add_Marker.Enabled = true;
con_Button_Listen_OFF.Enabled = true;
con_Button_Listen_ON.Enabled = false;
con_Button_Quit.Enabled = false;
con_Button_Reset_Flags.Enabled = true;
con_txt_mysql_database.Enabled = false;
con_txt_mysql_username.Enabled = false;
con_txt_mysql_password.Enabled = false;
@@ -130,11 +138,14 @@ namespace Perun_v1
con_txt_dcs_instance.Enabled = false;
}
private void form_Main_EnableControls()
private void form_Main_SetControlsToDisconnected()
{
// Enables controls
con_Button_Listen_ON.Enabled = true;
con_Button_Reset_Flags.Enabled = false;
con_Button_Listen_OFF.Enabled = false;
con_Button_Listen_ON.Enabled = true;
con_Button_Quit.Enabled = true;
con_Button_Add_Marker.Enabled = false;
con_txt_mysql_database.Enabled = true;
con_txt_mysql_username.Enabled = true;
con_txt_mysql_password.Enabled = true;
@@ -146,79 +157,103 @@ namespace Perun_v1
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";
// Set globals
Globals.AppInstanceID = Int32.Parse(con_txt_dcs_instance.Text);
Globals.AppForceIconReload = true;
Globals.ErrorsDatabase = 0; // Reset error counter
Globals.ErrorsGame = 0; // Reset error counter
Globals.ErrorsSRS = 0; // Reset error counter
Globals.ErrorsLotATC = 0; // Reset error counter
Globals.StatusConnection = false; // Reset connection status
form_Main_DisableControls(); // Disable controlls
form_Main_SaveSettings(); // Save settings
// Prepare GUI
form_Main_SetControlsToConnected();
form_Main_SaveSettings();
this.Text = "[#" + con_txt_dcs_instance.Text + "] " + Globals.AppTitle; // Set title bar
trayIconMain.Text = this.Text; // Set notification icon text
// 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;
// Prepare MySQL connection string
DatabaseConnection.DatabaseConnectionString = "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 listening
PerunHelper.AddLog(ref Globals.AppLogHistory, "Opening connections",0,1);
TCPServer.Create(Int32.Parse(con_txt_dcs_server_port.Text), ref Globals.AppLogHistory, ref DatabaseSendBuffer);
TCPServer.thrTCPListener = new Thread(TCPServer.StartListen);
TCPServer.thrTCPListener.Start();
TCPServer.thrTCPListener.Name = "TCPThread";
// Start timmers
tim_200ms.Enabled = true;
tim_1000ms.Enabled = true;
tim_10000ms.Enabled = true;
tim_MySQL.Enabled = true;
tim_GUI.Enabled = true;
tim_3rdparties.Enabled = true;
// Send initial data
tim_10000ms_Tick(null, null);
// Set title bar
this.Text = "[#"+ con_txt_dcs_instance.Text + "] " + Globals.strPerunTitleText;
Tim_MySQL_Tick(null, null);
tim_3rdparties_Tick(null, null);
}
private void con_Button_Listen_OFF_Click(object sender, EventArgs e)
{
// Stop listening
// Display information
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "Closing connections");
// Prepare GUI
PerunHelper.AddLog(ref Globals.AppLogHistory, "Closing connections",0,1);
con_Button_Listen_OFF.Enabled = false;
timer1_Tick(null, null);
Tim_GUI_Tick(null, null);
this.Refresh();
Application.DoEvents();
// Stop timmers
tim_GUI.Enabled = false;
tim_3rdparties.Enabled = false;
tim_MySQL.Enabled = false;
try
{
tcpcServer.StopListen();
// Stop the server
TCPServer.StopListen();
}
catch (Exception ex)
{
PerunHelper.AddLog(ref Globals.AppLogHistory, "TCP ERROR, error: " + ex.Message, 2, 1, "?");
Console.WriteLine(ex.ToString());
}
while (tcpcServer.thrTCPListener.IsAlive)
while (TCPServer.thrTCPListener.IsAlive)
{
Thread.Sleep(100); //ms
// Wait untill TCP server closed connection
Thread.Sleep(200); //ms
}
form_Main_EnableControls(); // Enable controls
form_Main_SetControlsToDisconnected(); // 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;
// Load status images
con_img_db.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_disconnected");
con_img_dcs.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_disconnected");
con_img_lotATC.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_disconnected");
con_img_srs.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_disconnected");
// Display information about closed connections
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "Connections closed");
timer1_Tick(null, null);
PerunHelper.AddLog(ref Globals.AppLogHistory, "Connections closed",0,1);
Tim_GUI_Tick(null, null);
// Set title bar
this.Text = Globals.strPerunTitleText;
this.Text = Globals.AppTitle;
trayIconMain.Text = this.Text;
// Set globals
Globals.AppInstanceID = 0;
Globals.AppUpdateGUI = false;
Globals.StatusDatabase = false;
Globals.StatusHistoryConnection = false;
Globals.StatusSRS = false;
Globals.StatusLotATC = false;
Globals.StatusConnection = false;
}
private void con_lab_github_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
@@ -261,13 +296,13 @@ namespace Perun_v1
// ################################ Form state ################################
private void con_Button_Quit_Click(object sender, EventArgs e)
{
// Close app
// Try to 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
AppCanClose = true; // Save settings on exit
this.Close(); // Allow to exit application
}
else if (dialogResult == DialogResult.No)
@@ -276,16 +311,6 @@ namespace Perun_v1
}
}
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
@@ -313,11 +338,10 @@ namespace Perun_v1
TopMost = top;
}
private void form_Main_FormClosing(object sender, FormClosingEventArgs e)
{
// Minimize to try on clicking "X"
if (e.CloseReason == CloseReason.UserClosing && !bLetMeOut)
if (e.CloseReason == CloseReason.UserClosing && !AppCanClose)
{
e.Cancel = true;
form_Main_SendToTray(); // Send app to system tray
@@ -331,169 +355,286 @@ namespace Perun_v1
}
// ################################ Timers ################################
private void timer1_Tick(object sender, EventArgs e)
private void Tim_GUI_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 (Globals.AppUpdateGUI)
{
if (i != null)
con_List_Received.Items.Clear();
foreach (string i in Globals.AppLogHistory)
{
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 (i != null)
{
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();
}
con_List_Received.Items.Add(i);
}
}
Globals.AppUpdateGUI = false;
}
else
{
// Do nothing , control does not require update
}
if (raw_lotatc.Count > 0)
// Update status icons at main form - MySQL
if ((DatabaseConnection.DatabaseStatus != Globals.StatusDatabase) || Globals.AppForceIconReload)
{
if (DatabaseConnection.DatabaseStatus)
{
if (Globals.ErrorsDatabase == 0)
{
strSRSJson = JsonConvert.SerializeObject(raw_lotatc);
strSRSJson = "{'type':'100','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':'" + strSRSJson + "'}";
con_img_db.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_connected");
}
else
{
strSRSJson = "{'type':'100','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':{'ignore':'false'}}"; // No SRS clients connected
con_img_db.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_connected_error");
}
boolSRSdefault = false;
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#" + Int32.Parse(con_txt_dcs_instance.Text) + " > SRS data loaded");
bSRSStatus = true;
}
catch
else
{
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#" + Int32.Parse(con_txt_dcs_instance.Text) + " > SRS data ERROR");
bSRSStatus = false;
con_img_db.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_disconnected_error");
}
Globals.StatusDatabase = DatabaseConnection.DatabaseStatus;
}
if (boolSRSdefault)
// Update status icons at main form - DCS
if ((Globals.StatusConnection != Globals.StatusHistoryConnection) || Globals.AppForceIconReload || Globals.ErrorsGame != Globals.ErrorsHistoryGame)
{
strSRSJson = "{'type':'100','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':{'ignore':'true'}}";
if (Globals.StatusConnection)
{
if (Globals.ErrorsGame == 0)
{
con_img_dcs.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_connected");
}
else
{
con_img_dcs.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_connected_error");
}
}
else
{
con_img_dcs.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_disconnected_error");
}
Globals.StatusHistoryConnection = Globals.StatusConnection;
Globals.ErrorsHistoryGame = Globals.ErrorsGame;
}
// Update status icons at main form - SRS
if ((ExtSRSStatus != Globals.StatusSRS) || Globals.AppForceIconReload)
{
if (ExtSRSStatus && con_check_3rd_srs.Checked)
{
if (Globals.ErrorsSRS == 0)
{
con_img_srs.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_connected");
}
else
{
con_img_srs.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_connected_error");
}
}
else
{
con_img_srs.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_disconnected_error");
}
Globals.StatusSRS = ExtSRSStatus;
}
// Update status icons at main form - LotATC
if ((ExtLotATCStatus != Globals.StatusLotATC) || Globals.AppForceIconReload)
{
if (ExtLotATCStatus && con_check_3rd_lotatc.Checked)
{
if (Globals.ErrorsLotATC == 0)
{
con_img_lotATC.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_connected");
}
else
{
con_img_lotATC.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_connected_error");
}
}
else
{
con_img_lotATC.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_disconnected_error");
}
Globals.StatusLotATC = ExtLotATCStatus;
}
Globals.AppForceIconReload = false;
}
private void Tim_MySQL_Tick(object sender, EventArgs e)
{
// Send buffer to MySQL
for (int i = 0; i < DatabaseSendBuffer.Length - 1; i++)
{
if (DatabaseSendBuffer[i] != null)
{
if (DatabaseConnection.SendToMySql(DatabaseSendBuffer[i]) > 0)
{
DatabaseSendBuffer[i] = null; // If packet was send then delete it from send buffer
}
}
}
}
private void tim_3rdparties_Tick(object sender, EventArgs e)
{
// Main timer to check MySQL connection and send JSON files to MySQL
// Send ping to check for possible connection issues
DatabaseConnection.SendToMySql("", true);
if (PerunHelper.CheckVersions()==0)
{
MessageBox.Show("Version mismatch detected - please check log files and update.\n\nPerun will now terminate.", "Perun ERROR!",MessageBoxButtons.OK,MessageBoxIcon.Error);
con_Button_Listen_OFF_Click(null, null);
}
// Take care of 3rd party stuff
string ExtSRSJson = "";
string ExtLotATCJson = "";
bool ExtSRSUseDefault = true;
bool ExtLotATCUseDefault = true;
// Handle SRS
if (Globals.StatusConnection)
{
if (con_check_3rd_srs.Checked)
{
try
{
ExtSRSJson = System.IO.File.ReadAllText(con_txt_3rd_srs.Text);
dynamic raw_lotatc = JsonConvert.DeserializeObject(ExtSRSJson);
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)
{
ExtSRSJson = JsonConvert.SerializeObject(raw_lotatc);
ExtSRSJson = "{'type':'100','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':'" + ExtSRSJson + "'}";
}
else
{
ExtSRSJson = "{'type':'100','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':{'ignore':'false'}}"; // No SRS clients connected
}
ExtSRSUseDefault = false;
PerunHelper.AddLog(ref Globals.AppLogHistory, "SRS data loaded", 3, 0, "100", true);
ExtSRSStatus = true;
}
catch (Exception exc_srs)
{
PerunHelper.AddLog(ref Globals.AppLogHistory, "SRS data ERROR , error: " + exc_srs.Message, 3, 1, "100");
ExtSRSStatus = false;
Globals.ErrorsSRS++;
}
}
if (ExtSRSUseDefault)
{
ExtSRSJson = "{'type':'100','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':{'ignore':'true'}}";
}
DatabaseConnection.SendToMySql(ExtSRSJson);
}
dcConnection.SendToMySql(strSRSJson);
// Handle LotATC
if (con_check_3rd_lotatc.Checked)
if (Globals.StatusConnection)
{
try
if (con_check_3rd_lotatc.Checked)
{
strLotATCJson = System.IO.File.ReadAllText(con_txt_3rd_lotatc.Text);
dynamic raw_srs = JsonConvert.DeserializeObject(strLotATCJson);
try
{
ExtLotATCJson = System.IO.File.ReadAllText(con_txt_3rd_lotatc.Text);
dynamic raw_srs = JsonConvert.DeserializeObject(ExtLotATCJson);
ExtLotATCJson = "{'type':'101','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':'" + ExtLotATCJson + "'}";
ExtLotATCUseDefault = false;
PerunHelper.AddLog(ref Globals.AppLogHistory, "LotATC data loaded", 3, 0, "101", true);
ExtLotATCStatus = true;
}
catch (Exception exc_lotatc)
{
PerunHelper.AddLog(ref Globals.AppLogHistory, "LotATC data ERROR, error: " + exc_lotatc.Message, 3, 1, "101");
ExtLotATCStatus = false;
Globals.ErrorsLotATC++;
}
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
if (ExtLotATCUseDefault)
{
PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#" + Int32.Parse(con_txt_dcs_instance.Text) + " > LotATC data ERROR");
bLotATCStatus = false;
ExtLotATCJson = "{'type':'101','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':{'ignore':'true'}}"; // No LotATC controller connected
}
DatabaseConnection.SendToMySql(ExtLotATCJson);
}
if (boolLotATCdefault)
// Let's do not risk int overload
Globals.ErrorsDatabase = (Globals.ErrorsDatabase > 999) ? 999 : Globals.ErrorsDatabase;
Globals.ErrorsGame = (Globals.ErrorsGame > 999) ? 999 : Globals.ErrorsGame;
Globals.ErrorsSRS = (Globals.ErrorsSRS > 999) ? 999 : Globals.ErrorsSRS;
Globals.ErrorsLotATC = (Globals.ErrorsLotATC > 999) ? 999 : Globals.ErrorsLotATC;
}
private void con_Button_Reset_Flags_Click(object sender, EventArgs e)
{
// Reset error flags
DialogResult dialogResult = MessageBox.Show("Are you sure to reset error flags?", "Question", MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question);
if (dialogResult == DialogResult.Yes)
{
strLotATCJson = "{'type':'101','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':{'ignore':'true'}}"; // No LotATC controller connected
// Reset errors counter
Globals.ErrorsDatabase = 0; // MySQL - Error counter
Globals.ErrorsGame = 0; // TCP connection - Error counter
Globals.ErrorsHistoryGame = 0; // TCP connection - historic value of Error counter
Globals.ErrorsSRS = 0; // DCS SRS - error counter
Globals.ErrorsLotATC = 0; // LotATC - error counter
// Force icons reload
Globals.AppForceIconReload = true;
// Add information
PerunHelper.AddLog(ref Globals.AppLogHistory, "Resetted error counter",0,1);
}
dcConnection.SendToMySql(strLotATCJson);
else if (dialogResult == DialogResult.No)
{
// Do nothing
}
}
private void con_Button_Add_Marker_Click(object sender, EventArgs e)
{
// Added user marker
PerunHelper.AddLog(ref Globals.AppLogHistory, "User Marker",0,1);
}
}
}

View File

@@ -117,7 +117,7 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="tim_1000ms.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<metadata name="tim_GUI.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="trayIconMain.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
@@ -413,14 +413,14 @@
<metadata name="openFileDialog_LotATC.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>397, 17</value>
</metadata>
<metadata name="tim_10000ms.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<metadata name="tim_3rdparties.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>563, 19</value>
</metadata>
<metadata name="tim_200ms.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<metadata name="tim_MySQL.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 name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>26</value>
</metadata>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 909 B

View File

@@ -34,7 +34,7 @@
<CreateWebPageOnPublish>true</CreateWebPageOnPublish>
<WebPage>Perun.htm</WebPage>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>0.8.0.%2a</ApplicationVersion>
<ApplicationVersion>0.8.3.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<CreateDesktopShortcut>true</CreateDesktopShortcut>
<PublishWizardCompleted>true</PublishWizardCompleted>
@@ -49,6 +49,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>SecurityRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -123,32 +124,30 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="01_Classes\LogController.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>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Compile>
<Compile Include="02_Forms\form_Main.Designer.cs">
<DependentUpon>form_Main.cs</DependentUpon>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Compile>
<Compile Include="01_Classes\Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="02_Forms\form_Main.resx">
<DependentUpon>form_Main.cs</DependentUpon>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="00_Config\packages.config" />
<None Include="00_Config\Perun_v1_TemporaryKey.pfx" />
<None Include="app.config" />
@@ -158,6 +157,11 @@
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
@@ -181,12 +185,12 @@
</ItemGroup>
<ItemGroup>
<Content Include="03_Resources\perun_logo.ico" />
<None Include="Resources\ico_error.png" />
<None Include="Resources\ico_srs.png" />
<None Include="Resources\ico_lotatc.png" />
<None Include="Resources\ico_game.png" />
<None Include="Resources\ico_db.png" />
<None Include="Resources\img_db.png" />
<None Include="03_Resources\perun_logo.png" />
<None Include="Resources\perun_logo.png" />
<None Include="Resources\status-connected-error.png" />
<None Include="Resources\status-disconnected-error.png" />
<None Include="Resources\status-disconnected.png" />
<None Include="Resources\status-connected.png" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

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
// przy użyciu symbolu „*”, tak jak pokazano poniżej:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.8.0.0")]
[assembly: AssemblyFileVersion("0.8.0.0")]
[assembly: AssemblyVersion("0.8.3.0")]
[assembly: AssemblyFileVersion("0.8.3.0")]
[assembly: NeutralResourcesLanguage("en")]

View File

@@ -63,9 +63,9 @@ namespace Perun_v1.Properties {
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ico_db {
internal static System.Drawing.Bitmap perun_logo {
get {
object obj = ResourceManager.GetObject("ico_db", resourceCulture);
object obj = ResourceManager.GetObject("perun_logo", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
@@ -73,9 +73,9 @@ namespace Perun_v1.Properties {
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ico_error {
internal static System.Drawing.Bitmap status_connected {
get {
object obj = ResourceManager.GetObject("ico_error", resourceCulture);
object obj = ResourceManager.GetObject("status_connected", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
@@ -83,9 +83,9 @@ namespace Perun_v1.Properties {
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ico_game {
internal static System.Drawing.Bitmap status_connected_error {
get {
object obj = ResourceManager.GetObject("ico_game", resourceCulture);
object obj = ResourceManager.GetObject("status_connected_error", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
@@ -93,9 +93,9 @@ namespace Perun_v1.Properties {
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ico_lotatc {
internal static System.Drawing.Bitmap status_disconnected {
get {
object obj = ResourceManager.GetObject("ico_lotatc", resourceCulture);
object obj = ResourceManager.GetObject("status_disconnected", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
@@ -103,9 +103,9 @@ namespace Perun_v1.Properties {
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap ico_srs {
internal static System.Drawing.Bitmap status_disconnected_error {
get {
object obj = ResourceManager.GetObject("ico_srs", resourceCulture);
object obj = ResourceManager.GetObject("status_disconnected_error", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}

View File

@@ -118,19 +118,19 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</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 name="perun_logo" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\03_Resources\perun_logo.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 name="status_connected" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\03_Resources\status-connected.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 name="status_connected_error" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\03_Resources\status-connected-error.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 name="status_disconnected" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\03_Resources\status-disconnected.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 name="status_disconnected_error" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\03_Resources\status-disconnected-error.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

View File

Before

Width:  |  Height:  |  Size: 233 B

After

Width:  |  Height:  |  Size: 233 B

View File

@@ -8,6 +8,45 @@ SET time_zone = "+00:00";
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
CREATE DATABASE IF NOT EXISTS `m1081_perun` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USE `m1081_perun`;
DELIMITER $$
DROP PROCEDURE IF EXISTS `sp_CleanDatabase`$$
CREATE DEFINER=`m1081`@`%.devil` PROCEDURE `sp_CleanDatabase` () MODIFIES SQL DATA
BEGIN
DELETE FROM pe_DataMissionHashes;
DELETE FROM pe_DataPlayers;
DELETE FROM pe_DataRaw;
DELETE FROM pe_LogChat;
DELETE FROM pe_LogEvent;
DELETE FROM pe_LogLogins;
DELETE FROM pe_LogStats;
ALTER TABLE pe_DataMissionHashes AUTO_INCREMENT = 1;
ALTER TABLE pe_DataPlayers AUTO_INCREMENT = 1;
ALTER TABLE pe_DataRaw AUTO_INCREMENT = 1;
ALTER TABLE pe_LogChat AUTO_INCREMENT = 1;
ALTER TABLE pe_LogEvent AUTO_INCREMENT = 1;
ALTER TABLE pe_LogLogins AUTO_INCREMENT = 1;
ALTER TABLE pe_LogStats AUTO_INCREMENT = 1;
END$$
DROP PROCEDURE IF EXISTS `sp_SyncForumGame`$$
$$
DELIMITER ;
DROP TABLE IF EXISTS `pe_Config`;
CREATE TABLE IF NOT EXISTS `pe_Config` (
`pe_Config_id` int(11) NOT NULL,
`pe_Config_payload` varchar(255) DEFAULT NULL,
PRIMARY KEY (`pe_Config_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `pe_Config` (`pe_Config_id`, `pe_Config_payload`) VALUES
(1, 'v0.8.3');
DROP TABLE IF EXISTS `pe_DataMissionHashes`;
CREATE TABLE IF NOT EXISTS `pe_DataMissionHashes` (
@@ -18,7 +57,7 @@ CREATE TABLE IF NOT EXISTS `pe_DataMissionHashes` (
PRIMARY KEY (`pe_DataMissionHashes_id`),
UNIQUE KEY `UNIQUE_hash` (`pe_DataMissionHashes_hash`),
KEY `pe_DataMissionHashes_instance` (`pe_DataMissionHashes_instance`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
) ENGINE=InnoDB AUTO_INCREMENT=818 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `pe_DataPlayers`;
CREATE TABLE IF NOT EXISTS `pe_DataPlayers` (
@@ -29,7 +68,7 @@ CREATE TABLE IF NOT EXISTS `pe_DataPlayers` (
`pe_DataPlayers_updated` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`pe_DataPlayers_id`),
UNIQUE KEY `UNIQUE_UCID` (`pe_DataPlayers_ucid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
) ENGINE=InnoDB AUTO_INCREMENT=219 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `pe_DataRaw`;
CREATE TABLE IF NOT EXISTS `pe_DataRaw` (
@@ -47,7 +86,7 @@ CREATE TABLE IF NOT EXISTS `pe_DataTypes` (
`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;
) ENGINE=InnoDB AUTO_INCREMENT=57 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `pe_LogChat`;
CREATE TABLE IF NOT EXISTS `pe_LogChat` (
@@ -61,7 +100,7 @@ CREATE TABLE IF NOT EXISTS `pe_LogChat` (
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 AUTO_INCREMENT=19739 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `pe_LogEvent`;
CREATE TABLE IF NOT EXISTS `pe_LogEvent` (
@@ -75,7 +114,7 @@ CREATE TABLE IF NOT EXISTS `pe_LogEvent` (
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 AUTO_INCREMENT=93657 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `pe_LogLogins`;
CREATE TABLE IF NOT EXISTS `pe_LogLogins` (
@@ -88,7 +127,7 @@ CREATE TABLE IF NOT EXISTS `pe_LogLogins` (
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 AUTO_INCREMENT=10742 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `pe_LogStats`;
CREATE TABLE IF NOT EXISTS `pe_LogStats` (
@@ -132,7 +171,7 @@ CREATE TABLE IF NOT EXISTS `pe_LogStats` (
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 AUTO_INCREMENT=9595 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

View File

@@ -2,25 +2,24 @@
![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 logo](https://i.imgur.com/JkeHYjJ.png)
# Perun for DCS World
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 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 MySQL data and/or JSON file; you will need to process/display it yourself.
![Perun in action](https://i.imgur.com/vHw8Xu5.png)
![Perun in action](https://i.imgur.com/MieyBej.png)
![Data flow](https://i.imgur.com/JbNu77l.png)
## Prerequisites
Core:
* For JSON Export:
* DCS World stable or DCS World beta
* **(Optional)** For MySQL Export:
* MySQL database with read/write access (tested with v5.7.21)
* MySQL database with read/write access running at min. 5.7 server (tested with v5.7.21; native JSON support is required)
* .NET Framework 4.8.0
3rd party applications support:
@@ -28,7 +27,6 @@ Core:
* 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
* 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)
* **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
@@ -57,6 +55,15 @@ 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"
```
## Troubleshooting - FAQ
- [I keep getting 1305 MySQL error](#i-keep-getting-1305-mysql-error)
- [Carrier landing are not tracked correctly](#carrier-landing-are-not-tracked-correctly)
### I keep getting 1305 MySQL error
That probably means that your database does not support JSON functions, you shall upgrade your MySQL server to at lease 5.7 version.
### Carrier landing are not tracked correctly
DCS API does not track carrier landing natively, so there is a trick to achive that. You shall set your carrier to a propoer group name to have landings tracked.
# API documentation (for expert users)
## MySQL database structure
@@ -71,48 +78,48 @@ C:\Perun_v1\Perun.exe 48621 1 "G:\DCS SRS\clients-list.json" "C:\Users\DCS\Saved
## Data packets - send from lua to TCP port
* ```ID: 1```, contains version/diagnostic information
* perun version - for server administration usage
* player count - actual number of connected players
* ```ID: 2```, contains status data in the following sections
* mission - minimal information about mission
* mission name - name of the mission file
* model time - simulation time
* real time - real time
* pause - information if server is paused
* multiplayer - information if this is multiplayer game (always true for dedicated server usage)
* theather - information about area of operation
* weather - basic weather information
* players - connected players
* ```ID: 3```, available slots list and coalitions
* coalitions - available coalitions
* slots - available slots
* ```ID: 4```, stores mission data
* ```ID: 4```, stores mission data ; idea is to have whole DCS.getCurrentMission() result - currenlty commented out due to performance issues
* ```ID: 50```, chat event
* ```ID: 51```, game event
* ```ID: 52```, player stats
* ```ID: 52```, player stats ; note that as DSC native stats are not reliable, seperate stats couting methods are used
* ```ID: 53```, player login to DCS server
* ```ID: 100```, DCS SRS's client-list.json
* ```ID: 101```, LotATC's stats.json
# Project information
## Built With
* [VisualStudio 2017 Community](https://visualstudio.microsoft.com/vs/community/)
* [Notepad++](https://notepad-plus-plus.org/)
## used 3rd party resources
* [Tango Icon Library](http://tango.freedesktop.org/Tango_Icon_Library)
## Contributing
Please contact me if you'd like to contribute.
## Versioning
We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/szporwolik/perun/tags).
## Authors
* **Szymon Porwolik** - *Initial work* - [szporwolik](https://github.com/szporwolik)
See also the list of [contributors](https://github.com/szporwolik/perun/contributors) who participated in this project.
## License
This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details
## Acknowledgments
![Gildia.org Logo](https://images.weserv.nl/?url=https://i.imgur.com/nFHxQMy.png&w=140&il)
* Thanks to [Gildia DCS](https://forum.gildia.org) Polish community of DCS World pilots.
Thanks to [Gildia DCS](https://forum.gildia.org) Polish community of DCS World pilots.