0.25 kb display

shows keyboard inputs on screen (replay functionality fixed hopefully)

当前为 2019-07-30 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name 0.25 kb display
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.25
  5. // @description shows keyboard inputs on screen (replay functionality fixed hopefully)
  6. // @author Oki perhaps and possibly meppydc
  7. // @match https://*.jstris.jezevec10.com/*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. /**************************
  12. Keyboard Display Script
  13. **************************/
  14. (function() {
  15. window.addEventListener('load', function() {
  16.  
  17. //Only display the keyboard if either in a Game or Replay
  18. if (typeof Game != "undefined" || typeof Replayer != "undefined") {
  19.  
  20. //labels are 0 1 2 3
  21. var labels = ['hail','jez', 'HL', 'HD',
  22. // 4 5 6 7 8 9
  23. '180', 'CCW', 'CW', 'L', 'SD', 'R']
  24. // left right sd hd ccw cw hold 180 reset new
  25. //order is: [6, 8, 1, 2, 3, 5, 4, 0] (.22)
  26. //order is: [7, 9, 8, 2, 5, 6, 1, 4] (.23)
  27. //order is: [7, 9, 8, 2, 5, 6, 1, 4] (.24)
  28. //order is: [7, 9, 8, 2, 5, 6, 1, 4, 0 3] (.24.1)
  29. //order is: [7, 9, 8, 3, 5, 6, 2, 4, 0 1] (.24.2)
  30. //0.25 added crap ton of variables, maybe use dictionary instead?
  31. var lefth = 7
  32. var righth = 9
  33. var sdh = 8
  34. var hdh = 3
  35. var ccwh = 5
  36. var cwh = 6
  37. var holdh = 2
  38. var doubleturnh = 4
  39.  
  40. //not important
  41. var reseth = 0
  42. var newh = 1
  43.  
  44. //var highlight = [[6,2],[8,2],[6,0],[8,0],[3,2],[5,2],[0,2],[2,2],[1,2],,[4,2]][this['actions'][this['ptr']]["a"]] //reference
  45.  
  46.  
  47.  
  48.  
  49. if (typeof getParams != "function") {
  50. var getParams = a => {
  51. var params = a.slice(a.indexOf("(") + 1);
  52. params = params.substr(0, params.indexOf(")")).split(",");
  53. return params
  54. }
  55. }
  56. if (typeof trim != "function") {
  57. var trim = a => {
  58. a = a.slice(0, -1);
  59. a = a.substr(a.indexOf("{") + 1);
  60. return a
  61. }
  62. }
  63.  
  64. //Create the "keyboard holder". It's a div positioned where the keyboard will be, but it doesnt contain anything yet.
  65. var kbhold = document.createElement("div");
  66. kbhold.id = "keyboardHolder";
  67. kbhold.style.position = "absolute"
  68. //Im trying to position it relative to the main canvas (this doesnt really work well...)
  69. kbhold.style.left = (myCanvas.getBoundingClientRect().left - 300) + "px";
  70. kbhold.style.top = (myCanvas.getBoundingClientRect().top + 100) + "px";
  71.  
  72. //Helper method for keyboards in replays
  73. if (typeof Replayer != "undefined" && typeof Game == "undefined") {
  74. Replayer["pressKey"] = function(num, type) {
  75. //type: 0=release 1=down 2=press
  76. //Highlights the corresponding key
  77. document.getElementsByClassName("kbkey")[num].style.backgroundColor = type ? "lightgoldenrodyellow" : ""
  78. if (type == 2) {
  79. //from replay data you dont really know how long a key has been pressed. im using 100ms as a default
  80. setTimeout(x => {
  81. document.getElementsByClassName("kbkey")[num].style.backgroundColor = ""
  82. }, 100)
  83. }
  84.  
  85. }
  86. //positions the keyboard holder differently for replays (thanks to meppydc)
  87. kbhold.style.left = (myCanvas.getBoundingClientRect().right + 200) + "px";
  88. kbhold.style.top = (myCanvas.getBoundingClientRect().top + 200) + "px";
  89. }
  90.  
  91. document.body.appendChild(kbhold);
  92.  
  93.  
  94. //(important)
  95. //this is what is pasted into the keyboard holder and makes up the entire visual keyboard.
  96. //(i decompressed and tidied it up a bit)
  97. //basically it's a table consisting of 2 rows and 6 columns
  98. //maybe read up on css tables if you wanna add new cells
  99.  
  100.  
  101. f = `
  102.  
  103. <style>
  104. #kbo {text-align:center;position: absolute;font-size:15px;}
  105. #kbo .tg {border-collapse:collapse;border-spacing:0;color:red;}
  106. #kbo .tg td{padding:10px 5px;border-style:solid;border-width:2px;}
  107. #kbo .tg th{padding:10px 5px;border-style:solid;border-width:2px;}
  108. #kbo .tg .tg-wp8o{border-color:#000000;border:inherit;}
  109. #kbo .tg .tg-tc3e{border-color:#34ff34;}
  110. #kbo .tg .tg-jy2k{border-color:#f8a102;}
  111. #kbo .tg .tg-p39m{border-color:#f8ff00;
  112. }</style>
  113.  
  114. <div id=\"kbo\"><div id=\"kps\"></div>
  115. <table class=\"tg\">
  116. <tr>
  117. <td class=\"tg-tc3e kbkey\">${labels[0]}</td>
  118. <td class=\"tg-tc3e kbkey\">${labels[1]}</td>
  119. <td class=\"tg-tc3e kbkey\">${labels[2]}</td>
  120. <td class=\"tg-wp8o\"></td>
  121. <td class=\"tg-jy2k kbkey\">${labels[3]}</td>
  122. <td class=\"tg-wp8o\"></td>
  123. </tr>
  124. <tr>
  125. <td class=\"tg-p39m kbkey\">${labels[4]}</td>
  126. <td class=\"tg-p39m kbkey\">${labels[5]}</td>
  127. <td class=\"tg-p39m kbkey\">${labels[6]}</td>
  128. <td class=\"tg-jy2k kbkey\">${labels[7]}</td>
  129. <td class=\"tg-jy2k kbkey\">${labels[8]}</td>
  130. <td class=\"tg-jy2k kbkey\">${labels[9]}</td>
  131. </tr>
  132. </table>
  133. </div>
  134. `
  135.  
  136. /*f = `
  137.  
  138. <style>
  139. #kbo {text-align:center;position: absolute;font-size:15px;}
  140. #kbo .tg {border-collapse:collapse;border-spacing:0;color:red;}
  141. #kbo .tg td{padding:10px 5px;border-style:solid;border-width:2px;}
  142. #kbo .tg th{padding:10px 5px;border-style:solid;border-width:2px;}
  143. #kbo .tg .tg-wp8o{border-color:#000000;border:inherit;}
  144. #kbo .tg .tg-tc3e{border-color:#34ff34;}
  145. #kbo .tg .tg-jy2k{border-color:#f8a102;}
  146. #kbo .tg .tg-p39m{border-color:#f8ff00;
  147. }</style>
  148.  
  149. <div id=\"kbo\"><div id=\"kps\"></div>
  150. <table class=\"tg\">
  151. <tr>
  152. <td class=\"tg-tc3e kbkey\">180</td>
  153. <td class=\"tg-tc3e kbkey\">SD</td>
  154. <td class=\"tg-tc3e kbkey\">HD</td>
  155. <td class=\"tg-wp8o\"></td>
  156. <td class=\"tg-jy2k kbkey\">CCW</td>
  157. <td class=\"tg-wp8o\"></td>
  158. </tr>
  159. <tr>
  160. <td class=\"tg-p39m kbkey\">HL</td>
  161. <td class=\"tg-p39m kbkey\">CW</td>
  162. <td class=\"tg-wp8o\"></td>
  163. <td class=\"tg-jy2k kbkey\">&lt;</td>
  164. <td class=\"tg-jy2k kbkey\">v</td>
  165. <td class=\"tg-jy2k kbkey\">&gt;</td>
  166. </tr>
  167. </table>
  168. </div>
  169. `
  170. */
  171. keyboardHolder.innerHTML = f
  172.  
  173. //keyboard if in game (not replays)********************************************************************************************************************************
  174. if (typeof Game != "undefined") {
  175.  
  176. document['addEventListener']('keydown', press);
  177. document['addEventListener']('keyup', press);
  178.  
  179. function press(e) {
  180. if (~Game['set2ings'].indexOf(e.keyCode)) {
  181. //something happens (oki sent me this)
  182. console.log(Game['set2ings'])//displays the keycodes of your controls
  183. // left right sd hd ccw cw hold 180
  184. //(important)
  185. //listens to pressed keys and highlights the corresponsing div.
  186. //the magic array converts between the actions and the div that is highlighted.
  187. //If you change the order of the boxes, you might also have to adjust the numbers in this array
  188. // left right sd hd ccw cw hold 180 reset new
  189. //order is: [6, 8, 1, 2, 3, 5, 4, 0] (.22 order)
  190. //order is: [7, 9, 8, 2, 5, 6, 1, 4] (.23 order)
  191. //order is: [7, 9, 8, 2, 5, 6, 1, 4] (.24 order)
  192. //order is: [7, 9, 8, 2, 5, 6, 1, 4, 0 3] (.24.1 order)
  193. //order is: [7, 9, 8, 3, 5, 6, 2, 4, 0 1] (.24.2 order)
  194. var corresponding = [lefth, righth, sdh, hdh, ccwh, cwh, holdh, doubleturnh, reseth, newh][Game['set2ings'].indexOf(e.keyCode)]
  195. document.getElementsByClassName("kbkey")[corresponding].style.backgroundColor = ["lightgoldenrodyellow", ""][+(e.type == "keyup")]
  196. }
  197. }
  198.  
  199. //This saves the settings array (which maps all actions in jstris to their keycodes) to a global variable for me to use (called Game['se2ings'])
  200. //resets every time a new game is started
  201. var set2ings = Game['prototype']['readyGo'].toString()
  202. set2ings = "Game['set2ings']=this.Settings.controls;" + trim(set2ings)
  203. Game['prototype']['readyGo'] = new Function(set2ings);
  204.  
  205. //calculates kps from kpp and pps and writes it into the kps element
  206. var updateTextBarFunc = Game['prototype']['updateTextBar'].toString()
  207. updateTextBarFunc = trim(updateTextBarFunc) + ";kps.innerHTML='KPS: '+(this.getKPP()*this.placedBlocks/this.clock).toFixed(2)"
  208. Game['prototype']['updateTextBar'] = new Function(updateTextBarFunc);
  209. } else {
  210.  
  211. //else: we're in a replay********************************************************************************************************************************
  212.  
  213. var website = "jstris.jezevec10.com"
  214. var url = window.location.href
  215. var parts = url.split("/")
  216.  
  217. if (parts[3] == "replay" && parts[2].endsWith(website)) {
  218.  
  219. //making a web request for the sole purpose of getting the DAS that was used for the replay
  220. //(can be done more elegantly)
  221. fetch("https://" + parts[2] + "/replay/data?id=" + (parts.length == 6 ? (parts[5] + "&live=1") : (parts[4])))
  222. .then(function(response) {
  223. return response.json();
  224. })
  225. .then(function(jsonResponse) {
  226. var das = jsonResponse.c.das
  227. var playT = Replayer['prototype']['playUntilTime'].toString()
  228. var playTparams = getParams(playT);
  229.  
  230.  
  231. //going though the list of actions done in the replay, and translating that into the timings for highlighting the divs
  232. //i dont rememer how exactly i did this but it's not pretty
  233. var insert1 = `
  234. kps.innerHTML="KPS: "+(this.getKPP()*this.placedBlocks/(this.clock/1000)).toFixed(2)
  235. this["delayedActions"] = []
  236. for (var i = 0; i < this["actions"].length; i++) {
  237. var action = JSON.parse(JSON.stringify(this["actions"][i]));
  238. if(action.a == 2 || action.a == 3){
  239. action.t = (action.t-` + das + `)>0 ? (action.t-` + das + `) : 0
  240. }
  241. this["delayedActions"].push(action)
  242. }
  243.  
  244. this["delayedActions"].sort(function(a, b) {
  245. return a.t - b.t;
  246. });
  247.  
  248. var oldVals = [this["timer"],this["ptr"]]
  249.  
  250. while (` + playTparams[0] + ` >= this['delayedActions'][this['ptr']]['t']) {
  251. if (this['ptr']) {
  252. this['timer'] += (this['delayedActions'][this['ptr']]['t'] - this['delayedActions'][this['ptr'] - 1]['t']) / 1000
  253. };
  254. if(this['delayedActions'][this['ptr']]["a"] == 2){
  255. Replayer["pressKey"](${lefth},1)
  256. }
  257. if(this['delayedActions'][this['ptr']]["a"] == 3){
  258. Replayer["pressKey"](${righth},1)
  259. }
  260.  
  261. this['ptr']++;
  262. if (this['delayedActions']['length'] === this['ptr']) {
  263. this['reachedEnd'] = true;
  264. break
  265. }
  266. };
  267.  
  268. this["timer"] = oldVals[0]
  269. this["ptr"] = oldVals[1]`
  270.  
  271.  
  272. //this maps a specific action (this['actions'][this['ptr']]["a"]) to what to do with the divs
  273. //the list of what action code equals what action is in that one harddrop forum post
  274. //for example, if you DAS_LEFT then left will be held down.
  275. //You might also adjust the numbers here (the first number in the pairs. remap them the same as in the magic array)
  276. var insert2 = `
  277. var highlight = [[${lefth},2],[${righth},2],[${lefth},0],[${righth},0],[${ccwh},2],[${cwh},2],[${doubleturnh},2],[${hdh},2],[${sdh},2],,[${holdh},2]][this['actions'][this['ptr']]["a"]]
  278. if(highlight){
  279. Replayer["pressKey"](...highlight)
  280. };
  281. `
  282.  
  283. playT = playT.replace(";", insert1 + ";")
  284. playT = playT.replace("1000};", "1000};" + insert2)
  285. Replayer['prototype']['playUntilTime'] = new Function(...playTparams, trim(playT));
  286.  
  287. //i hate myself - Oki
  288. //I heard jez whips Oki - meppydc
  289. });
  290. }
  291. }
  292. }
  293. });
  294. })();