multyx-client 0.1.0 → 0.1.1
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/README.md +1611 -0
- package/dist/controller.d.ts +57 -0
- package/dist/index.d.ts +49 -0
- package/dist/items/index.d.ts +5 -0
- package/dist/items/list.d.ts +40 -0
- package/dist/items/object.d.ts +30 -0
- package/dist/items/router.d.ts +1 -0
- package/dist/items/value.d.ts +31 -0
- package/dist/message.d.ts +12 -0
- package/dist/options.d.ts +8 -0
- package/dist/options.js +1 -1
- package/dist/types.d.ts +16 -0
- package/dist/utils.d.ts +28 -0
- package/multyx.js +1 -1
- package/package.json +1 -1
- package/src/options.ts +1 -1
- package/tsconfig.json +1 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { RawObject } from "./types";
|
|
2
|
+
export declare class Controller {
|
|
3
|
+
private mouseGetter;
|
|
4
|
+
listening: Set<string>;
|
|
5
|
+
ws: WebSocket;
|
|
6
|
+
preventDefault: boolean;
|
|
7
|
+
keys: RawObject<boolean>;
|
|
8
|
+
mouse: {
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
down: boolean;
|
|
12
|
+
centerX: number;
|
|
13
|
+
centerY: number;
|
|
14
|
+
scaleX: number;
|
|
15
|
+
scaleY: number;
|
|
16
|
+
};
|
|
17
|
+
constructor(ws: WebSocket);
|
|
18
|
+
/**
|
|
19
|
+
* Map the canvas to specified top left and bottom right positions
|
|
20
|
+
* @param canvas HTML canvas element
|
|
21
|
+
* @param canvasContext 2D rendering context for canvas
|
|
22
|
+
* @param top Canvas position to correspond to top of canvas
|
|
23
|
+
* @param left Canvas position to correspond to left of canvas
|
|
24
|
+
* @param bottom Canvas position to correspond to bottom of canvas
|
|
25
|
+
* @param right Canvas position to correspond to right of canvas
|
|
26
|
+
* @param anchor Anchor the origin at a specific spot on the canvas
|
|
27
|
+
*/
|
|
28
|
+
mapCanvasPosition(canvas: HTMLCanvasElement, position: {
|
|
29
|
+
top?: number;
|
|
30
|
+
bottom?: number;
|
|
31
|
+
left?: number;
|
|
32
|
+
right?: number;
|
|
33
|
+
anchor?: 'center' | 'left' | 'right' | 'top' | 'bottom' | 'topleft' | 'topright' | 'bottomleft' | 'bottomright';
|
|
34
|
+
}): void;
|
|
35
|
+
/**
|
|
36
|
+
* @param centerX Anchor x-value corresponding to mouse position x-value of 0
|
|
37
|
+
* @param centerY Anchor y-value corresponding to mouse position y-value of 0
|
|
38
|
+
* @param anchor HTML Element to read mouse position relative to
|
|
39
|
+
* @param scaleX Number of anchor pixels corresponding to a mouse position x-value change of 1
|
|
40
|
+
* @param scaleY Number of anchor pixels corresponding to a mouse position y-value change of 1
|
|
41
|
+
*/
|
|
42
|
+
mapMousePosition(centerX: number, centerY: number, anchor?: HTMLElement, scaleX?: number, scaleY?: number): void;
|
|
43
|
+
/**
|
|
44
|
+
* Map mouse position to the corresponding canvas coordinates on screen
|
|
45
|
+
* @param canvas Canvas element in DOM
|
|
46
|
+
*/
|
|
47
|
+
mapMouseToCanvas(canvas: HTMLCanvasElement): void;
|
|
48
|
+
/**
|
|
49
|
+
* Utilize mouse coordinates of another object
|
|
50
|
+
* @param mouseGetter Callback that returns the mouse coordinates at any given time
|
|
51
|
+
*/
|
|
52
|
+
setMouseAs(mouseGetter: () => {
|
|
53
|
+
x: number;
|
|
54
|
+
y: number;
|
|
55
|
+
}): void;
|
|
56
|
+
private relayInput;
|
|
57
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Add } from './utils';
|
|
2
|
+
import { RawObject } from "./types";
|
|
3
|
+
import { Controller } from "./controller";
|
|
4
|
+
import { MultyxClientObject } from "./items";
|
|
5
|
+
import { Options } from "./options";
|
|
6
|
+
export default class Multyx {
|
|
7
|
+
ws: WebSocket;
|
|
8
|
+
uuid: string;
|
|
9
|
+
joinTime: number;
|
|
10
|
+
ping: number;
|
|
11
|
+
events: Map<string | Symbol, ((data?: any) => void)[]>;
|
|
12
|
+
self: RawObject;
|
|
13
|
+
all: RawObject;
|
|
14
|
+
clients: RawObject;
|
|
15
|
+
teams: RawObject;
|
|
16
|
+
controller: Controller;
|
|
17
|
+
options: Options;
|
|
18
|
+
private listenerQueue;
|
|
19
|
+
static Start: symbol;
|
|
20
|
+
static Connection: symbol;
|
|
21
|
+
static Disconnect: symbol;
|
|
22
|
+
static Edit: symbol;
|
|
23
|
+
static Native: symbol;
|
|
24
|
+
static Custom: symbol;
|
|
25
|
+
static Any: symbol;
|
|
26
|
+
constructor(options?: Options, callback?: () => void);
|
|
27
|
+
on(name: string | Symbol, callback: (data: RawObject) => void): void;
|
|
28
|
+
send(name: string, data: any, expectResponse?: boolean): Promise<unknown>;
|
|
29
|
+
/**
|
|
30
|
+
* Loop over a function
|
|
31
|
+
* @param callback Function to call on a loop
|
|
32
|
+
* @param timesPerSecond Recommended to leave blank. Number of times to loop in each second, if undefined, use requestAnimationFrame
|
|
33
|
+
*/
|
|
34
|
+
loop(callback: () => void, timesPerSecond?: number): void;
|
|
35
|
+
/**
|
|
36
|
+
* Create a callback function that gets called for any current or future client
|
|
37
|
+
* @param callbackfn Function to call for every client
|
|
38
|
+
*/
|
|
39
|
+
forAll(callback: (client: MultyxClientObject) => void): void;
|
|
40
|
+
private parseNativeEvent;
|
|
41
|
+
private initialize;
|
|
42
|
+
private parseEdit;
|
|
43
|
+
private parseSelf;
|
|
44
|
+
/**
|
|
45
|
+
* Add function to listener queue
|
|
46
|
+
* @param fn Function to call once frame is complete
|
|
47
|
+
*/
|
|
48
|
+
[Add](fn: ((...args: any[]) => void)): void;
|
|
49
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import MultyxClientList from "./list";
|
|
2
|
+
import MultyxClientObject from "./object";
|
|
3
|
+
import MultyxClientValue from "./value";
|
|
4
|
+
type MultyxClientItem<T = any> = T extends any[] ? MultyxClientList : T extends object ? MultyxClientObject : MultyxClientValue;
|
|
5
|
+
export { MultyxClientList, MultyxClientObject, MultyxClientValue, MultyxClientItem, };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import Multyx from '../';
|
|
2
|
+
import { MultyxClientItem } from '.';
|
|
3
|
+
import { EditWrapper } from '../utils';
|
|
4
|
+
import MultyxClientObject from "./object";
|
|
5
|
+
export default class MultyxClientList extends MultyxClientObject {
|
|
6
|
+
length: number;
|
|
7
|
+
get value(): any[];
|
|
8
|
+
constructor(multyx: Multyx, list: any[] | EditWrapper<any[]>, propertyPath: string[], editable: boolean);
|
|
9
|
+
set(index: string | number, value: any): boolean;
|
|
10
|
+
delete(index: string | number, native?: boolean): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Create a callback function that gets called for any current or future element in list
|
|
13
|
+
* @param callbackfn Function to call for every element
|
|
14
|
+
*/
|
|
15
|
+
forAll(callbackfn: (value: any, index: number) => void): void;
|
|
16
|
+
push(...items: any): number;
|
|
17
|
+
pop(): MultyxClientItem | null;
|
|
18
|
+
unshift(...items: any[]): number;
|
|
19
|
+
shift(): import("./value").default | MultyxClientObject;
|
|
20
|
+
splice(start: number, deleteCount?: number, ...items: any[]): void;
|
|
21
|
+
filter(predicate: (value: any, index: number, array: MultyxClientList) => boolean): void;
|
|
22
|
+
map(callbackfn: (value: any, index: number, array: MultyxClientList) => any): void;
|
|
23
|
+
flat(): void;
|
|
24
|
+
reduce(callbackfn: (accumulator: any, currentValue: any, index: number, array: MultyxClientList) => any, startingAccumulator: any): any;
|
|
25
|
+
reduceRight(callbackfn: (accumulator: any, currentValue: any, index: number, array: MultyxClientList) => any, startingAccumulator: any): any;
|
|
26
|
+
reverse(): this;
|
|
27
|
+
forEach(callbackfn: (value: any, index: number, array: MultyxClientList) => void): void;
|
|
28
|
+
every(predicate: (value: any, index: number, array: MultyxClientList) => boolean): boolean;
|
|
29
|
+
some(predicate: (value: any, index: number, array: MultyxClientList) => boolean): boolean;
|
|
30
|
+
find(predicate: (value: any, index: number, array: MultyxClientList) => boolean): import("./value").default | MultyxClientObject;
|
|
31
|
+
findIndex(predicate: (value: any, index: number, array: MultyxClientList) => boolean): number;
|
|
32
|
+
deorder(): MultyxClientItem[];
|
|
33
|
+
deorderEntries(): [number, MultyxClientItem][];
|
|
34
|
+
entries(): [any, number][];
|
|
35
|
+
keys(): number[];
|
|
36
|
+
[Symbol.iterator](): Iterator<MultyxClientItem>;
|
|
37
|
+
toString: () => string;
|
|
38
|
+
valueOf: () => any[];
|
|
39
|
+
[Symbol.toPrimitive]: () => any[];
|
|
40
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { RawObject } from '../types';
|
|
2
|
+
import { EditWrapper, Unpack } from "../utils";
|
|
3
|
+
import type Multyx from '../index';
|
|
4
|
+
import type { MultyxClientItem } from ".";
|
|
5
|
+
export default class MultyxClientObject {
|
|
6
|
+
protected object: RawObject<MultyxClientItem>;
|
|
7
|
+
private multyx;
|
|
8
|
+
propertyPath: string[];
|
|
9
|
+
editable: boolean;
|
|
10
|
+
private setterListeners;
|
|
11
|
+
get value(): {};
|
|
12
|
+
constructor(multyx: Multyx, object: RawObject | EditWrapper<RawObject>, propertyPath: string[], editable: boolean);
|
|
13
|
+
has(property: any): boolean;
|
|
14
|
+
get(property: any): MultyxClientItem;
|
|
15
|
+
set(property: any, value: any): boolean;
|
|
16
|
+
delete(property: any, native?: boolean): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Create a callback function that gets called for any current or future property in object
|
|
19
|
+
* @param callbackfn Function to call for every property
|
|
20
|
+
*/
|
|
21
|
+
forAll(callbackfn: (key: any, value: any) => void): void;
|
|
22
|
+
keys(): any[];
|
|
23
|
+
values(): any[];
|
|
24
|
+
entries(): [any, any][];
|
|
25
|
+
/**
|
|
26
|
+
* Unpack constraints from server
|
|
27
|
+
* @param constraints Packed constraints object mirroring MultyxClientObject shape
|
|
28
|
+
*/
|
|
29
|
+
[Unpack](constraints: RawObject): void;
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function MultyxClientItemRouter(data: any): any;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type Multyx from '../';
|
|
2
|
+
import { Constraint, RawObject, Value } from "../types";
|
|
3
|
+
import { EditWrapper, Unpack } from '../utils';
|
|
4
|
+
export default class MultyxClientValue {
|
|
5
|
+
private _value;
|
|
6
|
+
private multyx;
|
|
7
|
+
propertyPath: string[];
|
|
8
|
+
editable: boolean;
|
|
9
|
+
constraints: {
|
|
10
|
+
[key: string]: Constraint;
|
|
11
|
+
};
|
|
12
|
+
private interpolator;
|
|
13
|
+
get value(): Value;
|
|
14
|
+
set value(v: Value);
|
|
15
|
+
constructor(multyx: Multyx, value: Value | EditWrapper<Value>, propertyPath: string[], editable: boolean);
|
|
16
|
+
set(value: Value | EditWrapper<Value>): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Unpack constraints sent from server and store
|
|
19
|
+
* @param constraints Packed constraints from server
|
|
20
|
+
*/
|
|
21
|
+
[Unpack](constraints: RawObject): void;
|
|
22
|
+
/**
|
|
23
|
+
* Linearly interpolate value across frames
|
|
24
|
+
* Will run 1 frame behind on average
|
|
25
|
+
*/
|
|
26
|
+
Lerp(): void;
|
|
27
|
+
PredictiveLerp(): void;
|
|
28
|
+
toString: () => string;
|
|
29
|
+
valueOf: () => Value;
|
|
30
|
+
[Symbol.toPrimitive]: () => Value;
|
|
31
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Update } from "./types";
|
|
2
|
+
export declare class Message {
|
|
3
|
+
name: string;
|
|
4
|
+
data: any;
|
|
5
|
+
time: number;
|
|
6
|
+
native: boolean;
|
|
7
|
+
private constructor();
|
|
8
|
+
static BundleOperations(deltaTime: any, operations: any): string;
|
|
9
|
+
static Native(update: Update): string;
|
|
10
|
+
static Parse(str: string): Message;
|
|
11
|
+
static Create(name: string, data: any): string;
|
|
12
|
+
}
|
package/dist/options.js
CHANGED
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type RawObject<V = any> = {
|
|
2
|
+
[key: string | number | symbol]: V;
|
|
3
|
+
};
|
|
4
|
+
export type Value = string | number | boolean;
|
|
5
|
+
export type Constraint = (n: Value) => Value | null;
|
|
6
|
+
export type EditUpdate = {
|
|
7
|
+
instruction: 'edit';
|
|
8
|
+
path: string[];
|
|
9
|
+
value: any;
|
|
10
|
+
};
|
|
11
|
+
export type InputUpdate = {
|
|
12
|
+
instruction: 'input';
|
|
13
|
+
input: string;
|
|
14
|
+
data?: RawObject<Value>;
|
|
15
|
+
};
|
|
16
|
+
export type Update = EditUpdate | InputUpdate;
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Constraint, RawObject, Value } from "./types";
|
|
2
|
+
export declare const Unpack: unique symbol;
|
|
3
|
+
export declare const Done: unique symbol;
|
|
4
|
+
export declare const Add: unique symbol;
|
|
5
|
+
export declare class EditWrapper<T> {
|
|
6
|
+
value: T;
|
|
7
|
+
constructor(value: T);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Set a customized interpolation curve for values to follow
|
|
11
|
+
* @param values Slices to interpolate through. Time must be between 0 and 1, while progress is the percentage between the old value and new value at the respective time, where 0 represents old value and 1 represents new value
|
|
12
|
+
* @example
|
|
13
|
+
* ```js
|
|
14
|
+
* car.get('speed').interpolate([
|
|
15
|
+
* { time: 0, progress: 0 },
|
|
16
|
+
* { time: 0.2, progress: 0.6 },
|
|
17
|
+
* { time: 0.4, progress: 1.2 },
|
|
18
|
+
* { time: 0.6, progress: 1.4 },
|
|
19
|
+
* { time: 0.8, progress: 1.2 },
|
|
20
|
+
* { time: 1, progress: 1 }
|
|
21
|
+
* ]);
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function Interpolate(object: RawObject, property: string, interpolationCurve: {
|
|
25
|
+
time: number;
|
|
26
|
+
progress: number;
|
|
27
|
+
}[]): void;
|
|
28
|
+
export declare function BuildConstraint(name: string, args: Value[]): Constraint | void;
|
package/multyx.js
CHANGED
|
@@ -1 +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})()));
|
|
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:8443,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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "multyx-client",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
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
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
package/src/options.ts
CHANGED
package/tsconfig.json
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"target": "es6", // Specify the target ECMAScript version.
|
|
4
4
|
"lib": ["es2017", "dom"],
|
|
5
5
|
"module": "commonjs", // Do not use any module system (for browser use).
|
|
6
|
+
"declaration": true,
|
|
6
7
|
"outDir": "./dist",
|
|
7
8
|
"rootDir": "./src", // Specify the root directory of your TypeScript source files.
|
|
8
9
|
}
|