diff --git a/index.js b/index.js index 7dda799..e9c615a 100644 --- a/index.js +++ b/index.js @@ -5,7 +5,7 @@ See file "LICENSE" or go to "https://choosealicense.com/licenses/mit" for full license details. */ -const ld = require ('node-ld') +const ld = require('node-ld') const fs = require('fs'); const path = require('path'); const { DH_CHECK_P_NOT_PRIME } = require('constants'); @@ -38,21 +38,21 @@ var connection = false; * Pages 23 & 25 are the upgrade data */ -function createVehicle(id, upgrades, uid){ - upgrades = upgrades || [0,0]; +function createVehicle(id, upgrades, uid) { + upgrades = upgrades || [0, 0]; var token = new Buffer(180); token.fill(0); token.uid = uid; //console.log(upgrades); - token.writeUInt32LE(upgrades[0],0x23*4); - token.writeUInt16LE(id,0x24*4); - token.writeUInt32LE(upgrades[1],0x25*4); - token.writeUInt16BE(1,0x26*4); //Page 26 is used for verification of somekind. + token.writeUInt32LE(upgrades[0], 0x23 * 4); + token.writeUInt16LE(id, 0x24 * 4); + token.writeUInt32LE(upgrades[1], 0x25 * 4); + token.writeUInt16BE(1, 0x26 * 4); //Page 26 is used for verification of somekind. return token; } //Create a token JSON object from provided character data -function createCharacter(id, uid){ +function createCharacter(id, uid) { var token = new Buffer(180) token.fill(0); // Game really only cares about 0x26 being 0 and D4 returning an ID token.uid = uid; @@ -61,8 +61,8 @@ function createCharacter(id, uid){ } //This finds a character or vehicles name from the ID provided. -function getNameFromID(id){ - if(id < 1000) +function getNameFromID(id) { + if (id < 1000) dbfilename = './server/json/charactermap.json'; else dbfilename = './server/json/tokenmap.json'; @@ -70,101 +70,101 @@ function getNameFromID(id){ const data = fs.readFileSync(dbfilename, 'utf8'); const databases = JSON.parse(data); databases.forEach(db => { - if(id == db.id){ + if (id == db.id) { name = db.name } - }); + }); return name; } //This finds and returns an JSON entry from toytags.json with the matching uid. -function getJSONFromUID(uid){ +function getJSONFromUID(uid) { const data = fs.readFileSync(toytagFileName, 'utf8'); const databases = JSON.parse(data); var entry; databases.forEach(db => { - if(db.uid==uid) + if (db.uid == uid) entry = db; - }); + }); return entry; } //This updates the pad index of a tag in toytags.json, so that info can be accessed locally. -function updatePadIndex(uid, index){ +function updatePadIndex(uid, index) { console.log('Planning to set UID: ' + uid + ' to index ' + index); const data = fs.readFileSync(toytagFileName, 'utf8'); const databases = JSON.parse(data); databases.forEach(db => { - if(uid == db.uid){ + if (uid == db.uid) { db.index = index; } - }); - fs.writeFileSync(toytagFileName, JSON.stringify(databases, null, 4), function(){ + }); + fs.writeFileSync(toytagFileName, JSON.stringify(databases, null, 4), function () { console.log('Set UID: ' + uid + ' to index ' + index); }) } //This searches toytags.json and returns to UID of the entry with the matching index. -function getUIDFromIndex(index){ +function getUIDFromIndex(index) { const data = fs.readFileSync(toytagFileName, 'utf8'); const databases = JSON.parse(data); var uid; databases.forEach(db => { - if(index == db.index){ + if (index == db.index) { uid = db.uid; } - }); + }); return uid; } //This updates the provided datatype, of the entry with the matching uid, with the provided data. -function writeJSONData(uid, datatype, data){ - console.log('Planning to set '+ datatype + ' of ' + uid + ' to ' + data); +function writeJSONData(uid, datatype, data) { + console.log('Planning to set ' + datatype + ' of ' + uid + ' to ' + data); const tags = fs.readFileSync(toytagFileName, 'utf8'); const databases = JSON.parse(tags); databases.forEach(db => { - if(uid == db.uid){ + if (uid == db.uid) { db[datatype] = data; return; } - }); - fs.writeFileSync(toytagFileName, JSON.stringify(databases, null, 4), function(){ - console.log('Set '+ datatype + ' of ' + uid + ' to ' + data); + }); + fs.writeFileSync(toytagFileName, JSON.stringify(databases, null, 4), function () { + console.log('Set ' + datatype + ' of ' + uid + ' to ' + data); }) } //This sets all saved index values to '-1' (meaning unplaced). -function initalizeToyTagsJSON(){ +function initalizeToyTagsJSON() { const data = fs.readFileSync(toytagFileName, 'utf8'); const databases = JSON.parse(data); databases.forEach(db => { db.index = "-1"; - }); - fs.writeFileSync(toytagFileName, JSON.stringify(databases, null, 4), function(){ + }); + fs.writeFileSync(toytagFileName, JSON.stringify(databases, null, 4), function () { console.log("Initalized toytags.JSON"); io.emit("refreshTokens"); }) } -function RGBToHex(r,g,b) { +function RGBToHex(r, g, b) { r = r.toString(16); g = g.toString(16); b = b.toString(16); - + if (r.length == 1) - r = "0" + r; + r = "0" + r; if (g.length == 1) - g = "0" + g; + g = "0" + g; if (b.length == 1) - b = "0" + b; - + b = "0" + b; + return "#" + r + g + b; - } +} function getUIDAtPad(index) { token = tp._tokens.find(t => t.index == index); - if(token != null) + if (token != null) return token.uid; else return -1; @@ -194,27 +194,27 @@ tp.hook(tp.CMD_WRITE, (req, res) => { console.log('REQUEST (CMD_WRITE): index:', ind, 'page', page, 'data', data); //The ID is stored in page 24 - if(page == 24 || page == 36){ - writeJSONData(uid,"id",data.readInt16LE(0)); + if (page == 24 || page == 36) { + writeJSONData(uid, "id", data.readInt16LE(0)); var name = getNameFromID(data.readInt16LE(0)); - writeJSONData(uid,"name",name); - writeJSONData(uid,"type","vehicle"); + writeJSONData(uid, "name", name); + writeJSONData(uid, "type", "vehicle"); //writeVehicleData(uid, "uid", tp.randomUID()) } //Vehicle uprades are stored in Pages 23 & 25 - else if(page == 23 || page == 35) + else if (page == 23 || page == 35) writeJSONData(uid, "vehicleUpgradesP23", data.readUInt32LE(0)); - else if (page == 25 || page == 37){ + else if (page == 25 || page == 37) { writeJSONData(uid, "vehicleUpgradesP25", data.readUInt32LE(0)); io.emit("refreshTokens"); //Refreshes the html's tag gui. } res.payload = new Buffer('00', 'hex'); var token = tp._tokens.find(t => t.index == ind); - if (token){ + if (token) { req.payload.copy(token.token, 4 * page, 2, 6); } - + }); //Colors @@ -224,17 +224,17 @@ tp.hook(tp.CMD_COL, (req, res) => { console.log(' => red:', req.payload[1]) console.log(' => green:', req.payload[2]) console.log(' => blue:', req.payload[3]) - const pad_number = req.payload[0]; + const pad_number = req.payload[0]; const pad_color = RGBToHex(req.payload[1], req.payload[2], req.payload[3]); - if(pad_number == 0) + if (pad_number == 0) io.emit("Color All", [pad_color, pad_color, pad_color]); else io.emit("Color One", [pad_number, pad_color]); }) tp.hook(tp.CMD_FADE, (req, res) => { - const pad_number = req.payload[0]; - const pad_speed = req.payload[1]; + const pad_number = req.payload[0]; + const pad_speed = req.payload[1]; const pad_cycles = req.payload[2]; const pad_color = RGBToHex(req.payload[3], req.payload[4], req.payload[5]); io.emit("Fade One", [pad_number, pad_speed, pad_cycles, pad_color]); @@ -260,19 +260,19 @@ tp.hook(tp.CMD_FADRD, (req, res) => { }) tp.hook(tp.CMD_FADAL, (req, res) => { - const top_pad_speed = req.payload[1]; + const top_pad_speed = req.payload[1]; const top_pad_cycles = req.payload[2]; const top_pad_color = RGBToHex(req.payload[3], req.payload[4], req.payload[5]); - const left_pad_speed = req.payload[7]; + const left_pad_speed = req.payload[7]; const left_pad_cycles = req.payload[8]; const left_pad_color = RGBToHex(req.payload[9], req.payload[10], req.payload[11]); - const right_pad_speed = req.payload[13]; + const right_pad_speed = req.payload[13]; const right_pad_cycles = req.payload[14]; const right_pad_color = RGBToHex(req.payload[15], req.payload[16], req.payload[17]); - io.emit("Fade All", [top_pad_speed, top_pad_cycles, top_pad_color, - left_pad_speed, left_pad_cycles, left_pad_color, - right_pad_speed, right_pad_cycles, right_pad_color]); + io.emit("Fade All", [top_pad_speed, top_pad_cycles, top_pad_color, + left_pad_speed, left_pad_cycles, left_pad_color, + right_pad_speed, right_pad_cycles, right_pad_color]); // setTimeout(function(){io.emit("Fade All", // [top_pad_speed, top_pad_cycles, 'white', // left_pad_speed, left_pad_cycles, 'white', @@ -341,10 +341,10 @@ app.post('/character', (request, response) => { console.log("name: " + name, " uid: " + character.uid, " id: " + character.id) fs.readFile(toytagFileName, 'utf8', (err, data) => { - if(err){ + if (err) { console.log(err) } - else{ + else { const tags = JSON.parse(data.toString()); tags.push({ @@ -378,15 +378,15 @@ app.post('/characterPlace', (request, response) => { //console.log(entry.type); - if(entry.type == "character"){ + if (entry.type == "character") { var character = createCharacter(request.body.id, request.body.uid); tp.place(character, request.body.position, request.body.index, character.uid); console.log('Character tag: ' + request.body.id); updatePadIndex(character.uid, request.body.index); response.send(); } - else{ - var vehicle = createVehicle(request.body.id,[entry.vehicleUpgradesP23, entry.vehicleUpgradesP25],request.body.uid); + else { + var vehicle = createVehicle(request.body.id, [entry.vehicleUpgradesP23, entry.vehicleUpgradesP25], request.body.uid); tp.place(vehicle, request.body.position, request.body.index, vehicle.uid); console.log('Vehicle tag: ' + request.body.id); updatePadIndex(vehicle.uid, request.body.index); @@ -403,10 +403,10 @@ app.post('/vehicle', (request, response) => { console.log("name: " + name, " uid: " + vehicle.uid, " id: " + vehicle.id) fs.readFile(toytagFileName, 'utf8', (err, data) => { - if(err){ + if (err) { console.log(err) } - else{ + else { const tags = JSON.parse(data.toString()); var entry = { name: name, @@ -449,13 +449,13 @@ app.delete('/remove', (request, response) => { io.on('connection', (socket) => { //Listening for 'deleteToken' call from index.html socket.on('deleteToken', (uid) => { - console.log('IO Recieved: Deleting entry '+ uid + ' from JSON'); + console.log('IO Recieved: Deleting entry ' + uid + ' from JSON'); const tags = fs.readFileSync(toytagFileName, 'utf8'); const databases = JSON.parse(tags); var index = -1; var i = 0; databases.forEach(db => { - if(uid == db.uid){ + if (uid == db.uid) { index = i; return; } @@ -464,8 +464,8 @@ io.on('connection', (socket) => { console.log('Entry to delete: ', index) if (index > -1) { databases.splice(index, 1); - } - fs.writeFileSync(toytagFileName, JSON.stringify(databases, null, 4), function(){ + } + fs.writeFileSync(toytagFileName, JSON.stringify(databases, null, 4), function () { if (index > -1) console.log('Token not found'); else @@ -475,7 +475,7 @@ io.on('connection', (socket) => { }); socket.on('connectionStatus', () => { - if(connection == true){ + if (connection == true) { io.emit("Connection True"); } }); @@ -485,9 +485,9 @@ io.on('connection', (socket) => { initalizeToyTagsJSON(); for (let i = 1; i <= 7; i++) { uid = getUIDAtPad(i); - if(uid != -1) { + if (uid != -1) { //console.log(uid, "is at pad #", i); - writeJSONData(uid,"index",i); + writeJSONData(uid, "index", i); } } io.emit("refreshTokens"); diff --git a/package.json b/package.json index fe25a3c..adafcee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ld-toypad-emulator", - "version": "1.3.4", + "version": "1.3.5", "description": "Toy Pad Emulator for Lego Dimensions", "repository": "https://github.com/Berny23/LD-ToyPad-Emulator", "main": "index.js", diff --git a/server/index.html b/server/index.html index 2f2fecf..c9a0bde 100755 --- a/server/index.html +++ b/server/index.html @@ -8,544 +8,577 @@ --> - - - Lego Dimensions Toy Pad Emulator | v1.3.4 - - - - - - -
-

Lego Dimensions Toy Pad Emulator

-

- → If you encounter a token that is not responding, move to the toy box and then back to the Toy Pad ←
+ #sync { + margin-top: 0.5em; + background-color: #8e99f3; + } + + #sync:hover, + #sync:active { + background-color: #5c6bc0; + } + + .container { + width: fit-content; + margin: auto; + background-color: #efefef; + box-shadow: 0 4px 8px 0 rgb(0 0 0 / 20%), 0 6px 20px 0 rgb(0 0 0 / 19%); + padding: 2em; + margin-bottom: 1.5em; + border-radius: 0.50rem; + } + + .flex-container { + flex-direction: column; + width: fit-content; + margin: auto; + background-color: #efefef; + box-shadow: 0 4px 8px 0 rgb(0 0 0 / 20%), 0 6px 20px 0 rgb(0 0 0 / 19%); + padding: 1em; + margin-bottom: 1.5em; + display: flex; + min-height: 100px; + border-radius: 0.50rem; + } + + #tag-creation-container { + display: inline-flex; + } + + #character-select { + margin-right: 2em; + } + + .box { + border: solid 3px transparent; + margin: 0; + list-style-type: none; + padding: 10px; + transition: background-color 0.25s ease-out; + border-radius: 0.50rem; + + /* align items in the box */ + } + + .drop-targets { + display: flex; + flex-direction: row; + justify-content: space-around; + align-items: center; + position: relative; + margin: 1em 0; + } + + .drop-targets>.box { + height: 9em; + width: 9em; + display: flex; + align-items: center; + justify-content: center; + background-color: #e8eaf6; + background-blend-mode: soft-light; + margin: 0 0.5em; + } + + .item { + width: 7em; + height: 7em; + background-color: #ffa726; + border: 1px solid transparent; + border-radius: 0.50rem; + color: #000; + box-sizing: border-box; + cursor: pointer; + box-shadow: rgb(0 0 0 / 20%) 0 4px 12px; + cursor: grab; + } + + .item:hover, + .item:focus, + .item:active { + background-color: #c77800; + transition: background-color 250ms; + } + + .item[data-type="vehicle"] { + background-color: #9ccc65; + } + + .item[data-type="vehicle"]:hover, + .item[data-type="vehicle"]:focus, + .item[data-type="vehicle"]:active { + background-color: #6b9b37; + } + + .item.ui-sortable-helper { + cursor: grabbing; + } + + #warnings { + color: #e8eaf6; + background-color: #26418f; + padding: 1em; + line-height: 2em; + } + + #status { + color: #e8eaf6; + background-color: #b61827; + padding: 1em; + } + + #token-box { + box-shadow: 0 4px 8px 0 rgb(0 0 0 / 0%), 0 6px 20px 0 rgb(0 0 0 / 0%); + flex-direction: row; + } + + #remove-tokens { + height: 8em; + width: 8em; + display: flex; + align-items: center; + justify-content: center; + border-radius: 0.50rem; + cursor: default; + padding: 0; + background-color: #ef5350; + } + + #remove-tokens>.item { + background-color: #ef5350; + box-shadow: none; + cursor: default; + } + + #remove-tokens>.placeholder { + width: 0px; + height: 0px; + } + + #toybox-tokens { + list-style-type: none; + margin: 0; + padding: 0; + width: 50em; + border-radius: 0.50rem; + min-height: 8em; + margin-right: 0.5em; + background-color: #bdbdbd; + } + + #toybox-tokens li { + margin: 0.5em; + float: left; + } + + + + + + +

+

Lego Dimensions Toy Pad Emulator

+

+ Create characters and vehicles with the boxes at the top, then drag them to the Toy Pad. +
+ If you encounter a token that is not responding, move it to the toy box and then back to the Toy Pad. +
+ +

+ +
+
+
- Create characters and vehicles with boxes at the top then drag them to the Toy Pad.
-

- -
- - -
- - - -
-
- -
-

Toy Box

-

Drag an entry to move it to the pad

-
-
    -
      -
    • -

      Drag to
      this side
      to delete

      -
    • -
    -
    + +
    + + +
    + +
    +

    Toy Box

    +
    +
      +
        +
      • + +   Drag to + +   this side + +   to delete + +       ➜ +
      • +
      +
      -

      - WARNING: Do not place any characters, I have not communicated with the game.
      - Placing characters now will cause me to crash.
      - This message will disappear when I can see the game. -

      - -
      -

      The Toy Pad

      -
      -
      -
      - -
      - -
      -
      -
      -
      -
      - -
      -
      -
      +

      + WARNING: Do not place any characters, I have not communicated with the game yet.
      + Placing characters now will cause me to crash.
      + This message will disappear when I can see the game. +

      + +
      +

      The Toy Pad

      +
      +
      +
      + +
      + +
      +
      +
      +
      +
      + +
      +
      - -
      - - - - - - - - - + + + + + -

      - Copyright © 2022 Berny23 & Cort1237 | v1.3.4
      - GitHub: https://github.com/Berny23/LD-ToyPad-Emulator
      - This software is licensed under the MIT license. -

      - - + + $('#vehicle-select').submit(function (e) { + e.preventDefault(); + + var name = $('#vehicle-name').val(); + console.log(name); + var id = filterByName(vehicles, name).id; + $.ajax({ + method: 'POST', + contentType: 'application/json', + url: '/vehicle', + data: JSON.stringify({ id: id }) + }).done(function () { + var now = Date.now(); + var end = now + 150; + while (now < end) { now = Date.now(); } + socket.emit("syncToyPad"); + $('#vehicle-select')[0].reset(); + }); + }); + + $('#sync').click(function () { + socket.emit("syncToyPad"); + }); + }); + + + + \ No newline at end of file