@shaunlwm/pickle.ts 0.5.0 → 1.0.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/index.d.ts CHANGED
@@ -28,6 +28,109 @@ type QueueUpdate = {
28
28
  queueLength: number;
29
29
  };
30
30
 
31
+ /** Core appearance slots shared by all servers (CPJourney, CPLegacy, NewCP). */
32
+ type PlayerAppearance = {
33
+ color: number;
34
+ head: number;
35
+ face: number;
36
+ neck: number;
37
+ body: number;
38
+ hand: number;
39
+ feet: number;
40
+ flag: number;
41
+ photo: number;
42
+ };
43
+ /** CPJourney only */
44
+ type PlayerSettings = {
45
+ music_volume: number;
46
+ sfx_volume: number;
47
+ hide_penguins: boolean;
48
+ hide_chats: boolean;
49
+ hide_emotes: boolean;
50
+ hide_ui: boolean;
51
+ hide_usernames: boolean;
52
+ quality: number;
53
+ silence_notifications: boolean;
54
+ opt_out_postcards: boolean;
55
+ opt_out_buddy_requests: boolean;
56
+ };
57
+ type Buddy = {
58
+ id: number;
59
+ username: string;
60
+ online: boolean;
61
+ /** CPJourney only */
62
+ favorite?: boolean;
63
+ /** CPJourney only */
64
+ items?: number[];
65
+ /** CPJourney only */
66
+ onlineServer?: string;
67
+ };
68
+ /**
69
+ * A penguin visible in a room. Only fields present on 2+ servers are
70
+ * top-level. Single-server extras live in `meta`.
71
+ *
72
+ * Display name mapping:
73
+ * - CPJourney: `displayName`
74
+ * - CPLegacy: `realUsername` → `displayName`
75
+ * - NewCP: `nickname` → `displayName`
76
+ */
77
+ type RoomUser = PlayerAppearance & {
78
+ id: number;
79
+ username: string;
80
+ x: number;
81
+ y: number;
82
+ frame: number;
83
+ /** Adapter-specific extras. See each adapter's normalizeUser for keys. */
84
+ meta: Record<string, unknown>;
85
+ /** Original unnormalized server response */
86
+ _raw: Record<string, unknown>;
87
+ /** Display name — source field varies per server, normalized here */
88
+ displayName?: string;
89
+ /** CPJourney, CPLegacy */
90
+ joinTime?: string;
91
+ /** CPJourney: puffle type number, CPLegacy: walking puffle ID */
92
+ walking?: number;
93
+ };
94
+ /**
95
+ * Full player data from `load_player`. Only fields present on 2+ servers
96
+ * are top-level. Single-server extras live in `meta`.
97
+ *
98
+ * Coins/rank source:
99
+ * - CPJourney/NewCP: sibling fields of `user` in `load_player` args
100
+ * - CPLegacy: inside `user` object directly
101
+ */
102
+ type PlayerData = RoomUser & {
103
+ coins: number;
104
+ rank: number;
105
+ inventory: number[];
106
+ /** CPJourney, NewCP */
107
+ buddies?: Buddy[];
108
+ /** CPJourney, CPLegacy (CPLegacy maps from `pending` array) */
109
+ buddyRequests?: number[];
110
+ /** CPJourney, NewCP */
111
+ ignores?: number[];
112
+ /** All servers — CPJourney: array, CPLegacy/NewCP: Record<string, number> */
113
+ furniture?: unknown[] | Record<string, unknown>;
114
+ /** CPJourney, NewCP */
115
+ flooring?: unknown[];
116
+ /** CPJourney, NewCP */
117
+ igloos?: unknown[];
118
+ };
119
+ type Postcard = {
120
+ id: number;
121
+ username: string;
122
+ senderId: number;
123
+ postcardId: number;
124
+ extra: string | null;
125
+ date: string;
126
+ };
127
+ type Mascot = {
128
+ id: number;
129
+ name: string;
130
+ giveaway: number;
131
+ stamp: number;
132
+ };
133
+
31
134
  type ConnectOptions = {
32
135
  onQueueUpdate?: (update: QueueUpdate) => void;
33
136
  };
@@ -38,6 +141,54 @@ declare abstract class BaseAdapter {
38
141
  abstract connect(serverName: string, loginResult: LoginResult, options?: ConnectOptions): Promise<Socket>;
39
142
  abstract disconnect(): void;
40
143
  abstract send(action: string, args: Record<string, unknown>): void;
144
+ normalizeUser(_raw: Record<string, unknown>): RoomUser;
145
+ normalizePlayer(_raw: Record<string, unknown>): PlayerData;
146
+ protected extractAppearance(raw: Record<string, unknown>): PlayerAppearance;
147
+ sendMessage(_message: string): void;
148
+ sendEmote(_emote: number): void;
149
+ sendSafe(_safe: number): void;
150
+ walk(_x: number, _y: number): void;
151
+ sendFrame(_frame: number, _set?: boolean): void;
152
+ snowball(_x: number, _y: number): void;
153
+ joinRoom(_room: number, _x?: number, _y?: number): void;
154
+ addItem(_item: number): void;
155
+ equipColor(_item: number): void;
156
+ equipHead(_item: number): void;
157
+ equipFace(_item: number): void;
158
+ equipNeck(_item: number): void;
159
+ equipBody(_item: number): void;
160
+ equipHand(_item: number): void;
161
+ equipFeet(_item: number): void;
162
+ equipFlag(_item: number): void;
163
+ equipPhoto(_item: number): void;
164
+ buddyRequest(_id: number): void;
165
+ buddyAccept(_id: number): void;
166
+ buddyReject(_id: number): void;
167
+ buddyRequestSeen(_id: number): void;
168
+ getBuddy(_id: number, _type: "buddies" | "buddyRequests"): void;
169
+ removeBuddy(_id: number): void;
170
+ addIgnore(_id: number): void;
171
+ removeIgnore(_id: number): void;
172
+ getPlayer(_id: number): void;
173
+ getAllSlots(): void;
174
+ getMascots(): void;
175
+ sendPostcard(_userId: number, _cardId: string): void;
176
+ getStamps(_userId: number): void;
177
+ getPostcards(): void;
178
+ getIglooOpen(_igloo: number): void;
179
+ joinIgloo(_igloo: number, _x?: number, _y?: number): void;
180
+ gameOver(_coins: number): void;
181
+ collectStamp(_stamp: number): void;
182
+ }
183
+
184
+ declare class CpjourneyAdapter extends BaseAdapter {
185
+ readonly id = "CPJourney";
186
+ login(options: LoginOptions | TokenLoginOptions): Promise<LoginResult>;
187
+ connect(serverName: string, loginResult: LoginResult, options?: ConnectOptions): Promise<Socket>;
188
+ send(action: string, args: Record<string, unknown>): void;
189
+ disconnect(): void;
190
+ normalizeUser(raw: Record<string, unknown>): RoomUser;
191
+ normalizePlayer(raw: Record<string, unknown>): PlayerData;
41
192
  sendMessage(message: string): void;
42
193
  sendEmote(emote: number): void;
43
194
  sendSafe(safe: number): void;
@@ -73,14 +224,6 @@ declare abstract class BaseAdapter {
73
224
  joinIgloo(igloo: number, x?: number, y?: number): void;
74
225
  gameOver(coins: number): void;
75
226
  collectStamp(stamp: number): void;
76
- }
77
-
78
- declare class CpjourneyAdapter extends BaseAdapter {
79
- readonly id = "CPJourney";
80
- login(options: LoginOptions | TokenLoginOptions): Promise<LoginResult>;
81
- connect(serverName: string, loginResult: LoginResult, options?: ConnectOptions): Promise<Socket>;
82
- send(action: string, args: Record<string, unknown>): void;
83
- disconnect(): void;
84
227
  private createSocket;
85
228
  }
86
229
 
@@ -91,6 +234,37 @@ declare class CplegacyAdapter extends BaseAdapter {
91
234
  connect(serverName: string, loginResult: LoginResult, options?: ConnectOptions): Promise<Socket>;
92
235
  send(action: string, args: Record<string, unknown>): void;
93
236
  disconnect(): void;
237
+ normalizeUser(raw: Record<string, unknown>): RoomUser;
238
+ normalizePlayer(raw: Record<string, unknown>): PlayerData;
239
+ sendMessage(message: string): void;
240
+ sendEmote(emote: number): void;
241
+ sendSafe(safe: number): void;
242
+ walk(x: number, y: number): void;
243
+ sendFrame(frame: number, set?: boolean): void;
244
+ snowball(x: number, y: number): void;
245
+ joinRoom(room: number, x?: number, y?: number): void;
246
+ addItem(item: number): void;
247
+ equipColor(item: number): void;
248
+ equipHead(item: number): void;
249
+ equipFace(item: number): void;
250
+ equipNeck(item: number): void;
251
+ equipBody(item: number): void;
252
+ equipHand(item: number): void;
253
+ equipFeet(item: number): void;
254
+ equipFlag(item: number): void;
255
+ equipPhoto(item: number): void;
256
+ buddyRequest(id: number): void;
257
+ buddyAccept(id: number): void;
258
+ buddyReject(id: number): void;
259
+ removeBuddy(id: number): void;
260
+ addIgnore(id: number): void;
261
+ removeIgnore(id: number): void;
262
+ getPlayer(id: number): void;
263
+ getStamps(userId: number): void;
264
+ getPostcards(): void;
265
+ joinIgloo(igloo: number, x?: number, y?: number): void;
266
+ gameOver(coins: number): void;
267
+ collectStamp(stamp: number): void;
94
268
  private postLogin;
95
269
  }
96
270
 
@@ -102,6 +276,33 @@ declare class NewcpAdapter extends BaseAdapter {
102
276
  connect(serverName: string, loginResult: LoginResult, options?: ConnectOptions): Promise<Socket>;
103
277
  send(action: string, args: Record<string, unknown>): void;
104
278
  disconnect(): void;
279
+ normalizeUser(raw: Record<string, unknown>): RoomUser;
280
+ normalizePlayer(raw: Record<string, unknown>): PlayerData;
281
+ sendMessage(message: string): void;
282
+ sendEmote(emote: number): void;
283
+ sendSafe(safe: number): void;
284
+ walk(x: number, y: number): void;
285
+ sendFrame(frame: number, set?: boolean): void;
286
+ snowball(x: number, y: number): void;
287
+ joinRoom(room: number, x?: number, y?: number): void;
288
+ addItem(item: number): void;
289
+ equipColor(item: number): void;
290
+ equipHead(item: number): void;
291
+ equipFace(item: number): void;
292
+ equipNeck(item: number): void;
293
+ equipBody(item: number): void;
294
+ equipHand(item: number): void;
295
+ equipFeet(item: number): void;
296
+ equipFlag(item: number): void;
297
+ equipPhoto(item: number): void;
298
+ buddyRequest(id: number): void;
299
+ buddyAccept(id: number): void;
300
+ buddyReject(id: number): void;
301
+ removeBuddy(id: number): void;
302
+ addIgnore(id: number): void;
303
+ removeIgnore(id: number): void;
304
+ getPlayer(id: number): void;
305
+ joinIgloo(igloo: number, x?: number, y?: number): void;
105
306
  private createSocket;
106
307
  private loadWorlds;
107
308
  }
@@ -113,99 +314,6 @@ declare const ADAPTERS: {
113
314
  };
114
315
  type AdapterName = keyof typeof ADAPTERS;
115
316
 
116
- type PlayerAppearance = {
117
- color: number;
118
- hat: number;
119
- head: number;
120
- face: number;
121
- face_mask: number;
122
- neck: number;
123
- neck_scarf: number;
124
- body: number;
125
- body_shirt: number;
126
- hand: number;
127
- hand_glove: number;
128
- feet: number;
129
- flag: number;
130
- photo: number;
131
- transform: number;
132
- };
133
- type PlayerSettings = {
134
- music_volume: number;
135
- sfx_volume: number;
136
- hide_penguins: boolean;
137
- hide_chats: boolean;
138
- hide_emotes: boolean;
139
- hide_ui: boolean;
140
- hide_usernames: boolean;
141
- quality: number;
142
- silence_notifications: boolean;
143
- opt_out_postcards: boolean;
144
- opt_out_buddy_requests: boolean;
145
- };
146
- type Buddy = {
147
- id: number;
148
- username: string;
149
- online: boolean;
150
- favorite: boolean;
151
- items: number[];
152
- onlineServer: string;
153
- };
154
- type RoomUser = PlayerAppearance & {
155
- id: number;
156
- username: string;
157
- displayName: string;
158
- joinTime: string;
159
- x: number;
160
- y: number;
161
- frame: number;
162
- walking: number;
163
- walkingPuffleType: number;
164
- openSprite?: string;
165
- mascotGiveaway?: unknown;
166
- iglooOpen: number;
167
- iglooBounds: number;
168
- igloo_slot: number;
169
- currentLayer: number;
170
- fireRank: number;
171
- };
172
- type PlayerData = RoomUser & {
173
- coins: number;
174
- partyCoins: number;
175
- gems: number;
176
- rank: number;
177
- streamer: boolean;
178
- username_verified: boolean;
179
- email_verified: boolean;
180
- settings: PlayerSettings;
181
- buddies: Buddy[];
182
- buddyRequests: number[];
183
- ignores: number[];
184
- inventory: number[];
185
- puffleInventory: unknown[];
186
- igloos: unknown[];
187
- furniture: unknown[];
188
- flooring: unknown[];
189
- inf_skill_points: number;
190
- highest_floor_reached: number;
191
- towerMeters: number;
192
- towerExperience: number;
193
- };
194
- type Postcard = {
195
- id: number;
196
- username: string;
197
- senderId: number;
198
- postcardId: number;
199
- extra: string | null;
200
- date: string;
201
- };
202
- type Mascot = {
203
- id: number;
204
- name: string;
205
- giveaway: number;
206
- stamp: number;
207
- };
208
-
209
317
  type ClientMessages = {
210
318
  send_position: {
211
319
  x: number;
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- var m=class{socket=null;sendMessage(e){this.send("send_message",{message:e})}sendEmote(e){this.send("send_emote",{emote:e})}sendSafe(e){this.send("send_safe",{safe:e})}walk(e,n){this.send("send_position",{x:e,y:n})}sendFrame(e,n){this.send("send_frame",{frame:e,set:n})}snowball(e,n){this.send("snowball",{x:e,y:n})}joinRoom(e,n,s){this.send("join_room",{room:e,x:n??0,y:s??0})}addItem(e){this.send("add_item",{item:e})}equipColor(e){this.send("update_color",{item:e})}equipHead(e){this.send("update_head",{item:e})}equipFace(e){this.send("update_face",{item:e})}equipNeck(e){this.send("update_neck",{item:e})}equipBody(e){this.send("update_body",{item:e})}equipHand(e){this.send("update_hand",{item:e})}equipFeet(e){this.send("update_feet",{item:e})}equipFlag(e){this.send("update_flag",{item:e})}equipPhoto(e){this.send("update_photo",{item:e})}buddyRequest(e){this.send("buddy_request",{id:e})}buddyAccept(e){this.send("buddy_accept",{id:e})}buddyReject(e){this.send("buddy_reject",{id:e})}buddyRequestSeen(e){this.send("buddy_request_seen",{id:e})}getBuddy(e,n){this.send("get_buddy",{id:e,type:n})}removeBuddy(e){this.send("remove_buddy",{id:e})}addIgnore(e){this.send("ignore_add",{id:e})}removeIgnore(e){this.send("ignore_remove",{id:e})}getPlayer(e){this.send("get_player",{id:e})}getAllSlots(){this.send("get_all_slots",{})}getMascots(){this.send("get_mascots",{})}sendPostcard(e,n){this.send("send_postcard",{userId:e,cardId:n})}getStamps(e){this.send("get_stamps",{userId:e})}getPostcards(){this.send("get_postcards",{})}getIglooOpen(e){this.send("get_igloo_open",{igloo:e})}joinIgloo(e,n,s){this.send("join_igloo",{igloo:e,x:n??0,y:s??0})}gameOver(e){this.send("game_over",{coins:e})}collectStamp(e){this.send("collect_stamp",{stamp:e})}};import{EventEmitter as N}from"events";import{io as R}from"socket.io-client";import L from"socket.io-msgpack-parser";var O="wss://play.cpjourney.net",P="skip",h=class extends m{id="CPJourney";async login(e){let n=this.createSocket("/world/login/");return await new Promise((o,t)=>{let i=setTimeout(()=>{n.disconnect(),t(new Error("Login timed out"))},1e4);n.on("connect",()=>{let a=e.secret??P,r="token"in e?{username:e.username,token:e.token,secret:a}:{username:e.username,password:e.password,secret:a};n.emit("message",{action:"login",args:r})}),n.on("message",a=>{if(a.action!=="login")return;clearTimeout(i),n.disconnect();let r=a.args;if(!r.success){t(new Error("Login failed"));return}let c=Object.entries(r.populations).map(([u,p])=>({name:u,population:p}));o({servers:c,key:r.key,username:r.username,moderator:r.moderator,buddyWorlds:r.buddyWorlds??[]})}),n.on("connect_error",a=>{clearTimeout(i),n.disconnect(),t(new Error(`Login connection failed: ${a.message}`))})})}async connect(e,n,s){let o=this.createSocket(`/world/${e.toLowerCase()}/`);return this.socket=o,await new Promise((t,i)=>{let a=!1;o.on("connect",()=>{o.emit("message",{action:"game_auth",args:{username:n.username,key:n.key,createToken:!1,joinInvis:!1,takeoverMascot:!1,token:""}})}),o.on("message",r=>{switch(r.action){case"wait_queue_update":{s?.onQueueUpdate?.(r.args);break}case"game_auth":{if(a)break;if(a=!0,!r.args.success){o.disconnect(),i(new Error("Game auth failed"));return}o.emit("message",{action:"join_server",args:{}}),t();break}}}),o.on("connect_error",r=>{o.disconnect(),i(new Error(`Game connection failed: ${r.message}`))})}),o}send(e,n){if(!this.socket)throw new Error("Not connected");this.socket.emit("message",{action:e,args:n})}disconnect(){this.socket?.disconnect(),this.socket=null}createSocket(e){return R(O,{path:e,parser:L,transports:["polling","websocket"],reconnection:!1})}};import{io as E}from"socket.io-client";import T from"socket.io-msgpack-parser";var q="https://api.cplegacy.com/login",x="https://api.cplegacy.com/token_login";function A(d){let e=d.on.bind(d);return d.on=((n,s)=>n==="message"?e(n,(o,t)=>{s({action:o,args:t??{}})}):e(n,s)),d}var b=class extends m{id="CPLegacy";version="";async login(e){let n="token"in e?x:q,s="token"in e?{username:e.username,token:e.token}:{username:e.username,password:e.password,version:this.version},o=await this.postLogin(n,s);if(!o.success&&o.wantedVersion&&(this.version=o.wantedVersion,s.version=this.version,o=await this.postLogin(n,s)),!o.success)throw new Error(`Login failed: ${o.message??"unknown error"}`);return{servers:Object.entries(o.populations??{}).map(([i,a])=>({name:i,population:a})),key:o.key,username:o.username,moderator:!1,buddyWorlds:[]}}async connect(e,n,s){let o=`wss://${e.toLowerCase()}.server.cplegacy.com`,t=E(o,{path:"/socket.io/",parser:T,transports:["websocket"],reconnection:!1});return this.socket=t,await new Promise((i,a)=>{let r=setTimeout(()=>{t.disconnect(),a(new Error("Game connection timed out"))},15e3);t.on("connect",()=>{t.emit("message","game_auth",{username:n.username,key:n.key,createToken:!1,token:""})}),t.on("message",(c,u)=>{switch(c){case"wait_queue_update":{s?.onQueueUpdate?.(u);break}case"game_auth":{if(!u.success){clearTimeout(r),t.disconnect(),a(new Error("Game auth failed"));return}t.emit("message","load_player",{}),t.emit("message","join_server",{}),clearTimeout(r),i();break}}}),t.on("connect_error",c=>{clearTimeout(r),t.disconnect(),a(new Error(`Game connection failed: ${c.message}`))})}),A(t)}send(e,n){if(!this.socket)throw new Error("Not connected");this.socket.emit("message",e,n)}disconnect(){this.socket?.disconnect(),this.socket=null}async postLogin(e,n){return(await fetch(e,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(n)})).json()}};import{createCipheriv as C,createDecipheriv as M,randomBytes as K}from"crypto";import{io as U}from"socket.io-client";import k from"tweetnacl";var B="https://media8.newcp.net/assets/media/crumbs/en/crumbs.json",y=class{aesKey=null;keypair=k.box.keyPair();get publicKey(){return Buffer.from(this.keypair.publicKey).toString("base64")}get encrypted(){return this.aesKey!==null}acquireKey(e,n){let s=Buffer.from(e,"base64"),o=Buffer.from(n,"base64"),t=s.subarray(0,k.box.nonceLength),i=s.subarray(k.box.nonceLength),a=k.box.open(new Uint8Array(i),new Uint8Array(t),new Uint8Array(o),this.keypair.secretKey);return a?new TextDecoder().decode(a):null}setKey(e){this.aesKey=Buffer.from(e,"utf-8")}encrypt(e){if(!this.aesKey)throw new Error("Encryption key not set");let n=K(16),s=C("aes-256-cbc",this.aesKey,n),o=Buffer.concat([s.update(e,"utf-8"),s.final()]);return Buffer.concat([n,o]).toString("base64")}decrypt(e){if(!this.aesKey)throw new Error("Encryption key not set");let n=Buffer.from(e,"base64"),s=n.subarray(0,16),o=n.subarray(16),t=M("aes-256-cbc",this.aesKey,s);return Buffer.concat([t.update(o),t.final()]).toString("utf-8")}encode(e){return this.encrypted?this.encrypt(JSON.stringify(e)):JSON.stringify(e)}decode(e){return this.encrypted&&typeof e=="string"?JSON.parse(this.decrypt(e)):typeof e=="string"?JSON.parse(e):e}};function w(d,e){return new Promise((n,s)=>{let o=setTimeout(()=>{s(new Error("Handshake timed out"))},1e4);d.once("handshake",(t,i)=>{clearTimeout(o);let a=e.acquireKey(t,i);if(!a){s(new Error("Failed to decrypt handshake key"));return}let r=JSON.parse(a);if(r.time&&typeof r.time=="number"&&Math.abs(Date.now()-r.time)>3e5){s(new Error("Server time desync"));return}e.setKey(r.key),n()}),d.emit("handshake",e.publicKey)})}function j(d,e){let n=d.on.bind(d);return d.on=((s,o)=>s==="message"?n(s,t=>{try{let i=e.decode(t);o({action:i.action,args:i.args??{}})}catch{}}):n(s,o)),d}var f=class extends m{id="NewCP";encryptor=new y;worlds=null;async login(e){this.worlds||await this.loadWorlds();let n=Object.values(this.worlds??{}).find(t=>t.login);if(!n)throw new Error("Login world not found in crumbs");let s=this.createSocket(n.host,n.path);return this.encryptor=new y,await new Promise((t,i)=>{let a=setTimeout(()=>{s.disconnect(),i(new Error("Login timed out"))},15e3);s.on("connect",async()=>{try{await w(s,this.encryptor);let r="token"in e?{username:e.username,token:e.token}:{username:e.username,password:e.password},c=this.encryptor.encode({action:"login",args:r});s.emit("message",c)}catch(r){clearTimeout(a),s.disconnect(),i(r)}}),s.on("message",r=>{try{let c=this.encryptor.decode(r);if(c.action!=="login")return;clearTimeout(a),s.disconnect();let u=c.args;if(!u.success){i(new Error("Login failed"));return}let p=Object.entries(u.populations??{}).map(([l,g])=>({name:l,population:g}));t({servers:p,key:u.key,username:u.username,moderator:u.moderator??!1,buddyWorlds:u.buddyWorlds??[]})}catch(c){clearTimeout(a),s.disconnect(),i(c)}}),s.on("connect_error",r=>{clearTimeout(a),s.disconnect(),i(new Error(`Login connection failed: ${r.message}`))})})}async connect(e,n,s){this.worlds||await this.loadWorlds();let o=this.worlds?.[e];if(!o)throw new Error(`World config not found for: ${e}`);this.encryptor=new y;let t=this.createSocket(o.host,o.path);return this.socket=t,await new Promise((i,a)=>{let r=setTimeout(()=>{t.disconnect(),a(new Error("Game connection timed out"))},15e3);t.on("connect",async()=>{try{await w(t,this.encryptor);let c=this.encryptor.encode({action:"game_auth",args:{username:n.username,key:n.key,createToken:!1}});t.emit("message",c)}catch(c){clearTimeout(r),t.disconnect(),a(c)}}),t.on("message",c=>{try{let u=this.encryptor.decode(c);switch(u.action){case"wait_queue_update":{s?.onQueueUpdate?.(u.args);break}case"game_auth":{if(!u.args.success){clearTimeout(r),t.disconnect(),a(new Error("Game auth failed"));return}let l=this.encryptor.encode({action:"join_server",args:{}});t.emit("message",l),clearTimeout(r),i();break}}}catch{}}),t.on("connect_error",c=>{clearTimeout(r),t.disconnect(),a(new Error(`Game connection failed: ${c.message}`))})}),j(t,this.encryptor)}send(e,n){if(!this.socket)throw new Error("Not connected");let s=this.encryptor.encode({action:e,args:n});this.socket.emit("message",s)}disconnect(){this.socket?.disconnect(),this.socket=null}createSocket(e,n){return U(e,{path:n,transports:["polling","websocket"],reconnection:!1})}async loadWorlds(){let e=await fetch(B);if(!e.ok)throw new Error(`Failed to fetch crumbs: ${e.status}`);let n=await e.json();this.worlds=n.worlds}};var I={CPJourney:h,CPLegacy:b,NewCP:f};function _(d){return new I[d]}function S(d){return typeof d=="object"&&d!==null&&"action"in d&&"args"in d}var v=class extends N{player=null;room=null;users=new Map;connected=!1;adapter;loginResult=null;log=null;constructor(e,n){super(),this.adapter=_(e),n?.debug&&(this.log=typeof n.debug=="function"?n.debug:console.log.bind(console))}async login(e){return this.log?.("[login] logging in as",e.username),this.loginResult=await this.adapter.login(e),this.log?.("[login] success \u2014",this.loginResult.servers.length,"servers"),this.loginResult.servers}async connect(e,n){if(!this.loginResult)throw new Error("Must call login() first");this.log?.("[connect] joining",e);let s={...n,onQueueUpdate:t=>{this.log?.("[queue]",`#${t.position}/${t.queueLength}`),this.emit("wait_queue_update",t),n?.onQueueUpdate?.(t)}},o=await this.adapter.connect(e,this.loginResult,s);o.on("message",t=>{S(t)&&this.handleMessage(t)}),o.on("disconnect",()=>{this.log?.("[disconnect] connection lost"),this.cleanup(),this.emit("disconnect")}),await new Promise((t,i)=>{let a=setTimeout(()=>{i(new Error("Waiting for load_player timed out"))},1e4),r=!1,c=!1,u=()=>{r&&c&&(clearTimeout(a),this.connected=!0,t())},p=g=>{if(S(g))switch(g.action){case"load_player":r=!0,u();break;case"join_room":c=!0,u();break;case"kick":clearTimeout(a),o.off("message",p),i(new Error(`Kicked: ${g.args.reason??"unknown"}`));break;case"close_with_error":clearTimeout(a),o.off("message",p),i(new Error(`Kicked: ${g.args.error??"unknown"}`));break;case"error":clearTimeout(a),o.off("message",p),i(new Error(`Server error: ${g.args.error??"unknown"}`));break}},l=()=>{(!r||!c)&&(clearTimeout(a),i(new Error("Disconnected before fully loaded")))};o.on("message",p),o.once("disconnect",l)})}on(e,n){return super.on(e,n)}off(e,n){return super.off(e,n)}once(e,n){return super.once(e,n)}emit(e,...n){return super.emit(e,...n)}sendMessage(e){this.adapter.sendMessage(e)}sendEmote(e){this.adapter.sendEmote(e)}sendSafe(e){this.adapter.sendSafe(e)}walk(e,n){this.adapter.walk(e,n)}sendFrame(e,n){this.adapter.sendFrame(e,n)}snowball(e,n){this.adapter.snowball(e,n)}joinRoom(e,n,s){this.adapter.joinRoom(e,n,s)}addItem(e){this.adapter.addItem(e)}equipColor(e){this.adapter.equipColor(e)}equipHead(e){this.adapter.equipHead(e)}equipFace(e){this.adapter.equipFace(e)}equipNeck(e){this.adapter.equipNeck(e)}equipBody(e){this.adapter.equipBody(e)}equipHand(e){this.adapter.equipHand(e)}equipFeet(e){this.adapter.equipFeet(e)}equipFlag(e){this.adapter.equipFlag(e)}equipPhoto(e){this.adapter.equipPhoto(e)}buddyRequest(e){this.adapter.buddyRequest(e)}buddyAccept(e){this.adapter.buddyAccept(e)}buddyReject(e){this.adapter.buddyReject(e)}buddyRequestSeen(e){this.adapter.buddyRequestSeen(e)}getBuddy(e,n){this.adapter.getBuddy(e,n)}removeBuddy(e){this.adapter.removeBuddy(e)}addIgnore(e){this.adapter.addIgnore(e)}removeIgnore(e){this.adapter.removeIgnore(e)}getPlayer(e){this.adapter.getPlayer(e)}getAllSlots(){this.adapter.getAllSlots()}getMascots(){this.adapter.getMascots()}sendPostcard(e,n){this.adapter.sendPostcard(e,n)}getStamps(e){this.adapter.getStamps(e)}getPostcards(){this.adapter.getPostcards()}getIglooOpen(e){this.adapter.getIglooOpen(e)}joinIgloo(e,n,s){this.adapter.joinIgloo(e,n,s)}gameOver(e){this.adapter.gameOver(e)}collectStamp(e){this.adapter.collectStamp(e)}sleep(e){return new Promise(n=>setTimeout(n,e))}disconnect(){this.log?.("[disconnect] closing connection"),this.adapter.disconnect(),this.cleanup()}cleanup(){this.connected=!1,this.player=null,this.room=null,this.users.clear()}handleMessage(e){let{action:n,args:s}=e;switch(n){case"load_player":{let t=s.user;t.coins=s.coins??0,t.inventory=s.inventory??[],t.furniture=s.furniture??[],t.flooring=s.flooring??[],t.rank=s.rank??0,this.player=t,this.log?.("[load_player]",t.username,`id=${t.id}`,`coins=${t.coins}`,`inventory=${t.inventory.length}`);break}case"join_room":{let t=s.room,i=s.users;this.room=t,this.users.clear();for(let a of i)this.users.set(a.id,a);this.log?.("[join_room]",`room=${t}`,`users=${i.length}`);break}case"add_player":{let t=s.user;this.users.set(t.id,t),this.log?.("[add_player]",t.username,`id=${t.id}`);break}case"remove_player":{let t=s.user;this.users.delete(t),this.log?.("[remove_player]",`id=${t}`);break}case"send_position":{let t=s.id,i=this.users.get(t);i&&(i.x=s.x,i.y=s.y);break}case"send_frame":{let t=s.id,i=this.users.get(t);i&&(i.frame=s.frame);break}case"update_player":{let t=s.id,i=s.slot,a=s.item,r=this.users.get(t);r&&i in r&&(r[i]=a);break}case"kick":{let t=s.reason??"unknown";this.log?.("[kick]",t),this.cleanup();break}case"close_with_error":{let t=s.error??"unknown";this.log?.("[kick]",t),this.cleanup();break}default:{this.log?.(`[${n}]`,JSON.stringify(s));break}}let o=n==="error"?"server_error":n;this.emit(o,s)}};export{m as BaseAdapter,v as Client};
1
+ var p=class{socket=null;normalizeUser(e){throw new Error("Not implemented: normalizeUser")}normalizePlayer(e){throw new Error("Not implemented: normalizePlayer")}extractAppearance(e){return{color:e.color??0,head:e.head??0,face:e.face??0,neck:e.neck??0,body:e.body??0,hand:e.hand??0,feet:e.feet??0,flag:e.flag??0,photo:e.photo??0}}sendMessage(e){throw new Error("Not implemented: sendMessage")}sendEmote(e){throw new Error("Not implemented: sendEmote")}sendSafe(e){throw new Error("Not implemented: sendSafe")}walk(e,o){throw new Error("Not implemented: walk")}sendFrame(e,o){throw new Error("Not implemented: sendFrame")}snowball(e,o){throw new Error("Not implemented: snowball")}joinRoom(e,o,r){throw new Error("Not implemented: joinRoom")}addItem(e){throw new Error("Not implemented: addItem")}equipColor(e){throw new Error("Not implemented: equipColor")}equipHead(e){throw new Error("Not implemented: equipHead")}equipFace(e){throw new Error("Not implemented: equipFace")}equipNeck(e){throw new Error("Not implemented: equipNeck")}equipBody(e){throw new Error("Not implemented: equipBody")}equipHand(e){throw new Error("Not implemented: equipHand")}equipFeet(e){throw new Error("Not implemented: equipFeet")}equipFlag(e){throw new Error("Not implemented: equipFlag")}equipPhoto(e){throw new Error("Not implemented: equipPhoto")}buddyRequest(e){throw new Error("Not implemented: buddyRequest")}buddyAccept(e){throw new Error("Not implemented: buddyAccept")}buddyReject(e){throw new Error("Not implemented: buddyReject")}buddyRequestSeen(e){throw new Error("Not implemented: buddyRequestSeen")}getBuddy(e,o){throw new Error("Not implemented: getBuddy")}removeBuddy(e){throw new Error("Not implemented: removeBuddy")}addIgnore(e){throw new Error("Not implemented: addIgnore")}removeIgnore(e){throw new Error("Not implemented: removeIgnore")}getPlayer(e){throw new Error("Not implemented: getPlayer")}getAllSlots(){throw new Error("Not implemented: getAllSlots")}getMascots(){throw new Error("Not implemented: getMascots")}sendPostcard(e,o){throw new Error("Not implemented: sendPostcard")}getStamps(e){throw new Error("Not implemented: getStamps")}getPostcards(){throw new Error("Not implemented: getPostcards")}getIglooOpen(e){throw new Error("Not implemented: getIglooOpen")}joinIgloo(e,o,r){throw new Error("Not implemented: joinIgloo")}gameOver(e){throw new Error("Not implemented: gameOver")}collectStamp(e){throw new Error("Not implemented: collectStamp")}};import{EventEmitter as F}from"events";import{io as S}from"socket.io-client";import E from"socket.io-msgpack-parser";var q="wss://play.cpjourney.net",P="skip",v=class extends p{id="CPJourney";async login(e){let o=this.createSocket("/world/login/");return await new Promise((s,t)=>{let n=setTimeout(()=>{o.disconnect(),t(new Error("Login timed out"))},1e4);o.on("connect",()=>{let i=e.secret??P,d="token"in e?{username:e.username,token:e.token,secret:i}:{username:e.username,password:e.password,secret:i};o.emit("message",{action:"login",args:d})}),o.on("message",i=>{if(i.action!=="login")return;clearTimeout(n),o.disconnect();let d=i.args;if(!d.success){t(new Error("Login failed"));return}let a=Object.entries(d.populations).map(([m,c])=>({name:m,population:c}));s({servers:a,key:d.key,username:d.username,moderator:d.moderator,buddyWorlds:d.buddyWorlds??[]})}),o.on("connect_error",i=>{clearTimeout(n),o.disconnect(),t(new Error(`Login connection failed: ${i.message}`))})})}async connect(e,o,r){let s=this.createSocket(`/world/${e.toLowerCase()}/`);return this.socket=s,await new Promise((t,n)=>{let i=!1;s.on("connect",()=>{s.emit("message",{action:"game_auth",args:{username:o.username,key:o.key,createToken:!1,joinInvis:!1,takeoverMascot:!1,token:""}})}),s.on("message",d=>{switch(d.action){case"wait_queue_update":{r?.onQueueUpdate?.(d.args);break}case"game_auth":{if(i)break;if(i=!0,!d.args.success){s.disconnect(),n(new Error("Game auth failed"));return}s.emit("message",{action:"join_server",args:{}}),t();break}}}),s.on("connect_error",d=>{s.disconnect(),n(new Error(`Game connection failed: ${d.message}`))})}),s}send(e,o){if(!this.socket)throw new Error("Not connected");this.socket.emit("message",{action:e,args:o})}disconnect(){this.socket?.disconnect(),this.socket=null}normalizeUser(e){return{...this.extractAppearance(e),id:e.id,username:e.username,displayName:e.displayName,joinTime:e.joinTime,x:e.x??0,y:e.y??0,frame:e.frame??0,walking:e.walking,meta:{hat:e.hat,face_mask:e.face_mask,neck_scarf:e.neck_scarf,body_shirt:e.body_shirt,hand_glove:e.hand_glove,transform:e.transform,walkingPuffleType:e.walkingPuffleType,openSprite:e.openSprite,mascotGiveaway:e.mascotGiveaway,iglooOpen:e.iglooOpen,iglooBounds:e.iglooBounds,igloo_slot:e.igloo_slot,currentLayer:e.currentLayer,fireRank:e.fireRank},_raw:e}}normalizePlayer(e){let o=e.user,r=this.normalizeUser(o);return{...r,_raw:e,coins:e.coins??0,rank:e.rank??0,inventory:e.inventory??[],furniture:e.furniture??[],flooring:e.flooring??[],buddies:o.buddies??[],buddyRequests:o.buddyRequests??[],ignores:o.ignores??[],igloos:o.igloos??[],meta:{...r.meta,settings:o.settings,puffleInventory:e.puffleInventory??o.puffleInventory,partyCoins:e.partyCoins??o.partyCoins,gems:e.gems??o.gems,streamer:e.streamer??o.streamer,username_verified:e.username_verified??o.username_verified,email_verified:e.email_verified??o.email_verified,inf_skill_points:e.inf_skill_points??o.inf_skill_points,highest_floor_reached:e.highest_floor_reached??o.highest_floor_reached,towerMeters:e.towerMeters??o.towerMeters,towerExperience:e.towerExperience??o.towerExperience}}}sendMessage(e){this.send("send_message",{message:e})}sendEmote(e){this.send("send_emote",{emote:e})}sendSafe(e){this.send("send_safe",{safe:e})}walk(e,o){this.send("send_position",{x:e,y:o})}sendFrame(e,o){this.send("send_frame",{frame:e,set:o})}snowball(e,o){this.send("snowball",{x:e,y:o})}joinRoom(e,o,r){this.send("join_room",{room:e,x:o??0,y:r??0})}addItem(e){this.send("add_item",{item:e})}equipColor(e){this.send("update_color",{item:e})}equipHead(e){this.send("update_head",{item:e})}equipFace(e){this.send("update_face",{item:e})}equipNeck(e){this.send("update_neck",{item:e})}equipBody(e){this.send("update_body",{item:e})}equipHand(e){this.send("update_hand",{item:e})}equipFeet(e){this.send("update_feet",{item:e})}equipFlag(e){this.send("update_flag",{item:e})}equipPhoto(e){this.send("update_photo",{item:e})}buddyRequest(e){this.send("buddy_request",{id:e})}buddyAccept(e){this.send("buddy_accept",{id:e})}buddyReject(e){this.send("buddy_reject",{id:e})}buddyRequestSeen(e){this.send("buddy_request_seen",{id:e})}getBuddy(e,o){this.send("get_buddy",{id:e,type:o})}removeBuddy(e){this.send("remove_buddy",{id:e})}addIgnore(e){this.send("ignore_add",{id:e})}removeIgnore(e){this.send("ignore_remove",{id:e})}getPlayer(e){this.send("get_player",{id:e})}getAllSlots(){this.send("get_all_slots",{})}getMascots(){this.send("get_mascots",{})}sendPostcard(e,o){this.send("send_postcard",{userId:e,cardId:o})}getStamps(e){this.send("get_stamps",{userId:e})}getPostcards(){this.send("get_postcards",{})}getIglooOpen(e){this.send("get_igloo_open",{igloo:e})}joinIgloo(e,o,r){this.send("join_igloo",{igloo:e,x:o??0,y:r??0})}gameOver(e){this.send("game_over",{coins:e})}collectStamp(e){this.send("collect_stamp",{stamp:e})}createSocket(e){return S(q,{path:e,parser:E,transports:["polling","websocket"],reconnection:!1})}};import{io as L}from"socket.io-client";import N from"socket.io-msgpack-parser";var O="https://api.cplegacy.com/login",x="https://api.cplegacy.com/token_login";function C(u){let e=u.on.bind(u);return u.on=((o,r)=>o==="message"?e(o,(s,t)=>{r({action:s,args:t??{}})}):e(o,r)),u}var h=class extends p{id="CPLegacy";version="";async login(e){let o="token"in e?x:O,r="token"in e?{username:e.username,token:e.token}:{username:e.username,password:e.password,version:this.version},s=await this.postLogin(o,r);if(!s.success&&s.wantedVersion&&(this.version=s.wantedVersion,r.version=this.version,s=await this.postLogin(o,r)),!s.success)throw new Error(`Login failed: ${s.message??"unknown error"}`);return{servers:Object.entries(s.populations??{}).map(([n,i])=>({name:n,population:i})),key:s.key,username:s.username,moderator:!1,buddyWorlds:[]}}async connect(e,o,r){let s=`wss://${e.toLowerCase()}.server.cplegacy.com`,t=L(s,{path:"/socket.io/",parser:N,transports:["websocket"],reconnection:!1});return this.socket=t,await new Promise((n,i)=>{let d=setTimeout(()=>{t.disconnect(),i(new Error("Game connection timed out"))},15e3);t.on("connect",()=>{t.emit("message","game_auth",{username:o.username,key:o.key,createToken:!1,token:""})}),t.on("message",(a,m)=>{switch(a){case"wait_queue_update":{r?.onQueueUpdate?.(m);break}case"game_auth":{if(!m.success){clearTimeout(d),t.disconnect(),i(new Error("Game auth failed"));return}t.emit("message","load_player",{}),t.emit("message","join_server",{}),clearTimeout(d),n();break}}}),t.on("connect_error",a=>{clearTimeout(d),t.disconnect(),i(new Error(`Game connection failed: ${a.message}`))})}),C(t)}send(e,o){if(!this.socket)throw new Error("Not connected");this.socket.emit("message",e,o)}disconnect(){this.socket?.disconnect(),this.socket=null}normalizeUser(e){return{...this.extractAppearance(e),id:e.id,username:e.username,displayName:e.realUsername??e.username,joinTime:e.joinTime,x:e.x??0,y:e.y??0,frame:e.frame??0,walking:e.walking??void 0,meta:{internalUsername:e.username,approved:e.approved,emailVerified:e.emailVerified,safeChat:e.safeChat,tutorial:e.tutorial,loginStreak:e.loginStreak,walkingColor:e.walkingColor,stampbookColor:e.stampbookColor,stampbookClasp:e.stampbookClasp,stampbookPattern:e.stampbookPattern,ninjaPoints:e.ninjaPoints,highestNinjaRank:e.highestNinjaRank,character:e.character,transformed:e.transformed},_raw:e}}normalizePlayer(e){let o=e.user;return{...this.normalizeUser(o),_raw:e,coins:o.coins??0,rank:o.rank??0,inventory:e.inventory??[],furniture:e.furniture,buddies:[],buddyRequests:e.pending?.map(r=>r.id)??[],ignores:[],igloos:e.igloos??[]}}sendMessage(e){this.send("send_message",{message:e})}sendEmote(e){this.send("send_emote",{emote:e})}sendSafe(e){this.send("send_safe",{safe:e})}walk(e,o){this.send("send_position",{x:e,y:o})}sendFrame(e,o){this.send("send_frame",{frame:e,set:o})}snowball(e,o){this.send("snowball",{x:e,y:o})}joinRoom(e,o,r){this.send("join_room",{room:e,x:o??0,y:r??0})}addItem(e){this.send("add_item",{item:e})}equipColor(e){this.send("update_color",{item:e})}equipHead(e){this.send("update_head",{item:e})}equipFace(e){this.send("update_face",{item:e})}equipNeck(e){this.send("update_neck",{item:e})}equipBody(e){this.send("update_body",{item:e})}equipHand(e){this.send("update_hand",{item:e})}equipFeet(e){this.send("update_feet",{item:e})}equipFlag(e){this.send("update_flag",{item:e})}equipPhoto(e){this.send("update_photo",{item:e})}buddyRequest(e){this.send("buddy_request",{id:e})}buddyAccept(e){this.send("buddy_accept",{id:e})}buddyReject(e){this.send("buddy_reject",{id:e})}removeBuddy(e){this.send("remove_buddy",{id:e})}addIgnore(e){this.send("ignore_add",{id:e})}removeIgnore(e){this.send("ignore_remove",{id:e})}getPlayer(e){this.send("get_player",{id:e})}getStamps(e){this.send("get_stamps",{userId:e})}getPostcards(){this.send("get_postcards",{})}joinIgloo(e,o,r){this.send("join_igloo",{igloo:e,x:o??0,y:r??0})}gameOver(e){this.send("game_over",{coins:e})}collectStamp(e){this.send("collect_stamp",{stamp:e})}async postLogin(e,o){return(await fetch(e,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(o)})).json()}};import{createCipheriv as j,createDecipheriv as T,randomBytes as U}from"crypto";import{io as A}from"socket.io-client";import y from"tweetnacl";var B="https://media8.newcp.net/assets/media/crumbs/en/crumbs.json",b=class{aesKey=null;keypair=y.box.keyPair();get publicKey(){return Buffer.from(this.keypair.publicKey).toString("base64")}get encrypted(){return this.aesKey!==null}acquireKey(e,o){let r=Buffer.from(e,"base64"),s=Buffer.from(o,"base64"),t=r.subarray(0,y.box.nonceLength),n=r.subarray(y.box.nonceLength),i=y.box.open(new Uint8Array(n),new Uint8Array(t),new Uint8Array(s),this.keypair.secretKey);return i?new TextDecoder().decode(i):null}setKey(e){this.aesKey=Buffer.from(e,"utf-8")}encrypt(e){if(!this.aesKey)throw new Error("Encryption key not set");let o=U(16),r=j("aes-256-cbc",this.aesKey,o),s=Buffer.concat([r.update(e,"utf-8"),r.final()]);return Buffer.concat([o,s]).toString("base64")}decrypt(e){if(!this.aesKey)throw new Error("Encryption key not set");let o=Buffer.from(e,"base64"),r=o.subarray(0,16),s=o.subarray(16),t=T("aes-256-cbc",this.aesKey,r);return Buffer.concat([t.update(s),t.final()]).toString("utf-8")}encode(e){return this.encrypted?this.encrypt(JSON.stringify(e)):JSON.stringify(e)}decode(e){return this.encrypted&&typeof e=="string"?JSON.parse(this.decrypt(e)):typeof e=="string"?JSON.parse(e):e}};function _(u,e){return new Promise((o,r)=>{let s=setTimeout(()=>{r(new Error("Handshake timed out"))},1e4);u.once("handshake",(t,n)=>{clearTimeout(s);let i=e.acquireKey(t,n);if(!i){r(new Error("Failed to decrypt handshake key"));return}let d=JSON.parse(i);if(d.time&&typeof d.time=="number"&&Math.abs(Date.now()-d.time)>3e5){r(new Error("Server time desync"));return}e.setKey(d.key),o()}),u.emit("handshake",e.publicKey)})}function I(u,e){let o=u.on.bind(u);return u.on=((r,s)=>r==="message"?o(r,t=>{try{let n=e.decode(t);s({action:n.action,args:n.args??{}})}catch{}}):o(r,s)),u}var f=class extends p{id="NewCP";encryptor=new b;worlds=null;async login(e){this.worlds||await this.loadWorlds();let o=Object.values(this.worlds??{}).find(t=>t.login);if(!o)throw new Error("Login world not found in crumbs");let r=this.createSocket(o.host,o.path);return this.encryptor=new b,await new Promise((t,n)=>{let i=setTimeout(()=>{r.disconnect(),n(new Error("Login timed out"))},15e3);r.on("connect",async()=>{try{await _(r,this.encryptor);let d="token"in e?{username:e.username,token:e.token}:{username:e.username,password:e.password},a=this.encryptor.encode({action:"login",args:d});r.emit("message",a)}catch(d){clearTimeout(i),r.disconnect(),n(d)}}),r.on("message",d=>{try{let a=this.encryptor.decode(d);if(a.action!=="login")return;clearTimeout(i),r.disconnect();let m=a.args;if(!m.success){n(new Error("Login failed"));return}let c=Object.entries(m.populations??{}).map(([g,l])=>({name:g,population:l}));t({servers:c,key:m.key,username:m.username,moderator:m.moderator??!1,buddyWorlds:m.buddyWorlds??[]})}catch(a){clearTimeout(i),r.disconnect(),n(a)}}),r.on("connect_error",d=>{clearTimeout(i),r.disconnect(),n(new Error(`Login connection failed: ${d.message}`))})})}async connect(e,o,r){this.worlds||await this.loadWorlds();let s=this.worlds?.[e];if(!s)throw new Error(`World config not found for: ${e}`);this.encryptor=new b;let t=this.createSocket(s.host,s.path);return this.socket=t,await new Promise((n,i)=>{let d=setTimeout(()=>{t.disconnect(),i(new Error("Game connection timed out"))},15e3);t.on("connect",async()=>{try{await _(t,this.encryptor);let a=this.encryptor.encode({action:"game_auth",args:{username:o.username,key:o.key,createToken:!1}});t.emit("message",a)}catch(a){clearTimeout(d),t.disconnect(),i(a)}}),t.on("message",a=>{try{let m=this.encryptor.decode(a);switch(m.action){case"wait_queue_update":{r?.onQueueUpdate?.(m.args);break}case"game_auth":{if(!m.args.success){clearTimeout(d),t.disconnect(),i(new Error("Game auth failed"));return}let g=this.encryptor.encode({action:"join_server",args:{}});t.emit("message",g),clearTimeout(d),n();break}}}catch{}}),t.on("connect_error",a=>{clearTimeout(d),t.disconnect(),i(new Error(`Game connection failed: ${a.message}`))})}),I(t,this.encryptor)}send(e,o){if(!this.socket)throw new Error("Not connected");let r=this.encryptor.encode({action:e,args:o});this.socket.emit("message",r)}disconnect(){this.socket?.disconnect(),this.socket=null}normalizeUser(e){return{...this.extractAppearance(e),id:e.id,username:e.username,displayName:e.nickname,x:e.x??0,y:e.y??0,frame:e.frame??0,meta:{nickname:e.nickname,registrationDate:e.registrationDate,customNameColor:e.customNameColor,customBubbleColor:e.customBubbleColor,customBubbleTextColor:e.customBubbleTextColor,wallHacks:e.wallHacks,moderator:e.moderator,character:e.character,approved:e.approved,walking:e.walking},_raw:e}}normalizePlayer(e){let o=e.user;return{...this.normalizeUser(o),_raw:e,coins:e.coins??0,rank:e.rank??0,inventory:e.inventory??[],buddies:e.buddies??[],ignores:e.ignores??[],furniture:e.furniture,flooring:e.floorings??[],igloos:e.igloos??[]}}sendMessage(e){this.send("send_message",{message:e})}sendEmote(e){this.send("send_emote",{emote:e})}sendSafe(e){this.send("send_safe",{safe:e})}walk(e,o){this.send("send_position",{x:e,y:o})}sendFrame(e,o){this.send("send_frame",{frame:e,set:o})}snowball(e,o){this.send("snowball",{x:e,y:o})}joinRoom(e,o,r){this.send("join_room",{room:e,x:o??0,y:r??0})}addItem(e){this.send("add_item",{item:e})}equipColor(e){this.send("update_color",{item:e})}equipHead(e){this.send("update_head",{item:e})}equipFace(e){this.send("update_face",{item:e})}equipNeck(e){this.send("update_neck",{item:e})}equipBody(e){this.send("update_body",{item:e})}equipHand(e){this.send("update_hand",{item:e})}equipFeet(e){this.send("update_feet",{item:e})}equipFlag(e){this.send("update_flag",{item:e})}equipPhoto(e){this.send("update_photo",{item:e})}buddyRequest(e){this.send("buddy_request",{id:e})}buddyAccept(e){this.send("buddy_accept",{id:e})}buddyReject(e){this.send("buddy_reject",{id:e})}removeBuddy(e){this.send("remove_buddy",{id:e})}addIgnore(e){this.send("ignore_add",{id:e})}removeIgnore(e){this.send("ignore_remove",{id:e})}getPlayer(e){this.send("get_player",{id:e})}joinIgloo(e,o,r){this.send("join_igloo",{igloo:e,x:o??0,y:r??0})}createSocket(e,o){return A(e,{path:o,transports:["polling","websocket"],reconnection:!1})}async loadWorlds(){let e=await fetch(B);if(!e.ok)throw new Error(`Failed to fetch crumbs: ${e.status}`);let o=await e.json();this.worlds=o.worlds}};var M={CPJourney:v,CPLegacy:h,NewCP:f};function w(u){return new M[u]}function R(u){return typeof u=="object"&&u!==null&&"action"in u&&"args"in u}var k=class extends F{player=null;room=null;users=new Map;connected=!1;adapter;loginResult=null;log=null;constructor(e,o){super(),this.adapter=w(e),o?.debug&&(this.log=typeof o.debug=="function"?o.debug:console.log.bind(console))}async login(e){return this.log?.("[login] logging in as",e.username),this.loginResult=await this.adapter.login(e),this.log?.("[login] success \u2014",this.loginResult.servers.length,"servers"),this.loginResult.servers}async connect(e,o){if(!this.loginResult)throw new Error("Must call login() first");this.log?.("[connect] joining",e);let r={...o,onQueueUpdate:t=>{this.log?.("[queue]",`#${t.position}/${t.queueLength}`),this.emit("wait_queue_update",t),o?.onQueueUpdate?.(t)}},s=await this.adapter.connect(e,this.loginResult,r);s.on("message",t=>{R(t)&&this.handleMessage(t)}),s.on("disconnect",()=>{this.log?.("[disconnect] connection lost"),this.cleanup(),this.emit("disconnect")}),await new Promise((t,n)=>{let i=setTimeout(()=>{n(new Error("Waiting for load_player timed out"))},1e4),d=!1,a=!1,m=()=>{d&&a&&(clearTimeout(i),this.connected=!0,t())},c=l=>{if(R(l))switch(l.action){case"load_player":d=!0,m();break;case"join_room":a=!0,m();break;case"kick":clearTimeout(i),s.off("message",c),n(new Error(`Kicked: ${l.args.reason??"unknown"}`));break;case"close_with_error":clearTimeout(i),s.off("message",c),n(new Error(`Kicked: ${l.args.error??"unknown"}`));break;case"error":clearTimeout(i),s.off("message",c),n(new Error(`Server error: ${l.args.error??"unknown"}`));break}},g=()=>{(!d||!a)&&(clearTimeout(i),n(new Error("Disconnected before fully loaded")))};s.on("message",c),s.once("disconnect",g)})}on(e,o){return super.on(e,o)}off(e,o){return super.off(e,o)}once(e,o){return super.once(e,o)}emit(e,...o){return super.emit(e,...o)}sendMessage(e){this.adapter.sendMessage(e)}sendEmote(e){this.adapter.sendEmote(e)}sendSafe(e){this.adapter.sendSafe(e)}walk(e,o){this.adapter.walk(e,o)}sendFrame(e,o){this.adapter.sendFrame(e,o)}snowball(e,o){this.adapter.snowball(e,o)}joinRoom(e,o,r){this.adapter.joinRoom(e,o,r)}addItem(e){this.adapter.addItem(e)}equipColor(e){this.adapter.equipColor(e)}equipHead(e){this.adapter.equipHead(e)}equipFace(e){this.adapter.equipFace(e)}equipNeck(e){this.adapter.equipNeck(e)}equipBody(e){this.adapter.equipBody(e)}equipHand(e){this.adapter.equipHand(e)}equipFeet(e){this.adapter.equipFeet(e)}equipFlag(e){this.adapter.equipFlag(e)}equipPhoto(e){this.adapter.equipPhoto(e)}buddyRequest(e){this.adapter.buddyRequest(e)}buddyAccept(e){this.adapter.buddyAccept(e)}buddyReject(e){this.adapter.buddyReject(e)}buddyRequestSeen(e){this.adapter.buddyRequestSeen(e)}getBuddy(e,o){this.adapter.getBuddy(e,o)}removeBuddy(e){this.adapter.removeBuddy(e)}addIgnore(e){this.adapter.addIgnore(e)}removeIgnore(e){this.adapter.removeIgnore(e)}getPlayer(e){this.adapter.getPlayer(e)}getAllSlots(){this.adapter.getAllSlots()}getMascots(){this.adapter.getMascots()}sendPostcard(e,o){this.adapter.sendPostcard(e,o)}getStamps(e){this.adapter.getStamps(e)}getPostcards(){this.adapter.getPostcards()}getIglooOpen(e){this.adapter.getIglooOpen(e)}joinIgloo(e,o,r){this.adapter.joinIgloo(e,o,r)}gameOver(e){this.adapter.gameOver(e)}collectStamp(e){this.adapter.collectStamp(e)}sleep(e){return new Promise(o=>setTimeout(o,e))}disconnect(){this.log?.("[disconnect] closing connection"),this.adapter.disconnect(),this.cleanup()}cleanup(){this.connected=!1,this.player=null,this.room=null,this.users.clear()}handleMessage(e){let{action:o,args:r}=e,s=r;switch(o){case"load_player":{let n=this.adapter.normalizePlayer(r);this.player=n,s={user:n},this.log?.("[load_player]",n.username,`id=${n.id}`,`coins=${n.coins}`,`inventory=${n.inventory.length}`);break}case"join_room":{let n=r.room,i=r.users;this.room=n,this.users.clear();let d=[];for(let a of i){let m=this.adapter.normalizeUser(a);this.users.set(m.id,m),d.push(m)}s={room:n,users:d},this.log?.("[join_room]",`room=${n}`,`users=${d.length}`);break}case"add_player":{let n=this.adapter.normalizeUser(r.user);this.users.set(n.id,n),s={user:n},this.log?.("[add_player]",n.username,`id=${n.id}`);break}case"remove_player":{let n=r.user;this.users.delete(n),this.log?.("[remove_player]",`id=${n}`);break}case"send_position":{let n=r.id,i=this.users.get(n);i&&(i.x=r.x,i.y=r.y);break}case"send_frame":{let n=r.id,i=this.users.get(n);i&&(i.frame=r.frame);break}case"update_player":{let n=r.id,i=r.slot,d=r.item,a=this.users.get(n);a&&i in a&&(a[i]=d);break}case"kick":{let n=r.reason??"unknown";this.log?.("[kick]",n),this.cleanup();break}case"close_with_error":{let n=r.error??"unknown";this.log?.("[kick]",n),this.cleanup();break}default:{this.log?.(`[${o}]`,JSON.stringify(r));break}}let t=o==="error"?"server_error":o;this.emit(t,s)}};export{p as BaseAdapter,k as Client};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/adapters/base-adapter.ts","../src/client.ts","../src/adapters/cpjourney-adapter.ts","../src/adapters/cplegacy-adapter.ts","../src/adapters/newcp-adapter.ts","../src/adapters/index.ts"],"sourcesContent":["import type { Socket } from \"socket.io-client\";\nimport type {\n LoginOptions,\n LoginResult,\n QueueUpdate,\n TokenLoginOptions,\n} from \"../types/adapter-types.js\";\n\nexport type ConnectOptions = {\n onQueueUpdate?: (update: QueueUpdate) => void;\n};\n\nexport abstract class BaseAdapter {\n abstract readonly id: string;\n protected socket: Socket | null = null;\n\n abstract login(\n options: LoginOptions | TokenLoginOptions,\n ): Promise<LoginResult>;\n abstract connect(\n serverName: string,\n loginResult: LoginResult,\n options?: ConnectOptions,\n ): Promise<Socket>;\n abstract disconnect(): void;\n abstract send(action: string, args: Record<string, unknown>): void;\n\n sendMessage(message: string): void {\n this.send(\"send_message\", { message });\n }\n\n sendEmote(emote: number): void {\n this.send(\"send_emote\", { emote });\n }\n\n sendSafe(safe: number): void {\n this.send(\"send_safe\", { safe });\n }\n\n walk(x: number, y: number): void {\n this.send(\"send_position\", { x, y });\n }\n\n sendFrame(frame: number, set?: boolean): void {\n this.send(\"send_frame\", { frame, set });\n }\n\n snowball(x: number, y: number): void {\n this.send(\"snowball\", { x, y });\n }\n\n joinRoom(room: number, x?: number, y?: number): void {\n this.send(\"join_room\", { room, x: x ?? 0, y: y ?? 0 });\n }\n\n addItem(item: number): void {\n this.send(\"add_item\", { item });\n }\n\n equipColor(item: number): void {\n this.send(\"update_color\", { item });\n }\n\n equipHead(item: number): void {\n this.send(\"update_head\", { item });\n }\n\n equipFace(item: number): void {\n this.send(\"update_face\", { item });\n }\n\n equipNeck(item: number): void {\n this.send(\"update_neck\", { item });\n }\n\n equipBody(item: number): void {\n this.send(\"update_body\", { item });\n }\n\n equipHand(item: number): void {\n this.send(\"update_hand\", { item });\n }\n\n equipFeet(item: number): void {\n this.send(\"update_feet\", { item });\n }\n\n equipFlag(item: number): void {\n this.send(\"update_flag\", { item });\n }\n\n equipPhoto(item: number): void {\n this.send(\"update_photo\", { item });\n }\n\n buddyRequest(id: number): void {\n this.send(\"buddy_request\", { id });\n }\n\n buddyAccept(id: number): void {\n this.send(\"buddy_accept\", { id });\n }\n\n buddyReject(id: number): void {\n this.send(\"buddy_reject\", { id });\n }\n\n buddyRequestSeen(id: number): void {\n this.send(\"buddy_request_seen\", { id });\n }\n\n getBuddy(id: number, type: \"buddies\" | \"buddyRequests\"): void {\n this.send(\"get_buddy\", { id, type });\n }\n\n removeBuddy(id: number): void {\n this.send(\"remove_buddy\", { id });\n }\n\n addIgnore(id: number): void {\n this.send(\"ignore_add\", { id });\n }\n\n removeIgnore(id: number): void {\n this.send(\"ignore_remove\", { id });\n }\n\n getPlayer(id: number): void {\n this.send(\"get_player\", { id });\n }\n\n getAllSlots(): void {\n this.send(\"get_all_slots\", {});\n }\n\n getMascots(): void {\n this.send(\"get_mascots\", {});\n }\n\n sendPostcard(userId: number, cardId: string): void {\n this.send(\"send_postcard\", { userId, cardId });\n }\n\n getStamps(userId: number): void {\n this.send(\"get_stamps\", { userId });\n }\n\n getPostcards(): void {\n this.send(\"get_postcards\", {});\n }\n\n getIglooOpen(igloo: number): void {\n this.send(\"get_igloo_open\", { igloo });\n }\n\n joinIgloo(igloo: number, x?: number, y?: number): void {\n this.send(\"join_igloo\", { igloo, x: x ?? 0, y: y ?? 0 });\n }\n\n gameOver(coins: number): void {\n this.send(\"game_over\", { coins });\n }\n\n collectStamp(stamp: number): void {\n this.send(\"collect_stamp\", { stamp });\n }\n}\n","import { EventEmitter } from \"node:events\";\nimport type { BaseAdapter, ConnectOptions } from \"./adapters/base-adapter.js\";\nimport { type AdapterName, createAdapter } from \"./adapters/index.js\";\nimport type {\n LoginOptions,\n LoginResult,\n QueueUpdate,\n ServerInfo,\n TokenLoginOptions,\n} from \"./types/adapter-types.js\";\nimport type { ServerMessages } from \"./types/message-types.js\";\nimport type { PlayerData, RoomUser } from \"./types/player-types.js\";\n\ntype ServerMessageHandler<K extends keyof ServerMessages> = (\n args: ServerMessages[K],\n) => void;\n\nexport type LogFn = (message: string, ...args: unknown[]) => void;\n\nexport type ClientOptions = {\n debug?: boolean | LogFn;\n};\n\ntype MessagePayload = {\n action: string;\n args: Record<string, unknown>;\n};\n\nfunction isMessagePayload(msg: unknown): msg is MessagePayload {\n return (\n typeof msg === \"object\" && msg !== null && \"action\" in msg && \"args\" in msg\n );\n}\n\nexport class Client extends EventEmitter {\n player: PlayerData | null = null;\n room: number | null = null;\n users: Map<number, RoomUser> = new Map();\n connected = false;\n\n private adapter: BaseAdapter;\n private loginResult: LoginResult | null = null;\n private log: LogFn | null = null;\n\n constructor(server: AdapterName, options?: ClientOptions) {\n super();\n this.adapter = createAdapter(server);\n\n if (options?.debug) {\n this.log =\n typeof options.debug === \"function\"\n ? options.debug\n : console.log.bind(console);\n }\n }\n\n async login(\n options: LoginOptions | TokenLoginOptions,\n ): Promise<ServerInfo[]> {\n this.log?.(\"[login] logging in as\", options.username);\n this.loginResult = await this.adapter.login(options);\n this.log?.(\"[login] success —\", this.loginResult.servers.length, \"servers\");\n return this.loginResult.servers;\n }\n\n async connect(serverName: string, options?: ConnectOptions): Promise<void> {\n if (!this.loginResult) throw new Error(\"Must call login() first\");\n\n this.log?.(\"[connect] joining\", serverName);\n\n const connectOptions: ConnectOptions = {\n ...options,\n onQueueUpdate: (update: QueueUpdate) => {\n this.log?.(\"[queue]\", `#${update.position}/${update.queueLength}`);\n this.emit(\"wait_queue_update\", update);\n options?.onQueueUpdate?.(update);\n },\n };\n\n const socket = await this.adapter.connect(\n serverName,\n this.loginResult,\n connectOptions,\n );\n\n socket.on(\"message\", (msg: unknown) => {\n if (!isMessagePayload(msg)) return;\n this.handleMessage(msg);\n });\n\n socket.on(\"disconnect\", () => {\n this.log?.(\"[disconnect] connection lost\");\n this.cleanup();\n this.emit(\"disconnect\");\n });\n\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(\"Waiting for load_player timed out\"));\n }, 10_000);\n\n let playerLoaded = false;\n let roomJoined = false;\n\n const checkReady = (): void => {\n if (playerLoaded && roomJoined) {\n clearTimeout(timeout);\n this.connected = true;\n resolve();\n }\n };\n\n const onMessage = (msg: unknown): void => {\n if (!isMessagePayload(msg)) return;\n switch (msg.action) {\n case \"load_player\":\n playerLoaded = true;\n checkReady();\n break;\n case \"join_room\":\n roomJoined = true;\n checkReady();\n break;\n case \"kick\":\n clearTimeout(timeout);\n socket.off(\"message\", onMessage);\n reject(\n new Error(\n `Kicked: ${(msg.args as { reason?: string }).reason ?? \"unknown\"}`,\n ),\n );\n break;\n case \"close_with_error\":\n clearTimeout(timeout);\n socket.off(\"message\", onMessage);\n reject(\n new Error(\n `Kicked: ${(msg.args as { error?: string }).error ?? \"unknown\"}`,\n ),\n );\n break;\n case \"error\":\n clearTimeout(timeout);\n socket.off(\"message\", onMessage);\n reject(\n new Error(\n `Server error: ${(msg.args as { error?: string | number }).error ?? \"unknown\"}`,\n ),\n );\n break;\n }\n };\n\n const onDisconnect = (): void => {\n if (!playerLoaded || !roomJoined) {\n clearTimeout(timeout);\n reject(new Error(\"Disconnected before fully loaded\"));\n }\n };\n\n socket.on(\"message\", onMessage);\n socket.once(\"disconnect\", onDisconnect);\n });\n }\n\n on<K extends keyof ServerMessages>(\n event: K,\n listener: ServerMessageHandler<K>,\n ): this;\n on(event: string, listener: (...args: unknown[]) => void): this;\n on(event: string, listener: (...args: unknown[]) => void): this {\n return super.on(event, listener);\n }\n\n off<K extends keyof ServerMessages>(\n event: K,\n listener: ServerMessageHandler<K>,\n ): this;\n off(event: string, listener: (...args: unknown[]) => void): this;\n off(event: string, listener: (...args: unknown[]) => void): this {\n return super.off(event, listener);\n }\n\n once<K extends keyof ServerMessages>(\n event: K,\n listener: ServerMessageHandler<K>,\n ): this;\n once(event: string, listener: (...args: unknown[]) => void): this;\n once(event: string, listener: (...args: unknown[]) => void): this {\n return super.once(event, listener);\n }\n\n emit<K extends keyof ServerMessages>(\n event: K,\n args: ServerMessages[K],\n ): boolean;\n emit(event: string, ...args: unknown[]): boolean;\n emit(event: string, ...args: unknown[]): boolean {\n return super.emit(event, ...args);\n }\n\n sendMessage(message: string): void {\n this.adapter.sendMessage(message);\n }\n sendEmote(emote: number): void {\n this.adapter.sendEmote(emote);\n }\n sendSafe(safe: number): void {\n this.adapter.sendSafe(safe);\n }\n walk(x: number, y: number): void {\n this.adapter.walk(x, y);\n }\n sendFrame(frame: number, set?: boolean): void {\n this.adapter.sendFrame(frame, set);\n }\n snowball(x: number, y: number): void {\n this.adapter.snowball(x, y);\n }\n joinRoom(room: number, x?: number, y?: number): void {\n this.adapter.joinRoom(room, x, y);\n }\n addItem(item: number): void {\n this.adapter.addItem(item);\n }\n equipColor(item: number): void {\n this.adapter.equipColor(item);\n }\n equipHead(item: number): void {\n this.adapter.equipHead(item);\n }\n equipFace(item: number): void {\n this.adapter.equipFace(item);\n }\n equipNeck(item: number): void {\n this.adapter.equipNeck(item);\n }\n equipBody(item: number): void {\n this.adapter.equipBody(item);\n }\n equipHand(item: number): void {\n this.adapter.equipHand(item);\n }\n equipFeet(item: number): void {\n this.adapter.equipFeet(item);\n }\n equipFlag(item: number): void {\n this.adapter.equipFlag(item);\n }\n equipPhoto(item: number): void {\n this.adapter.equipPhoto(item);\n }\n buddyRequest(id: number): void {\n this.adapter.buddyRequest(id);\n }\n buddyAccept(id: number): void {\n this.adapter.buddyAccept(id);\n }\n buddyReject(id: number): void {\n this.adapter.buddyReject(id);\n }\n buddyRequestSeen(id: number): void {\n this.adapter.buddyRequestSeen(id);\n }\n getBuddy(id: number, type: \"buddies\" | \"buddyRequests\"): void {\n this.adapter.getBuddy(id, type);\n }\n removeBuddy(id: number): void {\n this.adapter.removeBuddy(id);\n }\n addIgnore(id: number): void {\n this.adapter.addIgnore(id);\n }\n removeIgnore(id: number): void {\n this.adapter.removeIgnore(id);\n }\n getPlayer(id: number): void {\n this.adapter.getPlayer(id);\n }\n getAllSlots(): void {\n this.adapter.getAllSlots();\n }\n getMascots(): void {\n this.adapter.getMascots();\n }\n sendPostcard(userId: number, cardId: string): void {\n this.adapter.sendPostcard(userId, cardId);\n }\n getStamps(userId: number): void {\n this.adapter.getStamps(userId);\n }\n getPostcards(): void {\n this.adapter.getPostcards();\n }\n getIglooOpen(igloo: number): void {\n this.adapter.getIglooOpen(igloo);\n }\n joinIgloo(igloo: number, x?: number, y?: number): void {\n this.adapter.joinIgloo(igloo, x, y);\n }\n gameOver(coins: number): void {\n this.adapter.gameOver(coins);\n }\n collectStamp(stamp: number): void {\n this.adapter.collectStamp(stamp);\n }\n\n sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n disconnect(): void {\n this.log?.(\"[disconnect] closing connection\");\n this.adapter.disconnect();\n this.cleanup();\n }\n\n private cleanup(): void {\n this.connected = false;\n this.player = null;\n this.room = null;\n this.users.clear();\n }\n\n private handleMessage(msg: MessagePayload): void {\n const { action, args } = msg;\n\n switch (action) {\n case \"load_player\": {\n const user = args.user as PlayerData;\n user.coins = (args.coins as number) ?? 0;\n user.inventory = (args.inventory as number[]) ?? [];\n user.furniture = (args.furniture as unknown[]) ?? [];\n user.flooring = (args.flooring as unknown[]) ?? [];\n user.rank = (args.rank as number) ?? 0;\n this.player = user;\n this.log?.(\n \"[load_player]\",\n user.username,\n `id=${user.id}`,\n `coins=${user.coins}`,\n `inventory=${user.inventory.length}`,\n );\n break;\n }\n case \"join_room\": {\n const room = args.room as number;\n const users = args.users as RoomUser[];\n this.room = room;\n this.users.clear();\n for (const user of users) {\n this.users.set(user.id, user);\n }\n this.log?.(\"[join_room]\", `room=${room}`, `users=${users.length}`);\n break;\n }\n case \"add_player\": {\n const user = args.user as RoomUser;\n this.users.set(user.id, user);\n this.log?.(\"[add_player]\", user.username, `id=${user.id}`);\n break;\n }\n case \"remove_player\": {\n const id = args.user as number;\n this.users.delete(id);\n this.log?.(\"[remove_player]\", `id=${id}`);\n break;\n }\n case \"send_position\": {\n const id = args.id as number;\n const user = this.users.get(id);\n if (user) {\n user.x = args.x as number;\n user.y = args.y as number;\n }\n break;\n }\n case \"send_frame\": {\n const id = args.id as number;\n const user = this.users.get(id);\n if (user) {\n user.frame = args.frame as number;\n }\n break;\n }\n case \"update_player\": {\n const id = args.id as number;\n const slot = args.slot as string;\n const item = args.item as number;\n const user = this.users.get(id);\n if (user && slot in user) {\n (user as Record<string, unknown>)[slot] = item;\n }\n break;\n }\n case \"kick\": {\n const reason = (args as { reason?: string }).reason ?? \"unknown\";\n this.log?.(\"[kick]\", reason);\n this.cleanup();\n break;\n }\n case \"close_with_error\": {\n const error = (args as { error?: string }).error ?? \"unknown\";\n this.log?.(\"[kick]\", error);\n this.cleanup();\n break;\n }\n default: {\n this.log?.(`[${action}]`, JSON.stringify(args));\n break;\n }\n }\n\n const eventName = action === \"error\" ? \"server_error\" : action;\n this.emit(eventName, args);\n }\n}\n","import { io, type Socket } from \"socket.io-client\";\nimport msgpackParser from \"socket.io-msgpack-parser\";\nimport type {\n LoginOptions,\n LoginResult,\n QueueUpdate,\n ServerInfo,\n TokenLoginOptions,\n} from \"../types/adapter-types.js\";\nimport { BaseAdapter, type ConnectOptions } from \"./base-adapter.js\";\n\nconst BASE_URL = \"wss://play.cpjourney.net\";\nconst DEFAULT_SECRET = \"skip\";\n\ntype LoginResponse = {\n success: boolean;\n username: string;\n key: string;\n populations: Record<string, number>;\n moderator: boolean;\n buddyWorlds: string[];\n};\n\ntype GameAuthResponse = {\n success: boolean;\n token?: string;\n};\n\ntype ServerMessage = {\n action: string;\n args: Record<string, unknown>;\n};\n\nexport class CpjourneyAdapter extends BaseAdapter {\n readonly id = \"CPJourney\";\n\n async login(options: LoginOptions | TokenLoginOptions): Promise<LoginResult> {\n const loginSocket = this.createSocket(\"/world/login/\");\n\n const result = await new Promise<LoginResult>((resolve, reject) => {\n const timeout = setTimeout(() => {\n loginSocket.disconnect();\n reject(new Error(\"Login timed out\"));\n }, 10_000);\n\n loginSocket.on(\"connect\", () => {\n const secret = options.secret ?? DEFAULT_SECRET;\n const args =\n \"token\" in options\n ? { username: options.username, token: options.token, secret }\n : {\n username: options.username,\n password: options.password,\n secret,\n };\n\n loginSocket.emit(\"message\", { action: \"login\", args });\n });\n\n loginSocket.on(\"message\", (msg: ServerMessage) => {\n if (msg.action !== \"login\") return;\n\n clearTimeout(timeout);\n loginSocket.disconnect();\n\n const response = msg.args as LoginResponse;\n\n if (!response.success) {\n reject(new Error(\"Login failed\"));\n return;\n }\n\n const servers: ServerInfo[] = Object.entries(response.populations).map(\n ([name, population]) => ({ name, population }),\n );\n\n resolve({\n servers,\n key: response.key,\n username: response.username,\n moderator: response.moderator,\n buddyWorlds: response.buddyWorlds ?? [],\n });\n });\n\n loginSocket.on(\"connect_error\", (err: Error) => {\n clearTimeout(timeout);\n loginSocket.disconnect();\n reject(new Error(`Login connection failed: ${err.message}`));\n });\n });\n\n return result;\n }\n\n async connect(\n serverName: string,\n loginResult: LoginResult,\n options?: ConnectOptions,\n ): Promise<Socket> {\n const gameSocket = this.createSocket(`/world/${serverName.toLowerCase()}/`);\n this.socket = gameSocket;\n\n await new Promise<void>((resolve, reject) => {\n let authSent = false;\n\n gameSocket.on(\"connect\", () => {\n gameSocket.emit(\"message\", {\n action: \"game_auth\",\n args: {\n username: loginResult.username,\n key: loginResult.key,\n createToken: false,\n joinInvis: false,\n takeoverMascot: false,\n token: \"\",\n },\n });\n });\n\n gameSocket.on(\"message\", (msg: ServerMessage) => {\n switch (msg.action) {\n case \"wait_queue_update\": {\n options?.onQueueUpdate?.(msg.args as QueueUpdate);\n break;\n }\n case \"game_auth\": {\n if (authSent) break;\n authSent = true;\n\n const response = msg.args as GameAuthResponse;\n if (!response.success) {\n gameSocket.disconnect();\n reject(new Error(\"Game auth failed\"));\n return;\n }\n\n gameSocket.emit(\"message\", { action: \"join_server\", args: {} });\n resolve();\n break;\n }\n }\n });\n\n gameSocket.on(\"connect_error\", (err: Error) => {\n gameSocket.disconnect();\n reject(new Error(`Game connection failed: ${err.message}`));\n });\n });\n\n return gameSocket;\n }\n\n send(action: string, args: Record<string, unknown>): void {\n if (!this.socket) throw new Error(\"Not connected\");\n this.socket.emit(\"message\", { action, args });\n }\n\n disconnect(): void {\n this.socket?.disconnect();\n this.socket = null;\n }\n\n private createSocket(path: string): Socket {\n return io(BASE_URL, {\n path,\n parser: msgpackParser,\n transports: [\"polling\", \"websocket\"],\n reconnection: false,\n });\n }\n}\n","import { io, type Socket } from \"socket.io-client\";\nimport msgpackParser from \"socket.io-msgpack-parser\";\nimport type {\n LoginOptions,\n LoginResult,\n QueueUpdate,\n ServerInfo,\n TokenLoginOptions,\n} from \"../types/adapter-types.js\";\nimport { BaseAdapter, type ConnectOptions } from \"./base-adapter.js\";\n\nconst LOGIN_URL = \"https://api.cplegacy.com/login\";\nconst TOKEN_LOGIN_URL = \"https://api.cplegacy.com/token_login\";\n\ntype LoginResponse = {\n success: boolean;\n username: string;\n key: string;\n populations: Record<string, number>;\n requires2FA: boolean;\n message?: string;\n wantedVersion?: string;\n};\n\ntype GameAuthResponse = {\n success: boolean;\n};\n\n/**\n * Wraps a CPLegacy socket to normalize its positional message format\n * `(\"message\", action, args)` into the `{ action, args }` envelope\n * that the Client class expects.\n */\nfunction wrapSocket(raw: Socket): Socket {\n const original = raw.on.bind(raw);\n\n raw.on = ((event: string, listener: (...args: unknown[]) => void) => {\n if (event === \"message\") {\n return original(event, (action: unknown, args: unknown) => {\n listener({ action, args: args ?? {} });\n });\n }\n return original(event, listener);\n }) as typeof raw.on;\n\n return raw;\n}\n\nexport class CplegacyAdapter extends BaseAdapter {\n readonly id = \"CPLegacy\";\n private version = \"\";\n\n async login(options: LoginOptions | TokenLoginOptions): Promise<LoginResult> {\n const url = \"token\" in options ? TOKEN_LOGIN_URL : LOGIN_URL;\n const body: Record<string, unknown> =\n \"token\" in options\n ? { username: options.username, token: options.token }\n : {\n username: options.username,\n password: options.password,\n version: this.version,\n };\n\n let data = await this.postLogin(url, body);\n\n // Version negotiation: server returns wantedVersion when ours is stale/empty\n if (!data.success && data.wantedVersion) {\n this.version = data.wantedVersion;\n body.version = this.version;\n data = await this.postLogin(url, body);\n }\n\n if (!data.success) {\n throw new Error(`Login failed: ${data.message ?? \"unknown error\"}`);\n }\n\n const servers: ServerInfo[] = Object.entries(data.populations ?? {}).map(\n ([name, population]) => ({ name, population }),\n );\n\n return {\n servers,\n key: data.key,\n username: data.username,\n moderator: false,\n buddyWorlds: [],\n };\n }\n\n async connect(\n serverName: string,\n loginResult: LoginResult,\n options?: ConnectOptions,\n ): Promise<Socket> {\n const wsUrl = `wss://${serverName.toLowerCase()}.server.cplegacy.com`;\n const rawSocket = io(wsUrl, {\n path: \"/socket.io/\",\n parser: msgpackParser,\n transports: [\"websocket\"],\n reconnection: false,\n });\n this.socket = rawSocket;\n\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n rawSocket.disconnect();\n reject(new Error(\"Game connection timed out\"));\n }, 15_000);\n\n rawSocket.on(\"connect\", () => {\n rawSocket.emit(\"message\", \"game_auth\", {\n username: loginResult.username,\n key: loginResult.key,\n createToken: false,\n token: \"\",\n });\n });\n\n rawSocket.on(\n \"message\",\n (action: string, args: Record<string, unknown>) => {\n switch (action) {\n case \"wait_queue_update\": {\n options?.onQueueUpdate?.(args as unknown as QueueUpdate);\n break;\n }\n case \"game_auth\": {\n const response = args as unknown as GameAuthResponse;\n if (!response.success) {\n clearTimeout(timeout);\n rawSocket.disconnect();\n reject(new Error(\"Game auth failed\"));\n return;\n }\n\n // CPLegacy requires explicitly requesting load_player before join_server\n rawSocket.emit(\"message\", \"load_player\", {});\n rawSocket.emit(\"message\", \"join_server\", {});\n clearTimeout(timeout);\n resolve();\n break;\n }\n }\n },\n );\n\n rawSocket.on(\"connect_error\", (err: Error) => {\n clearTimeout(timeout);\n rawSocket.disconnect();\n reject(new Error(`Game connection failed: ${err.message}`));\n });\n });\n\n // Return wrapped socket so Client receives normalized { action, args } messages\n return wrapSocket(rawSocket);\n }\n\n send(action: string, args: Record<string, unknown>): void {\n if (!this.socket) throw new Error(\"Not connected\");\n this.socket.emit(\"message\", action, args);\n }\n\n disconnect(): void {\n this.socket?.disconnect();\n this.socket = null;\n }\n\n private async postLogin(\n url: string,\n body: Record<string, unknown>,\n ): Promise<LoginResponse> {\n const resp = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n },\n body: JSON.stringify(body),\n });\n\n return resp.json() as Promise<LoginResponse>;\n }\n}\n","import { createCipheriv, createDecipheriv, randomBytes } from \"node:crypto\";\nimport { io, type Socket } from \"socket.io-client\";\nimport nacl from \"tweetnacl\";\nimport type {\n LoginOptions,\n LoginResult,\n QueueUpdate,\n ServerInfo,\n TokenLoginOptions,\n} from \"../types/adapter-types.js\";\nimport { BaseAdapter, type ConnectOptions } from \"./base-adapter.js\";\n\nconst CRUMBS_URL =\n \"https://media8.newcp.net/assets/media/crumbs/en/crumbs.json\";\n\ntype WorldConfig = {\n id?: number;\n host: string;\n path: string;\n login?: boolean;\n};\n\ntype CrumbsWorlds = Record<string, WorldConfig>;\n\ntype LoginResponse = {\n success: boolean;\n username: string;\n key: string;\n populations: Record<string, number>;\n moderator: boolean;\n buddyWorlds: string[];\n};\n\ntype GameAuthResponse = {\n success: boolean;\n token?: string;\n};\n\nclass Encryptor {\n private aesKey: Buffer | null = null;\n private keypair = nacl.box.keyPair();\n\n get publicKey(): string {\n return Buffer.from(this.keypair.publicKey).toString(\"base64\");\n }\n\n get encrypted(): boolean {\n return this.aesKey !== null;\n }\n\n acquireKey(encryptedB64: string, serverPubKeyB64: string): string | null {\n const data = Buffer.from(encryptedB64, \"base64\");\n const serverPubKey = Buffer.from(serverPubKeyB64, \"base64\");\n const nonce = data.subarray(0, nacl.box.nonceLength);\n const ciphertext = data.subarray(nacl.box.nonceLength);\n const plaintext = nacl.box.open(\n new Uint8Array(ciphertext),\n new Uint8Array(nonce),\n new Uint8Array(serverPubKey),\n this.keypair.secretKey,\n );\n return plaintext ? new TextDecoder().decode(plaintext) : null;\n }\n\n setKey(keyString: string): void {\n this.aesKey = Buffer.from(keyString, \"utf-8\");\n }\n\n encrypt(plaintext: string): string {\n if (!this.aesKey) throw new Error(\"Encryption key not set\");\n const iv = randomBytes(16);\n const cipher = createCipheriv(\"aes-256-cbc\", this.aesKey, iv);\n const encrypted = Buffer.concat([\n cipher.update(plaintext, \"utf-8\"),\n cipher.final(),\n ]);\n const result = Buffer.concat([iv, encrypted]);\n return result.toString(\"base64\");\n }\n\n decrypt(data: string): string {\n if (!this.aesKey) throw new Error(\"Encryption key not set\");\n const buf = Buffer.from(data, \"base64\");\n const iv = buf.subarray(0, 16);\n const ciphertext = buf.subarray(16);\n const decipher = createDecipheriv(\"aes-256-cbc\", this.aesKey, iv);\n return Buffer.concat([\n decipher.update(ciphertext),\n decipher.final(),\n ]).toString(\"utf-8\");\n }\n\n encode(data: Record<string, unknown>): string {\n return this.encrypted\n ? this.encrypt(JSON.stringify(data))\n : JSON.stringify(data);\n }\n\n decode(data: unknown): Record<string, unknown> {\n if (this.encrypted && typeof data === \"string\") {\n return JSON.parse(this.decrypt(data)) as Record<string, unknown>;\n }\n return typeof data === \"string\"\n ? (JSON.parse(data) as Record<string, unknown>)\n : (data as Record<string, unknown>);\n }\n}\n\nfunction performHandshake(socket: Socket, encryptor: Encryptor): Promise<void> {\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(\"Handshake timed out\"));\n }, 10_000);\n\n socket.once(\n \"handshake\",\n (encryptedKey: string, serverPubKeyB64: string) => {\n clearTimeout(timeout);\n const raw = encryptor.acquireKey(encryptedKey, serverPubKeyB64);\n if (!raw) {\n reject(new Error(\"Failed to decrypt handshake key\"));\n return;\n }\n\n const parsed = JSON.parse(raw) as { key: string; time?: number };\n if (\n parsed.time &&\n typeof parsed.time === \"number\" &&\n Math.abs(Date.now() - parsed.time) > 300_000\n ) {\n reject(new Error(\"Server time desync\"));\n return;\n }\n\n encryptor.setKey(parsed.key);\n resolve();\n },\n );\n\n socket.emit(\"handshake\", encryptor.publicKey);\n });\n}\n\n/**\n * Wraps a NewCP socket to decrypt incoming messages into the\n * `{ action, args }` envelope that the Client class expects.\n */\nfunction wrapSocket(raw: Socket, encryptor: Encryptor): Socket {\n const original = raw.on.bind(raw);\n\n raw.on = ((event: string, listener: (...args: unknown[]) => void) => {\n if (event === \"message\") {\n return original(event, (msg: unknown) => {\n try {\n const decoded = encryptor.decode(msg);\n listener({ action: decoded.action, args: decoded.args ?? {} });\n } catch {\n // Skip malformed messages\n }\n });\n }\n return original(event, listener);\n }) as typeof raw.on;\n\n return raw;\n}\n\nexport class NewcpAdapter extends BaseAdapter {\n readonly id = \"NewCP\";\n private encryptor = new Encryptor();\n private worlds: CrumbsWorlds | null = null;\n\n async login(options: LoginOptions | TokenLoginOptions): Promise<LoginResult> {\n if (!this.worlds) {\n await this.loadWorlds();\n }\n\n const loginWorld = Object.values(this.worlds ?? {}).find((w) => w.login);\n if (!loginWorld) throw new Error(\"Login world not found in crumbs\");\n\n const loginSocket = this.createSocket(loginWorld.host, loginWorld.path);\n this.encryptor = new Encryptor();\n\n const result = await new Promise<LoginResult>((resolve, reject) => {\n const timeout = setTimeout(() => {\n loginSocket.disconnect();\n reject(new Error(\"Login timed out\"));\n }, 15_000);\n\n loginSocket.on(\"connect\", async () => {\n try {\n await performHandshake(loginSocket, this.encryptor);\n\n const args =\n \"token\" in options\n ? { username: options.username, token: options.token }\n : { username: options.username, password: options.password };\n\n const encrypted = this.encryptor.encode({ action: \"login\", args });\n loginSocket.emit(\"message\", encrypted);\n } catch (err) {\n clearTimeout(timeout);\n loginSocket.disconnect();\n reject(err);\n }\n });\n\n loginSocket.on(\"message\", (msg: unknown) => {\n try {\n const decoded = this.encryptor.decode(msg);\n if (decoded.action !== \"login\") return;\n\n clearTimeout(timeout);\n loginSocket.disconnect();\n\n const response = decoded.args as unknown as LoginResponse;\n\n if (!response.success) {\n reject(new Error(\"Login failed\"));\n return;\n }\n\n const servers: ServerInfo[] = Object.entries(\n response.populations ?? {},\n ).map(([name, population]) => ({ name, population }));\n\n resolve({\n servers,\n key: response.key,\n username: response.username,\n moderator: response.moderator ?? false,\n buddyWorlds: response.buddyWorlds ?? [],\n });\n } catch (err) {\n clearTimeout(timeout);\n loginSocket.disconnect();\n reject(err);\n }\n });\n\n loginSocket.on(\"connect_error\", (err: Error) => {\n clearTimeout(timeout);\n loginSocket.disconnect();\n reject(new Error(`Login connection failed: ${err.message}`));\n });\n });\n\n return result;\n }\n\n async connect(\n serverName: string,\n loginResult: LoginResult,\n options?: ConnectOptions,\n ): Promise<Socket> {\n if (!this.worlds) {\n await this.loadWorlds();\n }\n\n const worldConfig = this.worlds?.[serverName];\n if (!worldConfig)\n throw new Error(`World config not found for: ${serverName}`);\n\n this.encryptor = new Encryptor();\n const gameSocket = this.createSocket(worldConfig.host, worldConfig.path);\n this.socket = gameSocket;\n\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n gameSocket.disconnect();\n reject(new Error(\"Game connection timed out\"));\n }, 15_000);\n\n gameSocket.on(\"connect\", async () => {\n try {\n await performHandshake(gameSocket, this.encryptor);\n\n const encrypted = this.encryptor.encode({\n action: \"game_auth\",\n args: {\n username: loginResult.username,\n key: loginResult.key,\n createToken: false,\n },\n });\n gameSocket.emit(\"message\", encrypted);\n } catch (err) {\n clearTimeout(timeout);\n gameSocket.disconnect();\n reject(err);\n }\n });\n\n gameSocket.on(\"message\", (msg: unknown) => {\n try {\n const decoded = this.encryptor.decode(msg);\n\n switch (decoded.action) {\n case \"wait_queue_update\": {\n options?.onQueueUpdate?.(decoded.args as unknown as QueueUpdate);\n break;\n }\n case \"game_auth\": {\n const response = decoded.args as unknown as GameAuthResponse;\n if (!response.success) {\n clearTimeout(timeout);\n gameSocket.disconnect();\n reject(new Error(\"Game auth failed\"));\n return;\n }\n\n const joinEncrypted = this.encryptor.encode({\n action: \"join_server\",\n args: {},\n });\n gameSocket.emit(\"message\", joinEncrypted);\n clearTimeout(timeout);\n resolve();\n break;\n }\n }\n } catch {\n // Ignore decode errors during auth phase\n }\n });\n\n gameSocket.on(\"connect_error\", (err: Error) => {\n clearTimeout(timeout);\n gameSocket.disconnect();\n reject(new Error(`Game connection failed: ${err.message}`));\n });\n });\n\n return wrapSocket(gameSocket, this.encryptor);\n }\n\n send(action: string, args: Record<string, unknown>): void {\n if (!this.socket) throw new Error(\"Not connected\");\n const encrypted = this.encryptor.encode({ action, args });\n this.socket.emit(\"message\", encrypted);\n }\n\n disconnect(): void {\n this.socket?.disconnect();\n this.socket = null;\n }\n\n private createSocket(host: string, path: string): Socket {\n return io(host, {\n path,\n transports: [\"polling\", \"websocket\"],\n reconnection: false,\n });\n }\n\n private async loadWorlds(): Promise<void> {\n const resp = await fetch(CRUMBS_URL);\n if (!resp.ok) throw new Error(`Failed to fetch crumbs: ${resp.status}`);\n const crumbs = (await resp.json()) as { worlds: CrumbsWorlds };\n this.worlds = crumbs.worlds;\n }\n}\n","import type { BaseAdapter } from \"./base-adapter.js\";\nimport { CpjourneyAdapter } from \"./cpjourney-adapter.js\";\nimport { CplegacyAdapter } from \"./cplegacy-adapter.js\";\nimport { NewcpAdapter } from \"./newcp-adapter.js\";\n\nconst ADAPTERS = {\n CPJourney: CpjourneyAdapter,\n CPLegacy: CplegacyAdapter,\n NewCP: NewcpAdapter,\n} as const;\n\nexport type AdapterName = keyof typeof ADAPTERS;\n\nexport function createAdapter(name: AdapterName): BaseAdapter {\n return new ADAPTERS[name]();\n}\n"],"mappings":"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","names":["BaseAdapter","message","emote","safe","x","y","frame","set","room","item","id","type","userId","cardId","igloo","coins","stamp","EventEmitter","io","msgpackParser","BASE_URL","DEFAULT_SECRET","CpjourneyAdapter","BaseAdapter","options","loginSocket","resolve","reject","timeout","secret","args","msg","response","servers","name","population","err","serverName","loginResult","gameSocket","authSent","action","path","io","msgpackParser","io","msgpackParser","LOGIN_URL","TOKEN_LOGIN_URL","wrapSocket","raw","original","event","listener","action","args","CplegacyAdapter","BaseAdapter","options","url","body","data","name","population","serverName","loginResult","wsUrl","rawSocket","io","msgpackParser","resolve","reject","timeout","err","createCipheriv","createDecipheriv","randomBytes","io","nacl","CRUMBS_URL","Encryptor","nacl","encryptedB64","serverPubKeyB64","data","serverPubKey","nonce","ciphertext","plaintext","keyString","iv","randomBytes","cipher","createCipheriv","encrypted","buf","decipher","createDecipheriv","performHandshake","socket","encryptor","resolve","reject","timeout","encryptedKey","raw","parsed","wrapSocket","original","event","listener","msg","decoded","NewcpAdapter","BaseAdapter","options","loginWorld","w","loginSocket","args","err","response","servers","name","population","serverName","loginResult","worldConfig","gameSocket","joinEncrypted","action","host","path","io","resp","crumbs","ADAPTERS","CpjourneyAdapter","CplegacyAdapter","NewcpAdapter","createAdapter","name","isMessagePayload","msg","Client","EventEmitter","server","options","createAdapter","serverName","connectOptions","update","socket","resolve","reject","timeout","playerLoaded","roomJoined","checkReady","onMessage","onDisconnect","event","listener","args","message","emote","safe","x","y","frame","set","room","item","id","type","userId","cardId","igloo","coins","stamp","ms","action","user","users","slot","reason","error","eventName"]}
1
+ {"version":3,"sources":["../src/adapters/base-adapter.ts","../src/client.ts","../src/adapters/cpjourney-adapter.ts","../src/adapters/cplegacy-adapter.ts","../src/adapters/newcp-adapter.ts","../src/adapters/index.ts"],"sourcesContent":["import type { Socket } from \"socket.io-client\";\nimport type {\n LoginOptions,\n LoginResult,\n QueueUpdate,\n TokenLoginOptions,\n} from \"../types/adapter-types.js\";\nimport type {\n PlayerAppearance,\n PlayerData,\n RoomUser,\n} from \"../types/player-types.js\";\n\nexport type ConnectOptions = {\n onQueueUpdate?: (update: QueueUpdate) => void;\n};\n\nexport abstract class BaseAdapter {\n abstract readonly id: string;\n protected socket: Socket | null = null;\n\n abstract login(\n options: LoginOptions | TokenLoginOptions,\n ): Promise<LoginResult>;\n abstract connect(\n serverName: string,\n loginResult: LoginResult,\n options?: ConnectOptions,\n ): Promise<Socket>;\n abstract disconnect(): void;\n abstract send(action: string, args: Record<string, unknown>): void;\n\n normalizeUser(_raw: Record<string, unknown>): RoomUser {\n throw new Error(\"Not implemented: normalizeUser\");\n }\n\n normalizePlayer(_raw: Record<string, unknown>): PlayerData {\n throw new Error(\"Not implemented: normalizePlayer\");\n }\n\n protected extractAppearance(raw: Record<string, unknown>): PlayerAppearance {\n return {\n color: (raw.color as number) ?? 0,\n head: (raw.head as number) ?? 0,\n face: (raw.face as number) ?? 0,\n neck: (raw.neck as number) ?? 0,\n body: (raw.body as number) ?? 0,\n hand: (raw.hand as number) ?? 0,\n feet: (raw.feet as number) ?? 0,\n flag: (raw.flag as number) ?? 0,\n photo: (raw.photo as number) ?? 0,\n };\n }\n\n sendMessage(_message: string): void {\n throw new Error(\"Not implemented: sendMessage\");\n }\n\n sendEmote(_emote: number): void {\n throw new Error(\"Not implemented: sendEmote\");\n }\n\n sendSafe(_safe: number): void {\n throw new Error(\"Not implemented: sendSafe\");\n }\n\n walk(_x: number, _y: number): void {\n throw new Error(\"Not implemented: walk\");\n }\n\n sendFrame(_frame: number, _set?: boolean): void {\n throw new Error(\"Not implemented: sendFrame\");\n }\n\n snowball(_x: number, _y: number): void {\n throw new Error(\"Not implemented: snowball\");\n }\n\n joinRoom(_room: number, _x?: number, _y?: number): void {\n throw new Error(\"Not implemented: joinRoom\");\n }\n\n addItem(_item: number): void {\n throw new Error(\"Not implemented: addItem\");\n }\n\n equipColor(_item: number): void {\n throw new Error(\"Not implemented: equipColor\");\n }\n\n equipHead(_item: number): void {\n throw new Error(\"Not implemented: equipHead\");\n }\n\n equipFace(_item: number): void {\n throw new Error(\"Not implemented: equipFace\");\n }\n\n equipNeck(_item: number): void {\n throw new Error(\"Not implemented: equipNeck\");\n }\n\n equipBody(_item: number): void {\n throw new Error(\"Not implemented: equipBody\");\n }\n\n equipHand(_item: number): void {\n throw new Error(\"Not implemented: equipHand\");\n }\n\n equipFeet(_item: number): void {\n throw new Error(\"Not implemented: equipFeet\");\n }\n\n equipFlag(_item: number): void {\n throw new Error(\"Not implemented: equipFlag\");\n }\n\n equipPhoto(_item: number): void {\n throw new Error(\"Not implemented: equipPhoto\");\n }\n\n buddyRequest(_id: number): void {\n throw new Error(\"Not implemented: buddyRequest\");\n }\n\n buddyAccept(_id: number): void {\n throw new Error(\"Not implemented: buddyAccept\");\n }\n\n buddyReject(_id: number): void {\n throw new Error(\"Not implemented: buddyReject\");\n }\n\n buddyRequestSeen(_id: number): void {\n throw new Error(\"Not implemented: buddyRequestSeen\");\n }\n\n getBuddy(_id: number, _type: \"buddies\" | \"buddyRequests\"): void {\n throw new Error(\"Not implemented: getBuddy\");\n }\n\n removeBuddy(_id: number): void {\n throw new Error(\"Not implemented: removeBuddy\");\n }\n\n addIgnore(_id: number): void {\n throw new Error(\"Not implemented: addIgnore\");\n }\n\n removeIgnore(_id: number): void {\n throw new Error(\"Not implemented: removeIgnore\");\n }\n\n getPlayer(_id: number): void {\n throw new Error(\"Not implemented: getPlayer\");\n }\n\n getAllSlots(): void {\n throw new Error(\"Not implemented: getAllSlots\");\n }\n\n getMascots(): void {\n throw new Error(\"Not implemented: getMascots\");\n }\n\n sendPostcard(_userId: number, _cardId: string): void {\n throw new Error(\"Not implemented: sendPostcard\");\n }\n\n getStamps(_userId: number): void {\n throw new Error(\"Not implemented: getStamps\");\n }\n\n getPostcards(): void {\n throw new Error(\"Not implemented: getPostcards\");\n }\n\n getIglooOpen(_igloo: number): void {\n throw new Error(\"Not implemented: getIglooOpen\");\n }\n\n joinIgloo(_igloo: number, _x?: number, _y?: number): void {\n throw new Error(\"Not implemented: joinIgloo\");\n }\n\n gameOver(_coins: number): void {\n throw new Error(\"Not implemented: gameOver\");\n }\n\n collectStamp(_stamp: number): void {\n throw new Error(\"Not implemented: collectStamp\");\n }\n}\n","import { EventEmitter } from \"node:events\";\nimport type { BaseAdapter, ConnectOptions } from \"./adapters/base-adapter.js\";\nimport { type AdapterName, createAdapter } from \"./adapters/index.js\";\nimport type {\n LoginOptions,\n LoginResult,\n QueueUpdate,\n ServerInfo,\n TokenLoginOptions,\n} from \"./types/adapter-types.js\";\nimport type { ServerMessages } from \"./types/message-types.js\";\nimport type { PlayerData, RoomUser } from \"./types/player-types.js\";\n\ntype ServerMessageHandler<K extends keyof ServerMessages> = (\n args: ServerMessages[K],\n) => void;\n\nexport type LogFn = (message: string, ...args: unknown[]) => void;\n\nexport type ClientOptions = {\n debug?: boolean | LogFn;\n};\n\ntype MessagePayload = {\n action: string;\n args: Record<string, unknown>;\n};\n\nfunction isMessagePayload(msg: unknown): msg is MessagePayload {\n return (\n typeof msg === \"object\" && msg !== null && \"action\" in msg && \"args\" in msg\n );\n}\n\nexport class Client extends EventEmitter {\n player: PlayerData | null = null;\n room: number | null = null;\n users: Map<number, RoomUser> = new Map();\n connected = false;\n\n private adapter: BaseAdapter;\n private loginResult: LoginResult | null = null;\n private log: LogFn | null = null;\n\n constructor(server: AdapterName, options?: ClientOptions) {\n super();\n this.adapter = createAdapter(server);\n\n if (options?.debug) {\n this.log =\n typeof options.debug === \"function\"\n ? options.debug\n : console.log.bind(console);\n }\n }\n\n async login(\n options: LoginOptions | TokenLoginOptions,\n ): Promise<ServerInfo[]> {\n this.log?.(\"[login] logging in as\", options.username);\n this.loginResult = await this.adapter.login(options);\n this.log?.(\"[login] success —\", this.loginResult.servers.length, \"servers\");\n return this.loginResult.servers;\n }\n\n async connect(serverName: string, options?: ConnectOptions): Promise<void> {\n if (!this.loginResult) throw new Error(\"Must call login() first\");\n\n this.log?.(\"[connect] joining\", serverName);\n\n const connectOptions: ConnectOptions = {\n ...options,\n onQueueUpdate: (update: QueueUpdate) => {\n this.log?.(\"[queue]\", `#${update.position}/${update.queueLength}`);\n this.emit(\"wait_queue_update\", update);\n options?.onQueueUpdate?.(update);\n },\n };\n\n const socket = await this.adapter.connect(\n serverName,\n this.loginResult,\n connectOptions,\n );\n\n socket.on(\"message\", (msg: unknown) => {\n if (!isMessagePayload(msg)) return;\n this.handleMessage(msg);\n });\n\n socket.on(\"disconnect\", () => {\n this.log?.(\"[disconnect] connection lost\");\n this.cleanup();\n this.emit(\"disconnect\");\n });\n\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(\"Waiting for load_player timed out\"));\n }, 10_000);\n\n let playerLoaded = false;\n let roomJoined = false;\n\n const checkReady = (): void => {\n if (playerLoaded && roomJoined) {\n clearTimeout(timeout);\n this.connected = true;\n resolve();\n }\n };\n\n const onMessage = (msg: unknown): void => {\n if (!isMessagePayload(msg)) return;\n switch (msg.action) {\n case \"load_player\":\n playerLoaded = true;\n checkReady();\n break;\n case \"join_room\":\n roomJoined = true;\n checkReady();\n break;\n case \"kick\":\n clearTimeout(timeout);\n socket.off(\"message\", onMessage);\n reject(\n new Error(\n `Kicked: ${(msg.args as { reason?: string }).reason ?? \"unknown\"}`,\n ),\n );\n break;\n case \"close_with_error\":\n clearTimeout(timeout);\n socket.off(\"message\", onMessage);\n reject(\n new Error(\n `Kicked: ${(msg.args as { error?: string }).error ?? \"unknown\"}`,\n ),\n );\n break;\n case \"error\":\n clearTimeout(timeout);\n socket.off(\"message\", onMessage);\n reject(\n new Error(\n `Server error: ${(msg.args as { error?: string | number }).error ?? \"unknown\"}`,\n ),\n );\n break;\n }\n };\n\n const onDisconnect = (): void => {\n if (!playerLoaded || !roomJoined) {\n clearTimeout(timeout);\n reject(new Error(\"Disconnected before fully loaded\"));\n }\n };\n\n socket.on(\"message\", onMessage);\n socket.once(\"disconnect\", onDisconnect);\n });\n }\n\n on<K extends keyof ServerMessages>(\n event: K,\n listener: ServerMessageHandler<K>,\n ): this;\n on(event: string, listener: (...args: unknown[]) => void): this;\n on(event: string, listener: (...args: unknown[]) => void): this {\n return super.on(event, listener);\n }\n\n off<K extends keyof ServerMessages>(\n event: K,\n listener: ServerMessageHandler<K>,\n ): this;\n off(event: string, listener: (...args: unknown[]) => void): this;\n off(event: string, listener: (...args: unknown[]) => void): this {\n return super.off(event, listener);\n }\n\n once<K extends keyof ServerMessages>(\n event: K,\n listener: ServerMessageHandler<K>,\n ): this;\n once(event: string, listener: (...args: unknown[]) => void): this;\n once(event: string, listener: (...args: unknown[]) => void): this {\n return super.once(event, listener);\n }\n\n emit<K extends keyof ServerMessages>(\n event: K,\n args: ServerMessages[K],\n ): boolean;\n emit(event: string, ...args: unknown[]): boolean;\n emit(event: string, ...args: unknown[]): boolean {\n return super.emit(event, ...args);\n }\n\n sendMessage(message: string): void {\n this.adapter.sendMessage(message);\n }\n sendEmote(emote: number): void {\n this.adapter.sendEmote(emote);\n }\n sendSafe(safe: number): void {\n this.adapter.sendSafe(safe);\n }\n walk(x: number, y: number): void {\n this.adapter.walk(x, y);\n }\n sendFrame(frame: number, set?: boolean): void {\n this.adapter.sendFrame(frame, set);\n }\n snowball(x: number, y: number): void {\n this.adapter.snowball(x, y);\n }\n joinRoom(room: number, x?: number, y?: number): void {\n this.adapter.joinRoom(room, x, y);\n }\n addItem(item: number): void {\n this.adapter.addItem(item);\n }\n equipColor(item: number): void {\n this.adapter.equipColor(item);\n }\n equipHead(item: number): void {\n this.adapter.equipHead(item);\n }\n equipFace(item: number): void {\n this.adapter.equipFace(item);\n }\n equipNeck(item: number): void {\n this.adapter.equipNeck(item);\n }\n equipBody(item: number): void {\n this.adapter.equipBody(item);\n }\n equipHand(item: number): void {\n this.adapter.equipHand(item);\n }\n equipFeet(item: number): void {\n this.adapter.equipFeet(item);\n }\n equipFlag(item: number): void {\n this.adapter.equipFlag(item);\n }\n equipPhoto(item: number): void {\n this.adapter.equipPhoto(item);\n }\n buddyRequest(id: number): void {\n this.adapter.buddyRequest(id);\n }\n buddyAccept(id: number): void {\n this.adapter.buddyAccept(id);\n }\n buddyReject(id: number): void {\n this.adapter.buddyReject(id);\n }\n buddyRequestSeen(id: number): void {\n this.adapter.buddyRequestSeen(id);\n }\n getBuddy(id: number, type: \"buddies\" | \"buddyRequests\"): void {\n this.adapter.getBuddy(id, type);\n }\n removeBuddy(id: number): void {\n this.adapter.removeBuddy(id);\n }\n addIgnore(id: number): void {\n this.adapter.addIgnore(id);\n }\n removeIgnore(id: number): void {\n this.adapter.removeIgnore(id);\n }\n getPlayer(id: number): void {\n this.adapter.getPlayer(id);\n }\n getAllSlots(): void {\n this.adapter.getAllSlots();\n }\n getMascots(): void {\n this.adapter.getMascots();\n }\n sendPostcard(userId: number, cardId: string): void {\n this.adapter.sendPostcard(userId, cardId);\n }\n getStamps(userId: number): void {\n this.adapter.getStamps(userId);\n }\n getPostcards(): void {\n this.adapter.getPostcards();\n }\n getIglooOpen(igloo: number): void {\n this.adapter.getIglooOpen(igloo);\n }\n joinIgloo(igloo: number, x?: number, y?: number): void {\n this.adapter.joinIgloo(igloo, x, y);\n }\n gameOver(coins: number): void {\n this.adapter.gameOver(coins);\n }\n collectStamp(stamp: number): void {\n this.adapter.collectStamp(stamp);\n }\n\n sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n disconnect(): void {\n this.log?.(\"[disconnect] closing connection\");\n this.adapter.disconnect();\n this.cleanup();\n }\n\n private cleanup(): void {\n this.connected = false;\n this.player = null;\n this.room = null;\n this.users.clear();\n }\n\n private handleMessage(msg: MessagePayload): void {\n const { action, args } = msg;\n let emitArgs: unknown = args;\n\n switch (action) {\n case \"load_player\": {\n const player = this.adapter.normalizePlayer(args);\n this.player = player;\n emitArgs = { user: player };\n this.log?.(\n \"[load_player]\",\n player.username,\n `id=${player.id}`,\n `coins=${player.coins}`,\n `inventory=${player.inventory.length}`,\n );\n break;\n }\n case \"join_room\": {\n const room = args.room as number;\n const rawUsers = args.users as Record<string, unknown>[];\n this.room = room;\n this.users.clear();\n const users: RoomUser[] = [];\n for (const rawUser of rawUsers) {\n const user = this.adapter.normalizeUser(rawUser);\n this.users.set(user.id, user);\n users.push(user);\n }\n emitArgs = { room, users };\n this.log?.(\"[join_room]\", `room=${room}`, `users=${users.length}`);\n break;\n }\n case \"add_player\": {\n const user = this.adapter.normalizeUser(\n args.user as Record<string, unknown>,\n );\n this.users.set(user.id, user);\n emitArgs = { user };\n this.log?.(\"[add_player]\", user.username, `id=${user.id}`);\n break;\n }\n case \"remove_player\": {\n const id = args.user as number;\n this.users.delete(id);\n this.log?.(\"[remove_player]\", `id=${id}`);\n break;\n }\n case \"send_position\": {\n const id = args.id as number;\n const user = this.users.get(id);\n if (user) {\n user.x = args.x as number;\n user.y = args.y as number;\n }\n break;\n }\n case \"send_frame\": {\n const id = args.id as number;\n const user = this.users.get(id);\n if (user) {\n user.frame = args.frame as number;\n }\n break;\n }\n case \"update_player\": {\n const id = args.id as number;\n const slot = args.slot as string;\n const item = args.item as number;\n const user = this.users.get(id);\n if (user && slot in user) {\n (user as Record<string, unknown>)[slot] = item;\n }\n break;\n }\n case \"kick\": {\n const reason = (args as { reason?: string }).reason ?? \"unknown\";\n this.log?.(\"[kick]\", reason);\n this.cleanup();\n break;\n }\n case \"close_with_error\": {\n const error = (args as { error?: string }).error ?? \"unknown\";\n this.log?.(\"[kick]\", error);\n this.cleanup();\n break;\n }\n default: {\n this.log?.(`[${action}]`, JSON.stringify(args));\n break;\n }\n }\n\n const eventName = action === \"error\" ? \"server_error\" : action;\n this.emit(eventName, emitArgs);\n }\n}\n","import { io, type Socket } from \"socket.io-client\";\nimport msgpackParser from \"socket.io-msgpack-parser\";\nimport type {\n LoginOptions,\n LoginResult,\n QueueUpdate,\n ServerInfo,\n TokenLoginOptions,\n} from \"../types/adapter-types.js\";\nimport type { Buddy, PlayerData, RoomUser } from \"../types/player-types.js\";\nimport { BaseAdapter, type ConnectOptions } from \"./base-adapter.js\";\n\nconst BASE_URL = \"wss://play.cpjourney.net\";\nconst DEFAULT_SECRET = \"skip\";\n\ntype LoginResponse = {\n success: boolean;\n username: string;\n key: string;\n populations: Record<string, number>;\n moderator: boolean;\n buddyWorlds: string[];\n};\n\ntype GameAuthResponse = {\n success: boolean;\n token?: string;\n};\n\ntype ServerMessage = {\n action: string;\n args: Record<string, unknown>;\n};\n\nexport class CpjourneyAdapter extends BaseAdapter {\n readonly id = \"CPJourney\";\n\n async login(options: LoginOptions | TokenLoginOptions): Promise<LoginResult> {\n const loginSocket = this.createSocket(\"/world/login/\");\n\n const result = await new Promise<LoginResult>((resolve, reject) => {\n const timeout = setTimeout(() => {\n loginSocket.disconnect();\n reject(new Error(\"Login timed out\"));\n }, 10_000);\n\n loginSocket.on(\"connect\", () => {\n const secret = options.secret ?? DEFAULT_SECRET;\n const args =\n \"token\" in options\n ? { username: options.username, token: options.token, secret }\n : {\n username: options.username,\n password: options.password,\n secret,\n };\n\n loginSocket.emit(\"message\", { action: \"login\", args });\n });\n\n loginSocket.on(\"message\", (msg: ServerMessage) => {\n if (msg.action !== \"login\") return;\n\n clearTimeout(timeout);\n loginSocket.disconnect();\n\n const response = msg.args as LoginResponse;\n\n if (!response.success) {\n reject(new Error(\"Login failed\"));\n return;\n }\n\n const servers: ServerInfo[] = Object.entries(response.populations).map(\n ([name, population]) => ({ name, population }),\n );\n\n resolve({\n servers,\n key: response.key,\n username: response.username,\n moderator: response.moderator,\n buddyWorlds: response.buddyWorlds ?? [],\n });\n });\n\n loginSocket.on(\"connect_error\", (err: Error) => {\n clearTimeout(timeout);\n loginSocket.disconnect();\n reject(new Error(`Login connection failed: ${err.message}`));\n });\n });\n\n return result;\n }\n\n async connect(\n serverName: string,\n loginResult: LoginResult,\n options?: ConnectOptions,\n ): Promise<Socket> {\n const gameSocket = this.createSocket(`/world/${serverName.toLowerCase()}/`);\n this.socket = gameSocket;\n\n await new Promise<void>((resolve, reject) => {\n let authSent = false;\n\n gameSocket.on(\"connect\", () => {\n gameSocket.emit(\"message\", {\n action: \"game_auth\",\n args: {\n username: loginResult.username,\n key: loginResult.key,\n createToken: false,\n joinInvis: false,\n takeoverMascot: false,\n token: \"\",\n },\n });\n });\n\n gameSocket.on(\"message\", (msg: ServerMessage) => {\n switch (msg.action) {\n case \"wait_queue_update\": {\n options?.onQueueUpdate?.(msg.args as QueueUpdate);\n break;\n }\n case \"game_auth\": {\n if (authSent) break;\n authSent = true;\n\n const response = msg.args as GameAuthResponse;\n if (!response.success) {\n gameSocket.disconnect();\n reject(new Error(\"Game auth failed\"));\n return;\n }\n\n gameSocket.emit(\"message\", {\n action: \"join_server\",\n args: {},\n });\n resolve();\n break;\n }\n }\n });\n\n gameSocket.on(\"connect_error\", (err: Error) => {\n gameSocket.disconnect();\n reject(new Error(`Game connection failed: ${err.message}`));\n });\n });\n\n return gameSocket;\n }\n\n send(action: string, args: Record<string, unknown>): void {\n if (!this.socket) throw new Error(\"Not connected\");\n this.socket.emit(\"message\", { action, args });\n }\n\n disconnect(): void {\n this.socket?.disconnect();\n this.socket = null;\n }\n\n override normalizeUser(raw: Record<string, unknown>): RoomUser {\n return {\n ...this.extractAppearance(raw),\n id: raw.id as number,\n username: raw.username as string,\n displayName: raw.displayName as string | undefined,\n joinTime: raw.joinTime as string | undefined,\n x: (raw.x as number) ?? 0,\n y: (raw.y as number) ?? 0,\n frame: (raw.frame as number) ?? 0,\n walking: raw.walking as number | undefined,\n meta: {\n hat: raw.hat,\n face_mask: raw.face_mask,\n neck_scarf: raw.neck_scarf,\n body_shirt: raw.body_shirt,\n hand_glove: raw.hand_glove,\n transform: raw.transform,\n walkingPuffleType: raw.walkingPuffleType,\n openSprite: raw.openSprite,\n mascotGiveaway: raw.mascotGiveaway,\n iglooOpen: raw.iglooOpen,\n iglooBounds: raw.iglooBounds,\n igloo_slot: raw.igloo_slot,\n currentLayer: raw.currentLayer,\n fireRank: raw.fireRank,\n },\n _raw: raw,\n };\n }\n\n override normalizePlayer(raw: Record<string, unknown>): PlayerData {\n const user = raw.user as Record<string, unknown>;\n const normalized = this.normalizeUser(user);\n return {\n ...normalized,\n _raw: raw,\n coins: (raw.coins as number) ?? 0,\n rank: (raw.rank as number) ?? 0,\n inventory: (raw.inventory as number[]) ?? [],\n furniture: (raw.furniture as unknown[]) ?? [],\n flooring: (raw.flooring as unknown[]) ?? [],\n buddies: (user.buddies as Buddy[]) ?? [],\n buddyRequests: (user.buddyRequests as number[]) ?? [],\n ignores: (user.ignores as number[]) ?? [],\n igloos: (user.igloos as unknown[]) ?? [],\n meta: {\n ...normalized.meta,\n settings: user.settings,\n puffleInventory: raw.puffleInventory ?? user.puffleInventory,\n partyCoins: raw.partyCoins ?? user.partyCoins,\n gems: raw.gems ?? user.gems,\n streamer: raw.streamer ?? user.streamer,\n username_verified: raw.username_verified ?? user.username_verified,\n email_verified: raw.email_verified ?? user.email_verified,\n inf_skill_points: raw.inf_skill_points ?? user.inf_skill_points,\n highest_floor_reached:\n raw.highest_floor_reached ?? user.highest_floor_reached,\n towerMeters: raw.towerMeters ?? user.towerMeters,\n towerExperience: raw.towerExperience ?? user.towerExperience,\n },\n };\n }\n\n override sendMessage(message: string): void {\n this.send(\"send_message\", { message });\n }\n\n override sendEmote(emote: number): void {\n this.send(\"send_emote\", { emote });\n }\n\n override sendSafe(safe: number): void {\n this.send(\"send_safe\", { safe });\n }\n\n override walk(x: number, y: number): void {\n this.send(\"send_position\", { x, y });\n }\n\n override sendFrame(frame: number, set?: boolean): void {\n this.send(\"send_frame\", { frame, set });\n }\n\n override snowball(x: number, y: number): void {\n this.send(\"snowball\", { x, y });\n }\n\n override joinRoom(room: number, x?: number, y?: number): void {\n this.send(\"join_room\", { room, x: x ?? 0, y: y ?? 0 });\n }\n\n override addItem(item: number): void {\n this.send(\"add_item\", { item });\n }\n\n override equipColor(item: number): void {\n this.send(\"update_color\", { item });\n }\n\n override equipHead(item: number): void {\n this.send(\"update_head\", { item });\n }\n\n override equipFace(item: number): void {\n this.send(\"update_face\", { item });\n }\n\n override equipNeck(item: number): void {\n this.send(\"update_neck\", { item });\n }\n\n override equipBody(item: number): void {\n this.send(\"update_body\", { item });\n }\n\n override equipHand(item: number): void {\n this.send(\"update_hand\", { item });\n }\n\n override equipFeet(item: number): void {\n this.send(\"update_feet\", { item });\n }\n\n override equipFlag(item: number): void {\n this.send(\"update_flag\", { item });\n }\n\n override equipPhoto(item: number): void {\n this.send(\"update_photo\", { item });\n }\n\n override buddyRequest(id: number): void {\n this.send(\"buddy_request\", { id });\n }\n\n override buddyAccept(id: number): void {\n this.send(\"buddy_accept\", { id });\n }\n\n override buddyReject(id: number): void {\n this.send(\"buddy_reject\", { id });\n }\n\n override buddyRequestSeen(id: number): void {\n this.send(\"buddy_request_seen\", { id });\n }\n\n override getBuddy(id: number, type: \"buddies\" | \"buddyRequests\"): void {\n this.send(\"get_buddy\", { id, type });\n }\n\n override removeBuddy(id: number): void {\n this.send(\"remove_buddy\", { id });\n }\n\n override addIgnore(id: number): void {\n this.send(\"ignore_add\", { id });\n }\n\n override removeIgnore(id: number): void {\n this.send(\"ignore_remove\", { id });\n }\n\n override getPlayer(id: number): void {\n this.send(\"get_player\", { id });\n }\n\n override getAllSlots(): void {\n this.send(\"get_all_slots\", {});\n }\n\n override getMascots(): void {\n this.send(\"get_mascots\", {});\n }\n\n override sendPostcard(userId: number, cardId: string): void {\n this.send(\"send_postcard\", { userId, cardId });\n }\n\n override getStamps(userId: number): void {\n this.send(\"get_stamps\", { userId });\n }\n\n override getPostcards(): void {\n this.send(\"get_postcards\", {});\n }\n\n override getIglooOpen(igloo: number): void {\n this.send(\"get_igloo_open\", { igloo });\n }\n\n override joinIgloo(igloo: number, x?: number, y?: number): void {\n this.send(\"join_igloo\", { igloo, x: x ?? 0, y: y ?? 0 });\n }\n\n override gameOver(coins: number): void {\n this.send(\"game_over\", { coins });\n }\n\n override collectStamp(stamp: number): void {\n this.send(\"collect_stamp\", { stamp });\n }\n\n private createSocket(path: string): Socket {\n return io(BASE_URL, {\n path,\n parser: msgpackParser,\n transports: [\"polling\", \"websocket\"],\n reconnection: false,\n });\n }\n}\n","import { io, type Socket } from \"socket.io-client\";\nimport msgpackParser from \"socket.io-msgpack-parser\";\nimport type {\n LoginOptions,\n LoginResult,\n QueueUpdate,\n ServerInfo,\n TokenLoginOptions,\n} from \"../types/adapter-types.js\";\nimport type { Buddy, PlayerData, RoomUser } from \"../types/player-types.js\";\nimport { BaseAdapter, type ConnectOptions } from \"./base-adapter.js\";\n\nconst LOGIN_URL = \"https://api.cplegacy.com/login\";\nconst TOKEN_LOGIN_URL = \"https://api.cplegacy.com/token_login\";\n\ntype LoginResponse = {\n success: boolean;\n username: string;\n key: string;\n populations: Record<string, number>;\n requires2FA: boolean;\n message?: string;\n wantedVersion?: string;\n};\n\ntype GameAuthResponse = {\n success: boolean;\n};\n\n/**\n * Wraps a CPLegacy socket to normalize its positional message format\n * `(\"message\", action, args)` into the `{ action, args }` envelope\n * that the Client class expects.\n */\nfunction wrapSocket(raw: Socket): Socket {\n const original = raw.on.bind(raw);\n\n raw.on = ((event: string, listener: (...args: unknown[]) => void) => {\n if (event === \"message\") {\n return original(event, (action: unknown, args: unknown) => {\n listener({ action, args: args ?? {} });\n });\n }\n return original(event, listener);\n }) as typeof raw.on;\n\n return raw;\n}\n\nexport class CplegacyAdapter extends BaseAdapter {\n readonly id = \"CPLegacy\";\n private version = \"\";\n\n async login(options: LoginOptions | TokenLoginOptions): Promise<LoginResult> {\n const url = \"token\" in options ? TOKEN_LOGIN_URL : LOGIN_URL;\n const body: Record<string, unknown> =\n \"token\" in options\n ? { username: options.username, token: options.token }\n : {\n username: options.username,\n password: options.password,\n version: this.version,\n };\n\n let data = await this.postLogin(url, body);\n\n // Version negotiation: server returns wantedVersion when ours is stale/empty\n if (!data.success && data.wantedVersion) {\n this.version = data.wantedVersion;\n body.version = this.version;\n data = await this.postLogin(url, body);\n }\n\n if (!data.success) {\n throw new Error(`Login failed: ${data.message ?? \"unknown error\"}`);\n }\n\n const servers: ServerInfo[] = Object.entries(data.populations ?? {}).map(\n ([name, population]) => ({ name, population }),\n );\n\n return {\n servers,\n key: data.key,\n username: data.username,\n moderator: false,\n buddyWorlds: [],\n };\n }\n\n async connect(\n serverName: string,\n loginResult: LoginResult,\n options?: ConnectOptions,\n ): Promise<Socket> {\n const wsUrl = `wss://${serverName.toLowerCase()}.server.cplegacy.com`;\n const rawSocket = io(wsUrl, {\n path: \"/socket.io/\",\n parser: msgpackParser,\n transports: [\"websocket\"],\n reconnection: false,\n });\n this.socket = rawSocket;\n\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n rawSocket.disconnect();\n reject(new Error(\"Game connection timed out\"));\n }, 15_000);\n\n rawSocket.on(\"connect\", () => {\n rawSocket.emit(\"message\", \"game_auth\", {\n username: loginResult.username,\n key: loginResult.key,\n createToken: false,\n token: \"\",\n });\n });\n\n rawSocket.on(\n \"message\",\n (action: string, args: Record<string, unknown>) => {\n switch (action) {\n case \"wait_queue_update\": {\n options?.onQueueUpdate?.(args as unknown as QueueUpdate);\n break;\n }\n case \"game_auth\": {\n const response = args as unknown as GameAuthResponse;\n if (!response.success) {\n clearTimeout(timeout);\n rawSocket.disconnect();\n reject(new Error(\"Game auth failed\"));\n return;\n }\n\n // CPLegacy requires explicitly requesting load_player before join_server\n rawSocket.emit(\"message\", \"load_player\", {});\n rawSocket.emit(\"message\", \"join_server\", {});\n clearTimeout(timeout);\n resolve();\n break;\n }\n }\n },\n );\n\n rawSocket.on(\"connect_error\", (err: Error) => {\n clearTimeout(timeout);\n rawSocket.disconnect();\n reject(new Error(`Game connection failed: ${err.message}`));\n });\n });\n\n // Return wrapped socket so Client receives normalized { action, args } messages\n return wrapSocket(rawSocket);\n }\n\n send(action: string, args: Record<string, unknown>): void {\n if (!this.socket) throw new Error(\"Not connected\");\n this.socket.emit(\"message\", action, args);\n }\n\n disconnect(): void {\n this.socket?.disconnect();\n this.socket = null;\n }\n\n override normalizeUser(raw: Record<string, unknown>): RoomUser {\n return {\n ...this.extractAppearance(raw),\n id: raw.id as number,\n username: raw.username as string,\n displayName: (raw.realUsername as string) ?? (raw.username as string),\n joinTime: raw.joinTime as string | undefined,\n x: (raw.x as number) ?? 0,\n y: (raw.y as number) ?? 0,\n frame: (raw.frame as number) ?? 0,\n walking: (raw.walking as number) ?? undefined,\n meta: {\n internalUsername: raw.username as string,\n approved: raw.approved,\n emailVerified: raw.emailVerified,\n safeChat: raw.safeChat,\n tutorial: raw.tutorial,\n loginStreak: raw.loginStreak,\n walkingColor: raw.walkingColor,\n stampbookColor: raw.stampbookColor,\n stampbookClasp: raw.stampbookClasp,\n stampbookPattern: raw.stampbookPattern,\n ninjaPoints: raw.ninjaPoints,\n highestNinjaRank: raw.highestNinjaRank,\n character: raw.character,\n transformed: raw.transformed,\n },\n _raw: raw,\n };\n }\n\n override normalizePlayer(raw: Record<string, unknown>): PlayerData {\n const user = raw.user as Record<string, unknown>;\n return {\n ...this.normalizeUser(user),\n _raw: raw,\n coins: (user.coins as number) ?? 0,\n rank: (user.rank as number) ?? 0,\n inventory: (raw.inventory as number[]) ?? [],\n furniture: raw.furniture as Record<string, unknown> | undefined,\n buddies: [],\n buddyRequests:\n (raw.pending as Buddy[] | undefined)?.map((b) => b.id) ?? [],\n ignores: [],\n igloos: (raw.igloos as unknown[]) ?? [],\n };\n }\n\n override sendMessage(message: string): void {\n this.send(\"send_message\", { message });\n }\n\n override sendEmote(emote: number): void {\n this.send(\"send_emote\", { emote });\n }\n\n override sendSafe(safe: number): void {\n this.send(\"send_safe\", { safe });\n }\n\n override walk(x: number, y: number): void {\n this.send(\"send_position\", { x, y });\n }\n\n override sendFrame(frame: number, set?: boolean): void {\n this.send(\"send_frame\", { frame, set });\n }\n\n override snowball(x: number, y: number): void {\n this.send(\"snowball\", { x, y });\n }\n\n override joinRoom(room: number, x?: number, y?: number): void {\n this.send(\"join_room\", { room, x: x ?? 0, y: y ?? 0 });\n }\n\n override addItem(item: number): void {\n this.send(\"add_item\", { item });\n }\n\n override equipColor(item: number): void {\n this.send(\"update_color\", { item });\n }\n\n override equipHead(item: number): void {\n this.send(\"update_head\", { item });\n }\n\n override equipFace(item: number): void {\n this.send(\"update_face\", { item });\n }\n\n override equipNeck(item: number): void {\n this.send(\"update_neck\", { item });\n }\n\n override equipBody(item: number): void {\n this.send(\"update_body\", { item });\n }\n\n override equipHand(item: number): void {\n this.send(\"update_hand\", { item });\n }\n\n override equipFeet(item: number): void {\n this.send(\"update_feet\", { item });\n }\n\n override equipFlag(item: number): void {\n this.send(\"update_flag\", { item });\n }\n\n override equipPhoto(item: number): void {\n this.send(\"update_photo\", { item });\n }\n\n override buddyRequest(id: number): void {\n this.send(\"buddy_request\", { id });\n }\n\n override buddyAccept(id: number): void {\n this.send(\"buddy_accept\", { id });\n }\n\n override buddyReject(id: number): void {\n this.send(\"buddy_reject\", { id });\n }\n\n override removeBuddy(id: number): void {\n this.send(\"remove_buddy\", { id });\n }\n\n override addIgnore(id: number): void {\n this.send(\"ignore_add\", { id });\n }\n\n override removeIgnore(id: number): void {\n this.send(\"ignore_remove\", { id });\n }\n\n override getPlayer(id: number): void {\n this.send(\"get_player\", { id });\n }\n\n override getStamps(userId: number): void {\n this.send(\"get_stamps\", { userId });\n }\n\n override getPostcards(): void {\n this.send(\"get_postcards\", {});\n }\n\n override joinIgloo(igloo: number, x?: number, y?: number): void {\n this.send(\"join_igloo\", { igloo, x: x ?? 0, y: y ?? 0 });\n }\n\n override gameOver(coins: number): void {\n this.send(\"game_over\", { coins });\n }\n\n override collectStamp(stamp: number): void {\n this.send(\"collect_stamp\", { stamp });\n }\n\n private async postLogin(\n url: string,\n body: Record<string, unknown>,\n ): Promise<LoginResponse> {\n const resp = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n },\n body: JSON.stringify(body),\n });\n\n return resp.json() as Promise<LoginResponse>;\n }\n}\n","import { createCipheriv, createDecipheriv, randomBytes } from \"node:crypto\";\nimport { io, type Socket } from \"socket.io-client\";\nimport nacl from \"tweetnacl\";\nimport type {\n LoginOptions,\n LoginResult,\n QueueUpdate,\n ServerInfo,\n TokenLoginOptions,\n} from \"../types/adapter-types.js\";\nimport type { Buddy, PlayerData, RoomUser } from \"../types/player-types.js\";\nimport { BaseAdapter, type ConnectOptions } from \"./base-adapter.js\";\n\nconst CRUMBS_URL =\n \"https://media8.newcp.net/assets/media/crumbs/en/crumbs.json\";\n\ntype WorldConfig = {\n id?: number;\n host: string;\n path: string;\n login?: boolean;\n};\n\ntype CrumbsWorlds = Record<string, WorldConfig>;\n\ntype LoginResponse = {\n success: boolean;\n username: string;\n key: string;\n populations: Record<string, number>;\n moderator: boolean;\n buddyWorlds: string[];\n};\n\ntype GameAuthResponse = {\n success: boolean;\n token?: string;\n};\n\nclass Encryptor {\n private aesKey: Buffer | null = null;\n private keypair = nacl.box.keyPair();\n\n get publicKey(): string {\n return Buffer.from(this.keypair.publicKey).toString(\"base64\");\n }\n\n get encrypted(): boolean {\n return this.aesKey !== null;\n }\n\n acquireKey(encryptedB64: string, serverPubKeyB64: string): string | null {\n const data = Buffer.from(encryptedB64, \"base64\");\n const serverPubKey = Buffer.from(serverPubKeyB64, \"base64\");\n const nonce = data.subarray(0, nacl.box.nonceLength);\n const ciphertext = data.subarray(nacl.box.nonceLength);\n const plaintext = nacl.box.open(\n new Uint8Array(ciphertext),\n new Uint8Array(nonce),\n new Uint8Array(serverPubKey),\n this.keypair.secretKey,\n );\n return plaintext ? new TextDecoder().decode(plaintext) : null;\n }\n\n setKey(keyString: string): void {\n this.aesKey = Buffer.from(keyString, \"utf-8\");\n }\n\n encrypt(plaintext: string): string {\n if (!this.aesKey) throw new Error(\"Encryption key not set\");\n const iv = randomBytes(16);\n const cipher = createCipheriv(\"aes-256-cbc\", this.aesKey, iv);\n const encrypted = Buffer.concat([\n cipher.update(plaintext, \"utf-8\"),\n cipher.final(),\n ]);\n const result = Buffer.concat([iv, encrypted]);\n return result.toString(\"base64\");\n }\n\n decrypt(data: string): string {\n if (!this.aesKey) throw new Error(\"Encryption key not set\");\n const buf = Buffer.from(data, \"base64\");\n const iv = buf.subarray(0, 16);\n const ciphertext = buf.subarray(16);\n const decipher = createDecipheriv(\"aes-256-cbc\", this.aesKey, iv);\n return Buffer.concat([\n decipher.update(ciphertext),\n decipher.final(),\n ]).toString(\"utf-8\");\n }\n\n encode(data: Record<string, unknown>): string {\n return this.encrypted\n ? this.encrypt(JSON.stringify(data))\n : JSON.stringify(data);\n }\n\n decode(data: unknown): Record<string, unknown> {\n if (this.encrypted && typeof data === \"string\") {\n return JSON.parse(this.decrypt(data)) as Record<string, unknown>;\n }\n return typeof data === \"string\"\n ? (JSON.parse(data) as Record<string, unknown>)\n : (data as Record<string, unknown>);\n }\n}\n\nfunction performHandshake(socket: Socket, encryptor: Encryptor): Promise<void> {\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new Error(\"Handshake timed out\"));\n }, 10_000);\n\n socket.once(\n \"handshake\",\n (encryptedKey: string, serverPubKeyB64: string) => {\n clearTimeout(timeout);\n const raw = encryptor.acquireKey(encryptedKey, serverPubKeyB64);\n if (!raw) {\n reject(new Error(\"Failed to decrypt handshake key\"));\n return;\n }\n\n const parsed = JSON.parse(raw) as { key: string; time?: number };\n if (\n parsed.time &&\n typeof parsed.time === \"number\" &&\n Math.abs(Date.now() - parsed.time) > 300_000\n ) {\n reject(new Error(\"Server time desync\"));\n return;\n }\n\n encryptor.setKey(parsed.key);\n resolve();\n },\n );\n\n socket.emit(\"handshake\", encryptor.publicKey);\n });\n}\n\n/**\n * Wraps a NewCP socket to decrypt incoming messages into the\n * `{ action, args }` envelope that the Client class expects.\n */\nfunction wrapSocket(raw: Socket, encryptor: Encryptor): Socket {\n const original = raw.on.bind(raw);\n\n raw.on = ((event: string, listener: (...args: unknown[]) => void) => {\n if (event === \"message\") {\n return original(event, (msg: unknown) => {\n try {\n const decoded = encryptor.decode(msg);\n listener({ action: decoded.action, args: decoded.args ?? {} });\n } catch {\n // Skip malformed messages\n }\n });\n }\n return original(event, listener);\n }) as typeof raw.on;\n\n return raw;\n}\n\nexport class NewcpAdapter extends BaseAdapter {\n readonly id = \"NewCP\";\n private encryptor = new Encryptor();\n private worlds: CrumbsWorlds | null = null;\n\n async login(options: LoginOptions | TokenLoginOptions): Promise<LoginResult> {\n if (!this.worlds) {\n await this.loadWorlds();\n }\n\n const loginWorld = Object.values(this.worlds ?? {}).find((w) => w.login);\n if (!loginWorld) throw new Error(\"Login world not found in crumbs\");\n\n const loginSocket = this.createSocket(loginWorld.host, loginWorld.path);\n this.encryptor = new Encryptor();\n\n const result = await new Promise<LoginResult>((resolve, reject) => {\n const timeout = setTimeout(() => {\n loginSocket.disconnect();\n reject(new Error(\"Login timed out\"));\n }, 15_000);\n\n loginSocket.on(\"connect\", async () => {\n try {\n await performHandshake(loginSocket, this.encryptor);\n\n const args =\n \"token\" in options\n ? { username: options.username, token: options.token }\n : { username: options.username, password: options.password };\n\n const encrypted = this.encryptor.encode({ action: \"login\", args });\n loginSocket.emit(\"message\", encrypted);\n } catch (err) {\n clearTimeout(timeout);\n loginSocket.disconnect();\n reject(err);\n }\n });\n\n loginSocket.on(\"message\", (msg: unknown) => {\n try {\n const decoded = this.encryptor.decode(msg);\n if (decoded.action !== \"login\") return;\n\n clearTimeout(timeout);\n loginSocket.disconnect();\n\n const response = decoded.args as unknown as LoginResponse;\n\n if (!response.success) {\n reject(new Error(\"Login failed\"));\n return;\n }\n\n const servers: ServerInfo[] = Object.entries(\n response.populations ?? {},\n ).map(([name, population]) => ({ name, population }));\n\n resolve({\n servers,\n key: response.key,\n username: response.username,\n moderator: response.moderator ?? false,\n buddyWorlds: response.buddyWorlds ?? [],\n });\n } catch (err) {\n clearTimeout(timeout);\n loginSocket.disconnect();\n reject(err);\n }\n });\n\n loginSocket.on(\"connect_error\", (err: Error) => {\n clearTimeout(timeout);\n loginSocket.disconnect();\n reject(new Error(`Login connection failed: ${err.message}`));\n });\n });\n\n return result;\n }\n\n async connect(\n serverName: string,\n loginResult: LoginResult,\n options?: ConnectOptions,\n ): Promise<Socket> {\n if (!this.worlds) {\n await this.loadWorlds();\n }\n\n const worldConfig = this.worlds?.[serverName];\n if (!worldConfig)\n throw new Error(`World config not found for: ${serverName}`);\n\n this.encryptor = new Encryptor();\n const gameSocket = this.createSocket(worldConfig.host, worldConfig.path);\n this.socket = gameSocket;\n\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n gameSocket.disconnect();\n reject(new Error(\"Game connection timed out\"));\n }, 15_000);\n\n gameSocket.on(\"connect\", async () => {\n try {\n await performHandshake(gameSocket, this.encryptor);\n\n const encrypted = this.encryptor.encode({\n action: \"game_auth\",\n args: {\n username: loginResult.username,\n key: loginResult.key,\n createToken: false,\n },\n });\n gameSocket.emit(\"message\", encrypted);\n } catch (err) {\n clearTimeout(timeout);\n gameSocket.disconnect();\n reject(err);\n }\n });\n\n gameSocket.on(\"message\", (msg: unknown) => {\n try {\n const decoded = this.encryptor.decode(msg);\n\n switch (decoded.action) {\n case \"wait_queue_update\": {\n options?.onQueueUpdate?.(decoded.args as unknown as QueueUpdate);\n break;\n }\n case \"game_auth\": {\n const response = decoded.args as unknown as GameAuthResponse;\n if (!response.success) {\n clearTimeout(timeout);\n gameSocket.disconnect();\n reject(new Error(\"Game auth failed\"));\n return;\n }\n\n const joinEncrypted = this.encryptor.encode({\n action: \"join_server\",\n args: {},\n });\n gameSocket.emit(\"message\", joinEncrypted);\n clearTimeout(timeout);\n resolve();\n break;\n }\n }\n } catch {\n // Ignore decode errors during auth phase\n }\n });\n\n gameSocket.on(\"connect_error\", (err: Error) => {\n clearTimeout(timeout);\n gameSocket.disconnect();\n reject(new Error(`Game connection failed: ${err.message}`));\n });\n });\n\n return wrapSocket(gameSocket, this.encryptor);\n }\n\n send(action: string, args: Record<string, unknown>): void {\n if (!this.socket) throw new Error(\"Not connected\");\n const encrypted = this.encryptor.encode({ action, args });\n this.socket.emit(\"message\", encrypted);\n }\n\n disconnect(): void {\n this.socket?.disconnect();\n this.socket = null;\n }\n\n override normalizeUser(raw: Record<string, unknown>): RoomUser {\n return {\n ...this.extractAppearance(raw),\n id: raw.id as number,\n username: raw.username as string,\n displayName: raw.nickname as string | undefined,\n x: (raw.x as number) ?? 0,\n y: (raw.y as number) ?? 0,\n frame: (raw.frame as number) ?? 0,\n meta: {\n nickname: raw.nickname,\n registrationDate: raw.registrationDate,\n customNameColor: raw.customNameColor,\n customBubbleColor: raw.customBubbleColor,\n customBubbleTextColor: raw.customBubbleTextColor,\n wallHacks: raw.wallHacks,\n moderator: raw.moderator,\n character: raw.character,\n approved: raw.approved,\n walking: raw.walking,\n },\n _raw: raw,\n };\n }\n\n override normalizePlayer(raw: Record<string, unknown>): PlayerData {\n const user = raw.user as Record<string, unknown>;\n return {\n ...this.normalizeUser(user),\n _raw: raw,\n coins: (raw.coins as number) ?? 0,\n rank: (raw.rank as number) ?? 0,\n inventory: (raw.inventory as number[]) ?? [],\n buddies: (raw.buddies as Buddy[]) ?? [],\n ignores: (raw.ignores as number[]) ?? [],\n furniture: raw.furniture as Record<string, unknown> | undefined,\n flooring: (raw.floorings as unknown[]) ?? [],\n igloos: (raw.igloos as unknown[]) ?? [],\n };\n }\n\n override sendMessage(message: string): void {\n this.send(\"send_message\", { message });\n }\n\n override sendEmote(emote: number): void {\n this.send(\"send_emote\", { emote });\n }\n\n override sendSafe(safe: number): void {\n this.send(\"send_safe\", { safe });\n }\n\n override walk(x: number, y: number): void {\n this.send(\"send_position\", { x, y });\n }\n\n override sendFrame(frame: number, set?: boolean): void {\n this.send(\"send_frame\", { frame, set });\n }\n\n override snowball(x: number, y: number): void {\n this.send(\"snowball\", { x, y });\n }\n\n override joinRoom(room: number, x?: number, y?: number): void {\n this.send(\"join_room\", { room, x: x ?? 0, y: y ?? 0 });\n }\n\n override addItem(item: number): void {\n this.send(\"add_item\", { item });\n }\n\n override equipColor(item: number): void {\n this.send(\"update_color\", { item });\n }\n\n override equipHead(item: number): void {\n this.send(\"update_head\", { item });\n }\n\n override equipFace(item: number): void {\n this.send(\"update_face\", { item });\n }\n\n override equipNeck(item: number): void {\n this.send(\"update_neck\", { item });\n }\n\n override equipBody(item: number): void {\n this.send(\"update_body\", { item });\n }\n\n override equipHand(item: number): void {\n this.send(\"update_hand\", { item });\n }\n\n override equipFeet(item: number): void {\n this.send(\"update_feet\", { item });\n }\n\n override equipFlag(item: number): void {\n this.send(\"update_flag\", { item });\n }\n\n override equipPhoto(item: number): void {\n this.send(\"update_photo\", { item });\n }\n\n override buddyRequest(id: number): void {\n this.send(\"buddy_request\", { id });\n }\n\n override buddyAccept(id: number): void {\n this.send(\"buddy_accept\", { id });\n }\n\n override buddyReject(id: number): void {\n this.send(\"buddy_reject\", { id });\n }\n\n override removeBuddy(id: number): void {\n this.send(\"remove_buddy\", { id });\n }\n\n override addIgnore(id: number): void {\n this.send(\"ignore_add\", { id });\n }\n\n override removeIgnore(id: number): void {\n this.send(\"ignore_remove\", { id });\n }\n\n override getPlayer(id: number): void {\n this.send(\"get_player\", { id });\n }\n\n override joinIgloo(igloo: number, x?: number, y?: number): void {\n this.send(\"join_igloo\", { igloo, x: x ?? 0, y: y ?? 0 });\n }\n\n private createSocket(host: string, path: string): Socket {\n return io(host, {\n path,\n transports: [\"polling\", \"websocket\"],\n reconnection: false,\n });\n }\n\n private async loadWorlds(): Promise<void> {\n const resp = await fetch(CRUMBS_URL);\n if (!resp.ok) throw new Error(`Failed to fetch crumbs: ${resp.status}`);\n const crumbs = (await resp.json()) as { worlds: CrumbsWorlds };\n this.worlds = crumbs.worlds;\n }\n}\n","import type { BaseAdapter } from \"./base-adapter.js\";\nimport { CpjourneyAdapter } from \"./cpjourney-adapter.js\";\nimport { CplegacyAdapter } from \"./cplegacy-adapter.js\";\nimport { NewcpAdapter } from \"./newcp-adapter.js\";\n\nconst ADAPTERS = {\n CPJourney: CpjourneyAdapter,\n CPLegacy: CplegacyAdapter,\n NewCP: NewcpAdapter,\n} as const;\n\nexport type AdapterName = keyof typeof ADAPTERS;\n\nexport function createAdapter(name: AdapterName): BaseAdapter {\n return new ADAPTERS[name]();\n}\n"],"mappings":"AAiBO,IAAeA,EAAf,KAA2B,CAEtB,OAAwB,KAalC,cAAcC,EAAyC,CACrD,MAAM,IAAI,MAAM,gCAAgC,CAClD,CAEA,gBAAgBA,EAA2C,CACzD,MAAM,IAAI,MAAM,kCAAkC,CACpD,CAEU,kBAAkBC,EAAgD,CAC1E,MAAO,CACL,MAAQA,EAAI,OAAoB,EAChC,KAAOA,EAAI,MAAmB,EAC9B,KAAOA,EAAI,MAAmB,EAC9B,KAAOA,EAAI,MAAmB,EAC9B,KAAOA,EAAI,MAAmB,EAC9B,KAAOA,EAAI,MAAmB,EAC9B,KAAOA,EAAI,MAAmB,EAC9B,KAAOA,EAAI,MAAmB,EAC9B,MAAQA,EAAI,OAAoB,CAClC,CACF,CAEA,YAAYC,EAAwB,CAClC,MAAM,IAAI,MAAM,8BAA8B,CAChD,CAEA,UAAUC,EAAsB,CAC9B,MAAM,IAAI,MAAM,4BAA4B,CAC9C,CAEA,SAASC,EAAqB,CAC5B,MAAM,IAAI,MAAM,2BAA2B,CAC7C,CAEA,KAAKC,EAAYC,EAAkB,CACjC,MAAM,IAAI,MAAM,uBAAuB,CACzC,CAEA,UAAUC,EAAgBC,EAAsB,CAC9C,MAAM,IAAI,MAAM,4BAA4B,CAC9C,CAEA,SAASH,EAAYC,EAAkB,CACrC,MAAM,IAAI,MAAM,2BAA2B,CAC7C,CAEA,SAASG,EAAeJ,EAAaC,EAAmB,CACtD,MAAM,IAAI,MAAM,2BAA2B,CAC7C,CAEA,QAAQI,EAAqB,CAC3B,MAAM,IAAI,MAAM,0BAA0B,CAC5C,CAEA,WAAWA,EAAqB,CAC9B,MAAM,IAAI,MAAM,6BAA6B,CAC/C,CAEA,UAAUA,EAAqB,CAC7B,MAAM,IAAI,MAAM,4BAA4B,CAC9C,CAEA,UAAUA,EAAqB,CAC7B,MAAM,IAAI,MAAM,4BAA4B,CAC9C,CAEA,UAAUA,EAAqB,CAC7B,MAAM,IAAI,MAAM,4BAA4B,CAC9C,CAEA,UAAUA,EAAqB,CAC7B,MAAM,IAAI,MAAM,4BAA4B,CAC9C,CAEA,UAAUA,EAAqB,CAC7B,MAAM,IAAI,MAAM,4BAA4B,CAC9C,CAEA,UAAUA,EAAqB,CAC7B,MAAM,IAAI,MAAM,4BAA4B,CAC9C,CAEA,UAAUA,EAAqB,CAC7B,MAAM,IAAI,MAAM,4BAA4B,CAC9C,CAEA,WAAWA,EAAqB,CAC9B,MAAM,IAAI,MAAM,6BAA6B,CAC/C,CAEA,aAAaC,EAAmB,CAC9B,MAAM,IAAI,MAAM,+BAA+B,CACjD,CAEA,YAAYA,EAAmB,CAC7B,MAAM,IAAI,MAAM,8BAA8B,CAChD,CAEA,YAAYA,EAAmB,CAC7B,MAAM,IAAI,MAAM,8BAA8B,CAChD,CAEA,iBAAiBA,EAAmB,CAClC,MAAM,IAAI,MAAM,mCAAmC,CACrD,CAEA,SAASA,EAAaC,EAA0C,CAC9D,MAAM,IAAI,MAAM,2BAA2B,CAC7C,CAEA,YAAYD,EAAmB,CAC7B,MAAM,IAAI,MAAM,8BAA8B,CAChD,CAEA,UAAUA,EAAmB,CAC3B,MAAM,IAAI,MAAM,4BAA4B,CAC9C,CAEA,aAAaA,EAAmB,CAC9B,MAAM,IAAI,MAAM,+BAA+B,CACjD,CAEA,UAAUA,EAAmB,CAC3B,MAAM,IAAI,MAAM,4BAA4B,CAC9C,CAEA,aAAoB,CAClB,MAAM,IAAI,MAAM,8BAA8B,CAChD,CAEA,YAAmB,CACjB,MAAM,IAAI,MAAM,6BAA6B,CAC/C,CAEA,aAAaE,EAAiBC,EAAuB,CACnD,MAAM,IAAI,MAAM,+BAA+B,CACjD,CAEA,UAAUD,EAAuB,CAC/B,MAAM,IAAI,MAAM,4BAA4B,CAC9C,CAEA,cAAqB,CACnB,MAAM,IAAI,MAAM,+BAA+B,CACjD,CAEA,aAAaE,EAAsB,CACjC,MAAM,IAAI,MAAM,+BAA+B,CACjD,CAEA,UAAUA,EAAgBV,EAAaC,EAAmB,CACxD,MAAM,IAAI,MAAM,4BAA4B,CAC9C,CAEA,SAASU,EAAsB,CAC7B,MAAM,IAAI,MAAM,2BAA2B,CAC7C,CAEA,aAAaC,EAAsB,CACjC,MAAM,IAAI,MAAM,+BAA+B,CACjD,CACF,ECjMA,OAAS,gBAAAC,MAAoB,SCA7B,OAAS,MAAAC,MAAuB,mBAChC,OAAOC,MAAmB,2BAW1B,IAAMC,EAAW,2BACXC,EAAiB,OAqBVC,EAAN,cAA+BC,CAAY,CACvC,GAAK,YAEd,MAAM,MAAMC,EAAiE,CAC3E,IAAMC,EAAc,KAAK,aAAa,eAAe,EAuDrD,OArDe,MAAM,IAAI,QAAqB,CAACC,EAASC,IAAW,CACjE,IAAMC,EAAU,WAAW,IAAM,CAC/BH,EAAY,WAAW,EACvBE,EAAO,IAAI,MAAM,iBAAiB,CAAC,CACrC,EAAG,GAAM,EAETF,EAAY,GAAG,UAAW,IAAM,CAC9B,IAAMI,EAASL,EAAQ,QAAUH,EAC3BS,EACJ,UAAWN,EACP,CAAE,SAAUA,EAAQ,SAAU,MAAOA,EAAQ,MAAO,OAAAK,CAAO,EAC3D,CACE,SAAUL,EAAQ,SAClB,SAAUA,EAAQ,SAClB,OAAAK,CACF,EAENJ,EAAY,KAAK,UAAW,CAAE,OAAQ,QAAS,KAAAK,CAAK,CAAC,CACvD,CAAC,EAEDL,EAAY,GAAG,UAAYM,GAAuB,CAChD,GAAIA,EAAI,SAAW,QAAS,OAE5B,aAAaH,CAAO,EACpBH,EAAY,WAAW,EAEvB,IAAMO,EAAWD,EAAI,KAErB,GAAI,CAACC,EAAS,QAAS,CACrBL,EAAO,IAAI,MAAM,cAAc,CAAC,EAChC,MACF,CAEA,IAAMM,EAAwB,OAAO,QAAQD,EAAS,WAAW,EAAE,IACjE,CAAC,CAACE,EAAMC,CAAU,KAAO,CAAE,KAAAD,EAAM,WAAAC,CAAW,EAC9C,EAEAT,EAAQ,CACN,QAAAO,EACA,IAAKD,EAAS,IACd,SAAUA,EAAS,SACnB,UAAWA,EAAS,UACpB,YAAaA,EAAS,aAAe,CAAC,CACxC,CAAC,CACH,CAAC,EAEDP,EAAY,GAAG,gBAAkBW,GAAe,CAC9C,aAAaR,CAAO,EACpBH,EAAY,WAAW,EACvBE,EAAO,IAAI,MAAM,4BAA4BS,EAAI,OAAO,EAAE,CAAC,CAC7D,CAAC,CACH,CAAC,CAGH,CAEA,MAAM,QACJC,EACAC,EACAd,EACiB,CACjB,IAAMe,EAAa,KAAK,aAAa,UAAUF,EAAW,YAAY,CAAC,GAAG,EAC1E,YAAK,OAASE,EAEd,MAAM,IAAI,QAAc,CAACb,EAASC,IAAW,CAC3C,IAAIa,EAAW,GAEfD,EAAW,GAAG,UAAW,IAAM,CAC7BA,EAAW,KAAK,UAAW,CACzB,OAAQ,YACR,KAAM,CACJ,SAAUD,EAAY,SACtB,IAAKA,EAAY,IACjB,YAAa,GACb,UAAW,GACX,eAAgB,GAChB,MAAO,EACT,CACF,CAAC,CACH,CAAC,EAEDC,EAAW,GAAG,UAAYR,GAAuB,CAC/C,OAAQA,EAAI,OAAQ,CAClB,IAAK,oBAAqB,CACxBP,GAAS,gBAAgBO,EAAI,IAAmB,EAChD,KACF,CACA,IAAK,YAAa,CAChB,GAAIS,EAAU,MAId,GAHAA,EAAW,GAGP,CADaT,EAAI,KACP,QAAS,CACrBQ,EAAW,WAAW,EACtBZ,EAAO,IAAI,MAAM,kBAAkB,CAAC,EACpC,MACF,CAEAY,EAAW,KAAK,UAAW,CACzB,OAAQ,cACR,KAAM,CAAC,CACT,CAAC,EACDb,EAAQ,EACR,KACF,CACF,CACF,CAAC,EAEDa,EAAW,GAAG,gBAAkBH,GAAe,CAC7CG,EAAW,WAAW,EACtBZ,EAAO,IAAI,MAAM,2BAA2BS,EAAI,OAAO,EAAE,CAAC,CAC5D,CAAC,CACH,CAAC,EAEMG,CACT,CAEA,KAAKE,EAAgBX,EAAqC,CACxD,GAAI,CAAC,KAAK,OAAQ,MAAM,IAAI,MAAM,eAAe,EACjD,KAAK,OAAO,KAAK,UAAW,CAAE,OAAAW,EAAQ,KAAAX,CAAK,CAAC,CAC9C,CAEA,YAAmB,CACjB,KAAK,QAAQ,WAAW,EACxB,KAAK,OAAS,IAChB,CAES,cAAcY,EAAwC,CAC7D,MAAO,CACL,GAAG,KAAK,kBAAkBA,CAAG,EAC7B,GAAIA,EAAI,GACR,SAAUA,EAAI,SACd,YAAaA,EAAI,YACjB,SAAUA,EAAI,SACd,EAAIA,EAAI,GAAgB,EACxB,EAAIA,EAAI,GAAgB,EACxB,MAAQA,EAAI,OAAoB,EAChC,QAASA,EAAI,QACb,KAAM,CACJ,IAAKA,EAAI,IACT,UAAWA,EAAI,UACf,WAAYA,EAAI,WAChB,WAAYA,EAAI,WAChB,WAAYA,EAAI,WAChB,UAAWA,EAAI,UACf,kBAAmBA,EAAI,kBACvB,WAAYA,EAAI,WAChB,eAAgBA,EAAI,eACpB,UAAWA,EAAI,UACf,YAAaA,EAAI,YACjB,WAAYA,EAAI,WAChB,aAAcA,EAAI,aAClB,SAAUA,EAAI,QAChB,EACA,KAAMA,CACR,CACF,CAES,gBAAgBA,EAA0C,CACjE,IAAMC,EAAOD,EAAI,KACXE,EAAa,KAAK,cAAcD,CAAI,EAC1C,MAAO,CACL,GAAGC,EACH,KAAMF,EACN,MAAQA,EAAI,OAAoB,EAChC,KAAOA,EAAI,MAAmB,EAC9B,UAAYA,EAAI,WAA0B,CAAC,EAC3C,UAAYA,EAAI,WAA2B,CAAC,EAC5C,SAAWA,EAAI,UAA0B,CAAC,EAC1C,QAAUC,EAAK,SAAuB,CAAC,EACvC,cAAgBA,EAAK,eAA8B,CAAC,EACpD,QAAUA,EAAK,SAAwB,CAAC,EACxC,OAASA,EAAK,QAAwB,CAAC,EACvC,KAAM,CACJ,GAAGC,EAAW,KACd,SAAUD,EAAK,SACf,gBAAiBD,EAAI,iBAAmBC,EAAK,gBAC7C,WAAYD,EAAI,YAAcC,EAAK,WACnC,KAAMD,EAAI,MAAQC,EAAK,KACvB,SAAUD,EAAI,UAAYC,EAAK,SAC/B,kBAAmBD,EAAI,mBAAqBC,EAAK,kBACjD,eAAgBD,EAAI,gBAAkBC,EAAK,eAC3C,iBAAkBD,EAAI,kBAAoBC,EAAK,iBAC/C,sBACED,EAAI,uBAAyBC,EAAK,sBACpC,YAAaD,EAAI,aAAeC,EAAK,YACrC,gBAAiBD,EAAI,iBAAmBC,EAAK,eAC/C,CACF,CACF,CAES,YAAYE,EAAuB,CAC1C,KAAK,KAAK,eAAgB,CAAE,QAAAA,CAAQ,CAAC,CACvC,CAES,UAAUC,EAAqB,CACtC,KAAK,KAAK,aAAc,CAAE,MAAAA,CAAM,CAAC,CACnC,CAES,SAASC,EAAoB,CACpC,KAAK,KAAK,YAAa,CAAE,KAAAA,CAAK,CAAC,CACjC,CAES,KAAKC,EAAWC,EAAiB,CACxC,KAAK,KAAK,gBAAiB,CAAE,EAAAD,EAAG,EAAAC,CAAE,CAAC,CACrC,CAES,UAAUC,EAAeC,EAAqB,CACrD,KAAK,KAAK,aAAc,CAAE,MAAAD,EAAO,IAAAC,CAAI,CAAC,CACxC,CAES,SAASH,EAAWC,EAAiB,CAC5C,KAAK,KAAK,WAAY,CAAE,EAAAD,EAAG,EAAAC,CAAE,CAAC,CAChC,CAES,SAASG,EAAcJ,EAAYC,EAAkB,CAC5D,KAAK,KAAK,YAAa,CAAE,KAAAG,EAAM,EAAGJ,GAAK,EAAG,EAAGC,GAAK,CAAE,CAAC,CACvD,CAES,QAAQI,EAAoB,CACnC,KAAK,KAAK,WAAY,CAAE,KAAAA,CAAK,CAAC,CAChC,CAES,WAAWA,EAAoB,CACtC,KAAK,KAAK,eAAgB,CAAE,KAAAA,CAAK,CAAC,CACpC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,WAAWA,EAAoB,CACtC,KAAK,KAAK,eAAgB,CAAE,KAAAA,CAAK,CAAC,CACpC,CAES,aAAaC,EAAkB,CACtC,KAAK,KAAK,gBAAiB,CAAE,GAAAA,CAAG,CAAC,CACnC,CAES,YAAYA,EAAkB,CACrC,KAAK,KAAK,eAAgB,CAAE,GAAAA,CAAG,CAAC,CAClC,CAES,YAAYA,EAAkB,CACrC,KAAK,KAAK,eAAgB,CAAE,GAAAA,CAAG,CAAC,CAClC,CAES,iBAAiBA,EAAkB,CAC1C,KAAK,KAAK,qBAAsB,CAAE,GAAAA,CAAG,CAAC,CACxC,CAES,SAASA,EAAYC,EAAyC,CACrE,KAAK,KAAK,YAAa,CAAE,GAAAD,EAAI,KAAAC,CAAK,CAAC,CACrC,CAES,YAAYD,EAAkB,CACrC,KAAK,KAAK,eAAgB,CAAE,GAAAA,CAAG,CAAC,CAClC,CAES,UAAUA,EAAkB,CACnC,KAAK,KAAK,aAAc,CAAE,GAAAA,CAAG,CAAC,CAChC,CAES,aAAaA,EAAkB,CACtC,KAAK,KAAK,gBAAiB,CAAE,GAAAA,CAAG,CAAC,CACnC,CAES,UAAUA,EAAkB,CACnC,KAAK,KAAK,aAAc,CAAE,GAAAA,CAAG,CAAC,CAChC,CAES,aAAoB,CAC3B,KAAK,KAAK,gBAAiB,CAAC,CAAC,CAC/B,CAES,YAAmB,CAC1B,KAAK,KAAK,cAAe,CAAC,CAAC,CAC7B,CAES,aAAaE,EAAgBC,EAAsB,CAC1D,KAAK,KAAK,gBAAiB,CAAE,OAAAD,EAAQ,OAAAC,CAAO,CAAC,CAC/C,CAES,UAAUD,EAAsB,CACvC,KAAK,KAAK,aAAc,CAAE,OAAAA,CAAO,CAAC,CACpC,CAES,cAAqB,CAC5B,KAAK,KAAK,gBAAiB,CAAC,CAAC,CAC/B,CAES,aAAaE,EAAqB,CACzC,KAAK,KAAK,iBAAkB,CAAE,MAAAA,CAAM,CAAC,CACvC,CAES,UAAUA,EAAeV,EAAYC,EAAkB,CAC9D,KAAK,KAAK,aAAc,CAAE,MAAAS,EAAO,EAAGV,GAAK,EAAG,EAAGC,GAAK,CAAE,CAAC,CACzD,CAES,SAASU,EAAqB,CACrC,KAAK,KAAK,YAAa,CAAE,MAAAA,CAAM,CAAC,CAClC,CAES,aAAaC,EAAqB,CACzC,KAAK,KAAK,gBAAiB,CAAE,MAAAA,CAAM,CAAC,CACtC,CAEQ,aAAaC,EAAsB,CACzC,OAAOC,EAAG1C,EAAU,CAClB,KAAAyC,EACA,OAAQE,EACR,WAAY,CAAC,UAAW,WAAW,EACnC,aAAc,EAChB,CAAC,CACH,CACF,EC3XA,OAAS,MAAAC,MAAuB,mBAChC,OAAOC,MAAmB,2BAW1B,IAAMC,EAAY,iCACZC,EAAkB,uCAqBxB,SAASC,EAAWC,EAAqB,CACvC,IAAMC,EAAWD,EAAI,GAAG,KAAKA,CAAG,EAEhC,OAAAA,EAAI,IAAM,CAACE,EAAeC,IACpBD,IAAU,UACLD,EAASC,EAAO,CAACE,EAAiBC,IAAkB,CACzDF,EAAS,CAAE,OAAAC,EAAQ,KAAMC,GAAQ,CAAC,CAAE,CAAC,CACvC,CAAC,EAEIJ,EAASC,EAAOC,CAAQ,GAG1BH,CACT,CAEO,IAAMM,EAAN,cAA8BC,CAAY,CACtC,GAAK,WACN,QAAU,GAElB,MAAM,MAAMC,EAAiE,CAC3E,IAAMC,EAAM,UAAWD,EAAUV,EAAkBD,EAC7Ca,EACJ,UAAWF,EACP,CAAE,SAAUA,EAAQ,SAAU,MAAOA,EAAQ,KAAM,EACnD,CACE,SAAUA,EAAQ,SAClB,SAAUA,EAAQ,SAClB,QAAS,KAAK,OAChB,EAEFG,EAAO,MAAM,KAAK,UAAUF,EAAKC,CAAI,EASzC,GANI,CAACC,EAAK,SAAWA,EAAK,gBACxB,KAAK,QAAUA,EAAK,cACpBD,EAAK,QAAU,KAAK,QACpBC,EAAO,MAAM,KAAK,UAAUF,EAAKC,CAAI,GAGnC,CAACC,EAAK,QACR,MAAM,IAAI,MAAM,iBAAiBA,EAAK,SAAW,eAAe,EAAE,EAOpE,MAAO,CACL,QAL4B,OAAO,QAAQA,EAAK,aAAe,CAAC,CAAC,EAAE,IACnE,CAAC,CAACC,EAAMC,CAAU,KAAO,CAAE,KAAAD,EAAM,WAAAC,CAAW,EAC9C,EAIE,IAAKF,EAAK,IACV,SAAUA,EAAK,SACf,UAAW,GACX,YAAa,CAAC,CAChB,CACF,CAEA,MAAM,QACJG,EACAC,EACAP,EACiB,CACjB,IAAMQ,EAAQ,SAASF,EAAW,YAAY,CAAC,uBACzCG,EAAYC,EAAGF,EAAO,CAC1B,KAAM,cACN,OAAQG,EACR,WAAY,CAAC,WAAW,EACxB,aAAc,EAChB,CAAC,EACD,YAAK,OAASF,EAEd,MAAM,IAAI,QAAc,CAACG,EAASC,IAAW,CAC3C,IAAMC,EAAU,WAAW,IAAM,CAC/BL,EAAU,WAAW,EACrBI,EAAO,IAAI,MAAM,2BAA2B,CAAC,CAC/C,EAAG,IAAM,EAETJ,EAAU,GAAG,UAAW,IAAM,CAC5BA,EAAU,KAAK,UAAW,YAAa,CACrC,SAAUF,EAAY,SACtB,IAAKA,EAAY,IACjB,YAAa,GACb,MAAO,EACT,CAAC,CACH,CAAC,EAEDE,EAAU,GACR,UACA,CAACb,EAAgBC,IAAkC,CACjD,OAAQD,EAAQ,CACd,IAAK,oBAAqB,CACxBI,GAAS,gBAAgBH,CAA8B,EACvD,KACF,CACA,IAAK,YAAa,CAEhB,GAAI,CADaA,EACH,QAAS,CACrB,aAAaiB,CAAO,EACpBL,EAAU,WAAW,EACrBI,EAAO,IAAI,MAAM,kBAAkB,CAAC,EACpC,MACF,CAGAJ,EAAU,KAAK,UAAW,cAAe,CAAC,CAAC,EAC3CA,EAAU,KAAK,UAAW,cAAe,CAAC,CAAC,EAC3C,aAAaK,CAAO,EACpBF,EAAQ,EACR,KACF,CACF,CACF,CACF,EAEAH,EAAU,GAAG,gBAAkBM,GAAe,CAC5C,aAAaD,CAAO,EACpBL,EAAU,WAAW,EACrBI,EAAO,IAAI,MAAM,2BAA2BE,EAAI,OAAO,EAAE,CAAC,CAC5D,CAAC,CACH,CAAC,EAGMxB,EAAWkB,CAAS,CAC7B,CAEA,KAAKb,EAAgBC,EAAqC,CACxD,GAAI,CAAC,KAAK,OAAQ,MAAM,IAAI,MAAM,eAAe,EACjD,KAAK,OAAO,KAAK,UAAWD,EAAQC,CAAI,CAC1C,CAEA,YAAmB,CACjB,KAAK,QAAQ,WAAW,EACxB,KAAK,OAAS,IAChB,CAES,cAAcL,EAAwC,CAC7D,MAAO,CACL,GAAG,KAAK,kBAAkBA,CAAG,EAC7B,GAAIA,EAAI,GACR,SAAUA,EAAI,SACd,YAAcA,EAAI,cAA4BA,EAAI,SAClD,SAAUA,EAAI,SACd,EAAIA,EAAI,GAAgB,EACxB,EAAIA,EAAI,GAAgB,EACxB,MAAQA,EAAI,OAAoB,EAChC,QAAUA,EAAI,SAAsB,OACpC,KAAM,CACJ,iBAAkBA,EAAI,SACtB,SAAUA,EAAI,SACd,cAAeA,EAAI,cACnB,SAAUA,EAAI,SACd,SAAUA,EAAI,SACd,YAAaA,EAAI,YACjB,aAAcA,EAAI,aAClB,eAAgBA,EAAI,eACpB,eAAgBA,EAAI,eACpB,iBAAkBA,EAAI,iBACtB,YAAaA,EAAI,YACjB,iBAAkBA,EAAI,iBACtB,UAAWA,EAAI,UACf,YAAaA,EAAI,WACnB,EACA,KAAMA,CACR,CACF,CAES,gBAAgBA,EAA0C,CACjE,IAAMwB,EAAOxB,EAAI,KACjB,MAAO,CACL,GAAG,KAAK,cAAcwB,CAAI,EAC1B,KAAMxB,EACN,MAAQwB,EAAK,OAAoB,EACjC,KAAOA,EAAK,MAAmB,EAC/B,UAAYxB,EAAI,WAA0B,CAAC,EAC3C,UAAWA,EAAI,UACf,QAAS,CAAC,EACV,cACGA,EAAI,SAAiC,IAAKyB,GAAMA,EAAE,EAAE,GAAK,CAAC,EAC7D,QAAS,CAAC,EACV,OAASzB,EAAI,QAAwB,CAAC,CACxC,CACF,CAES,YAAY0B,EAAuB,CAC1C,KAAK,KAAK,eAAgB,CAAE,QAAAA,CAAQ,CAAC,CACvC,CAES,UAAUC,EAAqB,CACtC,KAAK,KAAK,aAAc,CAAE,MAAAA,CAAM,CAAC,CACnC,CAES,SAASC,EAAoB,CACpC,KAAK,KAAK,YAAa,CAAE,KAAAA,CAAK,CAAC,CACjC,CAES,KAAKC,EAAWC,EAAiB,CACxC,KAAK,KAAK,gBAAiB,CAAE,EAAAD,EAAG,EAAAC,CAAE,CAAC,CACrC,CAES,UAAUC,EAAeC,EAAqB,CACrD,KAAK,KAAK,aAAc,CAAE,MAAAD,EAAO,IAAAC,CAAI,CAAC,CACxC,CAES,SAASH,EAAWC,EAAiB,CAC5C,KAAK,KAAK,WAAY,CAAE,EAAAD,EAAG,EAAAC,CAAE,CAAC,CAChC,CAES,SAASG,EAAcJ,EAAYC,EAAkB,CAC5D,KAAK,KAAK,YAAa,CAAE,KAAAG,EAAM,EAAGJ,GAAK,EAAG,EAAGC,GAAK,CAAE,CAAC,CACvD,CAES,QAAQI,EAAoB,CACnC,KAAK,KAAK,WAAY,CAAE,KAAAA,CAAK,CAAC,CAChC,CAES,WAAWA,EAAoB,CACtC,KAAK,KAAK,eAAgB,CAAE,KAAAA,CAAK,CAAC,CACpC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,WAAWA,EAAoB,CACtC,KAAK,KAAK,eAAgB,CAAE,KAAAA,CAAK,CAAC,CACpC,CAES,aAAaC,EAAkB,CACtC,KAAK,KAAK,gBAAiB,CAAE,GAAAA,CAAG,CAAC,CACnC,CAES,YAAYA,EAAkB,CACrC,KAAK,KAAK,eAAgB,CAAE,GAAAA,CAAG,CAAC,CAClC,CAES,YAAYA,EAAkB,CACrC,KAAK,KAAK,eAAgB,CAAE,GAAAA,CAAG,CAAC,CAClC,CAES,YAAYA,EAAkB,CACrC,KAAK,KAAK,eAAgB,CAAE,GAAAA,CAAG,CAAC,CAClC,CAES,UAAUA,EAAkB,CACnC,KAAK,KAAK,aAAc,CAAE,GAAAA,CAAG,CAAC,CAChC,CAES,aAAaA,EAAkB,CACtC,KAAK,KAAK,gBAAiB,CAAE,GAAAA,CAAG,CAAC,CACnC,CAES,UAAUA,EAAkB,CACnC,KAAK,KAAK,aAAc,CAAE,GAAAA,CAAG,CAAC,CAChC,CAES,UAAUC,EAAsB,CACvC,KAAK,KAAK,aAAc,CAAE,OAAAA,CAAO,CAAC,CACpC,CAES,cAAqB,CAC5B,KAAK,KAAK,gBAAiB,CAAC,CAAC,CAC/B,CAES,UAAUC,EAAeR,EAAYC,EAAkB,CAC9D,KAAK,KAAK,aAAc,CAAE,MAAAO,EAAO,EAAGR,GAAK,EAAG,EAAGC,GAAK,CAAE,CAAC,CACzD,CAES,SAASQ,EAAqB,CACrC,KAAK,KAAK,YAAa,CAAE,MAAAA,CAAM,CAAC,CAClC,CAES,aAAaC,EAAqB,CACzC,KAAK,KAAK,gBAAiB,CAAE,MAAAA,CAAM,CAAC,CACtC,CAEA,MAAc,UACZ9B,EACAC,EACwB,CAUxB,OATa,MAAM,MAAMD,EAAK,CAC5B,OAAQ,OACR,QAAS,CACP,eAAgB,mBAChB,OAAQ,kBACV,EACA,KAAM,KAAK,UAAUC,CAAI,CAC3B,CAAC,GAEW,KAAK,CACnB,CACF,EC3VA,OAAS,kBAAA8B,EAAgB,oBAAAC,EAAkB,eAAAC,MAAmB,SAC9D,OAAS,MAAAC,MAAuB,mBAChC,OAAOC,MAAU,YAWjB,IAAMC,EACJ,8DAyBIC,EAAN,KAAgB,CACN,OAAwB,KACxB,QAAUC,EAAK,IAAI,QAAQ,EAEnC,IAAI,WAAoB,CACtB,OAAO,OAAO,KAAK,KAAK,QAAQ,SAAS,EAAE,SAAS,QAAQ,CAC9D,CAEA,IAAI,WAAqB,CACvB,OAAO,KAAK,SAAW,IACzB,CAEA,WAAWC,EAAsBC,EAAwC,CACvE,IAAMC,EAAO,OAAO,KAAKF,EAAc,QAAQ,EACzCG,EAAe,OAAO,KAAKF,EAAiB,QAAQ,EACpDG,EAAQF,EAAK,SAAS,EAAGH,EAAK,IAAI,WAAW,EAC7CM,EAAaH,EAAK,SAASH,EAAK,IAAI,WAAW,EAC/CO,EAAYP,EAAK,IAAI,KACzB,IAAI,WAAWM,CAAU,EACzB,IAAI,WAAWD,CAAK,EACpB,IAAI,WAAWD,CAAY,EAC3B,KAAK,QAAQ,SACf,EACA,OAAOG,EAAY,IAAI,YAAY,EAAE,OAAOA,CAAS,EAAI,IAC3D,CAEA,OAAOC,EAAyB,CAC9B,KAAK,OAAS,OAAO,KAAKA,EAAW,OAAO,CAC9C,CAEA,QAAQD,EAA2B,CACjC,GAAI,CAAC,KAAK,OAAQ,MAAM,IAAI,MAAM,wBAAwB,EAC1D,IAAME,EAAKC,EAAY,EAAE,EACnBC,EAASC,EAAe,cAAe,KAAK,OAAQH,CAAE,EACtDI,EAAY,OAAO,OAAO,CAC9BF,EAAO,OAAOJ,EAAW,OAAO,EAChCI,EAAO,MAAM,CACf,CAAC,EAED,OADe,OAAO,OAAO,CAACF,EAAII,CAAS,CAAC,EAC9B,SAAS,QAAQ,CACjC,CAEA,QAAQV,EAAsB,CAC5B,GAAI,CAAC,KAAK,OAAQ,MAAM,IAAI,MAAM,wBAAwB,EAC1D,IAAMW,EAAM,OAAO,KAAKX,EAAM,QAAQ,EAChCM,EAAKK,EAAI,SAAS,EAAG,EAAE,EACvBR,EAAaQ,EAAI,SAAS,EAAE,EAC5BC,EAAWC,EAAiB,cAAe,KAAK,OAAQP,CAAE,EAChE,OAAO,OAAO,OAAO,CACnBM,EAAS,OAAOT,CAAU,EAC1BS,EAAS,MAAM,CACjB,CAAC,EAAE,SAAS,OAAO,CACrB,CAEA,OAAOZ,EAAuC,CAC5C,OAAO,KAAK,UACR,KAAK,QAAQ,KAAK,UAAUA,CAAI,CAAC,EACjC,KAAK,UAAUA,CAAI,CACzB,CAEA,OAAOA,EAAwC,CAC7C,OAAI,KAAK,WAAa,OAAOA,GAAS,SAC7B,KAAK,MAAM,KAAK,QAAQA,CAAI,CAAC,EAE/B,OAAOA,GAAS,SAClB,KAAK,MAAMA,CAAI,EACfA,CACP,CACF,EAEA,SAASc,EAAiBC,EAAgBC,EAAqC,CAC7E,OAAO,IAAI,QAAQ,CAACC,EAASC,IAAW,CACtC,IAAMC,EAAU,WAAW,IAAM,CAC/BD,EAAO,IAAI,MAAM,qBAAqB,CAAC,CACzC,EAAG,GAAM,EAETH,EAAO,KACL,YACA,CAACK,EAAsBrB,IAA4B,CACjD,aAAaoB,CAAO,EACpB,IAAME,EAAML,EAAU,WAAWI,EAAcrB,CAAe,EAC9D,GAAI,CAACsB,EAAK,CACRH,EAAO,IAAI,MAAM,iCAAiC,CAAC,EACnD,MACF,CAEA,IAAMI,EAAS,KAAK,MAAMD,CAAG,EAC7B,GACEC,EAAO,MACP,OAAOA,EAAO,MAAS,UACvB,KAAK,IAAI,KAAK,IAAI,EAAIA,EAAO,IAAI,EAAI,IACrC,CACAJ,EAAO,IAAI,MAAM,oBAAoB,CAAC,EACtC,MACF,CAEAF,EAAU,OAAOM,EAAO,GAAG,EAC3BL,EAAQ,CACV,CACF,EAEAF,EAAO,KAAK,YAAaC,EAAU,SAAS,CAC9C,CAAC,CACH,CAMA,SAASO,EAAWF,EAAaL,EAA8B,CAC7D,IAAMQ,EAAWH,EAAI,GAAG,KAAKA,CAAG,EAEhC,OAAAA,EAAI,IAAM,CAACI,EAAeC,IACpBD,IAAU,UACLD,EAASC,EAAQE,GAAiB,CACvC,GAAI,CACF,IAAMC,EAAUZ,EAAU,OAAOW,CAAG,EACpCD,EAAS,CAAE,OAAQE,EAAQ,OAAQ,KAAMA,EAAQ,MAAQ,CAAC,CAAE,CAAC,CAC/D,MAAQ,CAER,CACF,CAAC,EAEIJ,EAASC,EAAOC,CAAQ,GAG1BL,CACT,CAEO,IAAMQ,EAAN,cAA2BC,CAAY,CACnC,GAAK,QACN,UAAY,IAAIlC,EAChB,OAA8B,KAEtC,MAAM,MAAMmC,EAAiE,CACtE,KAAK,QACR,MAAM,KAAK,WAAW,EAGxB,IAAMC,EAAa,OAAO,OAAO,KAAK,QAAU,CAAC,CAAC,EAAE,KAAMC,GAAMA,EAAE,KAAK,EACvE,GAAI,CAACD,EAAY,MAAM,IAAI,MAAM,iCAAiC,EAElE,IAAME,EAAc,KAAK,aAAaF,EAAW,KAAMA,EAAW,IAAI,EACtE,YAAK,UAAY,IAAIpC,EAEN,MAAM,IAAI,QAAqB,CAACqB,EAASC,IAAW,CACjE,IAAMC,EAAU,WAAW,IAAM,CAC/Be,EAAY,WAAW,EACvBhB,EAAO,IAAI,MAAM,iBAAiB,CAAC,CACrC,EAAG,IAAM,EAETgB,EAAY,GAAG,UAAW,SAAY,CACpC,GAAI,CACF,MAAMpB,EAAiBoB,EAAa,KAAK,SAAS,EAElD,IAAMC,EACJ,UAAWJ,EACP,CAAE,SAAUA,EAAQ,SAAU,MAAOA,EAAQ,KAAM,EACnD,CAAE,SAAUA,EAAQ,SAAU,SAAUA,EAAQ,QAAS,EAEzDrB,EAAY,KAAK,UAAU,OAAO,CAAE,OAAQ,QAAS,KAAAyB,CAAK,CAAC,EACjED,EAAY,KAAK,UAAWxB,CAAS,CACvC,OAAS0B,EAAK,CACZ,aAAajB,CAAO,EACpBe,EAAY,WAAW,EACvBhB,EAAOkB,CAAG,CACZ,CACF,CAAC,EAEDF,EAAY,GAAG,UAAYP,GAAiB,CAC1C,GAAI,CACF,IAAMC,EAAU,KAAK,UAAU,OAAOD,CAAG,EACzC,GAAIC,EAAQ,SAAW,QAAS,OAEhC,aAAaT,CAAO,EACpBe,EAAY,WAAW,EAEvB,IAAMG,EAAWT,EAAQ,KAEzB,GAAI,CAACS,EAAS,QAAS,CACrBnB,EAAO,IAAI,MAAM,cAAc,CAAC,EAChC,MACF,CAEA,IAAMoB,EAAwB,OAAO,QACnCD,EAAS,aAAe,CAAC,CAC3B,EAAE,IAAI,CAAC,CAACE,EAAMC,CAAU,KAAO,CAAE,KAAAD,EAAM,WAAAC,CAAW,EAAE,EAEpDvB,EAAQ,CACN,QAAAqB,EACA,IAAKD,EAAS,IACd,SAAUA,EAAS,SACnB,UAAWA,EAAS,WAAa,GACjC,YAAaA,EAAS,aAAe,CAAC,CACxC,CAAC,CACH,OAASD,EAAK,CACZ,aAAajB,CAAO,EACpBe,EAAY,WAAW,EACvBhB,EAAOkB,CAAG,CACZ,CACF,CAAC,EAEDF,EAAY,GAAG,gBAAkBE,GAAe,CAC9C,aAAajB,CAAO,EACpBe,EAAY,WAAW,EACvBhB,EAAO,IAAI,MAAM,4BAA4BkB,EAAI,OAAO,EAAE,CAAC,CAC7D,CAAC,CACH,CAAC,CAGH,CAEA,MAAM,QACJK,EACAC,EACAX,EACiB,CACZ,KAAK,QACR,MAAM,KAAK,WAAW,EAGxB,IAAMY,EAAc,KAAK,SAASF,CAAU,EAC5C,GAAI,CAACE,EACH,MAAM,IAAI,MAAM,+BAA+BF,CAAU,EAAE,EAE7D,KAAK,UAAY,IAAI7C,EACrB,IAAMgD,EAAa,KAAK,aAAaD,EAAY,KAAMA,EAAY,IAAI,EACvE,YAAK,OAASC,EAEd,MAAM,IAAI,QAAc,CAAC3B,EAASC,IAAW,CAC3C,IAAMC,EAAU,WAAW,IAAM,CAC/ByB,EAAW,WAAW,EACtB1B,EAAO,IAAI,MAAM,2BAA2B,CAAC,CAC/C,EAAG,IAAM,EAET0B,EAAW,GAAG,UAAW,SAAY,CACnC,GAAI,CACF,MAAM9B,EAAiB8B,EAAY,KAAK,SAAS,EAEjD,IAAMlC,EAAY,KAAK,UAAU,OAAO,CACtC,OAAQ,YACR,KAAM,CACJ,SAAUgC,EAAY,SACtB,IAAKA,EAAY,IACjB,YAAa,EACf,CACF,CAAC,EACDE,EAAW,KAAK,UAAWlC,CAAS,CACtC,OAAS0B,EAAK,CACZ,aAAajB,CAAO,EACpByB,EAAW,WAAW,EACtB1B,EAAOkB,CAAG,CACZ,CACF,CAAC,EAEDQ,EAAW,GAAG,UAAYjB,GAAiB,CACzC,GAAI,CACF,IAAMC,EAAU,KAAK,UAAU,OAAOD,CAAG,EAEzC,OAAQC,EAAQ,OAAQ,CACtB,IAAK,oBAAqB,CACxBG,GAAS,gBAAgBH,EAAQ,IAA8B,EAC/D,KACF,CACA,IAAK,YAAa,CAEhB,GAAI,CADaA,EAAQ,KACX,QAAS,CACrB,aAAaT,CAAO,EACpByB,EAAW,WAAW,EACtB1B,EAAO,IAAI,MAAM,kBAAkB,CAAC,EACpC,MACF,CAEA,IAAM2B,EAAgB,KAAK,UAAU,OAAO,CAC1C,OAAQ,cACR,KAAM,CAAC,CACT,CAAC,EACDD,EAAW,KAAK,UAAWC,CAAa,EACxC,aAAa1B,CAAO,EACpBF,EAAQ,EACR,KACF,CACF,CACF,MAAQ,CAER,CACF,CAAC,EAED2B,EAAW,GAAG,gBAAkBR,GAAe,CAC7C,aAAajB,CAAO,EACpByB,EAAW,WAAW,EACtB1B,EAAO,IAAI,MAAM,2BAA2BkB,EAAI,OAAO,EAAE,CAAC,CAC5D,CAAC,CACH,CAAC,EAEMb,EAAWqB,EAAY,KAAK,SAAS,CAC9C,CAEA,KAAKE,EAAgBX,EAAqC,CACxD,GAAI,CAAC,KAAK,OAAQ,MAAM,IAAI,MAAM,eAAe,EACjD,IAAMzB,EAAY,KAAK,UAAU,OAAO,CAAE,OAAAoC,EAAQ,KAAAX,CAAK,CAAC,EACxD,KAAK,OAAO,KAAK,UAAWzB,CAAS,CACvC,CAEA,YAAmB,CACjB,KAAK,QAAQ,WAAW,EACxB,KAAK,OAAS,IAChB,CAES,cAAcW,EAAwC,CAC7D,MAAO,CACL,GAAG,KAAK,kBAAkBA,CAAG,EAC7B,GAAIA,EAAI,GACR,SAAUA,EAAI,SACd,YAAaA,EAAI,SACjB,EAAIA,EAAI,GAAgB,EACxB,EAAIA,EAAI,GAAgB,EACxB,MAAQA,EAAI,OAAoB,EAChC,KAAM,CACJ,SAAUA,EAAI,SACd,iBAAkBA,EAAI,iBACtB,gBAAiBA,EAAI,gBACrB,kBAAmBA,EAAI,kBACvB,sBAAuBA,EAAI,sBAC3B,UAAWA,EAAI,UACf,UAAWA,EAAI,UACf,UAAWA,EAAI,UACf,SAAUA,EAAI,SACd,QAASA,EAAI,OACf,EACA,KAAMA,CACR,CACF,CAES,gBAAgBA,EAA0C,CACjE,IAAM0B,EAAO1B,EAAI,KACjB,MAAO,CACL,GAAG,KAAK,cAAc0B,CAAI,EAC1B,KAAM1B,EACN,MAAQA,EAAI,OAAoB,EAChC,KAAOA,EAAI,MAAmB,EAC9B,UAAYA,EAAI,WAA0B,CAAC,EAC3C,QAAUA,EAAI,SAAuB,CAAC,EACtC,QAAUA,EAAI,SAAwB,CAAC,EACvC,UAAWA,EAAI,UACf,SAAWA,EAAI,WAA2B,CAAC,EAC3C,OAASA,EAAI,QAAwB,CAAC,CACxC,CACF,CAES,YAAY2B,EAAuB,CAC1C,KAAK,KAAK,eAAgB,CAAE,QAAAA,CAAQ,CAAC,CACvC,CAES,UAAUC,EAAqB,CACtC,KAAK,KAAK,aAAc,CAAE,MAAAA,CAAM,CAAC,CACnC,CAES,SAASC,EAAoB,CACpC,KAAK,KAAK,YAAa,CAAE,KAAAA,CAAK,CAAC,CACjC,CAES,KAAKC,EAAWC,EAAiB,CACxC,KAAK,KAAK,gBAAiB,CAAE,EAAAD,EAAG,EAAAC,CAAE,CAAC,CACrC,CAES,UAAUC,EAAeC,EAAqB,CACrD,KAAK,KAAK,aAAc,CAAE,MAAAD,EAAO,IAAAC,CAAI,CAAC,CACxC,CAES,SAASH,EAAWC,EAAiB,CAC5C,KAAK,KAAK,WAAY,CAAE,EAAAD,EAAG,EAAAC,CAAE,CAAC,CAChC,CAES,SAASG,EAAcJ,EAAYC,EAAkB,CAC5D,KAAK,KAAK,YAAa,CAAE,KAAAG,EAAM,EAAGJ,GAAK,EAAG,EAAGC,GAAK,CAAE,CAAC,CACvD,CAES,QAAQI,EAAoB,CACnC,KAAK,KAAK,WAAY,CAAE,KAAAA,CAAK,CAAC,CAChC,CAES,WAAWA,EAAoB,CACtC,KAAK,KAAK,eAAgB,CAAE,KAAAA,CAAK,CAAC,CACpC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,UAAUA,EAAoB,CACrC,KAAK,KAAK,cAAe,CAAE,KAAAA,CAAK,CAAC,CACnC,CAES,WAAWA,EAAoB,CACtC,KAAK,KAAK,eAAgB,CAAE,KAAAA,CAAK,CAAC,CACpC,CAES,aAAaC,EAAkB,CACtC,KAAK,KAAK,gBAAiB,CAAE,GAAAA,CAAG,CAAC,CACnC,CAES,YAAYA,EAAkB,CACrC,KAAK,KAAK,eAAgB,CAAE,GAAAA,CAAG,CAAC,CAClC,CAES,YAAYA,EAAkB,CACrC,KAAK,KAAK,eAAgB,CAAE,GAAAA,CAAG,CAAC,CAClC,CAES,YAAYA,EAAkB,CACrC,KAAK,KAAK,eAAgB,CAAE,GAAAA,CAAG,CAAC,CAClC,CAES,UAAUA,EAAkB,CACnC,KAAK,KAAK,aAAc,CAAE,GAAAA,CAAG,CAAC,CAChC,CAES,aAAaA,EAAkB,CACtC,KAAK,KAAK,gBAAiB,CAAE,GAAAA,CAAG,CAAC,CACnC,CAES,UAAUA,EAAkB,CACnC,KAAK,KAAK,aAAc,CAAE,GAAAA,CAAG,CAAC,CAChC,CAES,UAAUC,EAAeP,EAAYC,EAAkB,CAC9D,KAAK,KAAK,aAAc,CAAE,MAAAM,EAAO,EAAGP,GAAK,EAAG,EAAGC,GAAK,CAAE,CAAC,CACzD,CAEQ,aAAaO,EAAcC,EAAsB,CACvD,OAAOC,EAAGF,EAAM,CACd,KAAAC,EACA,WAAY,CAAC,UAAW,WAAW,EACnC,aAAc,EAChB,CAAC,CACH,CAEA,MAAc,YAA4B,CACxC,IAAME,EAAO,MAAM,MAAMnE,CAAU,EACnC,GAAI,CAACmE,EAAK,GAAI,MAAM,IAAI,MAAM,2BAA2BA,EAAK,MAAM,EAAE,EACtE,IAAMC,EAAU,MAAMD,EAAK,KAAK,EAChC,KAAK,OAASC,EAAO,MACvB,CACF,EClfA,IAAMC,EAAW,CACf,UAAWC,EACX,SAAUC,EACV,MAAOC,CACT,EAIO,SAASC,EAAcC,EAAgC,CAC5D,OAAO,IAAIL,EAASK,CAAI,CAC1B,CJaA,SAASC,EAAiBC,EAAqC,CAC7D,OACE,OAAOA,GAAQ,UAAYA,IAAQ,MAAQ,WAAYA,GAAO,SAAUA,CAE5E,CAEO,IAAMC,EAAN,cAAqBC,CAAa,CACvC,OAA4B,KAC5B,KAAsB,KACtB,MAA+B,IAAI,IACnC,UAAY,GAEJ,QACA,YAAkC,KAClC,IAAoB,KAE5B,YAAYC,EAAqBC,EAAyB,CACxD,MAAM,EACN,KAAK,QAAUC,EAAcF,CAAM,EAE/BC,GAAS,QACX,KAAK,IACH,OAAOA,EAAQ,OAAU,WACrBA,EAAQ,MACR,QAAQ,IAAI,KAAK,OAAO,EAElC,CAEA,MAAM,MACJA,EACuB,CACvB,YAAK,MAAM,wBAAyBA,EAAQ,QAAQ,EACpD,KAAK,YAAc,MAAM,KAAK,QAAQ,MAAMA,CAAO,EACnD,KAAK,MAAM,yBAAqB,KAAK,YAAY,QAAQ,OAAQ,SAAS,EACnE,KAAK,YAAY,OAC1B,CAEA,MAAM,QAAQE,EAAoBF,EAAyC,CACzE,GAAI,CAAC,KAAK,YAAa,MAAM,IAAI,MAAM,yBAAyB,EAEhE,KAAK,MAAM,oBAAqBE,CAAU,EAE1C,IAAMC,EAAiC,CACrC,GAAGH,EACH,cAAgBI,GAAwB,CACtC,KAAK,MAAM,UAAW,IAAIA,EAAO,QAAQ,IAAIA,EAAO,WAAW,EAAE,EACjE,KAAK,KAAK,oBAAqBA,CAAM,EACrCJ,GAAS,gBAAgBI,CAAM,CACjC,CACF,EAEMC,EAAS,MAAM,KAAK,QAAQ,QAChCH,EACA,KAAK,YACLC,CACF,EAEAE,EAAO,GAAG,UAAYT,GAAiB,CAChCD,EAAiBC,CAAG,GACzB,KAAK,cAAcA,CAAG,CACxB,CAAC,EAEDS,EAAO,GAAG,aAAc,IAAM,CAC5B,KAAK,MAAM,8BAA8B,EACzC,KAAK,QAAQ,EACb,KAAK,KAAK,YAAY,CACxB,CAAC,EAED,MAAM,IAAI,QAAc,CAACC,EAASC,IAAW,CAC3C,IAAMC,EAAU,WAAW,IAAM,CAC/BD,EAAO,IAAI,MAAM,mCAAmC,CAAC,CACvD,EAAG,GAAM,EAELE,EAAe,GACfC,EAAa,GAEXC,EAAa,IAAY,CACzBF,GAAgBC,IAClB,aAAaF,CAAO,EACpB,KAAK,UAAY,GACjBF,EAAQ,EAEZ,EAEMM,EAAahB,GAAuB,CACxC,GAAKD,EAAiBC,CAAG,EACzB,OAAQA,EAAI,OAAQ,CAClB,IAAK,cACHa,EAAe,GACfE,EAAW,EACX,MACF,IAAK,YACHD,EAAa,GACbC,EAAW,EACX,MACF,IAAK,OACH,aAAaH,CAAO,EACpBH,EAAO,IAAI,UAAWO,CAAS,EAC/BL,EACE,IAAI,MACF,WAAYX,EAAI,KAA6B,QAAU,SAAS,EAClE,CACF,EACA,MACF,IAAK,mBACH,aAAaY,CAAO,EACpBH,EAAO,IAAI,UAAWO,CAAS,EAC/BL,EACE,IAAI,MACF,WAAYX,EAAI,KAA4B,OAAS,SAAS,EAChE,CACF,EACA,MACF,IAAK,QACH,aAAaY,CAAO,EACpBH,EAAO,IAAI,UAAWO,CAAS,EAC/BL,EACE,IAAI,MACF,iBAAkBX,EAAI,KAAqC,OAAS,SAAS,EAC/E,CACF,EACA,KACJ,CACF,EAEMiB,EAAe,IAAY,EAC3B,CAACJ,GAAgB,CAACC,KACpB,aAAaF,CAAO,EACpBD,EAAO,IAAI,MAAM,kCAAkC,CAAC,EAExD,EAEAF,EAAO,GAAG,UAAWO,CAAS,EAC9BP,EAAO,KAAK,aAAcQ,CAAY,CACxC,CAAC,CACH,CAOA,GAAGC,EAAeC,EAA8C,CAC9D,OAAO,MAAM,GAAGD,EAAOC,CAAQ,CACjC,CAOA,IAAID,EAAeC,EAA8C,CAC/D,OAAO,MAAM,IAAID,EAAOC,CAAQ,CAClC,CAOA,KAAKD,EAAeC,EAA8C,CAChE,OAAO,MAAM,KAAKD,EAAOC,CAAQ,CACnC,CAOA,KAAKD,KAAkBE,EAA0B,CAC/C,OAAO,MAAM,KAAKF,EAAO,GAAGE,CAAI,CAClC,CAEA,YAAYC,EAAuB,CACjC,KAAK,QAAQ,YAAYA,CAAO,CAClC,CACA,UAAUC,EAAqB,CAC7B,KAAK,QAAQ,UAAUA,CAAK,CAC9B,CACA,SAASC,EAAoB,CAC3B,KAAK,QAAQ,SAASA,CAAI,CAC5B,CACA,KAAKC,EAAWC,EAAiB,CAC/B,KAAK,QAAQ,KAAKD,EAAGC,CAAC,CACxB,CACA,UAAUC,EAAeC,EAAqB,CAC5C,KAAK,QAAQ,UAAUD,EAAOC,CAAG,CACnC,CACA,SAASH,EAAWC,EAAiB,CACnC,KAAK,QAAQ,SAASD,EAAGC,CAAC,CAC5B,CACA,SAASG,EAAcJ,EAAYC,EAAkB,CACnD,KAAK,QAAQ,SAASG,EAAMJ,EAAGC,CAAC,CAClC,CACA,QAAQI,EAAoB,CAC1B,KAAK,QAAQ,QAAQA,CAAI,CAC3B,CACA,WAAWA,EAAoB,CAC7B,KAAK,QAAQ,WAAWA,CAAI,CAC9B,CACA,UAAUA,EAAoB,CAC5B,KAAK,QAAQ,UAAUA,CAAI,CAC7B,CACA,UAAUA,EAAoB,CAC5B,KAAK,QAAQ,UAAUA,CAAI,CAC7B,CACA,UAAUA,EAAoB,CAC5B,KAAK,QAAQ,UAAUA,CAAI,CAC7B,CACA,UAAUA,EAAoB,CAC5B,KAAK,QAAQ,UAAUA,CAAI,CAC7B,CACA,UAAUA,EAAoB,CAC5B,KAAK,QAAQ,UAAUA,CAAI,CAC7B,CACA,UAAUA,EAAoB,CAC5B,KAAK,QAAQ,UAAUA,CAAI,CAC7B,CACA,UAAUA,EAAoB,CAC5B,KAAK,QAAQ,UAAUA,CAAI,CAC7B,CACA,WAAWA,EAAoB,CAC7B,KAAK,QAAQ,WAAWA,CAAI,CAC9B,CACA,aAAaC,EAAkB,CAC7B,KAAK,QAAQ,aAAaA,CAAE,CAC9B,CACA,YAAYA,EAAkB,CAC5B,KAAK,QAAQ,YAAYA,CAAE,CAC7B,CACA,YAAYA,EAAkB,CAC5B,KAAK,QAAQ,YAAYA,CAAE,CAC7B,CACA,iBAAiBA,EAAkB,CACjC,KAAK,QAAQ,iBAAiBA,CAAE,CAClC,CACA,SAASA,EAAYC,EAAyC,CAC5D,KAAK,QAAQ,SAASD,EAAIC,CAAI,CAChC,CACA,YAAYD,EAAkB,CAC5B,KAAK,QAAQ,YAAYA,CAAE,CAC7B,CACA,UAAUA,EAAkB,CAC1B,KAAK,QAAQ,UAAUA,CAAE,CAC3B,CACA,aAAaA,EAAkB,CAC7B,KAAK,QAAQ,aAAaA,CAAE,CAC9B,CACA,UAAUA,EAAkB,CAC1B,KAAK,QAAQ,UAAUA,CAAE,CAC3B,CACA,aAAoB,CAClB,KAAK,QAAQ,YAAY,CAC3B,CACA,YAAmB,CACjB,KAAK,QAAQ,WAAW,CAC1B,CACA,aAAaE,EAAgBC,EAAsB,CACjD,KAAK,QAAQ,aAAaD,EAAQC,CAAM,CAC1C,CACA,UAAUD,EAAsB,CAC9B,KAAK,QAAQ,UAAUA,CAAM,CAC/B,CACA,cAAqB,CACnB,KAAK,QAAQ,aAAa,CAC5B,CACA,aAAaE,EAAqB,CAChC,KAAK,QAAQ,aAAaA,CAAK,CACjC,CACA,UAAUA,EAAeV,EAAYC,EAAkB,CACrD,KAAK,QAAQ,UAAUS,EAAOV,EAAGC,CAAC,CACpC,CACA,SAASU,EAAqB,CAC5B,KAAK,QAAQ,SAASA,CAAK,CAC7B,CACA,aAAaC,EAAqB,CAChC,KAAK,QAAQ,aAAaA,CAAK,CACjC,CAEA,MAAMC,EAA2B,CAC/B,OAAO,IAAI,QAAS3B,GAAY,WAAWA,EAAS2B,CAAE,CAAC,CACzD,CAEA,YAAmB,CACjB,KAAK,MAAM,iCAAiC,EAC5C,KAAK,QAAQ,WAAW,EACxB,KAAK,QAAQ,CACf,CAEQ,SAAgB,CACtB,KAAK,UAAY,GACjB,KAAK,OAAS,KACd,KAAK,KAAO,KACZ,KAAK,MAAM,MAAM,CACnB,CAEQ,cAAcrC,EAA2B,CAC/C,GAAM,CAAE,OAAAsC,EAAQ,KAAAlB,CAAK,EAAIpB,EACrBuC,EAAoBnB,EAExB,OAAQkB,EAAQ,CACd,IAAK,cAAe,CAClB,IAAME,EAAS,KAAK,QAAQ,gBAAgBpB,CAAI,EAChD,KAAK,OAASoB,EACdD,EAAW,CAAE,KAAMC,CAAO,EAC1B,KAAK,MACH,gBACAA,EAAO,SACP,MAAMA,EAAO,EAAE,GACf,SAASA,EAAO,KAAK,GACrB,aAAaA,EAAO,UAAU,MAAM,EACtC,EACA,KACF,CACA,IAAK,YAAa,CAChB,IAAMZ,EAAOR,EAAK,KACZqB,EAAWrB,EAAK,MACtB,KAAK,KAAOQ,EACZ,KAAK,MAAM,MAAM,EACjB,IAAMc,EAAoB,CAAC,EAC3B,QAAWC,KAAWF,EAAU,CAC9B,IAAMG,EAAO,KAAK,QAAQ,cAAcD,CAAO,EAC/C,KAAK,MAAM,IAAIC,EAAK,GAAIA,CAAI,EAC5BF,EAAM,KAAKE,CAAI,CACjB,CACAL,EAAW,CAAE,KAAAX,EAAM,MAAAc,CAAM,EACzB,KAAK,MAAM,cAAe,QAAQd,CAAI,GAAI,SAASc,EAAM,MAAM,EAAE,EACjE,KACF,CACA,IAAK,aAAc,CACjB,IAAME,EAAO,KAAK,QAAQ,cACxBxB,EAAK,IACP,EACA,KAAK,MAAM,IAAIwB,EAAK,GAAIA,CAAI,EAC5BL,EAAW,CAAE,KAAAK,CAAK,EAClB,KAAK,MAAM,eAAgBA,EAAK,SAAU,MAAMA,EAAK,EAAE,EAAE,EACzD,KACF,CACA,IAAK,gBAAiB,CACpB,IAAMd,EAAKV,EAAK,KAChB,KAAK,MAAM,OAAOU,CAAE,EACpB,KAAK,MAAM,kBAAmB,MAAMA,CAAE,EAAE,EACxC,KACF,CACA,IAAK,gBAAiB,CACpB,IAAMA,EAAKV,EAAK,GACVwB,EAAO,KAAK,MAAM,IAAId,CAAE,EAC1Bc,IACFA,EAAK,EAAIxB,EAAK,EACdwB,EAAK,EAAIxB,EAAK,GAEhB,KACF,CACA,IAAK,aAAc,CACjB,IAAMU,EAAKV,EAAK,GACVwB,EAAO,KAAK,MAAM,IAAId,CAAE,EAC1Bc,IACFA,EAAK,MAAQxB,EAAK,OAEpB,KACF,CACA,IAAK,gBAAiB,CACpB,IAAMU,EAAKV,EAAK,GACVyB,EAAOzB,EAAK,KACZS,EAAOT,EAAK,KACZwB,EAAO,KAAK,MAAM,IAAId,CAAE,EAC1Bc,GAAQC,KAAQD,IACjBA,EAAiCC,CAAI,EAAIhB,GAE5C,KACF,CACA,IAAK,OAAQ,CACX,IAAMiB,EAAU1B,EAA6B,QAAU,UACvD,KAAK,MAAM,SAAU0B,CAAM,EAC3B,KAAK,QAAQ,EACb,KACF,CACA,IAAK,mBAAoB,CACvB,IAAMC,EAAS3B,EAA4B,OAAS,UACpD,KAAK,MAAM,SAAU2B,CAAK,EAC1B,KAAK,QAAQ,EACb,KACF,CACA,QAAS,CACP,KAAK,MAAM,IAAIT,CAAM,IAAK,KAAK,UAAUlB,CAAI,CAAC,EAC9C,KACF,CACF,CAEA,IAAM4B,EAAYV,IAAW,QAAU,eAAiBA,EACxD,KAAK,KAAKU,EAAWT,CAAQ,CAC/B,CACF","names":["BaseAdapter","_raw","raw","_message","_emote","_safe","_x","_y","_frame","_set","_room","_item","_id","_type","_userId","_cardId","_igloo","_coins","_stamp","EventEmitter","io","msgpackParser","BASE_URL","DEFAULT_SECRET","CpjourneyAdapter","BaseAdapter","options","loginSocket","resolve","reject","timeout","secret","args","msg","response","servers","name","population","err","serverName","loginResult","gameSocket","authSent","action","raw","user","normalized","message","emote","safe","x","y","frame","set","room","item","id","type","userId","cardId","igloo","coins","stamp","path","io","msgpackParser","io","msgpackParser","LOGIN_URL","TOKEN_LOGIN_URL","wrapSocket","raw","original","event","listener","action","args","CplegacyAdapter","BaseAdapter","options","url","body","data","name","population","serverName","loginResult","wsUrl","rawSocket","io","msgpackParser","resolve","reject","timeout","err","user","b","message","emote","safe","x","y","frame","set","room","item","id","userId","igloo","coins","stamp","createCipheriv","createDecipheriv","randomBytes","io","nacl","CRUMBS_URL","Encryptor","nacl","encryptedB64","serverPubKeyB64","data","serverPubKey","nonce","ciphertext","plaintext","keyString","iv","randomBytes","cipher","createCipheriv","encrypted","buf","decipher","createDecipheriv","performHandshake","socket","encryptor","resolve","reject","timeout","encryptedKey","raw","parsed","wrapSocket","original","event","listener","msg","decoded","NewcpAdapter","BaseAdapter","options","loginWorld","w","loginSocket","args","err","response","servers","name","population","serverName","loginResult","worldConfig","gameSocket","joinEncrypted","action","user","message","emote","safe","x","y","frame","set","room","item","id","igloo","host","path","io","resp","crumbs","ADAPTERS","CpjourneyAdapter","CplegacyAdapter","NewcpAdapter","createAdapter","name","isMessagePayload","msg","Client","EventEmitter","server","options","createAdapter","serverName","connectOptions","update","socket","resolve","reject","timeout","playerLoaded","roomJoined","checkReady","onMessage","onDisconnect","event","listener","args","message","emote","safe","x","y","frame","set","room","item","id","type","userId","cardId","igloo","coins","stamp","ms","action","emitArgs","player","rawUsers","users","rawUser","user","slot","reason","error","eventName"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shaunlwm/pickle.ts",
3
- "version": "0.5.0",
3
+ "version": "1.0.0",
4
4
  "description": "Club Penguin Private Server client library",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",