local initalized = false
local CollectionService = game:GetService("CollectionService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ChatService = game:GetService("Chat")
-- Coding makes me wanna LOVE EVERYONE. I know what I'm doing ALL THE TIME.
local API = {}
API.Phones = {}
API.InteractionPoint = ReplicatedStorage.Phone
API.UIStorage = ReplicatedStorage.PhoneGUIStorage
API.EmergencyNotificationSystem = ReplicatedStorage.PhoneAlert
type PhoneEntry = {
Ringer: Sound,
ClickDetector: ClickDetector,
Instance: Instance,
["Phone Code"]: string,
["Network"] : string,
CurrentPlayer: Player?,
LineOccupied: boolean?,
-- Functions
Ring: (self: PhoneEntry, State: boolean?) -> (),
GetCode: (self: PhoneEntry) -> string,
Call: (self: PhoneEntry) -> (),
DisplayMessage: (self: PhoneEntry, Message: string, Color: Enum.ChatColor?) -
> (),
PlaySound: (self: PhoneEntry, SoundName: string, RemoveAfterPlayBack:
boolean?) -> (),
StopSound: (self: PhoneEntry, SoundName: string, RemoveAfterPlayBack:
boolean?) -> (),
OnClick: (self: PhoneEntry, ClickingPlayer: Player) -> (),
}
type Session = {
["Network"] : string,
["Connections"] : {PhoneEntry?},
["PlayerChatEvents"] : {RBXScriptSignal?},
["PhoneEvents"] : {RBXScriptSignal?},
-- Functions
Establish: (self: Session, Sender: PhoneEntry, Reciever: PhoneEntry) -> ();
Chatted: (self: Session, Sender: Player, Message: string) -> ();
SessionDisconnect: (self: Session) -> ();
OnClick: (self: Session, ClickingPlayer: Player) -> ();
Destroy: (self: Session) -> ();
IsPlayerWithinSession: (self: Session, Player: Player) -> boolean;
}
local PhoneEntryMT = {} :: {
__index: PhoneEntry
}
PhoneEntryMT.__index = PhoneEntryMT
local Session = {} :: Session
local Sessions: {Session} = {}
function Session:Establish(Sender: PhoneEntry, Reciever: PhoneEntry)
local self: Session = self
self["Connections"] = {}
self["PhoneEvents"] = {}
self["PlayerChatEvents"] = {}
-- THIS WHOLE FUNCTION WILL BE CLEANED.
table.insert(self["PhoneEvents"],
Sender.ClickDetector.MouseClick:Connect(
function(Clicker)
self:OnClick(Clicker)
end
)
)
table.insert(self["PhoneEvents"],
Reciever.ClickDetector.MouseClick:Connect(
function(Clicker)
self:OnClick(Clicker)
end
)
)
table.insert(self["Connections"], Sender)
table.insert(self["Connections"], Reciever)
local ChatEvents: {RBXScriptConnection} = {}
if Sender.CurrentPlayer then
local ChatEvent: RBXScriptConnection =
Sender.CurrentPlayer.Chatted:Connect(function(message: string, recipient: Player)
Session:Chatted(message, Reciever)
end)
table.insert(ChatEvents, ChatEvent)
end
if Reciever.CurrentPlayer then
local ChatEvent: RBXScriptConnection =
Reciever.CurrentPlayer.Chatted:Connect(function(message: string, recipient: Player)
Session:Chatted(message, Sender)
end)
table.insert(ChatEvents, ChatEvent)
end
self["PlayerChatEvents"] = ChatEvents
table.insert(Sessions, self)
end
function Session:IsPlayerWithinSession(Player: Player): boolean
local self: Session = self
for _, Phone: PhoneEntry in ipairs(self["Connections"]) do
if Phone.CurrentPlayer and Phone.CurrentPlayer == Player then
return true
end
end
return false
end
function Session:SessionDisconnect()
Sessions[self] = nil
local self: Session = self
for index, Phone: PhoneEntry in ipairs(self["Connections"]) do
Phone:DisplayMessage("Call Ended")
Phone:PlaySound("Disconnect", true)
Phone.LineOccupied = false
Phone.CurrentPlayer = nil
end
self:Destroy()
end
function Session:OnClick(ClickingPlayer: Player)
local self: Session = self
if self:IsPlayerWithinSession(ClickingPlayer) then
self:SessionDisconnect()
end
end
function Session:Destroy()
local self: Session = self
for _, Connection in ipairs(self["PlayerChatEvents"]) do
Connection:Disconnect()
end
for _, Connection in ipairs(self["PhoneEvents"]) do
Connection:Disconnect()
end
setmetatable(self, nil)
end
function Session:Chatted(Message: string, SendTo: PhoneEntry)
local self: Session = self
SendTo:DisplayMessage(Message)
end
function PhoneEntryMT:DisplayMessage(Message: string, Color: Enum.ChatColor?)
local self: PhoneEntry = self
ChatService:Chat(self.Instance, Message, Color)
end
function PhoneEntryMT:Accept()
self.CurrentCallEntry = self.IncomingCallEntry
end
function PhoneEntryMT:Ring(State: boolean?)
if State then
self.Ringer:Play()
else
self.Ringer:Stop()
end
end
function PhoneEntryMT:PlaySound(SoundName: string, RemoveAfterPlayBack: boolean?)
local self: PhoneEntry = self
local SoundEntry = script:WaitForChild("Sounds", 5):FindFirstChild(SoundName)
if SoundEntry then
if self.Instance:FindFirstChild(SoundEntry.Name) then
self.Instance:FindFirstChild(SoundEntry.Name):Destroy()
end
local ClonedSoundEntry: Sound = SoundEntry:Clone()
ClonedSoundEntry.Parent = self.Instance
ClonedSoundEntry.Ended:Once(function()
if RemoveAfterPlayBack then
ClonedSoundEntry:Destroy()
end
end)
ClonedSoundEntry:Play()
end
end
function PhoneEntryMT:StopSound(SoundName)
local self: PhoneEntry = self
if self.Instance:FindFirstChild(SoundName) then
self.Instance:FindFirstChild(SoundName):Destroy()
end
end
function PhoneEntryMT:GetCode()
return self["Phone Code"]
end
function PhoneEntryMT:OnClick(ClickingPlayer: Player)
local self: PhoneEntry = self
if self.CurrentPlayer or self.Ringer.IsPlaying then
return
end
API:ConstructInterface(ClickingPlayer, self)
end
function PhoneEntryMT:Call(TargetNumber: string)
print(`[CALL REQUEST SENT] :: {self.Network}-{self:GetCode()} CALL REQUESTED
FOR {self.Network}-{TargetNumber}`)
API:EstablishConnection(self, TargetNumber)
end
local function EstablishTableEntry(Phone: Instance): PhoneEntry
local entry = {
Ringer = Phone:FindFirstChildWhichIsA("Sound") :: Sound,
ClickDetector = Phone:FindFirstChildWhichIsA("ClickDetector") ::
ClickDetector,
["Phone Code"] = Phone:GetAttribute("PhoneCode") :: string,
["Network"] = Phone:GetAttribute("NetworkName") :: string,
Instance = Phone,
LineOccupied = false,
}
return setmetatable(entry, PhoneEntryMT) :: PhoneEntry
end
function API:FindPhoneByNumber(Network: string, Number: string): PhoneEntry?
for _, Phone: PhoneEntry in ipairs(API.Phones[Network]) do
if tostring(Phone["Phone Code"]) == tostring(Number) then
return Phone
end
end
return false
end
local function onAcceptedCall(Sender, Reciever)
Session:Establish(Sender, Reciever)
end
function API:ConstructInterface(Player: Player, PhoneEntry: PhoneEntry)
local UI = API.UIStorage.PhoneSendGui:Clone()
if Player.PlayerGui:FindFirstChild(UI.Name) then
Player.PlayerGui:FindFirstChild(UI.Name):Destroy()
end
UI:FindFirstChild("PhoneObject", true).Value = PhoneEntry.Instance
UI.Parent = Player.PlayerGui
UI.PhoneUIHandler.Enabled = true
end
function API:EstablishConnection(Sender: PhoneEntry, TargetNumber: string)
-- WILL BE CLEANED
local TargetPhone: PhoneEntry = API:FindPhoneByNumber(Sender.Network,
TargetNumber)
if TargetPhone then
local wasAccepted = false
print(TargetPhone)
if TargetPhone.CurrentPlayer or TargetPhone.LineOccupied then
Sender:PlaySound("Busy", true)
Sender:DisplayMessage("The Phone you have Dialed is currently
Busy. Try again later.")
Sender.LineOccupied = false
return
end
Sender.LineOccupied = true
TargetPhone.LineOccupied = true
local SenderGui =
Sender.CurrentPlayer.PlayerGui:FindFirstChild("PhoneSendGui")
if SenderGui then
SenderGui:Destroy()
end
Sender:PlaySound("Dialing")
Sender:DisplayMessage(`Dialing...`, Enum.ChatColor.Green)
print(`[CALL REQUEST SENT] :: {Sender.Network}-{Sender:GetCode()}
RINGING {Sender.Network}-{TargetNumber}`)
TargetPhone:Ring(true)
local AcceptCallEvent =
TargetPhone.ClickDetector.MouseClick:Once(function(playerWhoClicked: Player)
TargetPhone:Ring(false)
Sender:DisplayMessage(`Call Accepted`, Enum.ChatColor.Green)
TargetPhone.CurrentPlayer = playerWhoClicked
Sender:StopSound("Dialing")
Sender.LineOccupied = true
TargetPhone.LineOccupied = true
onAcceptedCall(Sender, TargetPhone)
wasAccepted = true
end)
task.delay(5, function()
if wasAccepted then
return
end
if TargetPhone.CurrentPlayer then
return
else
AcceptCallEvent:Disconnect()
TargetPhone:Ring(false)
Sender:StopSound("Dialing")
Sender:PlaySound("Disconnect", true)
Sender:DisplayMessage(`Call Timed Out`, Enum.ChatColor.Red)
Sender.CurrentPlayer = nil
Sender.LineOccupied = false
TargetPhone.LineOccupied = false
return
end
end)
TargetPhone:DisplayMessage(`Call From... {Sender:GetCode()}`)
end
end
local function OnAPIRecieve(Player, Action: string, SentContent: {string | number |
Instance})
if Action == "CALL" then
local Caller: PhoneEntry? = API:FindPhoneByNumber(
tostring(SentContent["Network"]),
tostring(SentContent["PhoneCode"])
)
if ReplicatedStorage.LANOutage.Value then
Caller:PlaySound("Busy", true)
Caller:DisplayMessage("All Circuits are Busy.")
return
end
Caller.CurrentPlayer = Player
Caller:Call(tostring(SentContent["TargetPhoneNumber"]))
-- API:EstablishConnection(Caller,
tostring(SentContent["TargetPhoneNumber"]))
end
end
function API:EmergencyBroadcast(Network: string | "ALL", Message: string)
local NetworkSelection = ""
if Network == "ALL" then
NetworkSelection = API.Phones
else
if not API.Phones[Network] then
warn("NETWORK NOT FOUND.")
return
end
NetworkSelection = API.Phones[Network]
end
for _, PhoneNetwork: {PhoneEntry} in NetworkSelection do
for _, Phone: PhoneEntry in PhoneNetwork do
Phone:PlaySound("Emergency", true)
Phone:DisplayMessage(`EMERGENCY BROADCAST:\n\n\
n{tostring(Message)}`)
end
end
end
function API:Initalize()
local PhoneCollection = CollectionService:GetTagged("Phone")
for _, Phone: Model in ipairs(PhoneCollection) do
local hasRequiredAttributes = (Phone:GetAttribute("NetworkName") and
Phone:GetAttribute("PhoneCode"))
if hasRequiredAttributes then
if not API.Phones[Phone:GetAttribute("NetworkName")] then
API.Phones[Phone:GetAttribute("NetworkName")] = {}
end
local PhoneEntry: PhoneEntry = EstablishTableEntry(Phone);
if not script:GetAttribute("loaded") then
PhoneEntry.ClickDetector.MouseClick:Connect(function(playerWhoClicked:
Player)
PhoneEntry:OnClick(playerWhoClicked)
end)
end
table.insert(API.Phones[Phone:GetAttribute("NetworkName")],
PhoneEntry)
end
end
if not script:GetAttribute("loaded") then
API.InteractionPoint.OnServerEvent:Connect(OnAPIRecieve)
API.EmergencyNotificationSystem.Event:Connect(function(Network: string
| "ALL", Message: string)
API:EmergencyBroadcast(Network, Message)
end)
end
script:SetAttribute("loaded", true)
print(API.Phones)
end
print("hi")
API:Initalize()
return API