@shaunlwm/pickle.ts 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -2
- package/dist/index.d.ts +116 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Type-safe client library for Club Penguin Private Servers.
|
|
4
4
|
|
|
5
|
-
Built with TypeScript, Socket.IO, and msgpack. Supports multiple CPPS backends through an adapter pattern —
|
|
5
|
+
Built with TypeScript, Socket.IO, and msgpack. Supports multiple CPPS backends through an adapter pattern — ships with CPJourney and CPLegacy support.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -44,7 +44,7 @@ Creates a new client instance.
|
|
|
44
44
|
|
|
45
45
|
| Param | Type | Description |
|
|
46
46
|
|---|---|---|
|
|
47
|
-
| `server` | `"CPJourney"` | CPPS server identifier (strongly typed) |
|
|
47
|
+
| `server` | `"CPJourney" \| "CPLegacy"` | CPPS server identifier (strongly typed) |
|
|
48
48
|
| `options.debug` | `boolean \| LogFn` | Enable debug logging. Pass `true` for console.log, or a custom function |
|
|
49
49
|
|
|
50
50
|
```typescript
|
|
@@ -102,6 +102,7 @@ After `connect()` resolves, `client.player`, `client.room`, and `client.users` a
|
|
|
102
102
|
| `client.player` | `PlayerData \| null` | Your penguin's full data (coins, inventory, settings, etc.) |
|
|
103
103
|
| `client.room` | `number \| null` | Current room ID |
|
|
104
104
|
| `client.users` | `Map<number, RoomUser>` | All penguins in the current room, keyed by ID |
|
|
105
|
+
| `client.connected` | `boolean` | Whether the client is connected to a game server |
|
|
105
106
|
|
|
106
107
|
`client.users` is automatically kept in sync — players are added/removed as they join/leave, positions and equipment update in real-time.
|
|
107
108
|
|
|
@@ -134,10 +135,20 @@ client.addItem(itemId)
|
|
|
134
135
|
// Social
|
|
135
136
|
client.buddyRequest(userId)
|
|
136
137
|
client.buddyAccept(userId)
|
|
138
|
+
client.buddyReject(userId)
|
|
139
|
+
client.buddyRequestSeen(userId)
|
|
140
|
+
client.getBuddy(userId, "buddies") // fetch buddy details
|
|
141
|
+
client.getBuddy(userId, "buddyRequests") // fetch request details
|
|
137
142
|
client.removeBuddy(userId)
|
|
138
143
|
client.addIgnore(userId)
|
|
139
144
|
client.removeIgnore(userId)
|
|
140
145
|
client.getPlayer(userId)
|
|
146
|
+
client.sendPostcard(userId, "62") // send mail (costs coins)
|
|
147
|
+
|
|
148
|
+
// Stamps & Igloos
|
|
149
|
+
client.getStamps(userId) // view stampbook
|
|
150
|
+
client.getIglooOpen(userId) // check if igloo is open
|
|
151
|
+
client.joinIgloo(userId) // enter igloo
|
|
141
152
|
|
|
142
153
|
// Animation
|
|
143
154
|
client.sendFrame(frameId)
|
|
@@ -191,11 +202,29 @@ client.on("wait_queue_update", ({ position, queueLength }) => {
|
|
|
191
202
|
console.log(`Queue: #${position}/${queueLength}`)
|
|
192
203
|
})
|
|
193
204
|
|
|
205
|
+
client.on("kick", ({ reason }) => {
|
|
206
|
+
console.log(`Kicked: ${reason}`)
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
client.on("close_with_error", ({ error }) => {
|
|
210
|
+
console.log(`Disconnected: ${error}`)
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
client.on("buddy_accept", ({ id, username, online }) => {
|
|
214
|
+
console.log(`${username} accepted your buddy request (online: ${online})`)
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
client.on("stamps_result", ({ stamps, username }) => {
|
|
218
|
+
console.log(`${username} has ${stamps.length} stamps`)
|
|
219
|
+
})
|
|
220
|
+
|
|
194
221
|
client.on("disconnect", () => {
|
|
195
222
|
console.log("Connection lost")
|
|
196
223
|
})
|
|
197
224
|
```
|
|
198
225
|
|
|
226
|
+
The `kick` event fires on CPLegacy, `close_with_error` on CPJourney — both indicate the server forcibly disconnected the client (e.g. duplicate login). State is automatically cleaned up in both cases.
|
|
227
|
+
|
|
199
228
|
## Types
|
|
200
229
|
|
|
201
230
|
All types are exported for external use:
|
package/dist/index.d.ts
CHANGED
|
@@ -57,12 +57,19 @@ declare abstract class BaseAdapter {
|
|
|
57
57
|
equipPhoto(item: number): void;
|
|
58
58
|
buddyRequest(id: number): void;
|
|
59
59
|
buddyAccept(id: number): void;
|
|
60
|
+
buddyReject(id: number): void;
|
|
61
|
+
buddyRequestSeen(id: number): void;
|
|
62
|
+
getBuddy(id: number, type: "buddies" | "buddyRequests"): void;
|
|
60
63
|
removeBuddy(id: number): void;
|
|
61
64
|
addIgnore(id: number): void;
|
|
62
65
|
removeIgnore(id: number): void;
|
|
63
66
|
getPlayer(id: number): void;
|
|
64
67
|
getAllSlots(): void;
|
|
65
68
|
getMascots(): void;
|
|
69
|
+
sendPostcard(userId: number, cardId: string): void;
|
|
70
|
+
getStamps(userId: number): void;
|
|
71
|
+
getIglooOpen(igloo: number): void;
|
|
72
|
+
joinIgloo(igloo: number, x?: number, y?: number): void;
|
|
66
73
|
}
|
|
67
74
|
|
|
68
75
|
declare class CpjourneyAdapter extends BaseAdapter {
|
|
@@ -74,8 +81,19 @@ declare class CpjourneyAdapter extends BaseAdapter {
|
|
|
74
81
|
private createSocket;
|
|
75
82
|
}
|
|
76
83
|
|
|
84
|
+
declare class CplegacyAdapter extends BaseAdapter {
|
|
85
|
+
readonly id = "CPLegacy";
|
|
86
|
+
private version;
|
|
87
|
+
login(options: LoginOptions | TokenLoginOptions): Promise<LoginResult>;
|
|
88
|
+
connect(serverName: string, loginResult: LoginResult, options?: ConnectOptions): Promise<Socket>;
|
|
89
|
+
send(action: string, args: Record<string, unknown>): void;
|
|
90
|
+
disconnect(): void;
|
|
91
|
+
private postLogin;
|
|
92
|
+
}
|
|
93
|
+
|
|
77
94
|
declare const ADAPTERS: {
|
|
78
95
|
readonly CPJourney: typeof CpjourneyAdapter;
|
|
96
|
+
readonly CPLegacy: typeof CplegacyAdapter;
|
|
79
97
|
};
|
|
80
98
|
type AdapterName = keyof typeof ADAPTERS;
|
|
81
99
|
|
|
@@ -200,18 +218,43 @@ type ClientMessages = {
|
|
|
200
218
|
buddy_accept: {
|
|
201
219
|
id: number;
|
|
202
220
|
};
|
|
221
|
+
buddy_reject: {
|
|
222
|
+
id: number;
|
|
223
|
+
};
|
|
224
|
+
buddy_request_seen: {
|
|
225
|
+
id: number;
|
|
226
|
+
};
|
|
227
|
+
get_buddy: {
|
|
228
|
+
id: number;
|
|
229
|
+
type: "buddies" | "buddyRequests";
|
|
230
|
+
};
|
|
203
231
|
remove_buddy: {
|
|
204
232
|
id: number;
|
|
205
233
|
};
|
|
206
234
|
get_player: {
|
|
207
235
|
id: number;
|
|
208
236
|
};
|
|
209
|
-
|
|
237
|
+
ignore_add: {
|
|
210
238
|
id: number;
|
|
211
239
|
};
|
|
212
|
-
|
|
240
|
+
ignore_remove: {
|
|
213
241
|
id: number;
|
|
214
242
|
};
|
|
243
|
+
send_postcard: {
|
|
244
|
+
userId: number;
|
|
245
|
+
cardId: string;
|
|
246
|
+
};
|
|
247
|
+
get_stamps: {
|
|
248
|
+
userId: number;
|
|
249
|
+
};
|
|
250
|
+
get_igloo_open: {
|
|
251
|
+
igloo: number;
|
|
252
|
+
};
|
|
253
|
+
join_igloo: {
|
|
254
|
+
igloo: number;
|
|
255
|
+
x?: number;
|
|
256
|
+
y?: number;
|
|
257
|
+
};
|
|
215
258
|
update_color: {
|
|
216
259
|
item: number;
|
|
217
260
|
};
|
|
@@ -310,6 +353,61 @@ type ServerMessages = {
|
|
|
310
353
|
get_player: {
|
|
311
354
|
user: RoomUser;
|
|
312
355
|
};
|
|
356
|
+
buddy_request: {
|
|
357
|
+
id: number;
|
|
358
|
+
};
|
|
359
|
+
buddy_accept: {
|
|
360
|
+
id: number;
|
|
361
|
+
username: string;
|
|
362
|
+
requester: boolean;
|
|
363
|
+
online: boolean;
|
|
364
|
+
};
|
|
365
|
+
buddy_reject: {
|
|
366
|
+
id: number;
|
|
367
|
+
};
|
|
368
|
+
buddy_request_seen: {
|
|
369
|
+
id: number;
|
|
370
|
+
};
|
|
371
|
+
get_buddy: {
|
|
372
|
+
id: number;
|
|
373
|
+
penguin: Record<string, unknown>;
|
|
374
|
+
type: "buddies" | "buddyRequests";
|
|
375
|
+
};
|
|
376
|
+
send_postcard: {
|
|
377
|
+
coins: number;
|
|
378
|
+
};
|
|
379
|
+
stamps_result: {
|
|
380
|
+
stamps: number[];
|
|
381
|
+
inventory: number[];
|
|
382
|
+
coverOnly: number[];
|
|
383
|
+
unseen: number[];
|
|
384
|
+
username: string;
|
|
385
|
+
playerColor: number;
|
|
386
|
+
stampbook: {
|
|
387
|
+
userId: number;
|
|
388
|
+
colour: number;
|
|
389
|
+
clasp: number;
|
|
390
|
+
highlight: number;
|
|
391
|
+
pattern: number;
|
|
392
|
+
};
|
|
393
|
+
coverStamps: {
|
|
394
|
+
stampId: number;
|
|
395
|
+
itemId: number;
|
|
396
|
+
x: number;
|
|
397
|
+
y: number;
|
|
398
|
+
rotation: number;
|
|
399
|
+
}[];
|
|
400
|
+
};
|
|
401
|
+
ignore_add: {
|
|
402
|
+
id: number;
|
|
403
|
+
username: string;
|
|
404
|
+
};
|
|
405
|
+
ignore_remove: {
|
|
406
|
+
id: number;
|
|
407
|
+
};
|
|
408
|
+
get_igloo_open: {
|
|
409
|
+
open: boolean;
|
|
410
|
+
};
|
|
313
411
|
update_player: {
|
|
314
412
|
id: number;
|
|
315
413
|
item: number;
|
|
@@ -319,6 +417,13 @@ type ServerMessages = {
|
|
|
319
417
|
error: {
|
|
320
418
|
error: number;
|
|
321
419
|
};
|
|
420
|
+
kick: {
|
|
421
|
+
reason: string;
|
|
422
|
+
};
|
|
423
|
+
close_with_error: {
|
|
424
|
+
error: string;
|
|
425
|
+
};
|
|
426
|
+
disconnect: void;
|
|
322
427
|
};
|
|
323
428
|
|
|
324
429
|
type ServerMessageHandler<K extends keyof ServerMessages> = (args: ServerMessages[K]) => void;
|
|
@@ -330,6 +435,7 @@ declare class Client extends EventEmitter {
|
|
|
330
435
|
player: PlayerData | null;
|
|
331
436
|
room: number | null;
|
|
332
437
|
users: Map<number, RoomUser>;
|
|
438
|
+
connected: boolean;
|
|
333
439
|
private adapter;
|
|
334
440
|
private loginResult;
|
|
335
441
|
private log;
|
|
@@ -363,14 +469,22 @@ declare class Client extends EventEmitter {
|
|
|
363
469
|
equipPhoto(item: number): void;
|
|
364
470
|
buddyRequest(id: number): void;
|
|
365
471
|
buddyAccept(id: number): void;
|
|
472
|
+
buddyReject(id: number): void;
|
|
473
|
+
buddyRequestSeen(id: number): void;
|
|
474
|
+
getBuddy(id: number, type: "buddies" | "buddyRequests"): void;
|
|
366
475
|
removeBuddy(id: number): void;
|
|
367
476
|
addIgnore(id: number): void;
|
|
368
477
|
removeIgnore(id: number): void;
|
|
369
478
|
getPlayer(id: number): void;
|
|
370
479
|
getAllSlots(): void;
|
|
371
480
|
getMascots(): void;
|
|
481
|
+
sendPostcard(userId: number, cardId: string): void;
|
|
482
|
+
getStamps(userId: number): void;
|
|
483
|
+
getIglooOpen(igloo: number): void;
|
|
484
|
+
joinIgloo(igloo: number, x?: number, y?: number): void;
|
|
372
485
|
sleep(ms: number): Promise<void>;
|
|
373
486
|
disconnect(): void;
|
|
487
|
+
private cleanup;
|
|
374
488
|
private handleMessage;
|
|
375
489
|
}
|
|
376
490
|
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{EventEmitter as
|
|
1
|
+
import{EventEmitter as A}from"events";import{io as f}from"socket.io-client";import w from"socket.io-msgpack-parser";var p=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,s){this.send("send_position",{x:e,y:s})}sendFrame(e,s){this.send("send_frame",{frame:e,set:s})}snowball(e,s){this.send("snowball",{x:e,y:s})}joinRoom(e,s,o){this.send("join_room",{room:e,x:s??0,y:o??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,s){this.send("get_buddy",{id:e,type:s})}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,s){this.send("send_postcard",{userId:e,cardId:s})}getStamps(e){this.send("get_stamps",{userId:e})}getIglooOpen(e){this.send("get_igloo_open",{igloo:e})}joinIgloo(e,s,o){this.send("join_igloo",{igloo:e,x:s??0,y:o??0})}};var _="wss://play.cpjourney.net",R="skip",l=class extends p{id="CPJourney";async login(e){let s=this.createSocket("/world/login/");return await new Promise((n,t)=>{let a=setTimeout(()=>{s.disconnect(),t(new Error("Login timed out"))},1e4);s.on("connect",()=>{let r=e.secret??R,i="token"in e?{username:e.username,token:e.token,secret:r}:{username:e.username,password:e.password,secret:r};s.emit("message",{action:"login",args:i})}),s.on("message",r=>{if(r.action!=="login")return;clearTimeout(a),s.disconnect();let i=r.args;if(!i.success){t(new Error("Login failed"));return}let u=Object.entries(i.populations).map(([c,m])=>({name:c,population:m}));n({servers:u,key:i.key,username:i.username,moderator:i.moderator,buddyWorlds:i.buddyWorlds??[]})}),s.on("connect_error",r=>{clearTimeout(a),s.disconnect(),t(new Error(`Login connection failed: ${r.message}`))})})}async connect(e,s,o){let n=this.createSocket(`/world/${e.toLowerCase()}/`);return this.socket=n,await new Promise((t,a)=>{let r=!1;n.on("connect",()=>{n.emit("message",{action:"game_auth",args:{username:s.username,key:s.key,createToken:!1,joinInvis:!1,takeoverMascot:!1,token:""}})}),n.on("message",i=>{switch(i.action){case"wait_queue_update":{o?.onQueueUpdate?.(i.args);break}case"game_auth":{if(r)break;if(r=!0,!i.args.success){n.disconnect(),a(new Error("Game auth failed"));return}n.emit("message",{action:"join_server",args:{}}),t();break}}}),n.on("connect_error",i=>{n.disconnect(),a(new Error(`Game connection failed: ${i.message}`))})}),n}send(e,s){if(!this.socket)throw new Error("Not connected");this.socket.emit("message",{action:e,args:s})}disconnect(){this.socket?.disconnect(),this.socket=null}createSocket(e){return f(_,{path:e,parser:w,transports:["polling","websocket"],reconnection:!1})}};import{io as S}from"socket.io-client";import L from"socket.io-msgpack-parser";var P="https://api.cplegacy.com/login",q="https://api.cplegacy.com/token_login";function O(d){let e=d.on.bind(d);return d.on=function(s,o){return s==="message"?e(s,(n,t)=>{o({action:n,args:t??{}})}):e(s,o)},d}var h=class extends p{id="CPLegacy";version="";async login(e){let s="token"in e?q:P,o="token"in e?{username:e.username,token:e.token}:{username:e.username,password:e.password,version:this.version},n=await this.postLogin(s,o);if(!n.success&&n.wantedVersion&&(this.version=n.wantedVersion,o.version=this.version,n=await this.postLogin(s,o)),!n.success)throw new Error(`Login failed: ${n.message??"unknown error"}`);return{servers:Object.entries(n.populations??{}).map(([a,r])=>({name:a,population:r})),key:n.key,username:n.username,moderator:!1,buddyWorlds:[]}}async connect(e,s,o){let n=`wss://${e.toLowerCase()}.server.cplegacy.com`,t=S(n,{path:"/socket.io/",parser:L,transports:["websocket"],reconnection:!1});return this.socket=t,await new Promise((a,r)=>{let i=setTimeout(()=>{t.disconnect(),r(new Error("Game connection timed out"))},15e3);t.on("connect",()=>{t.emit("message","game_auth",{username:s.username,key:s.key,createToken:!1,token:""})}),t.on("message",(u,c)=>{switch(u){case"wait_queue_update":{o?.onQueueUpdate?.(c);break}case"game_auth":{if(!c.success){clearTimeout(i),t.disconnect(),r(new Error("Game auth failed"));return}t.emit("message","load_player",{}),t.emit("message","join_server",{}),clearTimeout(i),a();break}}}),t.on("connect_error",u=>{clearTimeout(i),t.disconnect(),r(new Error(`Game connection failed: ${u.message}`))})}),O(t)}send(e,s){if(!this.socket)throw new Error("Not connected");this.socket.emit("message",e,s)}disconnect(){this.socket?.disconnect(),this.socket=null}async postLogin(e,s){return(await fetch(e,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(s)})).json()}};var M={CPJourney:l,CPLegacy:h};function y(d){return new M[d]}function v(d){return typeof d=="object"&&d!==null&&"action"in d&&"args"in d}var b=class extends A{player=null;room=null;users=new Map;connected=!1;adapter;loginResult=null;log=null;constructor(e,s){super(),this.adapter=y(e),s?.debug&&(this.log=typeof s.debug=="function"?s.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,s){if(!this.loginResult)throw new Error("Must call login() first");this.log?.("[connect] joining",e);let o={...s,onQueueUpdate:t=>{this.log?.("[queue]",`#${t.position}/${t.queueLength}`),this.emit("wait_queue_update",t),s?.onQueueUpdate?.(t)}},n=await this.adapter.connect(e,this.loginResult,o);n.on("message",t=>{v(t)&&this.handleMessage(t)}),n.on("disconnect",()=>{this.log?.("[disconnect] connection lost"),this.cleanup(),this.emit("disconnect")}),await new Promise((t,a)=>{let r=setTimeout(()=>{a(new Error("Waiting for load_player timed out"))},1e4),i=!1,u=!1,c=()=>{i&&u&&(clearTimeout(r),this.connected=!0,t())},m=g=>{if(v(g))switch(g.action){case"load_player":i=!0,c();break;case"join_room":u=!0,c();break;case"kick":clearTimeout(r),n.off("message",m),a(new Error(`Kicked: ${g.args.reason??"unknown"}`));break;case"close_with_error":clearTimeout(r),n.off("message",m),a(new Error(`Kicked: ${g.args.error??"unknown"}`));break}},k=()=>{(!i||!u)&&(clearTimeout(r),a(new Error("Disconnected before fully loaded")))};n.on("message",m),n.once("disconnect",k)})}on(e,s){return super.on(e,s)}off(e,s){return super.off(e,s)}once(e,s){return super.once(e,s)}emit(e,...s){return super.emit(e,...s)}sendMessage(e){this.adapter.sendMessage(e)}sendEmote(e){this.adapter.sendEmote(e)}sendSafe(e){this.adapter.sendSafe(e)}walk(e,s){this.adapter.walk(e,s)}sendFrame(e,s){this.adapter.sendFrame(e,s)}snowball(e,s){this.adapter.snowball(e,s)}joinRoom(e,s,o){this.adapter.joinRoom(e,s,o)}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,s){this.adapter.getBuddy(e,s)}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,s){this.adapter.sendPostcard(e,s)}getStamps(e){this.adapter.getStamps(e)}getIglooOpen(e){this.adapter.getIglooOpen(e)}joinIgloo(e,s,o){this.adapter.joinIgloo(e,s,o)}sleep(e){return new Promise(s=>setTimeout(s,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:s,args:o}=e;switch(s){case"load_player":{let n=o.user;this.player=n,this.log?.("[load_player]",n.username,`id=${n.id}`);break}case"join_room":{let n=o.room,t=o.users;this.room=n,this.users.clear();for(let a of t)this.users.set(a.id,a);this.log?.("[join_room]",`room=${n}`,`users=${t.length}`);break}case"add_player":{let n=o.user;this.users.set(n.id,n),this.log?.("[add_player]",n.username,`id=${n.id}`);break}case"remove_player":{let n=o.user;this.users.delete(n),this.log?.("[remove_player]",`id=${n}`);break}case"send_position":{let n=o.id,t=this.users.get(n);t&&(t.x=o.x,t.y=o.y);break}case"send_frame":{let n=o.id,t=this.users.get(n);t&&(t.frame=o.frame);break}case"update_player":{let n=o.id,t=o.slot,a=o.item,r=this.users.get(n);r&&t in r&&(r[t]=a);break}case"kick":{let n=o.reason??"unknown";this.log?.("[kick]",n),this.cleanup();break}case"close_with_error":{let n=o.error??"unknown";this.log?.("[kick]",n),this.cleanup();break}default:{this.log?.(`[${s}]`,JSON.stringify(o));break}}this.emit(s,o)}};export{p as BaseAdapter,b as Client};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client.ts","../src/adapters/cpjourney-adapter.ts","../src/adapters/base-adapter.ts","../src/adapters/index.ts"],"sourcesContent":["import { EventEmitter } from \"node:events\"\nimport { createAdapter, type AdapterName } from \"./adapters/index.js\"\nimport type { BaseAdapter, ConnectOptions } from \"./adapters/base-adapter.js\"\nimport type { LoginOptions, LoginResult, QueueUpdate, ServerInfo, TokenLoginOptions } 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> = (args: ServerMessages[K]) => 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 typeof msg === \"object\" && msg !== null && \"action\" in msg && \"args\" in msg\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\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 = typeof options.debug === \"function\"\n ? options.debug\n : console.log.bind(console)\n }\n }\n\n async login(options: LoginOptions | TokenLoginOptions): 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(serverName, this.loginResult, connectOptions)\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 resolve()\n }\n }\n\n socket.on(\"message\", (msg: unknown) => {\n if (!isMessagePayload(msg)) return\n this.handleMessage(msg)\n\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 }\n })\n\n socket.on(\"disconnect\", () => {\n clearTimeout(timeout)\n if (!playerLoaded || !roomJoined) {\n reject(new Error(\"Disconnected before fully loaded\"))\n }\n this.emit(\"disconnect\")\n })\n })\n }\n\n on<K extends keyof ServerMessages>(event: K, listener: ServerMessageHandler<K>): 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>(event: K, listener: ServerMessageHandler<K>): 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>(event: K, listener: ServerMessageHandler<K>): 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>(event: K, args: ServerMessages[K]): 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 { this.adapter.sendMessage(message) }\n sendEmote(emote: number): void { this.adapter.sendEmote(emote) }\n sendSafe(safe: number): void { this.adapter.sendSafe(safe) }\n walk(x: number, y: number): void { this.adapter.walk(x, y) }\n sendFrame(frame: number, set?: boolean): void { this.adapter.sendFrame(frame, set) }\n snowball(x: number, y: number): void { this.adapter.snowball(x, y) }\n joinRoom(room: number, x?: number, y?: number): void { this.adapter.joinRoom(room, x, y) }\n addItem(item: number): void { this.adapter.addItem(item) }\n equipColor(item: number): void { this.adapter.equipColor(item) }\n equipHead(item: number): void { this.adapter.equipHead(item) }\n equipFace(item: number): void { this.adapter.equipFace(item) }\n equipNeck(item: number): void { this.adapter.equipNeck(item) }\n equipBody(item: number): void { this.adapter.equipBody(item) }\n equipHand(item: number): void { this.adapter.equipHand(item) }\n equipFeet(item: number): void { this.adapter.equipFeet(item) }\n equipFlag(item: number): void { this.adapter.equipFlag(item) }\n equipPhoto(item: number): void { this.adapter.equipPhoto(item) }\n buddyRequest(id: number): void { this.adapter.buddyRequest(id) }\n buddyAccept(id: number): void { this.adapter.buddyAccept(id) }\n removeBuddy(id: number): void { this.adapter.removeBuddy(id) }\n addIgnore(id: number): void { this.adapter.addIgnore(id) }\n removeIgnore(id: number): void { this.adapter.removeIgnore(id) }\n getPlayer(id: number): void { this.adapter.getPlayer(id) }\n getAllSlots(): void { this.adapter.getAllSlots() }\n getMascots(): void { this.adapter.getMascots() }\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.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 this.player = user\n this.log?.(\"[load_player]\", user.username, `id=${user.id}`)\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 default: {\n this.log?.(`[${action}]`, JSON.stringify(args))\n break\n }\n }\n\n this.emit(action, args)\n }\n}\n","import { io, type Socket } from \"socket.io-client\"\nimport msgpackParser from \"socket.io-msgpack-parser\"\nimport type { LoginOptions, LoginResult, QueueUpdate, ServerInfo, TokenLoginOptions } 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 = \"token\" in options\n ? { username: options.username, token: options.token, secret }\n : { username: options.username, password: options.password, secret }\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(serverName: string, loginResult: LoginResult, options?: ConnectOptions): 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 type { Socket } from \"socket.io-client\"\nimport type { LoginOptions, LoginResult, QueueUpdate, TokenLoginOptions } 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(options: LoginOptions | TokenLoginOptions): Promise<LoginResult>\n abstract connect(serverName: string, loginResult: LoginResult, options?: ConnectOptions): 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 removeBuddy(id: number): void {\n this.send(\"remove_buddy\", { id })\n }\n\n addIgnore(id: number): void {\n this.send(\"add_ignore\", { id })\n }\n\n removeIgnore(id: number): void {\n this.send(\"remove_ignore\", { 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","import type { BaseAdapter } from \"./base-adapter.js\"\nimport { CpjourneyAdapter } from \"./cpjourney-adapter.js\"\n\nconst ADAPTERS = {\n CPJourney: CpjourneyAdapter,\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":["EventEmitter","io","msgpackParser","BaseAdapter","message","emote","safe","x","y","frame","set","room","item","id","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","ADAPTERS","CpjourneyAdapter","createAdapter","name","isMessagePayload","msg","Client","EventEmitter","server","options","createAdapter","serverName","connectOptions","update","socket","resolve","reject","timeout","playerLoaded","roomJoined","checkReady","event","listener","args","message","emote","safe","x","y","frame","set","room","item","id","ms","action","user","users","slot"]}
|
|
1
|
+
{"version":3,"sources":["../src/client.ts","../src/adapters/cpjourney-adapter.ts","../src/adapters/base-adapter.ts","../src/adapters/cplegacy-adapter.ts","../src/adapters/index.ts"],"sourcesContent":["import { EventEmitter } from \"node:events\"\nimport { createAdapter, type AdapterName } from \"./adapters/index.js\"\nimport type { BaseAdapter, ConnectOptions } from \"./adapters/base-adapter.js\"\nimport type { LoginOptions, LoginResult, QueueUpdate, ServerInfo, TokenLoginOptions } 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> = (args: ServerMessages[K]) => 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 typeof msg === \"object\" && msg !== null && \"action\" in msg && \"args\" in msg\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 = typeof options.debug === \"function\"\n ? options.debug\n : console.log.bind(console)\n }\n }\n\n async login(options: LoginOptions | TokenLoginOptions): 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(serverName, this.loginResult, connectOptions)\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(new Error(`Kicked: ${(msg.args as { reason?: string }).reason ?? \"unknown\"}`))\n break\n case \"close_with_error\":\n clearTimeout(timeout)\n socket.off(\"message\", onMessage)\n reject(new Error(`Kicked: ${(msg.args as { error?: string }).error ?? \"unknown\"}`))\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>(event: K, listener: ServerMessageHandler<K>): 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>(event: K, listener: ServerMessageHandler<K>): 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>(event: K, listener: ServerMessageHandler<K>): 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>(event: K, args: ServerMessages[K]): 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 { this.adapter.sendMessage(message) }\n sendEmote(emote: number): void { this.adapter.sendEmote(emote) }\n sendSafe(safe: number): void { this.adapter.sendSafe(safe) }\n walk(x: number, y: number): void { this.adapter.walk(x, y) }\n sendFrame(frame: number, set?: boolean): void { this.adapter.sendFrame(frame, set) }\n snowball(x: number, y: number): void { this.adapter.snowball(x, y) }\n joinRoom(room: number, x?: number, y?: number): void { this.adapter.joinRoom(room, x, y) }\n addItem(item: number): void { this.adapter.addItem(item) }\n equipColor(item: number): void { this.adapter.equipColor(item) }\n equipHead(item: number): void { this.adapter.equipHead(item) }\n equipFace(item: number): void { this.adapter.equipFace(item) }\n equipNeck(item: number): void { this.adapter.equipNeck(item) }\n equipBody(item: number): void { this.adapter.equipBody(item) }\n equipHand(item: number): void { this.adapter.equipHand(item) }\n equipFeet(item: number): void { this.adapter.equipFeet(item) }\n equipFlag(item: number): void { this.adapter.equipFlag(item) }\n equipPhoto(item: number): void { this.adapter.equipPhoto(item) }\n buddyRequest(id: number): void { this.adapter.buddyRequest(id) }\n buddyAccept(id: number): void { this.adapter.buddyAccept(id) }\n buddyReject(id: number): void { this.adapter.buddyReject(id) }\n buddyRequestSeen(id: number): void { this.adapter.buddyRequestSeen(id) }\n getBuddy(id: number, type: \"buddies\" | \"buddyRequests\"): void { this.adapter.getBuddy(id, type) }\n removeBuddy(id: number): void { this.adapter.removeBuddy(id) }\n addIgnore(id: number): void { this.adapter.addIgnore(id) }\n removeIgnore(id: number): void { this.adapter.removeIgnore(id) }\n getPlayer(id: number): void { this.adapter.getPlayer(id) }\n getAllSlots(): void { this.adapter.getAllSlots() }\n getMascots(): void { this.adapter.getMascots() }\n sendPostcard(userId: number, cardId: string): void { this.adapter.sendPostcard(userId, cardId) }\n getStamps(userId: number): void { this.adapter.getStamps(userId) }\n getIglooOpen(igloo: number): void { this.adapter.getIglooOpen(igloo) }\n joinIgloo(igloo: number, x?: number, y?: number): void { this.adapter.joinIgloo(igloo, x, y) }\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 this.player = user\n this.log?.(\"[load_player]\", user.username, `id=${user.id}`)\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 this.emit(action, args)\n }\n}\n","import { io, type Socket } from \"socket.io-client\"\nimport msgpackParser from \"socket.io-msgpack-parser\"\nimport type { LoginOptions, LoginResult, QueueUpdate, ServerInfo, TokenLoginOptions } 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 = \"token\" in options\n ? { username: options.username, token: options.token, secret }\n : { username: options.username, password: options.password, secret }\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(serverName: string, loginResult: LoginResult, options?: ConnectOptions): 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 type { Socket } from \"socket.io-client\"\nimport type { LoginOptions, LoginResult, QueueUpdate, TokenLoginOptions } 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(options: LoginOptions | TokenLoginOptions): Promise<LoginResult>\n abstract connect(serverName: string, loginResult: LoginResult, options?: ConnectOptions): 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 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","import { io, type Socket } from \"socket.io-client\"\nimport msgpackParser from \"socket.io-msgpack-parser\"\nimport type { LoginOptions, LoginResult, QueueUpdate, ServerInfo, TokenLoginOptions } 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 = function (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> = \"token\" in options\n ? { username: options.username, token: options.token }\n : { username: options.username, password: options.password, version: this.version }\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(serverName: string, loginResult: LoginResult, options?: ConnectOptions): 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(\"message\", (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 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(url: string, body: Record<string, unknown>): 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 type { BaseAdapter } from \"./base-adapter.js\"\nimport { CpjourneyAdapter } from \"./cpjourney-adapter.js\"\nimport { CplegacyAdapter } from \"./cplegacy-adapter.js\"\n\nconst ADAPTERS = {\n CPJourney: CpjourneyAdapter,\n CPLegacy: CplegacyAdapter,\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":["EventEmitter","io","msgpackParser","BaseAdapter","message","emote","safe","x","y","frame","set","room","item","id","type","userId","cardId","igloo","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","ADAPTERS","CpjourneyAdapter","CplegacyAdapter","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","ms","action","user","users","slot","reason","error"]}
|