@rpgjs/server 5.0.0-alpha.42 → 5.0.0-alpha.44
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/Player/ParameterManager.d.ts +14 -0
- package/dist/index.js +515 -3995
- package/dist/index.js.map +1 -1
- package/dist/module-CuaepWlN.js +3965 -0
- package/dist/module-CuaepWlN.js.map +1 -0
- package/dist/node/connection.d.ts +51 -0
- package/dist/node/index.d.ts +5 -0
- package/dist/node/index.js +703 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/map.d.ts +16 -0
- package/dist/node/room.d.ts +21 -0
- package/dist/node/transport.d.ts +28 -0
- package/dist/node/types.d.ts +47 -0
- package/dist/rooms/map.d.ts +1 -1
- package/package.json +15 -4
- package/src/Player/MoveManager.ts +25 -4
- package/src/Player/ParameterManager.ts +103 -5
- package/src/Player/SkillManager.ts +67 -10
- package/src/Player/VariableManager.ts +11 -3
- package/src/node/connection.ts +254 -0
- package/src/node/index.ts +22 -0
- package/src/node/map.ts +328 -0
- package/src/node/room.ts +63 -0
- package/src/node/transport.ts +532 -0
- package/src/node/types.ts +61 -0
- package/src/rooms/map.ts +39 -11
- package/tests/event.spec.ts +1 -1
- package/tests/node-transport.spec.ts +223 -0
- package/tests/player-param.spec.ts +18 -1
- package/tests/world-maps.spec.ts +1 -1
- package/vite.config.ts +20 -3
|
@@ -176,6 +176,48 @@ export interface SkillObject extends SkillHooks {
|
|
|
176
176
|
*/
|
|
177
177
|
export function WithSkillManager<TBase extends PlayerCtor>(Base: TBase): TBase {
|
|
178
178
|
return class extends (Base as any) {
|
|
179
|
+
private _getSkillSnapshot(skillData: any) {
|
|
180
|
+
if (!skillData) return null;
|
|
181
|
+
|
|
182
|
+
const snapshot = {
|
|
183
|
+
...((skillData as any)._skillData || skillData),
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const reactiveKeys = [
|
|
187
|
+
"id",
|
|
188
|
+
"name",
|
|
189
|
+
"description",
|
|
190
|
+
"spCost",
|
|
191
|
+
"icon",
|
|
192
|
+
"hitRate",
|
|
193
|
+
"power",
|
|
194
|
+
"coefficient",
|
|
195
|
+
];
|
|
196
|
+
|
|
197
|
+
for (const key of reactiveKeys) {
|
|
198
|
+
const value = (skillData as any)[key];
|
|
199
|
+
if (typeof value === "function") {
|
|
200
|
+
if (key === "hitRate" && !(key in snapshot)) {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
snapshot[key] = value();
|
|
204
|
+
} else if (value !== undefined) {
|
|
205
|
+
snapshot[key] = value;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if ((skillData as any)._skillInstance) {
|
|
210
|
+
snapshot._skillInstance = (skillData as any)._skillInstance;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return snapshot;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
private _getLearnedSkillEntry(skillInput: SkillClass | SkillObject | string): Skill | null {
|
|
217
|
+
const index = this._getSkillIndex(skillInput);
|
|
218
|
+
return index >= 0 ? ((this as any).skills()[index] as Skill) : null;
|
|
219
|
+
}
|
|
220
|
+
|
|
179
221
|
private _getSkillMap(required: boolean = true) {
|
|
180
222
|
// Use this.map directly to support both RpgMap and LobbyRoom
|
|
181
223
|
const map = (this as any).getCurrentMap?.() || (this as any).map;
|
|
@@ -246,6 +288,10 @@ export function WithSkillManager<TBase extends PlayerCtor>(Base: TBase): TBase {
|
|
|
246
288
|
) {
|
|
247
289
|
const instance = new Skill(skillData);
|
|
248
290
|
instance.id.set(skillId);
|
|
291
|
+
(instance as any)._skillData = {
|
|
292
|
+
...skillData,
|
|
293
|
+
id: skillId,
|
|
294
|
+
};
|
|
249
295
|
|
|
250
296
|
if (skillInstance) {
|
|
251
297
|
(instance as any)._skillInstance = skillInstance;
|
|
@@ -349,8 +395,8 @@ export function WithSkillManager<TBase extends PlayerCtor>(Base: TBase): TBase {
|
|
|
349
395
|
* ```
|
|
350
396
|
*/
|
|
351
397
|
getSkill(skillInput: SkillClass | SkillObject | string): Skill | null {
|
|
352
|
-
const
|
|
353
|
-
return
|
|
398
|
+
const skill = this._getLearnedSkillEntry(skillInput);
|
|
399
|
+
return this._getSkillSnapshot(skill) as Skill | null;
|
|
354
400
|
}
|
|
355
401
|
|
|
356
402
|
/**
|
|
@@ -389,7 +435,7 @@ export function WithSkillManager<TBase extends PlayerCtor>(Base: TBase): TBase {
|
|
|
389
435
|
const { skillId, skillData, skillInstance } = this._resolveSkillInput(skillInput, map);
|
|
390
436
|
|
|
391
437
|
// Check if already learned
|
|
392
|
-
if (this.
|
|
438
|
+
if (this._getLearnedSkillEntry(skillId)) {
|
|
393
439
|
throw SkillLog.alreadyLearned(skillData);
|
|
394
440
|
}
|
|
395
441
|
|
|
@@ -438,11 +484,15 @@ export function WithSkillManager<TBase extends PlayerCtor>(Base: TBase): TBase {
|
|
|
438
484
|
throw SkillLog.notLearned(skillData);
|
|
439
485
|
}
|
|
440
486
|
|
|
441
|
-
const
|
|
487
|
+
const skillEntry = (this as any).skills()[index];
|
|
488
|
+
const skillData = this._getSkillSnapshot(skillEntry);
|
|
442
489
|
(this as any).skills().splice(index, 1);
|
|
443
490
|
|
|
444
491
|
// Call onForget hook
|
|
445
|
-
const hookTarget =
|
|
492
|
+
const hookTarget =
|
|
493
|
+
(skillEntry as any)?._skillInstance ||
|
|
494
|
+
(skillEntry as any)?._skillData ||
|
|
495
|
+
skillData;
|
|
446
496
|
this["execMethod"]("onForget", [this], hookTarget);
|
|
447
497
|
|
|
448
498
|
return skillData;
|
|
@@ -475,7 +525,8 @@ export function WithSkillManager<TBase extends PlayerCtor>(Base: TBase): TBase {
|
|
|
475
525
|
* ```
|
|
476
526
|
*/
|
|
477
527
|
useSkill(skillInput: SkillClass | SkillObject | string, otherPlayer?: RpgPlayer | RpgPlayer[]): any {
|
|
478
|
-
const
|
|
528
|
+
const skillEntry = this._getLearnedSkillEntry(skillInput);
|
|
529
|
+
const skill = this._getSkillSnapshot(skillEntry);
|
|
479
530
|
|
|
480
531
|
// Check for skill restriction effect
|
|
481
532
|
if ((this as any).hasEffect(Effect.CAN_NOT_SKILL)) {
|
|
@@ -488,7 +539,7 @@ export function WithSkillManager<TBase extends PlayerCtor>(Base: TBase): TBase {
|
|
|
488
539
|
}
|
|
489
540
|
|
|
490
541
|
// Check SP cost
|
|
491
|
-
const spCost = skill.spCost
|
|
542
|
+
const spCost = typeof skill.spCost === "number" ? skill.spCost : 0;
|
|
492
543
|
if (spCost > (this as any).sp) {
|
|
493
544
|
throw SkillLog.notEnoughSp(skill, spCost, (this as any).sp);
|
|
494
545
|
}
|
|
@@ -498,9 +549,12 @@ export function WithSkillManager<TBase extends PlayerCtor>(Base: TBase): TBase {
|
|
|
498
549
|
(this as any).sp -= spCost / costMultiplier;
|
|
499
550
|
|
|
500
551
|
// Check hit rate
|
|
501
|
-
const hitRate = skill.hitRate
|
|
552
|
+
const hitRate = typeof skill.hitRate === "number" ? skill.hitRate : 1;
|
|
502
553
|
if (Math.random() > hitRate) {
|
|
503
|
-
const hookTarget =
|
|
554
|
+
const hookTarget =
|
|
555
|
+
(skillEntry as any)?._skillInstance ||
|
|
556
|
+
(skillEntry as any)?._skillData ||
|
|
557
|
+
skill;
|
|
504
558
|
this["execMethod"]("onUseFailed", [this, otherPlayer], hookTarget);
|
|
505
559
|
throw SkillLog.chanceToUseFailed(skill);
|
|
506
560
|
}
|
|
@@ -515,7 +569,10 @@ export function WithSkillManager<TBase extends PlayerCtor>(Base: TBase): TBase {
|
|
|
515
569
|
}
|
|
516
570
|
|
|
517
571
|
// Call onUse hook
|
|
518
|
-
const hookTarget =
|
|
572
|
+
const hookTarget =
|
|
573
|
+
(skillEntry as any)?._skillInstance ||
|
|
574
|
+
(skillEntry as any)?._skillData ||
|
|
575
|
+
skill;
|
|
519
576
|
this["execMethod"]("onUse", [this, otherPlayer], hookTarget);
|
|
520
577
|
|
|
521
578
|
return skill;
|
|
@@ -30,7 +30,9 @@ export function WithVariableManager<TBase extends PlayerCtor>(Base: TBase) {
|
|
|
30
30
|
variables = type(signal<Record<string, any>>({}) as any, 'variables', { persist: true }, this as any);
|
|
31
31
|
|
|
32
32
|
setVariable(key: string, val: any): void {
|
|
33
|
-
this.variables()
|
|
33
|
+
this.variables.mutate((variables) => {
|
|
34
|
+
variables[key] = val;
|
|
35
|
+
});
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
getVariable<U = any>(key: string): U | undefined {
|
|
@@ -38,7 +40,13 @@ export function WithVariableManager<TBase extends PlayerCtor>(Base: TBase) {
|
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
removeVariable(key: string): boolean {
|
|
41
|
-
|
|
43
|
+
const variables = this.variables();
|
|
44
|
+
if (!(key in variables)) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
this.variables.mutate((draft) => {
|
|
48
|
+
delete draft[key];
|
|
49
|
+
});
|
|
42
50
|
return true;
|
|
43
51
|
}
|
|
44
52
|
|
|
@@ -110,4 +118,4 @@ export interface IVariableManager {
|
|
|
110
118
|
* Clear all variables
|
|
111
119
|
*/
|
|
112
120
|
clearVariables(): void;
|
|
113
|
-
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import type { RpgWebSocketConnection } from "./types";
|
|
2
|
+
|
|
3
|
+
type RuntimeProcess = {
|
|
4
|
+
env?: Record<string, string | undefined>;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
function readEnvVariable(name: string): string | undefined {
|
|
8
|
+
const value = (globalThis as { process?: RuntimeProcess }).process?.env?.[name];
|
|
9
|
+
return typeof value === "string" ? value : undefined;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class PartyConnection {
|
|
13
|
+
public id: string;
|
|
14
|
+
public uri: string;
|
|
15
|
+
private _state: any = {};
|
|
16
|
+
private messageQueue: Array<{ message: string; timestamp: number; sequence: number }> = [];
|
|
17
|
+
private isProcessingQueue = false;
|
|
18
|
+
private sequenceCounter = 0;
|
|
19
|
+
private incomingQueue: Array<{
|
|
20
|
+
message: string;
|
|
21
|
+
timestamp: number;
|
|
22
|
+
processor: (messages: string[]) => Promise<void>;
|
|
23
|
+
}> = [];
|
|
24
|
+
private isProcessingIncomingQueue = false;
|
|
25
|
+
|
|
26
|
+
public static packetLossRate = parseFloat(readEnvVariable("RPGJS_PACKET_LOSS_RATE") || "0.1");
|
|
27
|
+
public static packetLossEnabled = readEnvVariable("RPGJS_ENABLE_PACKET_LOSS") === "true";
|
|
28
|
+
public static packetLossFilter = readEnvVariable("RPGJS_PACKET_LOSS_FILTER") || "";
|
|
29
|
+
public static bandwidthEnabled = readEnvVariable("RPGJS_ENABLE_BANDWIDTH") === "true";
|
|
30
|
+
public static bandwidthKbps = parseInt(readEnvVariable("RPGJS_BANDWIDTH_KBPS") || "100");
|
|
31
|
+
public static bandwidthFilter = readEnvVariable("RPGJS_BANDWIDTH_FILTER") || "";
|
|
32
|
+
public static latencyEnabled = readEnvVariable("RPGJS_ENABLE_LATENCY") === "true";
|
|
33
|
+
public static latencyMs = parseInt(readEnvVariable("RPGJS_LATENCY_MS") || "50");
|
|
34
|
+
public static latencyFilter = readEnvVariable("RPGJS_LATENCY_FILTER") || "";
|
|
35
|
+
|
|
36
|
+
constructor(private ws: RpgWebSocketConnection, id?: string, uri?: string) {
|
|
37
|
+
this.id = id || this.generateId();
|
|
38
|
+
this.uri = uri || "";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private generateId(): string {
|
|
42
|
+
return `conn_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async send(data: any): Promise<void> {
|
|
46
|
+
if (this.ws.readyState !== 1) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const message = typeof data === "string" ? data : JSON.stringify(data);
|
|
51
|
+
const timestamp = Date.now();
|
|
52
|
+
const sequence = ++this.sequenceCounter;
|
|
53
|
+
|
|
54
|
+
this.messageQueue.push({ message, timestamp, sequence });
|
|
55
|
+
|
|
56
|
+
if (!this.isProcessingQueue) {
|
|
57
|
+
void this.processMessageQueue();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private async processMessageQueue(): Promise<void> {
|
|
62
|
+
if (this.isProcessingQueue) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
this.isProcessingQueue = true;
|
|
66
|
+
|
|
67
|
+
while (this.messageQueue.length > 0) {
|
|
68
|
+
const queueItem = this.messageQueue.shift()!;
|
|
69
|
+
|
|
70
|
+
if (this.shouldApplyLatency(queueItem.message)) {
|
|
71
|
+
await this.waitUntil(queueItem.timestamp + PartyConnection.latencyMs);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (PartyConnection.bandwidthEnabled && PartyConnection.bandwidthKbps > 0) {
|
|
75
|
+
if (!PartyConnection.bandwidthFilter || queueItem.message.includes(PartyConnection.bandwidthFilter)) {
|
|
76
|
+
const messageSizeBits = queueItem.message.length * 8;
|
|
77
|
+
const transmissionTimeMs = (messageSizeBits / (PartyConnection.bandwidthKbps * 1000)) * 1000;
|
|
78
|
+
const bandwidthDelayMs = Math.max(transmissionTimeMs, 10);
|
|
79
|
+
console.log(
|
|
80
|
+
`\x1b[34m[BANDWIDTH SIMULATION]\x1b[0m Connection ${this.id}: Message #${queueItem.sequence} transmission time: ${bandwidthDelayMs.toFixed(1)}ms`,
|
|
81
|
+
);
|
|
82
|
+
await new Promise((resolve) => setTimeout(resolve, bandwidthDelayMs));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
this.ws.send(queueItem.message);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
this.isProcessingQueue = false;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private shouldApplyLatency(message: string): boolean {
|
|
93
|
+
if (!PartyConnection.latencyEnabled || PartyConnection.latencyMs <= 0) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
if (!PartyConnection.latencyFilter) {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
return message.includes(PartyConnection.latencyFilter);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private async waitUntil(targetTimestamp: number): Promise<void> {
|
|
103
|
+
const delayMs = targetTimestamp - Date.now();
|
|
104
|
+
if (delayMs <= 0) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
close(): void {
|
|
111
|
+
if (this.ws.readyState === 1) {
|
|
112
|
+
this.ws.close();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
setState(value: any): void {
|
|
117
|
+
this._state = value;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
get state(): any {
|
|
121
|
+
return this._state;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
bufferIncoming(message: string, processor: (messages: string[]) => Promise<void>): void {
|
|
125
|
+
this.incomingQueue.push({
|
|
126
|
+
message,
|
|
127
|
+
timestamp: Date.now(),
|
|
128
|
+
processor,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
if (!this.isProcessingIncomingQueue) {
|
|
132
|
+
void this.processIncomingQueue();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
private async processIncomingQueue(): Promise<void> {
|
|
137
|
+
if (this.isProcessingIncomingQueue) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
this.isProcessingIncomingQueue = true;
|
|
141
|
+
|
|
142
|
+
while (this.incomingQueue.length > 0) {
|
|
143
|
+
const item = this.incomingQueue.shift()!;
|
|
144
|
+
if (this.shouldApplyLatency(item.message)) {
|
|
145
|
+
await this.waitUntil(item.timestamp + PartyConnection.latencyMs);
|
|
146
|
+
}
|
|
147
|
+
try {
|
|
148
|
+
await item.processor([item.message]);
|
|
149
|
+
} catch (err) {
|
|
150
|
+
console.error("Error processing incoming message:", err);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
this.isProcessingIncomingQueue = false;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
static configurePacketLoss(enabled: boolean, rate: number, filter?: string): void {
|
|
158
|
+
PartyConnection.packetLossEnabled = enabled;
|
|
159
|
+
PartyConnection.packetLossRate = Math.max(0, Math.min(1, rate));
|
|
160
|
+
PartyConnection.packetLossFilter = filter || "";
|
|
161
|
+
|
|
162
|
+
if (enabled && rate > 0) {
|
|
163
|
+
const filterInfo = filter ? ` (filtered: "${filter}")` : "";
|
|
164
|
+
console.log(`\x1b[35m[PACKET LOSS SIMULATION]\x1b[0m Enabled with ${(rate * 100).toFixed(1)}% loss rate${filterInfo}`);
|
|
165
|
+
} else if (enabled) {
|
|
166
|
+
console.log("\x1b[35m[PACKET LOSS SIMULATION]\x1b[0m Enabled but rate is 0% (no messages will be dropped)");
|
|
167
|
+
} else {
|
|
168
|
+
console.log("\x1b[35m[PACKET LOSS SIMULATION]\x1b[0m Disabled");
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
static getPacketLossStatus(): { enabled: boolean; rate: number; filter: string } {
|
|
173
|
+
return {
|
|
174
|
+
enabled: PartyConnection.packetLossEnabled,
|
|
175
|
+
rate: PartyConnection.packetLossRate,
|
|
176
|
+
filter: PartyConnection.packetLossFilter,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
static configureBandwidth(enabled: boolean, kbps: number, filter?: string): void {
|
|
181
|
+
PartyConnection.bandwidthEnabled = enabled;
|
|
182
|
+
PartyConnection.bandwidthKbps = Math.max(1, kbps);
|
|
183
|
+
PartyConnection.bandwidthFilter = filter || "";
|
|
184
|
+
|
|
185
|
+
if (enabled && kbps > 0) {
|
|
186
|
+
const filterInfo = filter ? ` (filtered: "${filter}")` : "";
|
|
187
|
+
console.log(`\x1b[35m[BANDWIDTH SIMULATION]\x1b[0m Enabled with ${kbps} kbps bandwidth${filterInfo}`);
|
|
188
|
+
} else if (enabled) {
|
|
189
|
+
console.log("\x1b[35m[BANDWIDTH SIMULATION]\x1b[0m Enabled but bandwidth is 0 kbps (no delay will be applied)");
|
|
190
|
+
} else {
|
|
191
|
+
console.log("\x1b[35m[BANDWIDTH SIMULATION]\x1b[0m Disabled");
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
static getBandwidthStatus(): { enabled: boolean; kbps: number; filter: string } {
|
|
196
|
+
return {
|
|
197
|
+
enabled: PartyConnection.bandwidthEnabled,
|
|
198
|
+
kbps: PartyConnection.bandwidthKbps,
|
|
199
|
+
filter: PartyConnection.bandwidthFilter,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
static configureLatency(enabled: boolean, ms: number, filter?: string): void {
|
|
204
|
+
PartyConnection.latencyEnabled = enabled;
|
|
205
|
+
PartyConnection.latencyMs = Math.max(0, ms);
|
|
206
|
+
PartyConnection.latencyFilter = filter || "";
|
|
207
|
+
|
|
208
|
+
if (enabled && ms > 0) {
|
|
209
|
+
const filterInfo = filter ? ` (filtered: "${filter}")` : "";
|
|
210
|
+
console.log(`\x1b[35m[LATENCY SIMULATION]\x1b[0m Enabled with ${ms}ms fixed latency${filterInfo}`);
|
|
211
|
+
} else if (enabled) {
|
|
212
|
+
console.log("\x1b[35m[LATENCY SIMULATION]\x1b[0m Enabled but latency is 0ms (no delay will be applied)");
|
|
213
|
+
} else {
|
|
214
|
+
console.log("\x1b[35m[LATENCY SIMULATION]\x1b[0m Disabled");
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
static getLatencyStatus(): { enabled: boolean; ms: number; filter: string } {
|
|
219
|
+
return {
|
|
220
|
+
enabled: PartyConnection.latencyEnabled,
|
|
221
|
+
ms: PartyConnection.latencyMs,
|
|
222
|
+
filter: PartyConnection.latencyFilter,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function logNetworkSimulationStatus(): void {
|
|
228
|
+
const packetLossStatus = PartyConnection.getPacketLossStatus();
|
|
229
|
+
const bandwidthStatus = PartyConnection.getBandwidthStatus();
|
|
230
|
+
const latencyStatus = PartyConnection.getLatencyStatus();
|
|
231
|
+
|
|
232
|
+
if (packetLossStatus.enabled) {
|
|
233
|
+
const filterInfo = packetLossStatus.filter ? ` (filter: "${packetLossStatus.filter}")` : "";
|
|
234
|
+
console.log(
|
|
235
|
+
`\x1b[36m[NETWORK SIMULATION]\x1b[0m Packet loss simulation: ${(packetLossStatus.rate * 100).toFixed(1)}% loss rate${filterInfo}`,
|
|
236
|
+
);
|
|
237
|
+
} else {
|
|
238
|
+
console.log("\x1b[36m[NETWORK SIMULATION]\x1b[0m Packet loss simulation: disabled");
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (bandwidthStatus.enabled) {
|
|
242
|
+
const filterInfo = bandwidthStatus.filter ? ` (filter: "${bandwidthStatus.filter}")` : "";
|
|
243
|
+
console.log(`\x1b[36m[NETWORK SIMULATION]\x1b[0m Bandwidth simulation: ${bandwidthStatus.kbps} kbps${filterInfo}`);
|
|
244
|
+
} else {
|
|
245
|
+
console.log("\x1b[36m[NETWORK SIMULATION]\x1b[0m Bandwidth simulation: disabled");
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (latencyStatus.enabled) {
|
|
249
|
+
const filterInfo = latencyStatus.filter ? ` (filter: "${latencyStatus.filter}")` : "";
|
|
250
|
+
console.log(`\x1b[36m[NETWORK SIMULATION]\x1b[0m Latency simulation: ${latencyStatus.ms}ms ping${filterInfo}`);
|
|
251
|
+
} else {
|
|
252
|
+
console.log("\x1b[36m[NETWORK SIMULATION]\x1b[0m Latency simulation: disabled");
|
|
253
|
+
}
|
|
254
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export { PartyConnection, logNetworkSimulationStatus } from "./connection";
|
|
2
|
+
export {
|
|
3
|
+
createMapUpdateHeaders,
|
|
4
|
+
isMapUpdateAuthorized,
|
|
5
|
+
MAP_UPDATE_TOKEN_ENV,
|
|
6
|
+
MAP_UPDATE_TOKEN_HEADER,
|
|
7
|
+
readMapUpdateToken,
|
|
8
|
+
resolveMapUpdateToken,
|
|
9
|
+
} from "./map";
|
|
10
|
+
export { PartyRoom } from "./room";
|
|
11
|
+
export { createRpgServerTransport, RpgServerTransport } from "./transport";
|
|
12
|
+
export type {
|
|
13
|
+
CreateRpgServerTransportOptions,
|
|
14
|
+
HandleNodeRequestOptions,
|
|
15
|
+
RpgTransportRequestLike,
|
|
16
|
+
RpgTransportServer,
|
|
17
|
+
RpgTransportServerConstructor,
|
|
18
|
+
RpgWebSocketConnection,
|
|
19
|
+
RpgWebSocketRequestLike,
|
|
20
|
+
RpgWebSocketServer,
|
|
21
|
+
SendMapUpdateOptions,
|
|
22
|
+
} from "./types";
|