sa2kit 1.6.34 → 1.6.36
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/{chunk-HQ7VHIEK.mjs → chunk-55FBYGRK.mjs} +409 -27
- package/dist/chunk-55FBYGRK.mjs.map +1 -0
- package/dist/{chunk-B34YUZRL.js → chunk-XXDMARU7.js} +409 -25
- package/dist/chunk-XXDMARU7.js.map +1 -0
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +22 -14
- package/dist/index.mjs +1 -1
- package/dist/mikuFireworks3D/index.d.mts +146 -52
- package/dist/mikuFireworks3D/index.d.ts +146 -52
- package/dist/mikuFireworks3D/index.js +22 -14
- package/dist/mikuFireworks3D/index.mjs +1 -1
- package/dist/mikuFireworks3D/server/index.d.mts +146 -0
- package/dist/mikuFireworks3D/server/index.d.ts +146 -0
- package/dist/mikuFireworks3D/server/index.js +338 -0
- package/dist/mikuFireworks3D/server/index.js.map +1 -0
- package/dist/mikuFireworks3D/server/index.mjs +335 -0
- package/dist/mikuFireworks3D/server/index.mjs.map +1 -0
- package/dist/types-DBVDr8Mu.d.mts +71 -0
- package/dist/types-DBVDr8Mu.d.ts +71 -0
- package/dist/universalFile/server/index.js +5 -5
- package/dist/universalFile/server/index.mjs +1 -1
- package/package.json +6 -1
- package/dist/chunk-B34YUZRL.js.map +0 -1
- package/dist/chunk-HQ7VHIEK.mjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React3, { useState, useCallback, useMemo,
|
|
1
|
+
import React3, { useState, useRef, useCallback, useMemo, useEffect } from 'react';
|
|
2
2
|
import * as THREE2 from 'three';
|
|
3
3
|
|
|
4
4
|
// src/mikuFireworks3D/components/MikuFireworks3D.tsx
|
|
@@ -71,7 +71,9 @@ function FireworksControlPanel({
|
|
|
71
71
|
avatarUrl,
|
|
72
72
|
onAvatarUrlChange,
|
|
73
73
|
onLaunch,
|
|
74
|
-
fps
|
|
74
|
+
fps,
|
|
75
|
+
realtimeConnected,
|
|
76
|
+
onlineCount
|
|
75
77
|
}) {
|
|
76
78
|
return /* @__PURE__ */ React3.createElement("div", { className: "rounded-xl border border-slate-600/40 bg-slate-900/70 p-3 text-slate-100 backdrop-blur-sm" }, /* @__PURE__ */ React3.createElement("div", { className: "mb-3 flex flex-wrap items-center gap-2" }, Object.keys(FIREWORK_KIND_LABELS).map((kind) => {
|
|
77
79
|
const active = kind === selectedKind;
|
|
@@ -100,7 +102,7 @@ function FireworksControlPanel({
|
|
|
100
102
|
checked: autoLaunchOnDanmaku,
|
|
101
103
|
onChange: (event) => onAutoLaunchChange(event.target.checked)
|
|
102
104
|
}
|
|
103
|
-
), "\u53D1\u9001\u5F39\u5E55\u540E\u81EA\u52A8\u653E\u70DF\u82B1"), /* @__PURE__ */ React3.createElement("div", { className: "text-sm text-slate-300" }, "FPS: ", fps)), selectedKind === "avatar" ? /* @__PURE__ */ React3.createElement("div", { className: "mt-2" }, /* @__PURE__ */ React3.createElement(
|
|
105
|
+
), "\u53D1\u9001\u5F39\u5E55\u540E\u81EA\u52A8\u653E\u70DF\u82B1"), /* @__PURE__ */ React3.createElement("div", { className: "text-sm text-slate-300" }, "FPS: ", fps), typeof realtimeConnected === "boolean" ? /* @__PURE__ */ React3.createElement("div", { className: "text-sm text-slate-300" }, "\u5B9E\u65F6\u72B6\u6001: ", realtimeConnected ? "\u5DF2\u8FDE\u63A5" : "\u672A\u8FDE\u63A5", typeof onlineCount === "number" ? ` \xB7 \u5728\u7EBF ${onlineCount}` : "") : null), selectedKind === "avatar" ? /* @__PURE__ */ React3.createElement("div", { className: "mt-2" }, /* @__PURE__ */ React3.createElement(
|
|
104
106
|
"input",
|
|
105
107
|
{
|
|
106
108
|
type: "url",
|
|
@@ -113,12 +115,24 @@ function FireworksControlPanel({
|
|
|
113
115
|
}
|
|
114
116
|
function useDanmakuController(options) {
|
|
115
117
|
const [items, setItems] = useState([]);
|
|
116
|
-
const
|
|
118
|
+
const cursorRef = useRef(0);
|
|
117
119
|
const removeItem = useCallback((id) => {
|
|
118
120
|
setItems((prev) => prev.filter((item) => item.id !== id));
|
|
119
121
|
}, []);
|
|
122
|
+
const addIncoming = useCallback((message) => {
|
|
123
|
+
setItems((prev) => {
|
|
124
|
+
const track = cursorRef.current % DANMAKU_TRACK_COUNT;
|
|
125
|
+
const item = {
|
|
126
|
+
...message,
|
|
127
|
+
track,
|
|
128
|
+
durationMs: 8e3 + Math.floor(Math.random() * 2800)
|
|
129
|
+
};
|
|
130
|
+
return [...prev.slice(-40), item];
|
|
131
|
+
});
|
|
132
|
+
cursorRef.current += 1;
|
|
133
|
+
}, []);
|
|
120
134
|
const send = useCallback(
|
|
121
|
-
(text, color) => {
|
|
135
|
+
(text, color, sendOptions) => {
|
|
122
136
|
const trimmed = text.trim();
|
|
123
137
|
if (!trimmed) {
|
|
124
138
|
return null;
|
|
@@ -134,31 +148,26 @@ function useDanmakuController(options) {
|
|
|
134
148
|
color,
|
|
135
149
|
timestamp: Date.now()
|
|
136
150
|
};
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
track,
|
|
142
|
-
durationMs: 8e3 + Math.floor(Math.random() * 2800)
|
|
143
|
-
};
|
|
144
|
-
return [...prev.slice(-40), item];
|
|
145
|
-
});
|
|
146
|
-
setCursor((prev) => prev + 1);
|
|
151
|
+
const optimistic = sendOptions?.optimistic ?? true;
|
|
152
|
+
if (optimistic) {
|
|
153
|
+
addIncoming(message);
|
|
154
|
+
}
|
|
147
155
|
options?.onSend?.(message);
|
|
148
156
|
return {
|
|
149
157
|
message,
|
|
150
158
|
launchKind
|
|
151
159
|
};
|
|
152
160
|
},
|
|
153
|
-
[
|
|
161
|
+
[addIncoming, options]
|
|
154
162
|
);
|
|
155
163
|
return useMemo(
|
|
156
164
|
() => ({
|
|
157
165
|
items,
|
|
158
166
|
send,
|
|
167
|
+
addIncoming,
|
|
159
168
|
removeItem
|
|
160
169
|
}),
|
|
161
|
-
[items, removeItem, send]
|
|
170
|
+
[addIncoming, items, removeItem, send]
|
|
162
171
|
);
|
|
163
172
|
}
|
|
164
173
|
function parseCommand(text) {
|
|
@@ -672,6 +681,302 @@ function useFireworksEngine(options) {
|
|
|
672
681
|
return api;
|
|
673
682
|
}
|
|
674
683
|
|
|
684
|
+
// src/mikuFireworks3D/client/WebSocketTransport.ts
|
|
685
|
+
var WebSocketTransport = class {
|
|
686
|
+
constructor(config, callbacks) {
|
|
687
|
+
this.socket = null;
|
|
688
|
+
this.reconnectTimer = null;
|
|
689
|
+
this.isManualClose = false;
|
|
690
|
+
this.pendingQueue = [];
|
|
691
|
+
this.config = config;
|
|
692
|
+
this.callbacks = callbacks || {};
|
|
693
|
+
this.state = {
|
|
694
|
+
connected: false,
|
|
695
|
+
joined: false,
|
|
696
|
+
onlineCount: 0,
|
|
697
|
+
roomId: config.roomId
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
connect() {
|
|
701
|
+
if (this.socket && (this.socket.readyState === window.WebSocket.OPEN || this.socket.readyState === window.WebSocket.CONNECTING)) {
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
704
|
+
this.isManualClose = false;
|
|
705
|
+
try {
|
|
706
|
+
this.socket = this.config.protocols ? new window.WebSocket(this.config.serverUrl, this.config.protocols) : new window.WebSocket(this.config.serverUrl);
|
|
707
|
+
} catch {
|
|
708
|
+
this.callbacks.onError?.(new Error("Failed to create WebSocket connection."));
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
this.socket.onopen = () => {
|
|
712
|
+
this.updateState({ connected: true, joined: false });
|
|
713
|
+
this.send({
|
|
714
|
+
type: "join",
|
|
715
|
+
roomId: this.config.roomId,
|
|
716
|
+
user: this.config.user
|
|
717
|
+
});
|
|
718
|
+
};
|
|
719
|
+
this.socket.onmessage = (event) => {
|
|
720
|
+
const parsed = parseServerMessage(event.data);
|
|
721
|
+
if (!parsed) {
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
this.handleServerMessage(parsed);
|
|
725
|
+
};
|
|
726
|
+
this.socket.onerror = () => {
|
|
727
|
+
this.callbacks.onError?.(new Error("WebSocket transport error."));
|
|
728
|
+
};
|
|
729
|
+
this.socket.onclose = () => {
|
|
730
|
+
this.updateState({ connected: false, joined: false });
|
|
731
|
+
this.scheduleReconnect();
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
disconnect() {
|
|
735
|
+
this.isManualClose = true;
|
|
736
|
+
this.pendingQueue.length = 0;
|
|
737
|
+
if (this.reconnectTimer != null) {
|
|
738
|
+
window.clearTimeout(this.reconnectTimer);
|
|
739
|
+
this.reconnectTimer = null;
|
|
740
|
+
}
|
|
741
|
+
if (!this.socket) {
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
this.send({ type: "leave" });
|
|
745
|
+
this.socket.close();
|
|
746
|
+
this.socket = null;
|
|
747
|
+
}
|
|
748
|
+
sendDanmaku(payload) {
|
|
749
|
+
this.send({
|
|
750
|
+
type: "danmaku.send",
|
|
751
|
+
payload
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
sendFirework(payload) {
|
|
755
|
+
this.send({
|
|
756
|
+
type: "firework.launch",
|
|
757
|
+
payload
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
getState() {
|
|
761
|
+
return this.state;
|
|
762
|
+
}
|
|
763
|
+
send(message) {
|
|
764
|
+
if (!this.socket || this.socket.readyState !== window.WebSocket.OPEN) {
|
|
765
|
+
if (message.type === "danmaku.send" || message.type === "firework.launch") {
|
|
766
|
+
this.pendingQueue.push(message);
|
|
767
|
+
}
|
|
768
|
+
return;
|
|
769
|
+
}
|
|
770
|
+
if ((message.type === "danmaku.send" || message.type === "firework.launch") && !this.state.joined) {
|
|
771
|
+
this.pendingQueue.push(message);
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
774
|
+
this.socket.send(JSON.stringify(message));
|
|
775
|
+
}
|
|
776
|
+
updateState(partial) {
|
|
777
|
+
this.state = {
|
|
778
|
+
...this.state,
|
|
779
|
+
...partial
|
|
780
|
+
};
|
|
781
|
+
this.callbacks.onStateChange?.(this.state);
|
|
782
|
+
}
|
|
783
|
+
handleServerMessage(message) {
|
|
784
|
+
if (message.type === "joined") {
|
|
785
|
+
this.updateState({ roomId: message.roomId, onlineCount: message.onlineCount, joined: true });
|
|
786
|
+
this.flushPendingQueue();
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
if (message.type === "room.user_joined" || message.type === "room.user_left") {
|
|
790
|
+
this.updateState({ onlineCount: message.onlineCount, roomId: message.roomId });
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
if (message.type === "room.snapshot") {
|
|
794
|
+
this.updateState({ roomId: message.roomId, onlineCount: message.users.length });
|
|
795
|
+
this.callbacks.onSnapshot?.(message);
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
if (message.type === "danmaku.broadcast") {
|
|
799
|
+
this.callbacks.onDanmakuBroadcast?.(message.event);
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
if (message.type === "firework.broadcast") {
|
|
803
|
+
this.callbacks.onFireworkBroadcast?.(message.event);
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
if (message.type === "error") {
|
|
807
|
+
this.callbacks.onError?.(new Error(`${message.code}: ${message.message}`));
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
scheduleReconnect() {
|
|
811
|
+
const reconnect = this.config.reconnect ?? true;
|
|
812
|
+
if (this.isManualClose || !reconnect) {
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
815
|
+
if (this.reconnectTimer != null) {
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
const delay = this.config.reconnectIntervalMs ?? 1500;
|
|
819
|
+
this.reconnectTimer = window.setTimeout(() => {
|
|
820
|
+
this.reconnectTimer = null;
|
|
821
|
+
this.connect();
|
|
822
|
+
}, delay);
|
|
823
|
+
}
|
|
824
|
+
flushPendingQueue() {
|
|
825
|
+
if (!this.socket || this.socket.readyState !== window.WebSocket.OPEN || !this.state.joined) {
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
828
|
+
while (this.pendingQueue.length > 0) {
|
|
829
|
+
const message = this.pendingQueue.shift();
|
|
830
|
+
if (!message) {
|
|
831
|
+
break;
|
|
832
|
+
}
|
|
833
|
+
this.socket.send(JSON.stringify(message));
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
};
|
|
837
|
+
function parseServerMessage(raw) {
|
|
838
|
+
if (typeof raw !== "string") {
|
|
839
|
+
return null;
|
|
840
|
+
}
|
|
841
|
+
try {
|
|
842
|
+
return JSON.parse(raw);
|
|
843
|
+
} catch {
|
|
844
|
+
return null;
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
// src/mikuFireworks3D/hooks/useFireworksRealtime.ts
|
|
849
|
+
function useFireworksRealtime(options) {
|
|
850
|
+
const { config, enabled, onDanmakuBroadcast, onFireworkBroadcast, onSnapshot, onError, onStateChange } = options;
|
|
851
|
+
const transportRef = useRef(null);
|
|
852
|
+
const callbackRef = useRef({
|
|
853
|
+
onDanmakuBroadcast,
|
|
854
|
+
onFireworkBroadcast,
|
|
855
|
+
onSnapshot,
|
|
856
|
+
onError,
|
|
857
|
+
onStateChange
|
|
858
|
+
});
|
|
859
|
+
const serverUrl = config?.serverUrl ?? "";
|
|
860
|
+
const roomId = config?.roomId ?? "";
|
|
861
|
+
const userId = config?.user.userId ?? "";
|
|
862
|
+
const nickname = config?.user.nickname ?? "";
|
|
863
|
+
const avatarUrl = config?.user.avatarUrl ?? "";
|
|
864
|
+
const reconnect = config?.reconnect ?? true;
|
|
865
|
+
const reconnectIntervalMs = config?.reconnectIntervalMs ?? 1500;
|
|
866
|
+
const [state, setState] = useState({
|
|
867
|
+
connected: false,
|
|
868
|
+
joined: false,
|
|
869
|
+
onlineCount: 0,
|
|
870
|
+
roomId
|
|
871
|
+
});
|
|
872
|
+
useEffect(() => {
|
|
873
|
+
callbackRef.current = {
|
|
874
|
+
onDanmakuBroadcast,
|
|
875
|
+
onFireworkBroadcast,
|
|
876
|
+
onSnapshot,
|
|
877
|
+
onError,
|
|
878
|
+
onStateChange
|
|
879
|
+
};
|
|
880
|
+
}, [onDanmakuBroadcast, onError, onFireworkBroadcast, onSnapshot, onStateChange]);
|
|
881
|
+
const normalizedConfig = useMemo(() => {
|
|
882
|
+
if (!serverUrl || !roomId || !userId) {
|
|
883
|
+
return void 0;
|
|
884
|
+
}
|
|
885
|
+
const protocols = Array.isArray(config?.protocols) ? [...config.protocols] : config?.protocols;
|
|
886
|
+
return {
|
|
887
|
+
serverUrl,
|
|
888
|
+
roomId,
|
|
889
|
+
user: {
|
|
890
|
+
userId,
|
|
891
|
+
nickname: nickname || void 0,
|
|
892
|
+
avatarUrl: avatarUrl || void 0
|
|
893
|
+
},
|
|
894
|
+
protocols,
|
|
895
|
+
reconnect,
|
|
896
|
+
reconnectIntervalMs
|
|
897
|
+
};
|
|
898
|
+
}, [avatarUrl, config?.protocols, nickname, reconnect, reconnectIntervalMs, roomId, serverUrl, userId]);
|
|
899
|
+
useEffect(() => {
|
|
900
|
+
if (!enabled || !normalizedConfig) {
|
|
901
|
+
transportRef.current?.disconnect();
|
|
902
|
+
transportRef.current = null;
|
|
903
|
+
setState({
|
|
904
|
+
connected: false,
|
|
905
|
+
joined: false,
|
|
906
|
+
onlineCount: 0,
|
|
907
|
+
roomId: normalizedConfig?.roomId
|
|
908
|
+
});
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
911
|
+
const transport = new WebSocketTransport(normalizedConfig, {
|
|
912
|
+
onStateChange: (nextState) => {
|
|
913
|
+
setState(nextState);
|
|
914
|
+
callbackRef.current.onStateChange?.(nextState);
|
|
915
|
+
},
|
|
916
|
+
onDanmakuBroadcast: (event) => {
|
|
917
|
+
callbackRef.current.onDanmakuBroadcast?.({
|
|
918
|
+
id: event.id,
|
|
919
|
+
text: event.text,
|
|
920
|
+
color: event.color,
|
|
921
|
+
kind: event.kind,
|
|
922
|
+
userId: event.user.userId,
|
|
923
|
+
timestamp: event.timestamp
|
|
924
|
+
});
|
|
925
|
+
},
|
|
926
|
+
onFireworkBroadcast: (event) => {
|
|
927
|
+
callbackRef.current.onFireworkBroadcast?.({
|
|
928
|
+
id: event.id,
|
|
929
|
+
payload: event.payload,
|
|
930
|
+
userId: event.user.userId,
|
|
931
|
+
timestamp: event.timestamp
|
|
932
|
+
});
|
|
933
|
+
},
|
|
934
|
+
onSnapshot: (snapshot) => {
|
|
935
|
+
callbackRef.current.onSnapshot?.({
|
|
936
|
+
roomId: snapshot.roomId,
|
|
937
|
+
danmakuHistory: snapshot.danmakuHistory.map((item) => ({
|
|
938
|
+
id: item.id,
|
|
939
|
+
text: item.text,
|
|
940
|
+
color: item.color,
|
|
941
|
+
kind: item.kind,
|
|
942
|
+
userId: item.user.userId,
|
|
943
|
+
timestamp: item.timestamp
|
|
944
|
+
})),
|
|
945
|
+
fireworkHistory: snapshot.fireworkHistory.map((item) => ({
|
|
946
|
+
id: item.id,
|
|
947
|
+
payload: item.payload,
|
|
948
|
+
userId: item.user.userId,
|
|
949
|
+
timestamp: item.timestamp
|
|
950
|
+
}))
|
|
951
|
+
});
|
|
952
|
+
},
|
|
953
|
+
onError: (error) => {
|
|
954
|
+
callbackRef.current.onError?.(error);
|
|
955
|
+
}
|
|
956
|
+
});
|
|
957
|
+
transport.connect();
|
|
958
|
+
transportRef.current = transport;
|
|
959
|
+
return () => {
|
|
960
|
+
transport.disconnect();
|
|
961
|
+
if (transportRef.current === transport) {
|
|
962
|
+
transportRef.current = null;
|
|
963
|
+
}
|
|
964
|
+
};
|
|
965
|
+
}, [enabled, normalizedConfig]);
|
|
966
|
+
return useMemo(
|
|
967
|
+
() => ({
|
|
968
|
+
state,
|
|
969
|
+
sendDanmaku: (payload) => {
|
|
970
|
+
transportRef.current?.sendDanmaku(payload);
|
|
971
|
+
},
|
|
972
|
+
sendFirework: (payload) => {
|
|
973
|
+
transportRef.current?.sendFirework(payload);
|
|
974
|
+
}
|
|
975
|
+
}),
|
|
976
|
+
[state]
|
|
977
|
+
);
|
|
978
|
+
}
|
|
979
|
+
|
|
675
980
|
// src/mikuFireworks3D/components/MikuFireworks3D.tsx
|
|
676
981
|
function MikuFireworks3D({
|
|
677
982
|
width = "100%",
|
|
@@ -685,11 +990,15 @@ function MikuFireworks3D({
|
|
|
685
990
|
onLaunch,
|
|
686
991
|
onDanmakuSend,
|
|
687
992
|
onError,
|
|
688
|
-
onFpsReport
|
|
993
|
+
onFpsReport,
|
|
994
|
+
onRealtimeStateChange,
|
|
995
|
+
realtime
|
|
689
996
|
}) {
|
|
690
997
|
const [selectedKind, setSelectedKind] = useState(defaultKind);
|
|
691
998
|
const [avatarUrl, setAvatarUrl] = useState(defaultAvatarUrl);
|
|
692
999
|
const [autoLaunch, setAutoLaunch] = useState(autoLaunchOnDanmaku);
|
|
1000
|
+
const seenDanmakuIdsRef = useRef(/* @__PURE__ */ new Set());
|
|
1001
|
+
const seenFireworkIdsRef = useRef(/* @__PURE__ */ new Set());
|
|
693
1002
|
const { containerRef, canvasRef, launch, fps } = useFireworksEngine({
|
|
694
1003
|
maxParticles,
|
|
695
1004
|
maxActiveFireworks,
|
|
@@ -697,22 +1006,93 @@ function MikuFireworks3D({
|
|
|
697
1006
|
onError,
|
|
698
1007
|
onFpsReport
|
|
699
1008
|
});
|
|
700
|
-
const { items, send, removeItem } = useDanmakuController({
|
|
1009
|
+
const { items, send, addIncoming, removeItem } = useDanmakuController({
|
|
701
1010
|
onSend: onDanmakuSend
|
|
702
1011
|
});
|
|
1012
|
+
const realtimeEnabled = Boolean(realtime && (realtime.enabled ?? true));
|
|
1013
|
+
const realtimeApi = useFireworksRealtime({
|
|
1014
|
+
enabled: realtimeEnabled,
|
|
1015
|
+
config: realtime,
|
|
1016
|
+
onStateChange: onRealtimeStateChange,
|
|
1017
|
+
onError,
|
|
1018
|
+
onDanmakuBroadcast: (event) => {
|
|
1019
|
+
if (seenDanmakuIdsRef.current.has(event.id)) {
|
|
1020
|
+
return;
|
|
1021
|
+
}
|
|
1022
|
+
seenDanmakuIdsRef.current.add(event.id);
|
|
1023
|
+
addIncoming({
|
|
1024
|
+
id: event.id,
|
|
1025
|
+
userId: event.userId,
|
|
1026
|
+
text: event.text,
|
|
1027
|
+
color: event.color,
|
|
1028
|
+
timestamp: event.timestamp
|
|
1029
|
+
});
|
|
1030
|
+
},
|
|
1031
|
+
onFireworkBroadcast: (event) => {
|
|
1032
|
+
if (seenFireworkIdsRef.current.has(event.id)) {
|
|
1033
|
+
return;
|
|
1034
|
+
}
|
|
1035
|
+
seenFireworkIdsRef.current.add(event.id);
|
|
1036
|
+
launch(event.payload);
|
|
1037
|
+
},
|
|
1038
|
+
onSnapshot: (snapshot) => {
|
|
1039
|
+
for (const danmaku of snapshot.danmakuHistory) {
|
|
1040
|
+
if (seenDanmakuIdsRef.current.has(danmaku.id)) {
|
|
1041
|
+
continue;
|
|
1042
|
+
}
|
|
1043
|
+
seenDanmakuIdsRef.current.add(danmaku.id);
|
|
1044
|
+
addIncoming({
|
|
1045
|
+
id: danmaku.id,
|
|
1046
|
+
userId: danmaku.userId,
|
|
1047
|
+
text: danmaku.text,
|
|
1048
|
+
color: danmaku.color,
|
|
1049
|
+
timestamp: danmaku.timestamp
|
|
1050
|
+
});
|
|
1051
|
+
}
|
|
1052
|
+
for (const firework of snapshot.fireworkHistory) {
|
|
1053
|
+
if (seenFireworkIdsRef.current.has(firework.id)) {
|
|
1054
|
+
continue;
|
|
1055
|
+
}
|
|
1056
|
+
seenFireworkIdsRef.current.add(firework.id);
|
|
1057
|
+
launch(firework.payload);
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
});
|
|
703
1061
|
const handleLaunch = (kind) => {
|
|
704
|
-
|
|
1062
|
+
const payload = {
|
|
705
1063
|
kind,
|
|
706
1064
|
avatarUrl: kind === "avatar" ? avatarUrl || void 0 : void 0
|
|
707
|
-
}
|
|
1065
|
+
};
|
|
1066
|
+
if (realtimeEnabled && realtimeApi.state.connected && realtimeApi.state.joined) {
|
|
1067
|
+
realtimeApi.sendFirework(payload);
|
|
1068
|
+
return;
|
|
1069
|
+
}
|
|
1070
|
+
launch(payload);
|
|
708
1071
|
};
|
|
709
1072
|
const handleSendDanmaku = (text) => {
|
|
710
|
-
const result = send(text
|
|
1073
|
+
const result = send(text, void 0, {
|
|
1074
|
+
optimistic: !(realtimeEnabled && realtimeApi.state.connected && realtimeApi.state.joined)
|
|
1075
|
+
});
|
|
711
1076
|
if (!result) {
|
|
712
1077
|
return;
|
|
713
1078
|
}
|
|
714
1079
|
const launchKind = result.launchKind ?? selectedKind;
|
|
715
|
-
if (
|
|
1080
|
+
if (realtimeEnabled && realtimeApi.state.connected && realtimeApi.state.joined) {
|
|
1081
|
+
realtimeApi.sendDanmaku({
|
|
1082
|
+
text: result.message.text,
|
|
1083
|
+
color: result.message.color,
|
|
1084
|
+
kind: result.launchKind
|
|
1085
|
+
});
|
|
1086
|
+
if (autoLaunch) {
|
|
1087
|
+
realtimeApi.sendFirework({
|
|
1088
|
+
kind: launchKind,
|
|
1089
|
+
avatarUrl: launchKind === "avatar" ? avatarUrl || void 0 : void 0,
|
|
1090
|
+
message: result.message
|
|
1091
|
+
});
|
|
1092
|
+
}
|
|
1093
|
+
return;
|
|
1094
|
+
}
|
|
1095
|
+
if (autoLaunch || result.launchKind) {
|
|
716
1096
|
launch({
|
|
717
1097
|
kind: launchKind,
|
|
718
1098
|
avatarUrl: launchKind === "avatar" ? avatarUrl || void 0 : void 0,
|
|
@@ -751,7 +1131,9 @@ function MikuFireworks3D({
|
|
|
751
1131
|
avatarUrl,
|
|
752
1132
|
onAvatarUrlChange: setAvatarUrl,
|
|
753
1133
|
onLaunch: () => handleLaunch(selectedKind),
|
|
754
|
-
fps
|
|
1134
|
+
fps,
|
|
1135
|
+
realtimeConnected: realtimeEnabled ? realtimeApi.state.connected : void 0,
|
|
1136
|
+
onlineCount: realtimeEnabled ? realtimeApi.state.onlineCount : void 0
|
|
755
1137
|
}
|
|
756
1138
|
), /* @__PURE__ */ React3.createElement(DanmakuPanel, { onSend: handleSendDanmaku }), /* @__PURE__ */ React3.createElement("style", null, `
|
|
757
1139
|
@keyframes sa2kit-danmaku-move {
|
|
@@ -767,6 +1149,6 @@ function MikuFireworks3D({
|
|
|
767
1149
|
`));
|
|
768
1150
|
}
|
|
769
1151
|
|
|
770
|
-
export { DANMAKU_MAX_LENGTH, DANMAKU_TRACK_COUNT, DEFAULT_MAX_ACTIVE_FIREWORKS, DEFAULT_MAX_PARTICLES, DanmakuPanel, FIREWORK_KIND_LABELS, FireworksCanvas, FireworksControlPanel, MIKU_PALETTE, MikuFireworks3D, NORMAL_PALETTE, useDanmakuController, useFireworksEngine };
|
|
771
|
-
//# sourceMappingURL=chunk-
|
|
772
|
-
//# sourceMappingURL=chunk-
|
|
1152
|
+
export { DANMAKU_MAX_LENGTH, DANMAKU_TRACK_COUNT, DEFAULT_MAX_ACTIVE_FIREWORKS, DEFAULT_MAX_PARTICLES, DanmakuPanel, FIREWORK_KIND_LABELS, FireworksCanvas, FireworksControlPanel, MIKU_PALETTE, MikuFireworks3D, NORMAL_PALETTE, WebSocketTransport, useDanmakuController, useFireworksEngine, useFireworksRealtime };
|
|
1153
|
+
//# sourceMappingURL=chunk-55FBYGRK.mjs.map
|
|
1154
|
+
//# sourceMappingURL=chunk-55FBYGRK.mjs.map
|