미디어위키:Gadget-xash3d.js

리버티게임(개발), 모두가 만들어가는 자유로운 게임
imported>Senouis님의 2023년 3월 27일 (월) 00:57 판
둘러보기로 이동 검색으로 이동

참고: 설정을 저장한 후에 바뀐 점을 확인하기 위해서는 브라우저의 캐시를 새로 고쳐야 합니다.

  • 파이어폭스 / 사파리: Shift 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5 또는 Ctrl-R을 입력 (Mac에서는 ⌘-R)
  • 구글 크롬: Ctrl-Shift-R키를 입력 (Mac에서는 ⌘-Shift-R)
  • 인터넷 익스플로러 / 엣지: Ctrl 키를 누르면서 새로 고침을 클릭하거나, Ctrl-F5를 입력.
  • 오페라: Ctrl-F5를 입력.
/**
 * Xash3D for Libertygame loader
 * external server code: https://github.com/Xen-alpha/Xen-alpha.github.io
 * 제작자: [[사용자:senouis]]
**/
function xash3d_asyncJSLoader(url) {
	return new Promise(function (resolve, reject) {
	try {
		var scriptElement = document.createElement("script");
		scriptElement.src = url;
		scriptElement.async = true; // force asynchronous loading
		scriptElement.type = "text/javascript";
		var contextsection = document.getElementById("mw-content-text");
		scriptElement.addEventListener("load", function (ev) {
	        resolve({ status: true });
	    });
	    scriptElement.addEventListener("error", function (ev) {
	        reject({
	            status: false,
	            message: "Failed to load the script"
	        });
	    });
	    contextsection.appendChild(scriptElement);
	} catch (e) {
        reject(e);
    }
	});
}

function xash3d_loadElement() {
	try {
		// Game canvas
		var canvas = document.createElement("canvas");
		canvas.style = "display:none;";
		canvas.class = "emscripten";
		canvas.id = "canvas";
		canvas.oncontextmenu = "event.preventDefault()";
		var canvasparent = document.getElementsByClassName("emscripten_border")[0]; // first element of emscripten-border
		canvasparent.appendChild(canvas);
		// screen option
		var gamecontrol = document.getElementById('xash-controls');
		var a1 = document.createElement("a");
		a1.class = "xash-glow";
		a1.innerHTML = "<span><input type=\"checkbox\" id=\"resize\">Resize canvas</span>";
		gamecontrol.appendChild(a1);
		var a2 = document.createElement("a");
		a2.class = "xash-glow";
		a2.innerHTML = "<span><input type=\"checkbox\" id=\"pointerLock\" checked>Lock/hide mouse pointer &nbsp;&nbsp;&nbsp;</span>";
		gamecontrol.appendChild(a2);
		var controlinputspan = document.createElement("span");
		controlinputspan.innerHTML = "<input type=\"button\" value=\"Fullscreen\" onclick=\"Module.requestFullscreen(document.getElementById('pointerLock').checked, document.getElementById('resize').checked)\">";
		gamecontrol.appendChild(controlinputspan);
		var outputcontainer = document.getElementById("xash-output-container");
		outputcontainer.innerHTML = "<textarea id=\"xash-output\" rows=\"8\"></textarea>";
		// game option
		var gameoptionsTitle = document.getElementById("optionsTitle");
		gameoptionsTitle.innerHTML = "<a class=\"glow\"><u><h1>Game Options</h1></u></a>";
		var pkgHider = document.getElementById("pkgHider");
		pkgHider.innerHTML = "<input name=\"b\" type=\"radio\" id=\"rPackage\" checked=true />Emscripten package from server (cached in IndexedDB if availiable)<select id=\"selectPkg\" style=\"display:none\"></select><br>";
		var zipHider = document.getElementById("zipHider");
		zipHider.innerHTML = "<input name=\"b\" type=radio id=\"rZip\" />ZIP archive from server (slower, but smaller, no IndexedDB cache)<select id=\"selectZip\" style=\"display:none\"></select><br>";
		var localHider = document.getElementById("localHider");
		localHider.innerHTML = "<input name=\"b\" type=radio id=\"rLocalZip\"  />Local ZIP file:<input type=file name=\"c\" id=\"iZipFile\" />";
		var xashlauncher = document.getElementById("xash-launch");
		xashlauncher.innerHTML = "Command-line arguments: <input name=\"d\" type=text id=\"iArgs\" /><br><br><input type=button onclick=\"startXash();return false;\" value=\"Launch Xash3D!\" />";
		if (document.createElement("detect").style.textShadow === "") {
			document.getElementsByTagName("html")[0].className += " textshadow";
		}
		// now load js files from external server
		xash3d_asyncJSLoader("https://xen-alpha.github.io/browserfs.min.js")
		.then(function (data) {
			var zipMods = [];
			var pkgMods = [];
			xash3d_asyncJSLoader("https://xen-alpha.github.io/mods.js")
			.then(function(data) {
				var statusElement = document.getElementById('status');
				var progressElement = document.getElementById('progress');
				var asyncDialog = document.getElementById('asyncDialog');
				var myerrorbuf = '';
				var myerrordate = new Date();
				var mounted = false;
				var gamedir = 'valve';
				var moduleCount = 0;
				//var mem = 150;
				var mfs;
				var zipSize;
		
		
				// make BrowserFS to work on ES5 browsers
				if (!ArrayBuffer["isView"]) {
					ArrayBuffer.isView = function(a) {
						return a !== null && typeof(a) === "object" && a['buffer'] instanceof ArrayBuffer;
					};
		
				}
		
				showElement('optionsTitle', false);
		
				function prepareSelects()
				{
					var len = zipMods.length;
					var select = document.getElementById('selectZip');
					if( len )
					{
						showElement('zipHider', true);
		
						if(len > 1)
						{
							var links = '';
							for(var i = 0; i < len; i++)
							{
								select.options[i] = new Option(zipMods[i][1], zipMods[i][0]);
								links += '<br><a href="'+zipMods[i][0]+'">'+zipMods[i][1]+'</a>';
							}
							select.style.display = 'block';
							document.getElementById('linksPlaceholder').innerHTML += links;
							showElement('linksPlaceholder', true);
						}
					}
					else
						document.getElementById('rZip').checked = false;
					len = pkgMods.length;
					select = document.getElementById('selectPkg');
					if( len )
					{
						showElement('pkgHider', true);
		
						if(len > 1)
						{
							for(var k = 0; k < len; k++)
								select.options[k] = new Option(pkgMods[k][1], pkgMods[k][0]);
							select.style.display = 'block';
						}
					}
					else
						document.getElementById('rPackage').checked = false;
		
					if( !zipMods.length && !len )
					{
						document.getElementById('rLocalZip').checked = true;
						showElement('rLocalZip', false);
					}
				}
		
				try{mem = Math.round(window.location.hash.substring(1));}
				catch(e) {mem = 150;}
		
				var Module = {
					TOTAL_MEMORY: mem * 1024 * 1024,
					preRun: [],
					postRun: [],
					print: (function() {
						var element = document.getElementById('output');
						if (element) element.value = ''; // clear browser cache
						return function(text) {
							if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
							// These replacements are necessary if you render to raw HTML
							//text = text.replace(/&/g, "&amp;");
							//text = text.replace(/</g, "&lt;");
							//text = text.replace(/>/g, "&gt;");
							//text = text.replace('\n', '<br>', 'g');
							//console.log(text);
							if(text)
								myerrorbuf += text + '\n';
							if (element) {
								if(element.value.length > 65536)
									element.value = element.value.substring(512) + myerrorbuf;
								else
									element.value += myerrorbuf;
								element.scrollTop = element.scrollHeight; // focus on bottom
							}
							myerrorbuf = '';
						};
					})(),
					printErr: function(text) {
						if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
						if (0) { // XXX disabled for safety typeof dump == 'function') {
							dump(text + '\n'); // fast, straight to the real console
						} else {
							if( myerrorbuf.length > 2048 )
							myerrorbuf = 'some lines skipped\n'+ myerrorbuf.substring(512);
							myerrorbuf += text + '\n';
							if(  new Date() - myerrordate > 3000 )
							{
								myerrordate = new Date();
								Module.print();
							}
						}
					},
					canvas: (function() {
						var canvas = document.getElementById('canvas');
		
						// As a default initial behavior, pop up an alert when webgl context is lost. To make your
						// application robust, you may want to override this behavior before shipping!
						// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
						canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
		
						return canvas;
					})(),
					setStatus: function(text) {
						if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
						if (text === Module.setStatus.text) return;
						if(  new Date() - myerrordate > 3000 )
						{
							myerrordate = new Date();
							Module.print();
						}
		
						statusElement.innerHTML = text;
						if( progressElement )
						{
							var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
		
							if(m)
							{
								var progress = Math.round(parseInt(m[2])*100/parseInt(m[4]));
								progressElement.style.color = progress > 5?'#303030':'#aaa000';
								progressElement.style.width = progressElement.innerHTML = ''+progress+'%';
							}
							showElement('progress1', !!m);
						}
					},
					totalDependencies: 0,
					monitorRunDependencies: function(left) {
						this.totalDependencies = Math.max(this.totalDependencies, left);
						if(left)
							Module.setStatus('Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')');
					}
				};
				window.onerror = function(event) {
					if(mounted)
						FS.syncfs(false, function(err){Module.print('Saving IDBFS: '+err);});
					if( (''+event).indexOf('SimulateInfiniteLoop') > 0 )
						return;
					var text = 'Exception thrown: ' + event;
					text = text.replace(/&/g, "&amp;");
					text = text.replace(/</g, "&lt;");
					text = text.replace(/>/g, "&gt;");
					text = text.replace('\n', '<br>', 'g');
					Module.setStatus(text);
					Module.print('Exception thrown: ' + event);
				};
		
				function haltRun()
				{
				}
		
				var savedRun;
		
				function radioChecked(id)
				{
					var r = document.getElementById('r'+id);
					if(r) return r.checked;
					return false;
				}
		
				function showElement(id, show)
				{
					var e = document.getElementById(id);
					if(!e) return;
					e.style.display=show?'block':'none';
				}
				Module.setStatus('Downloading...');
		
		
		
				function startXash()
				{
					showElement('loader1', false);
					showElement('optionsTitle', false);
					showElement('fSettings', false);
					setupFS();
					Module.arguments = document.getElementById('iArgs').value.split(' ');
					Module.run = run = savedRun;
					if( radioChecked('Zip') )
						fetchZIP(zipMods.length>1?document.getElementById('selectZip').value:zipMods[0][0], savedRun);
					else if( (!zipMods.length && !pkgMods.length) || radioChecked('LocalZip') )
					{
					var reader = new FileReader();
						reader.onload = function(){
							mountZIP(reader.result);
							Module.print("Loaded zip data");
							savedRun();
						};
						reader.readAsArrayBuffer(document.getElementById('iZipFile').files[0]);
					}
					else if( radioChecked('Package') )
					{
						var script = document.createElement('script');
						script.onload = savedRun;
						document.body.appendChild(script);
						script.src = pkgMods.length>1?document.getElementById('selectPkg').value:pkgMods[0][0];
					}
					showElement('canvas', true);
		
					window.addEventListener("beforeunload", function (e) {
						var confirmationMessage = 'Leave the game?';
		
						(e || window.event).returnValue = confirmationMessage; //Gecko + IE
						return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
					});
				}
		
				function mountZIP(data)
				{
					var Buffer = BrowserFS.BFSRequire('buffer').Buffer;
					mfs.mount('/zip', new BrowserFS.FileSystem.ZipFS(Buffer.from(data)));
					FS.mount(new BrowserFS.EmscriptenFS(), {root:'/zip'}, '/rodir');
				}
		
				function fetchZIP(packageName, cb)
				{
					var xhr = new XMLHttpRequest();
					xhr.open('GET', packageName, true);
					xhr.responseType = 'arraybuffer';
		
					xhr.onprogress = function(event) {
						var url = packageName;
						var size;
						if (event.total) size = event.total;
						else size = zipMods[document.getElementById('selectZip').selectedIndex][2];
						if (event.loaded) {
							var total = size;
							var loaded = event.loaded;
							var num = 0;
							if (Module['setStatus']) Module['setStatus']('Downloading data... (' + loaded + '/' + total + ')');
						} else if (!Module.dataFileDownloads) {
							if (Module['setStatus']) Module['setStatus']('Downloading data...');
						}
					};
					xhr.onerror = function(event) {
						throw new Error("NetworkError");
					};
					xhr.onload = function(event) {
						if (xhr.status == 200 || xhr.status == 304 || xhr.status == 206 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0
							mountZIP(xhr.response);
							cb();
						} else {
							throw new Error(xhr.statusText + " : " + xhr.responseURL);
						}
					};
					xhr.send(null);
				}
		
				function setupFS()
				{
					FS.mkdir('/rodir');
					FS.mkdir('/xash');
					try
					{
						mfs = new BrowserFS.FileSystem.MountableFileSystem();
						BrowserFS.initialize(mfs);
					}
					catch(e)
					{
						mfs = undefined;
						Module.print('Failed to initialize BrowserFS: '+e);
					}
		
					if( radioChecked('IndexedDB'))
					{
						FS.mount(IDBFS,{},'/xash');
						FS.syncfs(true,function(err){if(err)Module.print('Loading IDBFS: ' + err);});
						mounted = true;
					}
		
					if( radioChecked('LocalStorage') && mfs)
					{
						mfs.mount('/ls', new BrowserFS.FileSystem.LocalStorage());
						FS.mount(new BrowserFS.EmscriptenFS(), {root:'/ls'}, '/xash');
						Module.print('LocalStorage mounted');
					}
		
					FS.chdir('/xash/');
				}
		
				function skipRun()
				{
					savedRun = run;
					Module.run = haltRun;
					run = haltRun;
		
					Module.setStatus("Engine downloaded!");
					showElement('loader1', false);
					showElement('optionsTitle', true);
		
					if(window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB)
						showElement('idbHider', true);
					prepareSelects();
					showElement('fSettings',true);
		
					ENV.XASH3D_GAMEDIR = gamedir;
					ENV.XASH3D_RODIR = '/rodir';
		
					function loadModule(name)
					{
						var script = document.createElement('script');
						script.onload = function(){moduleCount++;if(moduleCount==3){Module.setStatus("Scripts downloaded!");}};
						document.body.appendChild(script);
						script.src = name + ".js";
					}
		
					loadModule("server");
					loadModule("client");
					loadModule("menu");
				}
		
				Module.preInit = [skipRun];
				Module.websocket = [];
				Module.websocket.url = 'wsproxy://the-swank.pp.ua:3000/';
				ENV = [];
				
				(function() {
	              var memoryInitializer = 'https://xen-alpha.github.io/xash.html.mem';
	              if (typeof Module['locateFile'] === 'function') {
	                memoryInitializer = Module['locateFile'](memoryInitializer);
	              } else if (Module['memoryInitializerPrefixURL']) {
	                memoryInitializer = Module['memoryInitializerPrefixURL'] + memoryInitializer;
	              }
	              var xhr = Module['memoryInitializerRequest'] = new XMLHttpRequest();
	              xhr.open('GET', memoryInitializer, true);
	              xhr.responseType = 'arraybuffer';
	              xhr.send(null);
	            })();

    	    	var script = document.createElement('script');
        		script.src = "https://xen-alpha.github.io/xash.js";
        		document.getElementById("mw-content-text").appendChild(script);
        		
			});
		});
	} catch (e){
		console.log("initiating xash3d for libertygame failed, stop loading elements...");
	}
}
$(xash3d_loadElement);