gimmickCellar

ComuChat

Mar 28th, 2026
36
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.63 KB | None | 0 0
  1. (function() {
  2. // Prevent multiple initializations
  3. if (window._comuChatInstalled) return;
  4. window._comuChatInstalled = true;
  5.  
  6. // Instruct the server to send us `cmd` broadcast messages
  7. // (In case the user hasn't received them yet)
  8. OWOT.broadcastReceive(true);
  9.  
  10. // ==========================================
  11. // 1. Create the Custom UI Elements
  12. // ==========================================
  13. const chatUpper = document.getElementById("chat_upper");
  14. const chatWindow = document.getElementById("chat_window");
  15. const chatLower = document.getElementById("chat_lower");
  16. const usrOnline = document.getElementById("usr_online");
  17.  
  18. // Create the Tab
  19. const comuTab = document.createElement("div");
  20. comuTab.className = "chat_tab_button";
  21. comuTab.id = "chat_comu_tab";
  22. comuTab.innerHTML = 'Comu<b id="comu_unread" class="unread" style="display: none;">(-)</b>';
  23.  
  24. // Create the Chat Field container
  25. const comuField = document.createElement("div");
  26. comuField.className = "chatfield";
  27. comuField.id = "comu_chatfield";
  28. comuField.style.display = "none";
  29.  
  30. // Inject into OWOT's DOM
  31. chatUpper.insertBefore(comuTab, usrOnline);
  32. chatWindow.insertBefore(comuField, chatLower);
  33.  
  34. let isComuActive = false;
  35. let comuUnreadCount = 0;
  36. const comuUnreadElm = document.getElementById("comu_unread");
  37.  
  38. function updateComuUnread() {
  39. if(isComuActive || comuUnreadCount === 0) {
  40. comuUnreadElm.style.display = "none";
  41. comuUnreadCount = 0;
  42. } else {
  43. comuUnreadElm.style.display = "";
  44. comuUnreadElm.innerText = comuUnreadCount > 99 ? "99+" : `(${comuUnreadCount})`;
  45. }
  46. }
  47.  
  48. // ==========================================
  49. // 2. Handle Tab Switching Logic
  50. // ==========================================
  51. const pageTab = document.getElementById("chat_page_tab");
  52. const globalTab = document.getElementById("chat_global_tab");
  53.  
  54. comuTab.addEventListener("click", function() {
  55. isComuActive = true;
  56.  
  57. // Update tab visuals
  58. comuTab.classList.add("chat_tab_selected");
  59. pageTab.classList.remove("chat_tab_selected");
  60. globalTab.classList.remove("chat_tab_selected");
  61.  
  62. // Swap chatfields
  63. comuField.style.display = "";
  64. document.getElementById("page_chatfield").style.display = "none";
  65. document.getElementById("global_chatfield").style.display = "none";
  66.  
  67. updateComuUnread();
  68. comuField.scrollTop = comuField.scrollHeight; // Snap to bottom
  69. });
  70.  
  71. // Make sure we un-select the custom tab if native tabs are clicked
  72. pageTab.addEventListener("click", () => {
  73. isComuActive = false;
  74. comuField.style.display = "none";
  75. comuTab.classList.remove("chat_tab_selected");
  76. });
  77. globalTab.addEventListener("click", () => {
  78. isComuActive = false;
  79. comuField.style.display = "none";
  80. comuTab.classList.remove("chat_tab_selected");
  81. });
  82.  
  83. // ==========================================
  84. // 3. Intercept Outgoing Chat Messages
  85. // ==========================================
  86. OWOT.on("chatSend", function(e) {
  87. if(isComuActive) {
  88. e.cancel = true; // Stop native chat from sending
  89.  
  90. let msg = e.message.trim();
  91. if(!msg) return;
  92.  
  93. // Respect the user's selected chat color
  94. let colorInt = window.defaultChatColor !== null ? window.defaultChatColor : YourWorld.Color;
  95. let colorHex = "#" + ("000000" + colorInt.toString(16)).slice(-6);
  96.  
  97. // Construct payload
  98. let payload = JSON.stringify({
  99. type: "comu_chat",
  100. msg: msg,
  101. color: colorHex
  102. });
  103.  
  104. // Broadcast over OWOT's `cmd` network protocol
  105. // true = Tells server to append the sender's username & ID natively
  106. OWOT.broadcastCommand(payload, true);
  107.  
  108. // Clear input
  109. document.getElementById("chatbar").value = "";
  110. }
  111. });
  112.  
  113. // Helper: Prevent XSS in chat
  114. function escapeHtml(text) {
  115. let map = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#039;' };
  116. return text.replace(/[&<>"']/g, function(m) { return map[m]; });
  117. }
  118.  
  119. // ==========================================
  120. // 4. Handle Incoming Comu Messages
  121. // ==========================================
  122. OWOT.on("cmd", function(e) {
  123. try {
  124. let data = JSON.parse(e.data);
  125. if(data.type === "comu_chat") {
  126. renderComuMessage(e.id, e.username, data.msg, data.color);
  127.  
  128. // Update unread counter if tab isn't active
  129. if(!isComuActive) {
  130. comuUnreadCount++;
  131. updateComuUnread();
  132. }
  133. }
  134. } catch(err) {
  135. // Not a valid JSON or not our protocol, safely ignore
  136. }
  137. });
  138.  
  139. // ==========================================
  140. // 5. Custom Renderer
  141. // ==========================================
  142. function renderComuMessage(id, username, msg, color) {
  143. let chatGroup = document.createElement("div");
  144.  
  145. // Nickname wrapper
  146. let nickDom = document.createElement("span");
  147. nickDom.style.fontWeight = "bold";
  148. nickDom.style.color = color || "#000000";
  149.  
  150. let safeUsername = escapeHtml(username || "Anonymous");
  151. let safeMsg = escapeHtml(msg);
  152.  
  153. // Add ID tags just like native chat
  154. let idTag = id ? `[${id}] ` : "";
  155. nickDom.innerHTML = idTag + safeUsername + ": ";
  156.  
  157. // Message wrapper
  158. let msgDom = document.createElement("span");
  159. msgDom.innerHTML = safeMsg;
  160.  
  161. chatGroup.appendChild(nickDom);
  162. chatGroup.appendChild(msgDom);
  163.  
  164. // Calculate scroll behavior (snap to bottom if they already are at bottom)
  165. let isAtBottom = (comuField.scrollHeight - comuField.scrollTop - comuField.clientHeight) < 20;
  166.  
  167. comuField.appendChild(chatGroup);
  168.  
  169. if(isAtBottom || isComuActive) {
  170. comuField.scrollTop = comuField.scrollHeight;
  171. }
  172.  
  173. // Limit history to prevent DOM memory leaks
  174. if(comuField.children.length > 500) {
  175. comuField.removeChild(comuField.firstChild);
  176. }
  177. }
  178.  
  179. console.log("Custom Comu Chat Protocol successfully initialized.");
  180. })();
Advertisement
Add Comment
Please, Sign In to add comment