mirror of
https://github.com/iDisaster/GTAConnected.git
synced 2026-03-08 01:15:23 +00:00
Fix chat issues: lobby visibility, event errors, message display, and text alignment
- Remove event.preventDefault() calls as these events are not cancellable in GTA Connected - Add in-game detection using localPlayer to hide chat when in lobby - Change network event parameters from objects to individual args for compatibility - Fix text alignment with consistent font sizes and proper vertical centering - Rename to "Revolution chat" per user preference
This commit is contained in:
@@ -63,6 +63,9 @@ let lastMessageTime = 0;
|
|||||||
let chatFadeDelay = 10000; // 10 seconds before fade
|
let chatFadeDelay = 10000; // 10 seconds before fade
|
||||||
let chatFadeSpeed = 0.02;
|
let chatFadeSpeed = 0.02;
|
||||||
|
|
||||||
|
// Track if player is in game (spawned)
|
||||||
|
let isPlayerInGame = false;
|
||||||
|
|
||||||
// Welcome/Leave notification queue
|
// Welcome/Leave notification queue
|
||||||
let notifications = [];
|
let notifications = [];
|
||||||
let notificationDuration = 5000; // 5 seconds
|
let notificationDuration = 5000; // 5 seconds
|
||||||
@@ -75,8 +78,12 @@ const chat = {
|
|||||||
messageHeight: 22,
|
messageHeight: 22,
|
||||||
maxVisibleMessages: 12,
|
maxVisibleMessages: 12,
|
||||||
padding: 12,
|
padding: 12,
|
||||||
inputHeight: 36,
|
inputHeight: 32,
|
||||||
borderRadius: 4
|
borderRadius: 4,
|
||||||
|
// Font sizes for consistent text alignment
|
||||||
|
fontSize: 10,
|
||||||
|
timestampSize: 10,
|
||||||
|
inputFontSize: 10
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -104,19 +111,25 @@ addEventHandler("OnResourceStart", function(event, resource) {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
// NETWORK EVENTS - Receive messages from server
|
// NETWORK EVENTS - Receive messages from server
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
addNetworkHandler("chatMessage", function(messageData) {
|
addNetworkHandler("chatMessage", function(text, type, playerName) {
|
||||||
addChatMessage(messageData.text, messageData.type || "normal", messageData.playerName || null);
|
// Receives individual parameters instead of object for better compatibility
|
||||||
|
console.log("[Chat] Received message: " + text + " type: " + type + " from: " + playerName);
|
||||||
|
addChatMessage(text, type || "normal", playerName || null);
|
||||||
});
|
});
|
||||||
|
|
||||||
addNetworkHandler("playerJoined", function(data) {
|
addNetworkHandler("playerJoined", function(playerName) {
|
||||||
addNotification(data.name + " joined the server", "join");
|
// Receives player name directly
|
||||||
addChatMessage(data.name + " has joined the server", "system");
|
console.log("[Chat] Player joined: " + playerName);
|
||||||
|
addNotification(playerName + " joined the server", "join");
|
||||||
|
addChatMessage(playerName + " has joined the server", "system");
|
||||||
});
|
});
|
||||||
|
|
||||||
addNetworkHandler("playerLeft", function(data) {
|
addNetworkHandler("playerLeft", function(playerName, reason) {
|
||||||
let reason = data.reason || "Disconnected";
|
// Receives individual parameters
|
||||||
addNotification(data.name + " left the server", "leave");
|
console.log("[Chat] Player left: " + playerName + " reason: " + reason);
|
||||||
addChatMessage(data.name + " has left the server (" + reason + ")", "system");
|
let reasonText = reason || "Disconnected";
|
||||||
|
addNotification(playerName + " left the server", "leave");
|
||||||
|
addChatMessage(playerName + " has left the server (" + reasonText + ")", "system");
|
||||||
});
|
});
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -217,6 +230,9 @@ function drawText(text, x, y, colour, size) {
|
|||||||
addEventHandler("OnDrawnHUD", function(event) {
|
addEventHandler("OnDrawnHUD", function(event) {
|
||||||
animTime += 0.016; // ~60fps
|
animTime += 0.016; // ~60fps
|
||||||
|
|
||||||
|
// Update player in-game state
|
||||||
|
isPlayerInGame = checkIfPlayerInGame();
|
||||||
|
|
||||||
let screenWidth = 1920;
|
let screenWidth = 1920;
|
||||||
let screenHeight = 1080;
|
let screenHeight = 1080;
|
||||||
try {
|
try {
|
||||||
@@ -224,6 +240,15 @@ addEventHandler("OnDrawnHUD", function(event) {
|
|||||||
screenHeight = game.height || 1080;
|
screenHeight = game.height || 1080;
|
||||||
} catch(e) {}
|
} catch(e) {}
|
||||||
|
|
||||||
|
// Don't render anything if player is in lobby (not spawned)
|
||||||
|
if (!isPlayerInGame) {
|
||||||
|
// Close chat input if it was open when entering lobby
|
||||||
|
if (chatInputActive) {
|
||||||
|
closeChatInput();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Update fade
|
// Update fade
|
||||||
if (Date.now() - lastMessageTime > chatFadeDelay && !chatInputActive) {
|
if (Date.now() - lastMessageTime > chatFadeDelay && !chatInputActive) {
|
||||||
chatFadeAlpha = Math.max(0.3, chatFadeAlpha - chatFadeSpeed);
|
chatFadeAlpha = Math.max(0.3, chatFadeAlpha - chatFadeSpeed);
|
||||||
@@ -277,13 +302,16 @@ addEventHandler("OnDrawnHUD", function(event) {
|
|||||||
let headerBg = toColour(UI.bgPanel.r, UI.bgPanel.g, UI.bgPanel.b, bgAlpha);
|
let headerBg = toColour(UI.bgPanel.r, UI.bgPanel.g, UI.bgPanel.b, bgAlpha);
|
||||||
drawRect(chat.x, chat.y + 2, chat.width, headerHeight, headerBg);
|
drawRect(chat.x, chat.y + 2, chat.width, headerHeight, headerBg);
|
||||||
|
|
||||||
|
// Calculate vertical centering for header text
|
||||||
|
let headerTextY = chat.y + Math.floor((headerHeight + 4 - 11) / 2);
|
||||||
|
|
||||||
// Header text
|
// Header text
|
||||||
let headerTextCol = toColour(UI.accent.r, UI.accent.g, UI.accent.b, alpha);
|
let headerTextCol = toColour(UI.accent.r, UI.accent.g, UI.accent.b, alpha);
|
||||||
drawText("CHAT", chat.x + chat.padding, chat.y + 8, headerTextCol, 11);
|
drawText("CHAT", chat.x + chat.padding, headerTextY, headerTextCol, 11);
|
||||||
|
|
||||||
// Online count (placeholder - can be updated via network)
|
// Online count (placeholder - can be updated via network)
|
||||||
let onlineCol = toColour(UI.textSecondary.r, UI.textSecondary.g, UI.textSecondary.b, alpha);
|
let onlineCol = toColour(UI.textSecondary.r, UI.textSecondary.g, UI.textSecondary.b, alpha);
|
||||||
drawText("Press T to chat", chat.x + chat.width - 120, chat.y + 9, onlineCol, 9);
|
drawText("Press T to chat", chat.x + chat.width - 115, headerTextY + 1, onlineCol, chat.fontSize);
|
||||||
|
|
||||||
// Header bottom border
|
// Header bottom border
|
||||||
let headerBorder = toColour(UI.border.r, UI.border.g, UI.border.b, Math.floor(100 * chatFadeAlpha));
|
let headerBorder = toColour(UI.border.r, UI.border.g, UI.border.b, Math.floor(100 * chatFadeAlpha));
|
||||||
@@ -311,23 +339,27 @@ addEventHandler("OnDrawnHUD", function(event) {
|
|||||||
let msgColor = getMessageColor(msg.type);
|
let msgColor = getMessageColor(msg.type);
|
||||||
let textCol = toColour(msgColor.r, msgColor.g, msgColor.b, alpha);
|
let textCol = toColour(msgColor.r, msgColor.g, msgColor.b, alpha);
|
||||||
|
|
||||||
|
// Calculate vertical centering offset for text in message row
|
||||||
|
let textY = msgY + Math.floor((chat.messageHeight - chat.fontSize) / 2) - 2;
|
||||||
|
|
||||||
// Draw timestamp
|
// Draw timestamp
|
||||||
let time = new Date(msg.timestamp);
|
let time = new Date(msg.timestamp);
|
||||||
let timeStr = "[" + padZero(time.getHours()) + ":" + padZero(time.getMinutes()) + "]";
|
let timeStr = "[" + padZero(time.getHours()) + ":" + padZero(time.getMinutes()) + "]";
|
||||||
let timeCol = toColour(UI.textMuted.r, UI.textMuted.g, UI.textMuted.b, Math.floor(alpha * 0.7));
|
let timeCol = toColour(UI.textMuted.r, UI.textMuted.g, UI.textMuted.b, Math.floor(alpha * 0.7));
|
||||||
drawText(timeStr, chat.x + chat.padding, msgY, timeCol, 9);
|
drawText(timeStr, chat.x + chat.padding, textY, timeCol, chat.timestampSize);
|
||||||
|
|
||||||
// Draw message text
|
// Draw message text - timestamp takes approximately 50 pixels
|
||||||
let textX = chat.x + chat.padding + 55;
|
let textX = chat.x + chat.padding + 52;
|
||||||
|
|
||||||
if (msg.playerName && msg.type === "normal") {
|
if (msg.playerName && msg.type === "normal") {
|
||||||
// Player name in accent color
|
// Player name in accent color
|
||||||
let nameCol = toColour(UI.playerName.r, UI.playerName.g, UI.playerName.b, alpha);
|
let nameCol = toColour(UI.playerName.r, UI.playerName.g, UI.playerName.b, alpha);
|
||||||
drawText(msg.playerName + ":", textX, msgY, nameCol, 10);
|
drawText(msg.playerName + ":", textX, textY, nameCol, chat.fontSize);
|
||||||
// Message text
|
// Message text - use consistent character width calculation (6 pixels per char for size 10)
|
||||||
drawText(msg.text, textX + (msg.playerName.length * 7) + 12, msgY, textCol, 10);
|
let nameWidth = (msg.playerName.length + 1) * 6 + 8;
|
||||||
|
drawText(msg.text, textX + nameWidth, textY, textCol, chat.fontSize);
|
||||||
} else {
|
} else {
|
||||||
drawText(msg.text, textX, msgY, textCol, 10);
|
drawText(msg.text, textX, textY, textCol, chat.fontSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,15 +400,18 @@ addEventHandler("OnDrawnHUD", function(event) {
|
|||||||
drawRect(chat.x, inputY, 2, chat.inputHeight, inputBorder);
|
drawRect(chat.x, inputY, 2, chat.inputHeight, inputBorder);
|
||||||
drawRect(chat.x + chat.width - 2, inputY, 2, chat.inputHeight, inputBorder);
|
drawRect(chat.x + chat.width - 2, inputY, 2, chat.inputHeight, inputBorder);
|
||||||
|
|
||||||
// Input label
|
// Calculate vertical centering for input text
|
||||||
let labelCol = toColour(UI.textMuted.r, UI.textMuted.g, UI.textMuted.b, 255);
|
let inputTextY = inputY + Math.floor((chat.inputHeight - chat.inputFontSize) / 2) - 1;
|
||||||
drawText("Say:", chat.x + chat.padding, inputY + 10, labelCol, 10);
|
|
||||||
|
|
||||||
// Input text with cursor
|
// Input label "Say:" with consistent positioning
|
||||||
|
let labelCol = toColour(UI.textMuted.r, UI.textMuted.g, UI.textMuted.b, 255);
|
||||||
|
drawText("Say:", chat.x + chat.padding, inputTextY, labelCol, chat.inputFontSize);
|
||||||
|
|
||||||
|
// Input text with cursor - "Say:" takes about 30 pixels
|
||||||
let cursorBlink = Math.floor(animTime * 2) % 2 === 0;
|
let cursorBlink = Math.floor(animTime * 2) % 2 === 0;
|
||||||
let inputTextCol = toColour(UI.textPrimary.r, UI.textPrimary.g, UI.textPrimary.b, 255);
|
let inputTextCol = toColour(UI.textPrimary.r, UI.textPrimary.g, UI.textPrimary.b, 255);
|
||||||
let displayText = chatInputText + (cursorBlink ? "|" : "");
|
let displayText = chatInputText + (cursorBlink ? "|" : "");
|
||||||
drawText(displayText, chat.x + chat.padding + 40, inputY + 10, inputTextCol, 10);
|
drawText(displayText, chat.x + chat.padding + 36, inputTextY, inputTextCol, chat.inputFontSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================
|
// ========================================
|
||||||
@@ -467,6 +502,17 @@ function padZero(num) {
|
|||||||
return num < 10 ? "0" + num : num.toString();
|
return num < 10 ? "0" + num : num.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if player is spawned in game (not in lobby)
|
||||||
|
function checkIfPlayerInGame() {
|
||||||
|
try {
|
||||||
|
// localPlayer is null/undefined when player is not spawned (in lobby)
|
||||||
|
if (typeof localPlayer !== 'undefined' && localPlayer != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch(e) {}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// KEY CODE CONSTANTS (in case they're not predefined)
|
// KEY CODE CONSTANTS (in case they're not predefined)
|
||||||
// SDL key codes use ASCII values for letters (lowercase)
|
// SDL key codes use ASCII values for letters (lowercase)
|
||||||
@@ -484,7 +530,8 @@ const KEY_PAGEDOWN = typeof SDLK_PAGEDOWN !== 'undefined' ? SDLK_PAGEDOWN : 1073
|
|||||||
|
|
||||||
// Bind T key to open chat
|
// Bind T key to open chat
|
||||||
bindKey(KEY_T, KEYSTATE_UP, function(event) {
|
bindKey(KEY_T, KEYSTATE_UP, function(event) {
|
||||||
if (!chatInputActive) {
|
// Only allow opening chat if player is in game (not in lobby)
|
||||||
|
if (!chatInputActive && isPlayerInGame) {
|
||||||
openChatInput();
|
openChatInput();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -528,14 +575,12 @@ addEventHandler("OnKeyUp", function(event, key, scancode, mods) {
|
|||||||
// Escape to close chat
|
// Escape to close chat
|
||||||
if ((key === KEY_ESCAPE || key === SDLK_ESCAPE) && chatInputActive) {
|
if ((key === KEY_ESCAPE || key === SDLK_ESCAPE) && chatInputActive) {
|
||||||
closeChatInput();
|
closeChatInput();
|
||||||
event.preventDefault();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enter to send message
|
// Enter to send message
|
||||||
if ((key === KEY_RETURN || key === SDLK_RETURN) && chatInputActive) {
|
if ((key === KEY_RETURN || key === SDLK_RETURN) && chatInputActive) {
|
||||||
sendChatMessage();
|
sendChatMessage();
|
||||||
event.preventDefault();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -559,7 +604,7 @@ addEventHandler("OnCharacter", function(event, character) {
|
|||||||
if (character.charCodeAt(0) >= 32) {
|
if (character.charCodeAt(0) >= 32) {
|
||||||
chatInputText += character;
|
chatInputText += character;
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
// Note: OnCharacter event is not cancellable in GTA Connected
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -569,11 +614,8 @@ addEventHandler("OnKeyDown", function(event, key, scancode, mods) {
|
|||||||
// Backspace
|
// Backspace
|
||||||
if ((key === KEY_BACKSPACE || key === SDLK_BACKSPACE) && chatInputText.length > 0) {
|
if ((key === KEY_BACKSPACE || key === SDLK_BACKSPACE) && chatInputText.length > 0) {
|
||||||
chatInputText = chatInputText.slice(0, -1);
|
chatInputText = chatInputText.slice(0, -1);
|
||||||
event.preventDefault();
|
|
||||||
}
|
}
|
||||||
|
// Note: OnKeyDown event is not cancellable in GTA Connected
|
||||||
// Block other keys from reaching the game while typing
|
|
||||||
event.preventDefault();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -627,9 +669,9 @@ addEventHandler("OnResourceReady", function(event, resource) {
|
|||||||
console.log("[Chat] Could not disable default chat: " + e);
|
console.log("[Chat] Could not disable default chat: " + e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a test message to verify the chat is working
|
// Add a welcome message - will only show when player is in game
|
||||||
addChatMessage("Custom chat loaded! Press T to type.", "system");
|
addChatMessage("Revolution chat loaded! Press T to type.", "system");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("[Chat] Client script loaded - Custom glossy UI enabled");
|
console.log("[Chat] Revolution chat loaded - Custom glossy UI enabled");
|
||||||
|
|||||||
@@ -41,14 +41,10 @@ addEventHandler("OnResourceStart", function(event, resource) {
|
|||||||
|
|
||||||
addEventHandler("OnPlayerJoined", function(event, client) {
|
addEventHandler("OnPlayerJoined", function(event, client) {
|
||||||
// Broadcast join notification to all clients
|
// Broadcast join notification to all clients
|
||||||
let joinData = {
|
// Send player name directly for better compatibility
|
||||||
name: client.name
|
|
||||||
};
|
|
||||||
|
|
||||||
// Send to all connected clients
|
|
||||||
let clients = getClients();
|
let clients = getClients();
|
||||||
for (let i = 0; i < clients.length; i++) {
|
for (let i = 0; i < clients.length; i++) {
|
||||||
triggerNetworkEvent("playerJoined", clients[i], joinData);
|
triggerNetworkEvent("playerJoined", clients[i], client.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log to console
|
// Log to console
|
||||||
@@ -63,15 +59,11 @@ addEventHandler("OnPlayerQuit", function(event, client, reason) {
|
|||||||
let reasonText = getDisconnectReason(reason);
|
let reasonText = getDisconnectReason(reason);
|
||||||
|
|
||||||
// Broadcast leave notification to all remaining clients
|
// Broadcast leave notification to all remaining clients
|
||||||
let leaveData = {
|
// Send individual parameters for better compatibility
|
||||||
name: client.name,
|
|
||||||
reason: reasonText
|
|
||||||
};
|
|
||||||
|
|
||||||
let clients = getClients();
|
let clients = getClients();
|
||||||
for (let i = 0; i < clients.length; i++) {
|
for (let i = 0; i < clients.length; i++) {
|
||||||
if (clients[i].index !== client.index) {
|
if (clients[i].index !== client.index) {
|
||||||
triggerNetworkEvent("playerLeft", clients[i], leaveData);
|
triggerNetworkEvent("playerLeft", clients[i], client.name, reasonText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,15 +94,10 @@ function getDisconnectReason(reason) {
|
|||||||
|
|
||||||
addEventHandler("OnPlayerChat", function(event, client, messageText) {
|
addEventHandler("OnPlayerChat", function(event, client, messageText) {
|
||||||
// Broadcast to all clients via custom network event
|
// Broadcast to all clients via custom network event
|
||||||
let chatData = {
|
// Send individual parameters for better compatibility
|
||||||
text: messageText,
|
|
||||||
type: "normal",
|
|
||||||
playerName: client.name
|
|
||||||
};
|
|
||||||
|
|
||||||
let clients = getClients();
|
let clients = getClients();
|
||||||
for (let i = 0; i < clients.length; i++) {
|
for (let i = 0; i < clients.length; i++) {
|
||||||
triggerNetworkEvent("chatMessage", clients[i], chatData);
|
triggerNetworkEvent("chatMessage", clients[i], messageText, "normal", client.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log to history
|
// Log to history
|
||||||
@@ -124,6 +111,8 @@ addEventHandler("OnPlayerChat", function(event, client, messageText) {
|
|||||||
addNetworkHandler("chatSendMessage", function(client, messageText) {
|
addNetworkHandler("chatSendMessage", function(client, messageText) {
|
||||||
if (!messageText || messageText.length === 0) return;
|
if (!messageText || messageText.length === 0) return;
|
||||||
|
|
||||||
|
console.log("[Chat] Received message from " + client.name + ": " + messageText);
|
||||||
|
|
||||||
// Check if it's a command
|
// Check if it's a command
|
||||||
if (messageText.charAt(0) === '/') {
|
if (messageText.charAt(0) === '/') {
|
||||||
// Parse command
|
// Parse command
|
||||||
@@ -136,15 +125,10 @@ addNetworkHandler("chatSendMessage", function(client, messageText) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Regular chat message - broadcast to all clients
|
// Regular chat message - broadcast to all clients
|
||||||
let chatData = {
|
// Send individual parameters for better compatibility
|
||||||
text: messageText,
|
|
||||||
type: "normal",
|
|
||||||
playerName: client.name
|
|
||||||
};
|
|
||||||
|
|
||||||
let clients = getClients();
|
let clients = getClients();
|
||||||
for (let i = 0; i < clients.length; i++) {
|
for (let i = 0; i < clients.length; i++) {
|
||||||
triggerNetworkEvent("chatMessage", clients[i], chatData);
|
triggerNetworkEvent("chatMessage", clients[i], messageText, "normal", client.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log to history
|
// Log to history
|
||||||
@@ -250,26 +234,16 @@ function handleCommand(client, cmd, params) {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
function broadcastChatMessage(text, type, senderName) {
|
function broadcastChatMessage(text, type, senderName) {
|
||||||
let chatData = {
|
// Send individual parameters for better compatibility
|
||||||
text: text,
|
|
||||||
type: type || "normal",
|
|
||||||
playerName: senderName || null
|
|
||||||
};
|
|
||||||
|
|
||||||
let clients = getClients();
|
let clients = getClients();
|
||||||
for (let i = 0; i < clients.length; i++) {
|
for (let i = 0; i < clients.length; i++) {
|
||||||
triggerNetworkEvent("chatMessage", clients[i], chatData);
|
triggerNetworkEvent("chatMessage", clients[i], text, type || "normal", senderName || "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendChatMessage(client, text, type, playerName) {
|
function sendChatMessage(client, text, type, playerName) {
|
||||||
let chatData = {
|
// Send individual parameters for better compatibility
|
||||||
text: text,
|
triggerNetworkEvent("chatMessage", client, text, type || "normal", playerName || "");
|
||||||
type: type || "normal",
|
|
||||||
playerName: playerName || null
|
|
||||||
};
|
|
||||||
|
|
||||||
triggerNetworkEvent("chatMessage", client, chatData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendSystemMessage(client, text) {
|
function sendSystemMessage(client, text) {
|
||||||
|
|||||||
Reference in New Issue
Block a user