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
|
@@ -96,7 +96,9 @@ function FireworksControlPanel({
|
|
|
96
96
|
avatarUrl,
|
|
97
97
|
onAvatarUrlChange,
|
|
98
98
|
onLaunch,
|
|
99
|
-
fps
|
|
99
|
+
fps,
|
|
100
|
+
realtimeConnected,
|
|
101
|
+
onlineCount
|
|
100
102
|
}) {
|
|
101
103
|
return /* @__PURE__ */ React3__default.default.createElement("div", { className: "rounded-xl border border-slate-600/40 bg-slate-900/70 p-3 text-slate-100 backdrop-blur-sm" }, /* @__PURE__ */ React3__default.default.createElement("div", { className: "mb-3 flex flex-wrap items-center gap-2" }, Object.keys(FIREWORK_KIND_LABELS).map((kind) => {
|
|
102
104
|
const active = kind === selectedKind;
|
|
@@ -125,7 +127,7 @@ function FireworksControlPanel({
|
|
|
125
127
|
checked: autoLaunchOnDanmaku,
|
|
126
128
|
onChange: (event) => onAutoLaunchChange(event.target.checked)
|
|
127
129
|
}
|
|
128
|
-
), "\u53D1\u9001\u5F39\u5E55\u540E\u81EA\u52A8\u653E\u70DF\u82B1"), /* @__PURE__ */ React3__default.default.createElement("div", { className: "text-sm text-slate-300" }, "FPS: ", fps)), selectedKind === "avatar" ? /* @__PURE__ */ React3__default.default.createElement("div", { className: "mt-2" }, /* @__PURE__ */ React3__default.default.createElement(
|
|
130
|
+
), "\u53D1\u9001\u5F39\u5E55\u540E\u81EA\u52A8\u653E\u70DF\u82B1"), /* @__PURE__ */ React3__default.default.createElement("div", { className: "text-sm text-slate-300" }, "FPS: ", fps), typeof realtimeConnected === "boolean" ? /* @__PURE__ */ React3__default.default.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__default.default.createElement("div", { className: "mt-2" }, /* @__PURE__ */ React3__default.default.createElement(
|
|
129
131
|
"input",
|
|
130
132
|
{
|
|
131
133
|
type: "url",
|
|
@@ -138,12 +140,24 @@ function FireworksControlPanel({
|
|
|
138
140
|
}
|
|
139
141
|
function useDanmakuController(options) {
|
|
140
142
|
const [items, setItems] = React3.useState([]);
|
|
141
|
-
const
|
|
143
|
+
const cursorRef = React3.useRef(0);
|
|
142
144
|
const removeItem = React3.useCallback((id) => {
|
|
143
145
|
setItems((prev) => prev.filter((item) => item.id !== id));
|
|
144
146
|
}, []);
|
|
147
|
+
const addIncoming = React3.useCallback((message) => {
|
|
148
|
+
setItems((prev) => {
|
|
149
|
+
const track = cursorRef.current % DANMAKU_TRACK_COUNT;
|
|
150
|
+
const item = {
|
|
151
|
+
...message,
|
|
152
|
+
track,
|
|
153
|
+
durationMs: 8e3 + Math.floor(Math.random() * 2800)
|
|
154
|
+
};
|
|
155
|
+
return [...prev.slice(-40), item];
|
|
156
|
+
});
|
|
157
|
+
cursorRef.current += 1;
|
|
158
|
+
}, []);
|
|
145
159
|
const send = React3.useCallback(
|
|
146
|
-
(text, color) => {
|
|
160
|
+
(text, color, sendOptions) => {
|
|
147
161
|
const trimmed = text.trim();
|
|
148
162
|
if (!trimmed) {
|
|
149
163
|
return null;
|
|
@@ -159,31 +173,26 @@ function useDanmakuController(options) {
|
|
|
159
173
|
color,
|
|
160
174
|
timestamp: Date.now()
|
|
161
175
|
};
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
track,
|
|
167
|
-
durationMs: 8e3 + Math.floor(Math.random() * 2800)
|
|
168
|
-
};
|
|
169
|
-
return [...prev.slice(-40), item];
|
|
170
|
-
});
|
|
171
|
-
setCursor((prev) => prev + 1);
|
|
176
|
+
const optimistic = sendOptions?.optimistic ?? true;
|
|
177
|
+
if (optimistic) {
|
|
178
|
+
addIncoming(message);
|
|
179
|
+
}
|
|
172
180
|
options?.onSend?.(message);
|
|
173
181
|
return {
|
|
174
182
|
message,
|
|
175
183
|
launchKind
|
|
176
184
|
};
|
|
177
185
|
},
|
|
178
|
-
[
|
|
186
|
+
[addIncoming, options]
|
|
179
187
|
);
|
|
180
188
|
return React3.useMemo(
|
|
181
189
|
() => ({
|
|
182
190
|
items,
|
|
183
191
|
send,
|
|
192
|
+
addIncoming,
|
|
184
193
|
removeItem
|
|
185
194
|
}),
|
|
186
|
-
[items, removeItem, send]
|
|
195
|
+
[addIncoming, items, removeItem, send]
|
|
187
196
|
);
|
|
188
197
|
}
|
|
189
198
|
function parseCommand(text) {
|
|
@@ -697,6 +706,302 @@ function useFireworksEngine(options) {
|
|
|
697
706
|
return api;
|
|
698
707
|
}
|
|
699
708
|
|
|
709
|
+
// src/mikuFireworks3D/client/WebSocketTransport.ts
|
|
710
|
+
var WebSocketTransport = class {
|
|
711
|
+
constructor(config, callbacks) {
|
|
712
|
+
this.socket = null;
|
|
713
|
+
this.reconnectTimer = null;
|
|
714
|
+
this.isManualClose = false;
|
|
715
|
+
this.pendingQueue = [];
|
|
716
|
+
this.config = config;
|
|
717
|
+
this.callbacks = callbacks || {};
|
|
718
|
+
this.state = {
|
|
719
|
+
connected: false,
|
|
720
|
+
joined: false,
|
|
721
|
+
onlineCount: 0,
|
|
722
|
+
roomId: config.roomId
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
connect() {
|
|
726
|
+
if (this.socket && (this.socket.readyState === window.WebSocket.OPEN || this.socket.readyState === window.WebSocket.CONNECTING)) {
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
this.isManualClose = false;
|
|
730
|
+
try {
|
|
731
|
+
this.socket = this.config.protocols ? new window.WebSocket(this.config.serverUrl, this.config.protocols) : new window.WebSocket(this.config.serverUrl);
|
|
732
|
+
} catch {
|
|
733
|
+
this.callbacks.onError?.(new Error("Failed to create WebSocket connection."));
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
this.socket.onopen = () => {
|
|
737
|
+
this.updateState({ connected: true, joined: false });
|
|
738
|
+
this.send({
|
|
739
|
+
type: "join",
|
|
740
|
+
roomId: this.config.roomId,
|
|
741
|
+
user: this.config.user
|
|
742
|
+
});
|
|
743
|
+
};
|
|
744
|
+
this.socket.onmessage = (event) => {
|
|
745
|
+
const parsed = parseServerMessage(event.data);
|
|
746
|
+
if (!parsed) {
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
this.handleServerMessage(parsed);
|
|
750
|
+
};
|
|
751
|
+
this.socket.onerror = () => {
|
|
752
|
+
this.callbacks.onError?.(new Error("WebSocket transport error."));
|
|
753
|
+
};
|
|
754
|
+
this.socket.onclose = () => {
|
|
755
|
+
this.updateState({ connected: false, joined: false });
|
|
756
|
+
this.scheduleReconnect();
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
disconnect() {
|
|
760
|
+
this.isManualClose = true;
|
|
761
|
+
this.pendingQueue.length = 0;
|
|
762
|
+
if (this.reconnectTimer != null) {
|
|
763
|
+
window.clearTimeout(this.reconnectTimer);
|
|
764
|
+
this.reconnectTimer = null;
|
|
765
|
+
}
|
|
766
|
+
if (!this.socket) {
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
this.send({ type: "leave" });
|
|
770
|
+
this.socket.close();
|
|
771
|
+
this.socket = null;
|
|
772
|
+
}
|
|
773
|
+
sendDanmaku(payload) {
|
|
774
|
+
this.send({
|
|
775
|
+
type: "danmaku.send",
|
|
776
|
+
payload
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
sendFirework(payload) {
|
|
780
|
+
this.send({
|
|
781
|
+
type: "firework.launch",
|
|
782
|
+
payload
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
getState() {
|
|
786
|
+
return this.state;
|
|
787
|
+
}
|
|
788
|
+
send(message) {
|
|
789
|
+
if (!this.socket || this.socket.readyState !== window.WebSocket.OPEN) {
|
|
790
|
+
if (message.type === "danmaku.send" || message.type === "firework.launch") {
|
|
791
|
+
this.pendingQueue.push(message);
|
|
792
|
+
}
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
795
|
+
if ((message.type === "danmaku.send" || message.type === "firework.launch") && !this.state.joined) {
|
|
796
|
+
this.pendingQueue.push(message);
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
this.socket.send(JSON.stringify(message));
|
|
800
|
+
}
|
|
801
|
+
updateState(partial) {
|
|
802
|
+
this.state = {
|
|
803
|
+
...this.state,
|
|
804
|
+
...partial
|
|
805
|
+
};
|
|
806
|
+
this.callbacks.onStateChange?.(this.state);
|
|
807
|
+
}
|
|
808
|
+
handleServerMessage(message) {
|
|
809
|
+
if (message.type === "joined") {
|
|
810
|
+
this.updateState({ roomId: message.roomId, onlineCount: message.onlineCount, joined: true });
|
|
811
|
+
this.flushPendingQueue();
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
if (message.type === "room.user_joined" || message.type === "room.user_left") {
|
|
815
|
+
this.updateState({ onlineCount: message.onlineCount, roomId: message.roomId });
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
if (message.type === "room.snapshot") {
|
|
819
|
+
this.updateState({ roomId: message.roomId, onlineCount: message.users.length });
|
|
820
|
+
this.callbacks.onSnapshot?.(message);
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
if (message.type === "danmaku.broadcast") {
|
|
824
|
+
this.callbacks.onDanmakuBroadcast?.(message.event);
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
if (message.type === "firework.broadcast") {
|
|
828
|
+
this.callbacks.onFireworkBroadcast?.(message.event);
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
if (message.type === "error") {
|
|
832
|
+
this.callbacks.onError?.(new Error(`${message.code}: ${message.message}`));
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
scheduleReconnect() {
|
|
836
|
+
const reconnect = this.config.reconnect ?? true;
|
|
837
|
+
if (this.isManualClose || !reconnect) {
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
if (this.reconnectTimer != null) {
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
const delay = this.config.reconnectIntervalMs ?? 1500;
|
|
844
|
+
this.reconnectTimer = window.setTimeout(() => {
|
|
845
|
+
this.reconnectTimer = null;
|
|
846
|
+
this.connect();
|
|
847
|
+
}, delay);
|
|
848
|
+
}
|
|
849
|
+
flushPendingQueue() {
|
|
850
|
+
if (!this.socket || this.socket.readyState !== window.WebSocket.OPEN || !this.state.joined) {
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
while (this.pendingQueue.length > 0) {
|
|
854
|
+
const message = this.pendingQueue.shift();
|
|
855
|
+
if (!message) {
|
|
856
|
+
break;
|
|
857
|
+
}
|
|
858
|
+
this.socket.send(JSON.stringify(message));
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
};
|
|
862
|
+
function parseServerMessage(raw) {
|
|
863
|
+
if (typeof raw !== "string") {
|
|
864
|
+
return null;
|
|
865
|
+
}
|
|
866
|
+
try {
|
|
867
|
+
return JSON.parse(raw);
|
|
868
|
+
} catch {
|
|
869
|
+
return null;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
// src/mikuFireworks3D/hooks/useFireworksRealtime.ts
|
|
874
|
+
function useFireworksRealtime(options) {
|
|
875
|
+
const { config, enabled, onDanmakuBroadcast, onFireworkBroadcast, onSnapshot, onError, onStateChange } = options;
|
|
876
|
+
const transportRef = React3.useRef(null);
|
|
877
|
+
const callbackRef = React3.useRef({
|
|
878
|
+
onDanmakuBroadcast,
|
|
879
|
+
onFireworkBroadcast,
|
|
880
|
+
onSnapshot,
|
|
881
|
+
onError,
|
|
882
|
+
onStateChange
|
|
883
|
+
});
|
|
884
|
+
const serverUrl = config?.serverUrl ?? "";
|
|
885
|
+
const roomId = config?.roomId ?? "";
|
|
886
|
+
const userId = config?.user.userId ?? "";
|
|
887
|
+
const nickname = config?.user.nickname ?? "";
|
|
888
|
+
const avatarUrl = config?.user.avatarUrl ?? "";
|
|
889
|
+
const reconnect = config?.reconnect ?? true;
|
|
890
|
+
const reconnectIntervalMs = config?.reconnectIntervalMs ?? 1500;
|
|
891
|
+
const [state, setState] = React3.useState({
|
|
892
|
+
connected: false,
|
|
893
|
+
joined: false,
|
|
894
|
+
onlineCount: 0,
|
|
895
|
+
roomId
|
|
896
|
+
});
|
|
897
|
+
React3.useEffect(() => {
|
|
898
|
+
callbackRef.current = {
|
|
899
|
+
onDanmakuBroadcast,
|
|
900
|
+
onFireworkBroadcast,
|
|
901
|
+
onSnapshot,
|
|
902
|
+
onError,
|
|
903
|
+
onStateChange
|
|
904
|
+
};
|
|
905
|
+
}, [onDanmakuBroadcast, onError, onFireworkBroadcast, onSnapshot, onStateChange]);
|
|
906
|
+
const normalizedConfig = React3.useMemo(() => {
|
|
907
|
+
if (!serverUrl || !roomId || !userId) {
|
|
908
|
+
return void 0;
|
|
909
|
+
}
|
|
910
|
+
const protocols = Array.isArray(config?.protocols) ? [...config.protocols] : config?.protocols;
|
|
911
|
+
return {
|
|
912
|
+
serverUrl,
|
|
913
|
+
roomId,
|
|
914
|
+
user: {
|
|
915
|
+
userId,
|
|
916
|
+
nickname: nickname || void 0,
|
|
917
|
+
avatarUrl: avatarUrl || void 0
|
|
918
|
+
},
|
|
919
|
+
protocols,
|
|
920
|
+
reconnect,
|
|
921
|
+
reconnectIntervalMs
|
|
922
|
+
};
|
|
923
|
+
}, [avatarUrl, config?.protocols, nickname, reconnect, reconnectIntervalMs, roomId, serverUrl, userId]);
|
|
924
|
+
React3.useEffect(() => {
|
|
925
|
+
if (!enabled || !normalizedConfig) {
|
|
926
|
+
transportRef.current?.disconnect();
|
|
927
|
+
transportRef.current = null;
|
|
928
|
+
setState({
|
|
929
|
+
connected: false,
|
|
930
|
+
joined: false,
|
|
931
|
+
onlineCount: 0,
|
|
932
|
+
roomId: normalizedConfig?.roomId
|
|
933
|
+
});
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
936
|
+
const transport = new WebSocketTransport(normalizedConfig, {
|
|
937
|
+
onStateChange: (nextState) => {
|
|
938
|
+
setState(nextState);
|
|
939
|
+
callbackRef.current.onStateChange?.(nextState);
|
|
940
|
+
},
|
|
941
|
+
onDanmakuBroadcast: (event) => {
|
|
942
|
+
callbackRef.current.onDanmakuBroadcast?.({
|
|
943
|
+
id: event.id,
|
|
944
|
+
text: event.text,
|
|
945
|
+
color: event.color,
|
|
946
|
+
kind: event.kind,
|
|
947
|
+
userId: event.user.userId,
|
|
948
|
+
timestamp: event.timestamp
|
|
949
|
+
});
|
|
950
|
+
},
|
|
951
|
+
onFireworkBroadcast: (event) => {
|
|
952
|
+
callbackRef.current.onFireworkBroadcast?.({
|
|
953
|
+
id: event.id,
|
|
954
|
+
payload: event.payload,
|
|
955
|
+
userId: event.user.userId,
|
|
956
|
+
timestamp: event.timestamp
|
|
957
|
+
});
|
|
958
|
+
},
|
|
959
|
+
onSnapshot: (snapshot) => {
|
|
960
|
+
callbackRef.current.onSnapshot?.({
|
|
961
|
+
roomId: snapshot.roomId,
|
|
962
|
+
danmakuHistory: snapshot.danmakuHistory.map((item) => ({
|
|
963
|
+
id: item.id,
|
|
964
|
+
text: item.text,
|
|
965
|
+
color: item.color,
|
|
966
|
+
kind: item.kind,
|
|
967
|
+
userId: item.user.userId,
|
|
968
|
+
timestamp: item.timestamp
|
|
969
|
+
})),
|
|
970
|
+
fireworkHistory: snapshot.fireworkHistory.map((item) => ({
|
|
971
|
+
id: item.id,
|
|
972
|
+
payload: item.payload,
|
|
973
|
+
userId: item.user.userId,
|
|
974
|
+
timestamp: item.timestamp
|
|
975
|
+
}))
|
|
976
|
+
});
|
|
977
|
+
},
|
|
978
|
+
onError: (error) => {
|
|
979
|
+
callbackRef.current.onError?.(error);
|
|
980
|
+
}
|
|
981
|
+
});
|
|
982
|
+
transport.connect();
|
|
983
|
+
transportRef.current = transport;
|
|
984
|
+
return () => {
|
|
985
|
+
transport.disconnect();
|
|
986
|
+
if (transportRef.current === transport) {
|
|
987
|
+
transportRef.current = null;
|
|
988
|
+
}
|
|
989
|
+
};
|
|
990
|
+
}, [enabled, normalizedConfig]);
|
|
991
|
+
return React3.useMemo(
|
|
992
|
+
() => ({
|
|
993
|
+
state,
|
|
994
|
+
sendDanmaku: (payload) => {
|
|
995
|
+
transportRef.current?.sendDanmaku(payload);
|
|
996
|
+
},
|
|
997
|
+
sendFirework: (payload) => {
|
|
998
|
+
transportRef.current?.sendFirework(payload);
|
|
999
|
+
}
|
|
1000
|
+
}),
|
|
1001
|
+
[state]
|
|
1002
|
+
);
|
|
1003
|
+
}
|
|
1004
|
+
|
|
700
1005
|
// src/mikuFireworks3D/components/MikuFireworks3D.tsx
|
|
701
1006
|
function MikuFireworks3D({
|
|
702
1007
|
width = "100%",
|
|
@@ -710,11 +1015,15 @@ function MikuFireworks3D({
|
|
|
710
1015
|
onLaunch,
|
|
711
1016
|
onDanmakuSend,
|
|
712
1017
|
onError,
|
|
713
|
-
onFpsReport
|
|
1018
|
+
onFpsReport,
|
|
1019
|
+
onRealtimeStateChange,
|
|
1020
|
+
realtime
|
|
714
1021
|
}) {
|
|
715
1022
|
const [selectedKind, setSelectedKind] = React3.useState(defaultKind);
|
|
716
1023
|
const [avatarUrl, setAvatarUrl] = React3.useState(defaultAvatarUrl);
|
|
717
1024
|
const [autoLaunch, setAutoLaunch] = React3.useState(autoLaunchOnDanmaku);
|
|
1025
|
+
const seenDanmakuIdsRef = React3.useRef(/* @__PURE__ */ new Set());
|
|
1026
|
+
const seenFireworkIdsRef = React3.useRef(/* @__PURE__ */ new Set());
|
|
718
1027
|
const { containerRef, canvasRef, launch, fps } = useFireworksEngine({
|
|
719
1028
|
maxParticles,
|
|
720
1029
|
maxActiveFireworks,
|
|
@@ -722,22 +1031,93 @@ function MikuFireworks3D({
|
|
|
722
1031
|
onError,
|
|
723
1032
|
onFpsReport
|
|
724
1033
|
});
|
|
725
|
-
const { items, send, removeItem } = useDanmakuController({
|
|
1034
|
+
const { items, send, addIncoming, removeItem } = useDanmakuController({
|
|
726
1035
|
onSend: onDanmakuSend
|
|
727
1036
|
});
|
|
1037
|
+
const realtimeEnabled = Boolean(realtime && (realtime.enabled ?? true));
|
|
1038
|
+
const realtimeApi = useFireworksRealtime({
|
|
1039
|
+
enabled: realtimeEnabled,
|
|
1040
|
+
config: realtime,
|
|
1041
|
+
onStateChange: onRealtimeStateChange,
|
|
1042
|
+
onError,
|
|
1043
|
+
onDanmakuBroadcast: (event) => {
|
|
1044
|
+
if (seenDanmakuIdsRef.current.has(event.id)) {
|
|
1045
|
+
return;
|
|
1046
|
+
}
|
|
1047
|
+
seenDanmakuIdsRef.current.add(event.id);
|
|
1048
|
+
addIncoming({
|
|
1049
|
+
id: event.id,
|
|
1050
|
+
userId: event.userId,
|
|
1051
|
+
text: event.text,
|
|
1052
|
+
color: event.color,
|
|
1053
|
+
timestamp: event.timestamp
|
|
1054
|
+
});
|
|
1055
|
+
},
|
|
1056
|
+
onFireworkBroadcast: (event) => {
|
|
1057
|
+
if (seenFireworkIdsRef.current.has(event.id)) {
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
seenFireworkIdsRef.current.add(event.id);
|
|
1061
|
+
launch(event.payload);
|
|
1062
|
+
},
|
|
1063
|
+
onSnapshot: (snapshot) => {
|
|
1064
|
+
for (const danmaku of snapshot.danmakuHistory) {
|
|
1065
|
+
if (seenDanmakuIdsRef.current.has(danmaku.id)) {
|
|
1066
|
+
continue;
|
|
1067
|
+
}
|
|
1068
|
+
seenDanmakuIdsRef.current.add(danmaku.id);
|
|
1069
|
+
addIncoming({
|
|
1070
|
+
id: danmaku.id,
|
|
1071
|
+
userId: danmaku.userId,
|
|
1072
|
+
text: danmaku.text,
|
|
1073
|
+
color: danmaku.color,
|
|
1074
|
+
timestamp: danmaku.timestamp
|
|
1075
|
+
});
|
|
1076
|
+
}
|
|
1077
|
+
for (const firework of snapshot.fireworkHistory) {
|
|
1078
|
+
if (seenFireworkIdsRef.current.has(firework.id)) {
|
|
1079
|
+
continue;
|
|
1080
|
+
}
|
|
1081
|
+
seenFireworkIdsRef.current.add(firework.id);
|
|
1082
|
+
launch(firework.payload);
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
});
|
|
728
1086
|
const handleLaunch = (kind) => {
|
|
729
|
-
|
|
1087
|
+
const payload = {
|
|
730
1088
|
kind,
|
|
731
1089
|
avatarUrl: kind === "avatar" ? avatarUrl || void 0 : void 0
|
|
732
|
-
}
|
|
1090
|
+
};
|
|
1091
|
+
if (realtimeEnabled && realtimeApi.state.connected && realtimeApi.state.joined) {
|
|
1092
|
+
realtimeApi.sendFirework(payload);
|
|
1093
|
+
return;
|
|
1094
|
+
}
|
|
1095
|
+
launch(payload);
|
|
733
1096
|
};
|
|
734
1097
|
const handleSendDanmaku = (text) => {
|
|
735
|
-
const result = send(text
|
|
1098
|
+
const result = send(text, void 0, {
|
|
1099
|
+
optimistic: !(realtimeEnabled && realtimeApi.state.connected && realtimeApi.state.joined)
|
|
1100
|
+
});
|
|
736
1101
|
if (!result) {
|
|
737
1102
|
return;
|
|
738
1103
|
}
|
|
739
1104
|
const launchKind = result.launchKind ?? selectedKind;
|
|
740
|
-
if (
|
|
1105
|
+
if (realtimeEnabled && realtimeApi.state.connected && realtimeApi.state.joined) {
|
|
1106
|
+
realtimeApi.sendDanmaku({
|
|
1107
|
+
text: result.message.text,
|
|
1108
|
+
color: result.message.color,
|
|
1109
|
+
kind: result.launchKind
|
|
1110
|
+
});
|
|
1111
|
+
if (autoLaunch) {
|
|
1112
|
+
realtimeApi.sendFirework({
|
|
1113
|
+
kind: launchKind,
|
|
1114
|
+
avatarUrl: launchKind === "avatar" ? avatarUrl || void 0 : void 0,
|
|
1115
|
+
message: result.message
|
|
1116
|
+
});
|
|
1117
|
+
}
|
|
1118
|
+
return;
|
|
1119
|
+
}
|
|
1120
|
+
if (autoLaunch || result.launchKind) {
|
|
741
1121
|
launch({
|
|
742
1122
|
kind: launchKind,
|
|
743
1123
|
avatarUrl: launchKind === "avatar" ? avatarUrl || void 0 : void 0,
|
|
@@ -776,7 +1156,9 @@ function MikuFireworks3D({
|
|
|
776
1156
|
avatarUrl,
|
|
777
1157
|
onAvatarUrlChange: setAvatarUrl,
|
|
778
1158
|
onLaunch: () => handleLaunch(selectedKind),
|
|
779
|
-
fps
|
|
1159
|
+
fps,
|
|
1160
|
+
realtimeConnected: realtimeEnabled ? realtimeApi.state.connected : void 0,
|
|
1161
|
+
onlineCount: realtimeEnabled ? realtimeApi.state.onlineCount : void 0
|
|
780
1162
|
}
|
|
781
1163
|
), /* @__PURE__ */ React3__default.default.createElement(DanmakuPanel, { onSend: handleSendDanmaku }), /* @__PURE__ */ React3__default.default.createElement("style", null, `
|
|
782
1164
|
@keyframes sa2kit-danmaku-move {
|
|
@@ -803,7 +1185,9 @@ exports.FireworksControlPanel = FireworksControlPanel;
|
|
|
803
1185
|
exports.MIKU_PALETTE = MIKU_PALETTE;
|
|
804
1186
|
exports.MikuFireworks3D = MikuFireworks3D;
|
|
805
1187
|
exports.NORMAL_PALETTE = NORMAL_PALETTE;
|
|
1188
|
+
exports.WebSocketTransport = WebSocketTransport;
|
|
806
1189
|
exports.useDanmakuController = useDanmakuController;
|
|
807
1190
|
exports.useFireworksEngine = useFireworksEngine;
|
|
808
|
-
|
|
809
|
-
//# sourceMappingURL=chunk-
|
|
1191
|
+
exports.useFireworksRealtime = useFireworksRealtime;
|
|
1192
|
+
//# sourceMappingURL=chunk-XXDMARU7.js.map
|
|
1193
|
+
//# sourceMappingURL=chunk-XXDMARU7.js.map
|