PageSourceSearch

https://rifftrax.games/js/mod.js?version=1.0.0.1

js rifftrax.games collected 2026-10-05 02:21:29 UTC 15,725 bytes, 685 lines download raw bytes

1
2const alertDialogUi = document.getElementById('alert');
3const alertMessageUi = document.getElementById('alertMessage');
4
5const homeUiWrapper = document.getElementById('homeWrapper');
6
7const moderationUiWrapper = document.getElementById('moderationWrapper');
8
9const messageUiWrapper = document.getElementById('messageWrapper');
10const messageUiTitle = document.getElementById('messageTitle');
11const messageUi = document.getElementById('message');
12
13const roomInput = document.getElementById('room');
14const passwordInput = document.getElementById('password');
15
16
17const content = document.getElementById('content');
18
19const PLAYER_ID_KEY = 'WTD_PLAYER_ID';
20const MODERATOR_KEY = 'MODERATOR';
21
22const MAX_RECONNECT_TRIES = 10;
23const RECONNECT_TIMEOUT = 1000;
24
25var modWrappers = [
26	document.getElementById('mod0'),
27	document.getElementById('mod1'),
28	document.getElementById('mod2'),
29	document.getElementById('mod3'),
30	document.getElementById('mod4'),
31	document.getElementById('mod5'),
32];
33
34var modButtons = [
35	document.getElementById('modButton0'),
36	document.getElementById('modButton1'),
37	document.getElementById('modButton2'),
38	document.getElementById('modButton3'),
39	document.getElementById('modButton4'),
40	document.getElementById('modButton5'),
41];
42
43var usernameDivs = [
44	document.getElementById('modUsername0'),
45	document.getElementById('modUsername1'),
46	document.getElementById('modUsername2'),
47	document.getElementById('modUsername3'),
48	document.getElementById('modUsername4'),
49	document.getElementById('modUsername5'),
50]
51
52
53if(localStorage.getItem('mod_pw') != null)
54	passwordInput.value = localStorage.getItem('mod_pw');
55
56if(localStorage.getItem('room') != null)
57	roomInput.value = localStorage.getItem('room');
58
59var _playerInternalId = localStorage.getItem('moderator_player_id');
60var _roomName = '';
61var _password = '';
62var _connected = false;
63var _joinRoomAfterConnect = false;
64var _reconnectCount = 0;
65var _tryingToReconnect = false;
66var _checkReconnectOnVisible = false;
67var _currentSubmissions = [];
68
69
70let _wakeLock = null;
71let _waklockSupported = 'wakeLock' in navigator;
72
73
74var client = new Photon.LoadBalancing.LoadBalancingClient(
75	window.location.href.startsWith('https') ? Photon.ConnectionProtocol.Wss : Photon.ConnectionProtocol.Ws,
76	'ccced71e-9a4e-4c84-a70d-b78576965328',
77	'v0.1_local_play_2.23'
78);
79
80function updateDisplay(displayType){
81
82	if(displayType == null){
83		content.style.display = 'none';
84		return;
85	}
86
87	content.style.display = 'block';
88
89	if(displayType == 'home') {
90		releaseWakeLock();
91	}
92
93	switch(displayType){
94		case 'message':
95		case 'start':
96		case 'cancel':
97		case 'next_game':
98		case 'intro':
99			messageUiTitle.style.display = 'block'
100			break;
101		default:
102			messageUiTitle.style.display = 'none';
103			break;
104	}
105
106	switch(displayType){
107		case 'message':
108		case 'intro':
109			messageUiWrapper.style.display = 'block'
110			break;
111		default:
112			messageUiWrapper.style.display = 'none';
113			break;
114	}
115
116	homeUiWrapper.style.display = displayType == 'home' ? 'block' : 'none';
117	moderationUiWrapper.style.display = displayType == 'moderate' ? 'block' : 'none';
118
119	setTimeout(scrollToTop, 0);
120
121}
122
123function scrollToTop(){
124	document.documentElement.scrollTop = 0;
125}
126
127function initDisplay(){
128	_joinRoomAfterConnect = false;
129	updateDisplay('home');
130}
131
132initDisplay();
133
134
135function createGuid() {
136   function _p8(s) {
137      let p = (Math.random().toString(16)+"000000000").substr(2,8);
138      return s ? "-" + p.substr(0,4) + "-" + p.substr(4,4) : p ;
139   }
140   return _p8() + _p8(true) + _p8(true) + _p8();
141}
142
143function setGenericMessage(text){
144	messageUi.innerText = text;
145	updateDisplay('message');
146}
147
148
149function closeAlert(){
150	alertDialogUi.classList.remove('active');
151}
152
153function setAlert(message){
154	if(message == null || message == ''){
155		closeAlert();
156		return;
157	}
158	alertMessageUi.innerText = message;
159	alertDialogUi.classList.add('active');
160}
161
162
163function joinGame(e){
164
165	_checkReconnectOnVisible = false;
166	_tryingToReconnect = false;
167
168	_roomName = roomInput.value.trim().toUpperCase();
169	if(_roomName.length == 0){
170		setAlert("Please enter a room.");
171		return false;
172	}
173
174
175	localStorage.setItem('room', _roomName);
176
177	_password = passwordInput.value.trim().toUpperCase();
178
179	if(_password.length == 0){
180		setAlert('Please enter a password.');
181		return false;
182	}
183
184	localStorage.setItem('mod_pw', _password);
185
186	//reset the actor
187	client._myActor = new Photon.LoadBalancing.Actor(createGuid(), -1, true);
188	closeAlert();
189
190	if(_playerInternalId == null) {
191		_playerInternalId = createGuid() + '_' + Date.now();
192		localStorage.setItem('player_id', _playerInternalId);
193	}
194
195	client.myActor().setCustomProperty(PLAYER_ID_KEY, _playerInternalId);
196	client.myActor().setCustomProperty(MODERATOR_KEY, 'true');
197
198	setGenericMessage('Connecting...')
199
200	if(!_connected){
201		connectToServerAndJoinRoom();
202	}
203	else{
204		joinRoom();
205	}
206
207	return false;
208
209}
210
211function connectToServerAndJoinRoom(){
212	_joinRoomAfterConnect = true;
213	client.connectToRegionMaster('us');
214}
215
216function joinRoom(){
217	closeAlert();
218	client.joinRoom(_roomName);
219}
220
221function disconnect(){
222	_connected = false;
223
224	if(client.isJoinedToRoom() || client.isConnectedToMaster())
225		client.disconnect();
226	else
227		initDisplay();
228}
229
230
231const WaitingForPlayersToJoinState = 0;
232const PlayingVideoToDubState = 1;
233const UserSubmittingDubsState = 2;
234const PlayingBackSubmittedDubsState = 3;
235const VotingOnDubsState = 4;
236const DisplayingVotingResultsState = 5;
237const WaitingForNextGameState = 6;
238const PlayingInstructionsGameState = 7;
239const NextRoundState = 8;
240
241function raiseModerationEvent(eventType, eventData){
242
243	if(eventData == null)
244		eventData = {}
245
246	eventData['password'] = _password;
247	eventData['playerId'] = _playerInternalId;
248
249
250	const data = {
251		'eventType': eventType,
252		'json': eventData != null ? JSON.stringify(eventData) : null,
253	};
254
255	client.raiseEvent(
256		ModerationEvent,
257		JSON.stringify(data),
258		{'receivers': Photon.LoadBalancing.Constants.ReceiverGroup.MasterClient}
259	);
260
261}
262
263
264
265client.onJoinRoom = function(createdByMe){
266
267	raiseModerationEvent(ModerationVerifyPasswordEvent, null);
268
269	_checkReconnectOnVisible = false;
270	createWakeLock();
271
272};
273
274
275
276client.onActorJoin = function(actor) {
277
278}
279
280client.onActorLeave = function(actor, cleanup){
281
282	//already disconnected so who cares
283	if(!_connected)
284		return;
285
286	//server gone
287	//only the server should ever by actor number 1
288	if(actor.getCustomProperty(PLAYER_ID_KEY) == 'SERVER' || actor.actorNr == 1){
289		setAlert('Lost Connection to Host');
290		disconnect();
291		return;
292	}
293
294}
295
296
297client.onStateChange = function(state){
298	switch(state){
299		case Photon.LoadBalancing.LoadBalancingClient.State.ConnectedToMaster:
300			_connected = true;
301			break;
302		case Photon.LoadBalancing.LoadBalancingClient.State.JoinedLobby:
303			_connected = true;
304
305			if(_joinRoomAfterConnect){
306				_joinRoomAfterConnect = false;
307				joinRoom();
308			}
309			break;
310
311		case Photon.LoadBalancing.LoadBalancingClient.State.Disconnected:
312			//if false, it was an intentional disconnect
313			if(_connected){
314
315				_checkReconnectOnVisible = document.visibilityState !== 'visible';
316				if(_checkReconnectOnVisible)
317					return;
318
319				setAlert('Lost connection to server');
320				_connected = false;
321			}
322
323			_checkReconnectOnVisible = false;
324			_joinRoomAfterConnect = false;
325			initDisplay();
326
327			break;
328
329	}
330};
331
332function alphaNumericOnly(text){
333	text.value = text.value.replace( /[^a-zA-Z0-9 ]/gm, '');
334}
335
336
337document.onkeydown = function(e){
338	e = e || window.event;
339	if(e.keyCode == 27){
340		closeOverlays();
341	}
342}
343
344roomInput.addEventListener( "input", event => {alphaNumericOnly(roomInput);}, false);
345roomInput.addEventListener( "paste", event => {setTimeout(function(){alphaNumericOnly(roomInput);}, 0)}, false);
346passwordInput.addEventListener( "input", event => {alphaNumericOnly(passwordInput);}, false);
347passwordInput.addEventListener( "paste", event => {setTimeout(function(){alphaNumericOnly(passwordInput);}, 0)}, false);
348
349
350client.onError = function(errorCode, errorMsg){
351
352
353	//game server disconnected
354	if(errorCode == 1003 && _connected){
355		setAlert("Lost connection to host. Reconnecting...");
356		_reconnectCount = 0;
357		attemptToReconnect();
358		return;
359	}
360
361	//3004 name server peer timeout
362	if(errorCode == 3004){
363		if(_tryingToReconnect){
364			setTimeout(attemptToReconnect, RECONNECT_TIMEOUT);
365		}else{
366			let port = getPortFromUrl(client.masterServerAddress, '19093');
367			setAlert("Unable to connect to host. If this happens repeatedly, ensure that port " + port + " is not blocked on your network's firewall");
368			initDisplay();
369		}
370	}
371
372	//Master peer timeout, potentially due to firewall
373	if(errorCode == 1004){
374		let port = getPortFromUrl(client.masterServerAddress, '19090');
375		if(client.masterServerAddress != null && client.masterServerAddress.lastIndexOf(':') > 0){
376			port = client.masterServerAddress.substring(client.masterServerAddress.lastIndexOf(':') + 1);
377		}
378		setAlert("Unable to connect to host. If this happens repeatedly, ensure that port " + port + " is not blocked on your network's firewall.");
379		initDisplay();
380	}
381}
382
383function getPortFromUrl(url, defaultValue=''){
384	if(url == null || url.lastIndexOf(':') <= 0)
385		return defaultValue;
386
387	return url.substring(url.lastIndexOf(':') + 1);
388}
389
390function attemptToReconnect(){
391	setGenericMessage("Reconnecting...");
392	_tryingToReconnect = true;
393	_reconnectCount++;
394
395	if(_reconnectCount > MAX_RECONNECT_TRIES){
396		_connected = false;
397		_checkReconnectOnVisible = false;
398		client.disconnect();
399		initDisplay();
400		setAlert('Reconnecting to host failed.');
401		return;
402	}
403
404	connectToServerAndJoinRoom();
405
406
407}
408
409client.onOperationResponse = function(errorCode, errorMsg, code, content){
410	if(errorCode){
411		// game does not exist
412		if(errorCode == 32758){
413			setAlert('Room "' + _roomName + '" not found.');
414			disconnect();
415			initDisplay();
416		}else if(errorCode == 32765){
417			setAlert('That game is full.');
418			disconnect();
419			initDisplay();
420		}
421	}
422}
423
424
425const EnterDubTimeEvent = 1;
426const DubSubmittedEvent = 2;
427const PlayingBackDubsEvent = 3;
428const StreamingClientEvent = 150;
429const ModerationEvent = 151;
430
431
432client.onEvent = function(code, content, actorNr){
433
434	switch(code){
435		case StreamingClientEvent:
436			handleStreamingClientEvent(content);
437			break;
438		case ModerationEvent:
439			handleModerationEvent(content);
440			break;
441		case PlayingBackDubsEvent:
442			_currentSubmissions = [];
443			updateCurrentSubmissionsDisplay();
444			break;
445		case EnterDubTimeEvent:
446			_currentSubmissions = [];
447			updateCurrentSubmissionsDisplay();
448			break;
449		case DubSubmittedEvent:
450
451			let submission = JSON.parse(content);
452			let dedupe = [];
453			for(let x = 0; x<_currentSubmissions.length; x++){
454				if(_currentSubmissions[x]['playerID'] == submission['playerID'])
455					continue;
456				dedupe.push(_currentSubmissions[x]);
457			}
458
459			dedupe.push(submission);
460			_currentSubmissions = dedupe;
461			updateCurrentSubmissionsDisplay();
462			break;
463	}
464}
465
466const ModerationNotEnabledEvent = 0;
467const ModerationVerifyPasswordEvent = 1;
468const ModerationInvalidPasswordEvent = 2;
469const ModerationModExistsEvent = 3;
470const ModerationValidLoginEvent = 4;
471const ModerationNoModeratorPickARiffEvent = 5;
472const ModerationApprovalSubmittedEvent = 6;
473
474
475function handleModerationEvent(content){
476
477		let event = JSON.parse(content);
478		let eventData = event['json'] != null && event['json'].length > 0 ? JSON.parse(event['json']) : {};
479
480		switch(event['eventType']){
481			case ModerationNotEnabledEvent:
482				disconnect();
483				setAlert('Moderation is not enabled in this game.');
484				break;
485			case ModerationInvalidPasswordEvent:
486				if(_playerInternalId != eventData['playerId'])
487					return;
488
489				disconnect();
490				setAlert('Invalid moderation password.');
491				break;
492			case ModerationModExistsEvent:
493
494				if(_playerInternalId != eventData['playerId'])
495					return;
496
497				disconnect();
498				setAlert('A moderator is already connected to this game.');
499				break;
500			case ModerationValidLoginEvent:
501
502				if(_playerInternalId != eventData['playerId'])
503					return;
504
505				checkGameStateOnJoin();
506				break;
507			case ModerationNoModeratorPickARiffEvent:
508				disconnect();
509				setAlert('Pick-A-Riff mode does not currently support moderation.');
510				break;
511
512		}
513
514}
515
516
517const StreamingClientPickARiffSubmissionEvent = 8;
518
519function handleStreamingClientEvent(content){
520	let event = JSON.parse(content);
521	let eventData = event['json'] != null && event['json'].length > 0 ? JSON.parse(event['json']) : {};
522
523	switch(event['eventType']){
524		case StreamingClientPickARiffSubmissionEvent:
525			let submission = eventData['sub']
526
527			let dedupe = [];
528			for(let x = 0; x<_currentSubmissions.length; x++){
529				if(_currentSubmissions[x]['playerID'] == submission['playerID'])
530					continue;
531				dedupe.push(_currentSubmissions[x]);
532			}
533
534			dedupe.push(submission);
535			_currentSubmissions = dedupe;
536			updateCurrentSubmissionsDisplay();
537			break;
538	}
539}
540
541function checkGameStateOnJoin(){
542
543
544	let gameState = client.myRoom().getCustomPropertyOrElse('game_state', 0);
545	if(gameState != UserSubmittingDubsState){
546		_currentSubmissions = [];
547		updateCurrentSubmissionsDisplay();
548		return;
549	}
550
551
552	_currentSubmissions = JSON.parse(client.myRoom().getCustomPropertyOrElse('current_submissions', '{"Items":[]}'))['Items'];
553
554	updateCurrentSubmissionsDisplay();
555}
556
557function updateCurrentSubmissionsDisplay(){
558	if(_currentSubmissions.length == 0) {
559		setGenericMessage('Waiting for submissions.');
560		return;
561	}
562
563	for(let x = 0; x<modWrappers.length; x++){
564		if(x >= _currentSubmissions.length){
565			modWrappers[x].style.display = 'none';
566			continue;
567		}
568
569		modWrappers[x].style.display = 'block';
570
571		modButtons[x].innerText = _currentSubmissions[x].dub;
572
573		let userName = getUsernameForPlayerId(_currentSubmissions[x].playerID);
574
575		if(userName != null){
576			usernameDivs[x].innerText = ' - ' + userName;
577			usernameDivs[x].style.display = 'block';
578		}else{
579			usernameDivs[x].style.display = 'none';
580		}
581
582	}
583
584	updateDisplay('moderate');
585
586}
587
588function getUsernameForPlayerId(playerID){
589
590	if(playerID == 'TWITCH_CHAT')
591		return 'Twitch Chat';
592
593	for(let x = 0; x<client.actorsArray.length; x++){
594		let actor = client.actorsArray[x];
595		if(actor.getCustomPropertyOrElse('WTD_PLAYER_ID') == playerID)
596			return actor.name
597	}
598
599	return null;
600}
601
602
603function approveAll(){
604	while(_currentSubmissions.length > 0){
605		approveRiff(0);
606	}
607	_currentSubmissions = [];
608	updateCurrentSubmissionsDisplay();
609}
610
611function rejectRiff(index){
612	submitApproval(_currentSubmissions[index], true);
613
614	_currentSubmissions.splice(index, 1);
615	updateCurrentSubmissionsDisplay();
616}
617
618function approveRiff(index){
619	submitApproval(_currentSubmissions[index], false);
620
621	_currentSubmissions.splice(index, 1);
622	updateCurrentSubmissionsDisplay();
623}
624
625function submitApproval(riff, rejected){
626
627	const data = {
628		'rejected': rejected,
629		'playerID': riff['playerID'],
630		'id': riff['id'],
631		'password': _password,
632	};
633
634	raiseModerationEvent(ModerationApprovalSubmittedEvent, data);
635}
636
637
638
639//wake lock
640async function createWakeLock(){
641
642	if(!_waklockSupported) {
643		return;
644	}
645	try {
646		_wakeLock = await navigator.wakeLock.request('screen');
647
648		_wakeLock.addEventListener('release', () => {
649			// the wake lock has been released
650			_wakeLock = null;
651		});
652	} catch (err) {
653	}
654}
655
656function releaseWakeLock(){
657	if(_wakeLock != null)
658		_wakeLock.release();
659}
660
661document.addEventListener('visibilitychange', () => {
662	if (client.isJoinedToRoom() && document.visibilityState === 'visible') {
663		createWakeLock();
664	}
665
666
667	//attempt to
668	if(document.visibilityState === 'hidden'){
669		_checkReconnectOnVisible = client.isJoinedToRoom();
670	} else if(document.visibilityState === 'visible'){
671		if(_checkReconnectOnVisible){
672			//nothing to do because still connected
673			if(client.isJoinedToRoom())
674				return;
675
676			client.disconnect();
677			attemptToReconnect();
678			return;
679		}
680
681		disconnect();
682	}
683});
684
685

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.