24 changed files with 2323 additions and 0 deletions
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
Recreate Love Letter as Browser Game (not for profit) |
||||
|
||||
Design Envisioned UI |
||||
Pick Modules around it |
||||
Express |
||||
Socket.IO |
||||
|
||||
Design Data Format |
||||
- Handle Multiple Games |
||||
- Allow Invites to Game |
||||
Design Backend |
||||
Design FrontEnd |
||||
Design an Invite Feature |
||||
Make it reconnectable |
||||
No logins, but have unique IDs |
||||
Make it https |
||||
Animations |
||||
Design Chat |
||||
Design Guide on how to play |
||||
Design Bots to play against |
||||
|
||||
#Basic setup with socket.io + Express |
||||
https://medium.com/@raj_36650/integrate-socket-io-with-node-js-express-2292ca13d891 |
||||
|
||||
#Guide for HTTPs on Express, SSL Cert |
||||
https://medium.com/@nitinpatel_20236/how-to-create-an-https-server-on-localhost-using-express-366435d61f28 |
||||
|
||||
#Socket.IO handling Cleaner |
||||
https://socket.io/docs/v4/server-application-structure/ |
||||
|
||||
#Automatic Node Reload on changes |
||||
https://stackoverflow.com/questions/45622125/how-can-i-add-live-reload-to-my-nodejs-server |
||||
|
||||
#socket.io, socket attributes |
||||
https://socket.io/docs/v4/client-socket-instance/ |
||||
|
||||
#MEVN stack. MongoDB, Express, VueJS, NodeJs |
||||
https://vegibit.com/vue-js-express-tutorial/ |
||||
https://mfikri.com/en/blog/nodejs-express-mysql-vue |
||||
|
||||
Install VUE Global |
||||
npm install -g @vue/cli |
||||
vue --version |
||||
|
||||
|
||||
___________________________________________________________________ |
||||
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIDWzCCAkOgAwIBAgIURu8OfAXOa5Hi1BdJO2SxEgrItuMwDQYJKoZIhvcNAQEL |
||||
BQAwPTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk1PMSEwHwYDVQQKDBhJbnRlcm5l |
||||
dCBXaWRnaXRzIFB0eSBMdGQwHhcNMjIwMjI1MTcwODUzWhcNMjMwMjI1MTcwODUz |
||||
WjA9MQswCQYDVQQGEwJVUzELMAkGA1UECAwCTU8xITAfBgNVBAoMGEludGVybmV0 |
||||
IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB |
||||
ANBWoQWSX8iyRuuMzN78ALkVLoEDGhQivpAj18n5VT4WNhpT3z7Gj2B2w6w3vsKv |
||||
XN28qILNBUcApzHMCawk4XyGgkTrFQzs2jTm5DKuU6dhn7lioMNzDgRVGieBuA0N |
||||
La3qa0gwem+fhJoT0Dm4tDeEoFEJeura6y0u/XRLm+uKSiLyo0tX12OYjgbbWh8Q |
||||
32aE6p0QqcHdFYRnUs5iy/SLkmYoMqNBrQWGAmjkYbHhwc2LhwvWEhv6HACE8Fk7 |
||||
QkAScf8V2CX/xpgqjJWgAhTp5zE/YKWQc4RH0hF2wMmVnMEDB7vmRPSuuRBlo+7y |
||||
DZTMPjg5KZ3jAwfzbQOLew8CAwEAAaNTMFEwHQYDVR0OBBYEFM582p8EGMRs3IVj |
||||
Q7pq20cNc+FWMB8GA1UdIwQYMBaAFM582p8EGMRs3IVjQ7pq20cNc+FWMA8GA1Ud |
||||
EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAA2d+WnGBysGoZMOkLt4hkb+ |
||||
UNp6oFcGNa/kd06UuEpFinsa82JPsAZWSNDNLqzTfTaUWFXCQkIGk2k/57NXOjXZ |
||||
3PhMJfjeR9jH3XRswxK9Dp8KaVyf1GTMbI6K+IKEULK/w2sOCAHEHVntIEPo5tCo |
||||
P4NAEmc0woPmm4NTqHU98zRR8Mqxu+112tOg3u+f6fr1YCI4o2jJeaDRdgivFYSr |
||||
V68YHq3GthzHxXLqynZBTReX8vF6fTzc7jaB79UFkgIuBwPscVYubk3PPJI0TQ38 |
||||
rR7nHmC6yB60Zsg+1TuCG5czS/TZuJUMoqj3hjTXVxPTaLgnga7vBBa+Gw21OYQ= |
||||
-----END CERTIFICATE----- |
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY----- |
||||
MIIEogIBAAKCAQEA0FahBZJfyLJG64zM3vwAuRUugQMaFCK+kCPXyflVPhY2GlPf |
||||
PsaPYHbDrDe+wq9c3byogs0FRwCnMcwJrCThfIaCROsVDOzaNObkMq5Tp2GfuWKg |
||||
w3MOBFUaJ4G4DQ0treprSDB6b5+EmhPQObi0N4SgUQl66trrLS79dEub64pKIvKj |
||||
S1fXY5iOBttaHxDfZoTqnRCpwd0VhGdSzmLL9IuSZigyo0GtBYYCaORhseHBzYuH |
||||
C9YSG/ocAITwWTtCQBJx/xXYJf/GmCqMlaACFOnnMT9gpZBzhEfSEXbAyZWcwQMH |
||||
u+ZE9K65EGWj7vINlMw+ODkpneMDB/NtA4t7DwIDAQABAoIBAAYoWVAB2ITlCAWU |
||||
PsXkat0NjDdR8SZhNIKsHIeir+tK2sSCcBm54qj2OahQaXn1lugS2GQtTRehJE/r |
||||
eOm2mVeF3jnNPO0J3xUrMdlxn5VV5FOlX50HPIXSQhii097G4e+++vbCQAwmidPH |
||||
/CKInAL8D4T1o8VnPQYz2lfimDQo7361mCytz0VEoPqAtXEHiyxq3ID9YZxFUGg1 |
||||
XFo63IhFp7fJU+mjmDLcSmCO+IAz7avdPWRKr2Fz7tI0+AipaaZSi8M+ej0IqHZs |
||||
nRzhxwVz60aVmVgdZsOfemqBR9+b9TTLSxyN4j7cjPv69w1g2pUki3rtFAuyPs/x |
||||
iaifp4kCgYEA+062Qic13JvI1werJqdE/UAIbEDOt5KGHJVpLnhScwqer7q3RmCs |
||||
xKZND4WJ64WfW9z+vkinswPfPgruNok/x8qVf673PGDEXimK2/jkRy0CKzLzdcHr |
||||
3tgRRTcu5Ejr1u/VIV+9axcmmODlHUYAUbRDssqf80g6jy+e7ra2/YMCgYEA1DqE |
||||
sCN5WJsnTnA6pjhcLcC3UQxQZ5d+iCEc/nWfYRcZsKdWh7A1xY2MDEiLWqj28x4G |
||||
mtThfu1f879t/N4yasQ7QA16RBQlquY4qfBGYcwoqY5e9V4xFg6kgTl6bgdcFc7/ |
||||
p7wcUm6KqD5PnxCSlOOwPlCUuPELHHXSf1YKQoUCgYBr/GGiwXiKiEJf68KmhF/H |
||||
trkn0x1AkmygYa9lsXw0RM71UfUo/6edhJw+XDJsiul0Lt0j5NJywOovncDInGdU |
||||
sX9V81f3kNkwYQdzCFsHHpb8+xLUefShuBSLum+i1pbIsBvUEHCzUKpcLN8mmgrP |
||||
EPe6HwlmH5ZSKrNPfiHZgwKBgGCRxCDV83hzGR6jCLzr9l3HTGLvxIJut9+/mY7b |
||||
/MrUFReB/Wi+sKkU8H4CYI6/Rad4qS644Wa9IqUqHSUsAir84a0StOjXdhBes7f4 |
||||
Ij6MBJCqvODPnGxZ+1blzaTVanxt9Xzgps6HiEZoHBjYFKr1NBQW3KWO4SxxHHhe |
||||
sUp1AoGADiduIMYTCQK9tTwzC+wi8L9ZzRzg8Bv9WoJwlOJ9UzebxZuoSE079WZy |
||||
R83WGVMfrGoRvt5o5zPPjXE1OVb1ZH/zqVxMqtXyNKpkaNA3zg3B+yd0t6j7r6KF |
||||
3rmR4RZQ4tvG4zSvoB6wRnQCMu5yT4Hy5UCO2okxUf/9ipkBxrI= |
||||
-----END RSA PRIVATE KEY----- |
||||
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
-----BEGIN ENCRYPTED PRIVATE KEY----- |
||||
MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIe3/Wm4HexdMCAggA |
||||
MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECHFVtycBEqVCBIIEyLgm/RkRojyc |
||||
D/pETZ9wG1BLaZC3ej6Gf1hYz3YN2ZAqXnRlNJcgniFw55QrxJxo1v9xQHacl8XR |
||||
BHTHozqegvbZBGV2ejrvHC5Ej0iFcoGez2Xo7UF+C7+qwPc1d6JjYTyev0hdfPN3 |
||||
jfqbpIhVG2iErG+VJeJm/HHDd6u3ikpxevfExwscDIC/LP9jMkvJQEvoSZIOjt1u |
||||
IU+i4OZa/ex+7rVtye+g+kXIzAF+hX6xf98Ra7grjc7MltRnvELXvFTgh42q5BeS |
||||
IWYgZDTDavsplMFp9khSBaweK1Lg7nNvRJ+3xhJmqQK9IBuO24SCPSP7eDlmdHds |
||||
KuOSa2wLHLl0Wj0ogd8TBV+Lu9RJplVrTuHumBVUrCgin0pgMT5pvrGNZBaF7lyf |
||||
oSMTTCizQglsXU/PaoS7MfAtTVM6QqPGKfdFS/QhdfWgeb6RXu1Uhc0e4FxrMBYF |
||||
nJPw+8InXRygXjLO9oGPmW2w9KycuxIxtsT7hFWEUqRS5zjXKE643DEgrRFuBaTT |
||||
08Tsd5W1H6Na9Madj48OHJ/lp4O27HsJn5WebbkQQhS2g+OTObgYX7FvLs8DFyQ9 |
||||
6OfIE9jMmTdxwI1EuIyDsTlRhGcF7K8gs7Zpt8F0VBE3U1zQNxdtwS0sR5azZa1+ |
||||
mU1Twp5TfYW10jvWGES4VPNiwTIcPLhIBr8t+x4wqejBvpW5Ya4M2uEBSi30TKSk |
||||
YGAx1++Xmm8zKXnr42S7Xk8FfmXNmOOj0hHerdqw7vMwnQt/4n5xNafsvAL3Yd3e |
||||
6X1n6wiRF/KtkBi9CtQc+yL8+QZSAr0S1V6rfwi3arZG5QxAi3bAtPghll+XeICl |
||||
W/UDus9QCWKU6MjStXH7X7hAIHOJrr7+9WxAHFG1KNVg18Xb/D5dKP6+6GDptXHG |
||||
sH/K43cqJu50pwTxk9/wyfmUOrxYuSauwX42hIahppnxLKh3MPZ2PsVLegT/KDhR |
||||
KX+QBKup0+0oqGoATe91GWIQZXFcPCYQabQegL+p9fFjDiW3kCbJAa5wnxxI4dCk |
||||
W044AsQdg+80qZckJmJ6+LwmPsKzxwgwOoCrVp8e4XIsl9IGKkOBRj4BdN1OqjJa |
||||
dH/ogI1rIst8lbfiEbk6jilFr/gsDDQwuZNU9QbHWTj+/HjPEIEL4QCQDPCSOyTP |
||||
5+FWqxrn04k7ThqMegPzwXPMvPtA6BmCZ4Vl4eKS1S0u9WfitDOYyng+H42/u3Ji |
||||
73GUVEmZ73RT4jPPDjS02y/Owvx5FLa9bs0rcd9fBVJay+dPovHmrQknj4lcziC4 |
||||
ly9AzaQByEHIoViiJuagU1MjxA9EJUa0FJ12g1lOr0HfeypWzCsleHQCPkGTyJQX |
||||
FyrQq8q0Jf38L5h2KEtF6Po1bUL+F7S6cwpkFkYGgsAYM+zpMVT2kXA0pP75Ca+g |
||||
w+HKRhXgbMmqKDuJTbs4UHgeofqrb+T3rXyk4gfgjNXmNfzwaoENKDVHiv7yp8Og |
||||
6qs2vdphNaxSf4iKd/ybaCAzCJlWnWEGUqyhYfKYaFJAmQx8fhw7zGRD2I8lKGz+ |
||||
YW7hGnmLUB68M7i1QUHHDBm8hxLSaSJPyOIHnKhX06DTuHyIsPmfi8i3VAkzkiaV |
||||
t4drORAApx1BSzNTI0xTWg== |
||||
-----END ENCRYPTED PRIVATE KEY----- |
||||
@ -0,0 +1,22 @@
@@ -0,0 +1,22 @@
|
||||
-----BEGIN CERTIFICATE----- |
||||
MIIDpzCCAo+gAwIBAgIUVgja2cJarOptGTXo5bwdUx2WGLswDQYJKoZIhvcNAQEL |
||||
BQAwYzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk1PMQswCQYDVQQHDAJLQzESMBAG |
||||
A1UECgwJbG9jYWxob3N0MRIwEAYDVQQLDAlsb2NhbGhvc3QxEjAQBgNVBAMMCWxv |
||||
Y2FsaG9zdDAeFw0yMjAzMjkxNzU5MjVaFw0yMjA0MjgxNzU5MjVaMGMxCzAJBgNV |
||||
BAYTAlVTMQswCQYDVQQIDAJNTzELMAkGA1UEBwwCS0MxEjAQBgNVBAoMCWxvY2Fs |
||||
aG9zdDESMBAGA1UECwwJbG9jYWxob3N0MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEi |
||||
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDpc68E8r32hLbMPUawJZwTaQn2 |
||||
RoGMHoOSzfHqOXcjF0D0QIOgeO2uMYJ6nMh4AfSKjRkOK2oJO4fknp72ArrK+S7x |
||||
KVaMg6T0FaVsffFYJO8/aujUBhnEyF+dAtyveABfMrJwU+/uTuwKJAJz7wvOl+3/ |
||||
7Idop49PAWo64HYlJkl3iQUuVmBL2kpyrHLNnTIT8HBKsLJVnO2IzozQnTrI0CnF |
||||
PFgdqjdPyTurJYhIYRNsSL1ZpTBdWoeZPCWIjYGr9X4Om4aaAkD3bWmaPNYwIaja |
||||
GwBaCfKTnGw9+EWDXrQxZfpOqVJp/19ZFTsoMGIJo0LtPRgmOwAFkjSfXwArAgMB |
||||
AAGjUzBRMB0GA1UdDgQWBBRFm+iZPyUN8ZMfGfnWO3iBbas15DAfBgNVHSMEGDAW |
||||
gBRFm+iZPyUN8ZMfGfnWO3iBbas15DAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 |
||||
DQEBCwUAA4IBAQDacoUJOm0Y8vm8hwqgqres3kYD2sQAYMsU146hfUeNfcRXIYYK |
||||
TLFiu6/bEc+85riZerZQCDFzPcVGJT4NPTkQkofYhkPG8UpDdEH/o8kZn5icDYoX |
||||
KcB/V8mOtSi+zN3Hol88XmfMkFDxeNYkUvI2vfycAE8PR21pKcnR6UROZBkMuCMC |
||||
p/wJY6cmaPNKwZGaGLWqlNcOFV1xEYQnFYm3IYsBjnQslhyU4Wpnd6MiZQ3uoerk |
||||
9fl4IGsu3BAkTkdAaibsnmUp4/SorvGoYi+hGJ/NvPherMjsINVP5MNH+uUqf2QT |
||||
f6nor/JgODkq1BXSAYJxY4xtD6hYNm/qWh6w |
||||
-----END CERTIFICATE----- |
||||
@ -0,0 +1,28 @@
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY----- |
||||
MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDpc68E8r32hLbM |
||||
PUawJZwTaQn2RoGMHoOSzfHqOXcjF0D0QIOgeO2uMYJ6nMh4AfSKjRkOK2oJO4fk |
||||
np72ArrK+S7xKVaMg6T0FaVsffFYJO8/aujUBhnEyF+dAtyveABfMrJwU+/uTuwK |
||||
JAJz7wvOl+3/7Idop49PAWo64HYlJkl3iQUuVmBL2kpyrHLNnTIT8HBKsLJVnO2I |
||||
zozQnTrI0CnFPFgdqjdPyTurJYhIYRNsSL1ZpTBdWoeZPCWIjYGr9X4Om4aaAkD3 |
||||
bWmaPNYwIajaGwBaCfKTnGw9+EWDXrQxZfpOqVJp/19ZFTsoMGIJo0LtPRgmOwAF |
||||
kjSfXwArAgMBAAECggEBANlkzfXYqod3HNbitQHxc/8rUIiTLa4y+ClsOLv6GXSH |
||||
AgiyTyDPm94b4rqVZ6VBhNzE+jEUwqCoXCrMf5DuB85d75XJ/fvJ14Eo6yw1t9py |
||||
Qo0W3IwcxkBWq5sGAEYyhH4iMsKhl4ue2PW0hMg7Mg6Hsq0hMROG/c//rFH5lmuO |
||||
DXuTG+iaJXbQn+TT/i2aSESuXDdKFM9LfB4k4VS+OCKYxFT38fFEI/lzeABc2tsh |
||||
g48PGdVgZjfcjVLzziwyG0TL7XjPuqSe4rFTTea79LTbXp/ck50ivqKT4TpdD7Ck |
||||
7kPTFkrXxyg74V+brD0vpJpmu54sFU2/G0z4CDZIGOECgYEA+IOEMTIqBDFtPrEc |
||||
IbBZWodfKMaOJqRq1ifypcMsZeSXNS2zjg4isdonh0WXsZXMUq04T1yh2d1MPcjP |
||||
Glc16dfpsEzF/f96ujjCJ7RA+QjQQ3K8mVAfjLr9hRbrqCMVHLo5DQ+rw5Uw5C6o |
||||
6z8ZeexFxLsHKh341akKi0waKHECgYEA8HwDfOhtsCySbSW65+h2y77K4s+EYyPh |
||||
6V0fGrIDrUtGVkAfmkpMEpjU+qempklKt5/mFqkWkXbjGUD+vz413ZMObsXaEPKU |
||||
JZ+XGuD9D80vfxqZp7w3Fjhzh8A23jYICFv3joZ0qs5M5jV67nFCW0ffh4ehD6dZ |
||||
o5N/CUuMoFsCgYEAzJ8tl3xgkDdKZlZafXrA+AOC3QYwQa0bst4Ns2MzCWrg/g51 |
||||
S8Bj3OFtrroknzpilKjANshlFAhdIHpZ3Kx2XedEKb/tPqi/mtnlM9/9p5AUO5Ub |
||||
qXkJoUzONmma/ER2u8Kx+wkuOsp7CUdKGvlHttZO1B/TVGB9ZR/c6LluyGECgYEA |
||||
v9iPB8R8TMEiBwTEeGFQ8/U+8XXPDTAA9yQcvjUpDcQxVnlNPM7spSFbNqMsJRfv |
||||
DVH4QjeeE2meffUFxRch7aN1LhWUg1ShruoDp6O4/jQYIfPchJ137LgYIkHLA7Zi |
||||
7hhAA2lsBR8S5cvgR/v+jcdmoT4n1M8SiZYPECE/DGUCgYEAnh5lIWpDdw2vcnW4 |
||||
/lgb1I9oXRZcLIYha+WhC6PXHAUqdTAk+afefmjF1QEIgu2lYZQU28TZDcTn2OgN |
||||
PVPuKItJjoTz/c6npgLABkn6dDuRfnAfFV2tj6mPmqQ70A9B8B4ql3f3tbiQOQPC |
||||
ZXPCc/cVEOJnBGT7wtZTdhP6eV8= |
||||
-----END PRIVATE KEY----- |
||||
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
let validCharacters = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'] |
||||
|
||||
genRandomString = (stringLength) => { |
||||
let newString = '' |
||||
for (let i = 0; i < stringLength; i++) { |
||||
$index = Math.floor(Math.random() * 35) |
||||
newString += validCharacters[$index] |
||||
} |
||||
return newString |
||||
} |
||||
|
||||
module.exports = { |
||||
genRandomString: genRandomString |
||||
} |
||||
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
// // sleep function
|
||||
// const sleep = (milliseconds) => {
|
||||
// const date = Date.now()
|
||||
// let currentDate = null
|
||||
// do {
|
||||
// currentDate = Date.now()
|
||||
// } while (currentDate - date < milliseconds)
|
||||
// }
|
||||
|
||||
const sleep = (ms) => { |
||||
return new Promise(resolve => setTimeout(resolve, ms)) |
||||
} |
||||
|
||||
module.exports = { |
||||
sleep: sleep |
||||
} |
||||
@ -0,0 +1,58 @@
@@ -0,0 +1,58 @@
|
||||
// Make console colors
|
||||
// based on what I found here:
|
||||
// https://www.kindacode.com/article/node-js-colorizing-console-log-output/
|
||||
// color chart found here:
|
||||
// https://en.m.wikipedia.org/wiki/ANSI_escape_code#Colors
|
||||
|
||||
// // red
|
||||
// console.log('\x1b[31m%s\x1b[0m', 'I am red')
|
||||
// // green
|
||||
// console.log('\x1b[32m%s\x1b[0m', 'I am green')
|
||||
// // yellow
|
||||
// console.log('\x1b[33m%s\x1b[0m', 'I am yellow')
|
||||
// // blue
|
||||
// console.log('\x1b[34m%s\x1b[0m', 'I am blue')
|
||||
// // magenta
|
||||
// console.log('\x1b[35m%s\x1b[0m', 'I am magenta')
|
||||
// // cyan
|
||||
// console.log('\x1b[36m%s\x1b[0m', 'I am cyan')
|
||||
|
||||
const wrtColorRed = (text) => { |
||||
console.log('\x1b[31m%s\x1b[0m', text) |
||||
} |
||||
const wrtColorGreen = (text) => { |
||||
console.log('\x1b[32m%s\x1b[0m', text) |
||||
} |
||||
const wrtColorYellow = (text) => { |
||||
console.log('\x1b[33m%s\x1b[0m', text) |
||||
} |
||||
const wrtColorBlue = (text) => { |
||||
console.log('\x1b[34m%s\x1b[0m', text) |
||||
} |
||||
const wrtColorMagenta = (text) => { |
||||
console.log('\x1b[35m%s\x1b[0m', text) |
||||
} |
||||
const wrtColorCyan = (text) => { |
||||
console.log('\x1b[36m%s\x1b[0m', text) |
||||
} |
||||
const wrtErr = (text) => { //Black on Red
|
||||
console.log('\x1b[30;41m%s\x1b[0m', text) |
||||
} |
||||
const wrtWarn = (text) => { //Black on Red
|
||||
console.log('\x1b[30;43m%s\x1b[0m', text) |
||||
} |
||||
const wrtTest = (text) => { // Green on Black
|
||||
console.log('\x1b[92;100m%s\x1b[0m', text) |
||||
} |
||||
|
||||
module.exports = { |
||||
red: wrtColorRed, |
||||
green: wrtColorGreen, |
||||
yellow: wrtColorYellow, |
||||
blue: wrtColorBlue, |
||||
magenta: wrtColorMagenta, |
||||
cyan: wrtColorCyan, |
||||
err: wrtErr, |
||||
warn: wrtWarn, |
||||
test: wrtTest, |
||||
} |
||||
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
// Object Definitions
|
||||
class player { |
||||
constructor (userid, |
||||
username, |
||||
gameid, |
||||
lastActivity, |
||||
connected) { |
||||
this.userid = userid |
||||
this.username = username |
||||
this.gameid = gameid |
||||
this.lastActivity = lastActivity |
||||
this.connected = connected |
||||
} |
||||
} |
||||
class table { |
||||
} |
||||
class game { |
||||
} |
||||
// Object Initialization
|
||||
let state = { |
||||
players:[], |
||||
tables:[], |
||||
games:[] |
||||
} |
||||
|
||||
module.exports = { |
||||
state: state, |
||||
players: state.players |
||||
} |
||||
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
const serverConfig = require('../../config/serverConfig.js') // Server Config
|
||||
const wrtColor = require('../common/wrtColor') |
||||
// const { sleep } = require('./common/sleep')
|
||||
|
||||
function filterExpired(player) { |
||||
// let diff = ((new Date())-player.lastActivity)
|
||||
// console.log(`${player.username} diff: ${diff}`)
|
||||
if (((new Date())-player.lastActivity) <= serverConfig.playerExpiration) { |
||||
return player |
||||
} else { |
||||
// console.log(`Expired Session: ${player.username}`)
|
||||
wrtColor.magenta(`Expired Session: ${player.username}`) |
||||
} |
||||
} |
||||
|
||||
function playerCleanup (state) { |
||||
// setInterval(function() { //<--This works, but I'm concerned about Memory Leak. I need to learn more.
|
||||
// console.log(state)
|
||||
// state.players = state.players.filter(checkExpired)
|
||||
// }, serverConfig.cleanupInterval)
|
||||
|
||||
//setTimeout Version self-calling function
|
||||
let timerId = setTimeout(function tick() { |
||||
// console.log(state)
|
||||
state.players = state.players.filter(filterExpired) |
||||
timerId = setTimeout(tick, serverConfig.cleanupInterval) |
||||
}, serverConfig.cleanupInterval) |
||||
} |
||||
|
||||
module.exports = { |
||||
playerCleanup: playerCleanup |
||||
} |
||||
@ -0,0 +1,66 @@
@@ -0,0 +1,66 @@
|
||||
// Sends Updates to socket when players change
|
||||
const wrtColor = require('../common/wrtColor') |
||||
|
||||
function mapRemoveLastActivityProp (player) { |
||||
// Make this specific by props to remove
|
||||
let {lastActivity, ...other} = player |
||||
// return {
|
||||
// id: player.id,
|
||||
// username: player.username,
|
||||
// gameid: player.gameid
|
||||
// }
|
||||
return other |
||||
} |
||||
|
||||
function continuousEmitPlayers (state,io) { |
||||
let previousPlayersRelevant = [] |
||||
let timerId = setTimeout(function tick() { |
||||
// get players excluding the "lastActivity" because it is constantly updating
|
||||
playersRelevant = state.players.map(mapRemoveLastActivityProp) |
||||
// console.log(playersRelevant)
|
||||
// convert to string for comparison
|
||||
if ((JSON.stringify(playersRelevant)) !== (JSON.stringify(previousPlayersRelevant))) { |
||||
// if changes happen, emit to all sockets
|
||||
// wrtColor.blue('change to Players. Push to Sockets')
|
||||
io.emit('playersUpdate', playersRelevant) |
||||
} |
||||
previousPlayersRelevant = playersRelevant |
||||
timerId = setTimeout(tick, 1000) |
||||
}, 1000) |
||||
} |
||||
|
||||
function socketGetPlayers (state,socket) { |
||||
playersRelevant = state.players.map(mapRemoveLastActivityProp) |
||||
socket.emit('playersUpdate', playersRelevant) |
||||
} |
||||
|
||||
function checkValidPlayerName(players,name) { |
||||
|
||||
let response = { |
||||
valid: true, |
||||
reason: "" |
||||
} |
||||
|
||||
// Returns True/False
|
||||
// 15 character limit
|
||||
// No special characters
|
||||
// name not in use already
|
||||
|
||||
|
||||
} |
||||
|
||||
function socketRegisterPlayer (io,state,data) { |
||||
wrtColor.warn('socketRegisterPlayer') |
||||
console.log(data) |
||||
//console.log(state.players)
|
||||
io.emit('msg',{poop:"salad"}) |
||||
let checkResult = checkValidPlayerName(state.players, name) |
||||
console.log(checkResult) |
||||
// add them to state.players
|
||||
} |
||||
|
||||
module.exports = { |
||||
continuousEmitPlayers: continuousEmitPlayers, |
||||
socketGetPlayers: socketGetPlayers, |
||||
socketRegisterPlayer: socketRegisterPlayer, |
||||
} |
||||
@ -0,0 +1,52 @@
@@ -0,0 +1,52 @@
|
||||
// const serverConfig = require('../config/serverConfig.js')
|
||||
const wrtColor = require('./common/wrtColor') |
||||
|
||||
//Load Object Definitions and Initialize them
|
||||
require('./objectDefinitions') |
||||
let { state } = require('./objectDefinitions') |
||||
|
||||
|
||||
// TODO: TEST FUNCTIONS
|
||||
require('./testFunctions') |
||||
const { addTestPlayers, addFluxPlayers } = require('./testFunctions') |
||||
wrtColor.test('adding Test Players') |
||||
addTestPlayers(state.players) |
||||
addFluxPlayers(state) |
||||
|
||||
|
||||
|
||||
//--- Socket Handling ---
|
||||
const { socketGetPlayers } = require('./players/playerMgmtFuncs') |
||||
const { continuousEmitPlayers } = require ('./players/playerMgmtFuncs') |
||||
const { socketRegisterPlayer } = require ('./players/playerMgmtFuncs') |
||||
function socketHandler (io) { |
||||
io.on('connection', function (socket) { |
||||
//--- Connection ---
|
||||
wrtColor.cyan(`socket connection established, id ${socket.id}`) |
||||
|
||||
//--- Register other socket event handler functions ---
|
||||
socket.on('getPlayers', () => socketGetPlayers(state,socket)) |
||||
socket.on('registerPlayer', (data) => socketRegisterPlayer(io,state,data)) |
||||
//......//
|
||||
|
||||
//--- Disconnection ---
|
||||
socket.on('disconnect', (reason) => { wrtColor.yellow(`socket disconnected, ${socket.id}, ${reason}`)}) |
||||
}) |
||||
|
||||
//--- Continuous Processes for Sockets ---
|
||||
continuousEmitPlayers(state,io) |
||||
} |
||||
|
||||
|
||||
//--- Continuous Server Side Processes ---
|
||||
const { playerCleanup } = require('./players/playerCleanup') |
||||
const { stateMonitor } = require('./stateMonitor') |
||||
playerCleanup(state) |
||||
stateMonitor(state) |
||||
|
||||
|
||||
|
||||
module.exports = { |
||||
socketHandler: socketHandler |
||||
} |
||||
|
||||
@ -0,0 +1,22 @@
@@ -0,0 +1,22 @@
|
||||
const serverConfig = require('../config/serverConfig.js') // Server Config
|
||||
const wrtColor = require('./common/wrtColor') |
||||
const fs = require('fs') |
||||
|
||||
|
||||
|
||||
function stateMonitor (state) { |
||||
setInterval(function() { |
||||
// Convert to string
|
||||
let stateString = JSON.stringify(state, null, 2) |
||||
fs.writeFile(serverConfig.stateJsonPath, stateString, (err) => { |
||||
if (err) { |
||||
throw err |
||||
} |
||||
// wrtColor.blue("state.json saved")
|
||||
}) |
||||
}, serverConfig.stateMonitorRate) |
||||
} |
||||
|
||||
module.exports = { |
||||
stateMonitor: stateMonitor |
||||
} |
||||
@ -0,0 +1,90 @@
@@ -0,0 +1,90 @@
|
||||
const { genRandomString } = require('./common/randomString') |
||||
const serverConfig = require('../config/serverConfig.js') |
||||
const wrtColor = require('./common/wrtColor') |
||||
const { state } = require('./objectDefinitions') |
||||
|
||||
let t = new Date() |
||||
let m15 = t.setSeconds(t.getSeconds()-15) |
||||
let p30 = t.setSeconds(t.getSeconds()+30) |
||||
let p45 = t.setSeconds(t.getSeconds()+45) |
||||
let p60 = t.setSeconds(t.getSeconds()+60) |
||||
|
||||
|
||||
function addTestPlayers(players) { |
||||
players.push({ |
||||
id: genRandomString(serverConfig.playerIdLength), |
||||
username: 'Charlie', |
||||
gameid: 222, |
||||
lastActivity: p30, |
||||
connected: false |
||||
}) |
||||
players.push({ |
||||
id: genRandomString(serverConfig.playerIdLength), |
||||
username: 'Dee', |
||||
gameid: 222, |
||||
lastActivity: p45, |
||||
connected: false |
||||
}) |
||||
players.push({ |
||||
id: genRandomString(serverConfig.playerIdLength), |
||||
username: 'Dennis', |
||||
gameid: 222, |
||||
lastActivity: p60, |
||||
connected: false |
||||
}) |
||||
players.push({ |
||||
id: genRandomString(serverConfig.playerIdLength), |
||||
username: 'Frank', |
||||
gameid: 222, |
||||
lastActivity: m15, |
||||
connected: true |
||||
}) |
||||
players.push({ |
||||
id: genRandomString(serverConfig.playerIdLength), |
||||
username: 'Mac', |
||||
gameid: 222, |
||||
lastActivity: p30, |
||||
connected: true |
||||
}) |
||||
} |
||||
|
||||
function addFluxPlayers (state) { |
||||
// Add and remove Pondy from players every 5 seconds
|
||||
setInterval(function () { |
||||
// PONDY
|
||||
// console.log(players)
|
||||
let pondyFound = false |
||||
for (let i = 0; i < state.players.length; i++) { |
||||
if (state.players[i].username === 'Pondy') { |
||||
pondyFound = true |
||||
break |
||||
} |
||||
} |
||||
if (pondyFound) { |
||||
// wrtColor.yellow('Pondy Found, removing')
|
||||
let pondyFilteredPlayers = state.players.filter( function (player) { |
||||
if (player.username !== 'Pondy') { |
||||
return player |
||||
} |
||||
}) |
||||
// console.log(pondyFilteredPlayers)
|
||||
state.players = pondyFilteredPlayers |
||||
} else { |
||||
// wrtColor.yellow('Pondy Not Found, adding')
|
||||
let t = new Date() |
||||
let p30 = t.setSeconds(t.getSeconds()+30) |
||||
state.players.push({ |
||||
id: genRandomString(serverConfig.playerIdLength), |
||||
username: 'Pondy', |
||||
gameid: 222, |
||||
lastActivity: p30, |
||||
connected: true |
||||
}) |
||||
} |
||||
}, 5000) |
||||
} |
||||
|
||||
module.exports = { |
||||
addTestPlayers: addTestPlayers, |
||||
addFluxPlayers: addFluxPlayers |
||||
} |
||||
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
module.exports = { |
||||
// Server
|
||||
certKeyPath: './cert/server.key', //Called by server.js
|
||||
certPath: './cert/server.cert', //Called by server.js
|
||||
httpsPort: 9000, |
||||
frontEndUrl: 'https://localhost', // Vue running from https
|
||||
//PlayerCleanup
|
||||
cleanupInterval: 5000, // runs every 5 seconds
|
||||
playerExpiration: 60000, //300000, // 5 minutes without activity before being removed
|
||||
//State Monitor
|
||||
stateJsonPath: './log/state.json', |
||||
stateMonitorRate: 1000, |
||||
//Player Settings
|
||||
playersUpdateCheckRate: 500, // Rate between checks to send player updates to sockets
|
||||
|
||||
playerNameMaxLength: 15, |
||||
playerIdLength: 6, |
||||
} |
||||
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
{ |
||||
"players": [], |
||||
"tables": [], |
||||
"games": [] |
||||
} |
||||
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
{ |
||||
"name": "loveletter", |
||||
"version": "1.0.0", |
||||
"description": "", |
||||
"main": "index.js", |
||||
"scripts": { |
||||
"test": "echo \"Error: no test specified\" && exit 1", |
||||
"start": "node server.js", |
||||
"live": "nodemon server.js --ignore ./log/" |
||||
}, |
||||
"author": "", |
||||
"license": "ISC", |
||||
"dependencies": { |
||||
"cors": "^2.8.5", |
||||
"express": "^4.17.3", |
||||
"socket.io": "^4.4.1", |
||||
"vue-router": "^4.0.13" |
||||
} |
||||
} |
||||
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
const path = require('path') |
||||
const fs = require('fs') |
||||
const express = require('express') |
||||
const serverConfig = require('./config/serverConfig.js') // Server Config
|
||||
const wrtColor = require('./components/common/wrtColor') |
||||
|
||||
//Http 80 Route traffic to the frontend VUE application running with HTTPS
|
||||
const http = require('http') |
||||
const httpApp = express() |
||||
httpApp.all('*', (req, res) => res.redirect(301, `${serverConfig.frontEndUrl}`)) //301 - Moved Permanently
|
||||
const httpServer = http.createServer(httpApp) |
||||
httpServer.listen(80, () => { |
||||
//console.log(`http redirectiong 80 to Vue front end at ${serverConfig.frontEndUrl}`)
|
||||
wrtColor.green(`http redirectiong 80 to Vue front end at ${serverConfig.frontEndUrl}`) |
||||
}) |
||||
|
||||
//Https to run socket.io
|
||||
const https = require('https') |
||||
const httpsApp = express() |
||||
const keyPath = fs.readFileSync(path.resolve(__dirname, `${serverConfig.certKeyPath}`)) |
||||
const certPath = fs.readFileSync(path.resolve(__dirname, `${serverConfig.certPath}`)) |
||||
const servOptions = { |
||||
key: keyPath, |
||||
cert: certPath |
||||
} |
||||
const httpsServer = https.createServer(servOptions,httpsApp) |
||||
httpsServer.listen(serverConfig.httpsPort, () => { |
||||
//console.log(`https listening on ${serverConfig.httpsPort} to handle socket.io requests`)
|
||||
wrtColor.green(`https listening on ${serverConfig.httpsPort} to handle socket.io requests`) |
||||
}) |
||||
|
||||
// Attach Socket.IO to https server
|
||||
const io = require('socket.io') (httpsServer, { |
||||
cors: { //https://socket.io/docs/v3/handling-cors/
|
||||
origin: `${serverConfig.frontEndUrl}`, |
||||
methods: ["GET", "POST"] |
||||
} |
||||
}) |
||||
|
||||
//load gameManagement
|
||||
require('./components/serverMgmt') |
||||
//pass socket.io connections to socketHandler
|
||||
const { socketHandler } = require('./components/serverMgmt.js') |
||||
socketHandler(io) |
||||
Loading…
Reference in new issue