mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-27 06:57:15 +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
|
* 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
|
* 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 () {
|
(function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
@@ -20,7 +21,8 @@
|
|||||||
playhead: 0, // ms from its start
|
playhead: 0, // ms from its start
|
||||||
playing: false,
|
playing: false,
|
||||||
selected: -1,
|
selected: -1,
|
||||||
loading: false
|
loading: false,
|
||||||
|
worlds: [] // the characters' moves between world servers (the worlds route)
|
||||||
};
|
};
|
||||||
|
|
||||||
function bytesText(n) {
|
function bytesText(n) {
|
||||||
@@ -139,6 +141,8 @@
|
|||||||
stop();
|
stop();
|
||||||
state.capture = state.live.concat(state.saved).filter(function (c) { return c.id === id; })[0] || { id: id, received: 0, bytes: 0 };
|
state.capture = state.live.concat(state.saved).filter(function (c) { return c.id === id; })[0] || { id: id, received: 0, bytes: 0 };
|
||||||
state.records = [];
|
state.records = [];
|
||||||
|
state.worlds = [];
|
||||||
|
byId('worldMarkers').innerHTML = '';
|
||||||
state.selected = -1;
|
state.selected = -1;
|
||||||
history.replaceState(null, '', '#capture=' + id);
|
history.replaceState(null, '', '#capture=' + id);
|
||||||
byId('viewer').classList.remove('d-none');
|
byId('viewer').classList.remove('d-none');
|
||||||
@@ -177,9 +181,23 @@
|
|||||||
if (fresh) setPlayhead(state.duration);
|
if (fresh) setPlayhead(state.duration);
|
||||||
else render();
|
else render();
|
||||||
renderHeader();
|
renderHeader();
|
||||||
|
loadWorlds(c.id);
|
||||||
}, function () { state.loading = false; });
|
}, 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() {
|
function filtered() {
|
||||||
var name = byId('nameFilter').value.trim().toUpperCase(), source = byId('sourceFilter').value;
|
var name = byId('nameFilter').value.trim().toUpperCase(), source = byId('sourceFilter').value;
|
||||||
if (!name && !source) return state.records;
|
if (!name && !source) return state.records;
|
||||||
@@ -240,6 +258,12 @@
|
|||||||
byId('playBtn').addEventListener('click', function () { if (state.playing) stop(); else play(); });
|
byId('playBtn').addEventListener('click', function () { if (state.playing) stop(); else play(); });
|
||||||
byId('endBtn').addEventListener('click', function () { stop(); setPlayhead(state.duration); });
|
byId('endBtn').addEventListener('click', function () { stop(); setPlayhead(state.duration); });
|
||||||
byId('scrub').addEventListener('input', function () { stop(); setPlayhead(Number(byId('scrub').value)); });
|
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('nameFilter').addEventListener('input', render);
|
||||||
byId('sourceFilter').addEventListener('change', render);
|
byId('sourceFilter').addEventListener('change', render);
|
||||||
document.addEventListener('keydown', function (e) {
|
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="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>
|
<option value="2">2×</option><option value="4">4×</option><option value="16">16×</option><option value="64">64×</option>
|
||||||
</select>
|
</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>
|
<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>
|
<button type="button" class="btn btn-sm btn-outline-secondary" id="endBtn" title="Show everything">End</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user