--
--Local variables : Please do not touch theses variables
--
if ( config. useCopWhitelist == true ) then
isCop = false
else
isCop = true
end
local isInService = false
local rank = "unknown"
local checkpoints = { }
local policeHeli = nil
local handCuffed = false
local isAlreadyDead = false
-- jail addon
local isHandCuffed = false -- Don't touch!
-- Jail addon end
local allServiceCops = { }
local blipsCops = { }
local drag = false
local officerDrag = - 1
anyMenuOpen = {
menuName = "" ,
isActive = false
}
--It isn't recommanded to use this array directly, please just use it in order to retrieve quickly the key code your are searching
--[[
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 clockInStation = {
{ x= 850.156677246094 , y=- 1283.92004394531 , z= 28.0047378540039 } , -- La Mesa
{ x= 457.956909179688 , y=- 992.72314453125 , z= 30.6895866394043 } , -- Mission Row
{ x= 1856.91320800781 , y= 3689.50073242188 , z= 34.2670783996582 } , -- Sandy Shore
{ x=- 450.063201904297 , y= 6016.5751953125 , z= 31.7163734436035 } -- Paleto Bay
}
local garageStation = {
{ x=- 470.85266113281 , y= 6022.9296875 , z= 31.340530395508 } , -- La Mesa
{ x= 1873.3372802734 , y= 3687.3508300781 , z= 33.616954803467 } , -- Mission Row
{ x= 452.115966796875 , y=- 1018.10681152344 , z= 28.4786586761475 } , -- Sandy Shore
{ x= 855.24249267578 , y=- 1279.9300537109 , z= 26.513223648071 } -- Paleto Bay
}
local heliStation = {
{ x= 449.113966796875 , y=- 981.084966796875 , z= 43.691966796875 } -- Mission Row
}
local armoryStation = {
{ x= 452.119966796875 , y=- 980.061966796875 , z= 30.690966796875 } -- Mission Row
}
--
--Events handlers
--
if ( config. useCopWhitelist == true ) then
AddEventHandler( "playerSpawned" , function ( )
TriggerServerEvent( "police:checkIsCop" )
end )
end
if ( config. useCopWhitelist == true ) then
RegisterNetEvent( 'police:receiveIsCop' )
AddEventHandler( 'police:receiveIsCop' , function ( result)
if ( result == "unknown" ) then
if ( config. useCopWhitelist == true ) then
isCop = false
end
else
isCop = true
rank = result
end
end )
end
if ( config. useCopWhitelist == true ) then
RegisterNetEvent( 'police:nowCop' )
AddEventHandler( 'police:nowCop' , function ( )
isCop = true
end )
end
if ( config. useCopWhitelist == true ) then
RegisterNetEvent( 'police:noLongerCop' )
AddEventHandler( 'police:noLongerCop' , function ( )
if ( config. useCopWhitelist == true ) then
isCop = false
end
isInService = false
if ( config. enableOutfits == true ) then
RemoveAllPedWeapons( GetPlayerPed( - 1 ) )
TriggerServerEvent( "skin_customization:SpawnPlayer" )
else
local model = GetHashKey( "a_m_y_mexthug_01" )
RequestModel( model)
while not HasModelLoaded( model) do
RequestModel( model)
Citizen. Wait( 0 )
end
SetPlayerModel( PlayerId( ) , model)
SetModelAsNoLongerNeeded( model)
RemoveAllPedWeapons( GetPlayerPed( - 1 ) )
end
if ( policeHeli ~= nil ) then
SetEntityAsMissionEntity( policeHeli, true , true )
Citizen. InvokeNative( 0xEA386986E786A54F , Citizen. PointerValueIntInitialized( policeHeli) )
policeHeli = nil
end
ServiceOff( )
end )
end
-- jail addon
RegisterNetEvent( 'jail:teleportPlayer' )
AddEventHandler( 'jail:teleportPlayer' , function ( amount)
if ( isHandCuffed == true ) then
SetEntityCoords( GetPlayerPed( - 1 ) , tonumber ( config. jail. pos_x) , tonumber ( config. jail. pos_y) , tonumber ( config. jail. pos_z) )
TriggerEvent( 'chatMessage' , txt[ config. lang] [ "title_notification" ] , { 0 , 0 , 0 } , txt[ config. lang] [ "jail_arrest_notification_part_1" ] .. amount .. txt[ config. lang] [ "jail_arrest_notification_part_2" ] )
Citizen. CreateThread( function ( )
while ( amount > 0 ) do
Citizen. Wait( 1000 )
amount = amount - 1
end
-- Remove Weapons
RemoveAllPedWeapons( GetPlayerPed( - 1 ) )
TriggerEvent( 'chatMessage' , txt[ config. lang] [ "title_notification" ] , { 0 , 0 , 0 } , txt[ config. lang] [ "jail_weapons_removed" ] )
-- Arrest
TriggerEvent( 'police:getArrested' , t)
end )
else
TriggerEvent( 'chatMessage' , source, txt[ config. lang] [ "title_notification" ] , { 0 , 0 , 0 } , txt[ config. lang] [ "jail_not_cuffed" ] )
end
end )
-- jail addon end
RegisterNetEvent( 'police:getArrested' )
AddEventHandler( 'police:getArrested' , function ( )
handCuffed = not handCuffed
if ( handCuffed) then
TriggerEvent( "police:notify" , "CHAR_ANDREAS" , 1 , txt[ config. lang] [ "title_notification" ] , false , txt[ config. lang] [ "now_cuffed" ] )
isHandCuffed = true -- jail addon
else
TriggerEvent( "police:notify" , "CHAR_ANDREAS" , 1 , txt[ config. lang] [ "title_notification" ] , false , txt[ config. lang] [ "now_uncuffed" ] )
isHandCuffed = false -- jail addon
drag = false
end
end )
--Inspired from emergency for request system (by Jyben : https://f...content-available-to-author-only...m.net/t/release-job-save-people-be-a-hero-paramedic-emergency-coma-ko/19773)
local lockAskingFine = false
RegisterNetEvent( 'police:payFines' )
AddEventHandler( 'police:payFines' , function ( amount, sender)
Citizen. CreateThread( function ( )
if ( lockAskingFine ~= true ) then
lockAskingFine = true
local notifReceivedAt = GetGameTimer( )
Notification( txt[ config. lang] [ "info_fine_request_before_amount" ] .. amount.. txt[ config. lang] [ "info_fine_request_after_amount" ] )
while ( true ) do
Wait( 0 )
if ( GetTimeDifference( GetGameTimer( ) , notifReceivedAt) > 15000 ) then
TriggerServerEvent( 'police:finesETA' , sender, 2 )
Notification( txt[ config. lang] [ "request_fine_expired" ] )
lockAskingFine = false
break
end
if IsControlPressed( 1 , 246 ) then
if ( config. useModifiedBanking == true ) then
TriggerServerEvent( 'bank:withdrawAmende' , amount)
else
TriggerServerEvent( 'bank:withdraw' , amount)
end
Notification( txt[ config. lang] [ "pay_fine_success_before_amount" ] .. amount.. txt[ config. lang] [ "pay_fine_success_after_amount" ] )
TriggerServerEvent( 'police:finesETA' , sender, 0 )
lockAskingFine = false
break
end
if IsControlPressed( 1 , 45 ) then
TriggerServerEvent( 'police:finesETA' , sender, 3 )
lockAskingFine = false
break
end
end
else
TriggerServerEvent( 'police:finesETA' , sender, 1 )
end
end )
end )
-- Copy/paste from fs_freeroam (by FiveM-Script : https://f...content-available-to-author-only...m.net/t/alpha-fs-freeroam-0-1-4-fivem-scripts/14097)
RegisterNetEvent( "police:notify" )
AddEventHandler( "police:notify" , function ( icon, type , sender, title, text)
Citizen. CreateThread( function ( )
Wait( 1 )
SetNotificationTextEntry( "STRING" ) ;
AddTextComponentString( text) ;
SetNotificationMessage( icon, icon, true , type , sender, title, text) ;
DrawNotification( false , true ) ;
end )
end )
if ( config. useVDKInventory == true ) then
RegisterNetEvent( 'police:dropIllegalItem' )
AddEventHandler( 'police:dropIllegalItem' , function ( id)
TriggerEvent( "player:looseItem" , tonumber ( id) , exports. vdk_inventory: getQuantity( id) )
end )
end
--Piece of code given by Thefoxeur54
RegisterNetEvent( 'police:unseatme' )
AddEventHandler( 'police:unseatme' , function ( t)
local ped = GetPlayerPed( t)
ClearPedTasksImmediately( ped)
plyPos = GetEntityCoords( GetPlayerPed( - 1 ) , true )
local xnew = plyPos. x+ 2
local ynew = plyPos. y+ 2
SetEntityCoords( GetPlayerPed( - 1 ) , xnew, ynew, plyPos. z)
end )
RegisterNetEvent( 'police:toggleDrag' )
AddEventHandler( 'police:toggleDrag' , function ( t)
if ( handCuffed) then
drag = not drag
officerDrag = t
end
end )
RegisterNetEvent( 'police:forcedEnteringVeh' )
AddEventHandler( 'police:forcedEnteringVeh' , function ( veh)
if ( handCuffed) then
local pos = GetEntityCoords( GetPlayerPed( - 1 ) )
local entityWorld = GetOffsetFromEntityInWorldCoords( GetPlayerPed( - 1 ) , 0.0 , 20.0 , 0.0 )
local rayHandle = CastRayPointToPoint( pos. x, pos. y, pos. z, entityWorld. x, entityWorld. y, entityWorld. z, 10 , GetPlayerPed( - 1 ) , 0 )
local _, _, _, _, vehicleHandle = GetRaycastResult( rayHandle)
if vehicleHandle ~= nil then
SetPedIntoVehicle( GetPlayerPed( - 1 ) , vehicleHandle, 1 )
end
end
end )
RegisterNetEvent( 'police:removeWeapons' )
AddEventHandler( 'police:removeWeapons' , function ( )
RemoveAllPedWeapons( GetPlayerPed( - 1 ) , true )
end )
if ( config. enableOtherCopsBlips == true ) then
RegisterNetEvent( 'police:resultAllCopsInService' )
AddEventHandler( 'police:resultAllCopsInService' , function ( array)
allServiceCops = array
enableCopBlips( )
end )
end
if ( config. useModifiedEmergency == true ) then
RegisterNetEvent( 'es_em:cl_ResPlayer' )
AddEventHandler( 'es_em:cl_ResPlayer' , function ( )
if ( isCop and isInService) then
ServiceOff( )
end
if ( handCuffed == true ) then
handCuffed = false
end
end )
end
--
--Functions
--
function Notification( msg)
SetNotificationTextEntry( "STRING" )
AddTextComponentString( msg)
DrawNotification( 0 , 1 )
end
function drawNotification( text)
SetNotificationTextEntry( "STRING" )
AddTextComponentString( text)
DrawNotification( false , false )
end
--From Player Blips and Above Head Display (by Scammer : https://f...content-available-to-author-only...m.net/t/release-scammers-script-collection-09-03-17/3313)
function enableCopBlips( )
for k, existingBlip in pairs ( blipsCops) do
RemoveBlip( existingBlip)
end
blipsCops = { }
local localIdCops = { }
for id = 0 , 64 do
if ( NetworkIsPlayerActive( id) and GetPlayerPed( id) ~= GetPlayerPed( - 1 ) ) then
for i, c in pairs ( allServiceCops) do
if ( i == GetPlayerServerId( id) ) then
localIdCops[ id] = c
break
end
end
end
end
for id, c in pairs ( localIdCops) do
local ped = GetPlayerPed( id)
local blip = GetBlipFromEntity( ped)
if not DoesBlipExist( blip ) then
blip = AddBlipForEntity( ped )
SetBlipSprite( blip, 1 )
Citizen. InvokeNative( 0x5FBCA48327B914DF , blip, true )
HideNumberOnBlip( blip )
SetBlipNameToPlayerName( blip, id )
SetBlipScale( blip, 0.85 )
SetBlipAlpha( blip, 255 )
table.insert ( blipsCops, blip)
else
blipSprite = GetBlipSprite( blip )
HideNumberOnBlip( blip )
if blipSprite ~= 1 then
SetBlipSprite( blip, 1 )
Citizen. InvokeNative( 0x5FBCA48327B914DF , blip, true )
end
SetBlipNameToPlayerName( blip, id )
SetBlipScale( blip, 0.85 )
SetBlipAlpha( blip, 255 )
table.insert ( blipsCops, blip)
end
end
end
function GetPlayers( )
local players = { }
for i = 0 , 31 do
if NetworkIsPlayerActive( i) then
table.insert ( players, i)
end
end
return players
end
function GetClosestPlayer( )
local players = GetPlayers( )
local closestDistance = - 1
local closestPlayer = - 1
local ply = GetPlayerPed( - 1 )
local plyCoords = GetEntityCoords( ply, 0 )
for index, value in ipairs ( players) do
local target = GetPlayerPed( value)
if ( target ~= ply) then
local targetCoords = GetEntityCoords( GetPlayerPed( value) , 0 )
local distance = Vdist( targetCoords[ "x" ] , targetCoords[ "y" ] , targetCoords[ "z" ] , plyCoords[ "x" ] , plyCoords[ "y" ] , plyCoords[ "z" ] )
if ( closestDistance == - 1 or closestDistance > distance) then
closestPlayer = value
closestDistance = distance
end
end
end
return closestPlayer, closestDistance
end
function drawTxt( text, font, centre, x, y, scale, r, g, b, a)
SetTextFont( font)
SetTextProportional( 0 )
SetTextScale( scale, scale)
SetTextColour( r, g, b, a)
SetTextDropShadow( 0 , 0 , 0 , 0 , 255 )
SetTextEdge( 1 , 0 , 0 , 0 , 255 )
SetTextDropShadow( )
SetTextOutline( )
SetTextCentre( centre)
SetTextEntry( "STRING" )
AddTextComponentString( text)
DrawText( x , y)
end
function isNearTakeService( )
local distance = 10000
local pos = { }
for i = 1 , # clockInStation do
local coords = GetEntityCoords( GetPlayerPed( - 1 ) , 0 )
local currentDistance = Vdist( clockInStation[ i] . x, clockInStation[ i] . y, clockInStation[ i] . z, coords. x, coords. y, coords. z)
if ( currentDistance < distance) then
distance = currentDistance
pos = clockInStation[ i]
end
end
if anyMenuOpen. menuName == "cloackroom" and anyMenuOpen. isActive and distance > 3 then
CloseMenu( )
end
if ( distance < 30 ) then
DrawMarker( 1 , pos. x, pos. y, pos. z- 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1.0 , 1.0 , 1.0 , 0 , 155 , 255 , 200 , 0 , 0 , 2 , 0 , 0 , 0 , 0 )
end
if ( distance < 2 ) then
return true
end
end
function isNearStationGarage( )
local distance = 10000
local pos = { }
for i = 1 , # garageStation do
local coords = GetEntityCoords( GetPlayerPed( - 1 ) , 0 )
local currentDistance = Vdist( garageStation[ i] . x, garageStation[ i] . y, garageStation[ i] . z, coords. x, coords. y, coords. z)
if ( currentDistance < distance) then
distance = currentDistance
pos = garageStation[ i]
end
end
if anyMenuOpen. menuName == "garage" and anyMenuOpen. isActive and distance > 5 then
CloseMenu( )
end
if ( distance < 30 ) then
DrawMarker( 1 , pos. x, pos. y, pos. z- 1 , 0 , 0 , 0 , 0 , 0 , 0 , 2.0 , 2.0 , 1.0 , 0 , 155 , 255 , 200 , 0 , 0 , 2 , 0 , 0 , 0 , 0 )
end
if ( distance < 2 ) then
return true
end
end
function isNearHelicopterStation( )
local distance = 10000
local pos = { }
for i = 1 , # heliStation do
local coords = GetEntityCoords( GetPlayerPed( - 1 ) , 0 )
local currentDistance = Vdist( heliStation[ i] . x, heliStation[ i] . y, heliStation[ i] . z, coords. x, coords. y, coords. z)
if ( currentDistance < distance) then
distance = currentDistance
pos = heliStation[ i]
end
end
if ( distance < 30 ) then
DrawMarker( 1 , pos. x, pos. y, pos. z- 1 , 0 , 0 , 0 , 0 , 0 , 0 , 2.5 , 2.5 , 1.0 , 0 , 155 , 255 , 200 , 0 , 0 , 2 , 0 , 0 , 0 , 0 )
end
if ( distance < 2 ) then
return true
end
end
function isNearArmory( )
local distance = 10000
local pos = { }
for i = 1 , # armoryStation do
local coords = GetEntityCoords( GetPlayerPed( - 1 ) , 0 )
local currentDistance = Vdist( armoryStation[ i] . x, armoryStation[ i] . y, armoryStation[ i] . z, coords. x, coords. y, coords. z)
if ( currentDistance < distance) then
distance = currentDistance
pos = armoryStation[ i]
end
end
if ( anyMenuOpen. menuName == "armory" or anyMenuOpen. menuName == "armory-weapon_list" ) and anyMenuOpen. isActive and distance > 2 then
CloseMenu( )
end
if ( distance < 30 ) then
DrawMarker( 1 , pos. x, pos. y, pos. z- 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1.0 , 1.0 , 1.0 , 0 , 155 , 255 , 200 , 0 , 0 , 2 , 0 , 0 , 0 , 0 )
end
if ( distance < 2 ) then
return true
end
end
function ServiceOn( )
isInService = true
if ( config. useJobSystem == true ) then
TriggerServerEvent( "jobssystem:jobs" , config. job. officer_on_duty_job_id)
end
TriggerServerEvent( "police:takeService" )
end
function ServiceOff( )
isInService = false
if ( config. useJobSystem == true ) then
TriggerServerEvent( "jobssystem:jobs" , config. job. officer_not_on_duty_job_id)
end
TriggerServerEvent( "police:breakService" )
if ( config. enableOtherCopsBlips == true ) then
allServiceCops = { }
for k, existingBlip in pairs ( blipsCops) do
RemoveBlip( existingBlip)
end
blipsCops = { }
end
end
function DisplayHelpText( str)
SetTextComponentFormat( "STRING" )
AddTextComponentString( str)
DisplayHelpTextFromStringLabel( 0 , 0 , 1 , - 1 )
end
function CloseMenu( )
SendNUIMessage( {
action = "close"
} )
anyMenuOpen. menuName = ""
anyMenuOpen. isActive = false
end
RegisterNUICallback( 'sendAction' , function ( data, cb)
_G [ data. action] ( )
cb( 'ok' )
end )
--
--Threads
--
local alreadyDead = false
Citizen. CreateThread( function ( )
--Embedded NeverWanted script // Non loop part
if ( config. enableNeverWanted == true ) then
SetPoliceIgnorePlayer( PlayerId( ) , true )
SetDispatchCopsForPlayer( PlayerId( ) , false )
Citizen. InvokeNative( 0xDC0F817884CDD856 , 1 , false )
Citizen. InvokeNative( 0xDC0F817884CDD856 , 2 , false )
Citizen. InvokeNative( 0xDC0F817884CDD856 , 3 , false )
Citizen. InvokeNative( 0xDC0F817884CDD856 , 5 , false )
Citizen. InvokeNative( 0xDC0F817884CDD856 , 8 , false )
Citizen. InvokeNative( 0xDC0F817884CDD856 , 9 , false )
Citizen. InvokeNative( 0xDC0F817884CDD856 , 10 , false )
Citizen. InvokeNative( 0xDC0F817884CDD856 , 11 , false )
end
for _, item in pairs ( clockInStation) do
item. blip = AddBlipForCoord( item. x, item. y, item. z)
SetBlipSprite( item. blip, 60 )
SetBlipAsShortRange( item. blip, true )
BeginTextCommandSetBlipName( "STRING" )
AddTextComponentString( txt[ config. lang] [ "police_station" ] )
EndTextCommandSetBlipName( item. blip)
end
while true do
Citizen. Wait( 10 )
DisablePlayerVehicleRewards( PlayerId( ) )
--Embedded NeverWanted script // Loop part
if ( config. enableNeverWanted == true ) then
SetPlayerWantedLevel( PlayerId( ) , 0 , false )
SetPlayerWantedLevelNow( PlayerId( ) , false )
ClearAreaOfCops( )
end
if ( anyMenuOpen. isActive) then
DisableControlAction( 1 , 21 )
DisableControlAction( 1 , 140 )
DisableControlAction( 1 , 141 )
DisableControlAction( 1 , 142 )
SetDisableAmbientMeleeMove( GetPlayerPed( - 1 ) , true )
if ( IsControlJustPressed( 1 , 172 ) ) then
SendNUIMessage( {
action = "keyup"
} )
elseif ( IsControlJustPressed( 1 , 173 ) ) then
SendNUIMessage( {
action = "keydown"
} )
elseif ( IsControlJustPressed( 1 , 176 ) ) then
SendNUIMessage( {
action = "keyenter"
} )
elseif ( IsControlJustPressed( 1 , 177 ) ) then
if ( anyMenuOpen. menuName == "policemenu" or anyMenuOpen. menuName == "armory" or anyMenuOpen. menuName == "cloackroom" or anyMenuOpen. menuName == "garage" ) then
CloseMenu( )
elseif ( anyMenuOpen. menuName == "armory-weapon_list" ) then
BackArmory( )
else
BackMenuPolice( )
end
end
else
EnableControlAction( 1 , 21 )
EnableControlAction( 1 , 140 )
EnableControlAction( 1 , 141 )
EnableControlAction( 1 , 142 )
end
--Control death events
if ( config. useModifiedEmergency == false ) then
if ( IsPlayerDead( PlayerId( ) ) ) then
if ( alreadyDead == false ) then
if ( isInService) then
ServiceOff( )
end
handCuffed = false
drag = false
alreadyDead = true
end
else
alreadyDead = false
end
end
if ( handCuffed == true ) then
RequestAnimDict( 'mp_arresting' )
while not HasAnimDictLoaded( 'mp_arresting' ) do
Citizen. Wait( 0 )
end
local myPed = PlayerPedId( - 1 )
local animation = 'idle'
local flags = 16
while ( IsPedBeingStunned( myPed, 0 ) ) do
ClearPedTasksImmediately( myPed)
end
TaskPlayAnim( myPed, 'mp_arresting' , animation, 8.0 , - 8 , - 1 , flags, 0 , 0 , 0 , 0 )
end
--Piece of code from Drag command (by Frazzle, Valk, Michael_Sanelli, NYKILLA1127 : https://f...content-available-to-author-only...m.net/t/release-drag-command/22174)
if drag then
local ped = GetPlayerPed( GetPlayerFromServerId( officerDrag) )
local myped = GetPlayerPed( - 1 )
AttachEntityToEntity( myped, ped, 4103 , 11816 , 0.48 , 0.00 , 0.0 , 0.0 , 0.0 , 0.0 , false , false , false , false , 2 , true )
else
DetachEntity( GetPlayerPed( - 1 ) , true , false )
end
if ( isCop) then
if ( isNearTakeService( ) ) then
DisplayHelpText( txt[ config. lang] [ "help_text_open_cloackroom" ] , 0 , 1 , 0.5 , 0.8 , 0.6 , 255 , 255 , 255 , 255 ) -- ~g~E~s~
if IsControlJustPressed( 1 , 51 ) then
OpenCloackroom( )
end
end
if ( isInService) then
--Open Garage menu
if ( isNearStationGarage( ) ) then
if ( policevehicle ~= nil ) then
DisplayHelpText( txt[ config. lang] [ "help_text_put_car_into_garage" ] , 0 , 1 , 0.5 , 0.8 , 0.6 , 255 , 255 , 255 , 255 )
else
DisplayHelpText( txt[ config. lang] [ "help_text_get_car_out_garage" ] , 0 , 1 , 0.5 , 0.8 , 0.6 , 255 , 255 , 255 , 255 )
end
if IsControlJustPressed( 1 , 51 ) then
if ( policevehicle ~= nil ) then
--Destroy police vehicle
Citizen. InvokeNative( 0xEA386986E786A54F , Citizen. PointerValueIntInitialized( policevehicle) )
policevehicle = nil
else
OpenGarage( )
end
end
end
--Open Garage menu
if ( isNearArmory( ) ) then
DisplayHelpText( txt[ config. lang] [ "help_text_open_armory" ] , 0 , 1 , 0.5 , 0.8 , 0.6 , 255 , 255 , 255 , 255 )
if IsControlJustPressed( 1 , 51 ) then
OpenArmory( )
end
end
--Open/Close Menu police
if ( IsControlJustPressed( 1 , 166 ) ) then
TogglePoliceMenu( )
end
--Control helicopter spawning
if isNearHelicopterStation( ) then
if ( policeHeli ~= nil ) then
DisplayHelpText( txt[ config. lang] [ "help_text_put_heli_into_garage" ] , 0 , 1 , 0.5 , 0.8 , 0.6 , 255 , 255 , 255 , 255 )
else
DisplayHelpText( txt[ config. lang] [ "help_text_get_heli_out_garage" ] , 0 , 1 , 0.5 , 0.8 , 0.6 , 255 , 255 , 255 , 255 )
end
if IsControlJustPressed( 1 , 51 ) then
if ( policeHeli ~= nil ) then
Citizen. InvokeNative( 0xEA386986E786A54F , Citizen. PointerValueIntInitialized( policeHeli) )
policeHeli = nil
else
local heli = GetHashKey( "polmav" )
local ply = GetPlayerPed( - 1 )
local plyCoords = GetEntityCoords( ply, 0 )
RequestModel( heli)
while not HasModelLoaded( heli) do
Citizen. Wait( 0 )
end
policeHeli = CreateVehicle( heli, plyCoords[ "x" ] , plyCoords[ "y" ] , plyCoords[ "z" ] , 90.0 , true , false )
SetVehicleHasBeenOwnedByPlayer( policevehicle, true )
local netid = NetworkGetNetworkIdFromEntity( policeHeli)
SetNetworkIdCanMigrate( netid, true )
NetworkRegisterEntityAsNetworked( VehToNet( policeHeli) )
SetVehicleLivery( policeHeli, 0 )
TaskWarpPedIntoVehicle( ply, policeHeli, - 1 )
SetEntityAsMissionEntity( policeHeli, true , true )
end
end
end
end
end
end
end )
LS0KLS1Mb2NhbCB2YXJpYWJsZXMgOiBQbGVhc2UgZG8gbm90IHRvdWNoIHRoZXNlcyB2YXJpYWJsZXMKLS0KCmlmKGNvbmZpZy51c2VDb3BXaGl0ZWxpc3QgPT0gdHJ1ZSkgdGhlbgoJaXNDb3AgPSBmYWxzZQplbHNlCglpc0NvcCA9IHRydWUKZW5kCmxvY2FsIGlzSW5TZXJ2aWNlID0gZmFsc2UKbG9jYWwgcmFuayA9ICJ1bmtub3duIgpsb2NhbCBjaGVja3BvaW50cyA9IHt9CmxvY2FsIHBvbGljZUhlbGkgPSBuaWwKbG9jYWwgaGFuZEN1ZmZlZCA9IGZhbHNlCmxvY2FsIGlzQWxyZWFkeURlYWQgPSBmYWxzZQotLSBqYWlsIGFkZG9uCmxvY2FsIGlzSGFuZEN1ZmZlZCA9IGZhbHNlIC0tIERvbid0IHRvdWNoIQotLSBKYWlsIGFkZG9uIGVuZApsb2NhbCBhbGxTZXJ2aWNlQ29wcyA9IHt9CmxvY2FsIGJsaXBzQ29wcyA9IHt9CmxvY2FsIGRyYWcgPSBmYWxzZQpsb2NhbCBvZmZpY2VyRHJhZyA9IC0xCgphbnlNZW51T3BlbiA9IHsKCW1lbnVOYW1lID0gIiIsCglpc0FjdGl2ZSA9IGZhbHNlCn0KCi0tSXQgaXNuJ3QgcmVjb21tYW5kZWQgdG8gdXNlIHRoaXMgYXJyYXkgZGlyZWN0bHksIHBsZWFzZSBqdXN0IHVzZSBpdCBpbiBvcmRlciB0byByZXRyaWV2ZSBxdWlja2x5IHRoZSBrZXkgY29kZSB5b3VyIGFyZSBzZWFyY2hpbmcKLS1bWwpsb2NhbCBLZXlzID0gewoJWyJFU0MiXSA9IDMyMiwgWyJGMSJdID0gMjg4LCBbIkYyIl0gPSAyODksIFsiRjMiXSA9IDE3MCwgWyJGNSJdID0gMTY2LCBbIkY2Il0gPSAxNjcsIFsiRjciXSA9IDE2OCwgWyJGOCJdID0gMTY5LCBbIkY5Il0gPSA1NiwgWyJGMTAiXSA9IDU3LAoJWyJ+Il0gPSAyNDMsIFsiMSJdID0gMTU3LCBbIjIiXSA9IDE1OCwgWyIzIl0gPSAxNjAsIFsiNCJdID0gMTY0LCBbIjUiXSA9IDE2NSwgWyI2Il0gPSAxNTksIFsiNyJdID0gMTYxLCBbIjgiXSA9IDE2MiwgWyI5Il0gPSAxNjMsIFsiLSJdID0gODQsIFsiPSJdID0gODMsIFsiQkFDS1NQQUNFIl0gPSAxNzcsCglbIlRBQiJdID0gMzcsIFsiUSJdID0gNDQsIFsiVyJdID0gMzIsIFsiRSJdID0gMzgsIFsiUiJdID0gNDUsIFsiVCJdID0gMjQ1LCBbIlkiXSA9IDI0NiwgWyJVIl0gPSAzMDMsIFsiUCJdID0gMTk5LCBbIlsiXSA9IDM5LCBbIl0iXSA9IDQwLCBbIkVOVEVSIl0gPSAxOCwKCVsiQ0FQUyJdID0gMTM3LCBbIkEiXSA9IDM0LCBbIlMiXSA9IDgsIFsiRCJdID0gOSwgWyJGIl0gPSAyMywgWyJHIl0gPSA0NywgWyJIIl0gPSA3NCwgWyJLIl0gPSAzMTEsIFsiTCJdID0gMTgyLAoJWyJMRUZUU0hJRlQiXSA9IDIxLCBbIloiXSA9IDIwLCBbIlgiXSA9IDczLCBbIkMiXSA9IDI2LCBbIlYiXSA9IDAsIFsiQiJdID0gMjksIFsiTiJdID0gMjQ5LCBbIk0iXSA9IDI0NCwgWyIsIl0gPSA4MiwgWyIuIl0gPSA4MSwKCVsiTEVGVENUUkwiXSA9IDM2LCBbIkxFRlRBTFQiXSA9IDE5LCBbIlNQQUNFIl0gPSAyMiwgWyJSSUdIVENUUkwiXSA9IDcwLAoJWyJIT01FIl0gPSAyMTMsIFsiUEFHRVVQIl0gPSAxMCwgWyJQQUdFRE9XTiJdID0gMTEsIFsiREVMRVRFIl0gPSAxNzgsCglbIkxFRlQiXSA9IDE3NCwgWyJSSUdIVCJdID0gMTc1LCBbIlRPUCJdID0gMjcsIFsiRE9XTiJdID0gMTczLAoJWyJORU5URVIiXSA9IDIwMSwgWyJONCJdID0gMTA4LCBbIk41Il0gPSA2MCwgWyJONiJdID0gMTA3LCBbIk4rIl0gPSA5NiwgWyJOLSJdID0gOTcsIFsiTjciXSA9IDExNywgWyJOOCJdID0gNjEsIFsiTjkiXSA9IDExOAp9XV0KCmxvY2FsIGNsb2NrSW5TdGF0aW9uID0gewogIHt4PTg1MC4xNTY2NzcyNDYwOTQsIHk9LTEyODMuOTIwMDQzOTQ1MzEsIHo9MjguMDA0NzM3ODU0MDAzOX0sIC0tIExhIE1lc2EKICB7eD00NTcuOTU2OTA5MTc5Njg4LCB5PS05OTIuNzIzMTQ0NTMxMjUsIHo9MzAuNjg5NTg2NjM5NDA0M30sIC0tIE1pc3Npb24gUm93CiAge3g9MTg1Ni45MTMyMDgwMDc4MSwgeT0zNjg5LjUwMDczMjQyMTg4LCB6PTM0LjI2NzA3ODM5OTY1ODJ9LCAtLSBTYW5keSBTaG9yZQogIHt4PS00NTAuMDYzMjAxOTA0Mjk3LCB5PTYwMTYuNTc1MTk1MzEyNSwgej0zMS43MTYzNzM0NDM2MDM1fSAtLSBQYWxldG8gQmF5Cn0KCmxvY2FsIGdhcmFnZVN0YXRpb24gPSB7Cgl7eD0tNDcwLjg1MjY2MTEzMjgxLCB5PTYwMjIuOTI5Njg3NSwgej0zMS4zNDA1MzAzOTU1MDh9LCAgLS0gTGEgTWVzYQoJe3g9MTg3My4zMzcyODAyNzM0LCB5PTM2ODcuMzUwODMwMDc4MSwgej0zMy42MTY5NTQ4MDM0Njd9LCAgLS0gTWlzc2lvbiBSb3cKCXt4PTQ1Mi4xMTU5NjY3OTY4NzUsIHk9LTEwMTguMTA2ODExNTIzNDQsIHo9MjguNDc4NjU4Njc2MTQ3NX0sIC0tIFNhbmR5IFNob3JlCgl7eD04NTUuMjQyNDkyNjc1NzgsIHk9LTEyNzkuOTMwMDUzNzEwOSwgej0yNi41MTMyMjM2NDgwNzEgfSAtLSBQYWxldG8gQmF5Cn0KCmxvY2FsIGhlbGlTdGF0aW9uID0gewoJe3g9NDQ5LjExMzk2Njc5Njg3NSwgeT0tOTgxLjA4NDk2Njc5Njg3NSwgej00My42OTE5NjY3OTY4NzV9IC0tIE1pc3Npb24gUm93Cn0KCmxvY2FsIGFybW9yeVN0YXRpb24gPSB7Cgl7eD00NTIuMTE5OTY2Nzk2ODc1LCB5PS05ODAuMDYxOTY2Nzk2ODc1LCB6PTMwLjY5MDk2Njc5Njg3NX0gLS0gTWlzc2lvbiBSb3cKfQoKLS0KLS1FdmVudHMgaGFuZGxlcnMKLS0KCmlmKGNvbmZpZy51c2VDb3BXaGl0ZWxpc3QgPT0gdHJ1ZSkgdGhlbgoJQWRkRXZlbnRIYW5kbGVyKCJwbGF5ZXJTcGF3bmVkIiwgZnVuY3Rpb24oKQoJCVRyaWdnZXJTZXJ2ZXJFdmVudCgicG9saWNlOmNoZWNrSXNDb3AiKQoJZW5kKQplbmQKCmlmKGNvbmZpZy51c2VDb3BXaGl0ZWxpc3QgPT0gdHJ1ZSkgdGhlbgoJUmVnaXN0ZXJOZXRFdmVudCgncG9saWNlOnJlY2VpdmVJc0NvcCcpCglBZGRFdmVudEhhbmRsZXIoJ3BvbGljZTpyZWNlaXZlSXNDb3AnLCBmdW5jdGlvbihyZXN1bHQpCgkJaWYocmVzdWx0ID09ICJ1bmtub3duIikgdGhlbgoJCQlpZihjb25maWcudXNlQ29wV2hpdGVsaXN0ID09IHRydWUpIHRoZW4KCQkJCWlzQ29wID0gZmFsc2UKCQkJZW5kCgkJZWxzZQoJCQlpc0NvcCA9IHRydWUKCQkJcmFuayA9IHJlc3VsdAoJCWVuZAoJZW5kKQplbmQKCmlmKGNvbmZpZy51c2VDb3BXaGl0ZWxpc3QgPT0gdHJ1ZSkgdGhlbgoJUmVnaXN0ZXJOZXRFdmVudCgncG9saWNlOm5vd0NvcCcpCglBZGRFdmVudEhhbmRsZXIoJ3BvbGljZTpub3dDb3AnLCBmdW5jdGlvbigpCgkJaXNDb3AgPSB0cnVlCgllbmQpCmVuZAoKaWYoY29uZmlnLnVzZUNvcFdoaXRlbGlzdCA9PSB0cnVlKSB0aGVuCglSZWdpc3Rlck5ldEV2ZW50KCdwb2xpY2U6bm9Mb25nZXJDb3AnKQoJQWRkRXZlbnRIYW5kbGVyKCdwb2xpY2U6bm9Mb25nZXJDb3AnLCBmdW5jdGlvbigpCgkJaWYoY29uZmlnLnVzZUNvcFdoaXRlbGlzdCA9PSB0cnVlKSB0aGVuCgkJCWlzQ29wID0gZmFsc2UKCQllbmQKCQlpc0luU2VydmljZSA9IGZhbHNlCgkJCgkJaWYoY29uZmlnLmVuYWJsZU91dGZpdHMgPT0gdHJ1ZSkgdGhlbgoJCQlSZW1vdmVBbGxQZWRXZWFwb25zKEdldFBsYXllclBlZCgtMSkpCgkJCVRyaWdnZXJTZXJ2ZXJFdmVudCgic2tpbl9jdXN0b21pemF0aW9uOlNwYXduUGxheWVyIikKCQllbHNlCgkJCWxvY2FsIG1vZGVsID0gR2V0SGFzaEtleSgiYV9tX3lfbWV4dGh1Z18wMSIpCgoJCQlSZXF1ZXN0TW9kZWwobW9kZWwpCgkJCXdoaWxlIG5vdCBIYXNNb2RlbExvYWRlZChtb2RlbCkgZG8KCQkJCVJlcXVlc3RNb2RlbChtb2RlbCkKCQkJCUNpdGl6ZW4uV2FpdCgwKQoJCQllbmQKCQkgCgkJCVNldFBsYXllck1vZGVsKFBsYXllcklkKCksIG1vZGVsKQoJCQlTZXRNb2RlbEFzTm9Mb25nZXJOZWVkZWQobW9kZWwpCgkJCVJlbW92ZUFsbFBlZFdlYXBvbnMoR2V0UGxheWVyUGVkKC0xKSkKCQllbmQKCQkKCQlpZihwb2xpY2VIZWxpIH49IG5pbCkgdGhlbgoJCQlTZXRFbnRpdHlBc01pc3Npb25FbnRpdHkocG9saWNlSGVsaSwgdHJ1ZSwgdHJ1ZSkKCQkJQ2l0aXplbi5JbnZva2VOYXRpdmUoMHhFQTM4Njk4NkU3ODZBNTRGLCBDaXRpemVuLlBvaW50ZXJWYWx1ZUludEluaXRpYWxpemVkKHBvbGljZUhlbGkpKQoJCQlwb2xpY2VIZWxpID0gbmlsCgkJZW5kCgkJCgkJU2VydmljZU9mZigpCgllbmQpCmVuZAoKLS0gamFpbCBhZGRvbgpSZWdpc3Rlck5ldEV2ZW50KCdqYWlsOnRlbGVwb3J0UGxheWVyJykKQWRkRXZlbnRIYW5kbGVyKCdqYWlsOnRlbGVwb3J0UGxheWVyJywgZnVuY3Rpb24oYW1vdW50KQoJaWYoaXNIYW5kQ3VmZmVkID09IHRydWUpIHRoZW4KCQlTZXRFbnRpdHlDb29yZHMoR2V0UGxheWVyUGVkKC0xKSwgdG9udW1iZXIoY29uZmlnLmphaWwucG9zX3gpLCB0b251bWJlcihjb25maWcuamFpbC5wb3NfeSksIHRvbnVtYmVyKGNvbmZpZy5qYWlsLnBvc196KSkKCgkJVHJpZ2dlckV2ZW50KCdjaGF0TWVzc2FnZScsIHR4dFtjb25maWcubGFuZ11bInRpdGxlX25vdGlmaWNhdGlvbiJdLCB7MCwwLDB9LCB0eHRbY29uZmlnLmxhbmddWyJqYWlsX2FycmVzdF9ub3RpZmljYXRpb25fcGFydF8xIl0gLi4gYW1vdW50IC4uIHR4dFtjb25maWcubGFuZ11bImphaWxfYXJyZXN0X25vdGlmaWNhdGlvbl9wYXJ0XzIiXSkKCgkJQ2l0aXplbi5DcmVhdGVUaHJlYWQoZnVuY3Rpb24oKQoJCQl3aGlsZSAoYW1vdW50ID4gMCkgZG8KCQkJCUNpdGl6ZW4uV2FpdCgxMDAwKQoJCQkJYW1vdW50ID0gYW1vdW50IC0gMQoJCQllbmQKCgkJCS0tIFJlbW92ZSBXZWFwb25zCgkJCVJlbW92ZUFsbFBlZFdlYXBvbnMoR2V0UGxheWVyUGVkKC0xKSkKCQkJVHJpZ2dlckV2ZW50KCdjaGF0TWVzc2FnZScsIHR4dFtjb25maWcubGFuZ11bInRpdGxlX25vdGlmaWNhdGlvbiJdLCB7MCwwLDB9LCB0eHRbY29uZmlnLmxhbmddWyJqYWlsX3dlYXBvbnNfcmVtb3ZlZCJdKQoKCQkJLS0gQXJyZXN0CgkJCVRyaWdnZXJFdmVudCgncG9saWNlOmdldEFycmVzdGVkJywgdCkKCQllbmQpCgllbHNlCgkJVHJpZ2dlckV2ZW50KCdjaGF0TWVzc2FnZScsIHNvdXJjZSwgdHh0W2NvbmZpZy5sYW5nXVsidGl0bGVfbm90aWZpY2F0aW9uIl0sIHswLDAsMH0sIHR4dFtjb25maWcubGFuZ11bImphaWxfbm90X2N1ZmZlZCJdKQoJZW5kCmVuZCkKLS0gamFpbCBhZGRvbiBlbmQKClJlZ2lzdGVyTmV0RXZlbnQoJ3BvbGljZTpnZXRBcnJlc3RlZCcpCkFkZEV2ZW50SGFuZGxlcigncG9saWNlOmdldEFycmVzdGVkJywgZnVuY3Rpb24oKQoJaGFuZEN1ZmZlZCA9IG5vdCBoYW5kQ3VmZmVkCglpZihoYW5kQ3VmZmVkKSB0aGVuCgkJVHJpZ2dlckV2ZW50KCJwb2xpY2U6bm90aWZ5IiwgICJDSEFSX0FORFJFQVMiLCAxLCB0eHRbY29uZmlnLmxhbmddWyJ0aXRsZV9ub3RpZmljYXRpb24iXSwgZmFsc2UsIHR4dFtjb25maWcubGFuZ11bIm5vd19jdWZmZWQiXSkKCQlpc0hhbmRDdWZmZWQgPSB0cnVlIC0tIGphaWwgYWRkb24KCWVsc2UKCQlUcmlnZ2VyRXZlbnQoInBvbGljZTpub3RpZnkiLCAgIkNIQVJfQU5EUkVBUyIsIDEsIHR4dFtjb25maWcubGFuZ11bInRpdGxlX25vdGlmaWNhdGlvbiJdLCBmYWxzZSwgdHh0W2NvbmZpZy5sYW5nXVsibm93X3VuY3VmZmVkIl0pCgkJaXNIYW5kQ3VmZmVkID0gZmFsc2UgLS0gamFpbCBhZGRvbgoJCWRyYWcgPSBmYWxzZQoJZW5kCmVuZCkKCi0tSW5zcGlyZWQgZnJvbSBlbWVyZ2VuY3kgZm9yIHJlcXVlc3Qgc3lzdGVtIChieSBKeWJlbiA6IGh0dHBzOi8vZi4uLmNvbnRlbnQtYXZhaWxhYmxlLXRvLWF1dGhvci1vbmx5Li4ubS5uZXQvdC9yZWxlYXNlLWpvYi1zYXZlLXBlb3BsZS1iZS1hLWhlcm8tcGFyYW1lZGljLWVtZXJnZW5jeS1jb21hLWtvLzE5NzczKQpsb2NhbCBsb2NrQXNraW5nRmluZSA9IGZhbHNlClJlZ2lzdGVyTmV0RXZlbnQoJ3BvbGljZTpwYXlGaW5lcycpCkFkZEV2ZW50SGFuZGxlcigncG9saWNlOnBheUZpbmVzJywgZnVuY3Rpb24oYW1vdW50LCBzZW5kZXIpCglDaXRpemVuLkNyZWF0ZVRocmVhZChmdW5jdGlvbigpCgkJCgkJaWYobG9ja0Fza2luZ0ZpbmUgfj0gdHJ1ZSkgdGhlbgoJCQlsb2NrQXNraW5nRmluZSA9IHRydWUKCQkJbG9jYWwgbm90aWZSZWNlaXZlZEF0ID0gR2V0R2FtZVRpbWVyKCkKCQkJTm90aWZpY2F0aW9uKHR4dFtjb25maWcubGFuZ11bImluZm9fZmluZV9yZXF1ZXN0X2JlZm9yZV9hbW91bnQiXS4uYW1vdW50Li50eHRbY29uZmlnLmxhbmddWyJpbmZvX2ZpbmVfcmVxdWVzdF9hZnRlcl9hbW91bnQiXSkKCQkJd2hpbGUodHJ1ZSkgZG8KCQkJCVdhaXQoMCkKCQkJCQoJCQkJaWYgKEdldFRpbWVEaWZmZXJlbmNlKEdldEdhbWVUaW1lcigpLCBub3RpZlJlY2VpdmVkQXQpID4gMTUwMDApIHRoZW4KCQkJCQlUcmlnZ2VyU2VydmVyRXZlbnQoJ3BvbGljZTpmaW5lc0VUQScsIHNlbmRlciwgMikKCQkJCQlOb3RpZmljYXRpb24odHh0W2NvbmZpZy5sYW5nXVsicmVxdWVzdF9maW5lX2V4cGlyZWQiXSkKCQkJCQlsb2NrQXNraW5nRmluZSA9IGZhbHNlCgkJCQkJYnJlYWsKCQkJCWVuZAoJCQkJCgkJCQlpZiBJc0NvbnRyb2xQcmVzc2VkKDEsIDI0NikgdGhlbgoJCQkJCWlmKGNvbmZpZy51c2VNb2RpZmllZEJhbmtpbmcgPT0gdHJ1ZSkgdGhlbgoJCQkJCQlUcmlnZ2VyU2VydmVyRXZlbnQoJ2Jhbms6d2l0aGRyYXdBbWVuZGUnLCBhbW91bnQpCgkJCQkJZWxzZQoJCQkJCQlUcmlnZ2VyU2VydmVyRXZlbnQoJ2Jhbms6d2l0aGRyYXcnLCBhbW91bnQpCgkJCQkJZW5kCgkJCQkJTm90aWZpY2F0aW9uKHR4dFtjb25maWcubGFuZ11bInBheV9maW5lX3N1Y2Nlc3NfYmVmb3JlX2Ftb3VudCJdLi5hbW91bnQuLnR4dFtjb25maWcubGFuZ11bInBheV9maW5lX3N1Y2Nlc3NfYWZ0ZXJfYW1vdW50Il0pCgkJCQkJVHJpZ2dlclNlcnZlckV2ZW50KCdwb2xpY2U6ZmluZXNFVEEnLCBzZW5kZXIsIDApCgkJCQkJbG9ja0Fza2luZ0ZpbmUgPSBmYWxzZQoJCQkJCWJyZWFrCgkJCQllbmQKCQkJCQoJCQkJaWYgSXNDb250cm9sUHJlc3NlZCgxLCA0NSkgdGhlbgoJCQkJCVRyaWdnZXJTZXJ2ZXJFdmVudCgncG9saWNlOmZpbmVzRVRBJywgc2VuZGVyLCAzKQoJCQkJCWxvY2tBc2tpbmdGaW5lID0gZmFsc2UKCQkJCQlicmVhawoJCQkJZW5kCgkJCWVuZAoJCWVsc2UKCQkJVHJpZ2dlclNlcnZlckV2ZW50KCdwb2xpY2U6ZmluZXNFVEEnLCBzZW5kZXIsIDEpCgkJZW5kCgllbmQpCmVuZCkKCi0tIENvcHkvcGFzdGUgZnJvbSBmc19mcmVlcm9hbSAoYnkgRml2ZU0tU2NyaXB0IDogaHR0cHM6Ly9mLi4uY29udGVudC1hdmFpbGFibGUtdG8tYXV0aG9yLW9ubHkuLi5tLm5ldC90L2FscGhhLWZzLWZyZWVyb2FtLTAtMS00LWZpdmVtLXNjcmlwdHMvMTQwOTcpClJlZ2lzdGVyTmV0RXZlbnQoInBvbGljZTpub3RpZnkiKQpBZGRFdmVudEhhbmRsZXIoInBvbGljZTpub3RpZnkiLCBmdW5jdGlvbihpY29uLCB0eXBlLCBzZW5kZXIsIHRpdGxlLCB0ZXh0KQogICAgQ2l0aXplbi5DcmVhdGVUaHJlYWQoZnVuY3Rpb24oKQoJCVdhaXQoMSkKCQlTZXROb3RpZmljYXRpb25UZXh0RW50cnkoIlNUUklORyIpOwoJCUFkZFRleHRDb21wb25lbnRTdHJpbmcodGV4dCk7CgkJU2V0Tm90aWZpY2F0aW9uTWVzc2FnZShpY29uLCBpY29uLCB0cnVlLCB0eXBlLCBzZW5kZXIsIHRpdGxlLCB0ZXh0KTsKCQlEcmF3Tm90aWZpY2F0aW9uKGZhbHNlLCB0cnVlKTsKICAgIGVuZCkKZW5kKQoKaWYoY29uZmlnLnVzZVZES0ludmVudG9yeSA9PSB0cnVlKSB0aGVuCglSZWdpc3Rlck5ldEV2ZW50KCdwb2xpY2U6ZHJvcElsbGVnYWxJdGVtJykKCUFkZEV2ZW50SGFuZGxlcigncG9saWNlOmRyb3BJbGxlZ2FsSXRlbScsIGZ1bmN0aW9uKGlkKQoJCVRyaWdnZXJFdmVudCgicGxheWVyOmxvb3NlSXRlbSIsIHRvbnVtYmVyKGlkKSwgZXhwb3J0cy52ZGtfaW52ZW50b3J5OmdldFF1YW50aXR5KGlkKSkKCWVuZCkKZW5kCgotLVBpZWNlIG9mIGNvZGUgZ2l2ZW4gYnkgVGhlZm94ZXVyNTQKUmVnaXN0ZXJOZXRFdmVudCgncG9saWNlOnVuc2VhdG1lJykKQWRkRXZlbnRIYW5kbGVyKCdwb2xpY2U6dW5zZWF0bWUnLCBmdW5jdGlvbih0KQoJbG9jYWwgcGVkID0gR2V0UGxheWVyUGVkKHQpICAgICAgICAKCUNsZWFyUGVkVGFza3NJbW1lZGlhdGVseShwZWQpCglwbHlQb3MgPSBHZXRFbnRpdHlDb29yZHMoR2V0UGxheWVyUGVkKC0xKSwgIHRydWUpCglsb2NhbCB4bmV3ID0gcGx5UG9zLngrMgoJbG9jYWwgeW5ldyA9IHBseVBvcy55KzIKICAgCglTZXRFbnRpdHlDb29yZHMoR2V0UGxheWVyUGVkKC0xKSwgeG5ldywgeW5ldywgcGx5UG9zLnopCmVuZCkKClJlZ2lzdGVyTmV0RXZlbnQoJ3BvbGljZTp0b2dnbGVEcmFnJykKQWRkRXZlbnRIYW5kbGVyKCdwb2xpY2U6dG9nZ2xlRHJhZycsIGZ1bmN0aW9uKHQpCglpZihoYW5kQ3VmZmVkKSB0aGVuCgkJZHJhZyA9IG5vdCBkcmFnCgkJb2ZmaWNlckRyYWcgPSB0CgllbmQKZW5kKQoKUmVnaXN0ZXJOZXRFdmVudCgncG9saWNlOmZvcmNlZEVudGVyaW5nVmVoJykKQWRkRXZlbnRIYW5kbGVyKCdwb2xpY2U6Zm9yY2VkRW50ZXJpbmdWZWgnLCBmdW5jdGlvbih2ZWgpCglpZihoYW5kQ3VmZmVkKSB0aGVuCgkJbG9jYWwgcG9zID0gR2V0RW50aXR5Q29vcmRzKEdldFBsYXllclBlZCgtMSkpCgkJbG9jYWwgZW50aXR5V29ybGQgPSBHZXRPZmZzZXRGcm9tRW50aXR5SW5Xb3JsZENvb3JkcyhHZXRQbGF5ZXJQZWQoLTEpLCAwLjAsIDIwLjAsIDAuMCkKCgkJbG9jYWwgcmF5SGFuZGxlID0gQ2FzdFJheVBvaW50VG9Qb2ludChwb3MueCwgcG9zLnksIHBvcy56LCBlbnRpdHlXb3JsZC54LCBlbnRpdHlXb3JsZC55LCBlbnRpdHlXb3JsZC56LCAxMCwgR2V0UGxheWVyUGVkKC0xKSwgMCkKCQlsb2NhbCBfLCBfLCBfLCBfLCB2ZWhpY2xlSGFuZGxlID0gR2V0UmF5Y2FzdFJlc3VsdChyYXlIYW5kbGUpCgoJCWlmIHZlaGljbGVIYW5kbGUgfj0gbmlsIHRoZW4KCQkJU2V0UGVkSW50b1ZlaGljbGUoR2V0UGxheWVyUGVkKC0xKSwgdmVoaWNsZUhhbmRsZSwgMSkKCQllbmQKCWVuZAplbmQpCgpSZWdpc3Rlck5ldEV2ZW50KCdwb2xpY2U6cmVtb3ZlV2VhcG9ucycpCkFkZEV2ZW50SGFuZGxlcigncG9saWNlOnJlbW92ZVdlYXBvbnMnLCBmdW5jdGlvbigpCiAgICBSZW1vdmVBbGxQZWRXZWFwb25zKEdldFBsYXllclBlZCgtMSksIHRydWUpCmVuZCkKCmlmKGNvbmZpZy5lbmFibGVPdGhlckNvcHNCbGlwcyA9PSB0cnVlKSB0aGVuCglSZWdpc3Rlck5ldEV2ZW50KCdwb2xpY2U6cmVzdWx0QWxsQ29wc0luU2VydmljZScpCglBZGRFdmVudEhhbmRsZXIoJ3BvbGljZTpyZXN1bHRBbGxDb3BzSW5TZXJ2aWNlJywgZnVuY3Rpb24oYXJyYXkpCgkJYWxsU2VydmljZUNvcHMgPSBhcnJheQoJCWVuYWJsZUNvcEJsaXBzKCkKCWVuZCkKZW5kCgppZihjb25maWcudXNlTW9kaWZpZWRFbWVyZ2VuY3kgPT0gdHJ1ZSkgdGhlbgoJUmVnaXN0ZXJOZXRFdmVudCgnZXNfZW06Y2xfUmVzUGxheWVyJykKCUFkZEV2ZW50SGFuZGxlcignZXNfZW06Y2xfUmVzUGxheWVyJywgZnVuY3Rpb24oKQoJCWlmKGlzQ29wIGFuZCBpc0luU2VydmljZSkgdGhlbgoJCQlTZXJ2aWNlT2ZmKCkKCQllbmQKCQkKCQlpZihoYW5kQ3VmZmVkID09IHRydWUpIHRoZW4KCQkJaGFuZEN1ZmZlZCA9IGZhbHNlCgkJZW5kCgllbmQpCmVuZAoKLS0KLS1GdW5jdGlvbnMKLS0KCmZ1bmN0aW9uIE5vdGlmaWNhdGlvbihtc2cpCglTZXROb3RpZmljYXRpb25UZXh0RW50cnkoIlNUUklORyIpCglBZGRUZXh0Q29tcG9uZW50U3RyaW5nKG1zZykKCURyYXdOb3RpZmljYXRpb24oMCwxKQplbmQKCmZ1bmN0aW9uIGRyYXdOb3RpZmljYXRpb24odGV4dCkKCVNldE5vdGlmaWNhdGlvblRleHRFbnRyeSgiU1RSSU5HIikKCUFkZFRleHRDb21wb25lbnRTdHJpbmcodGV4dCkKCURyYXdOb3RpZmljYXRpb24oZmFsc2UsIGZhbHNlKQplbmQKCi0tRnJvbSBQbGF5ZXIgQmxpcHMgYW5kIEFib3ZlIEhlYWQgRGlzcGxheSAoYnkgU2NhbW1lciA6IGh0dHBzOi8vZi4uLmNvbnRlbnQtYXZhaWxhYmxlLXRvLWF1dGhvci1vbmx5Li4ubS5uZXQvdC9yZWxlYXNlLXNjYW1tZXJzLXNjcmlwdC1jb2xsZWN0aW9uLTA5LTAzLTE3LzMzMTMpCmZ1bmN0aW9uIGVuYWJsZUNvcEJsaXBzKCkKCglmb3IgaywgZXhpc3RpbmdCbGlwIGluIHBhaXJzKGJsaXBzQ29wcykgZG8KICAgICAgICBSZW1vdmVCbGlwKGV4aXN0aW5nQmxpcCkKICAgIGVuZAoJYmxpcHNDb3BzID0ge30KCQoJbG9jYWwgbG9jYWxJZENvcHMgPSB7fQoJZm9yIGlkID0gMCwgNjQgZG8KCQlpZihOZXR3b3JrSXNQbGF5ZXJBY3RpdmUoaWQpIGFuZCBHZXRQbGF5ZXJQZWQoaWQpIH49IEdldFBsYXllclBlZCgtMSkpIHRoZW4KCQkJZm9yIGksYyBpbiBwYWlycyhhbGxTZXJ2aWNlQ29wcykgZG8KCQkJCWlmKGkgPT0gR2V0UGxheWVyU2VydmVySWQoaWQpKSB0aGVuCgkJCQkJbG9jYWxJZENvcHNbaWRdID0gYwoJCQkJCWJyZWFrCgkJCQllbmQKCQkJZW5kCgkJZW5kCgllbmQKCQoJZm9yIGlkLCBjIGluIHBhaXJzKGxvY2FsSWRDb3BzKSBkbwoJCWxvY2FsIHBlZCA9IEdldFBsYXllclBlZChpZCkKCQlsb2NhbCBibGlwID0gR2V0QmxpcEZyb21FbnRpdHkocGVkKQoJCQoJCWlmIG5vdCBEb2VzQmxpcEV4aXN0KCBibGlwICkgdGhlbgoKCQkJYmxpcCA9IEFkZEJsaXBGb3JFbnRpdHkoIHBlZCApCgkJCVNldEJsaXBTcHJpdGUoIGJsaXAsIDEgKQoJCQlDaXRpemVuLkludm9rZU5hdGl2ZSggMHg1RkJDQTQ4MzI3QjkxNERGLCBibGlwLCB0cnVlICkKCQkJSGlkZU51bWJlck9uQmxpcCggYmxpcCApCgkJCVNldEJsaXBOYW1lVG9QbGF5ZXJOYW1lKCBibGlwLCBpZCApCgkJCQoJCQlTZXRCbGlwU2NhbGUoIGJsaXAsICAwLjg1ICkKCQkJU2V0QmxpcEFscGhhKCBibGlwLCAyNTUgKQoJCQkKCQkJdGFibGUuaW5zZXJ0KGJsaXBzQ29wcywgYmxpcCkKCQllbHNlCgkJCQoJCQlibGlwU3ByaXRlID0gR2V0QmxpcFNwcml0ZSggYmxpcCApCgkJCQoJCQlIaWRlTnVtYmVyT25CbGlwKCBibGlwICkKCQkJaWYgYmxpcFNwcml0ZSB+PSAxIHRoZW4KCQkJCVNldEJsaXBTcHJpdGUoIGJsaXAsIDEgKQoJCQkJQ2l0aXplbi5JbnZva2VOYXRpdmUoIDB4NUZCQ0E0ODMyN0I5MTRERiwgYmxpcCwgdHJ1ZSApCgkJCWVuZAoJCQkKCQkJU2V0QmxpcE5hbWVUb1BsYXllck5hbWUoIGJsaXAsIGlkICkKCQkJU2V0QmxpcFNjYWxlKCBibGlwLCAgMC44NSApCgkJCVNldEJsaXBBbHBoYSggYmxpcCwgMjU1ICkKCQkJCgkJCXRhYmxlLmluc2VydChibGlwc0NvcHMsIGJsaXApCgkJZW5kCgllbmQKZW5kCgpmdW5jdGlvbiBHZXRQbGF5ZXJzKCkKICAgIGxvY2FsIHBsYXllcnMgPSB7fQoKICAgIGZvciBpID0gMCwgMzEgZG8KICAgICAgICBpZiBOZXR3b3JrSXNQbGF5ZXJBY3RpdmUoaSkgdGhlbgogICAgICAgICAgICB0YWJsZS5pbnNlcnQocGxheWVycywgaSkKICAgICAgICBlbmQKICAgIGVuZAoKICAgIHJldHVybiBwbGF5ZXJzCmVuZAoKZnVuY3Rpb24gR2V0Q2xvc2VzdFBsYXllcigpCglsb2NhbCBwbGF5ZXJzID0gR2V0UGxheWVycygpCglsb2NhbCBjbG9zZXN0RGlzdGFuY2UgPSAtMQoJbG9jYWwgY2xvc2VzdFBsYXllciA9IC0xCglsb2NhbCBwbHkgPSBHZXRQbGF5ZXJQZWQoLTEpCglsb2NhbCBwbHlDb29yZHMgPSBHZXRFbnRpdHlDb29yZHMocGx5LCAwKQoJCglmb3IgaW5kZXgsdmFsdWUgaW4gaXBhaXJzKHBsYXllcnMpIGRvCgkJbG9jYWwgdGFyZ2V0ID0gR2V0UGxheWVyUGVkKHZhbHVlKQoJCWlmKHRhcmdldCB+PSBwbHkpIHRoZW4KCQkJbG9jYWwgdGFyZ2V0Q29vcmRzID0gR2V0RW50aXR5Q29vcmRzKEdldFBsYXllclBlZCh2YWx1ZSksIDApCgkJCWxvY2FsIGRpc3RhbmNlID0gVmRpc3QodGFyZ2V0Q29vcmRzWyJ4Il0sIHRhcmdldENvb3Jkc1sieSJdLCB0YXJnZXRDb29yZHNbInoiXSwgcGx5Q29vcmRzWyJ4Il0sIHBseUNvb3Jkc1sieSJdLCBwbHlDb29yZHNbInoiXSkKCQkJaWYoY2xvc2VzdERpc3RhbmNlID09IC0xIG9yIGNsb3Nlc3REaXN0YW5jZSA+IGRpc3RhbmNlKSB0aGVuCgkJCQljbG9zZXN0UGxheWVyID0gdmFsdWUKCQkJCWNsb3Nlc3REaXN0YW5jZSA9IGRpc3RhbmNlCgkJCWVuZAoJCWVuZAoJZW5kCgkKCXJldHVybiBjbG9zZXN0UGxheWVyLCBjbG9zZXN0RGlzdGFuY2UKZW5kCgpmdW5jdGlvbiBkcmF3VHh0KHRleHQsZm9udCxjZW50cmUseCx5LHNjYWxlLHIsZyxiLGEpCglTZXRUZXh0Rm9udChmb250KQoJU2V0VGV4dFByb3BvcnRpb25hbCgwKQoJU2V0VGV4dFNjYWxlKHNjYWxlLCBzY2FsZSkKCVNldFRleHRDb2xvdXIociwgZywgYiwgYSkKCVNldFRleHREcm9wU2hhZG93KDAsIDAsIDAsIDAsMjU1KQoJU2V0VGV4dEVkZ2UoMSwgMCwgMCwgMCwgMjU1KQoJU2V0VGV4dERyb3BTaGFkb3coKQoJU2V0VGV4dE91dGxpbmUoKQoJU2V0VGV4dENlbnRyZShjZW50cmUpCglTZXRUZXh0RW50cnkoIlNUUklORyIpCglBZGRUZXh0Q29tcG9uZW50U3RyaW5nKHRleHQpCglEcmF3VGV4dCh4ICwgeSkKZW5kCgpmdW5jdGlvbiBpc05lYXJUYWtlU2VydmljZSgpCglsb2NhbCBkaXN0YW5jZSA9IDEwMDAwCglsb2NhbCBwb3MgPSB7fQoJZm9yIGkgPSAxLCAjY2xvY2tJblN0YXRpb24gZG8KCQlsb2NhbCBjb29yZHMgPSBHZXRFbnRpdHlDb29yZHMoR2V0UGxheWVyUGVkKC0xKSwgMCkKCQlsb2NhbCBjdXJyZW50RGlzdGFuY2UgPSBWZGlzdChjbG9ja0luU3RhdGlvbltpXS54LCBjbG9ja0luU3RhdGlvbltpXS55LCBjbG9ja0luU3RhdGlvbltpXS56LCBjb29yZHMueCwgY29vcmRzLnksIGNvb3Jkcy56KQoJCWlmKGN1cnJlbnREaXN0YW5jZSA8IGRpc3RhbmNlKSB0aGVuCgkJCWRpc3RhbmNlID0gY3VycmVudERpc3RhbmNlCgkJCXBvcyA9IGNsb2NrSW5TdGF0aW9uW2ldCgkJZW5kCgllbmQKCQoJaWYgYW55TWVudU9wZW4ubWVudU5hbWUgPT0gImNsb2Fja3Jvb20iIGFuZCBhbnlNZW51T3Blbi5pc0FjdGl2ZSBhbmQgZGlzdGFuY2UgPiAzIHRoZW4KCQlDbG9zZU1lbnUoKQoJZW5kCglpZihkaXN0YW5jZSA8IDMwKSB0aGVuCgkJRHJhd01hcmtlcigxLCBwb3MueCwgcG9zLnksIHBvcy56LTEsIDAsIDAsIDAsIDAsIDAsIDAsIDEuMCwgMS4wLCAxLjAsIDAsIDE1NSwgMjU1LCAyMDAsIDAsIDAsIDIsIDAsIDAsIDAsIDApCgllbmQKCWlmKGRpc3RhbmNlIDwgMikgdGhlbgoJCXJldHVybiB0cnVlCgllbmQKZW5kCgpmdW5jdGlvbiBpc05lYXJTdGF0aW9uR2FyYWdlKCkKCWxvY2FsIGRpc3RhbmNlID0gMTAwMDAKCWxvY2FsIHBvcyA9IHt9Cglmb3IgaSA9IDEsICNnYXJhZ2VTdGF0aW9uIGRvCgkJbG9jYWwgY29vcmRzID0gR2V0RW50aXR5Q29vcmRzKEdldFBsYXllclBlZCgtMSksIDApCgkJbG9jYWwgY3VycmVudERpc3RhbmNlID0gVmRpc3QoZ2FyYWdlU3RhdGlvbltpXS54LCBnYXJhZ2VTdGF0aW9uW2ldLnksIGdhcmFnZVN0YXRpb25baV0ueiwgY29vcmRzLngsIGNvb3Jkcy55LCBjb29yZHMueikKCQlpZihjdXJyZW50RGlzdGFuY2UgPCBkaXN0YW5jZSkgdGhlbgoJCQlkaXN0YW5jZSA9IGN1cnJlbnREaXN0YW5jZQoJCQlwb3MgPSBnYXJhZ2VTdGF0aW9uW2ldCgkJZW5kCgllbmQKCQoJaWYgYW55TWVudU9wZW4ubWVudU5hbWUgPT0gImdhcmFnZSIgYW5kIGFueU1lbnVPcGVuLmlzQWN0aXZlIGFuZCBkaXN0YW5jZSA+IDUgdGhlbgoJCUNsb3NlTWVudSgpCgllbmQKCWlmKGRpc3RhbmNlIDwgMzApIHRoZW4KCQlEcmF3TWFya2VyKDEsIHBvcy54LCBwb3MueSwgcG9zLnotMSwgMCwgMCwgMCwgMCwgMCwgMCwgMi4wLCAyLjAsIDEuMCwgMCwgMTU1LCAyNTUsIDIwMCwgMCwgMCwgMiwgMCwgMCwgMCwgMCkKCWVuZAoJaWYoZGlzdGFuY2UgPCAyKSB0aGVuCgkJcmV0dXJuIHRydWUKCWVuZAplbmQKCmZ1bmN0aW9uIGlzTmVhckhlbGljb3B0ZXJTdGF0aW9uKCkKCWxvY2FsIGRpc3RhbmNlID0gMTAwMDAKCWxvY2FsIHBvcyA9IHt9Cglmb3IgaSA9IDEsICNoZWxpU3RhdGlvbiBkbwoJCWxvY2FsIGNvb3JkcyA9IEdldEVudGl0eUNvb3JkcyhHZXRQbGF5ZXJQZWQoLTEpLCAwKQoJCWxvY2FsIGN1cnJlbnREaXN0YW5jZSA9IFZkaXN0KGhlbGlTdGF0aW9uW2ldLngsIGhlbGlTdGF0aW9uW2ldLnksIGhlbGlTdGF0aW9uW2ldLnosIGNvb3Jkcy54LCBjb29yZHMueSwgY29vcmRzLnopCgkJaWYoY3VycmVudERpc3RhbmNlIDwgZGlzdGFuY2UpIHRoZW4KCQkJZGlzdGFuY2UgPSBjdXJyZW50RGlzdGFuY2UKCQkJcG9zID0gaGVsaVN0YXRpb25baV0KCQllbmQKCWVuZAoJCglpZihkaXN0YW5jZSA8IDMwKSB0aGVuCgkJRHJhd01hcmtlcigxLCBwb3MueCwgcG9zLnksIHBvcy56LTEsIDAsIDAsIDAsIDAsIDAsIDAsIDIuNSwgMi41LCAxLjAsIDAsIDE1NSwgMjU1LCAyMDAsIDAsIDAsIDIsIDAsIDAsIDAsIDApCgllbmQKCWlmKGRpc3RhbmNlIDwgMikgdGhlbgoJCXJldHVybiB0cnVlCgllbmQKZW5kCgpmdW5jdGlvbiBpc05lYXJBcm1vcnkoKQoJbG9jYWwgZGlzdGFuY2UgPSAxMDAwMAoJbG9jYWwgcG9zID0ge30KCWZvciBpID0gMSwgI2FybW9yeVN0YXRpb24gZG8KCQlsb2NhbCBjb29yZHMgPSBHZXRFbnRpdHlDb29yZHMoR2V0UGxheWVyUGVkKC0xKSwgMCkKCQlsb2NhbCBjdXJyZW50RGlzdGFuY2UgPSBWZGlzdChhcm1vcnlTdGF0aW9uW2ldLngsIGFybW9yeVN0YXRpb25baV0ueSwgYXJtb3J5U3RhdGlvbltpXS56LCBjb29yZHMueCwgY29vcmRzLnksIGNvb3Jkcy56KQoJCWlmKGN1cnJlbnREaXN0YW5jZSA8IGRpc3RhbmNlKSB0aGVuCgkJCWRpc3RhbmNlID0gY3VycmVudERpc3RhbmNlCgkJCXBvcyA9IGFybW9yeVN0YXRpb25baV0KCQllbmQKCWVuZAoJCglpZiAoYW55TWVudU9wZW4ubWVudU5hbWUgPT0gImFybW9yeSIgb3IgYW55TWVudU9wZW4ubWVudU5hbWUgPT0gImFybW9yeS13ZWFwb25fbGlzdCIpIGFuZCBhbnlNZW51T3Blbi5pc0FjdGl2ZSBhbmQgZGlzdGFuY2UgPiAyIHRoZW4KCQlDbG9zZU1lbnUoKQoJZW5kCglpZihkaXN0YW5jZSA8IDMwKSB0aGVuCgkJRHJhd01hcmtlcigxLCBwb3MueCwgcG9zLnksIHBvcy56LTEsIDAsIDAsIDAsIDAsIDAsIDAsIDEuMCwgMS4wLCAxLjAsIDAsIDE1NSwgMjU1LCAyMDAsIDAsIDAsIDIsIDAsIDAsIDAsIDApCgllbmQKCWlmKGRpc3RhbmNlIDwgMikgdGhlbgoJCXJldHVybiB0cnVlCgllbmQKZW5kCgpmdW5jdGlvbiBTZXJ2aWNlT24oKQoJaXNJblNlcnZpY2UgPSB0cnVlCglpZihjb25maWcudXNlSm9iU3lzdGVtID09IHRydWUpIHRoZW4KCQlUcmlnZ2VyU2VydmVyRXZlbnQoImpvYnNzeXN0ZW06am9icyIsIGNvbmZpZy5qb2Iub2ZmaWNlcl9vbl9kdXR5X2pvYl9pZCkKCWVuZAoJVHJpZ2dlclNlcnZlckV2ZW50KCJwb2xpY2U6dGFrZVNlcnZpY2UiKQplbmQKCmZ1bmN0aW9uIFNlcnZpY2VPZmYoKQoJaXNJblNlcnZpY2UgPSBmYWxzZQoJaWYoY29uZmlnLnVzZUpvYlN5c3RlbSA9PSB0cnVlKSB0aGVuCgkJVHJpZ2dlclNlcnZlckV2ZW50KCJqb2Jzc3lzdGVtOmpvYnMiLCBjb25maWcuam9iLm9mZmljZXJfbm90X29uX2R1dHlfam9iX2lkKQoJZW5kCglUcmlnZ2VyU2VydmVyRXZlbnQoInBvbGljZTpicmVha1NlcnZpY2UiKQoJCglpZihjb25maWcuZW5hYmxlT3RoZXJDb3BzQmxpcHMgPT0gdHJ1ZSkgdGhlbgoJCWFsbFNlcnZpY2VDb3BzID0ge30KCQkKCQlmb3IgaywgZXhpc3RpbmdCbGlwIGluIHBhaXJzKGJsaXBzQ29wcykgZG8KCQkJUmVtb3ZlQmxpcChleGlzdGluZ0JsaXApCgkJZW5kCgkJYmxpcHNDb3BzID0ge30KCWVuZAplbmQKCmZ1bmN0aW9uIERpc3BsYXlIZWxwVGV4dChzdHIpCglTZXRUZXh0Q29tcG9uZW50Rm9ybWF0KCJTVFJJTkciKQoJQWRkVGV4dENvbXBvbmVudFN0cmluZyhzdHIpCglEaXNwbGF5SGVscFRleHRGcm9tU3RyaW5nTGFiZWwoMCwgMCwgMSwgLTEpCmVuZAoKZnVuY3Rpb24gQ2xvc2VNZW51KCkKCVNlbmROVUlNZXNzYWdlKHsKCQlhY3Rpb24gPSAiY2xvc2UiCgl9KQoJCglhbnlNZW51T3Blbi5tZW51TmFtZSA9ICIiCglhbnlNZW51T3Blbi5pc0FjdGl2ZSA9IGZhbHNlCmVuZAoKUmVnaXN0ZXJOVUlDYWxsYmFjaygnc2VuZEFjdGlvbicsIGZ1bmN0aW9uKGRhdGEsIGNiKQoJX0dbZGF0YS5hY3Rpb25dKCkKICAgIGNiKCdvaycpCmVuZCkKCi0tCi0tVGhyZWFkcwotLQoKbG9jYWwgYWxyZWFkeURlYWQgPSBmYWxzZQoKQ2l0aXplbi5DcmVhdGVUaHJlYWQoZnVuY3Rpb24oKQoKCS0tRW1iZWRkZWQgTmV2ZXJXYW50ZWQgc2NyaXB0IC8vIE5vbiBsb29wIHBhcnQKCWlmKGNvbmZpZy5lbmFibGVOZXZlcldhbnRlZCA9PSB0cnVlKSB0aGVuCgkJU2V0UG9saWNlSWdub3JlUGxheWVyKFBsYXllcklkKCksIHRydWUpCgkJU2V0RGlzcGF0Y2hDb3BzRm9yUGxheWVyKFBsYXllcklkKCksIGZhbHNlKQoJCUNpdGl6ZW4uSW52b2tlTmF0aXZlKDB4REMwRjgxNzg4NENERDg1NiwgMSwgZmFsc2UpCgkJQ2l0aXplbi5JbnZva2VOYXRpdmUoMHhEQzBGODE3ODg0Q0REODU2LCAyLCBmYWxzZSkKCQlDaXRpemVuLkludm9rZU5hdGl2ZSgweERDMEY4MTc4ODRDREQ4NTYsIDMsIGZhbHNlKQoJCUNpdGl6ZW4uSW52b2tlTmF0aXZlKDB4REMwRjgxNzg4NENERDg1NiwgNSwgZmFsc2UpCgkJQ2l0aXplbi5JbnZva2VOYXRpdmUoMHhEQzBGODE3ODg0Q0REODU2LCA4LCBmYWxzZSkKCQlDaXRpemVuLkludm9rZU5hdGl2ZSgweERDMEY4MTc4ODRDREQ4NTYsIDksIGZhbHNlKQoJCUNpdGl6ZW4uSW52b2tlTmF0aXZlKDB4REMwRjgxNzg4NENERDg1NiwgMTAsIGZhbHNlKQoJCUNpdGl6ZW4uSW52b2tlTmF0aXZlKDB4REMwRjgxNzg4NENERDg1NiwgMTEsIGZhbHNlKQoJZW5kCgkKCWZvciBfLCBpdGVtIGluIHBhaXJzKGNsb2NrSW5TdGF0aW9uKSBkbwogICAgICBpdGVtLmJsaXAgPSBBZGRCbGlwRm9yQ29vcmQoaXRlbS54LCBpdGVtLnksIGl0ZW0ueikKICAgICAgU2V0QmxpcFNwcml0ZShpdGVtLmJsaXAsIDYwKQogICAgICBTZXRCbGlwQXNTaG9ydFJhbmdlKGl0ZW0uYmxpcCwgdHJ1ZSkKICAgICAgQmVnaW5UZXh0Q29tbWFuZFNldEJsaXBOYW1lKCJTVFJJTkciKQogICAgICBBZGRUZXh0Q29tcG9uZW50U3RyaW5nKHR4dFtjb25maWcubGFuZ11bInBvbGljZV9zdGF0aW9uIl0pCiAgICAgIEVuZFRleHRDb21tYW5kU2V0QmxpcE5hbWUoaXRlbS5ibGlwKQogICAgZW5kCgkKICAgIHdoaWxlIHRydWUgZG8KICAgICAgICBDaXRpemVuLldhaXQoMTApCgkJCgkJRGlzYWJsZVBsYXllclZlaGljbGVSZXdhcmRzKFBsYXllcklkKCkpCgkJCgkJLS1FbWJlZGRlZCBOZXZlcldhbnRlZCBzY3JpcHQgLy8gTG9vcCBwYXJ0CgkJaWYoY29uZmlnLmVuYWJsZU5ldmVyV2FudGVkID09IHRydWUpIHRoZW4KCQkJU2V0UGxheWVyV2FudGVkTGV2ZWwoUGxheWVySWQoKSwgMCwgZmFsc2UpCgkJCVNldFBsYXllcldhbnRlZExldmVsTm93KFBsYXllcklkKCksIGZhbHNlKQoJCQlDbGVhckFyZWFPZkNvcHMoKQoJCWVuZAoJCQoJCWlmKGFueU1lbnVPcGVuLmlzQWN0aXZlKSB0aGVuCgkJCURpc2FibGVDb250cm9sQWN0aW9uKDEsIDIxKQoJCQlEaXNhYmxlQ29udHJvbEFjdGlvbigxLCAxNDApCgkJCURpc2FibGVDb250cm9sQWN0aW9uKDEsIDE0MSkKCQkJRGlzYWJsZUNvbnRyb2xBY3Rpb24oMSwgMTQyKQoJCQlTZXREaXNhYmxlQW1iaWVudE1lbGVlTW92ZShHZXRQbGF5ZXJQZWQoLTEpLCB0cnVlKQoJCQlpZiAoSXNDb250cm9sSnVzdFByZXNzZWQoMSwxNzIpKSB0aGVuCgkJCQlTZW5kTlVJTWVzc2FnZSh7CgkJCQkJYWN0aW9uID0gImtleXVwIgoJCQkJfSkKCQkJZWxzZWlmIChJc0NvbnRyb2xKdXN0UHJlc3NlZCgxLDE3MykpIHRoZW4KCQkJCVNlbmROVUlNZXNzYWdlKHsKCQkJCQlhY3Rpb24gPSAia2V5ZG93biIKCQkJCX0pCgkJCWVsc2VpZiAoSXNDb250cm9sSnVzdFByZXNzZWQoMSwxNzYpKSB0aGVuCgkJCQlTZW5kTlVJTWVzc2FnZSh7CgkJCQkJYWN0aW9uID0gImtleWVudGVyIgoJCQkJfSkKCQkJZWxzZWlmIChJc0NvbnRyb2xKdXN0UHJlc3NlZCgxLDE3NykpIHRoZW4KCQkJCWlmKGFueU1lbnVPcGVuLm1lbnVOYW1lID09ICJwb2xpY2VtZW51IiBvciBhbnlNZW51T3Blbi5tZW51TmFtZSA9PSAiYXJtb3J5IiBvciBhbnlNZW51T3Blbi5tZW51TmFtZSA9PSAiY2xvYWNrcm9vbSIgb3IgYW55TWVudU9wZW4ubWVudU5hbWUgPT0gImdhcmFnZSIpIHRoZW4KCQkJCQlDbG9zZU1lbnUoKQoJCQkJZWxzZWlmKGFueU1lbnVPcGVuLm1lbnVOYW1lID09ICJhcm1vcnktd2VhcG9uX2xpc3QiKSB0aGVuCgkJCQkJQmFja0FybW9yeSgpCgkJCQllbHNlCgkJCQkJQmFja01lbnVQb2xpY2UoKQoJCQkJZW5kCgkJCWVuZAoJCWVsc2UKCQkJRW5hYmxlQ29udHJvbEFjdGlvbigxLCAyMSkKCQkJRW5hYmxlQ29udHJvbEFjdGlvbigxLCAxNDApCgkJCUVuYWJsZUNvbnRyb2xBY3Rpb24oMSwgMTQxKQoJCQlFbmFibGVDb250cm9sQWN0aW9uKDEsIDE0MikKCQllbmQKCQkKCQktLUNvbnRyb2wgZGVhdGggZXZlbnRzCgkJaWYoY29uZmlnLnVzZU1vZGlmaWVkRW1lcmdlbmN5ID09IGZhbHNlKSB0aGVuCgkJCWlmKElzUGxheWVyRGVhZChQbGF5ZXJJZCgpKSkgdGhlbgoJCQkJaWYoYWxyZWFkeURlYWQgPT0gZmFsc2UpIHRoZW4KCQkJCQlpZihpc0luU2VydmljZSkgdGhlbgoJCQkJCQlTZXJ2aWNlT2ZmKCkKCQkJCQllbmQKCQkJCQloYW5kQ3VmZmVkID0gZmFsc2UKCQkJCQlkcmFnID0gZmFsc2UKCQkJCQlhbHJlYWR5RGVhZCA9IHRydWUKCQkJCWVuZAoJCQllbHNlCgkJCQlhbHJlYWR5RGVhZCA9IGZhbHNlCgkJCWVuZAoJCWVuZAoJCQoJCWlmIChoYW5kQ3VmZmVkID09IHRydWUpIHRoZW4KCQkJUmVxdWVzdEFuaW1EaWN0KCdtcF9hcnJlc3RpbmcnKQoKCQkJd2hpbGUgbm90IEhhc0FuaW1EaWN0TG9hZGVkKCdtcF9hcnJlc3RpbmcnKSBkbwoJCQkJQ2l0aXplbi5XYWl0KDApCgkJCWVuZAoKCQkJbG9jYWwgbXlQZWQgPSBQbGF5ZXJQZWRJZCgtMSkKCQkJbG9jYWwgYW5pbWF0aW9uID0gJ2lkbGUnCgkJCWxvY2FsIGZsYWdzID0gMTYKCQkJCgkJCXdoaWxlKElzUGVkQmVpbmdTdHVubmVkKG15UGVkLCAwKSkgZG8KCQkJCUNsZWFyUGVkVGFza3NJbW1lZGlhdGVseShteVBlZCkKCQkJZW5kCgkJCVRhc2tQbGF5QW5pbShteVBlZCwgJ21wX2FycmVzdGluZycsIGFuaW1hdGlvbiwgOC4wLCAtOCwgLTEsIGZsYWdzLCAwLCAwLCAwLCAwKQoJCWVuZAoJCQoJCS0tUGllY2Ugb2YgY29kZSBmcm9tIERyYWcgY29tbWFuZCAoYnkgRnJhenpsZSwgVmFsaywgTWljaGFlbF9TYW5lbGxpLCBOWUtJTExBMTEyNyA6IGh0dHBzOi8vZi4uLmNvbnRlbnQtYXZhaWxhYmxlLXRvLWF1dGhvci1vbmx5Li4ubS5uZXQvdC9yZWxlYXNlLWRyYWctY29tbWFuZC8yMjE3NCkKCQlpZiBkcmFnIHRoZW4KCQkJbG9jYWwgcGVkID0gR2V0UGxheWVyUGVkKEdldFBsYXllckZyb21TZXJ2ZXJJZChvZmZpY2VyRHJhZykpCgkJCWxvY2FsIG15cGVkID0gR2V0UGxheWVyUGVkKC0xKQoJCQlBdHRhY2hFbnRpdHlUb0VudGl0eShteXBlZCwgcGVkLCA0MTAzLCAxMTgxNiwgMC40OCwgMC4wMCwgMC4wLCAwLjAsIDAuMCwgMC4wLCBmYWxzZSwgZmFsc2UsIGZhbHNlLCBmYWxzZSwgMiwgdHJ1ZSkKCQllbHNlCgkJCURldGFjaEVudGl0eShHZXRQbGF5ZXJQZWQoLTEpLCB0cnVlLCBmYWxzZSkJCQoJCWVuZAoJCQogICAgICAgIGlmKGlzQ29wKSB0aGVuCgkJCWlmKGlzTmVhclRha2VTZXJ2aWNlKCkpIHRoZW4KCQkJCgkJCQlEaXNwbGF5SGVscFRleHQodHh0W2NvbmZpZy5sYW5nXVsiaGVscF90ZXh0X29wZW5fY2xvYWNrcm9vbSJdLDAsMSwwLjUsMC44LDAuNiwyNTUsMjU1LDI1NSwyNTUpIC0tIH5nfkV+c34KCQkJCWlmIElzQ29udHJvbEp1c3RQcmVzc2VkKDEsNTEpIHRoZW4KCQkJCQlPcGVuQ2xvYWNrcm9vbSgpCgkJCQllbmQKCQkJZW5kCgkJCQoJCQlpZihpc0luU2VydmljZSkgdGhlbgoJCQkKCQkJCS0tT3BlbiBHYXJhZ2UgbWVudQoJCQkJaWYoaXNOZWFyU3RhdGlvbkdhcmFnZSgpKSB0aGVuCgkJCQkJaWYocG9saWNldmVoaWNsZSB+PSBuaWwpIHRoZW4KCQkJCQkJRGlzcGxheUhlbHBUZXh0KHR4dFtjb25maWcubGFuZ11bImhlbHBfdGV4dF9wdXRfY2FyX2ludG9fZ2FyYWdlIl0sMCwxLDAuNSwwLjgsMC42LDI1NSwyNTUsMjU1LDI1NSkKCQkJCQllbHNlCgkJCQkJCURpc3BsYXlIZWxwVGV4dCh0eHRbY29uZmlnLmxhbmddWyJoZWxwX3RleHRfZ2V0X2Nhcl9vdXRfZ2FyYWdlIl0sMCwxLDAuNSwwLjgsMC42LDI1NSwyNTUsMjU1LDI1NSkKCQkJCQllbmQKCQkJCQkKCQkJCQlpZiBJc0NvbnRyb2xKdXN0UHJlc3NlZCgxLDUxKSB0aGVuCgkJCQkJCWlmKHBvbGljZXZlaGljbGUgfj0gbmlsKSB0aGVuCgkJCQkJCQktLURlc3Ryb3kgcG9saWNlIHZlaGljbGUKCQkJCQkJCUNpdGl6ZW4uSW52b2tlTmF0aXZlKDB4RUEzODY5ODZFNzg2QTU0RiwgQ2l0aXplbi5Qb2ludGVyVmFsdWVJbnRJbml0aWFsaXplZChwb2xpY2V2ZWhpY2xlKSkKCQkJCQkJCXBvbGljZXZlaGljbGUgPSBuaWwKCQkJCQkJZWxzZQoJCQkJCQkJT3BlbkdhcmFnZSgpCgkJCQkJCWVuZAoJCQkJCWVuZAoJCQkJZW5kCgkJCQkKCQkJCS0tT3BlbiBHYXJhZ2UgbWVudQoJCQkJaWYoaXNOZWFyQXJtb3J5KCkpIHRoZW4KCQkJCQkKCQkJCQlEaXNwbGF5SGVscFRleHQodHh0W2NvbmZpZy5sYW5nXVsiaGVscF90ZXh0X29wZW5fYXJtb3J5Il0sMCwxLDAuNSwwLjgsMC42LDI1NSwyNTUsMjU1LDI1NSkKCQkJCQkKCQkJCQlpZiBJc0NvbnRyb2xKdXN0UHJlc3NlZCgxLDUxKSB0aGVuCgkJCQkJCU9wZW5Bcm1vcnkoKQoJCQkJCWVuZAoJCQkJZW5kCgkJCQkKCQkJCS0tT3Blbi9DbG9zZSBNZW51IHBvbGljZQoJCQkJaWYgKElzQ29udHJvbEp1c3RQcmVzc2VkKDEsMTY2KSkgdGhlbgoJCQkJCVRvZ2dsZVBvbGljZU1lbnUoKQoJCQkJZW5kCgkJCQkKCQkJCS0tQ29udHJvbCBoZWxpY29wdGVyIHNwYXduaW5nCgkJCQlpZiBpc05lYXJIZWxpY29wdGVyU3RhdGlvbigpIHRoZW4KCQkJCQlpZihwb2xpY2VIZWxpIH49IG5pbCkgdGhlbgoJCQkJCQlEaXNwbGF5SGVscFRleHQodHh0W2NvbmZpZy5sYW5nXVsiaGVscF90ZXh0X3B1dF9oZWxpX2ludG9fZ2FyYWdlIl0sMCwxLDAuNSwwLjgsMC42LDI1NSwyNTUsMjU1LDI1NSkKCQkJCQllbHNlCgkJCQkJCURpc3BsYXlIZWxwVGV4dCh0eHRbY29uZmlnLmxhbmddWyJoZWxwX3RleHRfZ2V0X2hlbGlfb3V0X2dhcmFnZSJdLDAsMSwwLjUsMC44LDAuNiwyNTUsMjU1LDI1NSwyNTUpCgkJCQkJZW5kCgkJCQkJCgkJCQkJaWYgSXNDb250cm9sSnVzdFByZXNzZWQoMSw1MSkgIHRoZW4KCQkJCQkJaWYocG9saWNlSGVsaSB+PSBuaWwpIHRoZW4KCQkJCQkJCUNpdGl6ZW4uSW52b2tlTmF0aXZlKDB4RUEzODY5ODZFNzg2QTU0RiwgQ2l0aXplbi5Qb2ludGVyVmFsdWVJbnRJbml0aWFsaXplZChwb2xpY2VIZWxpKSkKCQkJCQkJCXBvbGljZUhlbGkgPSBuaWwKCQkJCQkJZWxzZQoJCQkJCQkJbG9jYWwgaGVsaSA9IEdldEhhc2hLZXkoInBvbG1hdiIpCgkJCQkJCQlsb2NhbCBwbHkgPSBHZXRQbGF5ZXJQZWQoLTEpCgkJCQkJCQlsb2NhbCBwbHlDb29yZHMgPSBHZXRFbnRpdHlDb29yZHMocGx5LCAwKQoJCQkJCQkJCgkJCQkJCQlSZXF1ZXN0TW9kZWwoaGVsaSkKCQkJCQkJCXdoaWxlIG5vdCBIYXNNb2RlbExvYWRlZChoZWxpKSBkbwoJCQkJCQkJCQlDaXRpemVuLldhaXQoMCkKCQkJCQkJCWVuZAoJCQkJCQkJCgkJCQkJCQlwb2xpY2VIZWxpID0gQ3JlYXRlVmVoaWNsZShoZWxpLCBwbHlDb29yZHNbIngiXSwgcGx5Q29vcmRzWyJ5Il0sIHBseUNvb3Jkc1sieiJdLCA5MC4wLCB0cnVlLCBmYWxzZSkKCQkJCQkJCVNldFZlaGljbGVIYXNCZWVuT3duZWRCeVBsYXllcihwb2xpY2V2ZWhpY2xlLHRydWUpCgkJCQkJCQlsb2NhbCBuZXRpZCA9IE5ldHdvcmtHZXROZXR3b3JrSWRGcm9tRW50aXR5KHBvbGljZUhlbGkpCgkJCQkJCQlTZXROZXR3b3JrSWRDYW5NaWdyYXRlKG5ldGlkLCB0cnVlKQoJCQkJCQkJTmV0d29ya1JlZ2lzdGVyRW50aXR5QXNOZXR3b3JrZWQoVmVoVG9OZXQocG9saWNlSGVsaSkpCgkJCQkJCQlTZXRWZWhpY2xlTGl2ZXJ5KHBvbGljZUhlbGksIDApCgkJCQkJCQlUYXNrV2FycFBlZEludG9WZWhpY2xlKHBseSwgcG9saWNlSGVsaSwgLTEpCgkJCQkJCQlTZXRFbnRpdHlBc01pc3Npb25FbnRpdHkocG9saWNlSGVsaSwgdHJ1ZSwgdHJ1ZSkKCQkJCQkJZW5kCgkJCQkJZW5kCgkJCQllbmQKCQkJZW5kCgkJZW5kCiAgICBlbmQKZW5kKQ==