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,29 @@
|
||||
-- _character_transfer_allocate_id(kind dune._charactertransferentrykind, data jsonb) -> bigint
|
||||
-- oid: 58095 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune._character_transfer_allocate_id(kind dune._charactertransferentrykind, data jsonb)
|
||||
RETURNS bigint
|
||||
LANGUAGE sql
|
||||
IMMUTABLE
|
||||
AS $function$
|
||||
select case
|
||||
when kind = 'acc' then nextval('encrypted_accounts_id_seq')
|
||||
when kind = 'act' then nextval('actors_id_seq')
|
||||
when kind = 'inv' then nextval('inventories_id_seq')
|
||||
when kind = 'itm' then nextval('items_id_seq')
|
||||
when kind = 'fgl' then nextval('character_transfer_fgl_entities_entity_id_seq')
|
||||
when kind = 'bbp' then nextval('building_blueprints_id_seq')
|
||||
|
||||
when kind = 'VehicleModule' then nextval('vehicle_modules_id_seq')
|
||||
|
||||
when kind = 'Faction' then (select id from factions where "name" = data->>'name')
|
||||
when kind = 'Tutorial' then (select id from tutorials where "name" = data->>'name')
|
||||
when kind = 'Keystone' then (select id from specialization_keystones_map where "name" = data->>'name')
|
||||
|
||||
when kind = 'BaseBackup' then nextval('base_backups_id_seq')
|
||||
when kind = 'TaxInvoice' then nextval('tax_invoice_id_seq')
|
||||
|
||||
when kind = 'DungeonCompletion' then nextval('dungeon_completion_completion_id_seq')
|
||||
else null
|
||||
end;
|
||||
$function$
|
||||
@@ -0,0 +1,26 @@
|
||||
-- _character_transfer_create_data_table() -> void
|
||||
-- oid: 58096 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune._character_transfer_create_data_table()
|
||||
RETURNS void
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
begin
|
||||
if not exists (
|
||||
select 1 from pg_catalog.pg_tables
|
||||
where schemaname=(select nspname from pg_catalog.pg_namespace where oid=pg_my_temp_schema())
|
||||
and tablename = 'export_data'
|
||||
) then
|
||||
create temporary table if not exists pg_temp.export_data (
|
||||
"id" BigInt DEFAULT NULL,
|
||||
"transfer_id" BigSerial PRIMARY KEY NOT NULL,
|
||||
"kind" _CharacterTransferEntryKind NOT NULL,
|
||||
"data" JsonB NOT NULL
|
||||
) on commit drop;
|
||||
create index on pg_temp.export_data("id");
|
||||
create index on pg_temp.export_data("kind");
|
||||
end if;
|
||||
alter sequence pg_temp.export_data_transfer_id_seq restart with 1;
|
||||
truncate pg_temp.export_data;
|
||||
end
|
||||
$function$
|
||||
@@ -0,0 +1,10 @@
|
||||
-- _character_transfer_data_filter(id text, removed text[], VARIADIC refs dune._charactertransferdatafilterref[]) -> dune._charactertransferdatafilter
|
||||
-- oid: 58097 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune._character_transfer_data_filter(id text, removed text[], VARIADIC refs dune._charactertransferdatafilterref[] DEFAULT '{}'::dune._charactertransferdatafilterref[])
|
||||
RETURNS dune._charactertransferdatafilter
|
||||
LANGUAGE sql
|
||||
IMMUTABLE
|
||||
AS $function$
|
||||
select (id, removed, refs)::_CharacterTransferDataFilter;
|
||||
$function$
|
||||
@@ -0,0 +1,20 @@
|
||||
-- _character_transfer_data_table_load(entries jsonb) -> void
|
||||
-- oid: 58098 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune._character_transfer_data_table_load(entries jsonb)
|
||||
RETURNS void
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
begin
|
||||
with parsed as (
|
||||
select
|
||||
(entry->>'id')::BigInt as transfer_id,
|
||||
(entry->>'kind')::_CharacterTransferEntryKind as kind,
|
||||
(entry->'data') as data
|
||||
from jsonb_array_elements(entries) as entry
|
||||
)
|
||||
insert into pg_temp.export_data("id", "transfer_id", "kind", "data")
|
||||
select _character_transfer_allocate_id(kind, data) as id, transfer_id, kind, data
|
||||
from parsed;
|
||||
end
|
||||
$function$
|
||||
@@ -0,0 +1,11 @@
|
||||
-- _character_transfer_data_table_save() -> jsonb
|
||||
-- oid: 58099 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune._character_transfer_data_table_save()
|
||||
RETURNS jsonb
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
begin
|
||||
return (select jsonb_agg(jsonb_build_object('id', transfer_id, 'kind', kind, 'data', data)) from pg_temp.export_data);
|
||||
end
|
||||
$function$
|
||||
@@ -0,0 +1,109 @@
|
||||
-- _character_transfer_get_filter(kind dune._charactertransferentrykind) -> dune._charactertransferdatafilter
|
||||
-- oid: 58101 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune._character_transfer_get_filter(kind dune._charactertransferentrykind)
|
||||
RETURNS dune._charactertransferdatafilter
|
||||
LANGUAGE sql
|
||||
IMMUTABLE
|
||||
AS $function$
|
||||
select case
|
||||
when kind = 'acc' then _character_transfer_data_filter('id', '{user,funcom_id}')
|
||||
when kind = 'act' then _character_transfer_data_filter('id', '{}', ('owner_account_id', 'acc', false))
|
||||
when kind = 'inv' then _character_transfer_data_filter(
|
||||
'id',
|
||||
'{exchange_id,item_id}',
|
||||
('actor_id', 'act', false),
|
||||
('vehicle_module_id', 'VehicleModule', false)
|
||||
)
|
||||
when kind = 'itm' then _character_transfer_data_filter(
|
||||
'id', '{}',
|
||||
('inventory_id', 'inv', true)
|
||||
)
|
||||
when kind = 'fgl' then _character_transfer_data_filter(
|
||||
'entity_id', '{}',
|
||||
('actor_id', 'act', true)
|
||||
)
|
||||
when kind = 'bbp' then _character_transfer_data_filter(
|
||||
'id', '{}',
|
||||
('item_id', 'itm', true),
|
||||
('player_id', 'act', false)
|
||||
)
|
||||
|
||||
when kind = 'Faction' then _character_transfer_data_filter('id', '{}')
|
||||
when kind = 'Tutorial' then _character_transfer_data_filter('id', '{}')
|
||||
when kind = 'Keystone' then _character_transfer_data_filter('id', '{}')
|
||||
|
||||
when kind = 'Character' then _character_transfer_data_filter(
|
||||
null, '{character_name}',
|
||||
('account_id', 'acc', true),
|
||||
('player_pawn_id', 'act', true),
|
||||
('player_controller_id', 'act', true),
|
||||
('player_state_id', 'act', true)
|
||||
)
|
||||
when kind = 'RespawnLocation' then _character_transfer_data_filter(
|
||||
null, '{}',
|
||||
('account_id', 'acc', true)
|
||||
)
|
||||
when kind = 'PlayerMarker' then _character_transfer_data_filter(null, '{}', ('player_id', 'act', true))
|
||||
when kind = 'Marker' then _character_transfer_data_filter(null, '{}')
|
||||
when kind = 'DialogueMetNpc' then _character_transfer_data_filter(null, '{}', ('player_id', 'act', true))
|
||||
when kind = 'DialogueTakenNode' then _character_transfer_data_filter(null, '{}', ('player_id', 'act', true))
|
||||
|
||||
when kind = 'PlayerFaction' then _character_transfer_data_filter(
|
||||
null, '{}',
|
||||
('actor_id', 'act', true), ('faction_id', 'Faction', true)
|
||||
)
|
||||
when kind = 'PlayerFactionReputation' then _character_transfer_data_filter(
|
||||
null, '{}',
|
||||
('actor_id', 'act', true), ('faction_id', 'Faction', true)
|
||||
)
|
||||
when kind = 'ConsumedLore' then _character_transfer_data_filter(null, '{}', ('actor_id', 'act', true))
|
||||
when kind = 'PlayerTutorial' then _character_transfer_data_filter(null, '{}', ('player_id', 'act', true), ('tutorial_id', 'Tutorial', true))
|
||||
when kind = 'PurchasedKeystone' then _character_transfer_data_filter(null, '{}', ('player_id', 'act', true), ('keystone_id', 'Keystone', true))
|
||||
when kind = 'SpecializationTracks' then _character_transfer_data_filter(null, '{}', ('player_id', 'act', true))
|
||||
when kind = 'SpecializationRefund' then _character_transfer_data_filter(null, '{}', ('player_id', 'act', true))
|
||||
|
||||
when kind = 'BuildingFavorite' then _character_transfer_data_filter(null, '{}', ('account_id', 'acc', true))
|
||||
when kind = 'BuildingProgression' then _character_transfer_data_filter(null, '{}', ('account_id', 'acc', true))
|
||||
when kind = 'CommuninetPlayer' then _character_transfer_data_filter(null, '{}', ('account_id', 'acc', true))
|
||||
when kind = 'CommuninetPlayerChannel' then _character_transfer_data_filter(null, '{}', ('account_id', 'acc', true))
|
||||
when kind = 'JourneyStoryNode' then _character_transfer_data_filter(null, '{}', ('account_id', 'acc', true))
|
||||
when kind = 'MapArea' then _character_transfer_data_filter(null, '{}', ('account_id', 'acc', true))
|
||||
when kind = 'PlayerAccessCode' then _character_transfer_data_filter(null, '{}', ('account_id', 'acc', true))
|
||||
when kind = 'PlayerTag' then _character_transfer_data_filter(null, '{}', ('account_id', 'acc', true))
|
||||
|
||||
when kind = 'ActorInventory' then _character_transfer_data_filter(null, '{}', ('inventory_id', 'inv', true))
|
||||
when kind = 'Sinkchart' then _character_transfer_data_filter(null, '{}', ('item_id', 'itm', true))
|
||||
|
||||
when kind = 'BackupVehicle' then _character_transfer_data_filter(null, '{}', ('account_id', 'acc', true), ('vehicle_id', 'act', true))
|
||||
when kind = 'RecoveredVehicle' then _character_transfer_data_filter(null, '{}', ('account_id', 'acc', true), ('vehicle_id', 'act', true))
|
||||
when kind = 'Vehicle' then _character_transfer_data_filter(null, '{}', ('id', 'act', true))
|
||||
when kind = 'VehicleModule' then _character_transfer_data_filter('id', '{}', ('vehicle_id', 'act', true))
|
||||
when kind = 'VehicleModuleInventory' then _character_transfer_data_filter(null, '{}', ('inventory_id', 'inv', true))
|
||||
|
||||
when kind = 'ActorState' then _character_transfer_data_filter(null, '{}', ('actor_id', 'act', true))
|
||||
|
||||
when kind = 'PermissionActor' then _character_transfer_data_filter(null, '{}', ('actor_id', 'act', true))
|
||||
when kind = 'PermissionActorRank' then _character_transfer_data_filter(null, '{}', ('permission_actor_id', 'act', true), ('player_id', 'act', true))
|
||||
|
||||
when kind = 'BuildingBlueprintInstance' then _character_transfer_data_filter(null, '{}', ('building_blueprint_id', 'bbp', true))
|
||||
when kind = 'BuildingBlueprintPlaceable' then _character_transfer_data_filter(null, '{}', ('building_blueprint_id', 'bbp', true))
|
||||
when kind = 'BuildingBlueprintPentashield' then _character_transfer_data_filter(null, '{}', ('building_blueprint_id', 'bbp', true))
|
||||
|
||||
when kind = 'Building' then _character_transfer_data_filter(null, '{}', ('id', 'act', true))
|
||||
when kind = 'BuildingInstance' then _character_transfer_data_filter(null, '{}', ('building_id', 'act', true), ('owner_entity_id', 'fgl', false))
|
||||
when kind = 'Placeable' then _character_transfer_data_filter(null, '{}', ('id', 'act', true), ('owner_entity_id', 'fgl', false))
|
||||
when kind = 'BaseBackup' then _character_transfer_data_filter('id', '{}', ('player_id', 'act', true))
|
||||
when kind = 'BaseBackupLinkedActor' then _character_transfer_data_filter(null, '{}', ('id', 'BaseBackup', true), ('actor_id', 'act', true))
|
||||
when kind = 'LandclaimSegment' then _character_transfer_data_filter(null, '{}', ('totem_id', 'act', true))
|
||||
when kind = 'TaxInvoice' then _character_transfer_data_filter('id', '{}', ('totem_id', 'act', true))
|
||||
|
||||
when kind = 'PlayerVirtualCurrencyBalance' then _character_transfer_data_filter(null, '{}', ('player_controller_id', 'act', true))
|
||||
|
||||
when kind = 'DungeonCompletion' then _character_transfer_data_filter('completion_id', '{}')
|
||||
when kind = 'DungeonCompletionPlayer' then _character_transfer_data_filter(null, '{}', ('player_id', 'act', true), ('completion_id', 'DungeonCompletion', true))
|
||||
when kind = 'Totem' then _character_transfer_data_filter(null, '{}', ('id', 'act', true))
|
||||
|
||||
when kind = 'LandsraadHouseRewards' then _character_transfer_data_filter(null, '{}', ('player_id', 'act', true))
|
||||
end;
|
||||
$function$
|
||||
@@ -0,0 +1,11 @@
|
||||
-- _character_transfer_get_patches_checksum() -> text
|
||||
-- oid: 58102 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune._character_transfer_get_patches_checksum()
|
||||
RETURNS text
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
begin
|
||||
return (SELECT md5(coalesce(string_agg("name", ',' ORDER BY "name"), '')) FROM applied_patches);
|
||||
end
|
||||
$function$
|
||||
@@ -0,0 +1,39 @@
|
||||
-- _character_transfer_pre_export_validation(in_fls_id text) -> TABLE(out_acc_id bigint, out_funcom_id text, out_player_controller_id bigint, out_player_pawn_id bigint)
|
||||
-- oid: 58103 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune._character_transfer_pre_export_validation(in_fls_id text)
|
||||
RETURNS TABLE(out_acc_id bigint, out_funcom_id text, out_player_controller_id bigint, out_player_pawn_id bigint)
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
DECLARE
|
||||
v_acc_id BigInt;
|
||||
v_funcom_id Text;
|
||||
v_player_controller_id BigInt;
|
||||
v_player_pawn_id BigInt;
|
||||
BEGIN
|
||||
if not (select is_player_offline(in_fls_id)) then
|
||||
raise exception 'sbRF3$ - player_online: Player % must be Offline', in_fls_id;
|
||||
end if;
|
||||
|
||||
v_acc_id := (select id from accounts where "user" = in_fls_id);
|
||||
IF v_acc_id is null THEN
|
||||
RAISE EXCEPTION 'sbFV2$ - unknown_fls_id: FLS ID % not found', in_fls_id;
|
||||
END IF;
|
||||
|
||||
v_funcom_id := (select funcom_id from accounts where "user" = in_fls_id);
|
||||
IF v_funcom_id is null THEN
|
||||
RAISE EXCEPTION 'sb9X3$ - missing_funcom_id: Player % does not have a funcomId', in_fls_id;
|
||||
END IF;
|
||||
|
||||
select into v_player_controller_id, v_player_pawn_id
|
||||
player_controller_id, player_pawn_id from player_state where account_id=v_acc_id;
|
||||
if v_player_controller_id is null then
|
||||
raise exception 'sbH84$ - missing_controller: Player % does not have a controller', in_fls_id;
|
||||
end if;
|
||||
if v_player_pawn_id is null then
|
||||
raise exception 'sbHF3$ - missing_character: Player % does not have a character', in_fls_id;
|
||||
end if;
|
||||
|
||||
return query select v_acc_id, v_funcom_id, v_player_controller_id, v_player_pawn_id;
|
||||
END;
|
||||
$function$
|
||||
@@ -0,0 +1,22 @@
|
||||
-- _character_transfer_property_not_exported_is_expected(path text) -> boolean
|
||||
-- oid: 58104 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune._character_transfer_property_not_exported_is_expected(path text)
|
||||
RETURNS boolean
|
||||
LANGUAGE sql
|
||||
IMMUTABLE
|
||||
AS $function$
|
||||
select (path = ANY(ARRAY[
|
||||
'.properties.BP_DunePlayerCharacter_C.m_CurrentVehicleId',
|
||||
'.properties.WeaponActorComponent.m_FavoriteWeaponItemDatabaseId',
|
||||
'.properties.ContractsCoordinatorComponent.m_TrackedContractItemUid',
|
||||
'.components.FItemCraftingComponent.*.RequestsQueue.*.InstigatorActorId',
|
||||
'.stats.FSinkchartsStats.*.CreatorPlayerId',
|
||||
'.components.FItemCraftingComponent.*.RequestsQueue.*.IngredientAllocations.*.ItemAllocNodes.*.AllocatedItems.*.ItemUniqueId', -- TODO [DA-4712]: Remove once this item loss is fixed
|
||||
'.stats.FBuildingBlueprintItemStats.*.PlayerBlueprintId', -- TODO [DA-4721]: Remove once this item loss is fixed
|
||||
'.properties.BP_TransportOrnithopter_CHOAM_C.m_HarnessedVehicleId',
|
||||
'.stats.FReferenceItemStats.*.ReferenceDatabaseId', -- These often point to items that no longer exist
|
||||
'.components.FTotemLandclaimComponent.*.m_PendingStakingUnitsEntityIds.*', -- Staking units are not transferred with the base backup. This is missing a cleanup
|
||||
'.components.FTotemLandclaimComponent.*.m_PendingVerticalStakingUnitsEntityIds.*' -- Staking units are not transferred with the base backup. This is missing a cleanup
|
||||
]::text[]));
|
||||
$function$
|
||||
@@ -0,0 +1,43 @@
|
||||
-- _character_transfer_replace_local_id_with_transfer_id(data text, path text) -> text
|
||||
-- oid: 58105 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune._character_transfer_replace_local_id_with_transfer_id(data text, path text)
|
||||
RETURNS text
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
declare
|
||||
v_kind _CharacterTransferEntryKind;
|
||||
v_raw_kind Text;
|
||||
v_id BigInt;
|
||||
v_transfer_id BigInt;
|
||||
begin
|
||||
v_raw_kind = substring(data from 3 for 3);
|
||||
begin
|
||||
v_kind := v_raw_kind::_CharacterTransferEntryKind;
|
||||
exception
|
||||
when invalid_text_representation then
|
||||
raise exception 'sbPH2$ - Invalid transfer id in data "%" at "%", unknown kind: %', data, path, v_raw_kind;
|
||||
end;
|
||||
|
||||
v_id := (substring(data from 7))::BigInt;
|
||||
if v_id = 0 then
|
||||
return format('!!%s@0', v_kind::text);
|
||||
end if;
|
||||
|
||||
if v_id < 0 and v_id >= -2147483648 then
|
||||
v_id := v_id + 4294967296;
|
||||
end if;
|
||||
|
||||
|
||||
v_transfer_id := (select transfer_id from pg_temp.export_data where id=v_id and kind=v_kind);
|
||||
if v_transfer_id is null then
|
||||
if _character_transfer_property_not_exported_is_expected(path) then
|
||||
return format('!!%s@0', v_kind::text);
|
||||
else
|
||||
raise exception 'sbQ73$ - Id % by % was not exported', data, path;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
return format('!!%s@%s', v_kind::text, v_transfer_id::text);
|
||||
end
|
||||
$function$
|
||||
@@ -0,0 +1,24 @@
|
||||
-- _character_transfer_replace_local_id_with_transfer_id_in_json(data jsonb, path text) -> jsonb
|
||||
-- oid: 58106 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune._character_transfer_replace_local_id_with_transfer_id_in_json(data jsonb, path text)
|
||||
RETURNS jsonb
|
||||
LANGUAGE sql
|
||||
AS $function$
|
||||
select case
|
||||
when data is json array then
|
||||
(select coalesce(jsonb_agg(_character_transfer_replace_local_id_with_transfer_id_in_json(
|
||||
element, path || '.*'
|
||||
)), '[]'::jsonb) from jsonb_array_elements(data) as element)
|
||||
when data is json object then
|
||||
(select coalesce(jsonb_object_agg(key, _character_transfer_replace_local_id_with_transfer_id_in_json(
|
||||
value, path || '.' || key
|
||||
)), '{}'::jsonb) from jsonb_each(data))
|
||||
when data is json scalar and jsonb_typeof(data) = 'string' and (data #>> '{}') like '!!___#%' then
|
||||
(select to_jsonb(_character_transfer_replace_local_id_with_transfer_id(
|
||||
data #>> '{}', path
|
||||
)))
|
||||
else
|
||||
data
|
||||
end;
|
||||
$function$
|
||||
@@ -0,0 +1,31 @@
|
||||
-- _character_transfer_replace_transfer_id_with_local_id(data text, path text) -> text
|
||||
-- oid: 58107 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune._character_transfer_replace_transfer_id_with_local_id(data text, path text)
|
||||
RETURNS text
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
declare
|
||||
v_kind _CharacterTransferEntryKind;
|
||||
v_id BigInt;
|
||||
v_transfer_id BigInt;
|
||||
begin
|
||||
if substring(data from 6 for 1) != '@' then
|
||||
raise exception 'sbFM3$ - Invalid transfer id % at %: expected @ separator', data, path;
|
||||
end if;
|
||||
|
||||
v_kind := substring(data from 3 for 3)::_CharacterTransferEntryKind;
|
||||
|
||||
v_transfer_id := (substring(data from 7))::BigInt;
|
||||
if v_transfer_id = 0 then
|
||||
return format('!!%s#0', v_kind::text);
|
||||
end if;
|
||||
|
||||
v_id := (select id from pg_temp.export_data where transfer_id=v_transfer_id and kind=v_kind);
|
||||
if v_id is null then
|
||||
raise exception 'sbQ64$ - Transfer id % at % was not imported', data, path;
|
||||
end if;
|
||||
|
||||
return format('!!%s#%s', v_kind::text, v_id::text);
|
||||
end
|
||||
$function$
|
||||
@@ -0,0 +1,47 @@
|
||||
-- _character_transfer_replace_transfer_id_with_local_id_in_json(data jsonb, path text) -> jsonb
|
||||
-- oid: 58108 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune._character_transfer_replace_transfer_id_with_local_id_in_json(data jsonb, path text)
|
||||
RETURNS jsonb
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
declare
|
||||
v_id_str Text;
|
||||
begin
|
||||
if data is json array then
|
||||
return (
|
||||
select coalesce(jsonb_agg(_character_transfer_replace_transfer_id_with_local_id_in_json(
|
||||
element, path || '.*'
|
||||
)), '[]'::jsonb) from jsonb_array_elements(data) as element
|
||||
);
|
||||
end if;
|
||||
|
||||
if data is json object then
|
||||
return (
|
||||
select coalesce(jsonb_object_agg(key, _character_transfer_replace_transfer_id_with_local_id_in_json(
|
||||
value, path || '.' || key
|
||||
)), '{}'::jsonb) from jsonb_each(data)
|
||||
);
|
||||
end if;
|
||||
|
||||
if data is json scalar then
|
||||
if jsonb_typeof(data) = 'string' then
|
||||
v_id_str := (data #>> '{}');
|
||||
|
||||
if v_id_str like '!!___#%' then
|
||||
raise exception 'sbJ34$ - Non-transfer id % is found at %', v_id_str, path;
|
||||
end if;
|
||||
|
||||
if v_id_str like '!!___@%' then
|
||||
return (select to_jsonb(_character_transfer_replace_transfer_id_with_local_id(v_id_str, path)));
|
||||
end if;
|
||||
|
||||
if v_id_str = '!!@0' then
|
||||
raise exception 'sb5G3$ - Transfer id missing kind marker at %: %', path, v_id_str;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
return data;
|
||||
end
|
||||
$function$
|
||||
@@ -0,0 +1,40 @@
|
||||
-- _character_transfer_top_level_export(in_kind dune._charactertransferentrykind, data jsonb) -> jsonb
|
||||
-- oid: 58110 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune._character_transfer_top_level_export(in_kind dune._charactertransferentrykind, data jsonb)
|
||||
RETURNS jsonb
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
declare
|
||||
v_id BigInt;
|
||||
v_transfer_id BigInt;
|
||||
v_ref _CharacterTransferDataFilterRef;
|
||||
v_filter _CharacterTransferDataFilter;
|
||||
begin
|
||||
v_filter := _character_transfer_get_filter(in_kind);
|
||||
data := data - (v_filter).removed;
|
||||
if (v_filter).id is not null then
|
||||
data := data - (v_filter).id;
|
||||
end if;
|
||||
foreach v_ref in array (v_filter).refs loop
|
||||
v_id := (data->>((v_ref).key))::BigInt;
|
||||
|
||||
if v_id is null then
|
||||
if (v_ref).required then
|
||||
raise exception 'sbP23$ - Required reference % not found in %', v_ref, data;
|
||||
else
|
||||
continue;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
v_transfer_id := (select transfer_id from pg_temp.export_data where kind=(v_ref).kind and id=v_id);
|
||||
if v_transfer_id is null then
|
||||
raise exception 'sbJG2$ - Id % in % not mapped into transfer id of kind %. Id exists as kind: %',
|
||||
v_id, data, (v_ref).kind, (select kind from pg_temp.export_data where id=v_id);
|
||||
end if;
|
||||
|
||||
data := jsonb_set(data, array[(v_ref).key], to_jsonb(v_transfer_id));
|
||||
end loop;
|
||||
return data;
|
||||
end
|
||||
$function$
|
||||
@@ -0,0 +1,44 @@
|
||||
-- _character_transfer_top_level_import(in_kind dune._charactertransferentrykind, data jsonb, in_id bigint) -> jsonb
|
||||
-- oid: 58111 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune._character_transfer_top_level_import(in_kind dune._charactertransferentrykind, data jsonb, in_id bigint)
|
||||
RETURNS jsonb
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
declare
|
||||
v_ref_transfer_id BigInt;
|
||||
v_ref_id BigInt;
|
||||
v_ref _CharacterTransferDataFilterRef;
|
||||
v_filter _CharacterTransferDataFilter;
|
||||
begin
|
||||
v_filter := _character_transfer_get_filter(in_kind);
|
||||
|
||||
if (v_filter).id is null then
|
||||
if in_id is not null then
|
||||
raise exception 'sbGM2$ - Transfer logic error: not-null in_id for secondary kind: %, data: %', in_kind, data;
|
||||
end if;
|
||||
else
|
||||
if in_id is null then
|
||||
raise exception 'sb8V2$ - Transfer logic error: null in_id for primary kind: %, data: %', in_kind, data;
|
||||
end if;
|
||||
data := data || jsonb_build_object((v_filter).id, in_id);
|
||||
end if;
|
||||
|
||||
foreach v_ref in array (v_filter).refs loop
|
||||
v_ref_transfer_id := (data->>((v_ref).key))::BigInt;
|
||||
if v_ref_transfer_id is null then
|
||||
if (v_ref).required then
|
||||
raise exception 'sb2C2$ - Missing reference % in import of kind %: %', (v_ref).key, in_kind, data;
|
||||
else
|
||||
continue;
|
||||
end if;
|
||||
end if;
|
||||
v_ref_id := (select to_jsonb(id) from pg_temp.export_data where kind=(v_ref).kind and transfer_id=v_ref_transfer_id);
|
||||
if v_ref_id is null then
|
||||
raise exception 'sb3W3$ - Unknown reference %s with transfer id % in import for kind %, reference id %: %', (v_ref).key, v_ref_transfer_id, in_kind, v_ref_id, data;
|
||||
end if;
|
||||
data := jsonb_set(data, array[(v_ref).key], to_jsonb(v_ref_id));
|
||||
end loop;
|
||||
return data;
|
||||
end
|
||||
$function$
|
||||
@@ -0,0 +1,9 @@
|
||||
-- can_takeover_account(in_user_id text) -> boolean
|
||||
-- oid: 58156 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.can_takeover_account(in_user_id text)
|
||||
RETURNS boolean
|
||||
LANGUAGE sql
|
||||
AS $function$
|
||||
select takeoverable from accounts WHERE "user" = in_user_id;
|
||||
$function$
|
||||
@@ -0,0 +1,21 @@
|
||||
-- character_migration_export(in_fls_id text) -> jsonb
|
||||
-- oid: 58158 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.character_migration_export(in_fls_id text)
|
||||
RETURNS jsonb
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
DECLARE
|
||||
v_player_controller_id BigInt;
|
||||
BEGIN
|
||||
select out_player_controller_id
|
||||
into v_player_controller_id
|
||||
from _character_transfer_pre_export_validation(in_fls_id);
|
||||
|
||||
perform _character_transfer_store_in_world_owned_vehicles_into_recovery(v_player_controller_id);
|
||||
perform base_backup_save_all_totems_from_player_owner(v_player_controller_id);
|
||||
-- Add any other migration-specific actions here before the export call
|
||||
|
||||
return character_transfer_export(in_fls_id);
|
||||
END;
|
||||
$function$
|
||||
@@ -0,0 +1,12 @@
|
||||
-- character_migration_import(in_data jsonb, in_fls_id text, in_character_name text) -> bigint
|
||||
-- oid: 58159 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.character_migration_import(in_data jsonb, in_fls_id text, in_character_name text)
|
||||
RETURNS bigint
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
BEGIN
|
||||
-- Add any migration-specific actions here before the import call
|
||||
RETURN character_transfer_import(in_data, in_fls_id, in_character_name);
|
||||
END
|
||||
$function$
|
||||
@@ -0,0 +1,304 @@
|
||||
-- character_transfer_export(in_fls_id text) -> jsonb
|
||||
-- oid: 58160 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.character_transfer_export(in_fls_id text)
|
||||
RETURNS jsonb
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
DECLARE
|
||||
v_acc_id BigInt;
|
||||
v_funcom_id Text;
|
||||
v_player_controller_id BigInt;
|
||||
v_player_pawn_id BigInt;
|
||||
v_vehicle_ids BigInt[];
|
||||
BEGIN
|
||||
select out_acc_id, out_funcom_id, out_player_controller_id, out_player_pawn_id
|
||||
into v_acc_id, v_funcom_id, v_player_controller_id, v_player_pawn_id
|
||||
from _character_transfer_pre_export_validation(in_fls_id);
|
||||
|
||||
perform _character_transfer_create_data_table();
|
||||
|
||||
-- accounts
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select id, 'acc', _character_transfer_top_level_export('acc', to_jsonb(accounts))
|
||||
from accounts where accounts.id=v_acc_id;
|
||||
|
||||
-- Vehicle and player actors
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select id, 'act', _character_transfer_top_level_export('act', to_jsonb(actors) - 'partition_id' #- '{properties,LandsraadCharacterComponent,m_NextContractAbandonUniverseTimeLimit}')
|
||||
from actors where id IN (
|
||||
-- player actors
|
||||
select unnest(array[player_controller_id, player_state_id, player_pawn_id]) as id
|
||||
from player_state where account_id=v_acc_id
|
||||
union
|
||||
-- backup vehicles
|
||||
select vehicle_id as id from backup_vehicles where account_id=v_acc_id
|
||||
union
|
||||
-- recovered vehicles
|
||||
select vehicle_id as id from recovered_vehicles where account_id=v_acc_id
|
||||
union
|
||||
-- base backup actors
|
||||
select actor_id as id from base_backup_linked_actors where id IN (
|
||||
select id from base_backups where player_id=v_player_controller_id
|
||||
)
|
||||
);
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select entity_id, 'fgl', _character_transfer_top_level_export(
|
||||
'fgl', to_jsonb(fgl_entities) || to_jsonb(actor_fgl_entities)
|
||||
) from actor_fgl_entities join fgl_entities using (entity_id) where actor_id IN (
|
||||
select id from pg_temp.export_data where kind='act'
|
||||
);
|
||||
|
||||
|
||||
-- Actor state entries tied to actors we export
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select actor_id, 'ActorState', _character_transfer_top_level_export('ActorState', to_jsonb(actor_state))
|
||||
from actor_state where
|
||||
actor_id IN (select id from pg_temp.export_data where kind = 'act');
|
||||
|
||||
|
||||
-- Permission data for the transferred actors
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select actor_id, 'PermissionActor', _character_transfer_top_level_export('PermissionActor', to_jsonb(permission_actor))
|
||||
from permission_actor where actor_id IN (select id from pg_temp.export_data where kind = 'act');
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select permission_actor_id, 'PermissionActorRank', _character_transfer_top_level_export('PermissionActorRank', to_jsonb(permission_actor_rank))
|
||||
from permission_actor_rank where
|
||||
permission_actor_id IN (select id from pg_temp.export_data where kind = 'act')
|
||||
and player_id IN (select id from pg_temp.export_data where kind = 'act');
|
||||
|
||||
-- vehicles and vehicle modules
|
||||
|
||||
insert into pg_temp.export_data("kind", "data")
|
||||
select 'Vehicle', _character_transfer_top_level_export('Vehicle', to_jsonb(vehicles))
|
||||
-- vehicle ids are aliases for actor ids
|
||||
from vehicles where id IN (select id from pg_temp.export_data where kind = 'act');
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select id, 'VehicleModule', _character_transfer_top_level_export('VehicleModule', to_jsonb(vehicle_modules))
|
||||
-- vehicle ids are aliases for actor ids
|
||||
from vehicle_modules where vehicle_id IN (select id from pg_temp.export_data where kind = 'act');
|
||||
|
||||
insert into pg_temp.export_data("kind", "data")
|
||||
select 'BackupVehicle', _character_transfer_top_level_export('BackupVehicle', to_jsonb(backup_vehicles))
|
||||
from backup_vehicles where account_id=v_acc_id;
|
||||
|
||||
insert into pg_temp.export_data("kind", "data")
|
||||
select 'RecoveredVehicle', _character_transfer_top_level_export('RecoveredVehicle', to_jsonb(recovered_vehicles))
|
||||
from recovered_vehicles where account_id=v_acc_id;
|
||||
|
||||
-- inventories and items
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select id, 'inv', _character_transfer_top_level_export('inv', to_jsonb(inventories))
|
||||
from inventories where
|
||||
actor_id IN (select id from pg_temp.export_data where kind = 'act')
|
||||
or vehicle_module_id IN (select id from pg_temp.export_data where kind = 'VehicleModule');
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select id, 'itm', _character_transfer_top_level_export('itm', to_jsonb(items))
|
||||
from items where inventory_id IN (select id from pg_temp.export_data where kind = 'inv');
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'ActorInventory', _character_transfer_top_level_export('ActorInventory', to_jsonb(actor_inventories))
|
||||
from actor_inventories where inventory_id IN (select id from pg_temp.export_data where kind = 'inv');
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'VehicleModuleInventory',
|
||||
_character_transfer_top_level_export('VehicleModuleInventory', to_jsonb(vehicle_module_inventories))
|
||||
from vehicle_module_inventories where inventory_id IN (select id from pg_temp.export_data where kind = 'inv');
|
||||
|
||||
-- Base backups (related actors are already added in the actors section)
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'Building', _character_transfer_top_level_export('Building', to_jsonb(buildings))
|
||||
from buildings where id in (select id from pg_temp.export_data where kind = 'act');
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'BuildingInstance', _character_transfer_top_level_export('BuildingInstance', to_jsonb(building_instances))
|
||||
from building_instances where building_id in (select id from pg_temp.export_data where kind = 'act');
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'Placeable', _character_transfer_top_level_export('Placeable', to_jsonb(placeables))
|
||||
from placeables where id in (select id from pg_temp.export_data where kind = 'act');
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'Totem', _character_transfer_top_level_export('Totem', to_jsonb(totems))
|
||||
from totems where id in (select id from pg_temp.export_data where kind = 'act');
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select id, 'BaseBackup', _character_transfer_top_level_export('BaseBackup', to_jsonb(base_backups))
|
||||
from base_backups where player_id=v_player_controller_id;
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select id, 'BaseBackupLinkedActor', _character_transfer_top_level_export('BaseBackupLinkedActor', to_jsonb(base_backup_linked_actors))
|
||||
from base_backup_linked_actors where id IN (
|
||||
select id from pg_temp.export_data where kind='BaseBackup'
|
||||
);
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'LandclaimSegment', _character_transfer_top_level_export('LandclaimSegment', to_jsonb(landclaim_segments))
|
||||
from landclaim_segments where totem_id IN (
|
||||
select id from pg_temp.export_data where kind='act'
|
||||
);
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select id, 'TaxInvoice', _character_transfer_top_level_export('TaxInvoice', to_jsonb(tax_invoice))
|
||||
from tax_invoice where totem_id IN (
|
||||
select id from pg_temp.export_data where kind='act'
|
||||
);
|
||||
|
||||
-- Other stuff
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select id, 'Faction', _character_transfer_top_level_export('Faction', to_jsonb(factions))
|
||||
from factions;
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select id, 'Tutorial', _character_transfer_top_level_export('Tutorial', to_jsonb(tutorials))
|
||||
from tutorials where id IN (select distinct tutorial_id from tutorial_per_player where player_id=v_player_controller_id);
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select id, 'Keystone', _character_transfer_top_level_export('Keystone', to_jsonb(specialization_keystones_map))
|
||||
from specialization_keystones_map where id IN (select distinct keystone_id from purchased_specialization_keystones where player_id=v_player_controller_id);
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'RespawnLocation',
|
||||
_character_transfer_top_level_export('RespawnLocation', to_jsonb(player_respawn_locations))
|
||||
|| jsonb_build_object('id', gen_random_uuid())
|
||||
-- TODO: add default to id and just delete it by filter
|
||||
from player_respawn_locations
|
||||
where account_id=v_acc_id and "group" = ANY('{PlayerStart,Checkpoint,CheckpointSafe}');
|
||||
|
||||
insert into pg_temp.export_data("kind", "data")
|
||||
select 'Character', _character_transfer_top_level_export('Character', to_jsonb(player_state) - 'last_avatar_activity' - 'reconnect_grace_period_end' - 'previous_server_partition_id')
|
||||
from player_state where player_state.account_id=v_acc_id;
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'PlayerMarker', _character_transfer_top_level_export('PlayerMarker', to_jsonb(player_markers))
|
||||
from player_markers join markers using (marker_hash_id, dimension_index, map_name_id) join map_names using (map_name_id)
|
||||
where dimension_index=-1 and player_id=v_player_controller_id and map_name <> 'DeepDesert'
|
||||
and ((marker).payload_type <> 'EMarkerPayloadType::Default' or ((marker).payload_type = 'EMarkerPayloadType::Default' and (marker).marker_type like 'FlourSand%'));
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'Marker', _character_transfer_top_level_export('Marker', to_jsonb(markers))
|
||||
from markers join player_markers using (marker_hash_id, dimension_index, map_name_id) join map_names using (map_name_id)
|
||||
where dimension_index=-1 and player_id=v_player_controller_id and map_name <> 'DeepDesert'
|
||||
and ((marker).payload_type <> 'EMarkerPayloadType::Default' or ((marker).payload_type = 'EMarkerPayloadType::Default' and (marker).marker_type like 'FlourSand%'));
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'DialogueMetNpc', _character_transfer_top_level_export('DialogueMetNpc', to_jsonb(dialogue_met_npcs))
|
||||
from dialogue_met_npcs where player_id=v_player_controller_id;
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'DialogueTakenNode', _character_transfer_top_level_export('DialogueTakenNode', to_jsonb(dialogue_taken_nodes))
|
||||
from dialogue_taken_nodes where player_id=v_player_controller_id;
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'PlayerFaction', _character_transfer_top_level_export('PlayerFaction', to_jsonb(player_faction))
|
||||
from player_faction where actor_id=v_player_controller_id;
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'PlayerFactionReputation', _character_transfer_top_level_export('PlayerFactionReputation', to_jsonb(player_faction_reputation))
|
||||
from player_faction_reputation where actor_id=v_player_controller_id;
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'ConsumedLore', _character_transfer_top_level_export('ConsumedLore', to_jsonb(consumed_per_player_lore))
|
||||
from consumed_per_player_lore where actor_id=v_player_controller_id;
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'PlayerTutorial', _character_transfer_top_level_export('PlayerTutorial', to_jsonb(tutorial_per_player))
|
||||
from tutorial_per_player where player_id=v_player_controller_id;
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'PurchasedKeystone', _character_transfer_top_level_export('PurchasedKeystone', to_jsonb(purchased_specialization_keystones))
|
||||
from purchased_specialization_keystones where player_id=v_player_controller_id;
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'SpecializationTracks', _character_transfer_top_level_export('SpecializationTracks', to_jsonb(specialization_tracks))
|
||||
from specialization_tracks where player_id=v_player_controller_id;
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'SpecializationRefund', _character_transfer_top_level_export('SpecializationRefund', to_jsonb(specialization_refund_id))
|
||||
from specialization_refund_id where player_id=v_player_controller_id;
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'BuildingFavorite', _character_transfer_top_level_export('BuildingFavorite', to_jsonb(building_favorites))
|
||||
from building_favorites where account_id=v_acc_id;
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'BuildingProgression', _character_transfer_top_level_export('BuildingProgression', to_jsonb(building_progression))
|
||||
from building_progression where account_id=v_acc_id;
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'CommuninetPlayer', _character_transfer_top_level_export('CommuninetPlayer', to_jsonb(communinet_player))
|
||||
from communinet_player where account_id=v_acc_id;
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'CommuninetPlayerChannel', _character_transfer_top_level_export('CommuninetPlayerChannel', to_jsonb(communinet_player_channels))
|
||||
from communinet_player_channels where account_id=v_acc_id;
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'JourneyStoryNode', _character_transfer_top_level_export('JourneyStoryNode', to_jsonb(journey_story_node))
|
||||
from journey_story_node where account_id=v_acc_id;
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'MapArea', _character_transfer_top_level_export('MapArea', to_jsonb(map_areas))
|
||||
from map_areas where account_id=v_acc_id and map_name <> 'DeepDesert';
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'PlayerAccessCode', _character_transfer_top_level_export('PlayerAccessCode', to_jsonb(player_access_codes))
|
||||
from player_access_codes where account_id=v_acc_id;
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'PlayerTag', _character_transfer_top_level_export('PlayerTag', to_jsonb(player_tags))
|
||||
from player_tags where account_id=v_acc_id;
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'Sinkchart', _character_transfer_top_level_export('Sinkchart', to_jsonb(sinkcharts))
|
||||
from sinkcharts where item_id IN (select id from pg_temp.export_data where kind='itm');
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select id, 'bbp', _character_transfer_top_level_export('bbp', to_jsonb(building_blueprints))
|
||||
from building_blueprints where item_id IN (select id from pg_temp.export_data where kind='itm');
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'BuildingBlueprintInstance', _character_transfer_top_level_export('BuildingBlueprintInstance', to_jsonb(building_blueprint_instances))
|
||||
from building_blueprint_instances where building_blueprint_id IN (select id from pg_temp.export_data where kind='bbp');
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'BuildingBlueprintPlaceable', _character_transfer_top_level_export('BuildingBlueprintPlaceable', to_jsonb(building_blueprint_placeables))
|
||||
from building_blueprint_placeables where building_blueprint_id IN (select id from pg_temp.export_data where kind='bbp');
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select null, 'BuildingBlueprintPentashield', _character_transfer_top_level_export('BuildingBlueprintPentashield', to_jsonb(building_blueprint_pentashields))
|
||||
from building_blueprint_pentashields where building_blueprint_id IN (select id from pg_temp.export_data where kind='bbp');
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select player_controller_id, 'PlayerVirtualCurrencyBalance', _character_transfer_top_level_export('PlayerVirtualCurrencyBalance', to_jsonb(player_virtual_currency_balances))
|
||||
from player_virtual_currency_balances where player_controller_id = v_player_controller_id;
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select completion_id, 'DungeonCompletion', _character_transfer_top_level_export('DungeonCompletion', to_jsonb(dungeon_completion))
|
||||
from dungeon_completion where completion_id IN (select completion_id from dungeon_completion_players where player_id = v_player_controller_id);
|
||||
|
||||
insert into pg_temp.export_data("id", "kind", "data")
|
||||
select completion_id, 'DungeonCompletionPlayer', _character_transfer_top_level_export('DungeonCompletionPlayer', to_jsonb(dungeon_completion_players))
|
||||
from dungeon_completion_players where player_id = v_player_controller_id;
|
||||
|
||||
insert into pg_temp.export_data("id","kind","data")
|
||||
select null, 'LandsraadHouseRewards', _character_transfer_top_level_export('LandsraadHouseRewards', to_jsonb(landsraad_house_rewards))
|
||||
from landsraad_house_rewards where player_id = v_player_controller_id;
|
||||
|
||||
update pg_temp.export_data set data=_character_transfer_replace_local_id_with_transfer_id_in_json(data, '');
|
||||
|
||||
return (select jsonb_build_object(
|
||||
'_patches_checksum', (_character_transfer_get_patches_checksum()),
|
||||
'funcom_id', (v_funcom_id),
|
||||
'player_controller_id', (v_player_controller_id),
|
||||
'entries', (_character_transfer_data_table_save())
|
||||
));
|
||||
END;
|
||||
$function$
|
||||
@@ -0,0 +1,27 @@
|
||||
-- character_transfer_get_unsaved_counts(in_fls_id text) -> TABLE(unsaved_bases_count bigint, unsaved_vehicles_count bigint)
|
||||
-- oid: 58162 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.character_transfer_get_unsaved_counts(in_fls_id text)
|
||||
RETURNS TABLE(unsaved_bases_count bigint, unsaved_vehicles_count bigint)
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
DECLARE
|
||||
v_acc_id BIGINT;
|
||||
BEGIN
|
||||
v_acc_id := (SELECT acc.id FROM encrypted_accounts acc WHERE acc.user = in_fls_id);
|
||||
|
||||
RETURN QUERY
|
||||
WITH unbacked_bases AS (
|
||||
SELECT COUNT(*) AS count
|
||||
FROM get_unsaved_base_totem_ids_for_account(v_acc_id)
|
||||
),
|
||||
unsaved_vehicles AS (
|
||||
SELECT COUNT(*) AS count
|
||||
FROM get_unbacked_up_vehicle_ids_for_account(v_acc_id)
|
||||
)
|
||||
SELECT
|
||||
ub.count AS unsaved_bases_count,
|
||||
uv.count AS unsaved_vehicles_count
|
||||
FROM unbacked_bases ub, unsaved_vehicles uv;
|
||||
END
|
||||
$function$
|
||||
@@ -0,0 +1,393 @@
|
||||
-- character_transfer_import(in_data jsonb, in_fls_id text, in_character_name text) -> bigint
|
||||
-- oid: 58163 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.character_transfer_import(in_data jsonb, in_fls_id text, in_character_name text)
|
||||
RETURNS bigint
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
DECLARE
|
||||
v_checksum TEXT;
|
||||
v_coriolis_seed BigInt;
|
||||
v_transfer_coriolis_seed BigInt;
|
||||
v_id BigInt;
|
||||
v_kind _CharacterTransferEntryKind;
|
||||
v_new_player_controller_id BigInt;
|
||||
v_vehicle_ids BigInt[];
|
||||
BEGIN
|
||||
if not (select is_player_offline(in_fls_id)) then
|
||||
raise exception 'sbRP2$ - Player must be Offline';
|
||||
end if;
|
||||
|
||||
PERFORM delete_account(in_fls_id, 'incoming char transfer');
|
||||
|
||||
v_checksum := (select _character_transfer_get_patches_checksum());
|
||||
IF NOT in_data->>'_patches_checksum' = v_checksum THEN
|
||||
raise exception 'sb9R2$ - Patches checksum mismatch, expected: %, got: %', v_checksum, in_data->>'_patches_checksum';
|
||||
END IF;
|
||||
|
||||
perform _character_transfer_create_data_table();
|
||||
perform _character_transfer_data_table_load(in_data->'entries');
|
||||
|
||||
update pg_temp.export_data set data=_character_transfer_replace_transfer_id_with_local_id_in_json(data, '');
|
||||
|
||||
-- accounts
|
||||
|
||||
insert into encrypted_accounts
|
||||
select (jsonb_populate_record(
|
||||
null::encrypted_accounts,
|
||||
_character_transfer_top_level_import(kind, data, id)
|
||||
|| jsonb_build_object(
|
||||
'encrypted_funcom_id', encrypt_user_data(in_data->>'funcom_id'),
|
||||
'user', in_fls_id
|
||||
)
|
||||
)).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'acc';
|
||||
|
||||
-- player and vehicle actors
|
||||
|
||||
insert into actors
|
||||
select (jsonb_populate_record(null::actors, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'act';
|
||||
|
||||
insert into fgl_entities
|
||||
select (jsonb_populate_record(null::fgl_entities, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'fgl';
|
||||
|
||||
insert into actor_fgl_entities
|
||||
select (jsonb_populate_record(null::actor_fgl_entities, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'fgl';
|
||||
|
||||
insert into actor_state
|
||||
select (jsonb_populate_record(null::actor_state, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'ActorState';
|
||||
|
||||
insert into permission_actor
|
||||
select (jsonb_populate_record(null::permission_actor, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'PermissionActor';
|
||||
|
||||
insert into permission_actor_rank
|
||||
select (jsonb_populate_record(null::permission_actor_rank, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'PermissionActorRank';
|
||||
|
||||
|
||||
-- vehicle and vehicle modules
|
||||
|
||||
insert into vehicles
|
||||
select (jsonb_populate_record(null::vehicles, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'Vehicle';
|
||||
|
||||
insert into vehicle_modules
|
||||
select (jsonb_populate_record(null::vehicle_modules, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'VehicleModule';
|
||||
|
||||
-- You can VBT as co-owner, but then there will be no owner in target BG. This is a state that permission system doesn't support.
|
||||
-- So for backed up vehicles we also update the players ownership so they are now set as owner.
|
||||
WITH inserted_backup_vehicles AS (
|
||||
INSERT INTO backup_vehicles
|
||||
SELECT (jsonb_populate_record(null::backup_vehicles, _character_transfer_top_level_import(kind, data, id))).*
|
||||
FROM pg_temp.export_data
|
||||
WHERE kind = 'BackupVehicle'
|
||||
RETURNING vehicle_id
|
||||
)
|
||||
SELECT array_agg(vehicle_id) INTO v_vehicle_ids FROM inserted_backup_vehicles;
|
||||
perform _character_transfer_ensure_player_is_owner_of_vbt_vehicle(v_vehicle_ids);
|
||||
|
||||
insert into recovered_vehicles
|
||||
select (jsonb_populate_record(null::recovered_vehicles, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'RecoveredVehicle';
|
||||
|
||||
-- inventories and items
|
||||
|
||||
insert into inventories
|
||||
select (jsonb_populate_record(null::inventories, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data e
|
||||
where kind = 'inv';
|
||||
|
||||
insert into items
|
||||
select (jsonb_populate_record(null::items, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'itm';
|
||||
|
||||
insert into actor_inventories
|
||||
select (jsonb_populate_record(null::actor_inventories, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'ActorInventory';
|
||||
|
||||
insert into vehicle_module_inventories
|
||||
select (jsonb_populate_record(null::vehicle_module_inventories, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'VehicleModuleInventory';
|
||||
|
||||
-- Base backups
|
||||
insert into buildings
|
||||
select (jsonb_populate_record(null::buildings, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'Building';
|
||||
|
||||
insert into building_instances
|
||||
select (jsonb_populate_record(null::building_instances, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'BuildingInstance';
|
||||
|
||||
insert into placeables
|
||||
select (jsonb_populate_record(null::placeables, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'Placeable';
|
||||
|
||||
insert into totems
|
||||
select (jsonb_populate_record(null::totems, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'Totem';
|
||||
|
||||
insert into base_backups
|
||||
select (jsonb_populate_record(null::base_backups, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'BaseBackup';
|
||||
|
||||
insert into base_backup_linked_actors
|
||||
select (jsonb_populate_record(null::base_backup_linked_actors, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'BaseBackupLinkedActor';
|
||||
|
||||
insert into landclaim_segments
|
||||
select (jsonb_populate_record(null::landclaim_segments, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'LandclaimSegment';
|
||||
|
||||
insert into tax_invoice
|
||||
select (jsonb_populate_record(null::tax_invoice, _character_transfer_top_level_import(kind, data, id))).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'TaxInvoice';
|
||||
|
||||
-- other stuff
|
||||
|
||||
insert into encrypted_player_state
|
||||
select (jsonb_populate_record(
|
||||
null::encrypted_player_state,
|
||||
_character_transfer_top_level_import(kind, data, id)
|
||||
|| jsonb_build_object(
|
||||
'encrypted_character_name', encrypt_user_data(in_character_name)
|
||||
)
|
||||
)).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'Character'
|
||||
returning player_controller_id into v_new_player_controller_id;
|
||||
|
||||
insert into player_respawn_locations
|
||||
select (
|
||||
jsonb_populate_record(null::player_respawn_locations, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'RespawnLocation';
|
||||
|
||||
insert into markers
|
||||
select (
|
||||
jsonb_populate_record(null::markers, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'Marker'
|
||||
on conflict ("marker_hash_id", "dimension_index", "map_name_id") do nothing;
|
||||
|
||||
insert into player_markers
|
||||
select (
|
||||
jsonb_populate_record(null::player_markers, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'PlayerMarker';
|
||||
|
||||
insert into dialogue_met_npcs
|
||||
select (
|
||||
jsonb_populate_record(null::dialogue_met_npcs, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'DialogueMetNpc';
|
||||
|
||||
insert into dialogue_taken_nodes
|
||||
select (
|
||||
jsonb_populate_record(null::dialogue_taken_nodes, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'DialogueTakenNode';
|
||||
|
||||
insert into player_faction
|
||||
select (
|
||||
jsonb_populate_record(null::player_faction, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'PlayerFaction';
|
||||
|
||||
insert into player_faction_reputation
|
||||
select (
|
||||
jsonb_populate_record(null::player_faction_reputation, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'PlayerFactionReputation';
|
||||
|
||||
insert into consumed_per_player_lore
|
||||
select (
|
||||
jsonb_populate_record(null::consumed_per_player_lore, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'ConsumedLore';
|
||||
|
||||
insert into tutorial_per_player
|
||||
select (
|
||||
jsonb_populate_record(null::tutorial_per_player, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'PlayerTutorial';
|
||||
|
||||
insert into purchased_specialization_keystones
|
||||
select (
|
||||
jsonb_populate_record(null::purchased_specialization_keystones, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'PurchasedKeystone';
|
||||
|
||||
insert into specialization_tracks
|
||||
select (
|
||||
jsonb_populate_record(null::specialization_tracks, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'SpecializationTracks';
|
||||
|
||||
insert into specialization_refund_id
|
||||
select (
|
||||
jsonb_populate_record(null::specialization_refund_id, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'SpecializationRefund';
|
||||
|
||||
insert into building_favorites
|
||||
select (
|
||||
jsonb_populate_record(null::building_favorites, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'BuildingFavorite';
|
||||
|
||||
insert into building_progression
|
||||
select (
|
||||
jsonb_populate_record(null::building_progression, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'BuildingProgression';
|
||||
|
||||
insert into communinet_player
|
||||
select (
|
||||
jsonb_populate_record(null::communinet_player, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'CommuninetPlayer';
|
||||
|
||||
insert into communinet_player_channels
|
||||
select (
|
||||
jsonb_populate_record(null::communinet_player_channels, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'CommuninetPlayerChannel';
|
||||
|
||||
insert into journey_story_node
|
||||
select (
|
||||
jsonb_populate_record(null::journey_story_node, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'JourneyStoryNode';
|
||||
|
||||
insert into map_areas
|
||||
select (
|
||||
jsonb_populate_record(null::map_areas, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'MapArea';
|
||||
|
||||
insert into player_access_codes
|
||||
select (
|
||||
jsonb_populate_record(null::player_access_codes, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'PlayerAccessCode';
|
||||
|
||||
insert into player_tags
|
||||
select (
|
||||
jsonb_populate_record(null::player_tags, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'PlayerTag';
|
||||
|
||||
insert into sinkcharts
|
||||
select (
|
||||
jsonb_populate_record(null::sinkcharts, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'Sinkchart';
|
||||
|
||||
insert into building_blueprints
|
||||
select (
|
||||
jsonb_populate_record(null::building_blueprints, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'bbp';
|
||||
|
||||
insert into building_blueprint_instances
|
||||
select (
|
||||
jsonb_populate_record(null::building_blueprint_instances, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'BuildingBlueprintInstance';
|
||||
|
||||
insert into building_blueprint_placeables
|
||||
select (
|
||||
jsonb_populate_record(null::building_blueprint_placeables, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'BuildingBlueprintPlaceable';
|
||||
|
||||
insert into building_blueprint_pentashields
|
||||
select (
|
||||
jsonb_populate_record(null::building_blueprint_pentashields, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'BuildingBlueprintPentashield';
|
||||
|
||||
insert into player_virtual_currency_balances
|
||||
select (
|
||||
jsonb_populate_record(null::player_virtual_currency_balances, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'PlayerVirtualCurrencyBalance';
|
||||
|
||||
insert into dungeon_completion
|
||||
select (
|
||||
jsonb_populate_record(null::dungeon_completion, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'DungeonCompletion';
|
||||
|
||||
insert into dungeon_completion_players
|
||||
select (
|
||||
jsonb_populate_record(null::dungeon_completion_players, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'DungeonCompletionPlayer';
|
||||
|
||||
insert into landsraad_house_rewards
|
||||
select (
|
||||
jsonb_populate_record(null::landsraad_house_rewards, _character_transfer_top_level_import(kind, data, id))
|
||||
).*
|
||||
from pg_temp.export_data
|
||||
where kind = 'LandsraadHouseRewards';
|
||||
|
||||
PERFORM set_character_import_state(in_fls_id, 'Complete'::TransferImportState);
|
||||
return v_new_player_controller_id;
|
||||
END;
|
||||
$function$
|
||||
@@ -0,0 +1,16 @@
|
||||
-- cleanup_account_log_and_orphaned_actors() -> void
|
||||
-- oid: 58171 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.cleanup_account_log_and_orphaned_actors()
|
||||
RETURNS void
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
BEGIN
|
||||
delete from actors
|
||||
WHERE
|
||||
-- not is null instead of is not null to match the index expression
|
||||
not owner_account_id is null
|
||||
AND NOT EXISTS(select 1 from accounts where id=owner_account_id);
|
||||
truncate account_removal_log;
|
||||
END
|
||||
$function$
|
||||
@@ -0,0 +1,11 @@
|
||||
-- cleanup_accounts_marked_for_deletion_in_fls(in_account_ids text[]) -> void
|
||||
-- oid: 58172 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.cleanup_accounts_marked_for_deletion_in_fls(in_account_ids text[])
|
||||
RETURNS void
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
begin
|
||||
perform delete_account(id, 'deleted in fls') from unnest(in_account_ids) as id;
|
||||
end
|
||||
$function$
|
||||
@@ -0,0 +1,48 @@
|
||||
-- delete_account(in_user_id text, in_reason text) -> boolean
|
||||
-- oid: 58198 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.delete_account(in_user_id text, in_reason text)
|
||||
RETURNS boolean
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
DECLARE
|
||||
was_found Boolean;
|
||||
BEGIN
|
||||
WITH referenced_actor_ids as (
|
||||
SELECT ARRAY[player_controller_id, player_pawn_id, player_state_id] as ids
|
||||
FROM player_state ps JOIN accounts a ON (ps.account_id = a.id)
|
||||
WHERE a.user = in_user_id
|
||||
),
|
||||
deleted_actors AS
|
||||
(
|
||||
DELETE FROM actors USING referenced_actor_ids WHERE id IN (SELECT id FROM actors WHERE id = ANY(referenced_actor_ids.ids) ORDER BY id FOR UPDATE) returning id
|
||||
),
|
||||
selected_respawn_beacons AS
|
||||
(
|
||||
SELECT player_respawn_locations.locator_actor_id FROM player_respawn_locations
|
||||
INNER JOIN accounts ON accounts.id = player_respawn_locations.account_id
|
||||
WHERE accounts.user = in_user_id AND player_respawn_locations.group = 'RespawnBeacon'
|
||||
),
|
||||
delete_respawn_beacons AS
|
||||
(
|
||||
DELETE FROM actors
|
||||
WHERE actors.id IN (SELECT * FROM selected_respawn_beacons)
|
||||
),
|
||||
delete_accounts as (
|
||||
DELETE FROM accounts WHERE accounts.user = in_user_id returning id as account_id
|
||||
),
|
||||
insert_into_removal_log as (
|
||||
insert into account_removal_log("fls_id", "account_id", "reason") select in_user_id, account_id, in_reason from delete_accounts
|
||||
),
|
||||
delete_from_cascades as (
|
||||
SELECT referenced_actor_ids.ids[1] as id,
|
||||
guild_handle_actor_delete(referenced_actor_ids.ids[1]),
|
||||
remove_party_member(referenced_actor_ids.ids[1], 0::SMALLINT),
|
||||
ownership_handle_actor_delete(referenced_actor_ids.ids[1]),
|
||||
perform_notify_on_character_delete(in_user_id)
|
||||
FROM referenced_actor_ids
|
||||
)
|
||||
SELECT count(*) > 0 INTO was_found FROM delete_from_cascades;
|
||||
return was_found;
|
||||
END;
|
||||
$function$
|
||||
@@ -0,0 +1,44 @@
|
||||
-- get_character_transfer_related_items(in_fls_id text) -> jsonb
|
||||
-- oid: 58293 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.get_character_transfer_related_items(in_fls_id text)
|
||||
RETURNS jsonb
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
BEGIN
|
||||
|
||||
RETURN (
|
||||
WITH acct AS (
|
||||
SELECT id
|
||||
FROM accounts
|
||||
WHERE "user" = in_FLS_ID
|
||||
LIMIT 1
|
||||
)
|
||||
SELECT jsonb_build_object(
|
||||
'items', COALESCE((
|
||||
SELECT jsonb_agg(jsonb_build_object('name', sub.template_id, 'amount', sub.amount))
|
||||
FROM (
|
||||
SELECT i.template_id, SUM(i.stack_size) AS amount
|
||||
FROM inventories inv
|
||||
JOIN items i ON i.inventory_id = inv.id
|
||||
JOIN player_state ps ON inv.actor_id = ps.player_pawn_id
|
||||
WHERE ps.account_id = acct.id AND (
|
||||
(inv.inventory_type = 0 AND i.template_id = 'SolarisCoin') OR
|
||||
(i.template_id IN ('BaseBackupTool', 'VehicleBackupTool'))
|
||||
)
|
||||
GROUP BY i.template_id
|
||||
) sub
|
||||
), '[]'::jsonb),
|
||||
'coin_balance', COALESCE((
|
||||
SELECT vc.balance from player_virtual_currency_balances vc
|
||||
JOIN player_state ps ON ps.account_id = acct.id
|
||||
WHERE vc.currency_id = get_solaris_id()
|
||||
AND vc.player_controller_id = ps.player_controller_id
|
||||
LIMIT 1
|
||||
), 0)
|
||||
)
|
||||
FROM acct
|
||||
);
|
||||
|
||||
END
|
||||
$function$
|
||||
@@ -0,0 +1,18 @@
|
||||
-- get_unsaved_base_totem_ids_for_account(in_account_id bigint) -> TABLE(totem_id bigint)
|
||||
-- oid: 58363 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.get_unsaved_base_totem_ids_for_account(in_account_id bigint)
|
||||
RETURNS TABLE(totem_id bigint)
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
BEGIN
|
||||
RETURN QUERY
|
||||
SELECT t.id
|
||||
FROM totems t
|
||||
JOIN permission_actor_rank par ON t.id = par.permission_actor_id
|
||||
JOIN player_state ps ON par.player_id = ps.player_controller_id
|
||||
LEFT JOIN base_backup_linked_actors bbla ON t.id = bbla.actor_id
|
||||
WHERE ps.account_id = in_account_id
|
||||
AND bbla.actor_id IS NULL;
|
||||
END
|
||||
$function$
|
||||
@@ -0,0 +1,26 @@
|
||||
-- migrate_character(in_account_id bigint, home_dimension integer, max_solaris_allowed bigint) -> void
|
||||
-- oid: 58476 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.migrate_character(in_account_id bigint, home_dimension integer, max_solaris_allowed bigint)
|
||||
RETURNS void
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
DECLARE
|
||||
controller_id BIGINT;
|
||||
pawn_id BIGINT;
|
||||
BEGIN
|
||||
SELECT player_controller_id, player_pawn_id into controller_id, pawn_id
|
||||
FROM player_state ps
|
||||
WHERE ps.account_id = in_account_id;
|
||||
|
||||
UPDATE encrypted_player_state SET home_dimension_index = home_dimension WHERE account_id = in_account_id;
|
||||
|
||||
UPDATE demo_users
|
||||
SET demo_state = 'DbMigratedToRetail'::DemoState, demo_playtime_seconds = NULL
|
||||
WHERE fls_id = (
|
||||
SELECT acc.user FROM accounts AS acc WHERE acc.id = in_account_id
|
||||
);
|
||||
|
||||
PERFORM migrate_clamp_max_allow_solaris(pawn_id, max_solaris_allowed);
|
||||
END
|
||||
$function$
|
||||
@@ -0,0 +1,29 @@
|
||||
-- migrate_clamp_max_allow_solaris(in_pawn_id bigint, max_solaris_allowed bigint) -> void
|
||||
-- oid: 58477 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.migrate_clamp_max_allow_solaris(in_pawn_id bigint, max_solaris_allowed bigint)
|
||||
RETURNS void
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
BEGIN
|
||||
with all_solaris_items as (
|
||||
SELECT row_number() over (), i.id, i.stack_size FROM inventories inv
|
||||
JOIN items i on i.inventory_id = inv.id
|
||||
WHERE inv.actor_id = in_pawn_id AND inv.inventory_type = 0 AND i.template_id = 'SolarisCoin' -- inventory_type 0 is backpack
|
||||
), total_solaris as (
|
||||
SELECT sum(all_solaris_items.stack_size) as total
|
||||
from all_solaris_items
|
||||
), items_to_delete AS (
|
||||
SELECT array_agg(id) AS item_ids
|
||||
FROM all_solaris_items
|
||||
WHERE row_number > 1
|
||||
), deleted_items AS (
|
||||
SELECT delete_items(item_ids)
|
||||
FROM items_to_delete
|
||||
)
|
||||
UPDATE items
|
||||
SET stack_size = LEAST(max_solaris_allowed, total_solaris.total)
|
||||
FROM all_solaris_items, total_solaris, deleted_items
|
||||
WHERE items.id = all_solaris_items.id AND all_solaris_items.row_number = 1;
|
||||
END
|
||||
$function$
|
||||
@@ -0,0 +1,11 @@
|
||||
-- remove_character_transfer_state(in_fls_id text) -> void
|
||||
-- oid: 58516 kind: FUNCTION category: transfer
|
||||
|
||||
CREATE OR REPLACE FUNCTION dune.remove_character_transfer_state(in_fls_id text)
|
||||
RETURNS void
|
||||
LANGUAGE plpgsql
|
||||
AS $function$
|
||||
BEGIN
|
||||
DELETE FROM character_transfer_imports WHERE fls_id = in_fls_id;
|
||||
END;
|
||||
$function$
|
||||
Reference in New Issue
Block a user