@shaunlwm/pickle.ts 0.0.1 → 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 +32 -3
- package/dist/index.d.ts +491 -7
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/package.json +8 -3
- package/dist/adapters/base-adapter.d.ts +0 -39
- package/dist/adapters/base-adapter.d.ts.map +0 -1
- package/dist/adapters/base-adapter.js +0 -79
- package/dist/adapters/base-adapter.js.map +0 -1
- package/dist/adapters/cpjourney-adapter.d.ts +0 -12
- package/dist/adapters/cpjourney-adapter.d.ts.map +0 -1
- package/dist/adapters/cpjourney-adapter.js +0 -114
- package/dist/adapters/cpjourney-adapter.js.map +0 -1
- package/dist/adapters/index.d.ts +0 -9
- package/dist/adapters/index.d.ts.map +0 -1
- package/dist/adapters/index.js +0 -8
- package/dist/adapters/index.js.map +0 -1
- package/dist/client.d.ts +0 -60
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js +0 -191
- package/dist/client.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/types/adapter-types.d.ts +0 -27
- package/dist/types/adapter-types.d.ts.map +0 -1
- package/dist/types/adapter-types.js +0 -2
- package/dist/types/adapter-types.js.map +0 -1
- package/dist/types/message-types.d.ts +0 -159
- package/dist/types/message-types.d.ts.map +0 -1
- package/dist/types/message-types.js +0 -2
- package/dist/types/message-types.js.map +0 -1
- package/dist/types/player-types.d.ts +0 -85
- package/dist/types/player-types.d.ts.map +0 -1
- package/dist/types/player-types.js +0 -2
- package/dist/types/player-types.js.map +0 -1
package/README.md
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
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
|
|
|
9
9
|
```bash
|
|
10
|
-
npm install pickle.ts
|
|
10
|
+
npm install @shaunlwm/pickle.ts
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
## Quick Start
|
|
@@ -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
|
@@ -1,7 +1,491 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import { Socket } from 'socket.io-client';
|
|
3
|
+
|
|
4
|
+
type ServerInfo = {
|
|
5
|
+
name: string;
|
|
6
|
+
population: number;
|
|
7
|
+
};
|
|
8
|
+
type LoginOptions = {
|
|
9
|
+
username: string;
|
|
10
|
+
password: string;
|
|
11
|
+
secret?: string;
|
|
12
|
+
};
|
|
13
|
+
type TokenLoginOptions = {
|
|
14
|
+
username: string;
|
|
15
|
+
token: string;
|
|
16
|
+
secret?: string;
|
|
17
|
+
};
|
|
18
|
+
type LoginResult = {
|
|
19
|
+
servers: ServerInfo[];
|
|
20
|
+
key: string;
|
|
21
|
+
username: string;
|
|
22
|
+
moderator: boolean;
|
|
23
|
+
buddyWorlds: string[];
|
|
24
|
+
};
|
|
25
|
+
type QueueUpdate = {
|
|
26
|
+
userId: number;
|
|
27
|
+
position: number;
|
|
28
|
+
queueLength: number;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
type ConnectOptions = {
|
|
32
|
+
onQueueUpdate?: (update: QueueUpdate) => void;
|
|
33
|
+
};
|
|
34
|
+
declare abstract class BaseAdapter {
|
|
35
|
+
abstract readonly id: string;
|
|
36
|
+
protected socket: Socket | null;
|
|
37
|
+
abstract login(options: LoginOptions | TokenLoginOptions): Promise<LoginResult>;
|
|
38
|
+
abstract connect(serverName: string, loginResult: LoginResult, options?: ConnectOptions): Promise<Socket>;
|
|
39
|
+
abstract disconnect(): void;
|
|
40
|
+
abstract send(action: string, args: Record<string, unknown>): void;
|
|
41
|
+
sendMessage(message: string): void;
|
|
42
|
+
sendEmote(emote: number): void;
|
|
43
|
+
sendSafe(safe: number): void;
|
|
44
|
+
walk(x: number, y: number): void;
|
|
45
|
+
sendFrame(frame: number, set?: boolean): void;
|
|
46
|
+
snowball(x: number, y: number): void;
|
|
47
|
+
joinRoom(room: number, x?: number, y?: number): void;
|
|
48
|
+
addItem(item: number): void;
|
|
49
|
+
equipColor(item: number): void;
|
|
50
|
+
equipHead(item: number): void;
|
|
51
|
+
equipFace(item: number): void;
|
|
52
|
+
equipNeck(item: number): void;
|
|
53
|
+
equipBody(item: number): void;
|
|
54
|
+
equipHand(item: number): void;
|
|
55
|
+
equipFeet(item: number): void;
|
|
56
|
+
equipFlag(item: number): void;
|
|
57
|
+
equipPhoto(item: number): void;
|
|
58
|
+
buddyRequest(id: number): void;
|
|
59
|
+
buddyAccept(id: number): void;
|
|
60
|
+
buddyReject(id: number): void;
|
|
61
|
+
buddyRequestSeen(id: number): void;
|
|
62
|
+
getBuddy(id: number, type: "buddies" | "buddyRequests"): void;
|
|
63
|
+
removeBuddy(id: number): void;
|
|
64
|
+
addIgnore(id: number): void;
|
|
65
|
+
removeIgnore(id: number): void;
|
|
66
|
+
getPlayer(id: number): void;
|
|
67
|
+
getAllSlots(): void;
|
|
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;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
declare class CpjourneyAdapter extends BaseAdapter {
|
|
76
|
+
readonly id = "CPJourney";
|
|
77
|
+
login(options: LoginOptions | TokenLoginOptions): Promise<LoginResult>;
|
|
78
|
+
connect(serverName: string, loginResult: LoginResult, options?: ConnectOptions): Promise<Socket>;
|
|
79
|
+
send(action: string, args: Record<string, unknown>): void;
|
|
80
|
+
disconnect(): void;
|
|
81
|
+
private createSocket;
|
|
82
|
+
}
|
|
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
|
+
|
|
94
|
+
declare const ADAPTERS: {
|
|
95
|
+
readonly CPJourney: typeof CpjourneyAdapter;
|
|
96
|
+
readonly CPLegacy: typeof CplegacyAdapter;
|
|
97
|
+
};
|
|
98
|
+
type AdapterName = keyof typeof ADAPTERS;
|
|
99
|
+
|
|
100
|
+
type PlayerAppearance = {
|
|
101
|
+
color: number;
|
|
102
|
+
hat: number;
|
|
103
|
+
head: number;
|
|
104
|
+
face: number;
|
|
105
|
+
face_mask: number;
|
|
106
|
+
neck: number;
|
|
107
|
+
neck_scarf: number;
|
|
108
|
+
body: number;
|
|
109
|
+
body_shirt: number;
|
|
110
|
+
hand: number;
|
|
111
|
+
hand_glove: number;
|
|
112
|
+
feet: number;
|
|
113
|
+
flag: number;
|
|
114
|
+
photo: number;
|
|
115
|
+
transform: number;
|
|
116
|
+
};
|
|
117
|
+
type PlayerSettings = {
|
|
118
|
+
music_volume: number;
|
|
119
|
+
sfx_volume: number;
|
|
120
|
+
hide_penguins: boolean;
|
|
121
|
+
hide_chats: boolean;
|
|
122
|
+
hide_emotes: boolean;
|
|
123
|
+
hide_ui: boolean;
|
|
124
|
+
hide_usernames: boolean;
|
|
125
|
+
quality: number;
|
|
126
|
+
silence_notifications: boolean;
|
|
127
|
+
opt_out_postcards: boolean;
|
|
128
|
+
opt_out_buddy_requests: boolean;
|
|
129
|
+
};
|
|
130
|
+
type Buddy = {
|
|
131
|
+
id: number;
|
|
132
|
+
username: string;
|
|
133
|
+
online: boolean;
|
|
134
|
+
favorite: boolean;
|
|
135
|
+
items: number[];
|
|
136
|
+
onlineServer: string;
|
|
137
|
+
};
|
|
138
|
+
type RoomUser = PlayerAppearance & {
|
|
139
|
+
id: number;
|
|
140
|
+
username: string;
|
|
141
|
+
displayName: string;
|
|
142
|
+
joinTime: string;
|
|
143
|
+
x: number;
|
|
144
|
+
y: number;
|
|
145
|
+
frame: number;
|
|
146
|
+
walking: number;
|
|
147
|
+
walkingPuffleType: number;
|
|
148
|
+
openSprite?: string;
|
|
149
|
+
mascotGiveaway?: unknown;
|
|
150
|
+
iglooOpen: number;
|
|
151
|
+
iglooBounds: number;
|
|
152
|
+
igloo_slot: number;
|
|
153
|
+
currentLayer: number;
|
|
154
|
+
fireRank: number;
|
|
155
|
+
};
|
|
156
|
+
type PlayerData = RoomUser & {
|
|
157
|
+
coins: number;
|
|
158
|
+
partyCoins: number;
|
|
159
|
+
gems: number;
|
|
160
|
+
rank: number;
|
|
161
|
+
streamer: boolean;
|
|
162
|
+
username_verified: boolean;
|
|
163
|
+
email_verified: boolean;
|
|
164
|
+
settings: PlayerSettings;
|
|
165
|
+
buddies: Buddy[];
|
|
166
|
+
buddyRequests: number[];
|
|
167
|
+
ignores: number[];
|
|
168
|
+
inventory: number[];
|
|
169
|
+
puffleInventory: unknown[];
|
|
170
|
+
igloos: unknown[];
|
|
171
|
+
furniture: unknown[];
|
|
172
|
+
flooring: unknown[];
|
|
173
|
+
inf_skill_points: number;
|
|
174
|
+
highest_floor_reached: number;
|
|
175
|
+
towerMeters: number;
|
|
176
|
+
towerExperience: number;
|
|
177
|
+
};
|
|
178
|
+
type Mascot = {
|
|
179
|
+
id: number;
|
|
180
|
+
name: string;
|
|
181
|
+
giveaway: number;
|
|
182
|
+
stamp: number;
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
type ClientMessages = {
|
|
186
|
+
send_position: {
|
|
187
|
+
x: number;
|
|
188
|
+
y: number;
|
|
189
|
+
};
|
|
190
|
+
send_frame: {
|
|
191
|
+
frame: number;
|
|
192
|
+
set?: boolean;
|
|
193
|
+
};
|
|
194
|
+
send_message: {
|
|
195
|
+
message: string;
|
|
196
|
+
};
|
|
197
|
+
join_room: {
|
|
198
|
+
room: number;
|
|
199
|
+
x?: number;
|
|
200
|
+
y?: number;
|
|
201
|
+
};
|
|
202
|
+
add_item: {
|
|
203
|
+
item: number;
|
|
204
|
+
};
|
|
205
|
+
send_emote: {
|
|
206
|
+
emote: number;
|
|
207
|
+
};
|
|
208
|
+
send_safe: {
|
|
209
|
+
safe: number;
|
|
210
|
+
};
|
|
211
|
+
snowball: {
|
|
212
|
+
x: number;
|
|
213
|
+
y: number;
|
|
214
|
+
};
|
|
215
|
+
buddy_request: {
|
|
216
|
+
id: number;
|
|
217
|
+
};
|
|
218
|
+
buddy_accept: {
|
|
219
|
+
id: number;
|
|
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
|
+
};
|
|
231
|
+
remove_buddy: {
|
|
232
|
+
id: number;
|
|
233
|
+
};
|
|
234
|
+
get_player: {
|
|
235
|
+
id: number;
|
|
236
|
+
};
|
|
237
|
+
ignore_add: {
|
|
238
|
+
id: number;
|
|
239
|
+
};
|
|
240
|
+
ignore_remove: {
|
|
241
|
+
id: number;
|
|
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
|
+
};
|
|
258
|
+
update_color: {
|
|
259
|
+
item: number;
|
|
260
|
+
};
|
|
261
|
+
update_head: {
|
|
262
|
+
item: number;
|
|
263
|
+
};
|
|
264
|
+
update_face: {
|
|
265
|
+
item: number;
|
|
266
|
+
};
|
|
267
|
+
update_neck: {
|
|
268
|
+
item: number;
|
|
269
|
+
};
|
|
270
|
+
update_body: {
|
|
271
|
+
item: number;
|
|
272
|
+
};
|
|
273
|
+
update_hand: {
|
|
274
|
+
item: number;
|
|
275
|
+
};
|
|
276
|
+
update_feet: {
|
|
277
|
+
item: number;
|
|
278
|
+
};
|
|
279
|
+
update_flag: {
|
|
280
|
+
item: number;
|
|
281
|
+
};
|
|
282
|
+
update_photo: {
|
|
283
|
+
item: number;
|
|
284
|
+
};
|
|
285
|
+
get_all_slots: Record<string, never>;
|
|
286
|
+
get_mascots: Record<string, never>;
|
|
287
|
+
get_weather: Record<string, never>;
|
|
288
|
+
join_server: Record<string, never>;
|
|
289
|
+
check_puffle_sprite: {
|
|
290
|
+
puffleSprite: unknown;
|
|
291
|
+
};
|
|
292
|
+
};
|
|
293
|
+
type ServerMessages = {
|
|
294
|
+
login: {
|
|
295
|
+
success: boolean;
|
|
296
|
+
username: string;
|
|
297
|
+
key: string;
|
|
298
|
+
populations: Record<string, number>;
|
|
299
|
+
moderator: boolean;
|
|
300
|
+
buddyWorlds: string[];
|
|
301
|
+
};
|
|
302
|
+
game_auth: {
|
|
303
|
+
success: boolean;
|
|
304
|
+
token?: string;
|
|
305
|
+
};
|
|
306
|
+
load_player: {
|
|
307
|
+
user: PlayerData;
|
|
308
|
+
};
|
|
309
|
+
join_room: {
|
|
310
|
+
room: number;
|
|
311
|
+
users: RoomUser[];
|
|
312
|
+
};
|
|
313
|
+
add_player: {
|
|
314
|
+
user: RoomUser;
|
|
315
|
+
};
|
|
316
|
+
remove_player: {
|
|
317
|
+
user: number;
|
|
318
|
+
};
|
|
319
|
+
send_position: {
|
|
320
|
+
id: number;
|
|
321
|
+
x: number;
|
|
322
|
+
y: number;
|
|
323
|
+
};
|
|
324
|
+
send_frame: {
|
|
325
|
+
id: number;
|
|
326
|
+
frame: number;
|
|
327
|
+
set?: boolean;
|
|
328
|
+
};
|
|
329
|
+
send_message: {
|
|
330
|
+
id: number;
|
|
331
|
+
message: string;
|
|
332
|
+
};
|
|
333
|
+
send_emote: {
|
|
334
|
+
id: number;
|
|
335
|
+
emote: number;
|
|
336
|
+
};
|
|
337
|
+
set_weather: {
|
|
338
|
+
type: string;
|
|
339
|
+
intensity: number;
|
|
340
|
+
};
|
|
341
|
+
open_sprite: {
|
|
342
|
+
id: number;
|
|
343
|
+
sprite: string;
|
|
344
|
+
};
|
|
345
|
+
close_sprite: {
|
|
346
|
+
id: number;
|
|
347
|
+
};
|
|
348
|
+
wait_queue_update: QueueUpdate;
|
|
349
|
+
cpj_ping: Record<string, never>;
|
|
350
|
+
get_mascots: {
|
|
351
|
+
mascots: Mascot[];
|
|
352
|
+
};
|
|
353
|
+
get_player: {
|
|
354
|
+
user: RoomUser;
|
|
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
|
+
};
|
|
411
|
+
update_player: {
|
|
412
|
+
id: number;
|
|
413
|
+
item: number;
|
|
414
|
+
slot: string;
|
|
415
|
+
};
|
|
416
|
+
slot: unknown[];
|
|
417
|
+
error: {
|
|
418
|
+
error: number;
|
|
419
|
+
};
|
|
420
|
+
kick: {
|
|
421
|
+
reason: string;
|
|
422
|
+
};
|
|
423
|
+
close_with_error: {
|
|
424
|
+
error: string;
|
|
425
|
+
};
|
|
426
|
+
disconnect: void;
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
type ServerMessageHandler<K extends keyof ServerMessages> = (args: ServerMessages[K]) => void;
|
|
430
|
+
type LogFn = (message: string, ...args: unknown[]) => void;
|
|
431
|
+
type ClientOptions = {
|
|
432
|
+
debug?: boolean | LogFn;
|
|
433
|
+
};
|
|
434
|
+
declare class Client extends EventEmitter {
|
|
435
|
+
player: PlayerData | null;
|
|
436
|
+
room: number | null;
|
|
437
|
+
users: Map<number, RoomUser>;
|
|
438
|
+
connected: boolean;
|
|
439
|
+
private adapter;
|
|
440
|
+
private loginResult;
|
|
441
|
+
private log;
|
|
442
|
+
constructor(server: AdapterName, options?: ClientOptions);
|
|
443
|
+
login(options: LoginOptions | TokenLoginOptions): Promise<ServerInfo[]>;
|
|
444
|
+
connect(serverName: string, options?: ConnectOptions): Promise<void>;
|
|
445
|
+
on<K extends keyof ServerMessages>(event: K, listener: ServerMessageHandler<K>): this;
|
|
446
|
+
on(event: string, listener: (...args: unknown[]) => void): this;
|
|
447
|
+
off<K extends keyof ServerMessages>(event: K, listener: ServerMessageHandler<K>): this;
|
|
448
|
+
off(event: string, listener: (...args: unknown[]) => void): this;
|
|
449
|
+
once<K extends keyof ServerMessages>(event: K, listener: ServerMessageHandler<K>): this;
|
|
450
|
+
once(event: string, listener: (...args: unknown[]) => void): this;
|
|
451
|
+
emit<K extends keyof ServerMessages>(event: K, args: ServerMessages[K]): boolean;
|
|
452
|
+
emit(event: string, ...args: unknown[]): boolean;
|
|
453
|
+
sendMessage(message: string): void;
|
|
454
|
+
sendEmote(emote: number): void;
|
|
455
|
+
sendSafe(safe: number): void;
|
|
456
|
+
walk(x: number, y: number): void;
|
|
457
|
+
sendFrame(frame: number, set?: boolean): void;
|
|
458
|
+
snowball(x: number, y: number): void;
|
|
459
|
+
joinRoom(room: number, x?: number, y?: number): void;
|
|
460
|
+
addItem(item: number): void;
|
|
461
|
+
equipColor(item: number): void;
|
|
462
|
+
equipHead(item: number): void;
|
|
463
|
+
equipFace(item: number): void;
|
|
464
|
+
equipNeck(item: number): void;
|
|
465
|
+
equipBody(item: number): void;
|
|
466
|
+
equipHand(item: number): void;
|
|
467
|
+
equipFeet(item: number): void;
|
|
468
|
+
equipFlag(item: number): void;
|
|
469
|
+
equipPhoto(item: number): void;
|
|
470
|
+
buddyRequest(id: number): void;
|
|
471
|
+
buddyAccept(id: number): void;
|
|
472
|
+
buddyReject(id: number): void;
|
|
473
|
+
buddyRequestSeen(id: number): void;
|
|
474
|
+
getBuddy(id: number, type: "buddies" | "buddyRequests"): void;
|
|
475
|
+
removeBuddy(id: number): void;
|
|
476
|
+
addIgnore(id: number): void;
|
|
477
|
+
removeIgnore(id: number): void;
|
|
478
|
+
getPlayer(id: number): void;
|
|
479
|
+
getAllSlots(): void;
|
|
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;
|
|
485
|
+
sleep(ms: number): Promise<void>;
|
|
486
|
+
disconnect(): void;
|
|
487
|
+
private cleanup;
|
|
488
|
+
private handleMessage;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
export { type AdapterName, BaseAdapter, type Buddy, Client, type ClientMessages, type ClientOptions, type ConnectOptions, type LogFn, type LoginOptions, type LoginResult, type Mascot, type PlayerAppearance, type PlayerData, type PlayerSettings, type QueueUpdate, type RoomUser, type ServerInfo, type ServerMessages, type TokenLoginOptions };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export { BaseAdapter } from "./adapters/base-adapter.js";
|
|
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};
|
|
3
2
|
//# sourceMappingURL=index.js.map
|