mirror of
https://github.com/citizenfx/cfx-server-data.git
synced 2025-12-12 06:14:09 +01:00
initial
This commit is contained in:
15
resources/[system]/chat/__resource.lua
Normal file
15
resources/[system]/chat/__resource.lua
Normal file
@@ -0,0 +1,15 @@
|
||||
description 'chat management stuff'
|
||||
|
||||
ui_page 'html/chat.html'
|
||||
|
||||
client_script 'chat_client.lua'
|
||||
server_script 'chat_server.lua'
|
||||
|
||||
export 'printChatLine'
|
||||
|
||||
files {
|
||||
'html/chat.html',
|
||||
'html/chat.css',
|
||||
'html/chat.js',
|
||||
'html/jquery.faketextbox.js'
|
||||
}
|
||||
56
resources/[system]/chat/chat_client.lua
Normal file
56
resources/[system]/chat/chat_client.lua
Normal file
@@ -0,0 +1,56 @@
|
||||
local chatInputActive = false
|
||||
local chatInputActivating = false
|
||||
|
||||
RegisterNetEvent('chatMessage')
|
||||
|
||||
AddEventHandler('chatMessage', function(name, color, message)
|
||||
SendNUIMessage({
|
||||
name = name,
|
||||
color = color,
|
||||
message = message
|
||||
})
|
||||
end)
|
||||
|
||||
RegisterNUICallback('chatResult', function(data, cb)
|
||||
chatInputActive = false
|
||||
|
||||
SetNuiFocus(false)
|
||||
|
||||
if data.message then
|
||||
local id = PlayerId()
|
||||
|
||||
--local r, g, b = GetPlayerRgbColour(id, _i, _i, _i)
|
||||
local r, g, b = 0, 0x99, 255
|
||||
|
||||
TriggerServerEvent('chatMessageEntered', GetPlayerName(id), { r, g, b }, data.message)
|
||||
end
|
||||
|
||||
cb('ok')
|
||||
end)
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
SetTextChatEnabled(false)
|
||||
|
||||
while true do
|
||||
Wait(0)
|
||||
|
||||
if not chatInputActive then
|
||||
if IsControlPressed(0, 245) --[[ INPUT_MP_TEXT_CHAT_ALL ]] then
|
||||
chatInputActive = true
|
||||
chatInputActivating = true
|
||||
|
||||
SendNUIMessage({
|
||||
meta = 'openChatBox'
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
if chatInputActivating then
|
||||
if not IsControlPressed(0, 245) then
|
||||
SetNuiFocus(true)
|
||||
|
||||
chatInputActivating = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
50
resources/[system]/chat/chat_server.lua
Normal file
50
resources/[system]/chat/chat_server.lua
Normal file
@@ -0,0 +1,50 @@
|
||||
RegisterServerEvent('chatCommandEntered')
|
||||
RegisterServerEvent('chatMessageEntered')
|
||||
|
||||
AddEventHandler('chatMessageEntered', function(name, color, message)
|
||||
if not name or not color or not message or #color ~= 3 then
|
||||
return
|
||||
end
|
||||
|
||||
TriggerEvent('chatMessage', source, name, message)
|
||||
|
||||
if not WasEventCanceled() then
|
||||
TriggerClientEvent('chatMessage', -1, name, color, message)
|
||||
end
|
||||
|
||||
print(name .. ': ' .. message)
|
||||
end)
|
||||
|
||||
-- player join messages
|
||||
AddEventHandler('playerActivated', function()
|
||||
TriggerClientEvent('chatMessage', -1, '', { 0, 0, 0 }, '^2* ' .. GetPlayerName(source) .. ' joined.')
|
||||
end)
|
||||
|
||||
AddEventHandler('playerDropped', function(reason)
|
||||
TriggerClientEvent('chatMessage', -1, '', { 0, 0, 0 }, '^2* ' .. GetPlayerName(source) ..' left (' .. reason .. ')')
|
||||
end)
|
||||
|
||||
-- say command handler
|
||||
AddEventHandler('rconCommand', function(commandName, args)
|
||||
if commandName == "say" then
|
||||
local msg = table.concat(args, ' ')
|
||||
|
||||
TriggerClientEvent('chatMessage', -1, 'console', { 0, 0x99, 255 }, msg)
|
||||
RconPrint('console: ' .. msg .. "\n")
|
||||
|
||||
CancelEvent()
|
||||
end
|
||||
end)
|
||||
|
||||
-- tell command handler
|
||||
AddEventHandler('rconCommand', function(commandName, args)
|
||||
if commandName == "tell" then
|
||||
local target = table.remove(args, 1)
|
||||
local msg = table.concat(args, ' ')
|
||||
|
||||
TriggerClientEvent('chatMessage', tonumber(target), 'console', { 0, 0x99, 255 }, msg)
|
||||
RconPrint('console: ' .. msg .. "\n")
|
||||
|
||||
CancelEvent()
|
||||
end
|
||||
end)
|
||||
102
resources/[system]/chat/html/chat.css
Normal file
102
resources/[system]/chat/html/chat.css
Normal file
@@ -0,0 +1,102 @@
|
||||
body
|
||||
{
|
||||
background-color: transparent;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
ul
|
||||
{
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
list-style-type: none; /* hii */
|
||||
}
|
||||
|
||||
#chat
|
||||
{
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
left: 30px;
|
||||
padding: 7px;
|
||||
width: 30%;
|
||||
font-size: 20px;
|
||||
font-family: "Segoe UI", "Segoe UI Symbol", "Segoe UI Emoji", Arial, sans-serif;
|
||||
color: #fff;
|
||||
overflow: hidden;
|
||||
text-shadow: 0px 0px 1px #333;
|
||||
}
|
||||
|
||||
input.fake
|
||||
{
|
||||
position: absolute;
|
||||
top: -10000px;
|
||||
left: -10000px;
|
||||
}
|
||||
|
||||
#chatInputHas
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
#chatInputHas strong
|
||||
{
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
text-transform: uppercase;
|
||||
height: 29px;
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
#chatInput
|
||||
{
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
outline: none !important;
|
||||
padding: 3px;
|
||||
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
|
||||
margin: 0px;
|
||||
color: #fff;
|
||||
text-shadow: 0px 0px 1px #333;
|
||||
|
||||
font: inherit;
|
||||
|
||||
white-space: pre;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#chatInput > div:first-child
|
||||
{
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
height: 23px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
#chatInput .caret
|
||||
{
|
||||
display: inline-block;
|
||||
min-width: 1px;
|
||||
height: 22px;
|
||||
margin-left: 1px;
|
||||
vertical-align: bottom;
|
||||
background-color: #fff;
|
||||
box-shadow: 0px 0px 1px #333;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#chatBuffer
|
||||
{
|
||||
height: 240px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.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: #cc0000;}
|
||||
20
resources/[system]/chat/html/chat.html
Normal file
20
resources/[system]/chat/html/chat.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="nui://game/ui/jquery.js" type="text/javascript"></script>
|
||||
<script src="jquery.faketextbox.js" type="text/javascript"></script>
|
||||
<script src="chat.js" type="text/javascript"></script>
|
||||
<link href="chat.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="chat">
|
||||
<div id="chatBuffer">
|
||||
<ul>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="chatInputHas">
|
||||
<strong>Chat</strong>
|
||||
<div id="chatInput" />
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
166
resources/[system]/chat/html/chat.js
Normal file
166
resources/[system]/chat/html/chat.js
Normal file
@@ -0,0 +1,166 @@
|
||||
function colorize(string)
|
||||
{
|
||||
var newString = '';
|
||||
var inSpan = false;
|
||||
|
||||
for (i = 0; i < string.length; i++)
|
||||
{
|
||||
if (string[i] == '^')
|
||||
{
|
||||
if (string[i + 1] == '7' || string[i + 1] == '0')
|
||||
{
|
||||
if (inSpan)
|
||||
{
|
||||
newString += '</span>';
|
||||
|
||||
inSpan = false;
|
||||
}
|
||||
|
||||
i += 2;
|
||||
}
|
||||
else if (string[i + 1] >= '0' && string[i + 1] <= '9')
|
||||
{
|
||||
if (inSpan)
|
||||
{
|
||||
newString += '</span>';
|
||||
}
|
||||
|
||||
i += 2;
|
||||
newString += '<span class="color-' + string[i - 1] + '">';
|
||||
|
||||
inSpan = true;
|
||||
}
|
||||
}
|
||||
|
||||
newString += string[i];
|
||||
}
|
||||
|
||||
if (inSpan)
|
||||
{
|
||||
newString += '</span>';
|
||||
}
|
||||
|
||||
return newString;
|
||||
}
|
||||
|
||||
$(function()
|
||||
{
|
||||
var chatHideTimeout;
|
||||
var inputShown = false;
|
||||
|
||||
function startHideChat()
|
||||
{
|
||||
if (chatHideTimeout)
|
||||
{
|
||||
clearTimeout(chatHideTimeout);
|
||||
}
|
||||
|
||||
if (inputShown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
chatHideTimeout = setTimeout(function()
|
||||
{
|
||||
if (inputShown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$('#chat').animate({ opacity: 0 }, 300);
|
||||
}, 7000);
|
||||
}
|
||||
|
||||
handleResult = function(elem, wasEnter)
|
||||
{
|
||||
inputShown = false;
|
||||
|
||||
$('#chatInputHas').hide();
|
||||
|
||||
startHideChat();
|
||||
|
||||
var obj = {};
|
||||
|
||||
if (wasEnter)
|
||||
{
|
||||
obj = { message: $(elem).val() };
|
||||
}
|
||||
|
||||
$(elem).val('');
|
||||
|
||||
$.post('http://chat/chatResult', JSON.stringify(obj), function(data)
|
||||
{
|
||||
console.log(data);
|
||||
});
|
||||
};
|
||||
|
||||
$('#chatInput').fakeTextbox(); // //
|
||||
|
||||
$('#chatInput')[0].onPress(function(e)
|
||||
{
|
||||
if (e.which == 13)
|
||||
{
|
||||
handleResult(this, true);
|
||||
}
|
||||
});
|
||||
|
||||
$(document).keyup(function(e)
|
||||
{
|
||||
if (e.keyCode == 27)
|
||||
{
|
||||
handleResult($('#chatInput')[0].getTextBox(), false);
|
||||
}
|
||||
});
|
||||
|
||||
$(document).keypress(function(e)
|
||||
{
|
||||
if (e.keyCode == 9)
|
||||
{
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('message', function(event)
|
||||
{
|
||||
var item = event.data;
|
||||
|
||||
if (item.meta && item.meta == 'openChatBox')
|
||||
{
|
||||
inputShown = true;
|
||||
|
||||
$('#chat').css('opacity', '1');
|
||||
|
||||
$('#chatInputHas').show();
|
||||
$('#chatInput')[0].doFocus();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: use some templating stuff for this
|
||||
var colorR = parseInt(item.color[0]);
|
||||
var colorG = parseInt(item.color[1]);
|
||||
var colorB = parseInt(item.color[2]);
|
||||
|
||||
var name = item.name.replace('<', '<');
|
||||
var message = item.message.replace('<', '<');
|
||||
|
||||
message = colorize(message);
|
||||
|
||||
var buf = $('#chatBuffer');
|
||||
|
||||
var nameStr = '';
|
||||
|
||||
if (name != '')
|
||||
{
|
||||
nameStr = '<strong style="color: rgb(' + colorR + ', ' + colorG + ', ' + colorB + ')">' + name + ': </strong>';
|
||||
}
|
||||
|
||||
buf.find('ul').append('<li>' + nameStr + message + '</li>');
|
||||
buf.scrollTop(buf[0].scrollHeight - buf.height());
|
||||
|
||||
$('#chat').css('opacity', '1');
|
||||
|
||||
startHideChat();
|
||||
}, false);
|
||||
});
|
||||
103
resources/[system]/chat/html/jquery.faketextbox.js
Normal file
103
resources/[system]/chat/html/jquery.faketextbox.js
Normal file
@@ -0,0 +1,103 @@
|
||||
(function ($) {
|
||||
$.fn.fakeTextbox = function () {
|
||||
|
||||
return this.each(function () {
|
||||
|
||||
var $me = $(this),
|
||||
cursorTimer,
|
||||
$tb = $('<input type="text" class="fake" />');
|
||||
|
||||
if ($me.data('ftbftw')) {
|
||||
console.log('already initialized');
|
||||
return;
|
||||
}
|
||||
|
||||
$me.data('ftbftw', 1);
|
||||
|
||||
$tb.insertAfter($me);
|
||||
|
||||
function appendCaret(toHere, position, selStart, selEnd) {
|
||||
if (position === selStart) {
|
||||
toHere += "</div><div class='caret'>";
|
||||
}
|
||||
if (position === selEnd) {
|
||||
toHere += "</div><div>";
|
||||
}
|
||||
return toHere;
|
||||
}
|
||||
|
||||
function syncTextbox() {
|
||||
var tbVal = $tb.val().replace('<', '<');
|
||||
var tbLen = tbVal.length;
|
||||
var selStart = $tb.get(0).selectionStart;
|
||||
var selEnd = $tb.get(0).selectionEnd;
|
||||
var newOut = '<div>';
|
||||
|
||||
for (var i = 0; i < tbLen; i++) {
|
||||
newOut = appendCaret(newOut, i, selStart, selEnd);
|
||||
newOut += tbVal[i];
|
||||
}
|
||||
|
||||
$me.html(colorize(appendCaret(newOut, i, selStart, selEnd) + '</div>'));
|
||||
if (selStart != selEnd) {
|
||||
$('.caret', $me).addClass('selection');
|
||||
}
|
||||
}
|
||||
|
||||
$me.click(function () {
|
||||
$tb.focus();
|
||||
});
|
||||
|
||||
$tb.bind("change keypress keyup", function()
|
||||
{
|
||||
setTimeout(syncTextbox, 1); //
|
||||
})
|
||||
.blur(function () {
|
||||
clearInterval(cursorTimer);
|
||||
cursorTimer = null;
|
||||
var $cursor = $('.caret', $me);
|
||||
$cursor.css({
|
||||
visibility: 'visible'
|
||||
});
|
||||
$me.removeClass('focused');
|
||||
}).focus(function () {
|
||||
if (!cursorTimer) {
|
||||
$me.addClass('focused');
|
||||
cursorTimer = window.setInterval(function () {
|
||||
var $cursor = $('.caret', $me);
|
||||
if ($cursor.hasClass('selection') || $cursor.css('visibility') === 'hidden') {
|
||||
$cursor.css({
|
||||
visibility: 'visible'
|
||||
});
|
||||
} else {
|
||||
$cursor.css({
|
||||
visibility: 'hidden'
|
||||
});
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
|
||||
this.doFocus = function()
|
||||
{
|
||||
$tb.focus();
|
||||
};
|
||||
|
||||
this.onPress = function(f)
|
||||
{
|
||||
$tb.bind('keypress', f);
|
||||
};
|
||||
|
||||
this.getTextBox = function()
|
||||
{
|
||||
return $tb;
|
||||
};
|
||||
|
||||
syncTextbox();
|
||||
|
||||
if ($me.hasClass('initFocus')) {
|
||||
$tb.focus();
|
||||
}
|
||||
});
|
||||
};
|
||||
}(jQuery));
|
||||
Reference in New Issue
Block a user