").append(m.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},m.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){m.fn[b]=function(a){return this.on(b,a)}}),m.expr.filters.animated=function(a){return m.grep(m.timers,function(b){return a===b.elem}).length};var cc=a.document.documentElement;function dc(a){return m.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}m.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=m.css(a,"position"),l=m(a),n={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=m.css(a,"top"),i=m.css(a,"left"),j=("absolute"===k||"fixed"===k)&&m.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),m.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(n.top=b.top-h.top+g),null!=b.left&&(n.left=b.left-h.left+e),"using"in b?b.using.call(a,n):l.css(n)}},m.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){m.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,m.contains(b,e)?(typeof e.getBoundingClientRect!==K&&(d=e.getBoundingClientRect()),c=dc(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===m.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),m.nodeName(a[0],"html")||(c=a.offset()),c.top+=m.css(a[0],"borderTopWidth",!0),c.left+=m.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-m.css(d,"marginTop",!0),left:b.left-c.left-m.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||cc;while(a&&!m.nodeName(a,"html")&&"static"===m.css(a,"position"))a=a.offsetParent;return a||cc})}}),m.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);m.fn[a]=function(d){return V(this,function(a,d,e){var f=dc(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?m(f).scrollLeft():e,c?e:m(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),m.each(["top","left"],function(a,b){m.cssHooks[b]=La(k.pixelPosition,function(a,c){return c?(c=Ja(a,b),Ha.test(c)?m(a).position()[b]+"px":c):void 0})}),m.each({Height:"height",Width:"width"},function(a,b){m.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){m.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return V(this,function(b,c,d){var e;return m.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?m.css(b,c,g):m.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),m.fn.size=function(){return this.length},m.fn.andSelf=m.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return m});var ec=a.jQuery,fc=a.$;return m.noConflict=function(b){return a.$===m&&(a.$=fc),b&&a.jQuery===m&&(a.jQuery=ec),m},typeof b===K&&(a.jQuery=a.$=m),m});
diff --git a/ReallifeGamemode.Client/assets/chat/js/main.js b/ReallifeGamemode.Client/assets/chat/js/main.js
new file mode 100644
index 00000000..aace5512
--- /dev/null
+++ b/ReallifeGamemode.Client/assets/chat/js/main.js
@@ -0,0 +1,189 @@
+let chat =
+{
+ size: 0,
+ history_limit: 50,
+ container: null,
+ input: null,
+ enabled: false,
+ active: true,
+ historyMsgs: [],
+ currentIndex: 0
+};
+
+const MAX_MSG_HISTORY = 36;
+
+function enableChatInput(enable)
+{
+ if(chat.active == false
+ && enable == true)
+ return;
+
+ if (enable != (chat.input != null))
+ {
+ mp.invoke("focus", enable);
+
+ if (enable)
+ {
+ chat.input = $("#chat").append('
').children(":last");
+ chat.input.children("input").focus();
+ }
+ else
+ {
+ chat.input.fadeOut('fast', function()
+ {
+ chat.input.remove();
+ chat.input = null;
+ });
+ }
+ }
+}
+
+var chatAPI =
+{
+ push: (text) =>
+ {
+ let colorPositions = [];
+ let colors = [];
+ let chatElement = "
";
+
+ for (let i = 0; i {
+ let sub = text.slice(el, -1);
+ colors.push(sub.slice(3, 9));
+ });
+
+ colorPositions.forEach((el, i) => {
+ let sub = text.slice(colorPositions[i] + 10, colorPositions[i + 1]);
+ chatElement += `${sub}`;
+ });
+
+ chatElement += "";
+
+ if (chatElement === "
") {
+ chat.container.prepend("
" + text + "");
+ } else {
+ chat.container.prepend(chatElement);
+ }
+
+ chat.size++;
+
+ if (chat.size >= chat.history_limit)
+ {
+ chat.container.children(":last").remove();
+ }
+ },
+
+ clear: () =>
+ {
+ chat.container.html("");
+ },
+
+ activate: (toggle) =>
+ {
+ if (toggle == false
+ && (chat.input != null))
+ enableChatInput(false);
+
+ chat.active = toggle;
+ },
+
+ show: (toggle) =>
+ {
+ if(toggle)
+ $("#chat").show();
+ else
+ $("#chat").hide();
+
+ chat.active = toggle;
+ }
+};
+
+$(document).ready(function()
+{
+ chat.container = $("#chat ul#chat_messages");
+
+ $(".ui_element").show();
+ chatAPI.push("Multiplayer started");
+
+ $("body").keyup(function(event)
+ {
+ if (event.which == 84 && chat.input == null
+ && chat.active == true)
+ {
+ chat.currentIndex = 0;
+ enableChatInput(true);
+ event.preventDefault();
+ } else if (event.which == 38) {
+ if (chat.historyMsgs.length === 0)
+ return;
+
+ const previousMessages = chat.historyMsgs;
+
+ if (previousMessages.length === chat.currentIndex)
+ return;
+
+
+ chat.input.children("input").val(previousMessages[chat.currentIndex]);
+
+ setTimeout(() => {
+ chat.input.children("input").setSelectionRange(previousMessages[chat.currentIndex].length, previousMessages[chat.currentIndex].length);
+ }, 1);
+
+ chat.currentIndex = chat.currentIndex + 1;
+
+
+ } else if (event.which == 40) {
+ if (chat.historyMsgs.length === 0)
+ return;
+
+ const previousMessages = chat.historyMsgs;
+
+ if (chat.currentIndex === -1) {
+ chat.input.children("input").val("")
+ return;
+ }
+
+ chat.currentIndex = chat.currentIndex - 1;
+ chat.input.children("input").val(previousMessages[chat.currentIndex]);
+
+ setTimeout(() => {
+ chat.input.children("input").setSelectionRange(previousMessages[chat.currentIndex].length, previousMessages[chat.currentIndex].length);
+ }, 1);
+ }
+ else if (event.which == 13 && chat.input != null)
+ {
+ var value = chat.input.children("input").val();
+
+ if (value.length > 0)
+ {
+ if (chat.historyMsgs.length >= MAX_MSG_HISTORY) {
+ chat.historyMsgs.pop();
+ }
+
+ chat.historyMsgs.unshift(value);
+ chat.currentIndex = 0;
+
+ if (value[0] == "/")
+ {
+ value = value.substr(1);
+
+ if (value.length > 0)
+ mp.invoke("command", value);
+ }
+ else
+ {
+ mp.invoke("chatMessage", value);
+ }
+ }
+
+ enableChatInput(false);
+ }
+ });
+});
\ No newline at end of file
diff --git a/ReallifeGamemode.Client/assets/chat/style/checkbox.css b/ReallifeGamemode.Client/assets/chat/style/checkbox.css
new file mode 100644
index 00000000..53fddb26
--- /dev/null
+++ b/ReallifeGamemode.Client/assets/chat/style/checkbox.css
@@ -0,0 +1 @@
+input[type=checkbox].css-checkbox{position:absolute;z-index:-1000;left:-1000px;overflow:hidden;clip:rect(0 0 0 0);height:1px;width:1px;margin:-1px;padding:0;border:0;}input[type=checkbox].css-checkbox+label.css-label{height:20px;width:20px;display:inline-block;background-repeat:no-repeat;background-position:0 0;cursor:pointer;}input[type=checkbox].css-checkbox:checked+label.css-label:after{content:'x';color:white;}label.css-label{background:#7b3784;border-radius:2px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}
\ No newline at end of file
diff --git a/ReallifeGamemode.Client/assets/chat/style/main.css b/ReallifeGamemode.Client/assets/chat/style/main.css
new file mode 100644
index 00000000..7e5afe51
--- /dev/null
+++ b/ReallifeGamemode.Client/assets/chat/style/main.css
@@ -0,0 +1,68 @@
+*,body,html{
+ padding:0;
+ margin:0}
+#chat,a,body,html{
+ color:#fff
+}
+body,html{
+ -webkit-font-smoothing:antialiased;
+ overflow:hidden;
+ font-size:14px;
+ -webkit-user-select:none
+}
+a{
+ text-decoration:none
+}
+.ui_element{
+ display:none;position:absolute;
+ width:100vw;height:100vh;z-index:2
+}
+#chat{
+ display:block;
+ z-index:0;
+ line-height:24px;
+ font-weight:700;
+ text-shadow:1px 1px 0 #000,-1px -1px 0 #000,1px -1px 0 #000,-1px 1px 0 #000,1px 1px 0 #000;
+ font-family:Myriad Pro,Segoe UI,Verdana,sans-serif;
+ font-size:16px;
+ letter-spacing:.4px;
+ margin-left:15px
+
+}
+@media screen and (min-height:1080px){
+
+#chat{
+ font-size:18px!important;
+ font-weight:700}}
+#chat ul#chat_messages{
+ overflow-y:auto;
+ height:285px;
+ margin-top:2vh; /*2vh*/
+ transform:rotate(180deg);
+ /*width:37vw; /* old: 37vw*/
+ width: 800px;
+ padding:10px 20px; /* old padding: 10px 20px*/
+ list-style-type:none}
+#chat ul#chat_messages>li{
+ transform:rotate(-180deg)}
+#chat input#chat_msg{
+ color:#fff;
+ background:rgba(0,0,0,.5);
+ outline:0;border:none;
+ font-family:Myriad Pro,Open Sans,sans-serif;
+ font-size:13px;
+ line-height:35px;
+ width:35vw;
+ padding:5px 5px 5px 15px}
+::-webkit-scrollbar{
+ width:11px;
+}
+::-webkit-scrollbar-thumb{
+ background:rgba(255, 17, 0, 0.3);
+ border-radius:20px
+
+}
+::-webkit-scrollbar-thumb:hover{
+ background: rgba(255, 17, 0, 0.65)
+
+}
\ No newline at end of file
diff --git a/ReallifeGamemode.Client/index.ts b/ReallifeGamemode.Client/index.ts
index 70a08959..91d6b678 100644
--- a/ReallifeGamemode.Client/index.ts
+++ b/ReallifeGamemode.Client/index.ts
@@ -7,6 +7,12 @@
import { IGame } from './game';
import RageGame from './core/rage-mp/game';
+// Disables default RageMP Chat
+mp.gui.chat.show(false);
+
+// Initialize chatbox CEF, mark it as default server chat
+const chatbox = mp.browsers.new('package://assets/chat/index.html');
+chatbox.markAsChat();
var inMenu: boolean = false;