local Keys = {
[ "ESC" ] = 322 , [ "F1" ] = 288 , [ "F2" ] = 289 , [ "F3" ] = 170 , [ "F5" ] = 166 , [ "F6" ] = 167 , [ "F7" ] = 168 , [ "F8" ] = 169 , [ "F9" ] = 56 , [ "F10" ] = 57 ,
[ "~" ] = 243 , [ "1" ] = 157 , [ "2" ] = 158 , [ "3" ] = 160 , [ "4" ] = 164 , [ "5" ] = 165 , [ "6" ] = 159 , [ "7" ] = 161 , [ "8" ] = 162 , [ "9" ] = 163 , [ "-" ] = 84 , [ "=" ] = 83 , [ "BACKSPACE" ] = 177 ,
[ "TAB" ] = 37 , [ "Q" ] = 44 , [ "W" ] = 32 , [ "E" ] = 38 , [ "R" ] = 45 , [ "T" ] = 245 , [ "Y" ] = 246 , [ "U" ] = 303 , [ "P" ] = 199 , [ "[" ] = 39 , [ "]" ] = 40 , [ "ENTER" ] = 18 ,
[ "CAPS" ] = 137 , [ "A" ] = 34 , [ "S" ] = 8 , [ "D" ] = 9 , [ "F" ] = 23 , [ "G" ] = 47 , [ "H" ] = 74 , [ "K" ] = 311 , [ "L" ] = 182 ,
[ "LEFTSHIFT" ] = 21 , [ "Z" ] = 20 , [ "X" ] = 73 , [ "C" ] = 26 , [ "V" ] = 0 , [ "B" ] = 29 , [ "N" ] = 249 , [ "M" ] = 244 , [ "," ] = 82 , [ "." ] = 81 ,
[ "LEFTCTRL" ] = 36 , [ "LEFTALT" ] = 19 , [ "SPACE" ] = 22 , [ "RIGHTCTRL" ] = 70 ,
[ "HOME" ] = 213 , [ "PAGEUP" ] = 10 , [ "PAGEDOWN" ] = 11 , [ "DELETE" ] = 178 ,
[ "LEFT" ] = 174 , [ "RIGHT" ] = 175 , [ "TOP" ] = 27 , [ "DOWN" ] = 173 ,
[ "NENTER" ] = 201 , [ "N4" ] = 108 , [ "N5" ] = 60 , [ "N6" ] = 107 , [ "N+" ] = 96 , [ "N-" ] = 97 , [ "N7" ] = 117 , [ "N8" ] = 61 , [ "N9" ] = 118
}
local PlayerData = { }
local GUI = { }
local HasAlreadyEnteredMarker = false
local LastPart = nil
local LastPartNum = nil
local CurrentAction = nil
local CurrentActionMsg = ''
local CurrentActionData = { }
ESX = nil
GUI. Time = 0
Citizen. CreateThread( function ( )
while ESX == nil do
TriggerEvent( 'esx:getSharedObject' , function ( obj) ESX = obj end )
Citizen. Wait( 0 )
end
end )
RegisterNetEvent( 'esx:playerLoaded' )
AddEventHandler( 'esx:playerLoaded' , function ( xPlayer)
PlayerData = xPlayer
end )
RegisterNetEvent( 'esx:setJob' )
AddEventHandler( 'esx:setJob' , function ( job)
PlayerData. job = job
end )
AddEventHandler( 'esx_hacking:hasEnteredMarker' , function ( part, partNum)
if part == 'Hacking' then
CurrentAction = 'hack'
CurrentActionMsg = _U( 'open_cloackroom' )
CurrentActionData = { }
end
end )
AddEventHandler( 'esx_hacking:hasExitedMarker' , function ( part, partNum)
ESX. UI. Menu. CloseAll( )
CurrentAction = nil
end )
AddEventHandler( 'esx_hacking:hasExitedMarker' , function ( part, partNum)
ESX. UI. Menu. CloseAll( )
CurrentAction = nil
end )
-- Create blips
Citizen. CreateThread( function ( )
for k, v in pairs ( Config. Hacks) do
local blip = AddBlipForCoord( v. Blip. Pos. x, v. Blip. Pos. y, v. Blip. Pos. z)
SetBlipSprite ( blip, v. Blip. Sprite)
SetBlipDisplay( blip, v. Blip. Display)
SetBlipScale ( blip, v. Blip. Scale)
SetBlipColour ( blip, v. Blip. Colour)
SetBlipAsShortRange( blip, true )
BeginTextCommandSetBlipName( "STRING" )
AddTextComponentString( _U( 'map_blip' ) )
EndTextCommandSetBlipName( blip)
end
end )
-- Display markers
Citizen. CreateThread( function ( )
while true do
Wait( 0 )
if PlayerData. job ~= nil and PlayerData. job. name == 'hacker' then
local playerPed = GetPlayerPed( - 1 )
local coords = GetEntityCoords( playerPed)
for k, v in pairs ( Config. Hacks) do
for i= 1 , # v. Hacking, 1 do
if GetDistanceBetweenCoords( coords, v. Hacking[ i] . x, v. Hacking[ i] . y, v. Hacking[ i] . z, true ) < Config. DrawDistance then
DrawMarker( Config. MarkerType, v. Hacking[ i] . x, v. Hacking[ i] . y, v. Hacking[ i] . z, 0.0 , 0.0 , 0.0 , 0 , 0.0 , 0.0 , Config. MarkerSize. x, Config. MarkerSize. y, Config. MarkerSize. z, Config. MarkerColor. r, Config. MarkerColor. g, Config. MarkerColor. b, 100 , false , true , 2 , false , false , false , false )
end
end
end
--[[
for k,v in pairs(Config.Hacks) do
for i=1, #v.Cloakrooms, 1 do
if GetDistanceBetweenCoords(coords, v.Cloakrooms[i].x, v.Cloakrooms[i].y, v.Cloakrooms[i].z, true) < Config.DrawDistance then
DrawMarker(Config.MarkerType, v.Cloakrooms[i].x, v.Cloakrooms[i].y, v.Cloakrooms[i].z, 0.0, 0.0, 0.0, 0, 0.0, 0.0, Config.MarkerSize.x, Config.MarkerSize.y, Config.MarkerSize.z, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, false, false, false, false)
end
end
for i=1, #v.Armories, 1 do
if GetDistanceBetweenCoords(coords, v.Armories[i].x, v.Armories[i].y, v.Armories[i].z, true) < Config.DrawDistance then
DrawMarker(Config.MarkerType, v.Armories[i].x, v.Armories[i].y, v.Armories[i].z, 0.0, 0.0, 0.0, 0, 0.0, 0.0, Config.MarkerSize.x, Config.MarkerSize.y, Config.MarkerSize.z, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, false, false, false, false)
end
end
for i=1, #v.Vehicles, 1 do
if GetDistanceBetweenCoords(coords, v.Vehicles[i].Spawner.x, v.Vehicles[i].Spawner.y, v.Vehicles[i].Spawner.z, true) < Config.DrawDistance then
DrawMarker(Config.MarkerType, v.Vehicles[i].Spawner.x, v.Vehicles[i].Spawner.y, v.Vehicles[i].Spawner.z, 0.0, 0.0, 0.0, 0, 0.0, 0.0, Config.MarkerSize.x, Config.MarkerSize.y, Config.MarkerSize.z, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, false, false, false, false)
end
end
for i=1, #v.VehicleDeleters, 1 do
if GetDistanceBetweenCoords(coords, v.VehicleDeleters[i].x, v.VehicleDeleters[i].y, v.VehicleDeleters[i].z, true) < Config.DrawDistance then
DrawMarker(Config.MarkerType, v.VehicleDeleters[i].x, v.VehicleDeleters[i].y, v.VehicleDeleters[i].z, 0.0, 0.0, 0.0, 0, 0.0, 0.0, Config.MarkerSize.x, Config.MarkerSize.y, Config.MarkerSize.z, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, false, false, false, false)
end
end
if Config.EnablePlayerManagement and PlayerData.job ~= nil and PlayerData.job.name == 'police' and PlayerData.job.grade_name == 'boss' then
for i=1, #v.BossActions, 1 do
if not v.BossActions[i].disabled and GetDistanceBetweenCoords(coords, v.BossActions[i].x, v.BossActions[i].y, v.BossActions[i].z, true) < Config.DrawDistance then
DrawMarker(Config.MarkerType, v.BossActions[i].x, v.BossActions[i].y, v.BossActions[i].z, 0.0, 0.0, 0.0, 0, 0.0, 0.0, Config.MarkerSize.x, Config.MarkerSize.y, Config.MarkerSize.z, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, false, false, false, false)
end
end
end
end
]] --
end
end
end )
-- Enter / Exit marker events
Citizen. CreateThread( function ( )
while true do
Wait( 0 )
print ( tostring ( PlayerData. job. name) )
if PlayerData. job ~= nil and PlayerData. job. name == 'hacker' then
local playerPed = GetPlayerPed( - 1 )
local coords = GetEntityCoords( playerPed)
local isInMarker = false
local currentPart = nil
local currentPartNum = nil
for k, v in pairs ( Config. Hacks) do
for i= 1 , # v. Hacking, 1 do
if GetDistanceBetweenCoords( coords, v. Hacking[ i] . x, v. Hacking[ i] . y, v. Hacking[ i] . z, true ) < Config. MarkerSize. x then
isInMarker = true
currentPart = 'Cloakroom'
currentPartNum = i
end
end
end
local hasExited = false
if isInMarker and not HasAlreadyEnteredMarker or ( isInMarker and ( LastPart ~= currentPart or LastPartNum ~= currentPartNum) ) then
if
( LastPart ~= nil and LastPartNum ~= nil ) and
( LastPart ~= currentPart or LastPartNum ~= currentPartNum)
then
TriggerEvent( 'esx_hacking:hasExitedMarker' , LastPart, LastPartNum)
hasExited = true
end
HasAlreadyEnteredMarker = true
LastPart = currentPart
LastPartNum = currentPartNum
TriggerEvent( 'esx_hacking:hasEnteredMarker' , currentPart, currentPartNum)
end
if not hasExited and not isInMarker and HasAlreadyEnteredMarker then
HasAlreadyEnteredMarker = false
TriggerEvent( 'esx_hacking:hasExitedMarker' , LastPart, LastPartNum)
end
end
end
end )
function HackingCallback( success, timeremaining)
if success then
TriggerEvent( 'esx_hacking:successHack' )
else
TriggerEvent( 'esx:showNotification' , xPlayer. source, 'Fail' )
end
end
function OpenMinigameMenu( )
TriggerEvent( "mhacking:show" )
TriggerEvent( "mhacking:start" , 7 , 35 , HackingCallback)
print ( 'Debug #3' )
end
-- Key Controls
Citizen. CreateThread( function ( )
while true do
Citizen. Wait( 0 )
if CurrentAction ~= nil then
SetTextComponentFormat( 'STRING' )
AddTextComponentString( CurrentActionMsg)
DisplayHelpTextFromStringLabel( 0 , 0 , 1 , - 1 )
if IsControlPressed( 0 , Keys[ 'E' ] ) and PlayerData. job ~= nil and PlayerData. job. name == 'hacker' and ( GetGameTimer( ) - GUI. Time) > 150 then
print ( 'Debug #2' )
if CurrentAction == 'hack' then
OpenMinigameMenu( )
end
CurrentAction = nil
GUI. Time = GetGameTimer( )
end
end
end
end )
-- your code goes here
bG9jYWwgS2V5cyA9IHsKICBbIkVTQyJdID0gMzIyLCBbIkYxIl0gPSAyODgsIFsiRjIiXSA9IDI4OSwgWyJGMyJdID0gMTcwLCBbIkY1Il0gPSAxNjYsIFsiRjYiXSA9IDE2NywgWyJGNyJdID0gMTY4LCBbIkY4Il0gPSAxNjksIFsiRjkiXSA9IDU2LCBbIkYxMCJdID0gNTcsCiAgWyJ+Il0gPSAyNDMsIFsiMSJdID0gMTU3LCBbIjIiXSA9IDE1OCwgWyIzIl0gPSAxNjAsIFsiNCJdID0gMTY0LCBbIjUiXSA9IDE2NSwgWyI2Il0gPSAxNTksIFsiNyJdID0gMTYxLCBbIjgiXSA9IDE2MiwgWyI5Il0gPSAxNjMsIFsiLSJdID0gODQsIFsiPSJdID0gODMsIFsiQkFDS1NQQUNFIl0gPSAxNzcsCiAgWyJUQUIiXSA9IDM3LCBbIlEiXSA9IDQ0LCBbIlciXSA9IDMyLCBbIkUiXSA9IDM4LCBbIlIiXSA9IDQ1LCBbIlQiXSA9IDI0NSwgWyJZIl0gPSAyNDYsIFsiVSJdID0gMzAzLCBbIlAiXSA9IDE5OSwgWyJbIl0gPSAzOSwgWyJdIl0gPSA0MCwgWyJFTlRFUiJdID0gMTgsCiAgWyJDQVBTIl0gPSAxMzcsIFsiQSJdID0gMzQsIFsiUyJdID0gOCwgWyJEIl0gPSA5LCBbIkYiXSA9IDIzLCBbIkciXSA9IDQ3LCBbIkgiXSA9IDc0LCBbIksiXSA9IDMxMSwgWyJMIl0gPSAxODIsCiAgWyJMRUZUU0hJRlQiXSA9IDIxLCBbIloiXSA9IDIwLCBbIlgiXSA9IDczLCBbIkMiXSA9IDI2LCBbIlYiXSA9IDAsIFsiQiJdID0gMjksIFsiTiJdID0gMjQ5LCBbIk0iXSA9IDI0NCwgWyIsIl0gPSA4MiwgWyIuIl0gPSA4MSwKICBbIkxFRlRDVFJMIl0gPSAzNiwgWyJMRUZUQUxUIl0gPSAxOSwgWyJTUEFDRSJdID0gMjIsIFsiUklHSFRDVFJMIl0gPSA3MCwKICBbIkhPTUUiXSA9IDIxMywgWyJQQUdFVVAiXSA9IDEwLCBbIlBBR0VET1dOIl0gPSAxMSwgWyJERUxFVEUiXSA9IDE3OCwKICBbIkxFRlQiXSA9IDE3NCwgWyJSSUdIVCJdID0gMTc1LCBbIlRPUCJdID0gMjcsIFsiRE9XTiJdID0gMTczLAogIFsiTkVOVEVSIl0gPSAyMDEsIFsiTjQiXSA9IDEwOCwgWyJONSJdID0gNjAsIFsiTjYiXSA9IDEwNywgWyJOKyJdID0gOTYsIFsiTi0iXSA9IDk3LCBbIk43Il0gPSAxMTcsIFsiTjgiXSA9IDYxLCBbIk45Il0gPSAxMTgKfQoKbG9jYWwgUGxheWVyRGF0YSAgICAgICAgICAgICAgICA9IHt9CmxvY2FsIEdVSSAgICAgICAgICAgICAgICAgICAgICAgPSB7fQpsb2NhbCBIYXNBbHJlYWR5RW50ZXJlZE1hcmtlciAgID0gZmFsc2UKbG9jYWwgTGFzdFBhcnQgICAgICAgICAgICAgICAgICA9IG5pbApsb2NhbCBMYXN0UGFydE51bSAgICAgICAgICAgICAgID0gbmlsCmxvY2FsIEN1cnJlbnRBY3Rpb24gICAgICAgICAgICAgPSBuaWwKbG9jYWwgQ3VycmVudEFjdGlvbk1zZyAgICAgICAgICA9ICcnCmxvY2FsIEN1cnJlbnRBY3Rpb25EYXRhICAgICAgICAgPSB7fQoKRVNYICAgICAgICAgICAgICAgICAgICAgICAgICAgICA9IG5pbApHVUkuVGltZSAgICAgICAgICAgICAgICAgICAgICAgID0gMAoKQ2l0aXplbi5DcmVhdGVUaHJlYWQoZnVuY3Rpb24oKQogIHdoaWxlIEVTWCA9PSBuaWwgZG8KICAgIFRyaWdnZXJFdmVudCgnZXN4OmdldFNoYXJlZE9iamVjdCcsIGZ1bmN0aW9uKG9iaikgRVNYID0gb2JqIGVuZCkKICAgIENpdGl6ZW4uV2FpdCgwKQogIGVuZAplbmQpCgpSZWdpc3Rlck5ldEV2ZW50KCdlc3g6cGxheWVyTG9hZGVkJykKQWRkRXZlbnRIYW5kbGVyKCdlc3g6cGxheWVyTG9hZGVkJywgZnVuY3Rpb24oeFBsYXllcikKICBQbGF5ZXJEYXRhID0geFBsYXllcgplbmQpCgpSZWdpc3Rlck5ldEV2ZW50KCdlc3g6c2V0Sm9iJykKQWRkRXZlbnRIYW5kbGVyKCdlc3g6c2V0Sm9iJywgZnVuY3Rpb24oam9iKQogIFBsYXllckRhdGEuam9iID0gam9iCmVuZCkKCgpBZGRFdmVudEhhbmRsZXIoJ2VzeF9oYWNraW5nOmhhc0VudGVyZWRNYXJrZXInLCBmdW5jdGlvbihwYXJ0LCBwYXJ0TnVtKQoKICBpZiBwYXJ0ID09ICdIYWNraW5nJyB0aGVuCiAgICBDdXJyZW50QWN0aW9uICAgICA9ICdoYWNrJwogICAgQ3VycmVudEFjdGlvbk1zZyAgPSBfVSgnb3Blbl9jbG9hY2tyb29tJykKICAgIEN1cnJlbnRBY3Rpb25EYXRhID0ge30KICBlbmQKCmVuZCkKCkFkZEV2ZW50SGFuZGxlcignZXN4X2hhY2tpbmc6aGFzRXhpdGVkTWFya2VyJywgZnVuY3Rpb24ocGFydCwgcGFydE51bSkKICBFU1guVUkuTWVudS5DbG9zZUFsbCgpCiAgQ3VycmVudEFjdGlvbiA9IG5pbAplbmQpCgpBZGRFdmVudEhhbmRsZXIoJ2VzeF9oYWNraW5nOmhhc0V4aXRlZE1hcmtlcicsIGZ1bmN0aW9uKHBhcnQsIHBhcnROdW0pCiAgRVNYLlVJLk1lbnUuQ2xvc2VBbGwoKQogIEN1cnJlbnRBY3Rpb24gPSBuaWwKZW5kKQoKCi0tIENyZWF0ZSBibGlwcwpDaXRpemVuLkNyZWF0ZVRocmVhZChmdW5jdGlvbigpCgogIGZvciBrLHYgaW4gcGFpcnMoQ29uZmlnLkhhY2tzKSBkbwoKICAgIGxvY2FsIGJsaXAgPSBBZGRCbGlwRm9yQ29vcmQodi5CbGlwLlBvcy54LCB2LkJsaXAuUG9zLnksIHYuQmxpcC5Qb3MueikKCiAgICBTZXRCbGlwU3ByaXRlIChibGlwLCB2LkJsaXAuU3ByaXRlKQogICAgU2V0QmxpcERpc3BsYXkoYmxpcCwgdi5CbGlwLkRpc3BsYXkpCiAgICBTZXRCbGlwU2NhbGUgIChibGlwLCB2LkJsaXAuU2NhbGUpCiAgICBTZXRCbGlwQ29sb3VyIChibGlwLCB2LkJsaXAuQ29sb3VyKQogICAgU2V0QmxpcEFzU2hvcnRSYW5nZShibGlwLCB0cnVlKQoKICAgIEJlZ2luVGV4dENvbW1hbmRTZXRCbGlwTmFtZSgiU1RSSU5HIikKICAgIEFkZFRleHRDb21wb25lbnRTdHJpbmcoX1UoJ21hcF9ibGlwJykpCiAgICBFbmRUZXh0Q29tbWFuZFNldEJsaXBOYW1lKGJsaXApCgogIGVuZAoKZW5kKQoKLS0gRGlzcGxheSBtYXJrZXJzCkNpdGl6ZW4uQ3JlYXRlVGhyZWFkKGZ1bmN0aW9uKCkKICB3aGlsZSB0cnVlIGRvCgogICAgV2FpdCgwKQoKICAgIGlmIFBsYXllckRhdGEuam9iIH49IG5pbCBhbmQgUGxheWVyRGF0YS5qb2IubmFtZSA9PSAnaGFja2VyJyB0aGVuCgogICAgICBsb2NhbCBwbGF5ZXJQZWQgPSBHZXRQbGF5ZXJQZWQoLTEpCiAgICAgIGxvY2FsIGNvb3JkcyAgICA9IEdldEVudGl0eUNvb3JkcyhwbGF5ZXJQZWQpCgkgIAoJICBmb3Igayx2IGluIHBhaXJzKENvbmZpZy5IYWNrcykgZG8KCSAgCgkJZm9yIGk9MSwgI3YuSGFja2luZywgMSBkbwogICAgICAgICAgaWYgR2V0RGlzdGFuY2VCZXR3ZWVuQ29vcmRzKGNvb3JkcywgIHYuSGFja2luZ1tpXS54LCAgdi5IYWNraW5nW2ldLnksICB2LkhhY2tpbmdbaV0ueiwgIHRydWUpIDwgQ29uZmlnLkRyYXdEaXN0YW5jZSB0aGVuCiAgICAgICAgICAgIERyYXdNYXJrZXIoQ29uZmlnLk1hcmtlclR5cGUsIHYuSGFja2luZ1tpXS54LCB2LkhhY2tpbmdbaV0ueSwgdi5IYWNraW5nW2ldLnosIDAuMCwgMC4wLCAwLjAsIDAsIDAuMCwgMC4wLCBDb25maWcuTWFya2VyU2l6ZS54LCBDb25maWcuTWFya2VyU2l6ZS55LCBDb25maWcuTWFya2VyU2l6ZS56LCBDb25maWcuTWFya2VyQ29sb3IuciwgQ29uZmlnLk1hcmtlckNvbG9yLmcsIENvbmZpZy5NYXJrZXJDb2xvci5iLCAxMDAsIGZhbHNlLCB0cnVlLCAyLCBmYWxzZSwgZmFsc2UsIGZhbHNlLCBmYWxzZSkKICAgICAgICAgIGVuZAogICAgICAgIGVuZAoJICAKCSAgZW5kCgkJLS1bWwogICAgICBmb3Igayx2IGluIHBhaXJzKENvbmZpZy5IYWNrcykgZG8KCiAgICAgICAgZm9yIGk9MSwgI3YuQ2xvYWtyb29tcywgMSBkbwogICAgICAgICAgaWYgR2V0RGlzdGFuY2VCZXR3ZWVuQ29vcmRzKGNvb3JkcywgIHYuQ2xvYWtyb29tc1tpXS54LCAgdi5DbG9ha3Jvb21zW2ldLnksICB2LkNsb2Frcm9vbXNbaV0ueiwgIHRydWUpIDwgQ29uZmlnLkRyYXdEaXN0YW5jZSB0aGVuCiAgICAgICAgICAgIERyYXdNYXJrZXIoQ29uZmlnLk1hcmtlclR5cGUsIHYuQ2xvYWtyb29tc1tpXS54LCB2LkNsb2Frcm9vbXNbaV0ueSwgdi5DbG9ha3Jvb21zW2ldLnosIDAuMCwgMC4wLCAwLjAsIDAsIDAuMCwgMC4wLCBDb25maWcuTWFya2VyU2l6ZS54LCBDb25maWcuTWFya2VyU2l6ZS55LCBDb25maWcuTWFya2VyU2l6ZS56LCBDb25maWcuTWFya2VyQ29sb3IuciwgQ29uZmlnLk1hcmtlckNvbG9yLmcsIENvbmZpZy5NYXJrZXJDb2xvci5iLCAxMDAsIGZhbHNlLCB0cnVlLCAyLCBmYWxzZSwgZmFsc2UsIGZhbHNlLCBmYWxzZSkKICAgICAgICAgIGVuZAogICAgICAgIGVuZAoKICAgICAgICBmb3IgaT0xLCAjdi5Bcm1vcmllcywgMSBkbwogICAgICAgICAgaWYgR2V0RGlzdGFuY2VCZXR3ZWVuQ29vcmRzKGNvb3JkcywgIHYuQXJtb3JpZXNbaV0ueCwgIHYuQXJtb3JpZXNbaV0ueSwgIHYuQXJtb3JpZXNbaV0ueiwgIHRydWUpIDwgQ29uZmlnLkRyYXdEaXN0YW5jZSB0aGVuCiAgICAgICAgICAgIERyYXdNYXJrZXIoQ29uZmlnLk1hcmtlclR5cGUsIHYuQXJtb3JpZXNbaV0ueCwgdi5Bcm1vcmllc1tpXS55LCB2LkFybW9yaWVzW2ldLnosIDAuMCwgMC4wLCAwLjAsIDAsIDAuMCwgMC4wLCBDb25maWcuTWFya2VyU2l6ZS54LCBDb25maWcuTWFya2VyU2l6ZS55LCBDb25maWcuTWFya2VyU2l6ZS56LCBDb25maWcuTWFya2VyQ29sb3IuciwgQ29uZmlnLk1hcmtlckNvbG9yLmcsIENvbmZpZy5NYXJrZXJDb2xvci5iLCAxMDAsIGZhbHNlLCB0cnVlLCAyLCBmYWxzZSwgZmFsc2UsIGZhbHNlLCBmYWxzZSkKICAgICAgICAgIGVuZAogICAgICAgIGVuZAoKICAgICAgICBmb3IgaT0xLCAjdi5WZWhpY2xlcywgMSBkbwogICAgICAgICAgaWYgR2V0RGlzdGFuY2VCZXR3ZWVuQ29vcmRzKGNvb3JkcywgIHYuVmVoaWNsZXNbaV0uU3Bhd25lci54LCAgdi5WZWhpY2xlc1tpXS5TcGF3bmVyLnksICB2LlZlaGljbGVzW2ldLlNwYXduZXIueiwgIHRydWUpIDwgQ29uZmlnLkRyYXdEaXN0YW5jZSB0aGVuCiAgICAgICAgICAgIERyYXdNYXJrZXIoQ29uZmlnLk1hcmtlclR5cGUsIHYuVmVoaWNsZXNbaV0uU3Bhd25lci54LCB2LlZlaGljbGVzW2ldLlNwYXduZXIueSwgdi5WZWhpY2xlc1tpXS5TcGF3bmVyLnosIDAuMCwgMC4wLCAwLjAsIDAsIDAuMCwgMC4wLCBDb25maWcuTWFya2VyU2l6ZS54LCBDb25maWcuTWFya2VyU2l6ZS55LCBDb25maWcuTWFya2VyU2l6ZS56LCBDb25maWcuTWFya2VyQ29sb3IuciwgQ29uZmlnLk1hcmtlckNvbG9yLmcsIENvbmZpZy5NYXJrZXJDb2xvci5iLCAxMDAsIGZhbHNlLCB0cnVlLCAyLCBmYWxzZSwgZmFsc2UsIGZhbHNlLCBmYWxzZSkKICAgICAgICAgIGVuZAogICAgICAgIGVuZAoKICAgICAgICBmb3IgaT0xLCAjdi5WZWhpY2xlRGVsZXRlcnMsIDEgZG8KICAgICAgICAgIGlmIEdldERpc3RhbmNlQmV0d2VlbkNvb3Jkcyhjb29yZHMsICB2LlZlaGljbGVEZWxldGVyc1tpXS54LCAgdi5WZWhpY2xlRGVsZXRlcnNbaV0ueSwgIHYuVmVoaWNsZURlbGV0ZXJzW2ldLnosICB0cnVlKSA8IENvbmZpZy5EcmF3RGlzdGFuY2UgdGhlbgogICAgICAgICAgICBEcmF3TWFya2VyKENvbmZpZy5NYXJrZXJUeXBlLCB2LlZlaGljbGVEZWxldGVyc1tpXS54LCB2LlZlaGljbGVEZWxldGVyc1tpXS55LCB2LlZlaGljbGVEZWxldGVyc1tpXS56LCAwLjAsIDAuMCwgMC4wLCAwLCAwLjAsIDAuMCwgQ29uZmlnLk1hcmtlclNpemUueCwgQ29uZmlnLk1hcmtlclNpemUueSwgQ29uZmlnLk1hcmtlclNpemUueiwgQ29uZmlnLk1hcmtlckNvbG9yLnIsIENvbmZpZy5NYXJrZXJDb2xvci5nLCBDb25maWcuTWFya2VyQ29sb3IuYiwgMTAwLCBmYWxzZSwgdHJ1ZSwgMiwgZmFsc2UsIGZhbHNlLCBmYWxzZSwgZmFsc2UpCiAgICAgICAgICBlbmQKICAgICAgICBlbmQKCiAgICAgICAgaWYgQ29uZmlnLkVuYWJsZVBsYXllck1hbmFnZW1lbnQgYW5kIFBsYXllckRhdGEuam9iIH49IG5pbCBhbmQgUGxheWVyRGF0YS5qb2IubmFtZSA9PSAncG9saWNlJyBhbmQgUGxheWVyRGF0YS5qb2IuZ3JhZGVfbmFtZSA9PSAnYm9zcycgdGhlbgogICAgICAgICAgZm9yIGk9MSwgI3YuQm9zc0FjdGlvbnMsIDEgZG8KICAgICAgICAgICAgaWYgbm90IHYuQm9zc0FjdGlvbnNbaV0uZGlzYWJsZWQgYW5kIEdldERpc3RhbmNlQmV0d2VlbkNvb3Jkcyhjb29yZHMsICB2LkJvc3NBY3Rpb25zW2ldLngsICB2LkJvc3NBY3Rpb25zW2ldLnksICB2LkJvc3NBY3Rpb25zW2ldLnosICB0cnVlKSA8IENvbmZpZy5EcmF3RGlzdGFuY2UgdGhlbgogICAgICAgICAgICAgIERyYXdNYXJrZXIoQ29uZmlnLk1hcmtlclR5cGUsIHYuQm9zc0FjdGlvbnNbaV0ueCwgdi5Cb3NzQWN0aW9uc1tpXS55LCB2LkJvc3NBY3Rpb25zW2ldLnosIDAuMCwgMC4wLCAwLjAsIDAsIDAuMCwgMC4wLCBDb25maWcuTWFya2VyU2l6ZS54LCBDb25maWcuTWFya2VyU2l6ZS55LCBDb25maWcuTWFya2VyU2l6ZS56LCBDb25maWcuTWFya2VyQ29sb3IuciwgQ29uZmlnLk1hcmtlckNvbG9yLmcsIENvbmZpZy5NYXJrZXJDb2xvci5iLCAxMDAsIGZhbHNlLCB0cnVlLCAyLCBmYWxzZSwgZmFsc2UsIGZhbHNlLCBmYWxzZSkKICAgICAgICAgICAgZW5kCiAgICAgICAgICBlbmQKICAgICAgICBlbmQKCQkKCiAgICAgIGVuZAoJCQldXS0tCiAgICBlbmQKCiAgZW5kCmVuZCkKCi0tIEVudGVyIC8gRXhpdCBtYXJrZXIgZXZlbnRzCkNpdGl6ZW4uQ3JlYXRlVGhyZWFkKGZ1bmN0aW9uKCkKCiAgd2hpbGUgdHJ1ZSBkbwoKICAgIFdhaXQoMCkKCXByaW50KHRvc3RyaW5nKFBsYXllckRhdGEuam9iLm5hbWUpKQogICAgaWYgUGxheWVyRGF0YS5qb2Igfj0gbmlsIGFuZCBQbGF5ZXJEYXRhLmpvYi5uYW1lID09ICdoYWNrZXInIHRoZW4KCiAgICAgIGxvY2FsIHBsYXllclBlZCAgICAgID0gR2V0UGxheWVyUGVkKC0xKQogICAgICBsb2NhbCBjb29yZHMgICAgICAgICA9IEdldEVudGl0eUNvb3JkcyhwbGF5ZXJQZWQpCiAgICAgIGxvY2FsIGlzSW5NYXJrZXIgICAgID0gZmFsc2UKICAgICAgbG9jYWwgY3VycmVudFBhcnQgICAgPSBuaWwKICAgICAgbG9jYWwgY3VycmVudFBhcnROdW0gPSBuaWwKCiAgICAgIGZvciBrLHYgaW4gcGFpcnMoQ29uZmlnLkhhY2tzKSBkbwoKICAgICAgICBmb3IgaT0xLCAjdi5IYWNraW5nLCAxIGRvCiAgICAgICAgICBpZiBHZXREaXN0YW5jZUJldHdlZW5Db29yZHMoY29vcmRzLCAgdi5IYWNraW5nW2ldLngsICB2LkhhY2tpbmdbaV0ueSwgIHYuSGFja2luZ1tpXS56LCAgdHJ1ZSkgPCBDb25maWcuTWFya2VyU2l6ZS54IHRoZW4KICAgICAgICAgICAgaXNJbk1hcmtlciAgICAgPSB0cnVlCiAgICAgICAgICAgIGN1cnJlbnRQYXJ0ICAgID0gJ0Nsb2Frcm9vbScKICAgICAgICAgICAgY3VycmVudFBhcnROdW0gPSBpCiAgICAgICAgICBlbmQKICAgICAgICBlbmQKCgogICAgICBlbmQKCiAgICAgIGxvY2FsIGhhc0V4aXRlZCA9IGZhbHNlCgogICAgICBpZiBpc0luTWFya2VyIGFuZCBub3QgSGFzQWxyZWFkeUVudGVyZWRNYXJrZXIgb3IgKGlzSW5NYXJrZXIgYW5kIChMYXN0UGFydCB+PSBjdXJyZW50UGFydCBvciBMYXN0UGFydE51bSB+PSBjdXJyZW50UGFydE51bSkgKSB0aGVuCgogICAgICAgIGlmCiAgICAgICAgICAoTGFzdFBhcnQgfj0gbmlsIGFuZCBMYXN0UGFydE51bSB+PSBuaWwpIGFuZAogICAgICAgICAgKExhc3RQYXJ0IH49IGN1cnJlbnRQYXJ0IG9yIExhc3RQYXJ0TnVtIH49IGN1cnJlbnRQYXJ0TnVtKQogICAgICAgIHRoZW4KICAgICAgICAgIFRyaWdnZXJFdmVudCgnZXN4X2hhY2tpbmc6aGFzRXhpdGVkTWFya2VyJywgTGFzdFBhcnQsIExhc3RQYXJ0TnVtKQogICAgICAgICAgaGFzRXhpdGVkID0gdHJ1ZQogICAgICAgIGVuZAoKICAgICAgICBIYXNBbHJlYWR5RW50ZXJlZE1hcmtlciA9IHRydWUKICAgICAgICBMYXN0UGFydCAgICAgICAgICAgICAgICA9IGN1cnJlbnRQYXJ0CiAgICAgICAgTGFzdFBhcnROdW0gICAgICAgICAgICAgPSBjdXJyZW50UGFydE51bQoKICAgICAgICBUcmlnZ2VyRXZlbnQoJ2VzeF9oYWNraW5nOmhhc0VudGVyZWRNYXJrZXInLCBjdXJyZW50UGFydCwgY3VycmVudFBhcnROdW0pCiAgICAgIGVuZAoKICAgICAgaWYgbm90IGhhc0V4aXRlZCBhbmQgbm90IGlzSW5NYXJrZXIgYW5kIEhhc0FscmVhZHlFbnRlcmVkTWFya2VyIHRoZW4KCiAgICAgICAgSGFzQWxyZWFkeUVudGVyZWRNYXJrZXIgPSBmYWxzZQoKICAgICAgICBUcmlnZ2VyRXZlbnQoJ2VzeF9oYWNraW5nOmhhc0V4aXRlZE1hcmtlcicsIExhc3RQYXJ0LCBMYXN0UGFydE51bSkKICAgICAgZW5kCgogICAgZW5kCgogIGVuZAplbmQpCgpmdW5jdGlvbiBIYWNraW5nQ2FsbGJhY2soc3VjY2VzcywgdGltZXJlbWFpbmluZykKCWlmIHN1Y2Nlc3MgdGhlbgoJCVRyaWdnZXJFdmVudCgnZXN4X2hhY2tpbmc6c3VjY2Vzc0hhY2snKQoJZWxzZQoJCVRyaWdnZXJFdmVudCgnZXN4OnNob3dOb3RpZmljYXRpb24nLCB4UGxheWVyLnNvdXJjZSwgJ0ZhaWwnKQoJZW5kCgplbmQKCmZ1bmN0aW9uIE9wZW5NaW5pZ2FtZU1lbnUoKQoJVHJpZ2dlckV2ZW50KCJtaGFja2luZzpzaG93IikKCVRyaWdnZXJFdmVudCgibWhhY2tpbmc6c3RhcnQiLDcsMzUsSGFja2luZ0NhbGxiYWNrKQoJcHJpbnQoJ0RlYnVnICMzJykKZW5kCgotLSBLZXkgQ29udHJvbHMKQ2l0aXplbi5DcmVhdGVUaHJlYWQoZnVuY3Rpb24oKQogIHdoaWxlIHRydWUgZG8KCiAgICBDaXRpemVuLldhaXQoMCkKCiAgICBpZiBDdXJyZW50QWN0aW9uIH49IG5pbCB0aGVuCgogICAgICBTZXRUZXh0Q29tcG9uZW50Rm9ybWF0KCdTVFJJTkcnKQogICAgICBBZGRUZXh0Q29tcG9uZW50U3RyaW5nKEN1cnJlbnRBY3Rpb25Nc2cpCiAgICAgIERpc3BsYXlIZWxwVGV4dEZyb21TdHJpbmdMYWJlbCgwLCAwLCAxLCAtMSkKCiAgICAgIGlmIElzQ29udHJvbFByZXNzZWQoMCwgIEtleXNbJ0UnXSkgYW5kIFBsYXllckRhdGEuam9iIH49IG5pbCBhbmQgUGxheWVyRGF0YS5qb2IubmFtZSA9PSAnaGFja2VyJyBhbmQgKEdldEdhbWVUaW1lcigpIC0gR1VJLlRpbWUpID4gMTUwIHRoZW4KCQlwcmludCgnRGVidWcgIzInKQogICAgICAgIGlmIEN1cnJlbnRBY3Rpb24gPT0gJ2hhY2snIHRoZW4KICAgICAgICAgIE9wZW5NaW5pZ2FtZU1lbnUoKQogICAgICAgIGVuZAoKICAgICAgICBDdXJyZW50QWN0aW9uID0gbmlsCiAgICAgICAgR1VJLlRpbWUgICAgICA9IEdldEdhbWVUaW1lcigpCgogICAgICBlbmQKCiAgICBlbmQKCiAgZW5kCmVuZCkKLS0geW91ciBjb2RlIGdvZXMgaGVyZQ==