NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name gats.io 3D // @description // @version 0.1 // @author entibo // @license MIT // @run-at document-end // @grant none // @match https://gats.io/ // ==/UserScript== window.a16 = ()=>{} // grid background //window.a55 = ()=>{} // fog for(let k of ['RA','RB','RC','RD']) { /* window[k].prototype.draw = ()=>{} window[k].prototype.drawBody = ()=>{} window[k].prototype.drawGun = ()=>{} */ } function a55(_0xb74969, _0x48631e) { if (j31 != j11 && j41 != j12) { var _0x2c90da = _0x48631e['getRelPos']({ 'x': 0, 'y': 0 }); var _0x37fb9f = _0x48631e['getRelPos']({ 'x': j11, 'y': j12 }); var _0x2148a2 = (j11 - j31) / 2; var _0x589b9a = (j12 - j41) / 2; _0xb74969['globalAlpha'] = 0.3; _0xb74969['fillStyle'] = '#b5b5b5'; _0xb74969['fillRect'](_0x2c90da['x'] - 5000, _0x2c90da['y'] - 5000, 5000 + _0x2148a2, j12 + 10000); _0xb74969['fillRect'](_0x37fb9f['x'] - _0x2148a2, _0x2c90da['y'] - 5000, _0x37fb9f['x'] + 5000, j12 + 10000); _0xb74969['fillRect'](_0x2c90da['x'] + _0x2148a2, _0x2c90da['y'] - 5000, j11 - _0x2148a2 * 2, 5000 + _0x589b9a); _0xb74969['fillRect'](_0x2c90da['x'] + _0x2148a2, _0x37fb9f['y'] - _0x589b9a, j11 - _0x2148a2 * 2, 5000 + _0x589b9a); _0xb74969['globalAlpha'] = 1; } } a41=eval(('('+a41+')').replace('a37();',` a37(); let cvs = document.getElementById("canvas") let ctx = cvs.getContext("2d") ctx.save() ctx.translate(cvs.width/2, cvs.height/2) ctx.rotate(Math.PI*cameraAngle/180); ctx.translate(-cvs.width/2, -cvs.height/2); `)) a41=eval(('('+a41+')').replace('a55(j10,c2);',` a55(j10,c2); ctx.restore(); `)) let movement = (() => { function mouseAngleToDir(a) { return Math.floor(((a+45/2)/45))%8 } let DIR = { R: 0, RD: 1, D: 2, LD: 3, L: 4, LU: 5, U: 6, RU: 7, } //let KEYS = ["LEFT","RIGHT","UP","DOWN","RELOAD","SPACE","CLICK"] let KEYS = { LEFT: 0, RIGHT: 1, UP: 2, DOWN: 3, } function moveDir(dir) { let socket = RF.list[0] let dx = ((dir+1)%8<3?1:0) + ((dir+5)%8<3?-1:0) let dy = ((dir+7)%8<3?1:0) + ((dir+3)%8<3?-1:0) if(dx == 0) { socket.send(`k,${KEYS.LEFT},0`) socket.send(`k,${KEYS.RIGHT},0`) } else { let k1 = KEYS.LEFT, k2 = KEYS.RIGHT if(dx < 0) [k1,k2]=[k2,k1] socket.send(`k,${k1},0`) socket.send(`k,${k2},1`) } if(dy == 0) { socket.send(`k,${KEYS.UP},0`) socket.send(`k,${KEYS.DOWN},0`) } else { let k1 = KEYS.UP, k2 = KEYS.DOWN if(dy < 0) [k1,k2]=[k2,k1] socket.send(`k,${k1},0`) socket.send(`k,${k2},1`) } } function move(a) { let dir = mouseAngleToDir(a) moveDir(dir) } function stop() { let socket = RF.list[0] socket.send(`k,${KEYS.LEFT},0`) socket.send(`k,${KEYS.RIGHT},0`) socket.send(`k,${KEYS.UP},0`) socket.send(`k,${KEYS.DOWN},0`) } let r = { move, stop, dx: 0, dy: 0, keys: [0,0,0,0] } function computeDelta() { r.dx = (r.keys[KEYS.LEFT]?-1:0) + (r.keys[KEYS.RIGHT]?+1:0) r.dy = (r.keys[KEYS.UP]?-1:0) + (r.keys[KEYS.DOWN]?+1:0) } document.addEventListener("keydown", e => { e.stopPropagation() let key = e.key.toLowerCase() if(key == "q" || key == "a" || key == "arrowleft") r.keys[KEYS.LEFT] = 1 if(key == "d" || key == "arrowright") r.keys[KEYS.RIGHT] = 1 if(key == "z" || key == "w" || key == "arrowup") r.keys[KEYS.UP] = 1 if(key == "s" || key == "arrowdown") r.keys[KEYS.DOWN] = 1 computeDelta() }, true) document.addEventListener("keyup", e => { e.stopPropagation() let key = e.key.toLowerCase() if(key == "q" || key == "a" || key == "arrowleft") r.keys[KEYS.LEFT] = 0 if(key == "d" || key == "arrowright") r.keys[KEYS.RIGHT] = 0 if(key == "z" || key == "w" || key == "arrowup") r.keys[KEYS.UP] = 0 if(key == "s" || key == "arrowdown") r.keys[KEYS.DOWN] = 0 computeDelta() }, true) return r })() window.movement = movement window.cameraAngle = 0 let start = () => { /** @type import("three") */ const THREE = window.THREE loadPointerLockThing() const scene = new THREE.Scene() scene.fog = new THREE.FogExp2(0x8DD8F8, 0.0015) let renderer = new THREE.WebGLRenderer() renderer.setClearColor(scene.fog.color) renderer.setPixelRatio(window.devicePixelRatio) renderer.setSize(window.innerWidth, window.innerHeight) renderer.domElement.style.position = "absolute" renderer.domElement.style.zIndex = "0" let container = document.body container.appendChild(renderer.domElement) let camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 2000); camera.position.y = 20 // Height the camera will be looking from camera.position.x = 0 camera.position.z = 0 window.camera = camera let controls = new THREE.PointerLockControls(camera) document.addEventListener("click", () => controls.lock()) window.controls = controls ;{ // Lights let lightOne = new THREE.DirectionalLight(0xffffff) lightOne.position.set(1, 1, 1) scene.add(lightOne) let lightTwo = new THREE.DirectionalLight(0xffffff, .4) lightTwo.position.set(1, -1, -1) scene.add(lightTwo) scene.add(new THREE.AmbientLight(0xffffff, 0.3)) }; let gridHelper ;{ // Ground let groundGeo = new THREE.PlaneGeometry(7000, 7000) let groundMat = new THREE.MeshPhongMaterial({ color: 0xf7f7f7, side: THREE.DoubleSide, flatShading: true, }) let ground = new THREE.Mesh(groundGeo, groundMat) ground.position.set(7000/2, 1, 7000/2) ground.rotation.x = Math.PI/2 scene.add(ground) gridHelper = new THREE.GridHelper(7000,700) window.gridHelper = gridHelper gridHelper.position.set(7000/2, 2, 7000/2) scene.add(gridHelper) }; ;{ // Walls (fog) half are not working for(let i=0, sign=1; i < 2; i++) { let H = 100 let perimGeo = new THREE.PlaneGeometry(7000, H); // Make the material double sided let perimMat = new THREE.MeshPhongMaterial({ color: 0x464646, side: THREE.DoubleSide }); // Make two walls let perimWallLR = new THREE.Mesh(perimGeo, perimMat); let perimWallFB = new THREE.Mesh(perimGeo, perimMat); // Create left/right walls perimWallLR.position.set(7000/2 + sign*j31/2, H / 2, 7000/2); perimWallLR.rotation.y = Math.PI; scene.add(perimWallLR); // Create front/back walls perimWallFB.position.set(7000/2, H / 2, 7000/2 + sign*j31/2); scene.add(perimWallFB); sign = -1; // Swap to negative value } } let makeBlock = (x, z, w, h, color) => { let H = 20 let boxGeo = new THREE.BoxGeometry(w, H, h) let boxMat = new THREE.MeshPhongMaterial({ color, }) let box = new THREE.Mesh(boxGeo, boxMat) box.position.x = x box.position.z = z box.position.y = H/2 scene.add(box) return box } /** @type Map<number,THREE.Object3D> */ let boxes = new Map() window.boxes = boxes let animate = () => { requestAnimationFrame(animate) renderer.render(scene, camera) if(c3 && RD.pool[c3]) { camera.position.x = RD.pool[c3].x camera.position.z = RD.pool[c3].y cameraAngle = (() => { let v = camera.getWorldDirection() return (360-180*Math.atan2(v.x, v.z)/Math.PI) % 360 })() if(movement.dx != 0 || movement.dy != 0) { let a = cameraAngle a += 180 a += 180*Math.atan2(movement.dy, movement.dx)/Math.PI a = ((a+720)%360) movement.move(a) } else { movement.stop() } let socket = RF.list[0] RD.pool[c3].playerAngle = (90+cameraAngle)%360 socket.send(`m,9999,9999,${RD.pool[c3].playerAngle}`) } Object.values(window.RB.pool).forEach(obj => { if(obj.activated) { if(!boxes.has(obj.id)) { let x = obj.x, y = obj.y let w, h, color switch(obj.type) { case "crate": w = 100; h = 100; color = 0xdfbf9f break case "longCrate": w = 100; h = 50; color = 0xbec8dd if(obj.angle == 180) { [w,h] = [h,w] } break case "userCrate": w = 40; h = 40; color = 0x53c68c default: w = 20; h = 20; color = 0x000000 break } let mesh = makeBlock(x, y, w, h, color) boxes.set(obj.id, mesh) } } else { let mesh = boxes.get(obj.id) if(mesh) scene.remove(mesh) } }) } animate() }; function inject(url) { let script = document.createElement("script") script.src = url document.head.appendChild(script) return new Promise((resolve, reject) => { script.addEventListener("load", resolve) script.addEventListener("error", reject) }) } loadPointerLockThing = () => { THREE.PointerLockControls = function ( camera, domElement=document.body ) { this.domElement = domElement; this.isLocked = false; // Set to constrain the pitch of the camera // Range is 0 to Math.PI radians this.minPolarAngle = 0; // radians this.maxPolarAngle = Math.PI; // radians // // internals // var scope = this; var changeEvent = { type: 'change' }; var lockEvent = { type: 'lock' }; var unlockEvent = { type: 'unlock' }; var euler = new THREE.Euler( 0, 0, 0, 'YXZ' ); var PI_2 = Math.PI / 2; var vec = new THREE.Vector3(); function onMouseMove( event ) { event.stopPropagation() event.preventDefault() if ( scope.isLocked === false ) return; var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; euler.setFromQuaternion( camera.quaternion ); euler.y -= movementX * 0.002; euler.x -= movementY * 0.002; euler.x = Math.max( PI_2 - scope.maxPolarAngle, Math.min( PI_2 - scope.minPolarAngle, euler.x ) ); camera.quaternion.setFromEuler( euler ); scope.dispatchEvent( changeEvent ); } function onPointerlockChange() { if ( scope.domElement.ownerDocument.pointerLockElement === scope.domElement ) { scope.dispatchEvent( lockEvent ); scope.isLocked = true; } else { scope.dispatchEvent( unlockEvent ); scope.isLocked = false; } } function onPointerlockError() { console.error( 'THREE.PointerLockControls: Unable to use Pointer Lock API' ); } this.connect = function () { scope.domElement.ownerDocument.addEventListener( 'mousemove', onMouseMove, true ); scope.domElement.ownerDocument.addEventListener( 'pointerlockchange', onPointerlockChange, false ); scope.domElement.ownerDocument.addEventListener( 'pointerlockerror', onPointerlockError, false ); }; this.disconnect = function () { scope.domElement.ownerDocument.removeEventListener( 'mousemove', onMouseMove, true ); scope.domElement.ownerDocument.removeEventListener( 'pointerlockchange', onPointerlockChange, false ); scope.domElement.ownerDocument.removeEventListener( 'pointerlockerror', onPointerlockError, false ); }; this.dispose = function () { this.disconnect(); }; this.getObject = function () { // retaining this method for backward compatibility return camera; }; this.getDirection = function () { var direction = new THREE.Vector3( 0, 0, - 1 ); return function ( v ) { return v.copy( direction ).applyQuaternion( camera.quaternion ); }; }(); this.moveForward = function ( distance ) { // move forward parallel to the xz-plane // assumes camera.up is y-up vec.setFromMatrixColumn( camera.matrix, 0 ); vec.crossVectors( camera.up, vec ); camera.position.addScaledVector( vec, distance ); }; this.moveRight = function ( distance ) { vec.setFromMatrixColumn( camera.matrix, 0 ); camera.position.addScaledVector( vec, distance ); }; this.lock = function () { this.domElement.requestPointerLock(); }; this.unlock = function () { scope.domElement.ownerDocument.exitPointerLock(); }; this.connect(); }; THREE.PointerLockControls.prototype = Object.create( THREE.EventDispatcher.prototype ); THREE.PointerLockControls.prototype.constructor = THREE.PointerLockControls; } inject("https://cdnjs.cloudflare.com/ajax/libs/three.js/r120/three.min.js").then(start)