multyx-client 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/controller.js +356 -0
- package/dist/index.js +213 -0
- package/dist/items/index.js +9 -0
- package/dist/items/list.js +250 -0
- package/dist/items/object.js +142 -0
- package/dist/items/router.js +8 -0
- package/dist/items/value.js +131 -0
- package/dist/message.js +36 -0
- package/dist/options.js +10 -0
- package/dist/types.js +2 -0
- package/dist/utils.js +74 -0
- package/multyx.js +1 -0
- package/package.json +34 -0
- package/src/controller.ts +353 -0
- package/src/index.ts +261 -0
- package/src/items/index.ts +14 -0
- package/src/items/list.ts +270 -0
- package/src/items/object.ts +170 -0
- package/src/items/router.ts +5 -0
- package/src/items/value.ts +150 -0
- package/src/message.ts +41 -0
- package/src/options.ts +15 -0
- package/src/types.ts +17 -0
- package/src/utils.ts +78 -0
- package/tsconfig.json +9 -0
- package/webpack.config.js +13 -0
package/multyx.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Multyx=e():t.Multyx=e()}(self,(()=>(()=>{"use strict";var t={376:(t,e,s)=>{Object.defineProperty(e,"__esModule",{value:!0}),e.Controller=void 0;const i=s(210);e.Controller=class{constructor(t){this.listening=new Set,this.ws=t,this.preventDefault=!1,this.keys={},this.mouse={x:NaN,y:NaN,down:!1,centerX:0,centerY:0,scaleX:1,scaleY:1},document.addEventListener("keydown",(t=>{this.preventDefault&&t.preventDefault;const e=t.key.toLowerCase();this.keys[e]&&this.listening.has("keyhold")&&this.relayInput("keyhold",{code:e}),this.keys[t.code]&&this.listening.has("keyhold")&&this.relayInput("keyhold",{code:t.code}),this.listening.has(e)&&!this.keys[e]&&this.relayInput("keydown",{code:t.key}),this.listening.has(t.code)&&!this.keys[t.code]&&this.relayInput("keydown",{code:t.code}),this.keys[e]=!0,this.keys[t.code]=!0})),document.addEventListener("keyup",(t=>{this.preventDefault&&t.preventDefault;const e=t.key.toLowerCase();delete this.keys[e],delete this.keys[t.code],this.listening.has(e)&&this.relayInput("keyup",{code:e}),this.listening.has(t.code)&&this.relayInput("keyup",{code:t.code})})),document.addEventListener("mousedown",(t=>{if(this.preventDefault&&t.preventDefault,this.mouseGetter){const t=this.mouseGetter();this.mouse.x=t.x,this.mouse.y=t.y}else this.mouse.x=(t.clientX-this.mouse.centerX)/this.mouse.scaleX,this.mouse.y=(t.clientY-this.mouse.centerY)/this.mouse.scaleY;this.mouse.down=!0,this.listening.has("mousedown")&&this.relayInput("mousedown",{x:this.mouse.x,y:this.mouse.y})})),document.addEventListener("mouseup",(t=>{if(this.preventDefault&&t.preventDefault,this.mouseGetter){const t=this.mouseGetter();this.mouse.x=t.x,this.mouse.y=t.y}else this.mouse.x=(t.clientX-this.mouse.centerX)/this.mouse.scaleX,this.mouse.y=(t.clientY-this.mouse.centerY)/this.mouse.scaleY;this.mouse.down=!1,this.listening.has("mouseup")&&this.relayInput("mouseup",{x:this.mouse.x,y:this.mouse.y})})),document.addEventListener("mousemove",(t=>{if(this.preventDefault&&t.preventDefault,this.mouseGetter){const t=this.mouseGetter();this.mouse.x=t.x,this.mouse.y=t.y}else this.mouse.x=(t.clientX-this.mouse.centerX)/this.mouse.scaleX,this.mouse.y=(t.clientY-this.mouse.centerY)/this.mouse.scaleY;this.listening.has("mousemove")&&this.relayInput("mousemove",{x:this.mouse.x,y:this.mouse.y})}))}mapCanvasPosition(t,e){var s,i,o,n,r,h,l,a,u,c,f,p,d,m,g,v;const b="top"in e,y="bottom"in e,w="left"in e,M="right"in e,x=e.anchor,j=t.getBoundingClientRect(),S=(t,...e)=>{const s=t?"Cannot include value for ":"Must include value for ",i=1==e.length?e[0]:e.slice(0,-1).join(", ")+(t?" and ":" or ")+e.slice(-1)[0],o=x?" if anchoring at "+x:" if not anchoring";console.error(s+i+o)},k=j.width/j.height,E=j.height/j.width;if((Number.isNaN(k)||Number.isNaN(E))&&console.error("Canvas element bounding box is flat, canvas must be present on the screen"),x){if("center"==x){if(b&&y&&e.top!==-e.bottom||w&&M&&e.left!==-e.right)return S(!0,"top","bottom","left","right");b?(e.left=w?e.left:M?-e.right:-Math.abs(k*e.top),e.right=w?-e.left:M?e.right:Math.abs(k*e.top),e.bottom=-e.top):y?(e.left=w?e.left:M?-e.right:-Math.abs(k*e.bottom),e.right=w?-e.left:M?e.right:Math.abs(k*e.bottom),e.top=-e.bottom):w?(e.top=b?e.top:y?-e.bottom:-Math.abs(E*e.left),e.bottom=b?-e.top:y?e.bottom:Math.abs(E*e.left),e.right=-e.left):M&&(e.top=b?e.top:y?-e.bottom:-Math.abs(E*e.right),e.bottom=b?-e.top:y?e.bottom:Math.abs(E*e.right),e.left=-e.right)}else if("bottom"==x){if(!w&&!M&&!b)return S(!1,"left","right","top");if(e.bottom)return S(!0,"bottom");e.bottom=0,w?(null!==(s=e.top)&&void 0!==s||(e.top=Math.abs(E*e.left*2)),null!==(i=e.right)&&void 0!==i||(e.right=-e.left)):M?(null!==(o=e.top)&&void 0!==o||(e.top=Math.abs(E*e.right*2)),null!==(n=e.left)&&void 0!==n||(e.left=-e.right)):(e.left=-Math.abs(k*e.top/2),e.right=-e.left)}else if("top"==x){if(!w&&!M&&!y)return S(!1,"left","right","bottom");if(e.top)return S(!0,"top");e.top=0,w?(null!==(r=e.bottom)&&void 0!==r||(e.bottom=Math.abs(E*e.left*2)),null!==(h=e.right)&&void 0!==h||(e.right=-e.left)):M?(null!==(l=e.bottom)&&void 0!==l||(e.bottom=Math.abs(E*e.right*2)),null!==(a=e.left)&&void 0!==a||(e.left=-e.right)):(e.left=-Math.abs(k*e.bottom/2),e.right=-e.left)}else if("left"==x){if(!b&&!y&&!M)return S(!1,"top","bottom","right");if(w)return S(!0,"left");e.left=0,b?(null!==(u=e.right)&&void 0!==u||(e.right=-Math.abs(k*e.top*2)),null!==(c=e.bottom)&&void 0!==c||(e.bottom=-e.top)):y?(null!==(f=e.right)&&void 0!==f||(e.right=Math.abs(k*e.bottom*2)),null!==(p=e.top)&&void 0!==p||(e.top=-e.bottom)):(e.top=-Math.abs(E*e.right/2),e.bottom=-e.top)}else if("right"==x){if(!b&&!y&&!w)return S(!1,"top","bottom","left");if(M)return S(!0,"right");e.right=0,b?(null!==(d=e.left)&&void 0!==d||(e.left=-Math.abs(k*e.top*2)),null!==(m=e.bottom)&&void 0!==m||(e.bottom=-e.top)):y?(null!==(g=e.left)&&void 0!==g||(e.left=Math.abs(k*e.bottom*2)),null!==(v=e.top)&&void 0!==v||(e.top=-e.bottom)):(e.top=-Math.abs(E*e.right/2),e.bottom=-e.top)}else if("topleft"==x){if(!M&&!y)return S(!1,"right","bottom");if(w||b)return S(!0,"left","top");e.left=e.top=0,M?e.bottom=Math.abs(E*e.right):e.right=Math.abs(k*e.bottom)}else if("topright"==x){if(!w&&!y)return S(!1,"left","bottom");if(M||b)return S(!0,"right","top");e.right=e.top=0,w?e.bottom=Math.abs(E*e.left):e.left=Math.abs(k*e.bottom)}else if("bottomleft"==x){if(!M&&!b)return S(!1,"right","top");if(y||w)return S(!0,"bottom","left");e.left=e.bottom=0,M?e.top=Math.abs(E*e.right):e.right=Math.abs(k*e.top)}else if("bottomright"==x){if(!b&&!w)return S(!1,"top","left");if(M||y)return S(!0,"bottom","right");e.right=e.bottom=0,w?e.top=Math.abs(E*e.left):e.left=Math.abs(k*e.top)}}else{if(!b&&!y)return S(!1,"top","bottom");if(y?b||(e.top=e.bottom-t.height):e.bottom=e.top+t.height,!w&&!M)return S(!1,"left","right");M?w||(e.left=e.right-t.width):e.right=e.left+t.width}const O=t.getContext("2d");O.setTransform(1,0,0,1,0,0),t.width=Math.floor(Math.abs(e.right-e.left)),t.height=Math.floor(Math.abs(e.bottom-e.top)),e.right<e.left&&O.scale(-1,1),e.top>e.bottom&&O.scale(1,-1),O.translate(-e.left,-e.top)}mapMousePosition(t,e,s=document.body,i=1,o=i){const n=window.innerWidth/(s instanceof HTMLCanvasElement?s.width:s.clientWidth),r=window.innerHeight/(s instanceof HTMLCanvasElement?s.height:s.clientHeight),h=s.getBoundingClientRect();this.mouse.centerX=h.left+t*n,this.mouse.centerY=h.top+e*r,this.mouse.scaleX=i*n,this.mouse.scaleY=o*r}mapMouseToCanvas(t){const e=t.getContext("2d").getTransform(),s=t.getBoundingClientRect(),i=s.width/t.width,o=s.height/t.height;this.mouse.centerX=s.left+e.e*i,this.mouse.centerY=s.top+e.f*o,this.mouse.scaleX=i*e.a,this.mouse.scaleY=o*e.d}setMouseAs(t){this.mouseGetter=t}relayInput(t,e){if(1!==this.ws.readyState)throw new Error("Websocket connection is "+(2==this.ws.readyState?"closing":"closed"));this.ws.send(i.Message.Native(Object.assign({instruction:"input",input:t},e?{data:e}:{})))}}},34:(t,e,s)=>{Object.defineProperty(e,"__esModule",{value:!0}),e.MultyxClientValue=e.MultyxClientObject=e.MultyxClientList=void 0;const i=s(70);e.MultyxClientList=i.default;const o=s(614);e.MultyxClientObject=o.default;const n=s(501);e.MultyxClientValue=n.default},70:(t,e,s)=>{var i;Object.defineProperty(e,"__esModule",{value:!0});const o=s(787),n=s(614);class r extends n.default{get value(){const t=[];for(let e=0;e<this.length;e++)t[e]=this.get(e).value;return t}constructor(t,e,s=[],n){return super(t,{},s,n),this.toString=()=>this.value.toString(),this.valueOf=()=>this.value,this[i]=()=>this.value,this.length=0,this.push(...e instanceof o.EditWrapper?e.value.map((t=>new o.EditWrapper(t))):e),new Proxy(this,{has:(t,e)=>e in t||t.has(e),get:(t,e)=>e in t?t[e]:t.get(e),set:(t,e,s)=>e in t?(t[e]=s,!0):t.set(e,s),deleteProperty:(t,e)=>t.delete(e,!1)})}set(t,e){if("string"==typeof t&&(t=parseInt(t)),void 0===e)return this.delete(t,!1);if(e instanceof o.EditWrapper&&void 0===e.value)return this.delete(t,!0);const s=super.set(t,e);return s&&t>=this.length&&(this.length=t+1),s}delete(t,e=!1){"string"==typeof t&&(t=parseInt(t));const s=super.delete(t,e);return s&&(this.length=this.reduce(((t,e,s)=>void 0!==e?s+1:t),0)),s}forAll(t){for(let e=0;e<this.length;e++)t(this.get(e),e);super.forAll(((e,s)=>t(s,e)))}push(...t){for(const e of t)this.set(this.length,e);return this.length}pop(){if(0===this.length)return null;const t=this.get(this.length);return this.delete(this.length),t}unshift(...t){for(let e=this.length-1;e>=0;e--)e>=t.length?this.set(e,this.get(e-t.length)):this.set(e,t[e]);return this.length}shift(){if(0==this.length)return;this.length--;const t=this.get(0);for(let t=0;t<this.length;t++)this.set(t,this.get(t+1));return t}splice(t,e,...s){void 0===e&&(e=this.length-t);let i=s.length-e;if(i>0)for(let s=this.length-1;s>=t+e;s--)this.set(s+i,this.get(s));else if(i<0){for(let s=t+e;s<this.length;s++)this.set(s+i,this.get(s));const s=this.length;for(let t=s+i;t<s;t++)this.set(t,void 0)}for(let e=t;e<s.length;e++)this.set(e,s[e])}filter(t){const e=[];for(let s=0;s<this.length;s++)e.push(t(this.get(s),s,this));let s=0;for(let t=0;t<e.length;t++)e[t]&&s&&this.set(t-s,this.get(t)),e[t]||s--}map(t){for(let e=0;e<this.length;e++)this.set(e,t(this.get(e),e,this))}flat(){for(let t=0;t<this.length;t++){const e=this.get(t);if(e instanceof r)for(let s=0;s<e.length;s++)t++,this.set(t,e[s])}}reduce(t,e){for(let s=0;s<this.length;s++)e=t(e,this.get(s),s,this);return e}reduceRight(t,e){for(let s=this.length-1;s>=0;s--)e=t(e,this.get(s),s,this);return e}reverse(){let t=this.length-1;for(let e=0;e<t;e++){const s=this.get(e),i=this.get(t);this.set(e,i),this.set(t,s)}return this}forEach(t){for(let e=0;e<this.length;e++)t(this.get(e),e,this)}every(t){for(let e=0;e<this.length;e++)if(!t(this.get(e),e,this))return!1;return!0}some(t){for(let e=0;e<this.length;e++)if(t(this.get(e),e,this))return!0;return!1}find(t){for(let e=0;e<this.length;e++)if(t(this.get(e),e,this))return this.get(e)}findIndex(t){for(let e=0;e<this.length;e++)if(t(this.get(e),e,this))return e;return-1}deorder(){const t=[];for(const e in this.object)t.push(this.get(e));return t}deorderEntries(){const t=[];for(const e in this.object)t.push([parseInt(e),this.get(e)]);return t}entries(){const t=[];for(let e=0;e<this.length;e++)t.push([this.get(e),e]);return t}keys(){return Array(this.length).fill(0).map(((t,e)=>e))}[Symbol.iterator](){const t=[];for(let e=0;e<this.length;e++)t[e]=this.get(e);return t[Symbol.iterator]()}}i=Symbol.toPrimitive,e.default=r},614:(t,e,s)=>{Object.defineProperty(e,"__esModule",{value:!0});const i=s(210),o=s(787),n=s(735),r=s(501);class h{get value(){const t={};for(const e in this.object)t[e]=this.object[e];return t}constructor(t,e,s=[],i){this.object={},this.propertyPath=s,this.multyx=t,this.editable=i,this.setterListeners=[],e instanceof h&&(e=e.value);for(const t in e instanceof o.EditWrapper?e.value:e)this.set(t,e instanceof o.EditWrapper?new o.EditWrapper(e.value[t]):e[t]);if(this.constructor===h)return new Proxy(this,{has:(t,e)=>t.has(e),get:(t,e)=>e in t?t[e]:t.get(e),set:(t,e,s)=>e in t?(t[e]=s,!0):t.set(e,s),deleteProperty:(t,e)=>t.delete(e,!1)})}has(t){return t in this.object}get(t){return this.object[t]}set(t,e){if(void 0===e)return this.delete(t);if(this.object[t]instanceof r.default)return this.object[t].set(e);if(e instanceof o.EditWrapper&&void 0===e.value)return this.delete(t,!0);if(!(e instanceof o.EditWrapper||this.editable))return this.multyx.options.verbose&&console.error(`Attempting to set property that is not editable. Setting '${this.propertyPath.join(".")+"."+t}' to ${e}`),!1;this.object[t]=new((0,n.default)(e instanceof o.EditWrapper?e.value:e))(this.multyx,e,[...this.propertyPath,t],this.editable);for(const e of this.setterListeners)this.multyx[o.Add]((()=>{this.has(t)&&e(t,this.get(t))}));return e instanceof o.EditWrapper||this.multyx.ws.send(i.Message.Native({instruction:"edit",path:this.propertyPath,value:this.object[t].value})),!0}delete(t,e=!1){return this.editable||e?(delete this.object[t],e||this.multyx.ws.send(i.Message.Native({instruction:"edit",path:[...this.propertyPath,t],value:void 0})),!0):(this.multyx.options.verbose&&console.error(`Attempting to delete property that is not editable. Deleting '${this.propertyPath.join(".")+"."+t}'`),!1)}forAll(t){for(let e in this.object)t(e,this.get(e));this.setterListeners.push(t)}keys(){return Object.keys(this.object)}values(){return Object.values(this.object)}entries(){const t=[];for(let e in this.object)t.push([e,this.get(e)]);return t}[o.Unpack](t){for(const e in t)this.object[e][o.Unpack](t[e])}}e.default=h},735:(t,e,s)=>{Object.defineProperty(e,"__esModule",{value:!0}),e.default=function(t){return Array.isArray(t)?s(70).default:"object"==typeof t?s(614).default:s(501).default}},501:(t,e,s)=>{var i;Object.defineProperty(e,"__esModule",{value:!0});const o=s(210),n=s(787);class r{get value(){return this.interpolator?this.interpolator.get():this._value}set value(t){this._value=t,this.interpolator&&this.interpolator.set()}constructor(t,e,s=[],o){this.toString=()=>this.value.toString(),this.valueOf=()=>this.value,this[i]=()=>this.value,this.propertyPath=s,this.editable=o,this.multyx=t,this.constraints={},this.set(e)}set(t){if(t instanceof n.EditWrapper)return this.value=t.value,!0;if(!this.editable)return this.multyx.options.verbose&&console.error(`Attempting to set property that is not editable. Setting '${this.propertyPath.join(".")}' to ${t}`),!1;let e=t;for(const s in this.constraints)if(e=(0,this.constraints[s])(e),null===e)return this.multyx.options.verbose&&console.error(`Attempting to set property that failed on constraint. Setting '${this.propertyPath.join(".")}' to ${t}, stopped by constraint '${s}'`),!1;return this.value===e?(this.value=e,!0):(this.value=e,this.multyx.ws.send(o.Message.Native({instruction:"edit",path:this.propertyPath,value:e})),!0)}[n.Unpack](t){for(const[e,s]of Object.entries(t)){const t=(0,n.BuildConstraint)(e,s);t&&(this.constraints[e]=t)}}Lerp(){this.interpolator={history:[{value:this._value,time:Date.now()},{value:this._value,time:Date.now()}],get:()=>{const[t,e]=this.interpolator.history,s=Math.min(1,(Date.now()-t.time)/Math.min(250,t.time-e.time));return Number.isNaN(s)||"number"!=typeof t.value||"number"!=typeof e.value?t.value:t.value*s+e.value*(1-s)},set:()=>{this.interpolator.history.pop(),this.interpolator.history.unshift({value:this._value,time:Date.now()})}}}PredictiveLerp(){this.interpolator={history:[{value:this._value,time:Date.now()},{value:this._value,time:Date.now()},{value:this._value,time:Date.now()}],get:()=>{const[t,e,s]=this.interpolator.history,i=Math.min(1,(Date.now()-t.time)/(t.time-e.time));return Number.isNaN(i)||"number"!=typeof s.value||"number"!=typeof t.value||"number"!=typeof e.value||Math.abs((t.value-e.value)/(e.value-s.value)-1)>.2?t.value:t.value*(1+i)-e.value*i},set:()=>{this.interpolator.history.pop(),this.interpolator.history.unshift({value:this._value,time:Date.now()})}}}}i=Symbol.toPrimitive,e.default=r},210:(t,e)=>{Object.defineProperty(e,"__esModule",{value:!0}),e.Message=void 0;class s{constructor(t,e,s=!1){this.name=t,this.data=e,this.time=Date.now(),this.native=s}static BundleOperations(t,e){return Array.isArray(e)||(e=[e]),JSON.stringify(new s("_",{operations:e,deltaTime:t}))}static Native(t){return JSON.stringify(new s("_",t,!0))}static Parse(t){const e=JSON.parse(t);return"_"==e.name[0]&&(e.name=e.name.slice(1)),new s(e.name,e.data,""==e.name)}static Create(t,e){if(0==t.length)throw new Error("Multyx message cannot have empty name");if("_"==t[0]&&(t="_"+t),"function"==typeof e)throw new Error("Multyx data must be JSON storable");return JSON.stringify(new s(t,e))}}e.Message=s},944:(t,e)=>{Object.defineProperty(e,"__esModule",{value:!0}),e.DefaultOptions=void 0,e.DefaultOptions={port:443,secure:!1,uri:"localhost",verbose:!1,logUpdateFrame:!1}},787:(t,e)=>{Object.defineProperty(e,"__esModule",{value:!0}),e.EditWrapper=e.Add=e.Done=e.Unpack=void 0,e.Interpolate=function(t,e,s){let i={value:t[e],time:Date.now()},o={value:t[e],time:Date.now()};Object.defineProperty(t,e,{get:()=>{const t=o.time-i.time;let e=s[0],n=s[0];for(const i of s)t>i.time&&i.time>e.time&&(e=i),t<i.time&&i.time<n.time&&(n=i);const r=(t-e.time)/(n.time-e.time),h=e.progress+r*(n.progress-e.progress);return Number.isNaN(h)?i.value:o.value*h+i.value*(1-h)},set:t=>Date.now()-o.time<10?(o.value=t,!0):(i=Object.assign({},o),o={value:t,time:Date.now()},!0)})},e.BuildConstraint=function(t,e){return"min"==t?t=>t>=e[0]?t:e[0]:"max"==t?t=>t<=e[0]?t:e[0]:"int"==t?t=>Math.floor(t):"ban"==t?t=>e.includes(t)?null:t:"disabled"==t?t=>e[0]?null:t:t=>t},e.Unpack=Symbol("unpack"),e.Done=Symbol("done"),e.Add=Symbol("add"),e.EditWrapper=class{constructor(t){this.value=t}}}},e={};function s(i){var o=e[i];if(void 0!==o)return o.exports;var n=e[i]={exports:{}};return t[i](n,n.exports,s),n.exports}var i={};return(()=>{var t=i;const e=s(210),o=s(787),n=s(376),r=s(34),h=s(944);class l{constructor(t={},s){this.options=Object.assign(Object.assign({},h.DefaultOptions),t);const i=`ws${this.options.secure?"s":""}://${this.options.uri}:${this.options.port}/`;this.ws=new WebSocket(i),this.ping=0,this.events=new Map,this.self={},this.all={},this.teams={},this.clients={},this.controller=new n.Controller(this.ws),this.listenerQueue=[],null==s||s(),this.ws.onmessage=t=>{var s,i,o;const n=e.Message.Parse(t.data);this.ping=2*(Date.now()-n.time),n.native?(this.parseNativeEvent(n),null===(s=this.events.get(l.Native))||void 0===s||s.forEach((t=>t(n)))):n.name in this.events&&(this.events[n.name](n.data),null===(i=this.events.get(l.Custom))||void 0===i||i.forEach((t=>t(n)))),null===(o=this.events.get(l.Any))||void 0===o||o.forEach((t=>t(n)))}}on(t,e){var s;const i=null!==(s=this.events.get(t))&&void 0!==s?s:[];i.push(e),this.events.set(t,i)}send(t,s,i=!1){if("_"===t[0]&&(t="_"+t),this.ws.send(e.Message.Create(t,s)),i)return new Promise((e=>this.events.set(Symbol.for("_"+t),[e])))}loop(t,e){if(e)this.on(l.Start,(()=>setInterval(t,Math.round(1e3/e))));else{const e=()=>{t(),requestAnimationFrame(e)};this.on(l.Start,(()=>requestAnimationFrame(e)))}}forAll(t){this.on(l.Start,(()=>{this.teams.all.clients.forAll((e=>t(this.clients[e])))})),this.on(l.Connection,t)}parseNativeEvent(t){var e,s,i,o;this.options.logUpdateFrame&&console.log(t);for(const n of t.data)switch(n.instruction){case"init":this.initialize(n);for(const t of null!==(e=this.events.get(l.Start))&&void 0!==e?e:[])this.listenerQueue.push((()=>t(n)));this.events.has(l.Start)&&(this.events.get(l.Start).length=0);break;case"edit":this.parseEdit(n);for(const t of null!==(s=this.events.get(l.Edit))&&void 0!==s?s:[])this.listenerQueue.push((()=>t(n)));break;case"self":this.parseSelf(n);break;case"conn":this.clients[n.uuid]=new r.MultyxClientObject(this,n.data,[n.uuid],!1);for(const t of null!==(i=this.events.get(l.Connection))&&void 0!==i?i:[])this.listenerQueue.push((()=>t(this.clients[n.uuid])));break;case"dcon":for(const t of null!==(o=this.events.get(l.Disconnect))&&void 0!==o?o:[]){const e=this.clients[n.client].value;this.listenerQueue.push((()=>t(e)))}delete this.clients[n.client];break;case"resp":(0,this.events.get(Symbol.for("_"+n.name))[0])(n.response);break;default:this.options.verbose&&console.error("Server error: Unknown native Multyx instruction")}this.listenerQueue.forEach((t=>t())),this.listenerQueue.length=0}initialize(t){this.uuid=t.client.uuid,this.joinTime=t.client.joinTime,this.controller.listening=new Set(t.client.controller),this.teams=new r.MultyxClientObject(this,{},[],!0);for(const e of Object.keys(t.teams))this.teams[e]=new o.EditWrapper(t.teams[e]);this.all=this.teams.all,this.clients={};for(const[e,s]of Object.entries(t.clients))e!=this.uuid&&(this.clients[e]=new r.MultyxClientObject(this,new o.EditWrapper(s),[e],!1));const e=new r.MultyxClientObject(this,new o.EditWrapper(t.client.self),[this.uuid],!0);this.self=e,this.clients[this.uuid]=e;for(const[e,s]of Object.entries(t.constraintTable))(this.uuid==e?this.self:this.teams[e])[o.Unpack](s)}parseEdit(t){let e=t.team?this.teams:this.clients;if(e){for(const s of t.path.slice(0,-1))s in e||(e[s]=new o.EditWrapper({})),e=e[s];e[t.path.slice(-1)[0]]=new o.EditWrapper(t.value)}}parseSelf(t){if("controller"==t.prop)this.controller.listening=new Set(t.data);else if("uuid"==t.prop)this.uuid=t.data;else if("constraint"==t.prop){let e=this.uuid==t.data.path[0]?this.self:this.teams[t.data.path[0]];for(const s of t.data.path.slice(1))e=null==e?void 0:e[s];if(void 0===e)return;e[o.Unpack]({[t.data.name]:t.data.args})}}[o.Add](t){this.listenerQueue.push(t)}}l.Start=Symbol("start"),l.Connection=Symbol("connection"),l.Disconnect=Symbol("disconnect"),l.Edit=Symbol("edit"),l.Native=Symbol("native"),l.Custom=Symbol("custom"),l.Any=Symbol("any"),t.default=l})(),i.default})()));
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "multyx-client",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Framework designed to simplify the creation of multiplayer browser games by addressing the complexities of managing server-client communication, shared state, and input handling",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"webpack": "tsc && npx webpack"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/seanlnge/multyx.git"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"multiplayer",
|
|
17
|
+
"javascript",
|
|
18
|
+
"websocket",
|
|
19
|
+
"server",
|
|
20
|
+
"browser-game",
|
|
21
|
+
"typescript"
|
|
22
|
+
],
|
|
23
|
+
"author": "Sean Lange",
|
|
24
|
+
"license": "ISC",
|
|
25
|
+
"types": "dist/index.d.ts",
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/seanlnge/multyx/issues"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://github.com/seanlnge/multyx#readme",
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"webpack": "^5.88.2",
|
|
32
|
+
"webpack-cli": "^5.1.4"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import { Message } from "./message";
|
|
2
|
+
import { RawObject } from "./types";
|
|
3
|
+
|
|
4
|
+
export class Controller {
|
|
5
|
+
private mouseGetter: () => { x: number, y: number };
|
|
6
|
+
listening: Set<string>;
|
|
7
|
+
ws: WebSocket;
|
|
8
|
+
|
|
9
|
+
preventDefault: boolean;
|
|
10
|
+
|
|
11
|
+
keys: RawObject<boolean>;
|
|
12
|
+
mouse: {
|
|
13
|
+
x: number, y: number, down: boolean, // Mouse state
|
|
14
|
+
centerX: number, centerY: number, // Translation in reference to top left of document body, scaled by unit pixels
|
|
15
|
+
scaleX: number, scaleY: number // Scaling in reference to unit pixels
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
constructor(ws: WebSocket) {
|
|
19
|
+
this.listening = new Set();
|
|
20
|
+
this.ws = ws;
|
|
21
|
+
this.preventDefault = false;
|
|
22
|
+
|
|
23
|
+
this.keys = {};
|
|
24
|
+
this.mouse = {
|
|
25
|
+
x: NaN,
|
|
26
|
+
y: NaN,
|
|
27
|
+
down: false,
|
|
28
|
+
centerX: 0,
|
|
29
|
+
centerY: 0,
|
|
30
|
+
scaleX: 1,
|
|
31
|
+
scaleY: 1
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
document.addEventListener('keydown', e => {
|
|
35
|
+
if(this.preventDefault) e.preventDefault;
|
|
36
|
+
|
|
37
|
+
const key = e.key.toLowerCase();
|
|
38
|
+
|
|
39
|
+
// When holding down key
|
|
40
|
+
if(this.keys[key] && this.listening.has('keyhold')) {
|
|
41
|
+
this.relayInput('keyhold', { code: key });
|
|
42
|
+
}
|
|
43
|
+
if(this.keys[e.code] && this.listening.has('keyhold')) {
|
|
44
|
+
this.relayInput('keyhold', { code: e.code });
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Change in key state
|
|
48
|
+
if(this.listening.has(key) && !this.keys[key]) {
|
|
49
|
+
this.relayInput('keydown', { code: e.key });
|
|
50
|
+
}
|
|
51
|
+
if(this.listening.has(e.code) && !this.keys[e.code]) {
|
|
52
|
+
this.relayInput('keydown', { code: e.code });
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
this.keys[key] = true;
|
|
56
|
+
this.keys[e.code] = true;
|
|
57
|
+
|
|
58
|
+
});
|
|
59
|
+
document.addEventListener('keyup', e => {
|
|
60
|
+
if(this.preventDefault) e.preventDefault;
|
|
61
|
+
|
|
62
|
+
const key = e.key.toLowerCase();
|
|
63
|
+
|
|
64
|
+
delete this.keys[key];
|
|
65
|
+
delete this.keys[e.code];
|
|
66
|
+
if(this.listening.has(key)) this.relayInput('keyup', { code: key });
|
|
67
|
+
if(this.listening.has(e.code)) this.relayInput('keyup', { code: e.code });
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Mouse input events
|
|
71
|
+
document.addEventListener('mousedown', e => {
|
|
72
|
+
if(this.preventDefault) e.preventDefault;
|
|
73
|
+
|
|
74
|
+
if(this.mouseGetter) {
|
|
75
|
+
const mouse = this.mouseGetter();
|
|
76
|
+
this.mouse.x = mouse.x;
|
|
77
|
+
this.mouse.y = mouse.y;
|
|
78
|
+
} else {
|
|
79
|
+
this.mouse.x = (e.clientX - this.mouse.centerX) / this.mouse.scaleX;
|
|
80
|
+
this.mouse.y = (e.clientY - this.mouse.centerY) / this.mouse.scaleY;
|
|
81
|
+
}
|
|
82
|
+
this.mouse.down = true;
|
|
83
|
+
if(this.listening.has('mousedown'))
|
|
84
|
+
this.relayInput('mousedown', {
|
|
85
|
+
x: this.mouse.x, y: this.mouse.y
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
document.addEventListener('mouseup', e => {
|
|
89
|
+
if(this.preventDefault) e.preventDefault;
|
|
90
|
+
|
|
91
|
+
if(this.mouseGetter) {
|
|
92
|
+
const mouse = this.mouseGetter();
|
|
93
|
+
this.mouse.x = mouse.x;
|
|
94
|
+
this.mouse.y = mouse.y;
|
|
95
|
+
} else {
|
|
96
|
+
this.mouse.x = (e.clientX - this.mouse.centerX) / this.mouse.scaleX;
|
|
97
|
+
this.mouse.y = (e.clientY - this.mouse.centerY) / this.mouse.scaleY;
|
|
98
|
+
}
|
|
99
|
+
this.mouse.down = false;
|
|
100
|
+
if(this.listening.has('mouseup'))
|
|
101
|
+
this.relayInput('mouseup', {
|
|
102
|
+
x: this.mouse.x, y: this.mouse.y
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
document.addEventListener('mousemove', e => {
|
|
106
|
+
if(this.preventDefault) e.preventDefault;
|
|
107
|
+
|
|
108
|
+
if(this.mouseGetter) {
|
|
109
|
+
const mouse = this.mouseGetter();
|
|
110
|
+
this.mouse.x = mouse.x;
|
|
111
|
+
this.mouse.y = mouse.y;
|
|
112
|
+
} else {
|
|
113
|
+
this.mouse.x = (e.clientX - this.mouse.centerX) / this.mouse.scaleX;
|
|
114
|
+
this.mouse.y = (e.clientY - this.mouse.centerY) / this.mouse.scaleY;
|
|
115
|
+
}
|
|
116
|
+
if(this.listening.has('mousemove'))
|
|
117
|
+
this.relayInput('mousemove', {
|
|
118
|
+
x: this.mouse.x, y: this.mouse.y
|
|
119
|
+
});
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Map the canvas to specified top left and bottom right positions
|
|
125
|
+
* @param canvas HTML canvas element
|
|
126
|
+
* @param canvasContext 2D rendering context for canvas
|
|
127
|
+
* @param top Canvas position to correspond to top of canvas
|
|
128
|
+
* @param left Canvas position to correspond to left of canvas
|
|
129
|
+
* @param bottom Canvas position to correspond to bottom of canvas
|
|
130
|
+
* @param right Canvas position to correspond to right of canvas
|
|
131
|
+
* @param anchor Anchor the origin at a specific spot on the canvas
|
|
132
|
+
*/
|
|
133
|
+
mapCanvasPosition(canvas: HTMLCanvasElement, position: {
|
|
134
|
+
top?: number, bottom?: number, left?: number, right?: number,
|
|
135
|
+
anchor?: 'center' | 'left' | 'right' | 'top' | 'bottom' | 'topleft' | 'topright' | 'bottomleft' | 'bottomright'
|
|
136
|
+
}) {
|
|
137
|
+
const t = 'top' in position;
|
|
138
|
+
const b = 'bottom' in position;
|
|
139
|
+
const l = 'left' in position;
|
|
140
|
+
const r = 'right' in position;
|
|
141
|
+
const a = position.anchor;
|
|
142
|
+
|
|
143
|
+
const bounding = canvas.getBoundingClientRect();
|
|
144
|
+
|
|
145
|
+
const error = (included: boolean, ...pieces: string[]) => {
|
|
146
|
+
const p1 = included ? "Cannot include value for " : "Must include value for ";
|
|
147
|
+
const p2 = pieces.length == 1 ? pieces[0] : pieces.slice(0, -1).join(', ') + (included ? ' and ' : ' or ') + pieces.slice(-1)[0];
|
|
148
|
+
const p3 = a ? " if anchoring at " + a : " if not anchoring";
|
|
149
|
+
console.error(p1 + p2 + p3);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const wToH = bounding.width / bounding.height;
|
|
153
|
+
const hToW = bounding.height / bounding.width;
|
|
154
|
+
|
|
155
|
+
if(Number.isNaN(wToH) || Number.isNaN(hToW)) {
|
|
156
|
+
console.error("Canvas element bounding box is flat, canvas must be present on the screen");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// mb bruh jus trust it works
|
|
160
|
+
if(!a) {
|
|
161
|
+
if(!t && !b) return error(false, 'top', 'bottom');
|
|
162
|
+
else if(!b) position.bottom = position.top + canvas.height;
|
|
163
|
+
else if(!t) position.top = position.bottom - canvas.height;
|
|
164
|
+
|
|
165
|
+
if(!l && !r) return error(false, 'left', 'right');
|
|
166
|
+
else if(!r) position.right = position.left + canvas.width;
|
|
167
|
+
else if(!l) position.left = position.right - canvas.width;
|
|
168
|
+
} else if(a == 'center') {
|
|
169
|
+
if(t && b && position.top !== -position.bottom
|
|
170
|
+
|| l && r && position.left !== -position.right) return error(true, 'top', 'bottom', 'left', 'right');
|
|
171
|
+
|
|
172
|
+
if(t) {
|
|
173
|
+
position.left = l ? position.left : r ? -position.right : -Math.abs(wToH * position.top);
|
|
174
|
+
position.right = l ? -position.left : r ? position.right : Math.abs(wToH * position.top);
|
|
175
|
+
position.bottom = -position.top;
|
|
176
|
+
} else if(b) {
|
|
177
|
+
position.left = l ? position.left : r ? -position.right : -Math.abs(wToH * position.bottom);
|
|
178
|
+
position.right = l ? -position.left : r ? position.right : Math.abs(wToH * position.bottom);
|
|
179
|
+
position.top = -position.bottom;
|
|
180
|
+
} else if(l) {
|
|
181
|
+
position.top = t ? position.top : b ? -position.bottom : -Math.abs(hToW * position.left);
|
|
182
|
+
position.bottom = t ? -position.top : b ? position.bottom : Math.abs(hToW * position.left);
|
|
183
|
+
position.right = -position.left;
|
|
184
|
+
} else if(r) {
|
|
185
|
+
position.top = t ? position.top : b ? -position.bottom : -Math.abs(hToW * position.right);
|
|
186
|
+
position.bottom = t ? -position.top : b ? position.bottom : Math.abs(hToW * position.right);
|
|
187
|
+
position.left = -position.right;
|
|
188
|
+
}
|
|
189
|
+
} else if(a == 'bottom') {
|
|
190
|
+
if(!l && !r && !t) return error(false, 'left', 'right', 'top');
|
|
191
|
+
if(position.bottom) return error(true, 'bottom');
|
|
192
|
+
position.bottom = 0;
|
|
193
|
+
|
|
194
|
+
if(l) {
|
|
195
|
+
position.top ??= Math.abs(hToW * position.left * 2);
|
|
196
|
+
position.right ??= -position.left;
|
|
197
|
+
} else if(r) {
|
|
198
|
+
position.top ??= Math.abs(hToW * position.right * 2);
|
|
199
|
+
position.left ??= -position.right;
|
|
200
|
+
} else {
|
|
201
|
+
position.left = -Math.abs(wToH * position.top / 2);
|
|
202
|
+
position.right = -position.left;
|
|
203
|
+
}
|
|
204
|
+
} else if(a == 'top') {
|
|
205
|
+
if(!l && !r && !b) return error(false, 'left', 'right', 'bottom');
|
|
206
|
+
if(position.top) return error(true, 'top');
|
|
207
|
+
position.top = 0;
|
|
208
|
+
|
|
209
|
+
if(l) {
|
|
210
|
+
position.bottom ??= Math.abs(hToW * position.left * 2);
|
|
211
|
+
position.right ??= -position.left;
|
|
212
|
+
} else if(r) {
|
|
213
|
+
position.bottom ??= Math.abs(hToW * position.right * 2);
|
|
214
|
+
position.left ??= -position.right;
|
|
215
|
+
} else {
|
|
216
|
+
position.left = -Math.abs(wToH * position.bottom / 2);
|
|
217
|
+
position.right = -position.left;
|
|
218
|
+
}
|
|
219
|
+
} else if(a == 'left') {
|
|
220
|
+
if(!t && !b && !r) return error(false, 'top', 'bottom', 'right');
|
|
221
|
+
if(l) return error(true, 'left');
|
|
222
|
+
position.left = 0;
|
|
223
|
+
|
|
224
|
+
if(t) {
|
|
225
|
+
position.right ??= -Math.abs(wToH * position.top * 2);
|
|
226
|
+
position.bottom ??= -position.top;
|
|
227
|
+
} else if(b) {
|
|
228
|
+
position.right ??= Math.abs(wToH * position.bottom * 2);
|
|
229
|
+
position.top ??= -position.bottom;
|
|
230
|
+
} else {
|
|
231
|
+
position.top = -Math.abs(hToW * position.right / 2);
|
|
232
|
+
position.bottom = -position.top;
|
|
233
|
+
}
|
|
234
|
+
} else if(a == 'right') {
|
|
235
|
+
if(!t && !b && !l) return error(false, 'top', 'bottom', 'left');
|
|
236
|
+
if(r) return error(true, 'right');
|
|
237
|
+
position.right = 0;
|
|
238
|
+
|
|
239
|
+
if(t) {
|
|
240
|
+
position.left ??= -Math.abs(wToH * position.top * 2);
|
|
241
|
+
position.bottom ??= -position.top;
|
|
242
|
+
} else if(b) {
|
|
243
|
+
position.left ??= Math.abs(wToH * position.bottom * 2);
|
|
244
|
+
position.top ??= -position.bottom;
|
|
245
|
+
} else {
|
|
246
|
+
position.top = -Math.abs(hToW * position.right / 2);
|
|
247
|
+
position.bottom = -position.top;
|
|
248
|
+
}
|
|
249
|
+
} else if(a == 'topleft') {
|
|
250
|
+
if(!r && !b) return error(false, 'right', 'bottom');
|
|
251
|
+
if(l || t) return error(true, 'left', 'top');
|
|
252
|
+
position.left = position.top = 0;
|
|
253
|
+
|
|
254
|
+
if(r) position.bottom = Math.abs(hToW * position.right);
|
|
255
|
+
else position.right = Math.abs(wToH * position.bottom);
|
|
256
|
+
} else if(a == 'topright') {
|
|
257
|
+
if(!l && !b) return error(false, 'left', 'bottom');
|
|
258
|
+
if(r || t) return error(true, 'right', 'top');
|
|
259
|
+
position.right = position.top = 0;
|
|
260
|
+
|
|
261
|
+
if(l) position.bottom = Math.abs(hToW * position.left);
|
|
262
|
+
else position.left = Math.abs(wToH * position.bottom);
|
|
263
|
+
} else if(a == 'bottomleft') {
|
|
264
|
+
if(!r && !t) return error(false, 'right', 'top');
|
|
265
|
+
if(b || l) return error(true, 'bottom', 'left');
|
|
266
|
+
position.left = position.bottom = 0;
|
|
267
|
+
|
|
268
|
+
if(r) position.top = Math.abs(hToW * position.right);
|
|
269
|
+
else position.right = Math.abs(wToH * position.top);
|
|
270
|
+
} else if(a == 'bottomright') {
|
|
271
|
+
if(!t && !l) return error(false, 'top', 'left');
|
|
272
|
+
if(r || b) return error(true, 'bottom', 'right');
|
|
273
|
+
position.right = position.bottom = 0;
|
|
274
|
+
|
|
275
|
+
if(l) position.top = Math.abs(hToW * position.left);
|
|
276
|
+
else position.left = Math.abs(wToH * position.top);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const ctx = canvas.getContext("2d");
|
|
280
|
+
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
281
|
+
|
|
282
|
+
canvas.width = Math.floor(Math.abs(position.right-position.left));
|
|
283
|
+
canvas.height = Math.floor(Math.abs(position.bottom-position.top));
|
|
284
|
+
if(position.right < position.left) ctx.scale(-1, 1);
|
|
285
|
+
if(position.top > position.bottom) ctx.scale(1, -1);
|
|
286
|
+
|
|
287
|
+
ctx.translate(-position.left, -position.top);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* @param centerX Anchor x-value corresponding to mouse position x-value of 0
|
|
292
|
+
* @param centerY Anchor y-value corresponding to mouse position y-value of 0
|
|
293
|
+
* @param anchor HTML Element to read mouse position relative to
|
|
294
|
+
* @param scaleX Number of anchor pixels corresponding to a mouse position x-value change of 1
|
|
295
|
+
* @param scaleY Number of anchor pixels corresponding to a mouse position y-value change of 1
|
|
296
|
+
*/
|
|
297
|
+
mapMousePosition(centerX: number, centerY: number, anchor: HTMLElement = document.body, scaleX: number = 1, scaleY: number = scaleX) {
|
|
298
|
+
const ratioX = window.innerWidth / (anchor instanceof HTMLCanvasElement
|
|
299
|
+
? anchor.width
|
|
300
|
+
: anchor.clientWidth
|
|
301
|
+
);
|
|
302
|
+
const ratioY = window.innerHeight / (anchor instanceof HTMLCanvasElement
|
|
303
|
+
? anchor.height
|
|
304
|
+
: anchor.clientHeight
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
const bounding = anchor.getBoundingClientRect();
|
|
308
|
+
this.mouse.centerX = bounding.left + centerX * ratioX;
|
|
309
|
+
this.mouse.centerY = bounding.top + centerY * ratioY;
|
|
310
|
+
this.mouse.scaleX = scaleX * ratioX;
|
|
311
|
+
this.mouse.scaleY = scaleY * ratioY;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Map mouse position to the corresponding canvas coordinates on screen
|
|
316
|
+
* @param canvas Canvas element in DOM
|
|
317
|
+
*/
|
|
318
|
+
mapMouseToCanvas(canvas: HTMLCanvasElement) {
|
|
319
|
+
const ctx = canvas.getContext("2d");
|
|
320
|
+
const transform = ctx.getTransform();
|
|
321
|
+
const bounding = canvas.getBoundingClientRect();
|
|
322
|
+
|
|
323
|
+
// Ratio between canvas scale to unit pixels
|
|
324
|
+
const canvasRatioX = bounding.width / canvas.width;
|
|
325
|
+
const canvasRatioY = bounding.height / canvas.height;
|
|
326
|
+
|
|
327
|
+
this.mouse.centerX = bounding.left + transform.e * canvasRatioX;
|
|
328
|
+
this.mouse.centerY = bounding.top + transform.f * canvasRatioY;
|
|
329
|
+
|
|
330
|
+
this.mouse.scaleX = canvasRatioX * transform.a;
|
|
331
|
+
this.mouse.scaleY = canvasRatioY * transform.d;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Utilize mouse coordinates of another object
|
|
336
|
+
* @param mouseGetter Callback that returns the mouse coordinates at any given time
|
|
337
|
+
*/
|
|
338
|
+
setMouseAs(mouseGetter: () => { x: number, y: number }) {
|
|
339
|
+
this.mouseGetter = mouseGetter;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
private relayInput(input: string, data?: RawObject) {
|
|
343
|
+
if(this.ws.readyState !== 1) {
|
|
344
|
+
throw new Error('Websocket connection is ' + (this.ws.readyState == 2 ? 'closing' : 'closed'));
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
this.ws.send(Message.Native({
|
|
348
|
+
instruction: 'input',
|
|
349
|
+
input: input,
|
|
350
|
+
...(data ? { data } : {})
|
|
351
|
+
}));
|
|
352
|
+
}
|
|
353
|
+
}
|