SHOW:
|
|
- or go back to the newest paste.
1 | // ==UserScript== | |
2 | // @id twitch-plays-control@meiguro.com | |
3 | // @name Twitch Plays Pokémon Touch Controller | |
4 | // @version 0.3.2 | |
5 | // @author Meiguro <meiguro@meiguro.com> http://meiguro.com/ | |
6 | // @namespace https://github.com/Meiguro/twitch-plays-control | |
7 | // @description Add Touch controls to Twitch Plays Pokemon touch-enabled games. | |
8 | // @include /^https?://(www|beta)?\.?twitch.tv/twitch_?plays.*$/ | |
9 | // @grant unsafeWindow, GM_addStyle, GM_info | |
10 | // @run-at document-start | |
11 | // @updateURL https://raw.githubusercontent.com/Meiguro/twitch-plays-control/master/twitch-plays-control.meta.js | |
12 | // @installURL https://raw.githubusercontent.com/Meiguro/twitch-plays-control/master/twitch-plays-control.user.js | |
13 | // @downloadURL https://raw.githubusercontent.com/Meiguro/twitch-plays-control/master/twitch-plays-control.user.js | |
14 | // ==/UserScript== | |
15 | ||
16 | /** | |
17 | * v0.3.2 CHANGELOG ༼ つ ◕_◕ ༽つ | |
18 | * | |
19 | * - Fixed the coordinate range to be 1,1 - 319,239. | |
20 | * | |
21 | * v0.3.1 | |
22 | * | |
23 | * - Updated to the new 3DS layout. Reset your controller settings if the | |
24 | * touch input box is in the wrong location. | |
25 | * | |
26 | * - The logic has been separated into components for maintainability. There | |
27 | * should be no break in functionality. | |
28 | * | |
29 | * Enjoy! | |
30 | * | |
31 | * - Meiguro | |
32 | */ | |
33 | ||
34 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | |
35 | /* globals GM_addStyle, GM_info */ | |
36 | ||
37 | var util2 = require('util2'); | |
38 | ||
39 | var dd = require('dd'); | |
40 | dd.ui = require('dd-ui'); | |
41 | ||
42 | var Entity = require('entity'); | |
43 | var Touch = require('touch'); | |
44 | var Chat = require('chat'); | |
45 | var Settings = require('settings'); | |
46 | var mywindow = require('window'); | |
47 | ||
48 | require('gm-shims'); | |
49 | ||
50 | var Control = function(def) { | |
51 | Entity.call(this, def); | |
52 | this.config = {}; | |
53 | }; | |
54 | ||
55 | util2.inherit(Control, Entity, Control.prototype); | |
56 | ||
57 | Control.DefaultConfig = { | |
58 | delay: 50, | |
59 | screen: { | |
60 | aspect: 1280 / 720, | |
61 | position: [0.997, 0.977], | |
62 | scale: 0.392, | |
63 | size: [320, 240], | |
64 | barHeight: 30 | |
65 | }, | |
66 | enabled: true, | |
67 | showBorder: true, | |
68 | showCoordTooltip: true, | |
69 | showCross: true, | |
70 | autoSend: true, | |
71 | showDroplets: true, | |
72 | streamDelay: 15, | |
73 | }; | |
74 | ||
75 | Control.PlayerSelector = '.dynamic-player, .player-container'; | |
76 | ||
77 | Control.prototype.updateLoad = function() { | |
78 | if (this.loaded) { return; } | |
79 | if (!this.loadable()) { return; } | |
80 | ||
81 | this.onload(); | |
82 | }; | |
83 | ||
84 | Control.prototype.update = function(force) { | |
85 | this.updateLoad(); | |
86 | ||
87 | Entity.prototype.update.call(this, force); | |
88 | }; | |
89 | ||
90 | Control.prototype.onClick = function(e) { | |
91 | this.component('touch').onClick(e); | |
92 | }; | |
93 | ||
94 | Control.prototype.onMove = function(e) { | |
95 | this.component('touch').onMove(e); | |
96 | }; | |
97 | ||
98 | Control.prototype.onPressReset = function(e) { | |
99 | $.extend(true, this.config, Control.DefaultConfig); | |
100 | ||
101 | this.eachComponent(function(component) { | |
102 | for (var k in component) { | |
103 | var $elem = component[k]; | |
104 | if ($elem.$change) { | |
105 | $elem.$change(); | |
106 | } | |
107 | } | |
108 | }); | |
109 | ||
110 | this.update(true); | |
111 | this.saveConfig(); | |
112 | }; | |
113 | ||
114 | Control.prototype.onPressChangeChatServer = function(e) { | |
115 | this.component('chat').onPressChangeChatServer(e); | |
116 | }; | |
117 | ||
118 | Control.prototype.saveConfig = function() { | |
119 | localStorage.TPControl = JSON.stringify(this.config); | |
120 | }; | |
121 | ||
122 | Control.prototype.loadConfig = function() { | |
123 | if (!localStorage.TPControl) { | |
124 | localStorage.TPControl = this.config; | |
125 | } else { | |
126 | try { | |
127 | var lastConfig = JSON.parse(localStorage.TPControl); | |
128 | for (var k in lastConfig) { | |
129 | this.config[k] = lastConfig[k]; | |
130 | } | |
131 | } catch(e) { | |
132 | console.log(e); | |
133 | } | |
134 | } | |
135 | }; | |
136 | ||
137 | Control.prototype.init = function() { | |
138 | var self = this; | |
139 | ||
140 | window.$ = mywindow.jQuery; | |
141 | ||
142 | $.extend(true, this.config, Control.DefaultConfig); | |
143 | ||
144 | this.loadConfig(); | |
145 | this.saveConfig(); | |
146 | ||
147 | dd.onChange = this.saveConfig.bind(this); | |
148 | ||
149 | if (this.config.screen.size[0] != Control.DefaultConfig.screen.size[0]) { | |
150 | $.extend(true, this.config.screen, Control.DefaultConfig.screen); | |
151 | } | |
152 | ||
153 | $('.tpc-mouse-box').remove(); | |
154 | $('.tpc-control-settings').remove(); | |
155 | ||
156 | var touch = new Touch(); | |
157 | var chat = new Chat(); | |
158 | var settings = new Settings(); | |
159 | ||
160 | this.addComponent(touch); | |
161 | this.addComponent(chat); | |
162 | this.addComponent(settings); | |
163 | ||
164 | var $player = touch.$player = $(Control.PlayerSelector); | |
165 | var $mouseBox = touch.$mouseBox = $('<div/>').addClass('tpc-mouse-box'); | |
166 | var $coordTooltip = touch.$coordTooltip = $('<div/>').addClass('tpc-coord-tooltip'); | |
167 | ||
168 | var $chatSettings = settings.$chatSettings = $(Settings.ChatSelector); | |
169 | var $controlSettings = settings.$controlSettings = $('<div/>').addClass('tpc-control-settings'); | |
170 | ||
171 | $player.css({ position: 'relative' }); | |
172 | $chatSettings.css({ position: 'absolute' }); | |
173 | ||
174 | $mouseBox.css({ | |
175 | cursor: 'pointer', | |
176 | border: '2px solid rgba(150, 150, 150, 0.2)', | |
177 | borderRadius: '5px' | |
178 | }); | |
179 | ||
180 | GM_addStyle( | |
181 | '.tpc-mouse-box .tpc-coord-tooltip { display: none; color: #444; font-weight: normal } ' + | |
182 | '.tpc-mouse-box:hover .tpc-coord-tooltip { display: block }'); | |
183 | ||
184 | $coordTooltip.css({ | |
185 | padding: '0px 5px', | |
186 | background: 'rgba(255, 255, 255, 0.8)', | |
187 | borderRadius: '2px' | |
188 | }); | |
189 | ||
190 | $mouseBox.empty(); | |
191 | $mouseBox.append($coordTooltip); | |
192 | ||
193 | $controlSettings.empty(); | |
194 | $controlSettings.append( | |
195 | '<div class="chat-menu tpc-touch-menu">' + | |
196 | '<div class="chat-menu-header">Touch Control Settings</div>' + | |
197 | '<div class="chat-menu-content tpc-control-sliders"></div>' + | |
198 | '<div class="chat-menu-content tpc-control-checkboxes"></div>' + | |
199 | '<div class="chat-menu-content tpc-control-last"></div>' + | |
200 | '</div>' + | |
201 | '<div class="chat-menu tpc-chat-menu">' + | |
202 | '<div class="chat-menu-header">Chat Server</div>' + | |
203 | '<div class="chat-menu-content tpc-control-chat"></div>' + | |
204 | '</div>'); | |
205 | ||
206 | $controlSettings.find('.tpc-control-sliders') | |
207 | .append(touch.xSlider = dd.ui.slider( | |
208 | 'tpc-x-slider tpc-slider', 'Touch-box x-position', { min: 0, max: 1, step: 0.0005 }, | |
209 | this.config, 'screen.position.0', function() { touch.updateMouseBox(true); })) | |
210 | .append(touch.ySlider = dd.ui.slider( | |
211 | 'tpc-y-slider tpc-slider', 'Touch-box y-position', { min: 0, max: 1, step: 0.0005 }, | |
212 | this.config, 'screen.position.1', function() { touch.updateMouseBox(true); })) | |
213 | .append(touch.scaleSlider = dd.ui.slider( | |
214 | 'tpc-scale-slider tpc-slider', 'Touch-box scale', { min: 0, max: 1, step: 0.0005 }, | |
215 | this.config, 'screen.scale', function() { touch.updateMouseBox(true); })); | |
216 | ||
217 | $controlSettings.find('.tpc-control-checkboxes') | |
218 | .append(touch.enabledCheckbox = dd.ui.checkbox( | |
219 | 'tpc-enabled-checkbox', 'Enable touch control', this.config, 'enabled', | |
220 | function() { | |
221 | touch.$mouseBox.css({ display: self.config.enabled ? 'block' : 'none' }); | |
222 | })) | |
223 | .append(touch.borderCheckbox = dd.ui.checkbox( | |
224 | 'tpc-border-checkbox', 'Show border box', this.config, 'showBorder', | |
225 | function() { | |
226 | touch.$mouseBox.css({ border: self.config.showBorder ? '2px solid rgba(255, 255, 255, 0.5)' : 'none' }); | |
227 | })) | |
228 | .append(touch.coordTooltipCheckbox = dd.ui.checkbox( | |
229 | 'tpc-tooltip-checkbox', 'Show coord tooltip', this.config, 'showCoordTooltip', | |
230 | function() { | |
231 | if (self.config.showCoordTooltip) { | |
232 | touch.$mouseBox.append(touch.$coordTooltip); | |
233 | } else { | |
234 | touch.$coordTooltip.remove(); | |
235 | } | |
236 | })) | |
237 | .append(touch.crossCheckbox = dd.ui.checkbox( | |
238 | 'tpc-cross-checkbox', 'Use cross pointer', this.config, 'showCross', | |
239 | function() { | |
240 | touch.$mouseBox.css({ cursor: self.config.showCross ? 'crosshair' : 'default' }); | |
241 | })) | |
242 | .append(touch.autoSendCheckbox = dd.ui.checkbox( | |
243 | 'tpc-auto-send-checkbox', 'Auto-send touches', this.config, 'autoSend')) | |
244 | .append(touch.dropletsCheckbox = dd.ui.checkbox( | |
245 | 'tpc-droplet-checkbox', 'Show touch droplets', this.config, 'showDroplets')); | |
246 | ||
247 | $controlSettings.find('.tpc-control-last') | |
248 | .append(touch.resetButton = dd.ui.button( | |
249 | 'tpc-reset-button', 'Reset controller settings', this.onPressReset.bind(this))); | |
250 | ||
251 | $controlSettings.find('.tpc-control-chat') | |
252 | .append('<p><label>Current <span class="tpc-chat-server"></span></label></p>') | |
253 | .append(chat.chatServerButton = dd.ui.button( | |
254 | 'tpc-chat-server-button', 'Change chat server', this.onPressChangeChatServer.bind(this))); | |
255 | ||
256 | $player.append($mouseBox); | |
257 | $chatSettings.append($controlSettings); | |
258 | ||
259 | $mouseBox.on('click', this.onClick.bind(this)); | |
260 | $mouseBox.on('mousemove', this.onMove.bind(this)); | |
261 | ||
262 | settings.update(true); | |
263 | ||
264 | this.loaded = true; | |
265 | ||
266 | this.start(); | |
267 | ||
268 | setTimeout(function() { | |
269 | $('.chat-room .loading-mask').remove(); | |
270 | }, 5000); | |
271 | }; | |
272 | ||
273 | Control.prototype.loadable = function() { | |
274 | var $ = mywindow.jQuery; | |
275 | if (typeof $ !== 'function') { return false; } | |
276 | ||
277 | var hasPlayer = $(Control.PlayerSelector).length; | |
278 | var hasChatSettings = $(Settings.ChatSelector).length; | |
279 | return hasPlayer || hasChatSettings; | |
280 | }; | |
281 | ||
282 | Control.prototype.onload = function() { | |
283 | this.init(); | |
284 | if (typeof GM_info === 'object') { | |
285 | console.log(GM_info.script.name + ' v' + GM_info.script.version + ' loaded!'); | |
286 | } else { | |
287 | console.log('Twitch Plays Control loaded!'); | |
288 | } | |
289 | }; | |
290 | ||
291 | var control = new Control(); | |
292 | ||
293 | setInterval(control.update.bind(control), Control.DefaultConfig.delay); | |
294 | ||
295 | control.update(); | |
296 | ||
297 | mywindow.TPControl = control; | |
298 | ||
299 | },{"chat":2,"dd":5,"dd-ui":4,"entity":6,"gm-shims":7,"settings":8,"touch":9,"util2":10,"window":11}],2:[function(require,module,exports){ | |
300 | var util2 = require('util2'); | |
301 | var Component = require('component'); | |
302 | ||
303 | var mywindow = require('window'); | |
304 | ||
305 | var Chat = function(def) { | |
306 | Component.call(this, def); | |
307 | }; | |
308 | ||
309 | util2.inherit(Chat, Component, Chat.prototype); | |
310 | ||
311 | Chat.InputSelector = '.ember-text-area'; | |
312 | Chat.ButtonSelector = '.send-chat-button button'; | |
313 | Chat.HiddenSelector = '.chat-hidden-overlay'; | |
314 | Chat.LogSelector = '.chat-messages .tse-content'; | |
315 | Chat.ServerAddress = '199.9.252.26:6667'; | |
316 | ||
317 | Chat.prototype.name = 'chat'; | |
318 | ||
319 | Chat.prototype.start = function() { | |
320 | }; | |
321 | ||
322 | Chat.prototype.getChatSession = function() { | |
323 | if (this.chatSession) { | |
324 | return this.chatSession; | |
325 | } | |
326 | ||
327 | var App = mywindow.App; | |
328 | if (App && App.Room) { | |
329 | return (this.chatSession = App.Room._getTmiSession().fulfillmentValue); | |
330 | } | |
331 | }; | |
332 | ||
333 | Chat.prototype.getChatConnection = function() { | |
334 | var chatSession = this.getChatSession(); | |
335 | var connections = chatSession._connections; | |
336 | var cluster = connections.prod || connections.event; | |
337 | if (cluster) { return cluster; } | |
338 | for (var k in connections) { | |
339 | return connections[k]; | |
340 | } | |
341 | }; | |
342 | ||
343 | Chat.prototype.getCurrentChatAddress = function() { | |
344 | var chatSession = this.getChatSession(); | |
345 | if (!chatSession) { return; } | |
346 | var connection = this.getChatConnection(); | |
347 | if (!connection) { return; } | |
348 | var addr = connection._addrs[connection._currentAddressIndex]; | |
349 | if (!addr) { return; } | |
350 | return addr.host + ':' + addr.port; | |
351 | }; | |
352 | ||
353 | Chat.prototype.connectServer = function(address) { | |
354 | var addr = address.split(':'); | |
355 | var chatSession = this.getChatSession(); | |
356 | var connection = this.getChatConnection(); | |
357 | if (!connection) { | |
358 | window.alert('TPC: Couldn\'t obtain a chat connection to manipulate!'); | |
359 | return; | |
360 | } | |
361 | ||
362 | connection.close(); | |
363 | connection._addrs = [{ host: addr[0], port: addr[1] }]; | |
364 | connection._currentAddressIndex = 0; | |
365 | connection._numSocketConnectAttempts = 0; | |
366 | connection.open(); | |
367 | ||
368 | var msg = 'connecting to chat server ' + address + '...'; | |
369 | $(Chat.LogSelector + ' .ember-view:last') | |
370 | .before('<div class="chat-line admin"><span class="message">' + msg + '</span></div>'); | |
371 | }; | |
372 | ||
373 | Chat.prototype.isChatVisible = function() { | |
374 | return $(Chat.InputSelector).length && !$(Chat.HiddenSelector).is(':visible'); | |
375 | }; | |
376 | ||
377 | Chat.prototype.setInput = function(input, broadcast) { | |
378 | $(Chat.InputSelector).val(input).focus().change().blur(); | |
379 | if (this.config.autoSend) { | |
380 | $(Chat.ButtonSelector).click(); | |
381 | } | |
382 | if (!this.isChatVisible() && broadcast !== false) { | |
383 | localStorage.TPCInput = input; | |
384 | } | |
385 | }; | |
386 | ||
387 | Chat.prototype.updateInput = function() { | |
388 | if (!this.entity.loaded) { return; } | |
389 | if (!this.config.enabled) { return; } | |
390 | ||
391 | if (!this.isChatVisible()) { return; } | |
392 | ||
393 | var input = localStorage.TPCInput; | |
394 | delete localStorage.TPCInput; | |
395 | if (typeof input === 'string' && input.length > 0) { | |
396 | this.setInput(input, false); | |
397 | } | |
398 | }; | |
399 | ||
400 | Chat.prototype.updateChatSession = function() { | |
401 | if (this.chatSession) { return; } | |
402 | ||
403 | var TMI = mywindow.TMI; | |
404 | if (!TMI) { return; } | |
405 | ||
406 | if (this.entity.loaded) { | |
407 | this.getChatSession(); | |
408 | } | |
409 | }; | |
410 | ||
411 | Chat.prototype.update = function() { | |
412 | this.updateChatSession(); | |
413 | this.updateInput(); | |
414 | }; | |
415 | ||
416 | Chat.prototype.onPressChangeChatServer = function(e) { | |
417 | var defaultAddress = Chat.ServerAddress; | |
418 | var currentAddress = this.getCurrentChatAddress(); | |
419 | var address = window.prompt( | |
420 | 'Enter chat server address:' + | |
421 | (currentAddress ? | |
422 | '\nCurrent ' + currentAddress : | |
423 | '\nExample ' + defaultAddress), | |
424 | defaultAddress) || ''; | |
425 | address = address.replace(/\s/, ''); | |
426 | if (address.length === 0) { | |
427 | return; | |
428 | } | |
429 | if (!address.match(':')) { | |
430 | address += ':6667'; | |
431 | } | |
432 | this.connectServer(address); | |
433 | }; | |
434 | ||
435 | module.exports = Chat; | |
436 | ||
437 | },{"component":3,"util2":10,"window":11}],3:[function(require,module,exports){ | |
438 | var Component = function(def) { | |
439 | this.state = def || {}; | |
440 | }; | |
441 | ||
442 | Component.prototype.component = function(name) { | |
443 | return this.entity.component(name); | |
444 | }; | |
445 | ||
446 | Component.prototype.start = function() {}; | |
447 | ||
448 | Component.prototype.update = function() {}; | |
449 | ||
450 | module.exports = Component; | |
451 | ||
452 | },{}],4:[function(require,module,exports){ | |
453 | var dd = require('dd'); | |
454 | ||
455 | dd.ui = dd.ui || {}; | |
456 | ||
457 | dd.ui.checkbox = function(id, label, obj, ref, onChange) { | |
458 | var $elem = $('<p><label for="'+id+'"><input id="'+id+'" type="checkbox"> '+label+'</label></p>'); | |
459 | var $input = $elem.find('input'); | |
460 | dd.bindGetSet($elem, $input.prop.bind($input, 'checked')); | |
461 | $input.on('change', dd.bindElement($elem, obj, ref, onChange)); | |
462 | return $elem; | |
463 | }; | |
464 | ||
465 | dd.ui.slider = function(klass, label, options, obj, ref, onChange) { | |
466 | var $elem = $('<p><label>'+label+'</label></p>'); | |
467 | var $slider = $('<div class="'+klass+'"></div>'); | |
468 | $slider.slider(options); | |
469 | $elem.prepend($slider); | |
470 | dd.bindGetSet($elem, $slider.slider.bind($slider, 'value')); | |
471 | $slider.slider({ slide: dd.bindElement($elem, obj, ref, onChange) }); | |
472 | return $elem; | |
473 | }; | |
474 | ||
475 | dd.ui.button = function(klass, label, onPress) { | |
476 | var $elem = $('<button class="'+klass+'">'+label+'</button>'); | |
477 | $elem.on('click', onPress); | |
478 | return $elem; | |
479 | }; | |
480 | ||
481 | module.exports = dd.ui; | |
482 | ||
483 | },{"dd":5}],5:[function(require,module,exports){ | |
484 | var dd = {}; | |
485 | ||
486 | dd.last = function(a) { | |
487 | return a[a.length - 1]; | |
488 | }; | |
489 | ||
490 | dd.toKey = function(obj, key) { | |
491 | return obj instanceof Array ? parseInt(key) : key; | |
492 | }; | |
493 | ||
494 | dd.getByKeys = function(obj, keys, offset) { | |
495 | for (var i = 0, ii = keys.length - (offset || 0); i < ii; ++i) { | |
496 | obj = obj[dd.toKey(obj, keys[i])]; | |
497 | } | |
498 | return obj; | |
499 | }; | |
500 | ||
501 | dd.setByKey = function(obj, key, value) { | |
502 | obj[dd.toKey(obj, key)] = value; | |
503 | }; | |
504 | ||
505 | dd.set = function(obj, ref, value) { | |
506 | var keys = ref.split('.'); | |
507 | dd.setByKey(dd.getByKeys(obj, keys, 1), dd.last(keys), value); | |
508 | }; | |
509 | ||
510 | dd.get = function(obj, ref) { | |
511 | return dd.getByKeys(obj, ref.split('.')); | |
512 | }; | |
513 | ||
514 | dd.bindGetSet = function($elem, get, set) { | |
515 | $elem.$get = get; | |
516 | $elem.$set = set || get; | |
517 | }; | |
518 | ||
519 | dd.bindElement = function($elem, obj, ref, onChange) { | |
520 | $elem.$obj = obj; | |
521 | $elem.$ref = ref; | |
522 | $elem.$change = function(e) { | |
523 | if (e) { | |
524 | dd.set(obj, ref, $elem.$get()); | |
525 | } else { | |
526 | $elem.$set(dd.get(obj, ref)); | |
527 | } | |
528 | if (onChange) { onChange(e); } | |
529 | if (dd.onChange) { dd.onChange(e); } | |
530 | }; | |
531 | $elem.$change(); | |
532 | return $elem.$change; | |
533 | }; | |
534 | ||
535 | module.exports = dd; | |
536 | ||
537 | },{}],6:[function(require,module,exports){ | |
538 | var Entity = function(def) { | |
539 | this.state = def || {}; | |
540 | this._components = []; | |
541 | this._componentsByName = {}; | |
542 | }; | |
543 | ||
544 | Entity.prototype.component = function(name) { | |
545 | return this._componentsByName[name]; | |
546 | }; | |
547 | ||
548 | Entity.prototype.eachComponent = function(callback) { | |
549 | this._components.forEach(callback.bind(this)); | |
550 | }; | |
551 | ||
552 | Entity.prototype.addComponent = function(component) { | |
553 | if (component.entity) { | |
554 | component.entity.removeComponent(component); | |
555 | } | |
556 | this._componentsByName[component.name] = component; | |
557 | this._components.push(component); | |
558 | component.entity = this; | |
559 | component.config = this.config; | |
560 | }; | |
561 | ||
562 | Entity.prototype.removeComponent = function(component) { | |
563 | var index = this._components.indexOf(component); | |
564 | if (index === -1) { return; } | |
565 | this._components.splice(index, 1); | |
566 | delete this._componentsByName[component.name]; | |
567 | delete component.entity; | |
568 | delete component.config; | |
569 | }; | |
570 | ||
571 | Entity.prototype.start = function() { | |
572 | for (var i = 0, ii = this._components.length; i < ii; ++i) { | |
573 | this._components[i].start(); | |
574 | } | |
575 | }; | |
576 | ||
577 | Entity.prototype.update = function(force) { | |
578 | for (var i = 0, ii = this._components.length; i < ii; ++i) { | |
579 | this._components[i].update(force); | |
580 | } | |
581 | }; | |
582 | ||
583 | module.exports = Entity; | |
584 | ||
585 | },{}],7:[function(require,module,exports){ | |
586 | (function (global){ | |
587 | ||
588 | if (typeof GM_addStyle === 'undefined') { | |
589 | global.GM_addStyle = function(style) { | |
590 | $('head:first').append($('<style>').text(style)); | |
591 | }; | |
592 | } | |
593 | ||
594 | }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
595 | },{}],8:[function(require,module,exports){ | |
596 | var util2 = require('util2'); | |
597 | var Component = require('component'); | |
598 | ||
599 | var Settings = function(def) { | |
600 | Component.call(this, def); | |
601 | }; | |
602 | ||
603 | util2.inherit(Settings, Component, Settings.prototype); | |
604 | ||
605 | Settings.ChatSelector = '.js-chat-settings'; | |
606 | Settings.ButtonSelector = '.settings.button'; | |
607 | ||
608 | Settings.prototype.name = 'settings'; | |
609 | ||
610 | Settings.prototype.start = function() { | |
611 | }; | |
612 | ||
613 | Settings.prototype.updateServerLabel = function() { | |
614 | var $chatServer = this.$chatSettings.find('.tpc-chat-server'); | |
615 | ||
616 | var labelAddress = $chatServer.text(); | |
617 | var currentAddress = this.component('chat').getCurrentChatAddress(); | |
618 | if (currentAddress !== labelAddress) { | |
619 | $chatServer.text(currentAddress); | |
620 | } | |
621 | }; | |
622 | ||
623 | Settings.prototype.updatePosition = function(force) { | |
624 | var overflow = this.$chatSettings.css('overflowY') || ''; | |
625 | ||
626 | if (overflow.match(/(auto|scroll)/)) { | |
627 | this.$controlSettings.css({ position: 'static', left: 'none', top: 'none' }); | |
628 | return; | |
629 | } | |
630 | ||
631 | var minWidth = Math.max(200, this.$chatSettings.width()); | |
632 | var position = { left: 0, top: 0 }; | |
633 | var offset = this.$chatSettings.offset(); | |
634 | var isSlim = offset.left > 0 && offset.left < minWidth; | |
635 | ||
636 | this.$controlSettings.css({ | |
637 | position: 'absolute', | |
638 | minWidth: minWidth, | |
639 | left: position.left + (minWidth + 5) * (isSlim ? 1 : -1), | |
640 | top: position.top + this.$chatSettings.height() - this.$controlSettings.height() | |
641 | }); | |
642 | }; | |
643 | ||
644 | Settings.prototype.update = function(force) { | |
645 | if (!this.entity.loaded) { return; } | |
646 | ||
647 | if (!this.$chatSettings.length) { return; } | |
648 | if (!this.$chatSettings.is(':visible') && force !== true) { return; } | |
649 | ||
650 | this.updateServerLabel(); | |
651 | this.updatePosition(); | |
652 | }; | |
653 | ||
654 | module.exports = Settings; | |
655 | ||
656 | },{"component":3,"util2":10}],9:[function(require,module,exports){ | |
657 | var util2 = require('util2'); | |
658 | var Component = require('component'); | |
659 | ||
660 | var Touch = function(def) { | |
661 | Component.call(this, def); | |
662 | }; | |
663 | ||
664 | util2.inherit(Touch, Component, Touch.prototype); | |
665 | ||
666 | Touch.SizeEdge = [false, false]; | |
667 | ||
668 | Touch.prototype.name = 'touch'; | |
669 | ||
670 | Touch.prototype.start = function() { | |
671 | }; | |
672 | ||
673 | Touch.prototype.getBorderSize = function() { | |
674 | return parseInt(this.$mouseBox.css('borderTopWidth')); | |
675 | }; | |
676 | ||
677 | Touch.prototype.getTouchPosition = function(e) { | |
678 | var offset = this.$mouseBox.offset(); | |
679 | var borderSize = this.getBorderSize(); | |
680 | var x = e.clientX - offset.left - 2 * borderSize; | |
681 | var y = e.clientY - offset.top - 2 * borderSize; | |
682 | ||
683 | var minX = 0 + (Touch.SizeEdge[0] ? 0 : 1); | |
684 | var minY = 0 + (Touch.SizeEdge[1] ? 0 : 1); | |
685 | var maxX = this.config.screen.size[0] - (Touch.SizeEdge[0] ? 0 : 1); | |
686 | var maxY = this.config.screen.size[1] - (Touch.SizeEdge[1] ? 0 : 1); | |
687 | ||
688 | var touchX = Math.ceil(x / this.scale); | |
689 | var touchY = Math.ceil(y / this.scale); | |
690 | var valid = (touchX >= minX && touchX <= maxX) && | |
691 | (touchY >= minY && touchY <= maxY); | |
692 | return { | |
693 | mouse: [x, y], | |
694 | position: [touchX, touchY], | |
695 | input: touchX + ',' + touchY, | |
696 | valid: valid | |
697 | }; | |
698 | }; | |
699 | ||
700 | Touch.prototype.spawnDroplet = function(position) { | |
701 | var $drop = $('<div/>').addClass('tpc-droplet'); | |
702 | var size = 10; | |
703 | $drop.css({ | |
704 | background: 'rgba(255, 255, 255, 0.8)', | |
705 | borderRadius: size, | |
706 | position: 'absolute', | |
707 | left: position[0] - size / 2, | |
708 | top: position[1] - size / 2, | |
709 | width: size, | |
710 | height: size | |
711 | }); | |
712 | this.$mouseBox.append($drop); | |
713 | $drop | |
714 | .animate({ | |
715 | left: position[0], | |
716 | top: position[1], | |
717 | width: 0, | |
718 | height: 0 | |
719 | }, this.config.streamDelay * 1000) | |
720 | .queue(function() { | |
721 | $drop.remove(); | |
722 | $drop.dequeue(); | |
723 | }); | |
724 | }; | |
725 | ||
726 | Touch.prototype.updateMouseBox = function(force) { | |
727 | var playerWidth = this.$player.width(); | |
728 | var playerHeight = this.$player.height() - this.config.screen.barHeight; | |
729 | ||
730 | if ((this.playerWidth === playerWidth && | |
731 | this.playerHeight === playerHeight) && force !== true) { | |
732 | return; | |
733 | } | |
734 | ||
735 | this.playerWidth = playerWidth; | |
736 | this.playerHeight = playerHeight; | |
737 | ||
738 | var aspect = playerWidth / playerHeight; | |
739 | ||
740 | var excessWidth = 0; | |
741 | if (aspect > this.config.screen.aspect) { | |
742 | excessWidth = playerWidth - playerHeight * this.config.screen.aspect; | |
743 | } | |
744 | ||
745 | this.scale = this.config.screen.scale * playerHeight / this.config.screen.size[1]; | |
746 | ||
747 | var borderSize = this.getBorderSize(); | |
748 | var width = this.scale * this.config.screen.size[0]; | |
749 | var height = this.scale * this.config.screen.size[1]; | |
750 | ||
751 | this.$mouseBox.css({ | |
752 | position: 'absolute', | |
753 | left: excessWidth / 2 + (playerWidth - width - excessWidth) * this.config.screen.position[0] - borderSize, | |
754 | top: (playerHeight - height) * this.config.screen.position[1] - borderSize, | |
755 | width: width, | |
756 | height: height | |
757 | }); | |
758 | ||
759 | if (!this.component('settings').$chatSettings.is(':visible')) { | |
760 | this.$mouseBox.stop(true, true).css({ background: 'transparent' }); | |
761 | return; | |
762 | } | |
763 | ||
764 | this.$mouseBox | |
765 | .stop(true, true) | |
766 | .animate({ backgroundColor: 'rgba(255, 255, 255, 0.5)' }, 100) | |
767 | .delay(1000) | |
768 | .animate({ backgroundColor: 'rgba(255, 255, 255, 0)' }) | |
769 | .animate({ background: 'transparent' }, 0); | |
770 | }; | |
771 | ||
772 | Touch.prototype.update = function(force) { | |
773 | if (!this.entity.loaded) { return; } | |
774 | if (!this.config.enabled) { return; } | |
775 | ||
776 | this.updateMouseBox(force); | |
777 | }; | |
778 | ||
779 | Touch.prototype.onClick = function(e) { | |
780 | var touch = this.getTouchPosition(e); | |
781 | if (!touch.valid) { return; } | |
782 | this.component('chat').setInput(touch.input); | |
783 | if (this.config.showDroplets) { | |
784 | this.spawnDroplet(touch.mouse); | |
785 | } | |
786 | }; | |
787 | ||
788 | Touch.prototype.onMove = function(e) { | |
789 | if (!this.config.showCoordTooltip) { return; } | |
790 | var touch = this.getTouchPosition(e); | |
791 | var borderSize = this.getBorderSize(); | |
792 | this.$coordTooltip | |
793 | .text(touch.valid ? touch.input : '') | |
794 | .css({ | |
795 | position: 'absolute', | |
796 | left: touch.mouse[0] + borderSize + 15, | |
797 | top: touch.mouse[1] + borderSize - this.$coordTooltip.outerHeight() / 2 | |
798 | }); | |
799 | }; | |
800 | ||
801 | module.exports = Touch; | |
802 | ||
803 | },{"component":3,"util2":10}],10:[function(require,module,exports){ | |
804 | /* | |
805 | * util2.js by Meiguro - MIT License | |
806 | */ | |
807 | ||
808 | var util2 = (function(){ | |
809 | ||
810 | var util2 = {}; | |
811 | ||
812 | util2.noop = function() {}; | |
813 | ||
814 | util2.copy = function(a, b) { | |
815 | b = b || (a instanceof Array ? [] : {}); | |
816 | for (var k in a) { b[k] = a[k]; } | |
817 | return b; | |
818 | }; | |
819 | ||
820 | util2.inherit = function(child, parent, proto) { | |
821 | child.prototype = Object.create(parent.prototype); | |
822 | child.prototype.constructor = child; | |
823 | if (proto) { | |
824 | util2.copy(proto, child.prototype); | |
825 | } | |
826 | return child.prototype; | |
827 | }; | |
828 | ||
829 | if (typeof module !== 'undefined') { | |
830 | module.exports = util2; | |
831 | } | |
832 | ||
833 | return util2; | |
834 | ||
835 | })(); | |
836 | ||
837 | },{}],11:[function(require,module,exports){ | |
838 | /* global unsafeWindow */ | |
839 | module.exports = typeof unsafeWindow !== 'undefined' ? unsafeWindow : window; | |
840 | ||
841 | },{}]},{},[1]) |