example
example

资源 一个可供QBCore使用的简单的聊天插件

Norria.

新用户
认证用户
这是我之前在刚刚开始学习Fivem相关的开发技术的时候,根据站里的教程和网上的资源自己尝试写的一个聊天插件,这两天整理电脑的时候无意又被我翻了出来。
虽然功能不多,也可能存在一些我还没改的小问题,但或许会对一些同样对fivem感兴趣的新开发者有所帮助,所以就分享给大家啦,也欢迎各位指出其中的错误和改良方案来让它变得更有价值。

代码如下:
client.lua
lua:
RegisterCommand("me", function(source, args)
    TriggerServerEvent('me', table.concat(args, " "))  

end)

RegisterCommand("do", function(source, args)
    TriggerServerEvent('do', table.concat(args, " "))  

end)

RegisterCommand("shout", function(source, args)
    TriggerServerEvent('shout', table.concat(args, " "))  

end)

RegisterCommand("s", function(source, args)
    TriggerServerEvent('shout', table.concat(args, " "))  

end)

RegisterCommand("getmyid", function(source, args)
    TriggerServerEvent('getid',table.concat(args, " "))  

end)

RegisterCommand("say", function(source, args)
    TriggerServerEvent('say',table.concat(args, " "))  

end)

RegisterCommand("pm", function(source, args)
    local targetid_pm = tonumber(args[1]) -- 第一个参数为目标玩家ID
    table.remove(args, 1) -- 移除目标玩家ID,获取私信内容
    local message = table.concat(args, " ") -- 连接剩余的参数作为私信内容
    TriggerServerEvent('pm', targetid_pm, message)
end)

RegisterCommand("whisper", function(source, args)
    local targetid_whisper = tonumber(args[1]) -- 第一个参数为目标玩家ID
    table.remove(args, 1) -- 移除目标玩家ID,获取私信内容
    local message = table.concat(args, " ") -- 连接剩余的参数作为私信内容
    TriggerServerEvent('whisper', targetid_whisper, message)
end)

RegisterCommand("w", function(source, args)
    local targetid_whisper = tonumber(args[1]) -- 第一个参数为目标玩家ID
    table.remove(args, 1) -- 移除目标玩家ID,获取私信内容
    local message = table.concat(args, " ") -- 连接剩余的参数作为私信内容
    TriggerServerEvent('whisper', targetid_whisper, message)
end)

RegisterCommand("ooc", function(source, args)
    TriggerServerEvent('ooc',table.concat(args, " "))  

end)

RegisterCommand("b", function(source, args)
    TriggerServerEvent('b',table.concat(args, " "))  

end)
server.lua
lua:
---------------------------QBCore前置文件-------------------------------------
local QBCore = exports['qb-core']:GetCoreObject()

--------------------------距离判定和显示---------------------------------

local function Distance(senderid,targeterid)
    local sender = senderid
  local targeter = targeterid
  local senderped = GetPlayerPed(sender)
  local targetped = GetPlayerPed(targeter)
  local senderCoords = GetEntityCoords(senderped)
  local targetCoords = GetEntityCoords(targetped)
    local distance = #(targetCoords - senderCoords)
    return distance
end
----------------------------QBCORE玩家角色名----------------------------------

function GetplayerCharname(source)
  local source = source
  local playerdata = QBCore.Functions.GetPlayer(source)
  local charfirstname = playerdata.PlayerData.charinfo.firstname
  local charlastname = playerdata.PlayerData.charinfo.lastname
  local charname = charfirstname.." "..charlastname
  return charname
end
-----------------------------------------------------------------------------
----------------------------QBCORE在线玩家----------------------------------------

-- local Players = QBCore.Functions.GetQBPlayers()


---------------------------------------------------------------------------------
---------------------------基础交流系统----------------------------------

RegisterServerEvent('message_enter')
AddEventHandler('message_enter', function(source,message)
    local source = source
      local charactername = GetplayerCharname(source)

    print(charactername.." 说:"..message.."(距离判定前)")

    for _, targetid in ipairs(GetPlayers()) do
      if DoesPlayerExist(targetid) then
        if Distance(source,targetid) <= 10 then
          -- 连接玩家角色名和输入的信息并打印在服务端
            print(charactername.. "说:"..message)
          -- 通过客户端事件将连接好的玩家角色名和输入的信息返回客户端,并打印在聊天窗口。颜色由最后的表内数值决定,类型是RGB
            TriggerClientEvent('chatMessage',targetid, charactername.. " 说:"..message,{255,255,255})
        end
      end
    end
end)

------------------------------------------------------------------------

--me指令--
RegisterServerEvent('me')

AddEventHandler('me',function (message)
  local message = message
  local charactername = GetplayerCharname(source)
  for _, targetid in ipairs(GetPlayers()) do
    if DoesPlayerExist(targetid) then
      if Distance(source,targetid) <= 10 then
        print(' * '..charactername.. message)
        TriggerClientEvent('chatMessage',targetid,' * '..charactername.." "..message,{187,160,215})
      end
    end
  end
end)

--do指令--
RegisterServerEvent('do')
    AddEventHandler('do', function(param)  
    local charactername = GetplayerCharname(source)
      for _, targetid in ipairs(GetPlayers()) do
        if DoesPlayerExist(targetid) then
          if Distance(source,targetid) <= 10 then
          print(param.." * (("..charactername..'('..source..')'.."))")
          TriggerClientEvent('chatMessage', targetid, param.." * (("..charactername..'('..source..')'.."))",{187,160,215})
          end
        end
      end
    end)


--大喊指令--
RegisterServerEvent('shout')
AddEventHandler('shout', function(param)  
 local charactername = GetplayerCharname(source)
  for _, targetid in ipairs(GetPlayers()) do
    if DoesPlayerExist(targetid) then
      if Distance(source,targetid) <= 20 then
       print(charactername.." 大喊道:"..param)
       TriggerClientEvent('chatMessage', targetid, charactername.." 大喊道:"..param.."!",{255,250,250})
      end
    end
  end
end)

--一般说话指令--
RegisterServerEvent('say')
AddEventHandler('say', function(param)
 local charactername = GetplayerCharname(source)
  for _, targetid in ipairs(GetPlayers()) do
    if DoesPlayerExist(targetid) then
      if Distance(source,targetid) <= 10 then
    print(charactername.." 说: "..param)
    TriggerClientEvent('chatMessage', targetid , charactername.." 说:"..param , {255, 255, 255})
      end
    end
  end
end)

--现实世界私聊指令--
RegisterServerEvent('pm')
AddEventHandler('pm', function(targetid_pm,message)
local charactername_sender = GetplayerCharname(source)
  -- 获取发送者的游戏id
  local senderid_pm = source
  -- 测试用,打印发送者id和接收者id到服务端
  print("targetid:"..targetid_pm.."senderid:"..senderid_pm)
  -- 判断目标玩家是否存在
  if DoesPlayerExist(targetid_pm) then
  -- 如果存在目标玩家,则获取目标玩家的角色姓名
    local charactername_target = GetplayerCharname(targetid_pm)
  -- 连接消息和发送者,打印在发送者的聊天界面
      print("消息:["..message.."].已发送至"..charactername_target.."("..targetid_pm..")")
      TriggerClientEvent('chatMessage', senderid_pm , "消息:["..message.."].已发送至"..charactername_target.."("..targetid_pm..")",{235, 216, 52})
  -- 连接消息和发送者,打印在接收者的聊天界面
      print("消息来自"..charactername_sender.."("..source..") "..": "..message)
      TriggerClientEvent('chatMessage', targetid_pm ,"消息来自"..charactername_sender.."("..source..") "..": "..message , {235, 216, 52})
      print("玩家"..charactername_sender.."("..senderid_pm..")".."pm了"..charactername_target.."("..targetid_pm..")".."内容是:"..message)
  -- 如果不存在目标玩家,提示检查输入是否正确
  else
    print("玩家ID: "..source.."试图向ID:"..targetid_pm.." 发送现实世界私聊:"..message..",但因目标不存在而失败")
    TriggerClientEvent('chatMessage', senderid_pm , "(( 目标id: "..targetid_pm.." 不存在,请核实后重试))",{235, 216, 58})
  end
end)

--耳语指令--
RegisterServerEvent('whisper')
AddEventHandler('whisper', function(targetid_whisper,message)
local charactername_sender = GetplayerCharname(source)
  -- 获取发送者的游戏id
  local senderid_whisper = source
  -- 测试用,打印发送者id和接收者id到服务端
  print("targetid:"..targetid_whisper.."senderid:"..senderid_whisper)
  -- 判断目标玩家是否存在
  if DoesPlayerExist(targetid_whisper) then
    if Distance(senderid_whisper,targetid_whisper) <= 2 then
    -- 如果存在目标玩家,则获取目标玩家的角色姓名
      local charactername_target = GetplayerCharname(targetid_whisper)
    -- 连接消息和发送者,打印在发送者的聊天界面
        print("你悄悄对"..charactername_target.."("..targetid_whisper..")".."说:"..message)
        TriggerClientEvent('chatMessage', senderid_whisper , "你悄悄对"..charactername_target.."("..targetid_whisper..")".."说:"..message,{179, 134, 62})
    -- 连接消息和发送者,打印在接收者的聊天界面
        print(charactername_sender.."("..source..") ".."悄悄对你说: "..message)
        TriggerClientEvent('chatMessage', targetid_whisper ,charactername_sender.."("..source..") ".."悄悄对你说: "..message , {179, 134, 62})
        print("玩家"..charactername_sender.."("..senderid_whisper..")".."悄悄对"..charactername_target.."("..targetid_whisper..")".."说:"..message)
    else
      print("玩家ID: "..senderid_whisper.."试图向ID:"..targetid_whisper.." 发送耳语:"..message..",但因距离过远而失败")
      TriggerClientEvent('chatMessage',senderid_whisper,"((这种距离("..distance..")想说悄悄话有点难哦))")
    end
  -- 如果不存在目标玩家,提示检查输入是否正确
  else
    print("玩家ID: "..senderid_whisper.."试图向ID:"..targetid_whisper.." 发送耳语:"..message..",但因目标不存在而失败")
    TriggerClientEvent('chatMessage', senderid_whisper , "(( 目标id: "..targetid_whisper.." 不存在,请核实后重试))",{179, 134, 58})
  end
 
end)

--全域现实世界消息--
RegisterServerEvent('ooc')
AddEventHandler('ooc', function(param)  
 local charactername = GetplayerCharname(source)
  print("(( 全域现实世界消息来自 "..charactername.."("..source..") : "..param.."))")
  TriggerClientEvent('chatMessage', -1, "(( 全域现实世界消息来自 "..charactername.."("..source..") : "..param.."))",{92, 92, 92})
end)

--范围现实世界消息--
RegisterServerEvent('b')
AddEventHandler('b', function(param)
 local charactername = GetplayerCharname(source)
  for _, targetid in ipairs(GetPlayers()) do
    if DoesPlayerExist(targetid) then
      if Distance(source,targetid) <= 10 and targetid ~= 0 then
    print("(("..charactername.." 说: "..param.."))")
    TriggerClientEvent('chatMessage', targetid , "(("..charactername.."("..source..")".." 说:"..param.."))" , {125, 123, 120})
      end
    end
  end
end)
fxmanifest.lua
lua:
fx_version 'cerulean'   --确定当前的版本,固定值

lua54 'yes'  -- 启用lua5.4

games { 'gta5' }    --为资源定义支持的游戏 API 集。

server_script "server.lua"   --定义服务端脚本

client_script "client.lua"   --定义客户端脚本

dependencies {  --插件依赖关系 要求在当前资源之前加载指定的资源。
    'chat';
    'qb-core';
}


files { -- 定义NUI面板内容
    "style1.css"
}

chat_theme 'rpchat_test' { --定义聊天界面主题
    styleSheet = 'style1.css'

}
style1.css
CSS:
.color-0{color: #ffffff;}
.color-1{color: #ff4444;}
.color-2{color: #99cc00;}
.color-3{color: #ffbb33;}
.color-4{color: #0099cc;}
.color-5{color: #33b5e5;}
.color-6{color: #aa66cc;}
.color-8{color: #cc0000;}
.color-9{color: #cc0068;}
.gameColor-w{color: #ffffff;}
.gameColor-r{color: #ff4444;}
.gameColor-g{color: #99cc00;}
.gameColor-y{color: #ffbb33;}
.gameColor-b{color: #33b5e5;}
/* todo: more game colors */
* {
  font-family: 'heiti', sans-serif;
  margin: 0;
  padding: 0;
  text-shadow: 0 0 0.5px #000000, 0 0 1px #000000, 0 0 2px #000000 , 0 0 4px #000000 , 0 0 6px #000000;
  font-weight: bold !important;
  font-size: 98%;
}
.no-grow {
  flex-grow: 0;
}
em {
  font-style: normal;
}
#app {
  font-family: 'Lato', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: white;
}
.chat-window {
  position: relative;
  top: 1.5%;
  left: 0.8%;
  width: 75%;
  height: 75%;
  background-color: inherit !important;
}

.chat-messages {
  position: relative;
  height: 95%;
  font-size: 1.8vh;
  margin: 1%;
  overflow-x: hidden; /* 允许内容在水平方向上溢出 */
  word-wrap: break-word; /* 在单词边界处断行,如果需要的话 */
  overflow-y: scroll;
  min-width: 28vh;
  min-height: 28vh;
  flex-shrink: 1;
  
  margin-bottom: 10px;
  max-width: 100vh;
  max-height: 58vh;
  min-width: 21vh;
  min-height: 21vh;
  resize: both;
  padding: 10px;
  display: flex;
  flex-direction: column;
}

.chat-input {
  font-size: 1.65vh;
  position: relative;
  top: 23.8%;
  left: 0.8%;
  width: 38%;
  max-width: 58%;
  max-height: 58%;
  box-sizing: border-box;
}
.chat-input > div.input {
  order: 2;
  margin-top: auto;
  
  position: relative;
  display: flex;
  align-items: stretch;
  width: 100%;
  background-color: rgba(68, 68, 68, 0.178)!important;
}
.chat-hide-state {
  text-transform: uppercase;
  margin-left: 0.05vw;
  font-size: 1.65vh;
}
.prefix {
  font-size: 1.8vh;
  height: 100%;
  vertical-align: middle;
  line-height: calc(1vh + 1vh + 1.85vh);
  padding-left: 0.5vh;
  text-transform: uppercase;
  font-weight: bold;
  display: inline-block;
}
textarea {
  font-size: 1.65vh;
  line-height: 1.85vh;
  display: block;
  box-sizing: content-box;
  padding: 1vh;
  padding-left: 0.5vh;
  color: white;
  border-width: 0;
  height: 3.15%;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
  background-color: transparent;
}
textarea:focus, input:focus {
    outline: none;
}
.msg {
  margin-bottom: 0.28%;
}
.multiline {
  margin-left: 4%;
  text-indent: -1.2rem;
  white-space: pre-line;
}
.suggestions {
  list-style-type: none;
  padding: 0.5%;
  padding-left: 1.4%;
  font-size: 1.65vh;
  box-sizing: border-box;
  color: white;
  background-color: rgba(255, 255, 255, 0)!important;
  width: 100%;
}
.help {
  color: #b0bbbd;
}
.disabled {
  color: #b0bbbd;
}
.suggestion {
  margin-bottom: 0.5%;
}
.hidden {
  opacity: 0;
}
.hidden.animated {
  transition: opacity 1s;
}

/* 滚动条本身 */
::-webkit-scrollbar{
  width: 8px;
  height: 8px;
}
/* 滚动条头 */
::-webkit-scrollbar-thumb{
  border-radius: 1em;
  background-color: rgba(0,24,41,0.2);
}
/* 滚动条轨道 */
::-webkit-scrollbar-track{
  border-radius: 1em;
  background-color: rgba(181,164,164,0);
}

希望能够有所帮助到你!
 
最后编辑:

Klein

用户
高级用户
认证用户
如何取消滑动条,让发出的信息能读取到最新的一条而不用滑到最下面
 

Norria.

新用户
认证用户
如何取消滑动条,让发出的信息能读取到最新的一条而不用滑到最下面
可以尝试在style1.css里的.chat-window或.chat-messages里添加这段:

CSS:
  display: flex;
  flex-direction: column;

或者直接复制刚刚修改之后的css代码试试看。
滚动条的话直接删掉css里所有scroll相关的设置就看不见了。
 

Klein

用户
高级用户
认证用户
可以尝试在style1.css里的.chat-window或.chat-messages里添加这段:

CSS:
  display: flex;
  flex-direction: column;

或者直接复制刚刚修改之后的css代码试试看。
滚动条的话直接删掉css里所有scroll相关的设置就看不见了。
ok了 我直接换了一个style1.css
 
顶部