docs(reference): import Dune: Awakening server-manager references
Phase 2 references for the host-agent Dune adapter, moved out of volatile /tmp
into docs/reference-repos/ (per Commander). Three upstream projects, .git +
node_modules + compiled binaries stripped (16MB source). Nested AI-instruction
files (.claude/, CLAUDE.md) removed so they don't pollute Corrosion sessions.
- icehunter/ dune-admin (Go+React) — 4 control planes; SETUP_DOCKER.md is the
closest analog to our agent's Dune docker control plane (compose
lifecycle, docker logs, RabbitMQ-via-exec, dune Postgres schema)
- adainrivers/ Rust/Tauri desktop — SSH+k8s BattleGroup control, maintenance
daemon, in-game admin console (Rust idiom reference)
- the4rchangel/ Node web UI replacing battlegroup.bat — matches the Commander's
Hyper-V self-host path + game-config schema
See docs/reference-repos/README.md for the full index + how we use each.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
-- _character_transfer_ensure_player_is_owner_of_vbt_vehicle(in_vehicle_id bigint[]) -> void
|
||||
-- oid: 58100 kind: FUNCTION category: vehicle
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune._character_transfer_ensure_player_is_owner_of_vbt_vehicle(in_vehicle_id bigint[])
|
||||
RETURNS void
|
||||
LANGUAGE sql
|
||||
AS $function$
|
||||
update permission_actor_rank set "rank" = 1 where permission_actor_id = any(in_vehicle_id);
|
||||
$function$
|
||||
@@ -0,0 +1,49 @@
|
||||
-- _character_transfer_store_in_world_owned_vehicles_into_recovery(in_player_id bigint) -> void
|
||||
-- oid: 58109 kind: FUNCTION category: vehicle
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune._character_transfer_store_in_world_owned_vehicles_into_recovery(in_player_id bigint)
|
||||
RETURNS void
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
DECLARE
|
||||
to_store RECORD;
|
||||
BEGIN
|
||||
-- remove any vehicles in 'Travel' state, so that they get re-added as recovered vehicles
|
||||
DELETE FROM actor_state ast
|
||||
WHERE ast.state = 'Travel'
|
||||
AND ast.actor_id IN (
|
||||
SELECT v.id
|
||||
FROM actors a
|
||||
INNER JOIN vehicles v ON a.id = v.id
|
||||
INNER JOIN permission_actor p ON a.id = p.actor_id
|
||||
INNER JOIN permission_actor_rank r ON p.actor_id = r.permission_actor_id
|
||||
WHERE r.player_id = in_player_id
|
||||
AND r.rank = 1::smallint
|
||||
);
|
||||
|
||||
FOR to_store IN
|
||||
SELECT v.id AS vehicle_id
|
||||
FROM actors a
|
||||
INNER JOIN vehicles v ON a.id = v.id
|
||||
INNER JOIN permission_actor p ON a.id = p.actor_id
|
||||
INNER JOIN permission_actor_rank r ON p.actor_id = r.permission_actor_id
|
||||
WHERE r.player_id = in_player_id
|
||||
AND r.rank = 1::smallint
|
||||
AND NOT EXISTS
|
||||
(
|
||||
SELECT 1 FROM actor_state
|
||||
WHERE actor_state.actor_id = v.id
|
||||
AND actor_state.state IS DISTINCT FROM 'Default'
|
||||
)
|
||||
LOOP
|
||||
-- note: storing hardcoded chassis durability because its not available from pure database :(
|
||||
-- this will only be shown incorrectly in UI though, the spawned vehicle will get the correct value
|
||||
PERFORM store_recovered_vehicle(to_store.vehicle_id, 1.0, 'None', true);
|
||||
|
||||
-- we delete the permissions for this vehicle so that they don't get exported and cause duplicated key failures
|
||||
-- when the player tries to recover their vehicle on the target battlegroup
|
||||
-- note: the server will destroy the vehicle as soon as it gets the pg_notify emitted from the store_recovered_vehicle call above, so this would happen regardless
|
||||
DELETE FROM permission_actor pa WHERE pa.actor_id = to_store.vehicle_id;
|
||||
END LOOP;
|
||||
END
|
||||
$function$
|
||||
@@ -0,0 +1,17 @@
|
||||
-- get_player_owned_vehicles_data(in_player_id bigint, in_account_id bigint) -> TABLE(out_actor_id bigint, out_name text, out_class text, out_map text, out_partition_id bigint, out_dimension integer, out_transform dune.transform, out_actor_state text)
|
||||
-- oid: 58342 kind: FUNCTION category: vehicle
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.get_player_owned_vehicles_data(in_player_id bigint, in_account_id bigint)
|
||||
RETURNS TABLE(out_actor_id bigint, out_name text, out_class text, out_map text, out_partition_id bigint, out_dimension integer, out_transform dune.transform, out_actor_state text)
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
BEGIN
|
||||
RETURN QUERY WITH owned_actors AS(
|
||||
SELECT (entry).actor_id, (entry).actor_name FROM get_permission_for_player_actors(in_player_id, 1::smallint) -- 1:owner
|
||||
WHERE (entry).actor_type = 2 -- 2:vehicles
|
||||
UNION SELECT vehicle_id, vehicle_name FROM recovered_vehicles -- note: recovered vehicles are removed from permission actors
|
||||
WHERE account_id = in_account_id
|
||||
) SELECT owned_actors.actor_id, actor_name, class, map, partition_id, dimension_index, transform, (actor_state).state::text
|
||||
FROM owned_actors LEFT JOIN actors ON actors.id = owned_actors.actor_id LEFT JOIN actor_state ON actor_state.actor_id = owned_actors.actor_id;
|
||||
END
|
||||
$function$
|
||||
@@ -0,0 +1,18 @@
|
||||
-- get_unbacked_up_vehicle_ids_for_account(in_account_id bigint) -> TABLE(vehicle_id bigint)
|
||||
-- oid: 58361 kind: FUNCTION category: vehicle
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.get_unbacked_up_vehicle_ids_for_account(in_account_id bigint)
|
||||
RETURNS TABLE(vehicle_id bigint)
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
BEGIN
|
||||
RETURN QUERY
|
||||
SELECT v.id
|
||||
FROM vehicles v
|
||||
JOIN permission_actor_rank par ON v.id = par.permission_actor_id
|
||||
JOIN player_state ps ON par.player_id = ps.player_controller_id
|
||||
left join backup_vehicles bv ON v.id = bv.vehicle_id
|
||||
WHERE ps.account_id = in_account_id
|
||||
AND bv.vehicle_id IS NULL;
|
||||
END
|
||||
$function$
|
||||
@@ -0,0 +1,18 @@
|
||||
-- get_vehicle_id(in_actor_id bigint, in_class text) -> bigint
|
||||
-- oid: 58364 kind: FUNCTION category: vehicle
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.get_vehicle_id(in_actor_id bigint, in_class text)
|
||||
RETURNS bigint
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
DECLARE
|
||||
vehicle_id BIGINT;
|
||||
BEGIN
|
||||
SELECT INTO vehicle_id id FROM vehicles WHERE "id" = in_actor_id;
|
||||
IF vehicle_id IS NULL THEN
|
||||
SELECT assign_actor_id(in_class) id INTO vehicle_id;
|
||||
INSERT INTO vehicles("id") VALUES(vehicle_id);
|
||||
END IF;
|
||||
RETURN vehicle_id;
|
||||
END
|
||||
$function$
|
||||
@@ -0,0 +1,17 @@
|
||||
-- get_vehicle_module_inventory_id(in_vehicle_module_id bigint, in_vehicle_module_inventory_type integer) -> bigint
|
||||
-- oid: 58365 kind: FUNCTION category: vehicle
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.get_vehicle_module_inventory_id(in_vehicle_module_id bigint, in_vehicle_module_inventory_type integer)
|
||||
RETURNS bigint
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
DECLARE
|
||||
inv_id BIGINT;
|
||||
BEGIN
|
||||
SELECT INTO inv_id inventory_id FROM vehicle_module_inventories vi JOIN inventories i ON (vi.inventory_id = i.id) WHERE i.vehicle_module_id = in_vehicle_module_id AND vi.vehicle_module_inventory_type = in_vehicle_module_inventory_type;
|
||||
IF inv_id IS NULL THEN
|
||||
INSERT INTO inventories("id", "vehicle_module_id") VALUES(DEFAULT, in_vehicle_module_id) RETURNING id INTO inv_id;
|
||||
INSERT INTO vehicle_module_inventories("inventory_id", "vehicle_module_inventory_type") VALUES(inv_id, in_vehicle_module_inventory_type);
|
||||
END IF;
|
||||
RETURN inv_id;
|
||||
END $function$
|
||||
@@ -0,0 +1,16 @@
|
||||
-- load_backup_vehicle(in_account_id bigint) -> TABLE(out_id bigint, out_class text, out_customization_id text)
|
||||
-- oid: 58439 kind: FUNCTION category: vehicle
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.load_backup_vehicle(in_account_id bigint)
|
||||
RETURNS TABLE(out_id bigint, out_class text, out_customization_id text)
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
BEGIN
|
||||
RETURN QUERY
|
||||
SELECT a.id, a.class, bv.customization_id
|
||||
FROM actors a
|
||||
JOIN backup_vehicles bv on a.id = bv.vehicle_id
|
||||
WHERE bv.account_id = in_account_id
|
||||
LIMIT 1;
|
||||
END
|
||||
$function$
|
||||
@@ -0,0 +1,18 @@
|
||||
-- load_recovered_vehicles(in_account_id bigint, in_restore_time_limit integer) -> TABLE(out_vehicle_id bigint, out_class text, out_name text, out_time_stored timestamp without time zone, out_chassis_durability real, out_customization_id text, out_migrated boolean)
|
||||
-- oid: 58461 kind: FUNCTION category: vehicle
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.load_recovered_vehicles(in_account_id bigint, in_restore_time_limit integer)
|
||||
RETURNS TABLE(out_vehicle_id bigint, out_class text, out_name text, out_time_stored timestamp without time zone, out_chassis_durability real, out_customization_id text, out_migrated boolean)
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
BEGIN
|
||||
RETURN QUERY
|
||||
SELECT vehicle_id, class, vehicle_name, time_stored AT TIME ZONE 'UTC', chassis_durability, customization_id, migrated
|
||||
FROM actors
|
||||
JOIN recovered_vehicles on id = vehicle_id
|
||||
WHERE account_id = in_account_id
|
||||
AND (migrated = TRUE OR time_stored > NOW() - in_restore_time_limit * INTERVAL '1 second')
|
||||
AND EXISTS (SELECT 1 FROM actor_state WHERE actor_state.actor_id = id AND actor_state.state = 'VehicleRecovery')
|
||||
ORDER BY time_stored DESC;
|
||||
END
|
||||
$function$
|
||||
@@ -0,0 +1,11 @@
|
||||
-- load_vehicle_modules(in_vehicle_id bigint) -> TABLE(module_id bigint, template_id text, stats jsonb)
|
||||
-- oid: 58467 kind: FUNCTION category: vehicle
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.load_vehicle_modules(in_vehicle_id bigint)
|
||||
RETURNS TABLE(module_id bigint, template_id text, stats jsonb)
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
begin
|
||||
return query SELECT vm.id, vm.template_id, vm.stats FROM vehicle_modules vm WHERE vehicle_id = in_vehicle_id ORDER BY id;
|
||||
end
|
||||
$function$
|
||||
@@ -0,0 +1,50 @@
|
||||
-- restore_backup_vehicle(in_account_id bigint, in_server_info dune.serverinfo, in_transform dune.transform) -> bigint
|
||||
-- oid: 58534 kind: FUNCTION category: vehicle
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.restore_backup_vehicle(in_account_id bigint, in_server_info dune.serverinfo, in_transform dune.transform)
|
||||
RETURNS bigint
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
DECLARE
|
||||
found_vehicle_id BIGINT;
|
||||
BEGIN
|
||||
-- Retrieve a backup vehicle for the provided account.
|
||||
SELECT vehicle_id INTO found_vehicle_id
|
||||
FROM backup_vehicles
|
||||
WHERE account_id = in_account_id
|
||||
LIMIT 1; -- In case more than one is stored.
|
||||
|
||||
IF NOT FOUND THEN
|
||||
RAISE EXCEPTION 'No backup vehicle found for account_id: %', in_account_id;
|
||||
END IF;
|
||||
|
||||
-- Only restore vehicle if the actor state is vehicle backup
|
||||
PERFORM 1 FROM actor_state WHERE actor_id = found_vehicle_id AND state = 'VehicleBackup';
|
||||
IF NOT FOUND THEN
|
||||
RAISE EXCEPTION 'Trying to restore vehicle % that does not belong to vehicle backup feature.', found_vehicle_id;
|
||||
END IF;
|
||||
|
||||
-- Update the actors record to restore the vehicle.
|
||||
UPDATE actors
|
||||
SET map = in_server_info.map,
|
||||
partition_id = in_server_info.partition_id,
|
||||
dimension_index = in_server_info.dimension_index,
|
||||
transform = in_transform
|
||||
WHERE id = found_vehicle_id;
|
||||
IF NOT FOUND THEN
|
||||
RAISE WARNING 'No actor record found with id % during restore.', found_vehicle_id;
|
||||
END IF;
|
||||
|
||||
-- Remove the restored vehicle from backup_vehicles.
|
||||
DELETE FROM backup_vehicles WHERE vehicle_id = found_vehicle_id;
|
||||
RAISE INFO 'Deleted backup record for vehicle %.', found_vehicle_id;
|
||||
|
||||
-- There is no need to keep the actor state in the table anymore since the vehicle backup was successful data wise
|
||||
DELETE FROM actor_state WHERE actor_id = found_vehicle_id;
|
||||
RAISE INFO 'Deleted actor state for vehicle %.', found_vehicle_id;
|
||||
|
||||
PERFORM verify_item_dup_backup_tool(in_account_id, found_vehicle_id, 'item_dup_on_restore_vbt');
|
||||
|
||||
RETURN found_vehicle_id;
|
||||
END;
|
||||
$function$
|
||||
@@ -0,0 +1,66 @@
|
||||
-- restore_recovered_vehicle(in_account_id bigint, in_vehicle_id bigint, in_server_info dune.serverinfo, in_transform dune.transform, in_restore_time_limit integer) -> void
|
||||
-- oid: 58535 kind: FUNCTION category: vehicle
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.restore_recovered_vehicle(in_account_id bigint, in_vehicle_id bigint, in_server_info dune.serverinfo, in_transform dune.transform, in_restore_time_limit integer)
|
||||
RETURNS void
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
DECLARE
|
||||
found_vehicle_id BIGINT;
|
||||
found_vehicle_name TEXT;
|
||||
found_player_id BIGINT;
|
||||
BEGIN
|
||||
-- Retrieve a recovered vehicle for the provided account.
|
||||
SELECT vehicle_id, vehicle_name INTO found_vehicle_id, found_vehicle_name
|
||||
FROM recovered_vehicles
|
||||
WHERE account_id = in_account_id AND vehicle_id = in_vehicle_id
|
||||
-- 60s leeway in favor of player in case they try to restore last second
|
||||
AND (migrated = TRUE OR time_stored > NOW() - (in_restore_time_limit + 60) * INTERVAL '1 second')
|
||||
LIMIT 1; -- In case more than one is stored.
|
||||
|
||||
IF NOT FOUND THEN
|
||||
RAISE EXCEPTION 'No recovered vehicle found for account_id: % and vehicle_id: %', in_account_id, in_vehicle_id;
|
||||
END IF;
|
||||
|
||||
-- Only restore vehicle if the actor state is VehicleRecovery
|
||||
PERFORM 1 FROM actor_state WHERE actor_id = found_vehicle_id AND state = 'VehicleRecovery';
|
||||
IF NOT FOUND THEN
|
||||
RAISE EXCEPTION 'Trying to restore vehicle % that does not belong to vehicle recovery feature.', found_vehicle_id;
|
||||
END IF;
|
||||
|
||||
-- Update the actors record to restore the vehicle.
|
||||
UPDATE actors
|
||||
SET map = in_server_info.map,
|
||||
partition_id = in_server_info.partition_id,
|
||||
dimension_index = in_server_info.dimension_index,
|
||||
transform = in_transform
|
||||
WHERE id = found_vehicle_id;
|
||||
IF NOT FOUND THEN
|
||||
RAISE WARNING 'No actor record found with id % during restore.', found_vehicle_id;
|
||||
END IF;
|
||||
|
||||
-- permissions use the player controllers id, so we need to get that from the account id
|
||||
SELECT player_controller_id INTO found_player_id FROM player_state WHERE account_id = in_account_id LIMIT 1;
|
||||
IF NOT FOUND THEN
|
||||
RAISE EXCEPTION 'No player_controller_id found for account: %', in_account_id;
|
||||
END IF;
|
||||
|
||||
-- restore default permissions
|
||||
INSERT INTO permission_actor("actor_id", "actor_name", "actor_type", "access_level", "is_child")
|
||||
VALUES(found_vehicle_id, found_vehicle_name, 2, 3, false);
|
||||
|
||||
INSERT INTO permission_actor_rank("permission_actor_id", "player_id", "rank")
|
||||
VALUES(found_vehicle_id, found_player_id, 1);
|
||||
|
||||
-- Remove the restored vehicle from recovered_vehicles.
|
||||
DELETE FROM recovered_vehicles WHERE vehicle_id = found_vehicle_id;
|
||||
RAISE INFO 'Deleted recovery record for vehicle %.', found_vehicle_id;
|
||||
|
||||
-- There is no need to keep the actor state in the table anymore since the vehicle recovery was successful data wise
|
||||
DELETE FROM actor_state WHERE actor_id = found_vehicle_id;
|
||||
RAISE INFO 'Deleted actor state for vehicle %.', found_vehicle_id;
|
||||
|
||||
--PERFORM verify_item_dup_backup_tool(in_account_id, found_vehicle_id, 'item_dup_on_restore_vbt');
|
||||
|
||||
END;
|
||||
$function$
|
||||
@@ -0,0 +1,37 @@
|
||||
-- save_vehicle_modules(in_add_list dune.vehiclemodule[], in_delete_list bigint[], in_stat_update dune.itemstatupdate[]) -> SETOF bigint
|
||||
-- oid: 58574 kind: FUNCTION category: vehicle
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.save_vehicle_modules(in_add_list dune.vehiclemodule[], in_delete_list bigint[], in_stat_update dune.itemstatupdate[])
|
||||
RETURNS SETOF bigint
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
DECLARE
|
||||
module VEHICLEMODULE;
|
||||
stat ItemStatUpdate;
|
||||
new_module_id BIGINT;
|
||||
currentstat RECORD;
|
||||
BEGIN
|
||||
--RAISE NOTICE 'Add vehicle modules';
|
||||
-- add vehicle modules
|
||||
FOREACH module IN ARRAY in_add_list LOOP
|
||||
INSERT INTO vehicle_modules(
|
||||
"vehicle_id", "template_id", "stats"
|
||||
) VALUES(
|
||||
(module).vehicle_id, (module).template_id, (module).stats
|
||||
) RETURNING id INTO new_module_id;
|
||||
RETURN NEXT new_module_id;
|
||||
END LOOP;
|
||||
|
||||
--RAISE NOTICE 'Delete vehicle modules';
|
||||
-- delete modules
|
||||
DELETE FROM vehicle_modules WHERE id = ANY(in_delete_list);
|
||||
|
||||
--RAISE NOTICE 'Add vehicle module stats';
|
||||
-- add vehicle module stats
|
||||
FOREACH stat IN ARRAY in_stat_update LOOP
|
||||
UPDATE vehicle_modules SET "stats" = vehicle_modules.stats || (stat).value WHERE "id" = (stat).item_id;
|
||||
END LOOP;
|
||||
|
||||
RETURN;
|
||||
END
|
||||
$function$
|
||||
@@ -0,0 +1,42 @@
|
||||
-- store_backup_vehicle(in_vehicle_id bigint, in_account_id bigint, in_customization_id text) -> void
|
||||
-- oid: 58598 kind: FUNCTION category: vehicle
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.store_backup_vehicle(in_vehicle_id bigint, in_account_id bigint, in_customization_id text)
|
||||
RETURNS void
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
BEGIN
|
||||
-- Lock the backup_vehicles table exclusively to prevent race conditions.
|
||||
LOCK TABLE backup_vehicles IN EXCLUSIVE MODE;
|
||||
|
||||
-- Check if the vehicle already belongs to an actor state
|
||||
PERFORM 1 FROM actor_state WHERE actor_id = in_vehicle_id;
|
||||
IF FOUND THEN
|
||||
RAISE EXCEPTION 'Trying to backup vehicle % that already has an actor state.', in_vehicle_id;
|
||||
END IF;
|
||||
|
||||
-- Check if the vehicle is already in backup_vehicles.
|
||||
PERFORM 1 FROM backup_vehicles WHERE vehicle_id = in_vehicle_id;
|
||||
IF FOUND THEN
|
||||
RAISE EXCEPTION 'Vehicle % is already stored as a backup.', in_vehicle_id;
|
||||
END IF;
|
||||
|
||||
-- Check if the vehicle exists in the actors table.
|
||||
PERFORM 1 FROM actors WHERE id = in_vehicle_id;
|
||||
IF NOT FOUND THEN
|
||||
RAISE EXCEPTION 'Vehicle % does not exist in actors.', in_vehicle_id;
|
||||
END IF;
|
||||
|
||||
-- Insert the vehicle into backup_vehicles.
|
||||
INSERT INTO backup_vehicles (account_id, vehicle_id, customization_id)
|
||||
VALUES (in_account_id, in_vehicle_id, in_customization_id);
|
||||
RAISE INFO 'Inserted vehicle % into backup_vehicles for account %.', in_vehicle_id, in_account_id;
|
||||
|
||||
-- Mark the actor as belonging to the vehicle backup tool
|
||||
INSERT INTO actor_state("actor_id", "state") VALUES(in_vehicle_id, 'VehicleBackup');
|
||||
RAISE INFO 'Inserted vehicle % into actor_state with VehicleBackup state', in_vehicle_id;
|
||||
|
||||
PERFORM verify_item_dup_backup_tool(in_account_id, in_vehicle_id, 'item_dup_on_store_vbt');
|
||||
|
||||
END;
|
||||
$function$
|
||||
@@ -0,0 +1,63 @@
|
||||
-- store_recovered_vehicle(in_vehicle_id bigint, in_chassis_durability real, in_customization_id text, in_is_migration boolean) -> void
|
||||
-- oid: 58599 kind: FUNCTION category: vehicle
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.store_recovered_vehicle(in_vehicle_id bigint, in_chassis_durability real, in_customization_id text, in_is_migration boolean DEFAULT false)
|
||||
RETURNS void
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
DECLARE
|
||||
owner_id BIGINT;
|
||||
player_id BIGINT;
|
||||
vehicle_class TEXT;
|
||||
vehicle_name TEXT;
|
||||
BEGIN
|
||||
-- Lock the recovered_vehicles table exclusively to prevent race conditions.
|
||||
LOCK TABLE recovered_vehicles IN EXCLUSIVE MODE;
|
||||
|
||||
-- Check if the vehicle already belongs to an actor state
|
||||
PERFORM 1 FROM actor_state WHERE actor_id = in_vehicle_id;
|
||||
IF FOUND THEN
|
||||
RAISE EXCEPTION 'Trying to store recovered vehicle % that already has an actor state.', in_vehicle_id;
|
||||
END IF;
|
||||
|
||||
-- Check if the vehicle is already in recovered_vehicles.
|
||||
PERFORM 1 FROM recovered_vehicles WHERE vehicle_id = in_vehicle_id;
|
||||
IF FOUND THEN
|
||||
RAISE EXCEPTION 'Vehicle % is already recovered.', in_vehicle_id;
|
||||
END IF;
|
||||
|
||||
-- Check if the vehicle exists in the actors table.
|
||||
SELECT class INTO vehicle_class
|
||||
FROM actors
|
||||
WHERE id = in_vehicle_id
|
||||
LIMIT 1;
|
||||
IF NOT FOUND THEN
|
||||
RAISE EXCEPTION 'Vehicle % does not exist in actors.', in_vehicle_id;
|
||||
END IF;
|
||||
|
||||
-- get the vehicles owner account id
|
||||
SELECT a.owner_account_id, r.player_id, p.actor_name INTO owner_id, player_id, vehicle_name
|
||||
FROM actors a
|
||||
INNER JOIN permission_actor_rank r ON r.player_id = a.id
|
||||
INNER JOIN permission_actor p ON p.actor_id = r.permission_actor_id
|
||||
WHERE r.permission_actor_id = in_vehicle_id
|
||||
AND r.rank = 1::smallint
|
||||
LIMIT 1;
|
||||
|
||||
IF NOT FOUND THEN
|
||||
RAISE EXCEPTION 'No account_id found for vehicle: %', in_vehicle_id;
|
||||
END IF;
|
||||
|
||||
-- Insert the vehicle into recovered_vehicles.
|
||||
INSERT INTO recovered_vehicles(account_id, vehicle_id, chassis_durability, vehicle_name, customization_id, migrated)
|
||||
VALUES (owner_id, in_vehicle_id, in_chassis_durability, vehicle_name, in_customization_id, in_is_migration);
|
||||
RAISE INFO 'Inserted vehicle % into recovered_vehicles for account %.', in_vehicle_id, owner_id;
|
||||
|
||||
-- Mark the actor as belonging to the vehicle recovery tool
|
||||
INSERT INTO actor_state("actor_id", "state") VALUES(in_vehicle_id, 'VehicleRecovery');
|
||||
RAISE INFO 'Inserted vehicle % into actor_state with VehicleRecovery state', in_vehicle_id;
|
||||
|
||||
PERFORM pg_notify('vehicle_recovery_notify_channel', FORMAT('stored#{"PlayerId":%s, "VehicleId":%s, "VehicleClass":"%s", "VehicleName":"%s", "VehicleCustomizationId":"%s", "TimeStored":"%s", "ChassisDurability":%s, "bIsMigrated":%s}', player_id, in_vehicle_id, vehicle_class, vehicle_name, in_customization_id, NOW() AT TIME ZONE 'UTC', in_chassis_durability, CASE WHEN in_is_migration THEN 'true' ELSE 'false' END) );
|
||||
|
||||
END;
|
||||
$function$
|
||||
@@ -0,0 +1,39 @@
|
||||
-- store_recovered_vehicles_wiped_before_spawn(in_vehicle_ids bigint[], in_delete_items boolean) -> void
|
||||
-- oid: 58600 kind: FUNCTION category: vehicle
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.store_recovered_vehicles_wiped_before_spawn(in_vehicle_ids bigint[], in_delete_items boolean DEFAULT true)
|
||||
RETURNS void
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
DECLARE
|
||||
to_store RECORD;
|
||||
BEGIN
|
||||
FOR to_store IN
|
||||
SELECT v.id AS vehicle_id, a.properties -> (regexp_replace("class", '^.*\.', '')) ->> 'm_CustomizationId' AS customization_id
|
||||
FROM actors a
|
||||
INNER JOIN vehicles v ON a.id = v.id
|
||||
INNER JOIN permission_actor p ON a.id = p.actor_id
|
||||
INNER JOIN permission_actor_rank r ON p.actor_id = r.permission_actor_id
|
||||
WHERE v.id = ANY(in_vehicle_ids)
|
||||
AND r.rank = 1::smallint
|
||||
AND NOT EXISTS
|
||||
(
|
||||
SELECT 1 FROM actor_state
|
||||
WHERE actor_state.actor_id = v.id
|
||||
AND actor_state.state IS DISTINCT FROM 'Default'
|
||||
)
|
||||
LOOP
|
||||
-- remove all items in all inventories of that vehicle
|
||||
if in_delete_items then
|
||||
PERFORM delete_items_from_actor(to_store.vehicle_id);
|
||||
end if;
|
||||
|
||||
-- note: storing hardcoded chassis durability because its not available from pure database :(
|
||||
-- this will only be shown incorrectly in UI though, the spawned vehicle will get the correct value
|
||||
PERFORM store_recovered_vehicle(to_store.vehicle_id, 0.25, to_store.customization_id);
|
||||
|
||||
-- remove permissions so the stored vehicles don't count towards the vehicle limit (the owner is preserved in the store function above)
|
||||
PERFORM permission_actor_destroy(to_store.vehicle_id);
|
||||
END LOOP;
|
||||
END
|
||||
$function$
|
||||
Reference in New Issue
Block a user