local HttpService = game:GetService("HttpService") local Players = game:GetService("Players") local UserInputService = game:GetService("UserInputService") local TweenService = game:GetService("TweenService") local RunService = game:GetService("RunService") local CoreGui = game:GetService("CoreGui") local LocalPlayer = Players.LocalPlayer local request = syn and syn.request or http_request or request local BASE_URL = "https://roblox-chat-4ens.onrender.com" local SoundIds = { Msg = "rbxassetid://5797533311", Open = "rbxassetid://6895079685", Click = "rbxassetid://6895079853" } local StickerIds = { "rbxassetid://11432924199", "rbxassetid://11432924681", "rbxassetid://14643093229", "rbxassetid://10906232386", "rbxassetid://9072382902", "rbxassetid://14394625232", "rbxassetid://12506240217", "rbxassetid://7335532598", "rbxassetid://12799984903" } local Colors = { Background = Color3.fromRGB(25, 25, 30), Accent = Color3.fromRGB(0, 120, 255), Text = Color3.fromRGB(240, 240, 240), GradientStart = Color3.fromRGB(35, 35, 40), GradientEnd = Color3.fromRGB(20, 20, 25), InputBackground = Color3.fromRGB(40, 40, 45), AvatarBackground = Color3.fromRGB(50, 50, 60), CloseButton = Color3.fromRGB(200, 80, 80), IconColor = Color3.fromRGB(150, 150, 160), NotificationRed = Color3.fromRGB(255, 60, 60), FrameBorder = Color3.fromRGB(60, 60, 70) } local existingGui = CoreGui:FindFirstChild("GC_V16") if existingGui then existingGui:Destroy() end local ScreenGui = Instance.new("ScreenGui") ScreenGui.Name = "GC_V16" ScreenGui.ResetOnSpawn = false ScreenGui.Parent = CoreGui local MainShadow = Instance.new("ImageLabel") MainShadow.Name = "MainShadow" MainShadow.Parent = ScreenGui MainShadow.Size = UDim2.new(0, 440, 0, 350) MainShadow.Position = UDim2.new(0.5, 0, 0.5, 0) MainShadow.AnchorPoint = Vector2.new(0.5, 0.5) MainShadow.BackgroundTransparency = 1 MainShadow.Image = "rbxassetid://6015897843" MainShadow.ImageTransparency = 0.4 MainShadow.ScaleType = Enum.ScaleType.Slice MainShadow.SliceCenter = Rect.new(47, 47, 450, 450) local MainFrame = Instance.new("Frame") MainFrame.Name = "MainFrame" MainFrame.Parent = MainShadow MainFrame.Size = UDim2.new(0, 400, 0, 310) MainFrame.Position = UDim2.new(0.5, -200, 0.5, -155) MainFrame.BackgroundColor3 = Colors.Background local MainGradient = Instance.new("UIGradient") MainGradient.Parent = MainFrame MainGradient.Rotation = 45 MainGradient.Color = ColorSequence.new({ ColorSequenceKeypoint.new(0, Colors.GradientStart), ColorSequenceKeypoint.new(1, Colors.GradientEnd) }) local MainCorner = Instance.new("UICorner") MainCorner.Parent = MainFrame MainCorner.CornerRadius = UDim.new(0, 14) local MinimizeButton = Instance.new("ImageButton") MinimizeButton.Name = "MinimizeButton" MinimizeButton.Parent = ScreenGui MinimizeButton.Size = UDim2.new(0, 45, 0, 45) MinimizeButton.Position = UDim2.new(0.9, -10, 0.85, -10) MinimizeButton.BackgroundColor3 = Colors.Background MinimizeButton.Image = "rbxassetid://3926305904" MinimizeButton.Visible = false local MinimizeCorner = Instance.new("UICorner") MinimizeCorner.Parent = MinimizeButton MinimizeCorner.CornerRadius = UDim.new(1, 0) local MinimizeStroke = Instance.new("UIStroke") MinimizeStroke.Parent = MinimizeButton MinimizeStroke.Color = Colors.Accent MinimizeStroke.Thickness = 2 local NotificationBadge = Instance.new("Frame") NotificationBadge.Name = "NotificationBadge" NotificationBadge.Parent = MinimizeButton NotificationBadge.Size = UDim2.new(0, 20, 0, 20) NotificationBadge.Position = UDim2.new(1, -12, 0, -5) NotificationBadge.BackgroundColor3 = Colors.NotificationRed NotificationBadge.Visible = false local NotificationCorner = Instance.new("UICorner") NotificationCorner.Parent = NotificationBadge NotificationCorner.CornerRadius = UDim.new(1, 0) local NotificationLabel = Instance.new("TextLabel") NotificationLabel.Name = "NotificationLabel" NotificationLabel.Parent = NotificationBadge NotificationLabel.Size = UDim2.new(1, 0, 1, 0) NotificationLabel.BackgroundTransparency = 1 NotificationLabel.TextColor3 = Color3.new(1, 1, 1) NotificationLabel.Text = "0" NotificationLabel.Font = Enum.Font.GothamBold NotificationLabel.TextSize = 12 local TitleBar = Instance.new("Frame") TitleBar.Name = "TitleBar" TitleBar.Parent = MainFrame TitleBar.Size = UDim2.new(1, 0, 0, 40) TitleBar.BackgroundTransparency = 1 local TitleLabel = Instance.new("TextLabel") TitleLabel.Name = "TitleLabel" TitleLabel.Parent = TitleBar TitleLabel.Text = "全局聊天 V16.3" TitleLabel.RichText = true TitleLabel.Size = UDim2.new(0, 200, 1, 0) TitleLabel.Position = UDim2.new(0, 15, 0, 0) TitleLabel.BackgroundTransparency = 1 TitleLabel.TextColor3 = Colors.Text TitleLabel.Font = Enum.Font.GothamBlack TitleLabel.TextSize = 16 TitleLabel.TextXAlignment = Enum.TextXAlignment.Left local CloseButton = Instance.new("ImageButton") CloseButton.Name = "CloseButton" CloseButton.Parent = TitleBar CloseButton.Image = "rbxassetid://7743878857" CloseButton.Size = UDim2.new(0, 20, 0, 20) CloseButton.Position = UDim2.new(1, -35, 0.5, -10) CloseButton.BackgroundTransparency = 1 CloseButton.ImageColor3 = Colors.CloseButton local PlayersButton = Instance.new("ImageButton") PlayersButton.Name = "PlayersButton" PlayersButton.Parent = TitleBar PlayersButton.Visible = false PlayersButton.Image = "rbxassetid://7734053495" PlayersButton.Size = UDim2.new(0, 20, 0, 20) PlayersButton.Position = UDim2.new(1, -65, 0.5, -10) PlayersButton.BackgroundTransparency = 1 PlayersButton.ImageColor3 = Colors.IconColor local ChatContainer = Instance.new("Frame") ChatContainer.Name = "ChatContainer" ChatContainer.Parent = MainFrame ChatContainer.Size = UDim2.new(1, -20, 1, -110) ChatContainer.Position = UDim2.new(0, 10, 0, 50) ChatContainer.BackgroundTransparency = 1 local ChatScrollingFrame = Instance.new("ScrollingFrame") ChatScrollingFrame.Name = "ChatScrollingFrame" ChatScrollingFrame.Parent = ChatContainer ChatScrollingFrame.Size = UDim2.new(1, 0, 1, 0) ChatScrollingFrame.BackgroundTransparency = 1 ChatScrollingFrame.ScrollBarThickness = 4 ChatScrollingFrame.CanvasSize = UDim2.new(0, 0, 0, 0) local ChatListLayout = Instance.new("UIListLayout") ChatListLayout.Parent = ChatScrollingFrame ChatListLayout.Padding = UDim.new(0, 8) ChatListLayout.SortOrder = Enum.SortOrder.LayoutOrder local InputContainer = Instance.new("Frame") InputContainer.Name = "InputContainer" InputContainer.Parent = MainFrame InputContainer.Size = UDim2.new(1, -24, 0, 40) InputContainer.Position = UDim2.new(0, 12, 1, -52) InputContainer.BackgroundColor3 = Colors.InputBackground local InputCorner = Instance.new("UICorner") InputCorner.Parent = InputContainer InputCorner.CornerRadius = UDim.new(1, 0) local StickerButton = Instance.new("ImageButton") StickerButton.Name = "StickerButton" StickerButton.Parent = InputContainer StickerButton.Size = UDim2.new(0, 24, 0, 24) StickerButton.Position = UDim2.new(0, 10, 0.5, -12) StickerButton.BackgroundTransparency = 1 StickerButton.Image = "rbxassetid://7733955740" StickerButton.ImageColor3 = Colors.IconColor local MessageInput = Instance.new("TextBox") MessageInput.Name = "MessageInput" MessageInput.Parent = InputContainer MessageInput.Size = UDim2.new(1, -80, 1, 0) MessageInput.Position = UDim2.new(0, 42, 0, 0) MessageInput.BackgroundTransparency = 1 MessageInput.TextColor3 = Colors.Text MessageInput.PlaceholderText = "在此输入..." MessageInput.Font = Enum.Font.GothamBold MessageInput.TextSize = 14 MessageInput.TextXAlignment = Enum.TextXAlignment.Left local SendButton = Instance.new("ImageButton") SendButton.Name = "SendButton" SendButton.Parent = InputContainer SendButton.Image = "rbxassetid://7733919156" SendButton.Size = UDim2.new(0, 24, 0, 24) SendButton.Position = UDim2.new(1, -32, 0.5, -12) SendButton.BackgroundTransparency = 1 SendButton.ImageColor3 = Colors.Accent local StickerPanel = Instance.new("Frame") StickerPanel.Name = "StickerPanel" StickerPanel.Parent = MainShadow StickerPanel.Size = UDim2.new(0, 180, 0, 130) StickerPanel.Position = UDim2.new(0.5, -200, 0.5, 100) StickerPanel.BackgroundColor3 = Colors.Background StickerPanel.Visible = false StickerPanel.ClipsDescendants = true local StickerPanelCorner = Instance.new("UICorner") StickerPanelCorner.Parent = StickerPanel StickerPanelCorner.CornerRadius = UDim.new(0, 10) local StickerPanelStroke = Instance.new("UIStroke") StickerPanelStroke.Parent = StickerPanel StickerPanelStroke.Color = Colors.FrameBorder local StickerPanelGradient = Instance.new("UIGradient") StickerPanelGradient.Parent = StickerPanel StickerPanelGradient.Rotation = 45 StickerPanelGradient.Color = ColorSequence.new({ ColorSequenceKeypoint.new(0, Colors.GradientStart), ColorSequenceKeypoint.new(1, Colors.GradientEnd) }) local StickerScrollingFrame = Instance.new("ScrollingFrame") StickerScrollingFrame.Name = "StickerScrollingFrame" StickerScrollingFrame.Parent = StickerPanel StickerScrollingFrame.Size = UDim2.new(1, -10, 1, -10) StickerScrollingFrame.Position = UDim2.new(0, 5, 0, 5) StickerScrollingFrame.BackgroundTransparency = 1 StickerScrollingFrame.ScrollBarThickness = 3 local StickerGridLayout = Instance.new("UIGridLayout") StickerGridLayout.Parent = StickerScrollingFrame StickerGridLayout.CellSize = UDim2.new(0, 50, 0, 50) StickerGridLayout.CellPadding = UDim2.new(0, 5, 0, 5) local ActivePlayersPanel = Instance.new("Frame") ActivePlayersPanel.Name = "ActivePlayersPanel" ActivePlayersPanel.Parent = MainShadow ActivePlayersPanel.Size = UDim2.new(0, 0, 0, 310) ActivePlayersPanel.Position = UDim2.new(0.5, 210, 0.5, -155) ActivePlayersPanel.BackgroundColor3 = Colors.Background ActivePlayersPanel.ClipsDescendants = true local ActivePlayersPanelCorner = Instance.new("UICorner") ActivePlayersPanelCorner.Parent = ActivePlayersPanel ActivePlayersPanelCorner.CornerRadius = UDim.new(0, 14) local ActivePlayersPanelGradient = Instance.new("UIGradient") ActivePlayersPanelGradient.Parent = ActivePlayersPanel ActivePlayersPanelGradient.Rotation = 45 ActivePlayersPanelGradient.Color = ColorSequence.new({ ColorSequenceKeypoint.new(0, Colors.GradientStart), ColorSequenceKeypoint.new(1, Colors.GradientEnd) }) local ActivePlayersScrollingFrame = Instance.new("ScrollingFrame") ActivePlayersScrollingFrame.Name = "ActivePlayersScrollingFrame" ActivePlayersScrollingFrame.Parent = ActivePlayersPanel ActivePlayersScrollingFrame.Size = UDim2.new(1, 0, 1, 0) ActivePlayersScrollingFrame.BackgroundTransparency = 1 ActivePlayersScrollingFrame.ScrollBarThickness = 2 local ActivePlayersListLayout = Instance.new("UIListLayout") ActivePlayersListLayout.Parent = ActivePlayersScrollingFrame ActivePlayersListLayout.Padding = UDim.new(0, 8) ActivePlayersListLayout.HorizontalAlignment = Enum.HorizontalAlignment.Center local ActivePlayersPadding = Instance.new("UIPadding") ActivePlayersPadding.Parent = ActivePlayersScrollingFrame ActivePlayersPadding.PaddingTop = UDim.new(0, 15) local function playSound(soundId) local sound = Instance.new("Sound") sound.Parent = workspace sound.SoundId = soundId sound.Volume = 0.5 sound.PlayOnRemove = true sound:Destroy() end local function sendMessage(message) spawn(function() pcall(function() request({ Url = BASE_URL .. "/chat", Method = "POST", Headers = { ["Content-Type"] = "application/json" }, Body = HttpService:JSONEncode({ message = message, player = LocalPlayer.Name }) }) end) end) end local function sendSticker(stickerAssetId) playSound(SoundIds.Click) sendMessage("||STICKER||" .. stickerAssetId) StickerPanel.Visible = false end for i, stickerId in ipairs(StickerIds) do local stickerButton = Instance.new("ImageButton") stickerButton.Name = "Sticker" .. i stickerButton.Parent = StickerScrollingFrame stickerButton.Image = stickerId stickerButton.BackgroundTransparency = 1 stickerButton.BackgroundColor3 = Colors.AvatarBackground local stickerCorner = Instance.new("UICorner") stickerCorner.Parent = stickerButton stickerCorner.CornerRadius = UDim.new(0, 6) stickerButton.MouseButton1Click:Connect(function() sendSticker(stickerId) end) end StickerGridLayout:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(function() StickerScrollingFrame.CanvasSize = UDim2.new(0, 0, 0, StickerGridLayout.AbsoluteContentSize.Y + 20) end) StickerButton.MouseButton1Click:Connect(function() StickerPanel.Visible = not StickerPanel.Visible playSound(SoundIds.Click) end) CloseButton.MouseButton1Click:Connect(function() playSound(SoundIds.Open) MainShadow.Visible = false MinimizeButton.Visible = true end) MinimizeButton.MouseButton1Click:Connect(function() playSound(SoundIds.Open) MainShadow.Visible = true MinimizeButton.Visible = false NotificationBadge.Visible = false NotificationLabel.Text = "0" end) PlayersButton.MouseButton1Click:Connect(function() local targetSize = UDim2.new(0, 150, 0, 310) local tween = TweenService:Create(ActivePlayersPanel, TweenInfo.new(0.5, Enum.EasingStyle.Quart), { Size = targetSize }) tween:Play() end) local function handleSendMessage() local message = MessageInput.Text if message == "" then return end playSound(SoundIds.Click) StickerPanel.Visible = false sendMessage(message) MessageInput.Text = "" end SendButton.MouseButton1Click:Connect(handleSendMessage) MessageInput.FocusLost:Connect(function(enterPressed) if enterPressed then handleSendMessage() end end) local function getPlayerAvatarUrl(userId) return "https://www.roblox.com/headshot-thumbnail/image?userId=" .. userId .. "&width=150&height=150&format=png" end local function formatTimestamp(timestamp) local date = os.date("*t", timestamp / 1000) return string.format("%02d:%02d", date.hour, date.min) end local function getRolePrefix(role) if role == "DEV" then return "[开发者] ", "#fff" elseif role == "ADMIN" then return "[管理员] ", "#ff5555" else return "", "#00a8ff" end end local function createMessageFrame(messageData, layoutOrder) local playerName = messageData.player local message = messageData.msg local timestamp = messageData.timestamp local messageType = messageData.type local role = messageData.role or "USER" local isSystem = playerName == "SYSTEM" local isAnnouncement = playerName == "ANNOUNCEMENT" local isSticker = message and string.find(message, "||STICKER||") local frameHeight = 30 if isSticker then frameHeight = 60 elseif message then local textLength = #message local estimatedLines = math.ceil(textLength / 50) frameHeight = math.max(30, 14 * estimatedLines + 16) end local messageFrame = Instance.new("Frame") messageFrame.Name = "MessageFrame" messageFrame.Parent = ChatScrollingFrame messageFrame.Size = UDim2.new(1, 0, 0, frameHeight) messageFrame.BackgroundTransparency = 1 messageFrame.LayoutOrder = layoutOrder or 0 local avatarImage = Instance.new("ImageLabel") avatarImage.Name = "AvatarImage" avatarImage.Parent = messageFrame avatarImage.Size = UDim2.new(0, 28, 0, 28) avatarImage.Position = UDim2.new(0, 2, 0, 0) avatarImage.BackgroundColor3 = Colors.AvatarBackground avatarImage.Image = "rbxassetid://0" local avatarCorner = Instance.new("UICorner") avatarCorner.Parent = avatarImage avatarCorner.CornerRadius = UDim.new(1, 0) if isSystem or isAnnouncement then avatarImage.Visible = false else task.spawn(function() pcall(function() local userId = Players:GetUserIdFromNameAsync(playerName) avatarImage.Image = getPlayerAvatarUrl(userId) end) end) end local contentFrame = Instance.new("Frame") contentFrame.Name = "ContentFrame" contentFrame.Parent = messageFrame contentFrame.Size = UDim2.new(1, -35, 1, 0) contentFrame.Position = UDim2.new(0, 35, 0, 0) contentFrame.BackgroundTransparency = 1 if isSystem or isAnnouncement then contentFrame.Position = UDim2.new(0, 5, 0, 0) end if isSticker then local stickerAssetId = string.gsub(message, "||STICKER||", "") local nameLabel = Instance.new("TextLabel") nameLabel.Parent = contentFrame nameLabel.Text = string.format("%s %s", formatTimestamp(timestamp), playerName) nameLabel.Size = UDim2.new(1, 0, 0, 15) nameLabel.BackgroundTransparency = 1 nameLabel.RichText = true nameLabel.TextXAlignment = Enum.TextXAlignment.Left local stickerImage = Instance.new("ImageLabel") stickerImage.Parent = contentFrame stickerImage.Size = UDim2.new(0, 45, 0, 45) stickerImage.Position = UDim2.new(0, 0, 0, 15) stickerImage.BackgroundTransparency = 1 stickerImage.Image = stickerAssetId stickerImage.ScaleType = Enum.ScaleType.Fit else local textLabel = Instance.new("TextLabel") textLabel.Name = "TextLabel" textLabel.Parent = contentFrame textLabel.Size = UDim2.new(1, 0, 1, 0) textLabel.BackgroundTransparency = 1 textLabel.RichText = true textLabel.Font = Enum.Font.Gotham textLabel.TextSize = 14 textLabel.TextWrapped = true textLabel.TextXAlignment = Enum.TextXAlignment.Left textLabel.TextYAlignment = Enum.TextYAlignment.Top if messageType == "sys" then textLabel.Text = string.format("%s", message) elseif messageType == "announce" then textLabel.Text = string.format("📢 %s", message) else local prefix, nameColor = getRolePrefix(role) textLabel.Text = string.format( "%s %s%s: %s", formatTimestamp(timestamp), nameColor, prefix, playerName, message or "" ) end end local replyButton = Instance.new("TextButton") replyButton.Name = "ReplyButton" replyButton.Parent = messageFrame replyButton.Size = UDim2.new(1, 0, 1, 0) replyButton.BackgroundTransparency = 1 replyButton.Text = "" replyButton.MouseButton1Click:Connect(function() MessageInput.Text = "> " .. playerName .. ": " MessageInput:CaptureFocus() end) return messageFrame end local lastMessageCount = 0 local unreadCount = 0 local function fetchAndDisplayMessages() spawn(function() local success, response = pcall(function() return request({ Url = BASE_URL .. "/chat?nocache=" .. tick(), Method = "GET" }) end) if success and response and response.StatusCode == 200 then local messages = HttpService:JSONDecode(response.Body) for _, child in ipairs(ChatScrollingFrame:GetChildren()) do if child:IsA("Frame") then child:Destroy() end end for i, messageData in ipairs(messages) do createMessageFrame(messageData, i) end ChatListLayout:ApplyLayout() ChatScrollingFrame.CanvasSize = UDim2.new(0, 0, 0, ChatListLayout.AbsoluteContentSize.Y + 20) local newMessageCount = #messages if newMessageCount > lastMessageCount then local newMessages = newMessageCount - lastMessageCount if lastMessageCount > 0 then unreadCount = unreadCount + newMessages if not MainShadow.Visible then NotificationBadge.Visible = true NotificationLabel.Text = tostring(unreadCount) end playSound(SoundIds.Msg) end task.delay(0.05, function() ChatScrollingFrame.CanvasPosition = Vector2.new(0, ChatListLayout.AbsoluteContentSize.Y + 100) end) end lastMessageCount = newMessageCount ChatContainer.Visible = true end end) end local function checkUserRole() spawn(function() local success, response = pcall(function() return request({ Url = BASE_URL .. "/check-role?player=" .. LocalPlayer.Name .. "&nocache=" .. tostring(tick()), Method = "GET" }) end) if success and response and response.StatusCode == 200 then local roleData = HttpService:JSONDecode(response.Body) if roleData.role == "ADMIN" or roleData.role == "DEV" then PlayersButton.Visible = true end end end) end RunService.RenderStepped:Connect(function() local time = tick() * 3 end) spawn(function() wait(1) fetchAndDisplayMessages() while true do wait(1) fetchAndDisplayMessages() end end) spawn(function() wait(3) while true do checkUserRole() wait(3) end end) local dragWindow = nil local dragInput = nil local dragStart = nil local startPos = nil local function updateDrag(input, frame) local delta = input.Position - dragStart frame.Position = UDim2.new( startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y ) end TitleBar.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragWindow = MainShadow dragStart = input.Position startPos = MainShadow.Position input.Changed:Connect(function() if input.UserInputState == Enum.UserInputState.End then dragWindow = nil end end) end end) TitleBar.InputChanged:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch then dragInput = input end end) MinimizeButton.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then dragWindow = MinimizeButton dragStart = input.Position startPos = MinimizeButton.Position input.Changed:Connect(function() if input.UserInputState == Enum.UserInputState.End then dragWindow = nil end end) end end) MinimizeButton.InputChanged:Connect(function(input) if input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch then dragInput = input end end) UserInputService.InputChanged:Connect(function(input) if input == dragInput and dragWindow then updateDrag(input, dragWindow) end end)