mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 21:53:46 +03:00
199 lines
6.2 KiB
Lua
199 lines
6.2 KiB
Lua
|
|
--[[
|
||
|
|
| This file was obtained through the combined efforts
|
||
|
|
| of Madbluntz & Plymouth Antiquarian Society.
|
||
|
|
|
|
||
|
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||
|
|
| Maloy, DrPepper10 @ RIP, Atle!
|
||
|
|
|
|
||
|
|
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||
|
|
--]]
|
||
|
|
|
||
|
|
ix.phone = ix.phone or {}
|
||
|
|
ix.phone.switch = ix.phone.switch or {}
|
||
|
|
|
||
|
|
-- a volatile table for caching ongoing connections
|
||
|
|
ix.phone.switch.connections = ix.phone.switch.connections or {}
|
||
|
|
|
||
|
|
function ix.phone.switch:ConnectionValid(connID)
|
||
|
|
if (self.connections[connID] == false) then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
|
||
|
|
return istable(self.connections[connID])
|
||
|
|
end
|
||
|
|
|
||
|
|
function ix.phone.switch:buildNewConnectionNode(connID, extID, extNum)
|
||
|
|
-- helper function to create source requests for connections
|
||
|
|
-- constructs a table that can be used by ix.phone.switch:connect()
|
||
|
|
if (!self:ConnectionValid(connID)) then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
if (!self.connections[connID].nodes) then
|
||
|
|
self.connections[connID].nodes = {}
|
||
|
|
end
|
||
|
|
|
||
|
|
local nodeID = #self.connections[connID].nodes + 1
|
||
|
|
self.connections[connID].nodes[nodeID] = {}
|
||
|
|
self.connections[connID].nodes[nodeID]["exchange"] = extID
|
||
|
|
self.connections[connID].nodes[nodeID]["extension"] = extNum
|
||
|
|
end
|
||
|
|
|
||
|
|
function ix.phone.switch:buildNewConnection()
|
||
|
|
-- helper function to that creates a new connection
|
||
|
|
|
||
|
|
-- attempt to reuse a freshly terminated connection
|
||
|
|
for id, conn in ipairs(self.connections) do
|
||
|
|
if (conn == false) then
|
||
|
|
self.connections[id] = {}
|
||
|
|
return id
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
-- no terminated connections
|
||
|
|
connectionID = #self.connections + 1
|
||
|
|
self.connections[connectionID] = {}
|
||
|
|
|
||
|
|
return connectionID
|
||
|
|
end
|
||
|
|
|
||
|
|
function ix.phone.switch:Disconnect(connID, noNotify)
|
||
|
|
-- disconnects provided connection at connID
|
||
|
|
-- if notify is set, then it wont notify listeners that the connection is terminated
|
||
|
|
if (!istable(self.connections[connID])) then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
local _nodes = self.connections[connID].nodes
|
||
|
|
for _, node in ipairs(_nodes) do
|
||
|
|
local recievers = self:getReceivers(node.exchange, node.extension)
|
||
|
|
|
||
|
|
if (!istable(recievers) or table.Count(recievers) < 1) then
|
||
|
|
continue
|
||
|
|
end
|
||
|
|
|
||
|
|
for _, reciever in ipairs(recievers) do
|
||
|
|
local ent = self.endpoints:GetEndpoint(reciever.endID)
|
||
|
|
if (ent and ent.HangUp and ent.isRinging) then
|
||
|
|
ent:HangUp()
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local listeners = self:getListenersFromRecvs(recievers)
|
||
|
|
|
||
|
|
if (!listeners or table.Count(listeners) < 1) then
|
||
|
|
continue
|
||
|
|
end
|
||
|
|
|
||
|
|
for _, listener in ipairs(listeners) do
|
||
|
|
self:DisconnectClient(listener)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
self.connections[connID] = false
|
||
|
|
end
|
||
|
|
|
||
|
|
-- disconnects the client's status and notifies them of said status change
|
||
|
|
-- IMPORTANT: Make sure you destroy the connection too!
|
||
|
|
function ix.phone.switch:DisconnectClient(client)
|
||
|
|
if (!client or !IsValid(client)) then
|
||
|
|
return ErrorNoHaltWithStack("Attempt to disconnect invalid client "..tostring(client))
|
||
|
|
end
|
||
|
|
|
||
|
|
local character = client:GetCharacter()
|
||
|
|
if (!istable(character)) then
|
||
|
|
return ErrorNoHaltWithStack("Attempt to disconnect client with invalid character "..tostring(character))
|
||
|
|
end
|
||
|
|
|
||
|
|
self:ResetCharVars(character)
|
||
|
|
self:NotifyStatusChange(client, false, false)
|
||
|
|
end
|
||
|
|
|
||
|
|
function ix.phone.switch:NotifyStatusChange(client, bCallActive, bInCall)
|
||
|
|
net.Start("ixConnectedCallStatusChange")
|
||
|
|
net.WriteBool(bCallActive)
|
||
|
|
net.WriteBool(bInCall)
|
||
|
|
net.Send(client)
|
||
|
|
end
|
||
|
|
|
||
|
|
function ix.phone.switch:NotifyAllListenersOfStatusChange(endID, bCallActive, bInCall)
|
||
|
|
local listeners = self.endpoints:GetListeners(endID)
|
||
|
|
if (!listeners or table.Count(listeners) < 1) then
|
||
|
|
return -- no need to do anything; no listeners
|
||
|
|
end
|
||
|
|
|
||
|
|
for _, listener in ipairs(listeners) do
|
||
|
|
-- notify all listeners of their call status change
|
||
|
|
self:NotifyStatusChange(listener, bCallActive, bInCall)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function ix.phone.switch:getListenersFromRecvs(recievers)
|
||
|
|
local listeners = {}
|
||
|
|
for k, recv in ipairs(recievers) do
|
||
|
|
-- there will almost always be one reciever.. but treating this as a list in case we ever do 'conference calls'
|
||
|
|
local _listeners = self.endpoints:GetListeners(recv.endID)
|
||
|
|
if (istable(_listeners)) then
|
||
|
|
for _, listener in ipairs(_listeners) do
|
||
|
|
listeners[table.Count(listeners) + 1] = listener
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return listeners
|
||
|
|
end
|
||
|
|
|
||
|
|
function ix.phone.switch:getReceivers(extID, extNum)
|
||
|
|
local conn = self:GetActiveConnection(extID, extNum)
|
||
|
|
if (!istable(conn)) then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
return self:getSourceRecieversFromConnection(conn.targetConnID,
|
||
|
|
conn.sourceNodeID)
|
||
|
|
end
|
||
|
|
|
||
|
|
function ix.phone.switch:GetListeners(extID, extNum)
|
||
|
|
return self:getListenersFromRecvs(self:getReceivers(extID, extNum))
|
||
|
|
end
|
||
|
|
|
||
|
|
function ix.phone.switch:GetReceivers(extID, extNum)
|
||
|
|
local conn = self:GetActiveConnection(extID, extNum)
|
||
|
|
if (!istable(conn)) then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
return self:getSourceRecieversFromConnection(conn.targetConnID,
|
||
|
|
conn.sourceNodeID)
|
||
|
|
end
|
||
|
|
|
||
|
|
-- returns the active connection in the form of {"targetConnID", "sourceNodeID"} if one is present
|
||
|
|
function ix.phone.switch:GetActiveConnection(extID, extNum)
|
||
|
|
for connID, conn in ipairs(self.connections) do
|
||
|
|
if (conn == false) then
|
||
|
|
continue
|
||
|
|
end
|
||
|
|
|
||
|
|
for nodeID, node in ipairs(conn.nodes) do
|
||
|
|
if (node["exchange"] == extID and node["extension"] == extNum) then
|
||
|
|
-- source is present in this connection
|
||
|
|
return {targetConnID = connID, sourceNodeID = nodeID}
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
-- returns the actively connected (except for the source) recievers for a given connection
|
||
|
|
function ix.phone.switch:getSourceRecieversFromConnection(connID, sourceNodeID)
|
||
|
|
local res = {}
|
||
|
|
for nodeID, node in ipairs(self.connections[connID].nodes) do
|
||
|
|
if (nodeID != sourceNodeID) then
|
||
|
|
-- we want to return this as it exists in the exchange as that will give us
|
||
|
|
-- extra details the node tree does not contain such as name and endID
|
||
|
|
res[#res + 1] = self:GetDest(node["exchange"], node["extension"])
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return res
|
||
|
|
end
|