mirror of
https://github.com/Michatec/ptelevision.git
synced 2026-04-01 07:56:29 +02:00
Delete ptelevision directory
This commit is contained in:
@@ -1,85 +0,0 @@
|
|||||||
local scale = 1.5
|
|
||||||
local screenWidth = math.floor(1920 / scale)
|
|
||||||
local screenHeight = math.floor(1080 / scale)
|
|
||||||
shouldDraw = false
|
|
||||||
|
|
||||||
function SetInteractScreen(bool)
|
|
||||||
if (not shouldDraw and bool) then
|
|
||||||
shouldDraw = bool
|
|
||||||
Citizen.CreateThread(function ()
|
|
||||||
-- Create screen
|
|
||||||
local nX = 0
|
|
||||||
local nY = 0
|
|
||||||
|
|
||||||
local w, h = screenWidth, screenHeight
|
|
||||||
|
|
||||||
local minX, maxX = ((w - (w / 2)) / 2), (w - (w / 4))
|
|
||||||
local totalX = minX - maxX
|
|
||||||
|
|
||||||
local minY, maxY = ((h - (h / 2)) / 2), (h - (h / 4))
|
|
||||||
local totalY = minY - maxY
|
|
||||||
|
|
||||||
RequestTextureDictionary('fib_pc')
|
|
||||||
|
|
||||||
-- Update controls while active
|
|
||||||
while shouldDraw do
|
|
||||||
nX = GetControlNormal(0, 239) * screenWidth
|
|
||||||
nY = GetControlNormal(0, 240) * screenHeight
|
|
||||||
DisableControlAction(0, 1, true) -- Disable looking horizontally
|
|
||||||
DisableControlAction(0, 2, true) -- Disable looking vertically
|
|
||||||
DisablePlayerFiring(PlayerPedId(), true) -- Disable weapon firing
|
|
||||||
DisableControlAction(0, 142, true) -- Disable aiming
|
|
||||||
DisableControlAction(0, 106, true) -- Disable in-game mouse controls
|
|
||||||
-- Update mouse position when changed
|
|
||||||
DrawSprite("ptelevision_b_dict", "ptelevision_b_txd", 0.5, 0.5, 0.5, 0.5, 0.0, 255, 255, 255, 255)
|
|
||||||
if nX ~= mX or nY ~= mY then
|
|
||||||
mX = nX; mY = nY
|
|
||||||
local duiX = -screenWidth * ((mX - minX) / totalX)
|
|
||||||
local duiY = -screenHeight * ((mY - minY) / totalY)
|
|
||||||
BlockWeaponWheelThisFrame()
|
|
||||||
if not (mX > 325) then
|
|
||||||
mX = 325
|
|
||||||
end
|
|
||||||
if not (mX < 965) then
|
|
||||||
mX = 965
|
|
||||||
end
|
|
||||||
if not (mY > 185) then
|
|
||||||
mY = 185
|
|
||||||
end
|
|
||||||
if not (mY < 545) then
|
|
||||||
mY = 545
|
|
||||||
end
|
|
||||||
SendDuiMouseMove(duiObj, math.floor(duiX), math.floor(duiY))
|
|
||||||
end
|
|
||||||
DrawSprite('fib_pc', 'arrow', mX / screenWidth, mY / screenHeight, 0.005, 0.01, 0.0, 255, 255, 255, 255)
|
|
||||||
|
|
||||||
-- Send scroll and click events to dui
|
|
||||||
|
|
||||||
if IsControlPressed(0, 177) then
|
|
||||||
SetInteractScreen(false)
|
|
||||||
OpenTVMenu()
|
|
||||||
end -- scroll up
|
|
||||||
if IsControlPressed(0, 172) then
|
|
||||||
SendDuiMouseWheel(duiObj, 10, 0) end -- scroll up
|
|
||||||
if IsControlPressed(0, 173) then
|
|
||||||
SendDuiMouseWheel(duiObj, -10, 0) end -- scroll down
|
|
||||||
|
|
||||||
if IsDisabledControlJustPressed(0, 24) then
|
|
||||||
SendDuiMouseDown(duiObj, 'left')
|
|
||||||
elseif IsDisabledControlJustReleased(0, 24) then
|
|
||||||
SendDuiMouseUp(duiObj, 'left')
|
|
||||||
SendDuiMouseUp(duiObj, "right")
|
|
||||||
end
|
|
||||||
if IsDisabledControlJustPressed(0, 25) then
|
|
||||||
SendDuiMouseDown(duiObj, "right")
|
|
||||||
elseif IsDisabledControlJustReleased(0, 24) then
|
|
||||||
SendDuiMouseUp(duiObj, "right")
|
|
||||||
end
|
|
||||||
|
|
||||||
Wait(0)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
else
|
|
||||||
shouldDraw = bool
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,185 +0,0 @@
|
|||||||
DEFAULT_URL = "https://cfx-nui-ptelevision/html/index.html"
|
|
||||||
duiUrl = DEFAULT_URL
|
|
||||||
duiObj = nil
|
|
||||||
tvObj = nil
|
|
||||||
volume = 0.5
|
|
||||||
CURRENT_SCREEN = nil
|
|
||||||
|
|
||||||
function getDuiURL()
|
|
||||||
return duiUrl
|
|
||||||
end
|
|
||||||
|
|
||||||
function SetVolume(coords, num)
|
|
||||||
volume = num
|
|
||||||
SetTelevisionLocal(coords, "volume", num)
|
|
||||||
end
|
|
||||||
|
|
||||||
function GetVolume(dist, range)
|
|
||||||
if not volume then return 0 end
|
|
||||||
local rem = (dist / range)
|
|
||||||
rem = rem > volume and volume or rem
|
|
||||||
local _vol = math.floor((volume - rem) * 100)
|
|
||||||
return _vol
|
|
||||||
end
|
|
||||||
|
|
||||||
function setDuiURL(url)
|
|
||||||
duiUrl = url
|
|
||||||
SetDuiUrl(duiObj, duiUrl)
|
|
||||||
end
|
|
||||||
|
|
||||||
local sfName = 'generic_texture_renderer'
|
|
||||||
|
|
||||||
local width = 1280
|
|
||||||
local height = 720
|
|
||||||
|
|
||||||
local sfHandle = nil
|
|
||||||
local txdHasBeenSet = false
|
|
||||||
|
|
||||||
|
|
||||||
function loadScaleform(scaleform)
|
|
||||||
local scaleformHandle = RequestScaleformMovie(scaleform)
|
|
||||||
|
|
||||||
while not HasScaleformMovieLoaded(scaleformHandle) do
|
|
||||||
scaleformHandle = RequestScaleformMovie(scaleform)
|
|
||||||
Citizen.Wait(0)
|
|
||||||
end
|
|
||||||
return scaleformHandle
|
|
||||||
end
|
|
||||||
|
|
||||||
function ShowScreen(data)
|
|
||||||
CURRENT_SCREEN = data
|
|
||||||
sfHandle = loadScaleform(sfName)
|
|
||||||
runtimeTxd = 'ptelevision_b_dict'
|
|
||||||
|
|
||||||
local txd = CreateRuntimeTxd('ptelevision_b_dict')
|
|
||||||
duiObj = CreateDui(duiUrl, width, height)
|
|
||||||
local dui = GetDuiHandle(duiObj)
|
|
||||||
local tx = CreateRuntimeTextureFromDuiHandle(txd, 'ptelevision_b_txd', dui)
|
|
||||||
|
|
||||||
Citizen.Wait(10)
|
|
||||||
|
|
||||||
PushScaleformMovieFunction(sfHandle, 'SET_TEXTURE')
|
|
||||||
|
|
||||||
PushScaleformMovieMethodParameterString('ptelevision_b_dict')
|
|
||||||
PushScaleformMovieMethodParameterString('ptelevision_b_txd')
|
|
||||||
|
|
||||||
PushScaleformMovieFunctionParameterInt(0)
|
|
||||||
PushScaleformMovieFunctionParameterInt(0)
|
|
||||||
PushScaleformMovieFunctionParameterInt(width)
|
|
||||||
PushScaleformMovieFunctionParameterInt(height)
|
|
||||||
|
|
||||||
PopScaleformMovieFunctionVoid()
|
|
||||||
Citizen.CreateThread(function()
|
|
||||||
local tvObj = data.entity
|
|
||||||
|
|
||||||
local _, status = GetTelevision(data.coords)
|
|
||||||
local _, lstatus = GetTelevisionLocal(data.coords)
|
|
||||||
local screenModel = Config.Models[data.model]
|
|
||||||
if status and status["ptv_status"] then
|
|
||||||
local status = status["ptv_status"]
|
|
||||||
Citizen.Wait(1000)
|
|
||||||
if status.type == "play" and lstatus then
|
|
||||||
if (status.channel and Channels[status.channel]) then
|
|
||||||
PlayVideo({url = Channels[status.channel].url, channel = status.channel})
|
|
||||||
elseif (status.url) then
|
|
||||||
local time
|
|
||||||
if (lstatus.start_time) then
|
|
||||||
time = math.floor((GetGameTimer() - lstatus.start_time) / 1000)
|
|
||||||
end
|
|
||||||
PlayVideo({url = status.url, time = time})
|
|
||||||
end
|
|
||||||
elseif (status.type == "browser") then
|
|
||||||
PlayBrowser({ url = status.url })
|
|
||||||
end
|
|
||||||
end
|
|
||||||
while duiObj do
|
|
||||||
if (tvObj and sfHandle ~= nil and HasScaleformMovieLoaded(sfHandle)) then
|
|
||||||
local pos = GetEntityCoords(tvObj)
|
|
||||||
local scale = screenModel.Scale
|
|
||||||
local offset = GetOffsetFromEntityInWorldCoords(tvObj, -1.02, -0.055, 1.04)
|
|
||||||
local hz = GetEntityHeading(tvObj)
|
|
||||||
DrawScaleformMovie_3dNonAdditive(sfHandle, offset.x, offset.y, offset.z, 0.0, -hz, 0.0, 2.0, 2.0, 2.0, scale * 1, scale * (9/16), 1, 2)
|
|
||||||
end
|
|
||||||
Citizen.Wait(0)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
Citizen.CreateThread(function()
|
|
||||||
local screen = CURRENT_SCREEN
|
|
||||||
local modelData = Config.Models[screen.model]
|
|
||||||
local coords = screen.coords
|
|
||||||
local range = modelData.Range
|
|
||||||
local _, lstatus = GetTelevisionLocal(coords)
|
|
||||||
if (lstatus and lstatus.volume) then
|
|
||||||
SetVolume(coords, lstatus.volume)
|
|
||||||
else
|
|
||||||
SetVolume(coords, modelData.DefaultVolume)
|
|
||||||
end
|
|
||||||
while duiObj do
|
|
||||||
local pcoords = GetEntityCoords(PlayerPedId())
|
|
||||||
local dist = #(coords - pcoords)
|
|
||||||
SendDuiMessage(duiObj, json.encode({
|
|
||||||
setVolume = true,
|
|
||||||
data = GetVolume(dist, range, volume)
|
|
||||||
}))
|
|
||||||
Citizen.Wait(100)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
function HideScreen()
|
|
||||||
if (duiObj) then
|
|
||||||
DestroyDui(duiObj)
|
|
||||||
SetScaleformMovieAsNoLongerNeeded(sfHandle)
|
|
||||||
duiObj = nil
|
|
||||||
sfHandle = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function GetClosestScreen()
|
|
||||||
local objPool = GetGamePool('CObject')
|
|
||||||
local closest = {dist = -1}
|
|
||||||
local pcoords = GetEntityCoords(PlayerPedId())
|
|
||||||
for i=1, #objPool do
|
|
||||||
local entity = objPool[i]
|
|
||||||
local model = GetEntityModel(entity)
|
|
||||||
local data = Config.Models[model]
|
|
||||||
if (data) then
|
|
||||||
local coords = GetEntityCoords(entity)
|
|
||||||
local dist = #(pcoords-coords)
|
|
||||||
if (dist < closest.dist or closest.dist < 0) and dist < data.Range then
|
|
||||||
closest = {dist = dist, coords = coords, model = model, entity = entity}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return (closest.entity and closest or nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
Citizen.CreateThread(function()
|
|
||||||
Citizen.Wait(2000)
|
|
||||||
TriggerServerEvent("ptelevision:requestUpdate")
|
|
||||||
while true do
|
|
||||||
local wait = 2500
|
|
||||||
local data = GetClosestScreen()
|
|
||||||
if (data and not duiObj) then
|
|
||||||
ShowScreen(data)
|
|
||||||
elseif ((not data or #(vec3(CURRENT_SCREEN.coords) - vec3(data.coords)) > 0.01 ) and duiObj) then
|
|
||||||
HideScreen()
|
|
||||||
end
|
|
||||||
Citizen.Wait(wait)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
RegisterNetEvent("ptelevision:requestUpdate", function(data)
|
|
||||||
Televisions = data.Televisions
|
|
||||||
Channels = data.Channels
|
|
||||||
end)
|
|
||||||
|
|
||||||
RegisterNUICallback("pageLoaded", function()
|
|
||||||
waitForLoad = false
|
|
||||||
end)
|
|
||||||
|
|
||||||
AddEventHandler('onResourceStop', function(name)
|
|
||||||
if name == GetCurrentResourceName() then
|
|
||||||
HideScreen()
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
@@ -1,226 +0,0 @@
|
|||||||
TelevisionsLocal = {}
|
|
||||||
|
|
||||||
function SetChannel(index)
|
|
||||||
TriggerServerEvent("ptelevision:event", CURRENT_SCREEN, "ptv_status", {
|
|
||||||
type = "play",
|
|
||||||
channel = index,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
function GetChannelList()
|
|
||||||
if not Channels then return {} end
|
|
||||||
local channel_list = {}
|
|
||||||
local menu_list = {}
|
|
||||||
local current = 1
|
|
||||||
local screen = CURRENT_SCREEN
|
|
||||||
local ent = screen.entity
|
|
||||||
local _, status = GetTelevision(screen.coords)
|
|
||||||
local channel = nil
|
|
||||||
if (status) then
|
|
||||||
channel = status.channel
|
|
||||||
end
|
|
||||||
for index,value in pairs(Channels) do
|
|
||||||
table.insert(channel_list, {index = index, url = value.url})
|
|
||||||
table.insert(menu_list, "Channel #" .. index .. " (".. value.name ..")")
|
|
||||||
if channel ~= nil and channel == index then
|
|
||||||
current = #channel_list
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return {list = channel_list, display = menu_list, current = current}
|
|
||||||
end
|
|
||||||
|
|
||||||
function BroadcastMenu()
|
|
||||||
local _source = GetPlayerServerId(PlayerId())
|
|
||||||
for k,v in pairs(Channels) do
|
|
||||||
if (v.source == _source) then
|
|
||||||
TriggerServerEvent("ptelevision:broadcast", nil)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local input = lib.inputDialog('Live Broadcast', {'Channel Name:', 'Broadcast URL:'})
|
|
||||||
if (input[1] and input[2]) then
|
|
||||||
TriggerServerEvent("ptelevision:broadcast", {name = input[1], url = input[2]})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function WebBrowserMenu()
|
|
||||||
lib.hideMenu()
|
|
||||||
local input = lib.inputDialog('Web Browser', {'URL:'})
|
|
||||||
|
|
||||||
if input then
|
|
||||||
TriggerServerEvent("ptelevision:event", CURRENT_SCREEN, "ptv_status", {
|
|
||||||
type = "browser",
|
|
||||||
url = input[1]
|
|
||||||
})
|
|
||||||
end
|
|
||||||
Citizen.Wait(300)
|
|
||||||
OpenTVMenu()
|
|
||||||
end
|
|
||||||
|
|
||||||
function VideoMenu()
|
|
||||||
lib.hideMenu()
|
|
||||||
local input = lib.inputDialog('Video Player', {'URL:'})
|
|
||||||
if input then
|
|
||||||
TriggerServerEvent("ptelevision:event", CURRENT_SCREEN, "ptv_status", {
|
|
||||||
type = "play",
|
|
||||||
url = input[1]
|
|
||||||
})
|
|
||||||
end
|
|
||||||
Citizen.Wait(300)
|
|
||||||
OpenTVMenu()
|
|
||||||
end
|
|
||||||
|
|
||||||
function VolumeMenu()
|
|
||||||
lib.hideMenu()
|
|
||||||
local input = lib.inputDialog('Volume', {'Set Volume (0-100):'})
|
|
||||||
if (tonumber(input[1])) then
|
|
||||||
local coords = CURRENT_SCREEN.coords
|
|
||||||
SetVolume(coords, tonumber(input[1])/100)
|
|
||||||
end
|
|
||||||
Citizen.Wait(300)
|
|
||||||
OpenTVMenu()
|
|
||||||
end
|
|
||||||
|
|
||||||
function OpenTVMenu()
|
|
||||||
local screen = CURRENT_SCREEN
|
|
||||||
if not screen then return end
|
|
||||||
lib.hideMenu()
|
|
||||||
local ChannelList = GetChannelList()
|
|
||||||
lib.registerMenu({
|
|
||||||
id = 'ptelevision-menu',
|
|
||||||
title = 'Television',
|
|
||||||
position = 'top-right',
|
|
||||||
onSideScroll = function(selected, scrollIndex, args)
|
|
||||||
if (selected == 3) then
|
|
||||||
SetChannel(ChannelList.list[scrollIndex].index)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
onSelected = function(selected, scrollIndex, args)
|
|
||||||
end,
|
|
||||||
onClose = function(keyPressed)
|
|
||||||
end,
|
|
||||||
options = {
|
|
||||||
{label = 'Videos', description = 'Play a video or stream on the screen.'},
|
|
||||||
{label = 'Web Browser', description = 'Access the web via your TV.'},
|
|
||||||
{label = 'TV Channels', values = ChannelList.display, description = 'Live TV Channels in San Andreas!', defaultIndex = ChannelList.current},
|
|
||||||
{label = 'Interact With Screen', description = 'Allows you to control on-screen elements.'},
|
|
||||||
{label = 'Set Volume', description = 'Sets your TV\'s volume (For yourself).'},
|
|
||||||
{label = 'Close Menu', close = true},
|
|
||||||
}
|
|
||||||
}, function(selected, scrollIndex, args)
|
|
||||||
if (selected == 1) then
|
|
||||||
VideoMenu()
|
|
||||||
elseif (selected == 2) then
|
|
||||||
WebBrowserMenu()
|
|
||||||
elseif (selected == 3) then
|
|
||||||
SetChannel(ChannelList.list[scrollIndex].index)
|
|
||||||
OpenTVMenu()
|
|
||||||
elseif selected == 4 then
|
|
||||||
SetInteractScreen(true)
|
|
||||||
elseif selected == 5 then
|
|
||||||
VolumeMenu()
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
lib.showMenu('ptelevision-menu')
|
|
||||||
end
|
|
||||||
|
|
||||||
function PlayBrowser(data)
|
|
||||||
while not IsDuiAvailable(duiObj) do Wait(10) end
|
|
||||||
setDuiURL(data.url)
|
|
||||||
end
|
|
||||||
|
|
||||||
function PlayVideo(data)
|
|
||||||
while not IsDuiAvailable(duiObj) do Wait(10) end
|
|
||||||
if (getDuiURL() ~= DEFAULT_URL) then
|
|
||||||
waitForLoad = true
|
|
||||||
setDuiURL(DEFAULT_URL)
|
|
||||||
while waitForLoad do Wait(10) end
|
|
||||||
end
|
|
||||||
SendDuiMessage(duiObj, json.encode({
|
|
||||||
setVideo = true,
|
|
||||||
data = data
|
|
||||||
}))
|
|
||||||
end
|
|
||||||
|
|
||||||
function ResetDisplay()
|
|
||||||
setDuiURL(DEFAULT_URL)
|
|
||||||
end
|
|
||||||
|
|
||||||
function GetTelevisionLocal(coords)
|
|
||||||
for k,v in pairs(TelevisionsLocal) do
|
|
||||||
if #(vec3(v.coords) - vec3(coords)) < 0.01 then
|
|
||||||
return k, v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function SetTelevisionLocal(coords, key, value)
|
|
||||||
local index, data = GetTelevisionLocal(coords)
|
|
||||||
if (index ~= nil) then
|
|
||||||
if (TelevisionsLocal[index] == nil) then
|
|
||||||
TelevisionsLocal[index] = {}
|
|
||||||
end
|
|
||||||
TelevisionsLocal[index][key] = value
|
|
||||||
else
|
|
||||||
index = GetGameTimer()
|
|
||||||
while TelevisionsLocal[index] do
|
|
||||||
index = index + 1
|
|
||||||
Citizen.Wait(0)
|
|
||||||
end
|
|
||||||
if (TelevisionsLocal[index] == nil) then
|
|
||||||
TelevisionsLocal[index] = {}
|
|
||||||
end
|
|
||||||
TelevisionsLocal[index][key] = value
|
|
||||||
end
|
|
||||||
TelevisionsLocal[index].coords = coords
|
|
||||||
return index
|
|
||||||
end
|
|
||||||
|
|
||||||
RegisterNetEvent("ptelevision:event", function(data, index, key, value)
|
|
||||||
Televisions = data
|
|
||||||
local data = Televisions[index]
|
|
||||||
local screen = CURRENT_SCREEN
|
|
||||||
if (screen and #(vec3(screen.coords) - vec3(data.coords)) < 0.001) then
|
|
||||||
local index, data = GetTelevision(screen.coords)
|
|
||||||
if (index) then
|
|
||||||
local event = value
|
|
||||||
if (event.type == "play") then
|
|
||||||
local data = { url = event.url }
|
|
||||||
if (event.channel) then
|
|
||||||
data = Channels[event.channel]
|
|
||||||
data.channel = event.channel
|
|
||||||
end
|
|
||||||
PlayVideo(data)
|
|
||||||
elseif (event.type == "browser") then
|
|
||||||
PlayBrowser({ url = event.url })
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
SetTelevisionLocal(Televisions[index].coords, "start_time", GetGameTimer())
|
|
||||||
end)
|
|
||||||
|
|
||||||
RegisterNetEvent("ptelevision:broadcast", function(data, index)
|
|
||||||
Channels = data
|
|
||||||
if getDuiURL() == DEFAULT_URL then
|
|
||||||
local screen = CURRENT_SCREEN
|
|
||||||
local tvObj = screen.entity
|
|
||||||
local _, status = GetTelevision(screen.coords)
|
|
||||||
if (status and status.channel == index and data[index] == nil) then
|
|
||||||
ResetDisplay()
|
|
||||||
Citizen.Wait(10)
|
|
||||||
end
|
|
||||||
SendDuiMessage(duiObj, json.encode({
|
|
||||||
showNotification = true,
|
|
||||||
channel = index,
|
|
||||||
data = data[index]
|
|
||||||
}))
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
RegisterCommand('tv', function()
|
|
||||||
OpenTVMenu()
|
|
||||||
end)
|
|
||||||
|
|
||||||
RegisterCommand("broadcast", function(source, args, raw)
|
|
||||||
BroadcastMenu()
|
|
||||||
end)
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
function CreateNamedRenderTargetForModel(name, model)
|
|
||||||
local handle = 0
|
|
||||||
if not IsNamedRendertargetRegistered(name) then
|
|
||||||
RegisterNamedRendertarget(name, 0)
|
|
||||||
end
|
|
||||||
if not IsNamedRendertargetLinked(model) then
|
|
||||||
LinkNamedRendertarget(model)
|
|
||||||
end
|
|
||||||
if IsNamedRendertargetRegistered(name) then
|
|
||||||
handle = GetNamedRendertargetRenderId(name)
|
|
||||||
end
|
|
||||||
|
|
||||||
return handle
|
|
||||||
end
|
|
||||||
|
|
||||||
function RequestTextureDictionary (dict)
|
|
||||||
RequestStreamedTextureDict(dict)
|
|
||||||
|
|
||||||
while not HasStreamedTextureDictLoaded(dict) do Wait(0) end
|
|
||||||
|
|
||||||
return dict
|
|
||||||
end
|
|
||||||
|
|
||||||
function LoadModel (model)
|
|
||||||
if not IsModelInCdimage(model) then return end
|
|
||||||
|
|
||||||
RequestModel(model)
|
|
||||||
|
|
||||||
while not HasModelLoaded(model) do Wait(0) end
|
|
||||||
|
|
||||||
return model
|
|
||||||
end
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
Config = {}
|
|
||||||
|
|
||||||
Config.Models = { -- Any TV Models used on the map or in locations must be defined here.
|
|
||||||
[`prop_tv_flat_01`] = {
|
|
||||||
DefaultVolume = 0.5,
|
|
||||||
Range = 20.0,
|
|
||||||
Scale = 0.085,
|
|
||||||
Offset = vector3(-1.02, -0.055, 1.04),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Config.Locations = { -- REMOVE ALL IF NOT USING ONESYNC, OR IT SHALL BREAK.
|
|
||||||
{
|
|
||||||
Model = `prop_tv_flat_01`,
|
|
||||||
Position = vector4(144.3038, -1037.4647, 29.4173, 70.1882)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Model = `prop_tv_flat_01`,
|
|
||||||
Position = vector4(264.0882, -830.7057, 29.4569, 340.7550)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
Config.Channels = { -- These channels are default channels and cannot be overriden.
|
|
||||||
{name = "Pickle Mods", url = "twitch.tv/picklemods"},
|
|
||||||
}
|
|
||||||
|
|
||||||
Config.Events = { -- Events for approving broadcasts / interactions (due to popular demand).
|
|
||||||
ScreenInteract = function(source, data, key, value, cb) -- cb() to approve.
|
|
||||||
cb()
|
|
||||||
end,
|
|
||||||
Broadcast = function(source, data, cb) -- cb() to approve.
|
|
||||||
cb()
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
fx_version "cerulean"
|
|
||||||
game "gta5"
|
|
||||||
author "Pickle Mods#0001"
|
|
||||||
|
|
||||||
ui_page "html/blank.html"
|
|
||||||
|
|
||||||
files {
|
|
||||||
"html/blank.html",
|
|
||||||
"html/index.html",
|
|
||||||
"html/style.css",
|
|
||||||
"html/main.js",
|
|
||||||
"html/VCR_OSD_MONO_1.001.ttf",
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_scripts {
|
|
||||||
"@ox_lib/init.lua",
|
|
||||||
"config.lua",
|
|
||||||
"shared/*.lua"
|
|
||||||
}
|
|
||||||
|
|
||||||
client_scripts {
|
|
||||||
"client/cursor.lua",
|
|
||||||
"client/utils.lua",
|
|
||||||
"client/tv.lua",
|
|
||||||
"client/main.lua",
|
|
||||||
}
|
|
||||||
|
|
||||||
server_scripts {
|
|
||||||
"server/*.lua"
|
|
||||||
}
|
|
||||||
|
|
||||||
lua54 'yes'
|
|
||||||
Binary file not shown.
@@ -1,12 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Document</title>
|
|
||||||
</head>
|
|
||||||
<body style="background-color: transparent">
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Document</title>
|
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
<script src="https://code.jquery.com/jquery-3.6.1.min.js" integrity="sha256-o88AwQnZB+VDvE9tvIXrMQaPlFFSUTR+nldQm1LuPXQ=" crossorigin="anonymous"></script>
|
|
||||||
<script src="https://player.twitch.tv/js/embed/v1.js"></script>
|
|
||||||
<script src="https://www.youtube.com/iframe_api"> </script>
|
|
||||||
<script src="main.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<!-- Add a placeholder for the Twitch embed -->
|
|
||||||
<div id="background">
|
|
||||||
</div>
|
|
||||||
<div id="tv-container">
|
|
||||||
<div>NO SIGNAL</div>
|
|
||||||
</div>
|
|
||||||
<div id="overlay"><span></span></div>
|
|
||||||
|
|
||||||
<div id="twitch-embed"></div>
|
|
||||||
|
|
||||||
<!-- Load the Twitch embed script -->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
var player;
|
|
||||||
var playerData;
|
|
||||||
$(document).ready(function() {
|
|
||||||
$.post("https://ptelevision/pageLoaded", JSON.stringify({}))
|
|
||||||
})
|
|
||||||
|
|
||||||
function GetURLID(link) {
|
|
||||||
if (link == null) return;
|
|
||||||
let url = link.toString();
|
|
||||||
var regExp = /^.*(youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
|
|
||||||
var match = url.match(regExp);
|
|
||||||
if (match && match[2].length == 11) {
|
|
||||||
return {type: "youtube", id: match[2]};
|
|
||||||
}
|
|
||||||
else if (url.split("twitch.tv/").length > 1) {
|
|
||||||
|
|
||||||
return {type: "twitch", id: url.split("twitch.tv/")[1]};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function ChannelDisplay(channel, channelFound) {
|
|
||||||
if (channel) {
|
|
||||||
var temp = 'CH<span style="font-size: 18pt !important;"> </span>'
|
|
||||||
if (channel > 9) {
|
|
||||||
temp += channel
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
temp += ("0" + channel)
|
|
||||||
}
|
|
||||||
$("#overlay span").show()
|
|
||||||
$("#overlay span").html(temp)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$("#overlay span").show()
|
|
||||||
$("#overlay span").html("")
|
|
||||||
}
|
|
||||||
if (channelFound) {
|
|
||||||
$("#tv-container").hide()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$("#tv-container").show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function SetVideo(video_data) {
|
|
||||||
var url = video_data.url;
|
|
||||||
var channel = video_data.channel;
|
|
||||||
var data = GetURLID(url)
|
|
||||||
|
|
||||||
playerData = data
|
|
||||||
if (player) {
|
|
||||||
player.destroy()
|
|
||||||
player = null;
|
|
||||||
}
|
|
||||||
if (data) {
|
|
||||||
if (data.type == "youtube") {
|
|
||||||
player = new YT.Player('twitch-embed', {
|
|
||||||
height: '100%',
|
|
||||||
width: '100%',
|
|
||||||
videoId: data.id,
|
|
||||||
playerVars: {
|
|
||||||
'playsinline': 1,
|
|
||||||
},
|
|
||||||
events: {
|
|
||||||
'onReady': function(event) {
|
|
||||||
event.target.playVideo();
|
|
||||||
event.target.seekTo(video_data.time)
|
|
||||||
},
|
|
||||||
'onStateChange': function(event) {
|
|
||||||
if (event.data == YT.PlayerState.PLAYING) {
|
|
||||||
event.target.unMute();
|
|
||||||
}
|
|
||||||
else if (event.data == YT.PlayerState.PAUSED) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (data.type == "twitch") {
|
|
||||||
player = new Twitch.Player("twitch-embed", {
|
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
channel: data.id,
|
|
||||||
volume: 1.0
|
|
||||||
});
|
|
||||||
player.addEventListener(Twitch.Embed.VIDEO_READY, function() {
|
|
||||||
player.setMuted(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$("#overlay span").hide()
|
|
||||||
$("#tv-container").hide()
|
|
||||||
}
|
|
||||||
if (channel) {
|
|
||||||
ChannelDisplay(channel, url)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function SetVolume(volume) {
|
|
||||||
|
|
||||||
if (player && playerData && player.setVolume) {
|
|
||||||
if (playerData.type == "twitch") {
|
|
||||||
player.setMuted(false);
|
|
||||||
player.setVolume(volume / 100.0);
|
|
||||||
}
|
|
||||||
else if (playerData.type == "youtube") {
|
|
||||||
player.setVolume(volume);
|
|
||||||
player.unMute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function ShowNotification(channel, data) {
|
|
||||||
$("#tv-container").addClass("notify")
|
|
||||||
$("#tv-container div").addClass("notify")
|
|
||||||
var display = $('#tv-container').is(':visible')
|
|
||||||
$('#tv-container').show()
|
|
||||||
$("#tv-container div").html("Channel #" + channel + (data ? (" ("+data.name+")") : "") + " is now " + (data ? "live!" : "offline."))
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
$("#tv-container").removeClass("notify")
|
|
||||||
$("#tv-container div").removeClass("notify")
|
|
||||||
$("#tv-container div").html("NO SIGNAL")
|
|
||||||
if (!display) {
|
|
||||||
$('#tv-container').hide()
|
|
||||||
}
|
|
||||||
}, 3500)
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener("message", function(ev) {
|
|
||||||
if (ev.data.setVideo) {
|
|
||||||
SetVideo(ev.data.data)
|
|
||||||
}
|
|
||||||
else if (ev.data.setVolume) {
|
|
||||||
SetVolume(ev.data.data)
|
|
||||||
}
|
|
||||||
else if (ev.data.showNotification) {
|
|
||||||
ShowNotification(ev.data.channel, ev.data.data)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
$(document).ready(function() {
|
|
||||||
ChannelDisplay()
|
|
||||||
})
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
@font-face {
|
|
||||||
font-family: 'BodyCam';
|
|
||||||
src: url('VCR_OSD_MONO_1.001.ttf') format('truetype') /* Safari, Android, iOS */
|
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
|
||||||
font-family: BodyCam;
|
|
||||||
color:white;
|
|
||||||
}
|
|
||||||
|
|
||||||
#twitch-embed {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
overflow: hidden;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#overlay {
|
|
||||||
position: absolute;
|
|
||||||
top: 10px;
|
|
||||||
right: 10px;
|
|
||||||
z-index: 1;
|
|
||||||
font-size: 48pt !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#background {
|
|
||||||
display: flex;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
min-height: 100%;
|
|
||||||
background-color: rgb(42, 42, 42);
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
z-index: -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tv-container {
|
|
||||||
display: flex;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
min-height: 100%;
|
|
||||||
background-color: transparent;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tv-container.notify {
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
min-height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tv-container > div {
|
|
||||||
font-size: 24pt;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tv-container > div.notify {
|
|
||||||
font-size: 24pt;
|
|
||||||
user-select: none;
|
|
||||||
width: -webkit-fill-available;
|
|
||||||
text-align: center;
|
|
||||||
padding: 25px;
|
|
||||||
background-color: rgba(0, 0, 0, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* width */
|
|
||||||
::-webkit-scrollbar {
|
|
||||||
width: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Track */
|
|
||||||
::-webkit-scrollbar-track {
|
|
||||||
background: rgb(42, 42, 42);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle */
|
|
||||||
::-webkit-scrollbar-thumb {
|
|
||||||
background: rgb(66, 66, 66);
|
|
||||||
}
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
local Locations = {}
|
|
||||||
|
|
||||||
function SetTelevision(coords, key, value, update)
|
|
||||||
local index, data = GetTelevision(coords)
|
|
||||||
if (index ~= nil) then
|
|
||||||
if (Televisions[index] == nil) then
|
|
||||||
Televisions[index] = {}
|
|
||||||
end
|
|
||||||
Televisions[index][key] = value
|
|
||||||
else
|
|
||||||
index = os.time()
|
|
||||||
while Televisions[index] do
|
|
||||||
index = index + 1
|
|
||||||
Citizen.Wait(0)
|
|
||||||
end
|
|
||||||
if (Televisions[index] == nil) then
|
|
||||||
Televisions[index] = {}
|
|
||||||
end
|
|
||||||
Televisions[index][key] = value
|
|
||||||
end
|
|
||||||
Televisions[index].coords = coords
|
|
||||||
if (update) then
|
|
||||||
TriggerClientEvent("ptelevision:event", -1, Televisions, index, key, value)
|
|
||||||
end
|
|
||||||
return index
|
|
||||||
end
|
|
||||||
|
|
||||||
function SetChannel(source, data)
|
|
||||||
if data then
|
|
||||||
for k,v in pairs(Channels) do
|
|
||||||
if (Channels[k].source == source) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local index = 1
|
|
||||||
while Channels[index] do
|
|
||||||
index = index + 1
|
|
||||||
Citizen.Wait(0)
|
|
||||||
end
|
|
||||||
Channels[index] = data
|
|
||||||
Channels[index].source = source
|
|
||||||
TriggerClientEvent("ptelevision:broadcast", -1, Channels, index)
|
|
||||||
return
|
|
||||||
else
|
|
||||||
for k,v in pairs(Channels) do
|
|
||||||
if (Channels[k].source == source) then
|
|
||||||
Channels[k] = nil
|
|
||||||
TriggerClientEvent("ptelevision:broadcast", -1, Channels, k)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
RegisterNetEvent("ptelevision:event", function(data, key, value)
|
|
||||||
local _source = source
|
|
||||||
Config.Events.ScreenInteract(_source, data, key, value, function()
|
|
||||||
SetTelevision(data.coords, key, value, true)
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
RegisterNetEvent("ptelevision:broadcast", function(data)
|
|
||||||
local _source = source
|
|
||||||
Config.Events.Broadcast(_source, data, function()
|
|
||||||
SetChannel(_source, data)
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
RegisterNetEvent("ptelevision:requestUpdate", function()
|
|
||||||
local _source = source
|
|
||||||
TriggerClientEvent("ptelevision:requestUpdate", _source, {
|
|
||||||
Televisions = Televisions,
|
|
||||||
Channels = Channels
|
|
||||||
})
|
|
||||||
end)
|
|
||||||
|
|
||||||
AddEventHandler('onResourceStop', function(name)
|
|
||||||
if name == GetCurrentResourceName() then
|
|
||||||
for i=1, #Locations do
|
|
||||||
local data = Locations[i]
|
|
||||||
if (DoesEntityExist(Locations[i].obj)) then
|
|
||||||
DeleteEntity(Locations[i].obj)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
AddEventHandler('playerDropped', function(reason)
|
|
||||||
local _source = source
|
|
||||||
SetChannel(_source, nil)
|
|
||||||
end)
|
|
||||||
|
|
||||||
Citizen.CreateThread(function()
|
|
||||||
Citizen.Wait(1000)
|
|
||||||
local locations = Config.Locations
|
|
||||||
for i=1, #locations do
|
|
||||||
local data = locations[i]
|
|
||||||
local obj = CreateObject(data.Model, data.Position.x, data.Position.y, data.Position.z, true)
|
|
||||||
SetEntityHeading(obj, data.Position.w)
|
|
||||||
table.insert(Locations, {data = data, obj = obj})
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
Televisions = {}
|
|
||||||
|
|
||||||
function DumpArray(obj, seen)
|
|
||||||
if type(obj) ~= 'table' then return obj end
|
|
||||||
if seen and seen[obj] then return seen[obj] end
|
|
||||||
local s = seen or {}
|
|
||||||
local res = setmetatable({}, getmetatable(obj))
|
|
||||||
s[obj] = res
|
|
||||||
for k, v in pairs(obj) do res[DumpArray(k, s)] = DumpArray(v, s) end
|
|
||||||
return res
|
|
||||||
end
|
|
||||||
|
|
||||||
function GetTelevision(coords)
|
|
||||||
for k,v in pairs(Televisions) do
|
|
||||||
if #(vec3(v.coords) - vec3(coords)) < 0.01 then
|
|
||||||
return k, v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Channels = DumpArray(Config.Channels)
|
|
||||||
Reference in New Issue
Block a user