Greasy Fork 还支持 简体中文。

Keyboard Display Script

shows keyboard inputs on screen

目前為 2019-09-13 提交的版本,檢視 最新版本

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