mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 10:53:44 +00:00
feat(dashboard): world change markers on the packet capture timeline
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
/**
|
||||
* Packet Captures (docs/CaptureReplay.md): arm a capture for an account, a character or everything; the running and
|
||||
* saved ones; and a viewer that plays a capture back on one timeline (play, pause, seek, speed), with each packet's
|
||||
* decoded fields and bytes. While it plays, the time is sent to World 3D pages showing the same capture.
|
||||
* decoded fields and bytes. While it plays, the time is sent to World 3D pages showing the same capture. The timeline
|
||||
* marks each time a captured character moved to another world server, with the zone's name.
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
@@ -20,7 +21,8 @@
|
||||
playhead: 0, // ms from its start
|
||||
playing: false,
|
||||
selected: -1,
|
||||
loading: false
|
||||
loading: false,
|
||||
worlds: [] // the characters' moves between world servers (the worlds route)
|
||||
};
|
||||
|
||||
function bytesText(n) {
|
||||
@@ -139,6 +141,8 @@
|
||||
stop();
|
||||
state.capture = state.live.concat(state.saved).filter(function (c) { return c.id === id; })[0] || { id: id, received: 0, bytes: 0 };
|
||||
state.records = [];
|
||||
state.worlds = [];
|
||||
byId('worldMarkers').innerHTML = '';
|
||||
state.selected = -1;
|
||||
history.replaceState(null, '', '#capture=' + id);
|
||||
byId('viewer').classList.remove('d-none');
|
||||
@@ -177,9 +181,23 @@
|
||||
if (fresh) setPlayhead(state.duration);
|
||||
else render();
|
||||
renderHeader();
|
||||
loadWorlds(c.id);
|
||||
}, function () { state.loading = false; });
|
||||
}
|
||||
|
||||
// The timeline's world change markers (world3d-core.js draws them, as World 3D's replay does)
|
||||
function loadWorlds(id) {
|
||||
Promise.all([api.get(url(id) + '/worlds'), import('/js/world3d-core.js')]).then(function (results) {
|
||||
var d = results[0], core = results[1];
|
||||
if (!state.capture || state.capture.id !== id || !d.worlds) return;
|
||||
state.worlds = d.worlds;
|
||||
var characters = {};
|
||||
d.worlds.forEach(function (w) { characters[w.character] = true; });
|
||||
var markers = core.worldMarkers(d.worlds, state.duration / 1000);
|
||||
byId('worldMarkers').innerHTML = core.markersHtml(markers, esc, Object.keys(characters).length > 1);
|
||||
}).catch(function () {});
|
||||
}
|
||||
|
||||
function filtered() {
|
||||
var name = byId('nameFilter').value.trim().toUpperCase(), source = byId('sourceFilter').value;
|
||||
if (!name && !source) return state.records;
|
||||
@@ -240,6 +258,12 @@
|
||||
byId('playBtn').addEventListener('click', function () { if (state.playing) stop(); else play(); });
|
||||
byId('endBtn').addEventListener('click', function () { stop(); setPlayhead(state.duration); });
|
||||
byId('scrub').addEventListener('input', function () { stop(); setPlayhead(Number(byId('scrub').value)); });
|
||||
byId('worldMarkers').addEventListener('click', function (e) {
|
||||
var marker = e.target.closest('[data-t]');
|
||||
if (!marker) return;
|
||||
stop();
|
||||
setPlayhead(Number(marker.dataset.t) * 1000);
|
||||
});
|
||||
byId('nameFilter').addEventListener('input', render);
|
||||
byId('sourceFilter').addEventListener('change', render);
|
||||
document.addEventListener('keydown', function (e) {
|
||||
|
||||
@@ -96,7 +96,10 @@
|
||||
<option value="0.25">0.25×</option><option value="0.5">0.5×</option><option value="1" selected>1×</option>
|
||||
<option value="2">2×</option><option value="4">4×</option><option value="16">16×</option><option value="64">64×</option>
|
||||
</select>
|
||||
<input type="range" class="form-range flex-grow-1 w-auto" id="scrub" min="0" max="1" step="1" value="0" aria-label="Time in the capture">
|
||||
<div class="timeline-track flex-grow-1">
|
||||
<div class="timeline-markers" id="worldMarkers" aria-label="World changes"></div>
|
||||
<input type="range" class="form-range" id="scrub" min="0" max="1" step="1" value="0" aria-label="Time in the capture">
|
||||
</div>
|
||||
<span class="font-monospace text-nowrap" id="timeText"></span>
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary" id="endBtn" title="Show everything">End</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user