From c4c299f701c546c019df447d25ced573eb45adf6 Mon Sep 17 00:00:00 2001 From: Benjamin Kraft Date: Mon, 20 Mar 2023 14:24:04 +0100 Subject: [PATCH] Working setup --- .gitignore | 1 + project.json | 6 + public/changelog.txt | 55 +++ public/data/images/favicon.ico | Bin 0 -> 318 bytes public/data/lib/benjocraeft/collision.js | 53 +++ public/data/lib/benjocraeft/colorPicker.js | 337 ++++++++++++++++ public/data/lib/benjocraeft/cookie.js | 29 ++ public/data/lib/benjocraeft/loader.js | 30 ++ public/data/lib/benjocraeft/prototypes.js | 30 ++ public/data/lib/benjocraeft/technical.js | 48 +++ public/data/scripts/drawer.js | 395 +++++++++++++++++++ public/data/scripts/events.js | 81 ++++ public/data/scripts/init.js | 125 ++++++ public/data/scripts/minimap.js | 67 ++++ public/data/scripts/online.js | 82 ++++ public/data/settings/get_port.php | 3 + public/data/settings/libraries.json | 8 + public/data/settings/settings.json | 22 ++ public/data/styles/color_picker.css | 76 ++++ public/data/styles/font.ttf | Bin 0 -> 30420 bytes public/data/styles/range_input.css | 86 +++++ public/index.html | 109 ++++++ public/styles.css | 226 +++++++++++ public/thumbnail.png | Bin 0 -> 175149 bytes server/.gitignore | 5 + server/package-lock.json | 424 +++++++++++++++++++++ server/package.json | 17 + server/src/client.ts | 169 ++++++++ server/src/definitions/serialized.d.ts | 20 + server/src/definitions/settings.d.ts | 29 ++ server/src/game_standard.ts | 38 ++ server/src/global_draw.ts | 149 ++++++++ server/src/index.ts | 7 + server/src/logger.ts | 105 +++++ server/src/manager.ts | 149 ++++++++ server/src/room.ts | 136 +++++++ server/src/start.ts | 39 ++ server/tsconfig.json | 11 + 38 files changed, 3167 insertions(+) create mode 100644 .gitignore create mode 100644 project.json create mode 100644 public/changelog.txt create mode 100644 public/data/images/favicon.ico create mode 100644 public/data/lib/benjocraeft/collision.js create mode 100644 public/data/lib/benjocraeft/colorPicker.js create mode 100644 public/data/lib/benjocraeft/cookie.js create mode 100644 public/data/lib/benjocraeft/loader.js create mode 100644 public/data/lib/benjocraeft/prototypes.js create mode 100644 public/data/lib/benjocraeft/technical.js create mode 100644 public/data/scripts/drawer.js create mode 100644 public/data/scripts/events.js create mode 100644 public/data/scripts/init.js create mode 100644 public/data/scripts/minimap.js create mode 100644 public/data/scripts/online.js create mode 100644 public/data/settings/get_port.php create mode 100644 public/data/settings/libraries.json create mode 100644 public/data/settings/settings.json create mode 100644 public/data/styles/color_picker.css create mode 100644 public/data/styles/font.ttf create mode 100644 public/data/styles/range_input.css create mode 100644 public/index.html create mode 100644 public/styles.css create mode 100644 public/thumbnail.png create mode 100644 server/.gitignore create mode 100644 server/package-lock.json create mode 100644 server/package.json create mode 100644 server/src/client.ts create mode 100644 server/src/definitions/serialized.d.ts create mode 100644 server/src/definitions/settings.d.ts create mode 100644 server/src/game_standard.ts create mode 100644 server/src/global_draw.ts create mode 100644 server/src/index.ts create mode 100644 server/src/logger.ts create mode 100644 server/src/manager.ts create mode 100644 server/src/room.ts create mode 100644 server/src/start.ts create mode 100644 server/tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..723ef36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/project.json b/project.json new file mode 100644 index 0000000..35c0908 --- /dev/null +++ b/project.json @@ -0,0 +1,6 @@ +{ + "display_name": "Global draw sheet", + "info_text": "A draw sheet for everyone.", + "visible": true, + "tags": ["Tool", "Multiplayer"] +} \ No newline at end of file diff --git a/public/changelog.txt b/public/changelog.txt new file mode 100644 index 0000000..ab00d57 --- /dev/null +++ b/public/changelog.txt @@ -0,0 +1,55 @@ +1.0.0 > - Started versioning + - Contents: + - ColorPicker + - Color pick from screen + - Thickness range input + - Thickness preview + - Minimap + - Two Modes: + - Draw Freely (lines) + - Pixel Art + - Disabled browser scrolling, added own scrolling via mousewheel + +1.0.1 > - Made changelog.txt public + +1.1.0 > - Changed Graphics resolution from 8000/8000 to 5000/5000 + - Changed pixel count for pixel art mode from 250 to 500 + - Added Skip Button for first drawing + - Inverted progress bar :D + - Added Button to request server save of drawings + +1.1.1 > - Enabled button usability feedback + +1.2.0 > - Disabled grid for pixel art + - Added hotkey for new alpha "grid" + +1.2.1 > - Changed pixel count for pixel art mode from 500 to 1000 + - Activated anti aliasing for free mode, deactivated for pixel mode + - Color copy ignores alpha grid + +1.2.2 > - Seperated settings for free mode and pixel mode + - Added hotkey set for pixel grid (defaults to 'G') + - Hotkey for pixel grid loads from session data + +1.2.3 > - ColorPicker displays a list of recently used colors + - Recently used colors are also loaded from site session data + +1.2.4 > - Recently used color defaults to white instead of black + +1.2.5 > - Made hotkey feature more understandable -_- + +1.2.6 > - 3-digit hex values for ColorPicker instantly convert to 6-digit values + +1.2.7 > - Enabled moving also with w,a,s,d + +1.2.8 > - Updated downloadable zip with newest contents + +1.2.9 > - Better Loading screen and bug fixes + +1.2.10 > - Nicer selection rectangle borders on minimap + +1.2.11 > - Zooming via mousewheel works much better now and is relative to mouse position + +1.2.12 > - Enabled user feedback :) + +1.2.13 > - Loading works much faster now!!! \ No newline at end of file diff --git a/public/data/images/favicon.ico b/public/data/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..3172667d2925fa58eae7e1b1767b3ef11fd8a37d GIT binary patch literal 318 zcmbtPISzm@408$tW3n(;o%&2Z!e96lGuRxJU_-b{+&XoX0LJ6)%sr|BBY?_qMrKGC zrX!z8wT5*7=B+({UrNd9k;oR|sc?pfNL0=7}mX3RI=dX}Q F-W`Jp3Z(!5 literal 0 HcmV?d00001 diff --git a/public/data/lib/benjocraeft/collision.js b/public/data/lib/benjocraeft/collision.js new file mode 100644 index 0000000..3941d1d --- /dev/null +++ b/public/data/lib/benjocraeft/collision.js @@ -0,0 +1,53 @@ +'use strict'; + +/* + 2D Collision detection and performing +*/ + +class Collision{ + + static ellipseToEllipse(e1, e2){ + + //Colliding angle of ball 1 to ball 2 using arc tan of both x and y differences + let collisionAngle = Math.atan2((e2.pos.y - e1.pos.y), (e2.pos.x - e1.pos.x)); + + //Converting directions of velocity vector of balls into angles + let d1 = Math.atan2(e1.vel.y, e1.vel.x); + let d2 = Math.atan2(e2.vel.y, e2.vel.x); + + //Ignoring mass effects new velocites are simply magnitude multiplied with value of angle differences + let newXspeed1 = e1.vel.mag() * Math.cos(d1 - collisionAngle); + let newYspeed1 = e1.vel.mag() * Math.sin(d1 - collisionAngle); + let newXspeed2 = e2.vel.mag() * Math.cos(d2 - collisionAngle); + let newYspeed2 = e2.vel.mag() * Math.sin(d2 - collisionAngle); + + //According to the principle of linear momentum, kinetic energy stays the same after collision, so velocities are now related to masses + let finalXspeed1 = ((e1.radius - e2.radius) * newXspeed1 + e2.radius * 2 * newXspeed2) / (e1.radius + e2.radius); + let finalYspeed1 = newYspeed1; + let finalXspeed2 = (e1.radius * 2 * newXspeed1 + (e2.radius - e1.radius) * newXspeed2) / (e1.radius + e2.radius); + let finalYspeed2 = newYspeed2; + + //Values of collisionAngle + let cosAngle = Math.cos(collisionAngle); + let sinAngle = Math.sin(collisionAngle); + + //To also keep velocites relative to pure collisionAngle, subtract sin*x from cos*x and add sin*y to cos*y because coordSystem has y = 0 on the top + let u1x = cosAngle * finalXspeed1 - sinAngle * finalYspeed1; + let u1y = sinAngle * finalXspeed1 + cosAngle * finalYspeed1; + let u2x = cosAngle * finalXspeed2 - sinAngle * finalYspeed2; + let u2y = sinAngle * finalXspeed2 + cosAngle * finalYspeed2; + + //Set new velocities to both balls + e1.vel.x = u1x; + e1.vel.y = u1y; + e2.vel.x = u2x; + e2.vel.y = u2y; + + //Move balls one vx/vy forward to avoid double inverting collision detection + e1.pos.x += e1.vel.x; + e1.pos.y += e1.vel.y; + e2.pos.x += e2.vel.x; + e2.pos.y += e2.vel.y; + } + +} \ No newline at end of file diff --git a/public/data/lib/benjocraeft/colorPicker.js b/public/data/lib/benjocraeft/colorPicker.js new file mode 100644 index 0000000..328922b --- /dev/null +++ b/public/data/lib/benjocraeft/colorPicker.js @@ -0,0 +1,337 @@ +class ColorPicker { + + constructor(){ + this.movingObject = ""; + } + + updateFromGraphical(){ + this.h = (1 - $("#hue_picker").position().top / $("#hue").height()) * 360; + this.s = ($("#sb_picker").position().left + 8) / $("#saturation").width() * 100; + this.v = (1 - ($("#sb_picker").position().top + 8) / $("#value").height()) * 100; + + this.r = HSVtoRGB(this.h, this.s, this.v).r; + this.g = HSVtoRGB(this.h, this.s, this.v).g; + this.b = HSVtoRGB(this.h, this.s, this.v).b; + + this.hex = RGBtoHEX(this.r, this.g, this.b); + + this.updateInterface(); + } + + updateFromHSV(){ + this.h = $($("#color_picker_hsv input")[0]).val(); + this.s = $($("#color_picker_hsv input")[1]).val(); + this.v = $($("#color_picker_hsv input")[2]).val(); + + this.r = HSVtoRGB(this.h, this.s, this.v).r; + this.g = HSVtoRGB(this.h, this.s, this.v).g; + this.b = HSVtoRGB(this.h, this.s, this.v).b; + + this.hex = RGBtoHEX(this.r, this.g, this.b); + + this.updateFromHEX(null, true); + + this.updateInterface(); + } + + updateFromRGB(rgba){ + if (rgba){ + this.r = rgba[0]; + this.g = rgba[1]; + this.b = rgba[2]; + } else { + this.r = $($("#color_picker_rgb input")[0]).val(); + this.g = $($("#color_picker_rgb input")[1]).val(); + this.b = $($("#color_picker_rgb input")[2]).val(); + } + + + this.h = RGBtoHSV(this.r, this.g, this.b).h; + this.s = RGBtoHSV(this.r, this.g, this.b).s; + this.v = RGBtoHSV(this.r, this.g, this.b).v; + + this.hex = RGBtoHEX(this.r, this.g, this.b); + + this.updateFromHEX(null, true); + + this.updateInterface(); + } + + updateFromHEX(input, otf){ + if (!otf){ //Not on the fly + if ($(input).val().isValidHEX()) this.hex = $(input).val(); + else { + alert("Error!"); + return; + } + } + + this.r = HEXtoRGB(this.hex).r; + this.g = HEXtoRGB(this.hex).g; + this.b = HEXtoRGB(this.hex).b; + + this.h = RGBtoHSV(this.r, this.g, this.b).h; + this.s = RGBtoHSV(this.r, this.g, this.b).s; + this.v = RGBtoHSV(this.r, this.g, this.b).v; + + this.hex = RGBtoHEX(this.r, this.g, this.b); + + this.updateInterface(); + } + + setFromUsed(used){ + let usedColorsData = p.getItem('usedColors'); + let index = $('.used_color').toArray().reverse().indexOf(used); + let color = usedColorsData[index]; + this.hex = color; + this.updateFromHEX(null, true); + } + + setUsed(color){ + this.lastSetUsedColor = color; + let usedColors = $('.used_color').toArray().reverse(); + let usedColorsData = p.getItem('usedColors'); + if (usedColorsData.includes(color)){ + let index = usedColorsData.indexOf(color); + let swap = usedColorsData[index - 1]; + if (swap){ + usedColorsData[index - 1] = color; + usedColorsData[index] = swap; + } + } else { + set(color, 0); + function set(c, i){ + let oldColor = usedColorsData[i]; + usedColorsData[i] = c; + + if (usedColorsData.length > i + 1) + set(oldColor, i + 1); + } + } + + for (let c of usedColorsData){ + let dom = usedColors[usedColorsData.indexOf(c)]; + $(dom).css('background-color', c); + } + + //p.storeItem('usedColors', usedColorsData); + } + + updateInterface(){ + + let r = $($("#color_picker_rgb input")[0]), + g = $($("#color_picker_rgb input")[1]), + b = $($("#color_picker_rgb input")[2]), + h = $($("#color_picker_hsv input")[0]), + s = $($("#color_picker_hsv input")[1]), + v = $($("#color_picker_hsv input")[2]), + hex = $("#color_picker_hex"), + bgColor; + + r.val(round(this.r)); + g.val(round(this.g)); + b.val(round(this.b)); + h.val(round(this.h)); + s.val(round(this.s)); + v.val(round(this.v)); + bgColor = color(this.r, 0, 0); + r.css({ + "background-color": bgColor.toString(), + "color": fontColor(bgColor) + }); + bgColor = color(0, this.g, 0); + g.css({ + "background-color": bgColor.toString(), + "color": fontColor(bgColor) + }); + bgColor = color(0, 0, this.b); + b.css({ + "background-color": bgColor.toString(), + "color": fontColor(bgColor) + }); + colorMode(HSL); + bgColor = color(this.h, 100, 50); + h.css({ + "background-color": bgColor.toString(), + "color": fontColor(bgColor) + }); + bgColor = color(this.h, this.s, 100 - this.s / 2); + s.css({ + "background-color": bgColor.toString(), + "color": fontColor(bgColor) + }); + bgColor = color(this.h, 100, this.v / 2); + v.css({ + "background-color": bgColor.toString(), + "color": fontColor(bgColor) + }); + colorMode(RGB); + hex.val(this.hex); + hex.css({ + "background-color": this.hex, + "color": fontColor(color(this.hex)) + }); + + + let sRGB = HSVtoRGB(this.h, 100, 100); + let saturationBackground = "linear-gradient(to right, #FFF 0%, rgb(" + + sRGB.r + "," + + sRGB.g + "," + + sRGB.b + ") 100%)"; + $("#hue_picker").css("top", (1 - this.h / 360) * $("#hue").height()); + $("#sb_picker").css({ + "left": this.s / 100 * $("#saturation").width() - 8, + "top": (1 - this.v / 100) * $("#value").height() - 8 + }); + $("#saturation").css("background", saturationBackground); + $("#thickness_preview").css("background-color", this.hex); + } + + mousePressed(){ + let x = p.winMouseX - $("#saturation").offset().left; + let y = p.winMouseY - $("#value").offset().top; + if (x > 0 && x < $("#saturation").width() && y > 0 && y < $("#value").height()){ + this.movingObject = "sb"; + this.mouseDragged(); + } + if (x > $("#saturation").width() + 6 && x < $("#saturation").width() + 6 + $("#hue").width() && y > 0 && y < $("#hue").height()){ + this.movingObject = "hue"; + this.mouseDragged(); + } + } + + mouseDragged(){ + if (this.movingObject == "hue"){ + let objH = $("#hue"); + let picker = $("#hue_picker"); + let h = p.winMouseY - objH.offset().top; + if (h > 0 && h < objH.height()){ + picker.css("top", h - 1); + } else if (h > objH.height()){ + picker.css("top", objH.height() - 1); + } else if (h < 0){ + picker.css("top", -1); + } + + this.updateFromGraphical(); + } + + if (this.movingObject == "sb"){ + let objS = $("#saturation"); + let objV = $("#value"); + let picker = $("#sb_picker"); + let s = p.winMouseX - objS.offset().left; + let v = p.winMouseY - objV.offset().top; + if (s > 0 && s < objS.width()){ + picker.css("left", s - 8); + } else if (s < 0){ + picker.css("left", -8); + } else if (s < objS.width()){ + picker.css("left", objS.width() - 8); + } + if (v > 0 && v < objV.height()){ + picker.css("top", v - 8); + } else if (v < 0){ + picker.css("top", -8); + } else if (v > objV.height()){ + picker.css("top", objV.height() - 8); + } + + this.updateFromGraphical(); + } + } + + mouseReleased(){ + this.movingObject = ""; + } + + getColor(){ + return this.hex; + } +} + +function fontColor(bg){ + //http://www.nbdtech.com/Blog/archive/2008/04/27/Calculating-the-Perceived-Brightness-of-a-Color.aspx + let o = (red(bg) * 299 + green(bg) * 587 + blue(bg) * 114) / 1000; + return (o > 125) ? "#000" : "#CCC"; +} + +//www.stackoverflow.com --> +function RGBtoHEX(r, g, b) { + let rgb = b | (g << 8) | (r << 16); + return '#' + (0x1000000 + rgb).toString(16).slice(1); +} + +function HEXtoRGB(hex) { + let shorthandRegex = /^#?([a-fA-F\d])([a-fA-F\d])([a-fA-F\d])$/i; + hex = hex.replace(shorthandRegex, function(m, r, g, b) { + return r + r + g + g + b + b; + }); + let result = /^#?([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})$/i.exec(hex); + return result ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16) + } : null; +} + +function HSVtoRGB(h, s, v) { + let r, g, b, i, f, p, q, t; + if (arguments.length === 1) { + s = h.s, v = h.v, h = h.h; + } + h /= 360; + s /= 100; + v /= 100; + i = Math.floor(h * 6); + f = h * 6 - i; + p = v * (1 - s); + q = v * (1 - f * s); + t = v * (1 - (1 - f) * s); + switch (i % 6) { + case 0: r = v, g = t, b = p; break; + case 1: r = q, g = v, b = p; break; + case 2: r = p, g = v, b = t; break; + case 3: r = p, g = q, b = v; break; + case 4: r = t, g = p, b = v; break; + case 5: r = v, g = p, b = q; break; + } + return { + r: r * 255, + g: g * 255, + b: b * 255 + }; +} + +function RGBtoHSV(r, g, b) { + if (arguments.length === 1) { + g = r.g, b = r.b, r = r.r; + } + let max = Math.max(r, g, b), min = Math.min(r, g, b), + d = max - min, + h, + s = (max === 0 ? 0 : d / max), + v = max / 255; + + switch (max) { + case min: h = 0; break; + case r: h = (g - b) + d * (g < b ? 6: 0); h /= 6 * d; break; + case g: h = (b - r) + d * 2; h /= 6 * d; break; + case b: h = (r - g) + d * 4; h /= 6 * d; break; + } + + return { + h: h * 360, + s: s * 100, + v: v * 100 + }; +} + +let round = (val) => p.round(val); +let color = (val) => p.color(val); +let red = (val) => p.red(val); +let green = (val) => p.green(val); +let blue = (val) => p.blue(val); +let colorMode = (val) => p.colorMode(val); +let HSL = p.HSL; +let RGB = p.RGB; \ No newline at end of file diff --git a/public/data/lib/benjocraeft/cookie.js b/public/data/lib/benjocraeft/cookie.js new file mode 100644 index 0000000..0ca3ed1 --- /dev/null +++ b/public/data/lib/benjocraeft/cookie.js @@ -0,0 +1,29 @@ +function setCookie(name, value, years){ + let expires = ""; + if (years){ + let date = new Date(); + date.setTime(date.getTime() + (years * 365 * 24 * 60 * 60 * 1000)); + expires = "; expires=" + date.toUTCString(); + } + document.cookie = name + "=" + value + expires + "; path=/"; +} + +function getCookie(name){ + let nameEQ = name + "="; + let ca = document.cookie.split(';'); + for (let i = 0; i < ca.length; i++){ + let c = ca[i]; + while (c.charAt(0) == ' ') c = c.substring(1, c.length); + if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length); + } + return null; +} + +function deleteCookies(){ + for (let i = 0; i < arguments.length; i++) setCookie(arguments[i], "", -1); +} + +function deleteAllCookies(){ + let cookies = document.cookie.split(";"); + for (let i = 0; i < cookies.length; i++) deleteCookies(cookies[i].split("=")[0]); +} \ No newline at end of file diff --git a/public/data/lib/benjocraeft/loader.js b/public/data/lib/benjocraeft/loader.js new file mode 100644 index 0000000..8f6b4f2 --- /dev/null +++ b/public/data/lib/benjocraeft/loader.js @@ -0,0 +1,30 @@ +class Loader{ + + constructor(dom){ + this.dim = createVector($(dom).width(), $(dom).height()); + this.c = createGraphics(this.dim.x, this.dim.y); + this.c.parent(dom); + this.radius = min(this.dim.x, this.dim.y) * 0.4; + this.center = createVector(this.dim.x / 2, this.dim.y / 2); + $(dom).find('canvas').show(); + this.angle = 0; + } + + update(){ + this.angle += PI / 10; + } + + display(){ + let c = this.c; + c.clear(); + c.noFill(); + c.stroke(0); + c.strokeWeight(5); + c.arc(this.center.x, this.center.y, this.radius * 2, this.radius * 2, this.angle, this.angle + PI + HALF_PI); + } + + destroy(){ + this.c.remove(); + } + +} \ No newline at end of file diff --git a/public/data/lib/benjocraeft/prototypes.js b/public/data/lib/benjocraeft/prototypes.js new file mode 100644 index 0000000..be71cea --- /dev/null +++ b/public/data/lib/benjocraeft/prototypes.js @@ -0,0 +1,30 @@ +Array.prototype.shuffle = function(){ + let currentIndex = this.length, temporaryValue, randomIndex; + while (0 != currentIndex){ + randomIndex = floor(random() * currentIndex); + currentIndex -= 1; + temporaryValue = this[currentIndex]; + this[currentIndex] = this[randomIndex]; + this[randomIndex] = temporaryValue; + } +} + +Array.prototype.copy = function(){ + return this.slice(0); +}; + +//Divides big Array into big multidimensional Array +Array.prototype.partitiate = function(dimensions){ + if (!dimensions) return this; + let parts = []; + while(this.length) parts.push(this.splice(0, round(pow(this.length, 1 / (1 + 1 / dimensions)))).partitiate(dimensions - 1)); + return parts; +} + +String.prototype.isValidHEX = function(){ + return /(^#[0-9A-Fa-f]{6}$)|(^#[0-9A-Fa-f]{3}$)/i.test(this); +} + +String.prototype.capitalize = function(){ + return this.charAt(0).toUpperCase() + this.slice(1); +} \ No newline at end of file diff --git a/public/data/lib/benjocraeft/technical.js b/public/data/lib/benjocraeft/technical.js new file mode 100644 index 0000000..483207c --- /dev/null +++ b/public/data/lib/benjocraeft/technical.js @@ -0,0 +1,48 @@ +function toTimeString(time, hoursWanted){ + + time = floor(time / 10); + + let hs = String(floor(time % 100)); + let fs = String(floor((time / 100) % 60)); + + if (hoursWanted){ + let min = String(floor(((time / 100) / 60) % 60)); + let hr = String(floor(((time / 100) / 60) / 60)); + + if (hs.length < 2) hs = "0" + hs; + if (fs.length < 2) fs = "0" + fs; + if (min.length < 2) min = "0" + min; + if (hr.length < 2) hr = "0" + hr; + + return hr + ":" + min + ":" + fs + ":" + hs; + } else { + let min = String(floor(((time / 100) / 60) % 60)); + + if (hs.length < 2) hs = "0" + hs; + if (fs.length < 2) fs = "0" + fs; + if (min.length < 2) min = "0" + min; + + return min + ":" + fs + ":" + hs; + } +} + + + + +function debugInformation(x, y){ + push(); + textSize(12); + textStyle(NORMAL); + stroke(255); + strokeWeight(1); + fill(255); + text("FPS : " + round(frameRate()), 10 + x, 10 + textAscent("FPS : ") + y); + text("MouseX : " + round(mouseX + x), 10 + x, 10 + textAscent("FPS : ") + 10 + textAscent("MouseX : ") + y); + text("MouseY : " + round(-mouseY - y), 10 + x, 10 + textAscent("FPS : ") + 10 + textAscent("MouseX : ") + 10 + textAscent("MouseY : ") + y); + pop(); +} + +function ranBool(chance){ + if (!chance) chance = 2; + return Math.floor(Math.random() * chance + 1) == chance ? true : false; +} \ No newline at end of file diff --git a/public/data/scripts/drawer.js b/public/data/scripts/drawer.js new file mode 100644 index 0000000..53dc8dc --- /dev/null +++ b/public/data/scripts/drawer.js @@ -0,0 +1,395 @@ +class Drawer{ + + constructor(){ + + this.dim = {x: 5000, y: 5000}; + this.viewport = { + x: (this.dim.x - p.width) / 2, + y: (this.dim.y - p.height) / 2, + maxX: this.dim.x, + maxY: this.dim.y, + scroll: 10, + zoom: 1, + zoomV: 2 + }; + this.oldMouseX = this.mouseX; + this.oldMouseY = this.mouseY; + this.map = new MiniMap($("#minimap"), "#minimap > canvas", true); + + //Free draw + this.lines = []; + this.linesToDraw = []; + this.linesImage = p.createGraphics(this.dim.x, this.dim.y); + this.linesImage.background(255); + + //Pixel art + this.pixels = []; + this.pixelsToFill = []; + this.gridPixelsToFill = []; + this.gridActive = false; + this.pixelsImage = p.createGraphics(this.dim.x, this.dim.y); + this.pixelsImage.background(255); + this.gridImage = p.createGraphics(this.dim.x, this.dim.y); + this.gridImage.background(255, 0); + this.gridImage.noStroke(); + this.gridImage.fill(0, 255 * 0.1); + this.pixelCount = {x: 1000, y: 1000}; + this.pixelSize = {x: this.dim.x / this.pixelCount.x, y: this.dim.y / this.pixelCount.y}; + for (let x = 0; x < this.pixelCount.x; x++){ + let column = []; + for (let y = 0; y < this.pixelCount.y; y++){ + let pixel = {x: x, y: y, c: "#FFFFFF"}; + column.push(pixel); + if (x % 2 == 0 && (y + 1) % 2 == 0 + || y % 2 == 0 && (x + 1) % 2 == 0) + this.gridPixelsToFill.push(pixel); + } + this.pixels.push(column); + } + + this.isCopying = false; + this.drawType = null; + this.thickness = parseInt($("#thickness").val()); + + this.pixelsMap = new MiniMap($("#pixels_map_holder"), "#pixels_map_holder > canvas", false); + this.linesMap = new MiniMap($("#lines_map_holder"), "#lines_map_holder > canvas", false); + } + + get image(){ + if (this.type === 'free') return this.linesImage; + if (this.type === 'pixel') return this.pixelsImage; + } + + get scrollSpeed(){ + return this.viewport.scroll; + } + + get mouseX(){ + return p.mouseX * this.viewport.zoom + this.viewport.x; + } + + get mouseY(){ + return p.mouseY * this.viewport.zoom + this.viewport.y; + } + + sendDrawing(){ + if (this.isDrawing && this.hasDrawnAllLines && this.hasFilledAllPixels){ + + if (this.type === 'free'){ + let pos1 = {x: p.round(this.oldMouseX), y: p.round(this.oldMouseY)}; + let pos2 = {x: p.round(this.mouseX), y: p.round(this.mouseY)}; + let color = colorPicker.getColor(); + + let line = {p1: pos1, p2: pos2, c: color, t: this.thickness}; + socket.emit('add-line', line); + } + + if (this.type === 'pixel'){ + let x = p.floor(this.mouseX / (this.dim.x / this.pixelCount.x)); + x = p.constrain(x, 0, this.pixelCount.x); + + let y = p.floor(this.mouseY / (this.dim.y / this.pixelCount.y)); + y = p.constrain(y, 0, this.pixelCount.y); + + let color = colorPicker.getColor(); + if (color === this.pixels[x][y].c) + return; + + let pixel = {x: x, y: y, c: color}; + socket.emit('fill-pixel', pixel); + } + + let color = colorPicker.getColor(); + if (colorPicker.lastSetUsedColor != color) + colorPicker.setUsed(color); + } + } + + draw(){ + p.clear(); + + if (this.hasDrawnAllLines && this.hasFilledAllPixels){ + this.moveViewport(); + this.map.draw(this.image, this.dim, this.viewport); + + + let x = this.viewport.x; + let y = this.viewport.y; + let w = p.width * this.viewport.zoom; + let h = p.height * this.viewport.zoom; + p.image(this.image, 0, 0, p.width, p.height, x, y, w, h); + + if (this.type === 'pixel' && this.gridActive){ + p.image(this.gridImage, 0, 0, p.width, p.height, x, y, w, h); + } + } + else { + this.pixelsMap.draw(this.pixelsImage, this.dim, this.viewport); + this.linesMap.draw(this.linesImage, this.dim, this.viewport); + this.updateProgress(); + } + + let drawSpeed = 800; + + for (let line of this.linesToDraw.slice(0, drawSpeed)) + this.drawLine(line); + this.linesToDraw.splice(0, drawSpeed); + if (this.linesToDraw.length === 0 && !this.hasDrawnAllLines && this.receivedLines && this.receivedPixels){ + this.hasDrawnAllLines = true; + if (this.hasFilledAllPixels) + $("#loading_drawings").fadeOut(200); + } + + for (let pixel of this.pixelsToFill.slice(0, drawSpeed)) + this.drawPixel(pixel); + this.pixelsToFill.splice(0, drawSpeed); + if (this.pixelsToFill.length === 0 && !this.hasFilledAllPixels && this.receivedPixels && this.receivedLines){ + this.hasFilledAllPixels = true; + if (this.hasDrawnAllLines) + $("#loading_drawings").fadeOut(200); + } + + for (let pixel of this.gridPixelsToFill.slice(0, drawSpeed)) + this.drawGridPixel(pixel); + this.gridPixelsToFill.splice(0, drawSpeed); + + + this.oldMouseX = this.mouseX; + this.oldMouseY = this.mouseY; + } + + moveViewport(){ + if (givesFeedback) + return; + + let y = 0, x = 0; + if (p.keyIsDown(40) || p.keyIsDown(83)) + y += this.scrollSpeed; + if (p.keyIsDown(38) || p.keyIsDown(87)) + y -= this.scrollSpeed; + if (p.keyIsDown(37) || p.keyIsDown(65)) + x -= this.scrollSpeed; + if (p.keyIsDown(39) || p.keyIsDown(68)) + x += this.scrollSpeed; + + this.viewport.x += x; + this.viewport.y += y; + + let maxX = this.viewport.maxX - p.width * this.viewport.zoom; + let maxY = this.viewport.maxY - p.height * this.viewport.zoom; + if (this.viewport.x > maxX) this.viewport.x = maxX; + if (this.viewport.y > maxY) this.viewport.y = maxY; + if (this.viewport.x < 0) this.viewport.x = 0; + if (this.viewport.y < 0) this.viewport.y = 0; + + if (x != 0 || y != 0) + this.sendDrawing(); + } + + addAll(lines){ + for (let line of lines) + this.addLine(line); + } + + drawLine(line){ + this.linesImage.strokeWeight(line.t); + this.linesImage.stroke(line.c); + this.linesImage.line(line.p1.x, line.p1.y, line.p2.x, line.p2.y); + } + + addLine(line){ + this.lines.push(line); + this.linesToDraw.push(line); + } + + fillPixel(pixel){ + this.pixels[pixel.x][pixel.y].c = pixel.c + this.pixelsToFill.push(pixel); + } + + fillAll(pixels){ + pixels.forEach(c => { + if (!c) return; + c.forEach(p => { + if (!p) return; + this.fillPixel(p); + }); + }); + } + drawPixel(pixel){ + let px = pixel.x * this.pixelSize.x; + let py = pixel.y * this.pixelSize.y; + let w = this.pixelSize.x; + let h = this.pixelSize.y; + + this.pixelsImage.fill(pixel.c); + this.pixelsImage.strokeWeight(1); + this.pixelsImage.noStroke(); + this.pixelsImage.rect(px, py, w, h); + } + + drawGridPixel(pixel){ + let px = pixel.x * this.pixelSize.x; + let py = pixel.y * this.pixelSize.y; + let w = this.pixelSize.x; + let h = this.pixelSize.y; + + this.gridImage.rect(px, py, w, h); + } + + onLinesLoaded(lines){ + this.receivedLines = lines; + console.log('Received all lines from server'); + + if (this.receivedPixels) + this.startDrawing(); + } + onPixelsLoaded(pixels){ + this.receivedPixels = pixels; + console.log('Received all pixels from server'); + + if (this.receivedLines) + this.startDrawing(); + } + startDrawing(){ + $("#action").html('Drawing...'); + $('#loading_drawings > *:not(#action)').show(); + + this.receivedPixels.forEach((c, i, a) => { + a[i] = c.filter(p => p.c !== '#ffffff' && p.c !== '#FFFFFF'); + }); + + this.addAll(this.receivedLines); + this.fillAll(this.receivedPixels); + + console.log('Started drawing...'); + } + + updateProgress(){ + if (!(this.receivedLines && this.receivedPixels)) + return; + let pixelCountDraw = 0; + this.receivedPixels.forEach(c => pixelCountDraw += c.length); + let allThingsToDraw = this.receivedLines.length + pixelCountDraw; + let thingsToDraw = this.pixelsToFill.length + this.linesToDraw.length; + let progress = thingsToDraw / allThingsToDraw; + progress = progress * 100; + progress = isNaN(progress) ? 0 : progress; + $("#loading_drawings > progress").val(progress); + } + + isLineVisible(line){ + return this.isPointVisible(line.pos1) || this.isPointVisible(line.pos2); + } + isPointVisible(point){ + if (!point) return; + let viewX = this.viewport.x; + let viewY = this.viewport.y; + return point.x - viewX > 0 && point.x - viewX < p.width + && point.y - viewY > 0 && point.y - viewY < p.height + } + + onMouseDown(){ + if (p.mouseX > 0 && p.mouseX < p.width){ + if (this.isCopying){ + this.isCopying = false; + $("body").css('cursor', 'default'); + } else { + this.isDrawing = true; + this.sendDrawing(); + } + } + + this.map.onMouseDown(); + } + onMouseUp(){ + this.isDrawing = false; + this.map.onMouseUp(); + } + onMouseDragged(){ + if (this.isDrawing){ + this.sendDrawing(); + } + + + this.map.onMouseDragged(); + } + onMouseMoved(){ + if (this.isCopying){ + let vp = this.viewport; + let image = this.image.get(vp.x, vp.y, p.width * vp.zoom, p.height * vp.zoom); + let pixel = image.get(p.mouseX * vp.zoom, p.mouseY * vp.zoom); + colorPicker.updateFromRGB(pixel); + } + } + + zoom(delta){ + let oldZoom = this.viewport.zoom; + this.viewport.zoom += delta / 100 * this.viewport.zoomV; + if (p.width * this.viewport.zoom > this.dim.x) + this.viewport.zoom = this.dim.x / p.width; + if (p.height * this.viewport.zoom > this.dim.y) + this.viewport.zoom = this.dim.y / height; + if (this.viewport.zoom < 0.1) + this.viewport.zoom = 0.1; + + let addZoom = this.viewport.zoom - oldZoom; + this.viewport.x -= addZoom * p.mouseX; + this.viewport.y -= addZoom * p.mouseY; + } + + skipDrawing(html){ + if (!this.receivedLines || !this.receivedPixels) + return; + + $(html).attr('disabled', 'disabled'); + + setTimeout(() => { + for (let pixel of this.pixelsToFill){ + this.drawPixel(pixel); + } + this.pixelsToFill = []; + + for (let line of this.linesToDraw){ + this.drawLine(line); + } + this.linesToDraw = []; + }, 0); + } + + requestServerSave(html){ + $(html).attr('disabled', 'disabled'); + socket.emit('save-all'); + } + + answerServerSave(){ + console.log('Drawings successfully saved on server'); + $('#server_answer').fadeIn(200, 'swing', () => { + setTimeout(() => + $('#server_answer').fadeOut(200) + , 1000 * 5); + setTimeout(() => + $('#server_save').attr('disabled', false) + , 1000 * 60 * 5); + }); + } +} + +function updateDrawType(drawType){ + drawer.type = drawType; + if (drawType === 'pixel'){ + p.noSmooth(); + $("#free_settings").hide(); + $('#pixel_settings').show(); + } + if (drawType === 'free'){ + p.smooth(); + $("#free_settings").show(); + $('#pixel_settings').hide(); + } +} + +function startCopyColor(){ + drawer.isCopying = true; + $("body").css('cursor', 'crosshair'); +} \ No newline at end of file diff --git a/public/data/scripts/events.js b/public/data/scripts/events.js new file mode 100644 index 0000000..5185b5e --- /dev/null +++ b/public/data/scripts/events.js @@ -0,0 +1,81 @@ +'use strict'; + +let GRID_HOTKEY; + +p.keyPressed = () => { + if (givesFeedback) + return; + if (p.keyCode === GRID_HOTKEY && drawer) + drawer.gridActive = !drawer.gridActive; +} + +p.keyTyped = () => { + if (givesFeedback) + return; + if (settingHotkey){ + GRID_HOTKEY = p.keyCode; + //p.storeItem('gridHotkey', GRID_HOTKEY); + $('#grid_hotkey').html(String.fromCharCode(p.keyCode)); + settingHotkey = false; + } +} + +p.mouseMoved = () => { + if (givesFeedback) + return; + if (drawer) + drawer.onMouseMoved(); +} + +p.mouseDragged = () => { + if (givesFeedback) + return; + if (drawer) + if (!drawer.hasDrawnAllLines || !drawer.hasFilledAllPixels) + return; + if (colorPicker) + colorPicker.mouseDragged(); + if (drawer) + drawer.onMouseDragged(); +} + +p.mousePressed = () => { + if (drawer) + if (!drawer.hasDrawnAllLines || !drawer.hasFilledAllPixels) + return; + if (givesFeedback) + return; + if (drawer) + drawer.onMouseDown(); + if (colorPicker) + colorPicker.mousePressed(); +} + +p.mouseReleased = () => { + if (drawer) + if (!drawer.hasDrawnAllLines || !drawer.hasFilledAllPixels) + return; + if (givesFeedback) + return; + if (drawer) + drawer.onMouseUp(); + if (colorPicker) + colorPicker.mouseReleased(); +} + +p.mouseWheel = (e) => { + if (drawer) + if (drawer.hasDrawnAllLines && drawer.hasFilledAllPixels) + drawer.zoom(e.delta); + e.preventDefault(); +} + +window.onresize = () => { + p.resizeCanvas($("#canvas-holder").width(), $("#canvas-holder").height()); +} + +let settingHotkey = false; +function setGridHotkey(dom){ + $(dom).blur(); + settingHotkey = true; +} diff --git a/public/data/scripts/init.js b/public/data/scripts/init.js new file mode 100644 index 0000000..688b324 --- /dev/null +++ b/public/data/scripts/init.js @@ -0,0 +1,125 @@ +'use strict'; + +let projectName = "project_pattern"; + +let debug = false, + font, + localSettings, + loader; + +let p; +let processor = new p5((p5Instance) => p = p5Instance); + +//Only for online games +let socket; + +let drawer; +let colorPicker; +let givesFeedback = false; + +p.preload = () => { + localSettings = p.loadJSON('data/settings/settings.json', (json) => { + console.log('Local settings loaded: ', json) + }, (error) => { + console.log('Local settings failed: ', error) + }); + + font = p.loadFont('data/styles/font.ttf', (json) => { + console.log('Local font loaded: ', json) + }, (error) => { + console.log('Local font failed: ', error) + }); + + p.loadJSON('data/settings/libraries.json', json => { + loadScripts(json) + console.log('BenjoCraeft library scripts loaded: ', json) + }); +} + +p.setup = () => { + canvasSetup(localSettings.frameWork); + interfaceSetup(); + + drawer = new Drawer(); + + socketConnect(localSettings.project); +} + +p.draw = () => { + + if (loader){ + loader.update(); + loader.display(); + } + + if (drawer) + drawer.draw(); + + if (debug) debugInformation(); +} + +function canvasSetup(frameWork){ + p.setFrameRate(frameWork.frameRate); + let w = frameWork.width, + h = frameWork.height; + if (w == null) + w = $("#canvas-holder").width(); + if (h == null) + h = $("#canvas-holder").height(); + let canvas = p.createCanvas(w, h); + canvas.parent('canvas-holder'); + p.textFont(font); + p.noSmooth(); +} + +function interfaceSetup(){ + updateThicknessPreview(); + $('input[type=radio][name=type]').change(function() { + updateDrawType(this.value); + $(this).blur(); + }); + + GRID_HOTKEY = p.getItem('gridHotkey'); + if (!GRID_HOTKEY) + GRID_HOTKEY = 'G'.charCodeAt(0); + //p.storeItem('gridHotkey', GRID_HOTKEY); + $('#grid_hotkey').html(String.fromCharCode(GRID_HOTKEY)); + + let usedColors = $('.used_color').toArray().reverse(); + let usedColorsData = p.getItem('usedColors'); + if (!usedColorsData) + usedColorsData = []; + for (let used of usedColors){ + let index = usedColors.indexOf(used); + let color = usedColorsData[index]; + if (!color) + color = '#FFFFFF'; + $(used).css('background-color', color); + usedColorsData[index] = color; + } + //p.storeItem('usedColors', usedColorsData); +} + +function updateThicknessPreview(){ + let size = $("#thickness").val(); + if (drawer) + drawer.thickness = parseInt(size); + $("#thickness_preview").css({width: size, height: size}); +} + +function loadScripts(libs){ + for (let script in libs){ + if (libs[script]){ + let url = 'data/lib/benjocraeft/' + script + '.js' + $.getScript(url, () => { + console.log('Successfully loaded script: ', url) + if (script === 'colorPicker'){ + colorPicker = new ColorPicker(null); + colorPicker.hex = "#000"; + colorPicker.updateFromHEX(null, true); + console.log('ColorPicker script loaded'); + } + }); + } + } +} \ No newline at end of file diff --git a/public/data/scripts/minimap.js b/public/data/scripts/minimap.js new file mode 100644 index 0000000..05425ee --- /dev/null +++ b/public/data/scripts/minimap.js @@ -0,0 +1,67 @@ +class MiniMap{ + + constructor(htmlHolder, htmlCanvas, isMinimap){ + let w = $(htmlHolder).width(); + let h = $(htmlHolder).height(); + this.dim = {x: w, y: h}; + this.p = p.createGraphics(w, h); + this.p.parent(htmlHolder.get(0)); + this.isMinimap = isMinimap; + $(htmlCanvas).show(); + } + + get mouseX(){ + return p.winMouseX - $("#minimap > canvas").offset().left; + } + + get mouseY(){ + return p.winMouseY - $("#minimap > canvas").offset().top; + } + + draw(image, dim, vp){ + this.p.clear(); + + this.p.image(image, 0, 0, this.dim.x, this.dim.y, 0, 0, dim.x, dim.y); + + if (this.isMinimap){ + let x = p.map(vp.x, 0, vp.maxX, 0, this.dim.x); + let y = p.map(vp.y, 0, vp.maxY, 0, this.dim.y); + let w = p.map(p.width * vp.zoom, 0, vp.maxX, 0, this.dim.x); + let h = p.map(p.height * vp.zoom, 0, vp.maxY, 0, this.dim.y); + let r = (w + h) / 2 * 0.02; + this.p.noFill(); + this.p.rect(x, y, w, h, r); + } + } + + onMouseDown(){ + if (this.mouseX > 0 && this.mouseX < this.p.width && + this.mouseY > 0 && this.mouseY < this.p.height){ + this.isDrawing = true; + this.moveViewport(); + } + } + + onMouseUp(){ + this.isDrawing = false; + } + + onMouseDragged(){ + if (this.isDrawing) + this.moveViewport(); + } + + moveViewport(){ + if (!this.isMinimap) + return; + + let vp = drawer.viewport; + let mapX = this.mouseX - p.map(p.width * vp.zoom / 2, 0, drawer.dim.x, 0, this.dim.x); + let mapY = this.mouseY - p.map(p.height * vp.zoom / 2, 0, drawer.dim.y, 0, this.dim.y); + let x = p.map(mapX, 0, this.dim.x, 0, vp.maxX); + let y = p.map(mapY, 0, this.dim.y, 0, vp.maxY); + drawer.viewport.x = x; + drawer.viewport.y = y; + } + +} \ No newline at end of file diff --git a/public/data/scripts/online.js b/public/data/scripts/online.js new file mode 100644 index 0000000..eb2e600 --- /dev/null +++ b/public/data/scripts/online.js @@ -0,0 +1,82 @@ +'use strict'; + +function socketConnect(project, name = "noone"){ + let urlQueries = '?game=' + project.name + '&name=' + name; + $.get('data/settings/get_port.php', port => { + let url = 'https://' + location.hostname + ':' + port + urlQueries; + + socket = io.connect(url); + socket.on('connect', () => { + console.log('Connected to ', url); + + socket.emit('join-lobby', 'global-draw-room'); + + socket.on('add-line', (lobby, line) => drawer.addLine(line)); + socket.on('fill-pixel', (lobby, pixel) => drawer.fillPixel(pixel)); + socket.on('add-all', (lines) => drawer.onLinesLoaded(lines)); + socket.on('fill-all', (pixels) => drawer.onPixelsLoaded(pixels)); + socket.on('member-joined', (lobby, clientId) => { + if (clientId !== socket.id) + return; + if (drawer) + if (drawer.lines.length !== 0) + return; + + socket.emit('request-all-lines'); + socket.emit('request-all-pixels'); + $("#action").html("Downloading..."); + }); + + socket.on('all-saved', (_lobby) => drawer.answerServerSave()); + + updateDrawType($("input[type=radio][name=type]:checked").val()); + }); + }); +} + +function sendFeedback(){ + $.post('/php/post_feedback.php', {content: $('#user_feedback > textarea').val(), projectName: localSettings.project.name}); +} + +function createLobby(dom){ + if (inputIsValid('create')){ + onlineRequestFrontend(dom); + //TODO + } +} + +function joinLobby(dom){ + if (inputIsValid('join')){ + onlineRequestFrontend(dom); + //TODO + } +} + +function onlineRequestFrontend(dom){ + $(dom).blur(); + $(dom).attr('disabled', 'disabled'); + if (loader) loader.destroy(); + loader = new Loader($('#loader').get(0)); +} + +function inputIsValid(type){ + let valid = true; + $('.error-label').html(''); + if (type === 'create'){ + if ($('#player-name > input').val() === ''){ + valid = false; + $('#player-name > .error-label').html('Please enter a name!'); + } + } + if (type === 'join'){ + if ($('#player-name > input').val() === ''){ + valid = false; + $('#player-name > .error-label').html('Please enter a name!'); + } + if ($('#lobby-code > input').val() === ''){ + valid = false; + $('#lobby-code > .error-label').html('Please enter your code!'); + } + } + return valid; +} \ No newline at end of file diff --git a/public/data/settings/get_port.php b/public/data/settings/get_port.php new file mode 100644 index 0000000..8de971e --- /dev/null +++ b/public/data/settings/get_port.php @@ -0,0 +1,3 @@ + input, #color_picker_hsv > input{ + width: 80px; + float: left; + height: 35px; + font-size: 25px; + color: #000; + margin-top: 5px; + border-radius: 10px; +} +#color_picker_rgb > input:nth-child(1), #color_picker_hsv > input:nth-child(1){ + margin-right: 10%; + margin-left: 3%; +} +#color_picker_rgb > input:nth-child(3), #color_picker_hsv > input:nth-child(3){ + margin-left: 10%; +} +#color_picker_hex{ + width: calc(100% - 5px); + height: 30px; + font-size: 25px; + border-radius: 10px; +} +#saturation{ + position: relative; + width: calc(100% - 33px); + height: 100%; + background: linear-gradient(to right, #FFF 0%, #F00 100%); + float: left; + margin-right: 6px; +} +#value { + width: 100%; + height: 100%; + background: linear-gradient(to top, #000 0%, rgba(255,255,255,0) 100%); +} +#sb_picker{ + border: 2px solid; + border-color: #FFF; + position: absolute; + width: 14px; + height: 14px; + border-radius: 10px; + bottom: -7px; + left: -8px; + box-sizing: border-box; + z-index: 10; +} +#hue { + width: 27px; + height: 100%; + position: relative; + float: left; + background: linear-gradient(to bottom, #F00 0%, #F0F 17%, #00F 34%, #0FF 50%, #0F0 67%, #FF0 84%, #F00 100%); +} +#hue_picker { + position: absolute; + background: #000; + border-bottom: 1px solid #000; + top: 0; + width: 27px; + height: 2px; +} \ No newline at end of file diff --git a/public/data/styles/font.ttf b/public/data/styles/font.ttf new file mode 100644 index 0000000000000000000000000000000000000000..199cf40be5021f3ef8132d1400e3b7eb4614e511 GIT binary patch literal 30420 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 + + + + + + + + + + + + + + + + Global Draw + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+
+ + + +
+ +
+
+
+
+ + + + + + + +
+ +
+
+ +
+
+
+
+
+
+ Grid Toggle: [] + +
+
+
+
+ +
+ +
+ + + +
+
+
+ Connecting... + + +
+ +
+ +
+ +
+ + \ No newline at end of file diff --git a/public/styles.css b/public/styles.css new file mode 100644 index 0000000..97e73dc --- /dev/null +++ b/public/styles.css @@ -0,0 +1,226 @@ +a:link, a:hover, a:active, a:visited{color: #000;} + +html, body{margin: 0; padding: 0; height: 100%; width: 100%; overflow: hidden;} + +canvas{margin: 0; padding: 0; border: none; display: block;} + +button:hover{cursor: pointer;} + +@font-face{ + font-family: "Rametto"; + src: url("data/styles/font.ttf"); +} + +*{ + font-family: "Rametto"; + color: #000; + font-size: 17px; +} + +:root{ + --if-background-color: rgb(0, 100, 131); + --if-width: 300px; + --if-border-width: 5px; + --if-padding: 25px; + --if-content-width: calc(var(--if-width) - var(--if-padding) * 2); +} + +/** + * Standard styles + */ + +#content{ + display: grid; + grid-template-columns: calc(var(--if-width) + var(--if-border-width)) calc(100% - var(--if-width)); + grid-template-rows: 100%; + width: 100%; + height: 100%; + overflow: hidden; +} + +button{ + background-color: rgb(67, 202, 67); + margin: 5px; + border-radius: 5px; +} +button:hover:not(.used_color):not([disabled]){ + background-color: rgb(49, 150, 49); +} +button:disabled{ + background-color: rgb(121, 121, 121); +} + + +#loading_drawings{ + position: absolute; + width: 100%; + height: 100%; + background-color: rgba(50, 182, 138, 0.699); + text-align: center; +} +#action{ + font-size: 50px; +} +#loading_drawings > progress{ + width: 700px; + height: 30px; +} +#warning{ + font-size: 10px; +} + +#p5_loading{ + display: none; +} +#loading_maps{ + width: 100%; + display: flex; + justify-content: center; +} +#pixels_map_holder, #lines_map_holder{ + width: 500px; + height: 500px; + border-radius: 5px; + border: 3px solid #000; + background-color: #FFF; + margin: 50px; +} + + +#user_feedback{ + position: absolute; + width: 100%; + height: 100%; + background-color: rgba(50, 182, 138, 0.699); + text-align: center; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} +#user_feedback > *{ + width: 50%; +} + + +#interface{ + background-color: var(--if-background-color); + border: var(--if-border-width) solid #000; + border-width: 0 5px 0 0; +} + +#version{ + position: absolute; + bottom: 55px; +} +#changelog{ + position: absolute; + bottom: 30px; +} +#start_user_feedback{ + position: absolute; + bottom: 0; + height: 25px; + font-size: 15px; +} + +#color_picker{ + width: var(--if-content-width); + height: var(--if-content-width); +} +#color_picker_numeric_holder{ + margin: 10px var(--if-padding); + width: var(--if-content-width); + background-color: none; +} +#color_picker_numeric{ + background-color: none; +} +#color_picker_rgb, #color_picker_hsv{ + display: none; +} +#used_colors{ + width: var(--if-content-width); + margin: 0 var(--if-padding); + display: flex; + justify-content: space-between; +} +.used_color{ + width: 30px; + height: 30px; + margin: 0; + background-color: white; +} +#get_color{ + width: calc(var(--if-content-width)); + margin: 0 var(--if-padding) 15px; + font-size: 11px; + border-radius: 3px; + background-color: white; +} +#get_color:hover{ + background-color: rgb(150, 150, 150); +} + +#free_settings, #pixel_settings{ + margin: 0px var(--if-padding); + width: var(--if-content-width); + height: 80px; +} + +#thickness_holder{ + display: flex; + align-items: center; +} +#thickness{ + width: calc(var(--if-content-width) - 50px); +} +#thickness_preview_holder{ + position: relative; + margin: 0 0 0 10px; + width: 40px; + height: 40px; +} +#thickness_preview{ + border: 1px solid #000; + position: absolute; + top: 50%; left: 50%; + transform: translate(-50%, -50%); + border-radius: 50%; +} + +#set_hotkey{ + float: right; + margin: 0; + font-size: 12px; + height: 28px; +} + +#minimap{ + width: var(--if-content-width); + height: var(--if-content-width); + margin: 22px; + border-radius: 5px; + border: 3px solid #000; +} +#minimap > canvas{ + border-radius: inherit; +} + +#draw_type{ + width: var(--if-content-width); + margin: 0 var(--if-padding); + text-align: center; +} + +#server_save{ + width: calc(var(--if-content-width) * 0.6); + margin: 10px calc(var(--if-padding) + var(--if-content-width) * 0.2) +} +#server_answer{ + display: block; + width: var(--if-content-width); + font-size: 15px; + text-align: center; + margin: 0 var(--if-padding); +} \ No newline at end of file diff --git a/public/thumbnail.png b/public/thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..2c6aba95fe51a10ee29fc1546923a4c5b8998989 GIT binary patch literal 175149 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ð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 literal 0 HcmV?d00001 diff --git a/server/.gitignore b/server/.gitignore new file mode 100644 index 0000000..7f2c5d6 --- /dev/null +++ b/server/.gitignore @@ -0,0 +1,5 @@ +out +json_data +logs +node_modules +.env \ No newline at end of file diff --git a/server/package-lock.json b/server/package-lock.json new file mode 100644 index 0000000..2a59cb2 --- /dev/null +++ b/server/package-lock.json @@ -0,0 +1,424 @@ +{ + "name": "global-draw-sheet", + "version": "2.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "global-draw-sheet", + "version": "2.0", + "dependencies": { + "dotenv": "^16.0.3", + "https": "^1.0.0", + "socket.io": "^4.4.1", + "typescript": "^5.0.2" + }, + "devDependencies": { + "@types/node": "^18.15.3" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, + "node_modules/@types/cors": { + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "18.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", + "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/engine.io": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.4.1.tgz", + "integrity": "sha512-JFYQurD/nbsA5BSPmbaOSLa3tSVj8L6o4srSwXXY3NqE+gGUNmmPTbhn8tjzcCtSqhFgIeqef81ngny8JM25hw==", + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.11.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz", + "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/https": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https/-/https-1.0.0.tgz", + "integrity": "sha512-4EC57ddXrkaF0x83Oj8sM6SLQHAWXw90Skqu2M4AEWENZ3F02dFJE/GARA8igO79tcgYqGrD7ae4f5L3um2lgg==" + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/socket.io": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.6.1.tgz", + "integrity": "sha512-KMcaAi4l/8+xEjkRICl6ak8ySoxsYG+gG6/XfRCPJPQ/haCRIJBTL4wIl8YCsmtaBovcAXGLOShyVWQ/FG8GZA==", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.4.1", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "dependencies": { + "ws": "~8.11.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz", + "integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/typescript": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", + "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + }, + "dependencies": { + "@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + }, + "@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, + "@types/cors": { + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "18.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", + "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==" + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" + }, + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==" + }, + "engine.io": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.4.1.tgz", + "integrity": "sha512-JFYQurD/nbsA5BSPmbaOSLa3tSVj8L6o4srSwXXY3NqE+gGUNmmPTbhn8tjzcCtSqhFgIeqef81ngny8JM25hw==", + "requires": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.11.0" + } + }, + "engine.io-parser": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz", + "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==" + }, + "https": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https/-/https-1.0.0.tgz", + "integrity": "sha512-4EC57ddXrkaF0x83Oj8sM6SLQHAWXw90Skqu2M4AEWENZ3F02dFJE/GARA8igO79tcgYqGrD7ae4f5L3um2lgg==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "socket.io": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.6.1.tgz", + "integrity": "sha512-KMcaAi4l/8+xEjkRICl6ak8ySoxsYG+gG6/XfRCPJPQ/haCRIJBTL4wIl8YCsmtaBovcAXGLOShyVWQ/FG8GZA==", + "requires": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.4.1", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.1" + } + }, + "socket.io-adapter": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "requires": { + "ws": "~8.11.0" + } + }, + "socket.io-parser": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz", + "integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==", + "requires": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + } + }, + "typescript": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", + "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + }, + "ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "requires": {} + } + } +} diff --git a/server/package.json b/server/package.json new file mode 100644 index 0000000..7d1a8d4 --- /dev/null +++ b/server/package.json @@ -0,0 +1,17 @@ +{ + "name": "global-draw", + "version": "2.0", + "private": true, + "scripts": { + "start": "node out/index.js" + }, + "dependencies": { + "dotenv": "^16.0.3", + "https": "^1.0.0", + "socket.io": "^4.4.1", + "typescript": "^5.0.2" + }, + "devDependencies": { + "@types/node": "^18.15.3" + } +} diff --git a/server/src/client.ts b/server/src/client.ts new file mode 100644 index 0000000..b1cd58c --- /dev/null +++ b/server/src/client.ts @@ -0,0 +1,169 @@ +import {Room} from "./room.js" +import {ConnectionManager, serializeObject} from "./manager.js" +import {log} from "./logger.js"; +import * as SocketIO from "socket.io"; +import {Settings} from "./definitions/settings"; + +export class Client { + + socket: SocketIO.Socket; + name: string; + game: string; + id: string; + isReady: boolean; + isPlayer: boolean; + isSpectator: boolean; + + constructor(socket: SocketIO.Socket, manager: ConnectionManager) { + this.socket = socket; + // @ts-ignore + this.name = socket.handshake.query.name; + // @ts-ignore + this.game = socket.handshake.query.game; + this.id = socket.id; + this.setEvents(manager) + } + + get serialized(): Serialized.Client { + return { + id: this.id, + name: this.name, + game: this.game, + isReady: this.isReady, + isPlayer: this.isPlayer, + isSpectator: this.isSpectator + }; + } + + setEvents(mng: ConnectionManager): void { + let s = this.socket; + s.on('room-list', () => this.sendRoomList()); + s.on('client-list', () => this.sendClientList()); + s.on('set-ready', ready => this.setReady(ready)); + s.on('game-settings', settings => this.setGameSettings(settings)); + s.on('create-lobby', (settings, name) => this.createRoom(settings, name)); + s.on('join-lobby', roomId => this.joinRoom(roomId)); + s.on('leave-lobby', roomId => this.leaveRoom(roomId)); + s.on('join-spectators', () => this.joinSpectators()); + s.on('join-players', () => this.joinPlayers()); + s.on('start-game', lobbyId => mng.startGame(this, lobbyId)); + s.on('stop-game', lobbyId => mng.stopGame(this, lobbyId)); + s.on('feedback', content => mng.saveFeedbackToFile(this, content)); + s.on('disconnect', () => mng.disconnected(this)); + + this.send('connected') + } + + sendRoomList(): void { + let rooms = ConnectionManager.RoomListByGame(this.game); + this.send('room-list', rooms) + } + + sendClientList(): void { + let clients = ConnectionManager.ClientListByClientId(this.id); + this.send('client-list', clients) + } + + setReady(ready: boolean): void { + let room = Room.getByClientId(this.id, ConnectionManager.Instance.rooms); + + if (room) { + this.isReady = ready; + room.toAll('client-list', room.clients) + } + } + + setGameSettings(settings: any): void { + let room = Room.getByClientId(this.id, ConnectionManager.Instance.rooms); + + if (room) { + room.gameSettings = settings; + room.toAll('game-settings', settings) + } + } + + createRoom(settings: Settings.Global, name: string): void { + let room = ConnectionManager.Instance.createRoom(settings, name); + + room.add(this); + this.send('created-lobby', room); + + log('lobby-created', this, room) + } + + joinRoom(roomId: string): Room { + let room = Room.getByRoomId(roomId, ConnectionManager.Instance.rooms); + + if (!room) { + this.send('join-failed', 'Room does not exist!'); + log('join-non-existent', this, new Room('not-existent', roomId)) + } else if (room.hasStarted && !room.settings.spectators) { + this.send('join-failed', 'Game has started yet!'); + log('join-started', this, room) + } else { + room.add(this); + log('member-joined', this, room) + } + return room + } + + leaveRoom(_roomId: string): void { + let room = Room.getByClientId(this.id, ConnectionManager.Instance.rooms); + + if (!room) + return; + + this.leave(room.id); + if (room.runningGame) + room.runningGame.removeClient(this); + room.clients.splice(room.clients.indexOf(this), 1); + room.toAll('member-left', this.id, this.name); + room.toAll('client-list', room.clients); + + this.send('left-lobby'); + + log('member-left', this, room); + + if (room.isEmpty && !room.settings.always) { + ConnectionManager.Instance.deleteRoom(room) + } + } + + joinSpectators() { + let room = Room.getByClientId(this.id, ConnectionManager.Instance.rooms); + if (!room) + return; + + this.isSpectator = true; + this.isPlayer = false; + + room.toAll('client-list', room.clients) + } + + joinPlayers() { + let room = Room.getByClientId(this.id, ConnectionManager.Instance.rooms); + if (!room) + return; + + if (room.hasStarted) + return; + + this.isSpectator = false; + this.isPlayer = true; + + room.toAll('client-list', room.clients) + } + + send(event: string, ...args: any[]): void { + this.socket.emit(event, ...serializeObject(args)) + } + + join(roomId: string): void { + this.socket.join(roomId) + } + + leave(roomId: string): void { + this.socket.leave(roomId) + } + +} \ No newline at end of file diff --git a/server/src/definitions/serialized.d.ts b/server/src/definitions/serialized.d.ts new file mode 100644 index 0000000..b7b6a04 --- /dev/null +++ b/server/src/definitions/serialized.d.ts @@ -0,0 +1,20 @@ +declare namespace Serialized { + + interface Lobby { + id: string + name: string + game: string + clientCounts: number[] + clients: Client[] + hasStarted: boolean + } + + interface Client { + id: string + name: string + game: string + isReady: boolean + isPlayer: boolean + isSpectator: boolean + } +} \ No newline at end of file diff --git a/server/src/definitions/settings.d.ts b/server/src/definitions/settings.d.ts new file mode 100644 index 0000000..55d1d03 --- /dev/null +++ b/server/src/definitions/settings.d.ts @@ -0,0 +1,29 @@ +import {ServerGame} from "../game_standard"; + +declare module Settings { + interface Global { + project: Project + frameWork: FrameWork + game: any + always: boolean + spectators: boolean + } + + interface Project { + name: string + author: string + playerCounts: number[] + } + + interface FrameWork { + frameRate: number + updateRate: number + width: number + height: number + } + + interface Server { + useP2P: boolean + gameClass: typeof ServerGame + } +} \ No newline at end of file diff --git a/server/src/game_standard.ts b/server/src/game_standard.ts new file mode 100644 index 0000000..cedb658 --- /dev/null +++ b/server/src/game_standard.ts @@ -0,0 +1,38 @@ +import {Room} from "./room.js" +import {Client} from "./client.js" +import {Settings} from "./definitions/settings"; + +export class ServerGame { + + room: Room; + settings: Settings.Global; + game: any; + + constructor(room: Room, settings: Settings.Global) { + this.settings = settings; + this.room = room; + this.room.clients.forEach(c => this.addClient(c)) + } + + addClient(client: Client): void { + this.setEvents(client) + } + + removeClient(client: Client): void { + this.removeEvents(client) + } + + gameAction(action: string, ...args: any[]): void { + } + + setEvents(client: Client): void { + let socket = client.socket; + socket.on('game-action', (action, ...args) => this.gameAction(action, ...args)) + } + + removeEvents(client: Client): void { + let socket = client.socket; + socket.removeAllListeners('game-action') + } + +} \ No newline at end of file diff --git a/server/src/global_draw.ts b/server/src/global_draw.ts new file mode 100644 index 0000000..345e545 --- /dev/null +++ b/server/src/global_draw.ts @@ -0,0 +1,149 @@ +import {ServerGame} from "./game_standard" +import {Room} from "./room"; +import {Settings} from "./definitions/settings"; +import {log} from "./logger"; +import {Client} from "./client"; +import * as fs from "fs"; + +export class GlobalDraw extends ServerGame { + + lines: any[]; + pixels: any[][]; + + linesPath = "json_data/global_draw/lines.json"; + pixelsPath = "json_data/global_draw/pixels.json"; + + pixelCount = 1000; + + constructor(lobby: Room, settings: Settings.Global) { + super(lobby, settings); + + this.lines = []; + this.pixels = []; + + for (let x = 0; x < this.pixelCount; x++) { + let column = []; + for (let y = 0; y < this.pixelCount; y++) { + column.push({x: x, y: y, c: "#ffffff"}); + } + this.pixels.push(column); + } + + let linesLoaded = false; + let pixelsLoaded = false; + + this.loadDrawingsFromFile(this.linesPath, (data: any[]) => { + this.lines = data; + }, () => { + linesLoaded = true; + if (pixelsLoaded) { + this.startSaveInterval(); + } + }); + this.loadDrawingsFromFile(this.pixelsPath, (data: any[]) => { + for (let x = 0; x < this.pixelCount; x++) { + for (let y = 0; y < this.pixelCount; y++) { + if (data[x]) + if (data[x][y]) + this.pixels[x][y].c = data[x][y].c + } + } + }, () => { + pixelsLoaded = true; + if (linesLoaded) { + this.startSaveInterval(); + } + }); + } + + startSaveInterval() { + this.saveAllDrawingsToFile(); + + //Saves once every day + setInterval(() => this.saveAllDrawingsToFile(), 1000 * 60 * 60 * 24); + } + + addLine(line: any) { + this.lines.push(line); + this.room.toAll('add-line', line) + } + + fillPixel(pixel: any) { + this.pixels[pixel.x][pixel.y].c = pixel.c; + this.room.toAll('fill-pixel', pixel) + } + + loadDrawingsFromFile(drawingsPath: string, successs: (data: any[]) => void, done: () => void) { + fs.readFile(drawingsPath, 'utf8', (err, data) => { + if (err) + log('load-error', null, this.room, err.message); + else { + try { + let parsed = JSON.parse(data); + log('load-success', null, this.room); + successs(parsed); + } catch (e) { + log('parse-error', null, this.room, e.message); + } + } + done(); + }); + } + + saveDrawingsToFile(drawings: any[], drawingsPath: string, callback: (err: any) => void) { + let splits = drawingsPath.split('/'); + let path = splits.slice(0, splits.length - 1).reduce((prev, curr) => prev + '/' + curr); + let name = splits[splits.length - 1]; + if (!fs.existsSync(path)) { + fs.mkdirSync(path, {recursive: true}); + } + fs.writeFile(drawingsPath, JSON.stringify(drawings), callback); + } + + saveAllDrawingsToFile() { + let linesSaved = false; + let pixelsSaved = false; + + this.saveDrawingsToFile(this.lines, this.linesPath, (err) => { + if (err) + log('save-error', null, this.room, err.message); + else { + linesSaved = true; + if (pixelsSaved) { + this.room.toAll('all-saved'); + linesSaved = false; + pixelsSaved = false + } + log('save-success', null, this.room, 'Successfully saved lines to file') + } + }); + this.saveDrawingsToFile(this.pixels, this.pixelsPath, (err) => { + if (err) + log('save-error', null, this.room, err.message); + else { + pixelsSaved = true; + if (linesSaved) { + this.room.toAll('all-saved'); + pixelsSaved = false; + linesSaved = false + } + log('save-success', null, this.room, 'Successfully saved pixels to file') + } + }); + } + + addClient(client: Client): void { + this.setEvents(client); + } + + setEvents(client: Client): void { + super.setEvents(client); + let socket = client.socket; + socket.on('add-line', (line) => this.addLine(line)); + socket.on('fill-pixel', (pixel) => this.fillPixel(pixel)); + socket.on('request-all-lines', () => socket.emit('add-all', this.lines)); + socket.on('request-all-pixels', () => socket.emit('fill-all', this.pixels)); + socket.on('save-all', () => this.saveAllDrawingsToFile()); + } + +} \ No newline at end of file diff --git a/server/src/index.ts b/server/src/index.ts new file mode 100644 index 0000000..1eee09a --- /dev/null +++ b/server/src/index.ts @@ -0,0 +1,7 @@ +import {GlobalDraw} from "./global_draw"; +import {StartServer} from "./start"; + +StartServer({ + useP2P: false, + gameClass: GlobalDraw +}); \ No newline at end of file diff --git a/server/src/logger.ts b/server/src/logger.ts new file mode 100644 index 0000000..2b4e936 --- /dev/null +++ b/server/src/logger.ts @@ -0,0 +1,105 @@ +import {Room} from "./room.js" +import {Client} from "./client.js" + +import * as fs from "fs"; +import * as util from "util"; + +let logFolder = "./logs"; + +if (!fs.existsSync(logFolder)) { + fs.mkdirSync(logFolder); +} + +let logFile = fs.createWriteStream(logFolder + '/' + new Date().getTime() + '.log', {flags: 'a'}); +let logStdout = process.stdout; + +console.log = function () { + logFile.write(util.format.apply(null, arguments) + '\n'); + logStdout.write(util.format.apply(null, arguments) + '\n'); +}; + +console.error = console.log; + +process.on('uncaughtException', err => { + console.error('Uncaught error: ', err); + process.exit(1); +}); + +process.stdin.pipe(logFile); + + +export function log(type: string, client: Client, lobby?: Room, msg?: string) { + let now = new Date(Date.now()).toString(), message, name, game; + let date = '[' + now.substring(0, now.indexOf('GMT') - 1) + ']'; + + if (client) { + game = '[' + client.game + ']'; + let short = client.id.substring(0, Math.round(client.id.length / 3)); + name = '"' + client.name + '(' + short + '...)"'; + } else { + if (type === 'lobby-deleted') { + game = '[' + lobby.gameName + ']'; + } else { + game = '[undefined]'; + } + name = 'UNKNOWN'; + } + if (lobby) { + game = '[' + lobby.gameName + ']'; + } + switch (type) { + case 'join-non-existent': + message = name + ' tried to join non-existent lobby "' + lobby.id + '"'; + break; + case 'join-started': + message = name + ' tried to join the started game "' + lobby.id + '"'; + break; + case 'lobby-created': + message = name + ' created new lobby: "' + lobby.id + '"'; + break; + case 'game-started': + message = name + ' started the game: "' + lobby.id + '"'; + break; + case 'game-stopped': + message = name + ' stopped the game: "' + lobby.id + '"'; + break; + case 'member-joined': + message = name + ' joined the lobby "' + lobby.id + '"'; + break; + case 'member-left': + message = name + ' left the lobby "' + lobby.id + '"'; + break; + case 'lobby-deleted': + message = 'Lobby "' + lobby.id + '" was deleted'; + break; + case 'save-success': + message = msg; + break; + case 'save-error': + message = 'Failed to save contents to file: ' + msg; + break; + case 'load-success': + message = 'Successfully loaded and parsed file contents'; + break; + case 'load-error': + message = 'Failed to load file: ' + msg; + break; + case 'parse-error': + message = 'Failed to parse contents: ' + msg; + break; + case 'feedback': + message = 'Saved feedback to file: ' + msg; + break; + case 'connection': + message = name + ' connected'; + break; + case 'disconnection': + message = name + ' disconnected'; + break; + case 'startup': + message = msg; + break; + } + + console.log(date + game + ' ---> {' + message + '}'); +} \ No newline at end of file diff --git a/server/src/manager.ts b/server/src/manager.ts new file mode 100644 index 0000000..6d50d8b --- /dev/null +++ b/server/src/manager.ts @@ -0,0 +1,149 @@ +import {Room} from "./room.js" +import {Client} from "./client.js" +import {log} from "./logger.js" +import * as fs from "fs"; +import * as SocketIO from "socket.io" +import {Settings} from "./definitions/settings"; + +export class ConnectionManager { + + static Instance: ConnectionManager; + io: SocketIO.Server; + rooms: Room[]; + + constructor(io: SocketIO.Server) { + ConnectionManager.Instance = this; + + this.io = io; + this.rooms = []; + + let drawSettings = { + project: { + name: 'global-draw', + playerCounts: null + }, + always: true, + spectators: true + }; + let drawRoom = this.createRoom(drawSettings, ''); + drawRoom.id = 'global-draw-room'; + drawRoom.startGame(); + this.rooms.push(drawRoom); + } + + static RoomListByGame(game: string): Room[] { + return this.Instance.rooms.filter(l => l.gameName === game) + } + + static ClientListByClientId(clientId: string): Client[] { + let room = Room.getByClientId(clientId, this.Instance.rooms); + + return room.clients + } + + newSocket(socket: SocketIO.Socket): void { + let client = new Client(socket, this); + log('connection', client) + } + + roomListUpdate(): void { + this.io.sockets.emit('room-list', serializeObject(this.rooms)) + } + + createRoom(settings: Settings.Global | any, name: string): Room { + let roomId = Room.generateCode(10); + let room = new Room(name, roomId, settings, this.io); + + this.rooms.push(room); + this.roomListUpdate(); + + return room + } + + deleteRoom(room: Room): void { + this.rooms.splice(this.rooms.indexOf(room), 1); + this.roomListUpdate(); + + log('lobby-deleted', null, room) + } + + //Starts the game of a room with given id + startGame(client: Client, _roomId: string): void { + let lobby = Room.getByClientId(client.id, this.rooms); + if (!lobby) return; + + if (!lobby.hasStarted) { + lobby.startGame(); + log('game-started', client, lobby) + } + + this.io.sockets.emit('room-list', serializeObject(this.rooms)) + } + + //Stops the game of a lobby with given id + stopGame(client: Client, lobbyId: string): void { + let lobby = Room.getByRoomId(lobbyId, this.rooms); + if (!lobby) return; + + lobby.stopGame(client); + log('game-stopped', client, lobby) + } + + + //Saves user feedback to a file + saveFeedbackToFile(client: Client, content: string): void { + let date = new Date(Date.now()).toString(); + let path = "feedback/" + client.game + '.txt'; + let saveToFile = (content: string) => { + fs.writeFile(path, content, (err: any) => { + if (err) + log('save-error', client, null, err.message); + else + log('feedback', client, null, path) + }); + }; + if (fs.existsSync(path)) { + fs.readFile(path, 'utf8', (err, data) => { + if (err) + log('load-error', client, null, err.message); + else { + log('load-success', client, null); + let newContent = data + '\n\n\n\n' + date + '\n\n' + content; + saveToFile(newContent) + } + }) + } else { + saveToFile(date + '\n' + content) + } + } + + //Removes a disconnected client from all references + disconnected(client: Client): void { + let room = Room.getByClientId(client.id, this.rooms); + + if (room) + client.leaveRoom(room.id); + + log('disconnection', client) + } + +} + +export function serializeObject(object: any): any { + function serialize(obj: any) { + if (!obj) + return obj; + if (obj.serialized) + return obj.serialized; + else if (obj instanceof Array) { + let content = []; + obj.forEach(o => { + content.push(serialize(o)) + }); + return content + } + return obj + } + + return serialize(object) +} \ No newline at end of file diff --git a/server/src/room.ts b/server/src/room.ts new file mode 100644 index 0000000..caf3fea --- /dev/null +++ b/server/src/room.ts @@ -0,0 +1,136 @@ +import {Client} from "./client.js" +import {ServerGame} from "./game_standard.js" +import {serializeObject} from "./manager.js"; +import {Server} from "socket.io"; +import {Settings} from "./definitions/settings"; + +export class Room { + + id: string; + gameName: string; + clientCounts: number[]; + io: Server; + clients: Client[]; + runningGame: ServerGame; + settings: Settings.Global; + gameSettings: any; + name: string; + + static GameClass: typeof ServerGame + + constructor(name: string, id: string, settings?: Settings.Global, io?: Server) { + this.id = id; + this.name = name; + if (!io || !settings) return; + this.settings = settings; + this.gameName = settings.project.name; + this.clientCounts = settings.project.playerCounts; + this.io = io; + this.clients = []; + this.gameSettings = {} + } + + get leader(): Client { + return this.players[0] + } + + get players(): Client[] { + return this.clients.filter(c => c.isPlayer) + } + + get spectators(): Client[] { + return this.clients.filter(c => c.isSpectator) + } + + get serialized(): Serialized.Lobby { + return { + id: this.id, + name: this.name, + game: this.gameName, + clientCounts: this.clientCounts, + clients: serializeObject(this.clients), + hasStarted: this.hasStarted + }; + } + + get isEmpty(): boolean { + return !(this.clients.length) + } + + get hasStarted(): boolean { + return this.runningGame != null + } + + static getByRoomId(id: string, lobbies: Room[]): Room { + for (let l of lobbies) { + if (l.id === id) + return l + } + return null; + } + + static getByClientId(id: string, lobbies: Room[]): Room { + for (let l of lobbies) { + for (let c of l.clients) { + if (c.id === id) + return l + } + } + return null; + } + + static generateCode(elements: number): string { + let code = ''; + let possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + while (elements--) { + code += possible.charAt(Math.floor(Math.random() * possible.length)) + } + return code + } + + startGame(): void { + let seed = Math.random() * 10000; + this.toAll('start-game', seed); + this.runGame() + } + + stopGame(client: Client): void { + this.toAll('stop-game', client); + this.runningGame = null + } + + add(client: Client): void { + this.clients.push(client); + + let isPlayer = !this.hasStarted && this.hasValidPlayerCount(); + client.isPlayer = isPlayer; + client.isSpectator = !isPlayer; + client.isReady = false; + client.join(this.id); + + this.toAll('member-joined', client.id, client.name); + this.toAll('client-list', this.clients); + this.toAll('game-settings', this.gameSettings); + + if (this.hasStarted) + this.runningGame.addClient(client) + } + + hasValidPlayerCount(): boolean { + let valid = false; + this.clientCounts.forEach(c => { + if (c === this.clients.length) + valid = true + }); + return valid + } + + runGame(): void { + this.runningGame = new Room.GameClass(this, this.settings); + } + + toAll(event: string, ...args: any[]): void { + this.io.to(this.id).emit(event, serializeObject(this), ...serializeObject(args)) + } + +} \ No newline at end of file diff --git a/server/src/start.ts b/server/src/start.ts new file mode 100644 index 0000000..82293ed --- /dev/null +++ b/server/src/start.ts @@ -0,0 +1,39 @@ +import {ConnectionManager} from "./manager.js"; +import {log} from "./logger.js"; + +import {Server} from 'socket.io'; +import {Room} from "./room.js"; +import * as https from "https"; +import * as fs from "fs"; + +export function StartServer(settings: any){ + + require("dotenv").config(); + const httpsPort = parseInt(process.env.HTTPS_PORT); + + let cert = fs.readFileSync(`${process.env.SSL_PATH}/cert.pem`); + let key = fs.readFileSync(`${process.env.SSL_PATH}/key.pem`); + + let httpsServer = https.createServer({key: key, cert: cert}); + + let sIO = new Server(httpsServer, { + cors: { + origin: ["https://play.benjamin-kraft.local", "https://play.benjamin-kraft.eu"] + } + }); + if (settings.useP2P){ + const p2p = require('socket.io-p2p-server').Server; + sIO.use(p2p); + } + + httpsServer.listen(httpsPort); + + Room.GameClass = settings.gameClass; + + let connectionManager = new ConnectionManager(sIO); + + // On new connection + sIO.on('connection', socket => connectionManager.newSocket(socket)); + + log('startup', null, null, 'Server is listening on port ' + httpsPort); +} \ No newline at end of file diff --git a/server/tsconfig.json b/server/tsconfig.json new file mode 100644 index 0000000..87d4284 --- /dev/null +++ b/server/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "module": "CommonJS", + "alwaysStrict": true, + "sourceMap": true, + "outDir": "./out" + }, + "include": [ + "./src" + ] +} \ No newline at end of file