Skip to content

List the server's entities, draw them on the live map and delete them a hundred at a time - #61

Merged
ImBaphomettt merged 12 commits into
mainfrom
entities
Nov 11, 2026
Merged

ImBaphomettt merged 12 commits into
mainfrom
entities

Conversation

@ImBaphomettt

@ImBaphomettt ImBaphomettt commented Nov 11, 2026 •

Copy link
Copy Markdown
Member

Seven commits, three merges of main (#56, #57, #59) and two commits the merges called for. The bridge lists the server's vehicles, peds and objects through OneSync while a panel looks at them, and deletes the ones an account picks, a hundred at a time, with the guards of the txAdmin fork's Entity Manager. The panel gets an Entities page under Insights, an Entities layer on the live map, and a Settings category for how often the server lists them. Entities is an optional feature of its own, on by default: turned off, it runs nothing and its routes answer feature_disabled. Observer keeps no entity: the list lives in memory.

What changed

The count of who follows a live view, out of the map (d9e2477)

  • crates/observer-app/src/watching.rs: Watchers (join, any, subscribe) and the Watching guard, moved out of map.rs. observer_app::Watching keeps its path.
  • crates/observer-web/src/live/topics.rs: map_events becomes watched_events, for any view the server feeds only while someone looks.

Shared panel helpers (d97f7c8)

  • web/src/lib/search.ts: oneOf, text and defined, taken out of drops/search.ts and statistics/search.ts.
  • web/src/settings/Row.tsx: CategoryLoading and CategoryLink, used by LiveMap.tsx. Bans.tsx keeps its own copies for now: other open branches rework it.

The server's side (e620e7e)

  • resource/observer/server.lua, in a block of its own before ACTIONS: action entities with a lease (everyMs, forMs), as positions has. A sweep reads GetAllVehicles, GetAllObjects and GetAllPeds, works a millisecond at a time and gives the frame back with Wait(0), stops at 50 ms of work or 20,000 rows, and spaces the next sweeps out (twice the cadence, up to 60 s) after one that took over 25 ms of work or 10 ms of listing. It reports entities in parts of 500 rows or 64 KB, a row being netId,serial,kind,class,model,x,y,z,owner,bucket,population,resource,flags, and looks the creating resource up for 300 entities a sweep at most, since GetEntityScript walks every resource. Action deleteEntities takes net id and serial pairs, a deadline and the bridge's epoch; it refuses a player's own ped, a vehicle a player sits in, a train, an entity whose serial or model changed, and anything past the deadline; it checks DoesEntityExist 250 ms later and reports entitiesDeleted. The contract does not change: two internal reports and two actions, no event, no export.
  • crates/observer-domain/src/entities.rs (types, filters, sort, limits), crates/observer-fxserver/src/entities.rs (the reports), crates/observer-app/src/entities.rs and entities/query.rs (the service: the lease while a topic or a page watches, the parts gathered into one list, filters, facets, pages, map points or density cells, the deletion and its audit entry), crates/observer-store/src/entities.rs (the cadence, in settings), crates/observer-web/src/api/entities.rs.
  • Routes: GET /api/servers/default/entities and GET …/entities/map (ENTITIES_VIEW), POST …/entities/delete (ENTITIES_DELETE), GET …/entities/settings (SETTINGS_VIEW), PUT …/entities/settings (SETTINGS_MANAGE, with the password again). Topic server.entities (ENTITIES_VIEW).
  • Permissions ENTITIES_VIEW (bit 27, area Entities) and ENTITIES_DELETE (bit 28, sensitive, implies the view). Audit actions entities_deleted and entities_settings_changed. Error codes entities_not_listed, entities_changed, entities_out_of_date, entities_deleting (409), too_many_entities and invalid_entities_settings (400). Feature entities, on by default.
  • Who owns an entity, and whether a player sits in a vehicle, are told only to accounts that also hold PLAYERS_MAP: both say where a player is.
  • fake-fxserver: entities set from its console (fake_entity, fake_entities, fake_entity_gone, fake_entity_stays, fake_enter, fake_possess), and the convars fake_entities_every_ms, fake_entities_row_us and fake_entities_list_us for what a sweep costs.
  • The generated bindings, and the panel's words for the new permissions, feature, audit actions and errors; the audit log words what a deletion took and left.

The Entities page (7416271)

  • web/src/pages/EntitiesPage.tsx, under Insights: the type with the map's mark, the model's hash, the net id, the creating resource, the owner, the position and the bucket. Filters by type, vehicle class, resource, owner and bucket, a search, the most common models; a sort by column, a hundred a page; filters, sort and page in the address.
  • A selection of up to 100 (web/src/entities/selection.ts): an occupied vehicle and a train are never offered, and nothing is deleted from a list three sweeps old or from another run of the server.
  • web/src/entities/DeleteDialog.tsx: what the selection holds, how many a script created or a player's game simulates, and from 20 entities the word DELETE to type; then a notice of what became of each.
  • A list in place of the table on a phone. web/src/components/Checkbox.tsx draws a page that is partly selected; web/src/components/SelectField.tsx is the labelled select.

The live map's layer (d3dd8ad)

  • web/src/entities/MapLayer.tsx: an Entities switch beside Names and Trails. The entities are drawn on one canvas under the players, a shape per kind. Past 5,000 in the part of the map in view, the API sends density cells instead, and a click on a cell zooms into it. A click on an entity opens its card, with its place in the list and a deletion.
  • web/src/map/MapCanvas.tsx gains generic props (renderLayer, onViewport, onPress, frame) and knows nothing of entities. useTopic takes enabled, so that the server lists only while the layer is on.
  • The list's pin opens the map on an entity: /map?entity=<net id>.

The cadence in Settings (1784f05): Settings › Entities, every 5, 10, 15, 30 or 60 seconds (15 by default), saved with the password again, in the audit log.

README (594471a): the Entities section, the rail's groups and the feature list.

Merges of main (9a4f9e5, 0ef1f3a, a842814) and what they called for (7a0cfbd, 98f3eee)

Why

Observer could not show what the server holds. The txAdmin fork's Entity Manager lists and deletes entities; this brings it with the fork's guards (100 at most, a word to type from 20, never a player's ped, an occupied vehicle or a train, never from a stale list, the owner hidden from who does not see the map), while the server pays for a sweep only while someone looks.

Notes for review

Verified

  • cargo xtask check on Windows at a842814: fmt, icons, clippy with -D warnings with and without test-catalog, 3,402 Rust tests in 49 test binaries, none failed, bindings unchanged, and in web/ format, lint, type check, 892 tests and the build, under Node 26.13.
  • Each of the seven commits on its own before it was made: Rust at d9e2477 and e620e7e (fmt, clippy, the app and web tests, bindings unchanged), the panel at each one (format, lint, type check, tests, and the build from 7416271 on).
  • npm run e2e at a842814, with the binaries cargo xtask e2e builds: 11 flows passed and 2 are skipped on Windows. A first run had stopped at the flow that checks a label on the player's profile: the Labels card did not show CHAR-1234 within 30 s. It passed on the next run, and this branch touches neither players nor labels. Chromium 1248, already on this machine, was given through PLAYWRIGHT_BROWSERS_PATH, because the npx playwright install of cargo xtask e2e would have downloaded 1254.
  • crates/fake-fxserver/tests/runtime.rs: a list made only while someone looks, a deletion with each outcome and its audit entry, a server without OneSync.
  • The bridge's entity code in a throwaway harness (mlua, Lua 5.4, natives mocked), its output read back by Observer's parser: a sweep, the end of the lease, parts and lookups, a stale handle, a costly sweep cut short and spaced out, the reasons it cannot list, the outcomes of a deletion. The harness is not in the repository.
  • In the browser, against a lab Observer and the fake with 6 players and about 520 then 7,000 entities, before the merges: the page, its filters, sort and selection, the dialog, a deletion and its audit entry, the layer and its density cells, the map opened on an entity from the list, the Settings category; dark and light, 1440 and 375 px, the console without errors.
  • GitHub Actions does not start the jobs at the moment: on this PR, the Panel job ended in 3 seconds, "not started because recent account payments have failed or your spending limit needs to be increased", and the two others were skipped, as on Run the fake FXServer tests on ports the system gives, so that two runs on one host no longer collide #56, Follow the server's resources on a Resources page, and start, stop, restart or rescan them #57 and Show the integration contract in the panel, on a Documentation page drawn from the file the binary ships #59. The checks above are the CI's Panel, Rust and browser steps, run locally on Windows.

Not verified

  • A real FXServer: no entity native ran on one. To try on the lab, with OneSync and two players: GetAllVehicles, GetAllObjects, GetAllPeds, NetworkGetNetworkIdFromEntity, GetEntityModel, GetVehicleType, GetEntityPopulationType, GetEntityCoords, NetworkGetEntityOwner, GetEntityRoutingBucket, GetEntityScript, GetPlayerPed with a string source, GetVehiclePedIsIn, NetworkGetEntityFromNetworkId, IsPedAPlayer, DeleteEntity and DoesEntityExist; os.nanotime in CfxLua; json.encode of an empty table; what a sweep costs on a busy server; the refusal under RedM; the lease ending within a second.
  • Linux: no WSL distribution on this machine, so the Linux leg of the Rust job did not run.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant