docs(reference): import Dune: Awakening server-manager references
All checks were successful
CI / backend-types (push) Successful in 10s
CI / frontend-build (push) Successful in 15s
CI / agent-tests (push) Successful in 39s
CI / integration (push) Successful in 22s

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:
Vantz Stockwell
2026-06-11 21:08:05 -04:00
parent 0715492ddf
commit 651a35d4be
1334 changed files with 238971 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
-- assign_actor_id(in_class text) -> bigint
-- oid: 58140 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.assign_actor_id(in_class text)
RETURNS bigint
LANGUAGE plpgsql
AS $function$
DECLARE
new_id BIGINT;
BEGIN
INSERT INTO actors(id) VALUES(DEFAULT) RETURNING id INTO new_id;
PERFORM add_actor_audit(new_id, in_class);
RETURN new_id;
END
$function$

View File

@@ -0,0 +1,15 @@
-- delete_actor_states_travel(in_actor_id bigint) -> void
-- oid: 58199 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.delete_actor_states_travel(in_actor_id bigint)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
WITH
traveling_actor_ids AS (
SELECT t.id FROM get_traveling_non_player_actor_ids(in_actor_id) AS t
)
DELETE FROM actor_state WHERE (actor_id IN (SELECT t.id FROM traveling_actor_ids AS t(id)) OR actor_id = in_actor_id) AND state = 'Travel';
END;
$function$

View File

@@ -0,0 +1,11 @@
-- delete_actors(in_ids bigint[]) -> void
-- oid: 58200 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.delete_actors(in_ids bigint[])
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
DELETE FROM actors WHERE id = ANY(in_ids);
END
$function$

View File

@@ -0,0 +1,47 @@
-- delete_actors_and_respawns_on_server(in_server_info dune.serverinfo, in_vehicle_classes_spawned_on_map text[], in_allow_vehicle_recovery boolean) -> void
-- oid: 58201 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.delete_actors_and_respawns_on_server(in_server_info dune.serverinfo, in_vehicle_classes_spawned_on_map text[], in_allow_vehicle_recovery boolean)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
WITH actors_to_delete AS (
SELECT a.id
FROM actors a
LEFT JOIN actor_state s ON a.id = s.actor_id
WHERE owner_account_id IS NULL
AND s.state IS DISTINCT FROM 'Travel'
AND s.state IS DISTINCT FROM 'VehicleBackup'
AND s.state IS DISTINCT FROM 'VehicleRecovery'
AND server_info_match(a, in_server_info)
AND (
-- Actors that are not vehicles should always be deleted
NOT EXISTS (SELECT 1 FROM vehicles v WHERE v.id = a.id)
-- Only vehicles that are allowed to be spawned on this map should be deleted
OR in_vehicle_classes_spawned_on_map IS NULL -- If the list is NULL all vehicles are allowed
OR a.class = ANY(in_vehicle_classes_spawned_on_map) -- Vehicle type is explicitly allowed on this map
)
ORDER BY a.id FOR UPDATE OF a
),
vehicles_to_recover AS (
SELECT COALESCE(ARRAY_AGG(v.id), ARRAY[]::BIGINT[]) AS ids FROM actors_to_delete a JOIN vehicles v ON (a.id = v.id)
WHERE in_allow_vehicle_recovery
),
recovered_vehicles AS (
SELECT ids, store_recovered_vehicles_wiped_before_spawn(ids) FROM vehicles_to_recover
)
DELETE FROM actors a USING recovered_vehicles rv
WHERE a.id = ANY(SELECT id FROM actors_to_delete)
AND NOT a.id = ANY(rv.ids);
with
deleted_ids as (
DELETE from player_respawn_locations
WHERE map = in_server_info.map AND dimension = in_server_info.dimension_index
returning id
)
update player_state set pending_respawn_location_id=null
where pending_respawn_location_id in (select * from deleted_ids);
END
$function$

View File

@@ -0,0 +1,35 @@
-- delete_markers_return_actor_ids(in_dimension_index integer, in_map_name text, in_marker_ids integer[]) -> TABLE(actor_id bigint, marker_id integer)
-- oid: 58226 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.delete_markers_return_actor_ids(in_dimension_index integer, in_map_name text, in_marker_ids integer[])
RETURNS TABLE(actor_id bigint, marker_id integer)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
-- Lock markers matching query
WITH affected_markers AS (
SELECT * FROM markers JOIN map_names USING(map_name_id)
WHERE (dimension_index = in_dimension_index OR dimension_index = -1)
AND map_names.map_name = in_map_name
AND marker_hash_id = ANY(in_marker_ids)
ORDER BY marker_hash_id, dimension_index FOR UPDATE -- Ordering to avoid deadlocks
),
-- Lock player_markers to be deleted on cascade
referencing_player_markers AS (
SELECT player_id, player_markers.marker_hash_id FROM player_markers, affected_markers
WHERE affected_markers.marker_hash_id = player_markers.marker_hash_id
AND affected_markers.dimension_index = player_markers.dimension_index
AND affected_markers.map_name_id = player_markers.map_name_id
ORDER BY player_id, player_markers.marker_hash_id, player_markers.dimension_index FOR UPDATE -- Ordering to avoid deadlocks
),
-- Delete markers
deleted_markers AS (
DELETE FROM markers USING affected_markers
WHERE affected_markers.marker_hash_id = markers.marker_hash_id
AND affected_markers.dimension_index = markers.dimension_index
AND affected_markers.map_name_id = markers.map_name_id
)
SELECT * FROM referencing_player_markers;
END
$function$

View File

@@ -0,0 +1,13 @@
-- find_actor_by_id(in_id bigint) -> dune.actorspawninfo
-- oid: 58263 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.find_actor_by_id(in_id bigint)
RETURNS dune.actorspawninfo
LANGUAGE plpgsql
AS $function$
begin
return (select (id, class, transform, partition_id, dimension_index)::ActorSpawnInfo
FROM actors WHERE actors.id = in_id
LIMIT 1);
end
$function$

View File

@@ -0,0 +1,13 @@
-- gather_ownerless_actors_on_server(in_server_info dune.serverinfo) -> SETOF dune.actorspawninfo
-- oid: 58266 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.gather_ownerless_actors_on_server(in_server_info dune.serverinfo)
RETURNS SETOF dune.actorspawninfo
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
SELECT a.id, a.class as class_name, a.transform, a.partition_id, a.dimension_index FROM actors as a
WHERE a.owner_account_id is null AND server_info_match(a, in_server_info);
END;
$function$

View File

@@ -0,0 +1,16 @@
-- gather_player_linked_actors(in_player_pawn_id bigint) -> SETOF dune.actorspawninfo
-- oid: 58267 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.gather_player_linked_actors(in_player_pawn_id bigint)
RETURNS SETOF dune.actorspawninfo
LANGUAGE plpgsql
AS $function$
begin
return query
select actors.id, actors.class as class_name, actors.transform, actors.partition_id, actors.dimension_index
from actors
left join actor_state on actor_state.actor_id = actors.id
where actors.id in (select id from get_traveling_non_player_actor_ids(in_player_pawn_id)) and actor_state.state = 'Travel' and actors.owner_account_id is null
order by actors.id;
end
$function$

View File

@@ -0,0 +1,25 @@
-- gather_removed_accounts_that_left_orphaned_actors_on_server(in_server_info dune.serverinfo) -> TABLE(account_id bigint, removal_reason text, actors_left dune.orphanedplayeractorinfo[])
-- oid: 58268 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.gather_removed_accounts_that_left_orphaned_actors_on_server(in_server_info dune.serverinfo)
RETURNS TABLE(account_id bigint, removal_reason text, actors_left dune.orphanedplayeractorinfo[])
LANGUAGE plpgsql
AS $function$
BEGIN
return query with
orphaned_actors_per_account as (
SELECT
a.owner_account_id as account_id,
array_agg((a.id, a.class)::OrphanedPlayerActorInfo) as actors_left
FROM actors as a
WHERE
-- not is null instead of is not null to match the index expression
not a.owner_account_id is null
AND NOT EXISTS(select 1 from accounts where id=owner_account_id)
AND server_info_match(a, in_server_info)
GROUP BY a.owner_account_id
)
select orphans.account_id, log.reason, orphans.actors_left
from orphaned_actors_per_account as orphans left join account_removal_log as log using (account_id);
END
$function$

View File

@@ -0,0 +1,15 @@
-- get_account_actor_ids(in_account_id bigint) -> dune.playeractorids
-- oid: 58269 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.get_account_actor_ids(in_account_id bigint)
RETURNS dune.playeractorids
LANGUAGE plpgsql
AS $function$
BEGIN
return (
select (player_controller_id, player_state_id, player_pawn_id)::PlayerActorIds from player_state
where account_id = in_account_id
limit 1
);
END
$function$

View File

@@ -0,0 +1,11 @@
-- get_actor_server_info(in_id bigint) -> dune.serverinfo
-- oid: 58271 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.get_actor_server_info(in_id bigint)
RETURNS dune.serverinfo
LANGUAGE plpgsql
AS $function$
begin
return (select (map, partition_id, dimension_index)::ServerInfo from actors where id=in_id limit 1);
end
$function$

View File

@@ -0,0 +1,11 @@
-- get_registered_spawned_actor(in_spawner_id bigint) -> SETOF bigint
-- oid: 58348 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.get_registered_spawned_actor(in_spawner_id bigint)
RETURNS SETOF bigint
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
SELECT actor_id FROM actor_spawner_actors WHERE spawner_id = in_spawner_id;
END; $function$

View File

@@ -0,0 +1,54 @@
-- load_actors(in_actor_ids bigint[], in_actor_state dune.actorstate) -> TABLE(ord bigint, actor_id bigint, generic_data dune.actorgenericdata, serial bigint)
-- oid: 58438 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.load_actors(in_actor_ids bigint[], in_actor_state dune.actorstate DEFAULT 'Default'::dune.actorstate)
RETURNS TABLE(ord bigint, actor_id bigint, generic_data dune.actorgenericdata, serial bigint)
LANGUAGE plpgsql
AS $function$
begin
return query
with
ids as (
select * from unnest(in_actor_ids) with ordinality as t(id, ord)
),
entities as (
select
fgl_bridge.actor_id,
(fgl_bridge.entity_id, fgl_bridge.slot_name, entity_data.components)::FglEntity as data
from
ids
left join actor_fgl_entities as fgl_bridge on ids.id=fgl_bridge.actor_id
left join fgl_entities as entity_data on fgl_bridge.entity_id = entity_data.entity_id
)
select
ids.ord, actors.id,
(
coalesce(array_agg(entities.data) filter (where entities.data is not null), array[]::FglEntity[]),
actors.properties,
actors.gas_attributes,
case
when exists(select 1 from buildings where actors.id = buildings.id) then load_building(actors.id)
end
,
case
when exists(select 1 from placeables where actors.id = placeables.id) then load_placeable(actors.id)
end
,
case
when exists(select 1 from totems where actors.id = totems.id) then load_totem(actors.id)
end
)::ActorGenericData, actors.serial
from
ids
join actors using (id)
left join entities on actors.id = entities.actor_id
where
case when (in_actor_state = 'Default') then
not exists(select 1 from actor_state where actors.id = actor_state.actor_id)
else
exists(select 1 from actor_state where actors.id = actor_state.actor_id and actor_state.state = in_actor_state)
end
group by ids.ord, actors.id, actors.properties, actors.gas_attributes, actors.serial
order by ids.ord;
END
$function$

View File

@@ -0,0 +1,48 @@
-- load_full_actors(in_ids bigint[]) -> SETOF dune.actordescription
-- oid: 58454 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.load_full_actors(in_ids bigint[])
RETURNS SETOF dune.actordescription
LANGUAGE plpgsql
AS $function$
begin
return query
with
ids as (
select * from unnest(in_ids) with ordinality as t(id, ord)
),
entities as (
select
actor_id,
(fgl_bridge.entity_id, fgl_bridge.slot_name, entity_data.components)::FglEntity as data
from
ids
left join actor_fgl_entities as fgl_bridge on ids.id=fgl_bridge.actor_id
left join fgl_entities as entity_data using (entity_id)
)
select
id, "class", "transform", (
coalesce(array_agg(entities.data) filter (where entities.data is not null), array[]::FglEntity[]),
actors.properties,
actors.gas_attributes,
case
when exists(select 1 from buildings where ids.id = buildings.id) then load_building(id)
else null
end,
case
when exists(select 1 from placeables where ids.id = placeables.id) then load_placeable(id)
else null
end
,
case
when exists(select 1 from totems where id = totems.id) then load_totem(id)
end
)::ActorGenericData, actors.serial
from
ids
join actors using (id)
left join entities on id=entities.actor_id
group by ids.ord, id, class, "transform", actors.properties, actors.gas_attributes, actors.serial
order by ids.ord;
end
$function$

View File

@@ -0,0 +1,32 @@
-- ownership_handle_actor_delete(in_player_id bigint) -> void
-- oid: 58482 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.ownership_handle_actor_delete(in_player_id bigint)
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
owned_totem_ids BIGINT[];
actors_with_permission BIGINT[];
BEGIN
-- Get owner entity ids (totems) where in_player_id is the owner
SELECT ARRAY_AGG(owner_entity_id) into owned_totem_ids
FROM permission_actor_rank
JOIN permission_actor ON actor_id = permission_actor_id
JOIN placeables on placeables.id = permission_actor_id
WHERE player_id = in_player_id AND rank = 1::smallint; -- 1:owner
-- Get actors where in_player_id is the owner
SELECT ARRAY_AGG(permission_actor_id) into actors_with_permission
FROM permission_actor_rank WHERE player_id = in_player_id AND rank = 1::smallint; -- 1:owner
-- Remove all permissions for those actors
IF cardinality(actors_with_permission) > 0 THEN
DELETE FROM permission_actor_rank WHERE permission_actor_id = ANY(actors_with_permission);
DELETE FROM MARKERS WHERE marker_hash_id = ANY(actors_with_permission);
PERFORM pg_notify('permission_notify_channel', format('owner_delete#{"PlayerId" : %s}', in_player_id));
END IF;
END
$function$

View File

@@ -0,0 +1,10 @@
-- register_spawned_actor(in_spawner_id bigint, in_actor_id bigint) -> void
-- oid: 58511 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.register_spawned_actor(in_spawner_id bigint, in_actor_id bigint)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
INSERT INTO actor_spawner_actors(spawner_id, actor_id) VALUES(in_spawner_id, in_actor_id);
END $function$

View File

@@ -0,0 +1,19 @@
-- remove_aborted_authority_transfer_actors(in_partition_id bigint) -> SETOF dune.actorspawninfo
-- oid: 58515 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.remove_aborted_authority_transfer_actors(in_partition_id bigint)
RETURNS SETOF dune.actorspawninfo
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
WITH removed_actors AS (
DELETE FROM actor_state WHERE actor_state.state = 'AbortedAuthorityTransfer'
RETURNING actor_state.actor_id
)
SELECT a.id, a.class AS class_name, a.transform, a.partition_id, a.dimension_index
FROM actors AS a
INNER JOIN removed_actors ON a.id = removed_actors.actor_id
WHERE a.partition_id = in_partition_id;
END
$function$

View File

@@ -0,0 +1,30 @@
-- remove_recipes_from_actor_properties(recipes_to_remove text[]) -> void
-- oid: 58525 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.remove_recipes_from_actor_properties(recipes_to_remove text[])
RETURNS void
LANGUAGE plpgsql
AS $function$
begin
with actors_properties as (
select id, properties->'CraftingRecipesLibraryActorComponent'->'m_KnownItemRecipes' as recipes
from actors
),
modified_actors_properties as (
select id, (
select jsonb_agg(recipe)
from jsonb_array_elements(actors_properties.recipes) as recipe
where not (recipe->'BaseRecipeId'->>'Name' = any(recipes_to_remove))
) as filtered_recipes
from actors_properties
)
update actors
set properties = jsonb_set(
actors.properties,
'{CraftingRecipesLibraryActorComponent,m_KnownItemRecipes}',
coalesce(modified_actors_properties.filtered_recipes, '[]'::jsonb)
)
from modified_actors_properties
where actors.id = modified_actors_properties.id;
end;
$function$

View File

@@ -0,0 +1,15 @@
-- save_aborted_authority_transfer_actors(in_actor_ids bigint[], in_partition_id bigint) -> void
-- oid: 58539 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.save_aborted_authority_transfer_actors(in_actor_ids bigint[], in_partition_id bigint)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
INSERT INTO actor_state(actor_id, state)
SELECT a.id, 'AbortedAuthorityTransfer'
FROM actors AS a
WHERE a.id = ANY(in_actor_ids) AND a.partition_id = in_partition_id
ON CONFLICT DO NOTHING;
END
$function$

View File

@@ -0,0 +1,23 @@
-- save_actor_dislocation(in_actor_id bigint, in_current_server_info dune.serverinfo, in_target_location dune.vector, in_target_dimension_index integer) -> void
-- oid: 58540 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.save_actor_dislocation(in_actor_id bigint, in_current_server_info dune.serverinfo, in_target_location dune.vector, in_target_dimension_index integer)
RETURNS void
LANGUAGE plpgsql
AS $function$
begin
update actors
set
transform = (in_target_location, (transform).rotation),
dimension_index = in_target_dimension_index,
partition_id = null
where id = in_actor_id
and map = (in_current_server_info).map
and dimension_index = (in_current_server_info).dimension_index
and (
partition_id is null
or (in_current_server_info).partition_id is null
or partition_id = (in_current_server_info).partition_id
);
end
$function$

View File

@@ -0,0 +1,132 @@
-- save_actors(in_server_info dune.serverinfo, in_actors dune.actordescription[], in_actor_state dune.actorstate) -> TABLE(actor_id bigint, current_saved_serial bigint, saved boolean)
-- oid: 58541 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.save_actors(in_server_info dune.serverinfo, in_actors dune.actordescription[], in_actor_state dune.actorstate DEFAULT 'Default'::dune.actorstate)
RETURNS TABLE(actor_id bigint, current_saved_serial bigint, saved boolean)
LANGUAGE plpgsql
AS $function$
BEGIN
return query with
input_actors as (
select * from unnest(in_actors)
),
valid_input_actors as (
select input_actors.id from input_actors
left join actor_state on input_actors.id = actor_state.actor_id
where actor_state.state = in_actor_state or (in_actor_state = 'Default' and actor_state.actor_id is null)
),
serial_checks as (
select
input.id,
input.serial as input_serial,
coalesce(actors.serial, 0) as saved_serial,
input.serial >= coalesce(actors.serial, 0) and input.id in (select id from valid_input_actors) as should_save
from
input_actors as input left join actors using (id)
),
actors_to_save as (
select i.* from input_actors as i join serial_checks as c using (id) where c.should_save
),
upsert_actors as (
insert into actors(
"id", "class", "transform",
"gas_attributes",
"properties",
"map", "partition_id", "dimension_index",
"serial"
)
select
i.id, i.class_name, i.transform,
(i.generic_data).gas_attribute_sets_json, (i.generic_data).properties_json,
in_server_info.map, in_server_info.partition_id, coalesce(in_server_info.dimension_index, 0),
i.serial
from actors_to_save as i
on conflict (id) do update
set
"class" = EXCLUDED.class, "transform" = case when EXCLUDED.transform is null or (EXCLUDED.transform).location = (zero_transform()).location then actors.transform else EXCLUDED.transform end,
"gas_attributes" = EXCLUDED.gas_attributes, "properties" = EXCLUDED.properties,
"map" = EXCLUDED.map, "partition_id" = EXCLUDED.partition_id, "dimension_index" = EXCLUDED.dimension_index,
"serial" = EXCLUDED.serial
returning id
),
fgl_entity_data as (
select id as actor_id, (u).entity_id, (u).slot_name, (u).components_json as components
from (select id, unnest((generic_data).entities) as u from actors_to_save) q
),
missing_entities as (
select entity_id
from actors_to_save join actor_fgl_entities as existing on (actors_to_save.id = existing.actor_id)
where not exists(select 1 from fgl_entity_data as updated where updated.entity_id=existing.entity_id)
),
delete_missing_entity_links as (
delete from actor_fgl_entities as existing using missing_entities
where existing.entity_id=missing_entities.entity_id
returning existing.entity_id as deleted_entity_id
),
delete_missing_entities as (
delete from fgl_entities as existing using missing_entities
where existing.entity_id=missing_entities.entity_id
),
upsert_entities as (
insert into fgl_entities("entity_id", "components")
select entity_id, components from fgl_entity_data
on conflict (entity_id) do update
set components=EXCLUDED.components
returning entity_id
),
upsert_entity_links as (
insert into actor_fgl_entities("actor_id", "entity_id", "slot_name")
select fgl_entity_data.actor_id, fgl_entity_data.entity_id, fgl_entity_data.slot_name
from fgl_entity_data left join upsert_entities using (entity_id)
-- HACK: this is a temporary fix until we do TECH-23063
where not entity_id in (select deleted_entity_id from delete_missing_entity_links)
on conflict (entity_id) do update
set
actor_id=EXCLUDED.actor_id,
slot_name=EXCLUDED.slot_name
returning actor_fgl_entities.actor_id, actor_fgl_entities.entity_id
),
all_actor_entities as (
select fgl_entity_data.actor_id as id, array_agg(entity_id) as entity_ids
from fgl_entity_data
left join upsert_entities using (entity_id)
left join upsert_entity_links using (entity_id)
group by fgl_entity_data.actor_id
),
extra_data as (
select
input_actors.id,
serial_checks.saved_serial,
(serial_checks.should_save) as saved,
(input_actors.generic_data).building_actor_data as building_data,
(input_actors.generic_data).placeable_actor_data as placeable_data,
(input_actors.generic_data).totem_actor_data as totem_data,
coalesce(all_actor_entities.entity_ids, array[]::int[]) as entity_ids
from
serial_checks
left join input_actors using(id)
left join upsert_actors using(id) -- this is needed for dependency
left join all_actor_entities using(id) -- this is needed for dependency only
),
save_extras as (
select
extra_data.id,
extra_data.saved_serial,
extra_data.saved,
case when extra_data.saved and building_data is not null then
save_building(id, building_data)
end,
case when extra_data.saved and placeable_data is not null then
save_placeable(id, placeable_data)
end,
case when extra_data.saved and totem_data is not null then
save_totem(id, totem_data)
end,
entity_ids
from extra_data
)
select id, saved_serial, save_extras.saved from save_extras;
END
$function$

View File

@@ -0,0 +1,47 @@
-- update_traveling_actor_dependencies(in_dep dune.traveldependency[]) -> void
-- oid: 58640 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.update_traveling_actor_dependencies(in_dep dune.traveldependency[])
RETURNS void
LANGUAGE plpgsql
AS $function$
begin
with valid_ids as (
with d as (select * from unnest(in_dep))
select d.id from d where d.id is not null
union
select d.parent_id from d where d.parent_id is not null
),
valid_ids_plus_dep as (
select * from valid_ids
union
select tap.id from travel_actor_parent as tap where tap.parent_id in (select * from valid_ids)
),
-- remove valid ids and connected dependencies from actor_state
delete_actor_state_ids AS (
delete from actor_state as acs
where acs.actor_id in (select * from valid_ids_plus_dep) and acs.state = 'Travel'
)
-- remove valid ids and connected dependencies from any other dependency tree
delete from travel_actor_parent
where id in (select * from valid_ids_plus_dep);
-- add/update dependencies with valid parent and child ids
with valid_dep as (
select a1.id as id, a2.id as parent_id, d.is_instigator
from unnest(in_dep) d
left join actors as a1
on d.id = a1.id
left join actors as a2
on d.parent_id = a2.id
where
a1.id is not null
and a2.id is not null
)
insert into travel_actor_parent (id, parent_id, is_instigator)
select * from valid_dep
on conflict (id) do update set
"parent_id" = excluded.parent_id,
"is_instigator" = excluded.is_instigator;
end
$function$

View File

@@ -0,0 +1,39 @@
-- update_traveling_actor_tree(in_actor_id bigint, in_target_transform dune.transform, in_target_map text, in_target_dimension_index integer, in_target_partition_id bigint) -> TABLE(out_id bigint, out_actor_state text)
-- oid: 58641 kind: FUNCTION category: actors
CREATE OR REPLACE FUNCTION dune.update_traveling_actor_tree(in_actor_id bigint, in_target_transform dune.transform, in_target_map text, in_target_dimension_index integer, in_target_partition_id bigint)
RETURNS TABLE(out_id bigint, out_actor_state text)
LANGUAGE plpgsql
AS $function$
begin
RETURN query WITH
traveling_actor_ids AS (
SELECT t.id FROM get_traveling_actor_ids(in_actor_id) AS t
),
invalid_traveling_actor_ids AS (
SELECT id, actor_state.state::TEXT FROM traveling_actor_ids
INNER JOIN actor_state ON actor_state.actor_id = traveling_actor_ids.id
WHERE actor_state.state != 'Travel'
),
valid_traveling_actor_ids AS (
SELECT id FROM traveling_actor_ids
WHERE NOT EXISTS (SELECT 1 FROM invalid_traveling_actor_ids)
),
insert_actor_state AS (
INSERT INTO actor_state(actor_id, state)
SELECT id, 'Travel' FROM valid_traveling_actor_ids
ON CONFLICT DO NOTHING
),
update_actors AS (
UPDATE actors
SET
transform = in_target_transform,
dimension_index = in_target_dimension_index,
map = in_target_map,
partition_id = in_target_partition_id
FROM valid_traveling_actor_ids
WHERE actors.id = valid_traveling_actor_ids.id
)
SELECT * FROM invalid_traveling_actor_ids;
end
$function$

View File

@@ -0,0 +1,11 @@
-- add_actor_audit(in_id bigint, in_class text) -> void
-- oid: 58118 kind: FUNCTION category: anticheat
CREATE OR REPLACE FUNCTION dune.add_actor_audit(in_id bigint, in_class text)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
INSERT INTO actor_audit("id", "class") VALUES(in_id, in_class) ON CONFLICT(id) DO NOTHING;
END
$function$

View File

@@ -0,0 +1,19 @@
-- flag_player_as_cheater(in_account_id bigint, in_cheat_type dune.cheat_type_enum) -> void
-- oid: 58265 kind: FUNCTION category: anticheat
CREATE OR REPLACE FUNCTION dune.flag_player_as_cheater(in_account_id bigint, in_cheat_type dune.cheat_type_enum)
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
v_FLS_id TEXT;
BEGIN
SELECT acc."user"
INTO v_FLS_id
FROM accounts acc
WHERE acc.id = in_account_id
LIMIT 1;
PERFORM log_cheating(v_FLS_id, in_cheat_type);
END;
$function$

View File

@@ -0,0 +1,21 @@
-- log_cheating(in_fls_id text, in_cheat_type dune.cheat_type_enum, in_event_time timestamp with time zone) -> void
-- oid: 58469 kind: FUNCTION category: anticheat
CREATE OR REPLACE FUNCTION dune.log_cheating(in_fls_id text, in_cheat_type dune.cheat_type_enum, in_event_time timestamp with time zone DEFAULT now())
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
-- Insert into suspicious_be
INSERT INTO cheater_tracking (
event_time,
fls_id,
cheat_type
) VALUES (
in_event_time,
in_fls_id,
in_cheat_type
);
END;
$function$

View File

@@ -0,0 +1,19 @@
-- base_backup_delete(in_base_backup_id bigint) -> void
-- oid: 58141 kind: FUNCTION category: base_backup
CREATE OR REPLACE FUNCTION dune.base_backup_delete(in_base_backup_id bigint)
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
actors_to_destroy BIGINT[];
BEGIN
DELETE FROM actors a WHERE id = ANY(
SELECT actor_id
FROM base_backup_linked_actors bbla
WHERE bbla.id = in_base_backup_id
);
DELETE FROM base_backups WHERE id = in_base_backup_id;
END
$function$

View File

@@ -0,0 +1,15 @@
-- base_backup_find_totems_from_player_owner(in_player_id bigint) -> TABLE(totem_id bigint)
-- oid: 58142 kind: FUNCTION category: base_backup
CREATE OR REPLACE FUNCTION dune.base_backup_find_totems_from_player_owner(in_player_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 par.permission_actor_id = t.id
WHERE par.player_id = in_player_id AND par.rank = 1;
END;
$function$

View File

@@ -0,0 +1,42 @@
-- base_backup_finish_placing(in_base_backup_id bigint) -> void
-- oid: 58143 kind: FUNCTION category: base_backup
CREATE OR REPLACE FUNCTION dune.base_backup_finish_placing(in_base_backup_id bigint)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
WITH base_info AS (
SELECT
bb.id AS base_backup_id,
a.partition_id,
a.dimension_index,
a.map
FROM
base_backups bb
JOIN actors a on bb.player_id = a.id
WHERE
bb.id = in_base_backup_id
)
UPDATE actors
SET
partition_id = base_info.partition_id,
dimension_index = base_info.dimension_index,
map = base_info.map
FROM
base_backup_linked_actors bbl
JOIN base_info ON bbl.id = base_info.base_backup_id
WHERE
actors.id = bbl.actor_id;
DELETE FROM actor_state a
WHERE actor_id = ANY(
SELECT actor_id
FROM base_backup_linked_actors bbla
WHERE bbla.id = in_base_backup_id
);
DELETE FROM base_backups
WHERE id = in_base_backup_id;
END
$function$

View File

@@ -0,0 +1,16 @@
-- base_backup_get_actors_to_spawn(in_base_backup_id bigint) -> SETOF dune.actorspawninfo
-- oid: 58144 kind: FUNCTION category: base_backup
CREATE OR REPLACE FUNCTION dune.base_backup_get_actors_to_spawn(in_base_backup_id bigint)
RETURNS SETOF dune.actorspawninfo
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
SELECT a.id, a.class as class_name, a.transform, a.partition_id, a.dimension_index
FROM actors as a
WHERE a.id IN (
SELECT actor_id FROM base_backup_linked_actors as bbla WHERE bbla.id = in_base_backup_id
);
END
$function$

View File

@@ -0,0 +1,24 @@
-- base_backup_get_available_backups(in_player_id bigint) -> TABLE(id bigint, base_backup_name text, totem_id bigint, totem_buildable_type text, landclaim_original_global_location real[], base_backup_map text)
-- oid: 58145 kind: FUNCTION category: base_backup
CREATE OR REPLACE FUNCTION dune.base_backup_get_available_backups(in_player_id bigint)
RETURNS TABLE(id bigint, base_backup_name text, totem_id bigint, totem_buildable_type text, landclaim_original_global_location real[], base_backup_map text)
LANGUAGE plpgsql
AS $function$
begin
RETURN QUERY
SELECT
bb.id,
bb.base_backup_name,
t.id AS totem_id,
p.building_type,
t.landclaim_original_global_location,
a.map
FROM base_backups bb
JOIN base_backup_linked_actors bbla ON bbla.id = bb.id
JOIN totems t ON bbla.actor_id = t.id
JOIN actors a ON a.id = t.id
JOIN placeables p ON p.id = a.id
WHERE bb.player_id = in_player_id;
END
$function$

View File

@@ -0,0 +1,30 @@
-- base_backup_get_buildable_data(in_base_backup_id bigint) -> TABLE(buildable_type text, total_count integer)
-- oid: 58146 kind: FUNCTION category: base_backup
CREATE OR REPLACE FUNCTION dune.base_backup_get_buildable_data(in_base_backup_id bigint)
RETURNS TABLE(buildable_type text, total_count integer)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
SELECT t.buildable_type, SUM(t.cnt)::INT AS total_count
FROM (
SELECT bi.building_type AS buildable_type, COUNT(*) AS cnt
FROM base_backup_linked_actors bla
JOIN building_instances bi ON bla.actor_id = bi.building_id
WHERE
bla.id = in_base_backup_id AND
(bi.building_flags IS NULL OR (bi.building_flags & (1 << 2) = 0 AND bi.building_flags & (1 << 7) = 0)) -- flag 2 and 7 not enabled, which relates to holograms and extensions
GROUP BY bi.building_type
UNION ALL
SELECT p.building_type AS buildable_type, COUNT(*) AS cnt
FROM base_backup_linked_actors bla
JOIN placeables p ON bla.actor_id = p.id
WHERE bla.id = in_base_backup_id AND p.is_hologram = FALSE
GROUP BY p.building_type
) t
GROUP BY t.buildable_type;
END
$function$

View File

@@ -0,0 +1,42 @@
-- base_backup_get_data(in_base_backup_id bigint) -> dune.getbasebackupdata
-- oid: 58147 kind: FUNCTION category: base_backup
CREATE OR REPLACE FUNCTION dune.base_backup_get_data(in_base_backup_id bigint)
RETURNS dune.getbasebackupdata
LANGUAGE plpgsql
AS $function$
DECLARE
base_backup_name TEXT;
totem_data BaseBackupTotemData;
buildings_array BaseBackupBuildingItem[];
placeables_array BaseBackupPlaceableItem[];
BEGIN
SELECT bb.base_backup_name
INTO base_backup_name
FROM base_backups bb
WHERE bb.id = in_base_backup_id;
totem_data := base_backup_get_totem_data(in_base_backup_id);
-- building pieces
SELECT array_agg((bi.building_id, bi.instance_id, bi.building_type, bi.transform, bi.building_flags)::BaseBackupBuildingItem)
into buildings_array
FROM
building_instances bi
JOIN base_backup_linked_actors bbla ON bi.building_id = bbla.actor_id
WHERE bbla.id = in_base_backup_id;
-- placeables
SELECT array_agg((p.building_type, a.transform)::BaseBackupPlaceableItem)
into placeables_array
FROM
placeables p
JOIN actors a ON p.id = a.id
JOIN base_backup_linked_actors bbla ON a.id = bbla.actor_id
WHERE
bbla.id = in_base_backup_id;
return ROW(base_backup_name, totem_data, buildings_array, placeables_array)::GetBaseBackupData;
END
$function$

View File

@@ -0,0 +1,26 @@
-- base_backup_get_totem_data(in_base_backup_id bigint) -> dune.basebackuptotemdata
-- oid: 58148 kind: FUNCTION category: base_backup
CREATE OR REPLACE FUNCTION dune.base_backup_get_totem_data(in_base_backup_id bigint)
RETURNS dune.basebackuptotemdata
LANGUAGE plpgsql
AS $function$
DECLARE
totem_id BIGINT;
result BaseBackupTotemData;
BEGIN
SELECT t.id
INTO totem_id
FROM totems t JOIN base_backup_linked_actors bbla ON t.id = bbla.actor_id
WHERE bbla.id = in_base_backup_id
LIMIT 1;
IF totem_id IS NULL THEN
RAISE EXCEPTION 'No totem found for base_backup id %', in_base_backup_id;
END IF;
result := base_backup_get_totem_data_from_totem_id(totem_id);
RETURN result;
END;
$function$

View File

@@ -0,0 +1,42 @@
-- base_backup_get_totem_data_from_totem_id(in_totem_id bigint) -> dune.basebackuptotemdata
-- oid: 58149 kind: FUNCTION category: base_backup
CREATE OR REPLACE FUNCTION dune.base_backup_get_totem_data_from_totem_id(in_totem_id bigint)
RETURNS dune.basebackuptotemdata
LANGUAGE plpgsql
AS $function$
DECLARE
result BaseBackupTotemData;
BEGIN
SELECT
t.id,
p.building_type,
a.map,
t.landclaim_original_global_location,
t.landclaim_original_global_yaw_rotation,
t.landclaim_vertical_level
INTO
result.totem_actor_id,
result.totem_building_type,
result.totem_map,
result.landclaim_original_global_location,
result.landclaim_original_global_yaw_rotation,
result.landclaim_vertical_level
FROM totems t
JOIN placeables p ON p.id = t.id
JOIN actors a ON a.id = t.id
WHERE t.id = in_totem_id
LIMIT 1;
IF result.totem_actor_id IS NULL THEN
RAISE EXCEPTION 'No totem found for totem_id %', in_totem_id;
END IF;
SELECT array_agg(ROW(grid_location_x, grid_location_y)::SMALLINTPOINT)
INTO result.landclaim_grid
FROM landclaim_segments s
WHERE s.totem_id = result.totem_actor_id;
RETURN result;
END;
$function$

View File

@@ -0,0 +1,24 @@
-- base_backup_get_totem_id(backup_id bigint) -> bigint
-- oid: 58150 kind: FUNCTION category: base_backup
CREATE OR REPLACE FUNCTION dune.base_backup_get_totem_id(backup_id bigint)
RETURNS bigint
LANGUAGE plpgsql
AS $function$
DECLARE
result BIGINT;
BEGIN
SELECT t.id
INTO result
FROM totems t
JOIN base_backup_linked_actors bbla ON t.id = bbla.actor_id
WHERE bbla.id = backup_id
LIMIT 1;
IF result IS NULL THEN
RAISE EXCEPTION 'No totem found for base_backup id %', backup_id;
END IF;
RETURN result;
END;
$function$

View File

@@ -0,0 +1,38 @@
-- base_backup_recycle(in_base_backup_id bigint, in_target_inventory_id bigint) -> integer
-- oid: 58151 kind: FUNCTION category: base_backup
CREATE OR REPLACE FUNCTION dune.base_backup_recycle(in_base_backup_id bigint, in_target_inventory_id bigint)
RETURNS integer
LANGUAGE plpgsql
AS $function$
DECLARE
base_backup_items_moved INT;
BEGIN
UPDATE items
SET inventory_id = in_target_inventory_id
FROM
inventories inv
JOIN base_backup_linked_actors bbla ON inv.actor_id = bbla.actor_id
WHERE
items.inventory_id = inv.id
AND bbla.id = in_base_backup_id;
get diagnostics base_backup_items_moved = ROW_COUNT;
-- Re-organize the index of all the items
UPDATE items
SET position_index = new_index
FROM (
SELECT
id,
ROW_NUMBER() OVER (ORDER BY position_index) - 1 AS new_index
FROM items
WHERE inventory_id = in_target_inventory_id
) AS sub
WHERE items.id = sub.id;
PERFORM base_backup_delete(in_base_backup_id);
return base_backup_items_moved;
END
$function$

View File

@@ -0,0 +1,58 @@
-- base_backup_save(in_player_actor_id bigint, in_base_backup_name text, in_building_pieces_to_link dune.basebackupbuildingitem[], in_placeables_to_link bigint[], in_placeables_to_remove_totem_owner bigint[]) -> bigint
-- oid: 58152 kind: FUNCTION category: base_backup
CREATE OR REPLACE FUNCTION dune.base_backup_save(in_player_actor_id bigint, in_base_backup_name text, in_building_pieces_to_link dune.basebackupbuildingitem[], in_placeables_to_link bigint[], in_placeables_to_remove_totem_owner bigint[])
RETURNS bigint
LANGUAGE plpgsql
AS $function$
DECLARE
v_backup_id BIGINT;
totem_id BIGINT;
BEGIN
-- Find and Validate the Totem exists in the list
SELECT t.id INTO totem_id
FROM totems t
JOIN unnest(in_placeables_to_link) AS ai(actor_id) ON t.id = ai.actor_id
LIMIT 1;
IF totem_id IS NULL THEN
RAISE EXCEPTION 'No totem found for base_backup_save';
END IF;
INSERT INTO base_backups(player_id, base_backup_name)
VALUES (in_player_actor_id, in_base_backup_name) RETURNING id INTO v_backup_id;
-- for each building_id, create a new actor for those building pieces and then assign that new building_id to the building pieces.
with
input as (select DISTINCT building_id from unnest(in_building_pieces_to_link)),
instances_input as (select building_id, instance_id from unnest(in_building_pieces_to_link)),
new_actor_ids as (select nextval('actors_id_seq') as new_id, building_id as old_id from input),
_copy_building_actors as (
insert into actors("id", "class", "map", "transform", "partition_id", "dimension_index")
select i.new_id, a."class", a."map", a."transform", a."partition_id", a."dimension_index"
from new_actor_ids i join actors a on (i.old_id = a.id)),
_insert_actor_states as (insert into actor_state(actor_id, state) select new_id, 'BaseBackup' from new_actor_ids),
_insert_buildings as (insert into buildings("id") select new_id from new_actor_ids),
_insert_base_backup_linked_actors as (insert into base_backup_linked_actors("id", "actor_id") select v_backup_id, new_id from new_actor_ids)
update building_instances bi set building_id = ids.new_id from new_actor_ids ids join instances_input i on (ids.old_id = i.building_id) where bi.building_id = ids.old_id and bi.instance_id = i.instance_id;
-- Link all placeables to the linked_base_backup_id and set them to BaseBackup ActorState in actor_state
INSERT INTO base_backup_linked_actors(id, actor_id)
SELECT v_backup_id, unnest(in_placeables_to_link);
INSERT INTO actor_state(actor_id, state)
SELECT unnest(in_placeables_to_link), 'BaseBackup'::ActorState;
UPDATE placeables
SET owner_entity_id = NULL
WHERE id = ANY(in_placeables_to_remove_totem_owner);
-- We need to remove permissions for the Totem
PERFORM permission_actor_destroy(totem_id);
-- Remove all invoices from the totem
PERFORM taxation_remove_invoices_from_totem(totem_id);
RETURN v_backup_id;
END
$function$

View File

@@ -0,0 +1,13 @@
-- base_backup_save_all_totems_from_player_owner(in_player_id bigint) -> TABLE(base_backup_id bigint)
-- oid: 58153 kind: FUNCTION category: base_backup
CREATE OR REPLACE FUNCTION dune.base_backup_save_all_totems_from_player_owner(in_player_id bigint)
RETURNS TABLE(base_backup_id bigint)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
SELECT base_backup_save_from_totem(in_player_id, totem_id)
FROM base_backup_find_totems_from_player_owner(in_player_id);
END;
$function$

View File

@@ -0,0 +1,47 @@
-- base_backup_save_from_totem(in_player_id bigint, totem_id bigint) -> bigint
-- oid: 58154 kind: FUNCTION category: base_backup
CREATE OR REPLACE FUNCTION dune.base_backup_save_from_totem(in_player_id bigint, totem_id bigint)
RETURNS bigint
LANGUAGE plpgsql
AS $function$
DECLARE
totem_entity_id BIGINT;
totem_name TEXT;
building_pieces_to_link BaseBackupBuildingItem[];
placeables_to_link BIGINT[];
placeables_to_remove_totem_owner BIGINT[];
BEGIN
SELECT entity_id INTO totem_entity_id
FROM actor_fgl_entities
WHERE actor_id = totem_id;
SELECT COALESCE(actor_name, '') INTO totem_name
FROM permission_actor
WHERE actor_id = totem_id
LIMIT 1;
SELECT array_agg((bi.building_id, bi.instance_id, bi.building_type, bi.transform, bi.building_flags)::BaseBackupBuildingItem)
INTO building_pieces_to_link
FROM building_instances bi
WHERE bi.owner_entity_id = totem_entity_id;
SELECT array_agg(p.id)
INTO placeables_to_link
FROM placeables p
WHERE (p.owner_entity_id = totem_entity_id AND p.has_buildable_support = TRUE) OR p.id = totem_id;
SELECT array_agg(p.id)
INTO placeables_to_remove_totem_owner
FROM placeables p
WHERE p.owner_entity_id = totem_entity_id AND p.has_buildable_support = FALSE AND p.id != totem_id;
RETURN base_backup_save(
in_player_id,
totem_name,
building_pieces_to_link,
placeables_to_link,
placeables_to_remove_totem_owner
);
END;
$function$

View File

@@ -0,0 +1,11 @@
-- get_battlegroup_close_date() -> timestamp without time zone
-- oid: 58286 kind: FUNCTION category: battlegroup
CREATE OR REPLACE FUNCTION dune.get_battlegroup_close_date()
RETURNS timestamp without time zone
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN (SELECT farm_variables.battlegroup_close_date from farm_variables);
END
$function$

View File

@@ -0,0 +1,13 @@
-- set_battlegroup_close_date(in_close_date timestamp without time zone) -> timestamp without time zone
-- oid: 58589 kind: FUNCTION category: battlegroup
CREATE OR REPLACE FUNCTION dune.set_battlegroup_close_date(in_close_date timestamp without time zone)
RETURNS timestamp without time zone
LANGUAGE plpgsql
AS $function$
BEGIN
INSERT INTO farm_variables (one_row, battlegroup_close_date) VALUES (true,in_close_date)
ON CONFLICT (one_row) DO UPDATE SET battlegroup_close_date = in_close_date;
RETURN (select * from get_battlegroup_close_date());
END
$function$

View File

@@ -0,0 +1,16 @@
-- _building_validate_totem_owner_id(in_totem_owner_id bigint) -> bigint
-- oid: 58094 kind: FUNCTION category: building_blueprint
CREATE OR REPLACE FUNCTION dune._building_validate_totem_owner_id(in_totem_owner_id bigint)
RETURNS bigint
LANGUAGE sql
BEGIN ATOMIC
SELECT
CASE
WHEN (in_totem_owner_id = 0) THEN NULL::bigint
WHEN (EXISTS ( SELECT 1
FROM dune.fgl_entities
WHERE (fgl_entities.entity_id = _building_validate_totem_owner_id.in_totem_owner_id))) THEN in_totem_owner_id
ELSE NULL::bigint
END AS "case";
END

View File

@@ -0,0 +1,16 @@
-- _placeable_validate_totem_owner_id(in_totem_owner_id bigint) -> bigint
-- oid: 58112 kind: FUNCTION category: building_blueprint
CREATE OR REPLACE FUNCTION dune._placeable_validate_totem_owner_id(in_totem_owner_id bigint)
RETURNS bigint
LANGUAGE sql
BEGIN ATOMIC
SELECT
CASE
WHEN (in_totem_owner_id = 0) THEN NULL::bigint
WHEN (EXISTS ( SELECT 1
FROM dune.fgl_entities
WHERE (fgl_entities.entity_id = _placeable_validate_totem_owner_id.in_totem_owner_id))) THEN in_totem_owner_id
ELSE NULL::bigint
END AS "case";
END

View File

@@ -0,0 +1,11 @@
-- delete_building_blueprint(in_building_item_id bigint) -> void
-- oid: 58209 kind: FUNCTION category: building_blueprint
CREATE OR REPLACE FUNCTION dune.delete_building_blueprint(in_building_item_id bigint)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
DELETE FROM building_blueprints WHERE id = in_building_item_id;
END
$function$

View File

@@ -0,0 +1,33 @@
-- get_building_blueprint_copy_data(in_building_blueprint_id bigint) -> dune.buildingblueprintgetcopydata
-- oid: 58289 kind: FUNCTION category: building_blueprint
CREATE OR REPLACE FUNCTION dune.get_building_blueprint_copy_data(in_building_blueprint_id bigint)
RETURNS dune.buildingblueprintgetcopydata
LANGUAGE plpgsql
AS $function$
DECLARE
buildings_array BuildingBlueprintItem[];
placeables_array BuildingBlueprintPlaceableItem[];
pentashields_array BuildingBlueprintPentashieldItem[];
BEGIN
-- All Building Pieces
SELECT array_agg((instance_id, building_type, transform, provides_stability, health, hologram)::BuildingBlueprintItem)
into buildings_array
FROM building_blueprint_instances
WHERE building_blueprint_id = in_building_blueprint_id;
-- All Placeables
SELECT array_agg((placeable_id, building_type, transform, hologram)::BuildingBlueprintPlaceableItem)
into placeables_array
FROM building_blueprint_placeables
WHERE building_blueprint_id = in_building_blueprint_id;
-- Pentashields
SELECT array_agg((placeable_id, scale)::BuildingBlueprintPentashieldItem)
into pentashields_array
FROM building_blueprint_pentashields
WHERE building_blueprint_id = in_building_blueprint_id;
return ROW(buildings_array, placeables_array, pentashields_array)::BuildingBlueprintGetCopyData;
END
$function$

View File

@@ -0,0 +1,11 @@
-- get_building_favorites(in_account_id bigint) -> TABLE(building_types text[])
-- oid: 58290 kind: FUNCTION category: building_blueprint
CREATE OR REPLACE FUNCTION dune.get_building_favorites(in_account_id bigint)
RETURNS TABLE(building_types text[])
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
SELECT building_favorites.building_types FROM building_favorites WHERE account_id = in_account_id;
END; $function$

View File

@@ -0,0 +1,19 @@
-- get_building_id(in_actor_id bigint, in_class text) -> dune.buildinggetidcomposite
-- oid: 58291 kind: FUNCTION category: building_blueprint
CREATE OR REPLACE FUNCTION dune.get_building_id(in_actor_id bigint, in_class text)
RETURNS dune.buildinggetidcomposite
LANGUAGE plpgsql
AS $function$
BEGIN
IF not exists(select 1 from buildings where "id" = in_actor_id) THEN
if in_actor_id is null or in_actor_id = 0 then
in_actor_id := (SELECT assign_actor_id(in_class));
end if;
INSERT INTO buildings("id") VALUES(in_actor_id);
END IF;
return ROW(in_actor_id)::BuildingGetIdComposite;
END
$function$

View File

@@ -0,0 +1,20 @@
-- get_placeable_id(in_actor_id bigint, in_class text, in_building_type text) -> dune.placeablegetidcomposite
-- oid: 58330 kind: FUNCTION category: building_blueprint
CREATE OR REPLACE FUNCTION dune.get_placeable_id(in_actor_id bigint, in_class text, in_building_type text)
RETURNS dune.placeablegetidcomposite
LANGUAGE plpgsql
AS $function$
DECLARE
placeable_id BIGINT;
BEGIN
SELECT INTO placeable_id id FROM placeables WHERE "id" = in_actor_id;
IF placeable_id IS NULL THEN
SELECT assign_actor_id(in_class) id INTO placeable_id;
INSERT INTO placeables("id", "building_type") VALUES(placeable_id, in_building_type);
END IF;
return ROW(placeable_id)::PlaceableGetIdComposite;
END
$function$

View File

@@ -0,0 +1,11 @@
-- load_building(in_building_id bigint) -> dune.buildingsavedata
-- oid: 58449 kind: FUNCTION category: building_blueprint
CREATE OR REPLACE FUNCTION dune.load_building(in_building_id bigint)
RETURNS dune.buildingsavedata
LANGUAGE sql
BEGIN ATOMIC
RETURN ( SELECT ROW(array_agg(ROW(building_instances.instance_id, building_instances.building_type, building_instances.transform, building_instances.owner_entity_id, building_instances.building_flags, building_instances.health, building_instances.shelter, building_instances.stabilization_begin_timespan, building_instances.stabilization_end_timespan, building_instances.stabilization_state, building_instances.sand_buildup)::dune.buildinginstance), ARRAY[]::integer[], ARRAY[]::dune.buildinginstanceupdateowner[], ARRAY[]::dune.buildinginstanceupdatestabilization[], ARRAY[]::dune.buildinginstanceupdatehealth[], ARRAY[]::dune.buildinginstanceupdateshelter[], ARRAY[]::dune.buildinginstanceupdatesandbuildup[], ARRAY[]::dune.buildinginstanceupdatebuildingflags[], ARRAY[]::dune.buildinginstanceupdatetransform[])::dune.buildingsavedata AS "row"
FROM dune.building_instances
WHERE (building_instances.building_id = load_building.in_building_id));
END

View File

@@ -0,0 +1,23 @@
-- load_placeable(in_placeable_id bigint) -> dune.placeablesavedata
-- oid: 58460 kind: FUNCTION category: building_blueprint
CREATE OR REPLACE FUNCTION dune.load_placeable(in_placeable_id bigint)
RETURNS dune.placeablesavedata
LANGUAGE plpgsql
AS $function$
DECLARE
result PlaceableSaveData;
BEGIN
SELECT
owner_entity_id as in_owner_entity_id,
health as in_health,
building_type as in_building_type,
has_hit_ground as in_has_hit_ground,
has_buildable_support as in_has_buildable_support,
is_hologram as in_is_hologram
INTO result
FROM placeables
WHERE id = in_placeable_id;
return result;
END
$function$

View File

@@ -0,0 +1,21 @@
-- load_totem(in_id bigint) -> dune.totemsavedata
-- oid: 58464 kind: FUNCTION category: building_blueprint
CREATE OR REPLACE FUNCTION dune.load_totem(in_id bigint)
RETURNS dune.totemsavedata
LANGUAGE plpgsql
AS $function$
DECLARE
result TotemSaveData;
BEGIN
SELECT
landclaim_vertical_level,
last_backup_timestamp,
landclaim_original_global_location,
landclaim_original_global_yaw_rotation
INTO result
FROM totems
WHERE id = in_id;
return result;
END
$function$

View File

@@ -0,0 +1,143 @@
-- save_building(in_building_id bigint, in_data dune.buildingsavedata) -> void
-- oid: 58543 kind: FUNCTION category: building_blueprint
CREATE OR REPLACE FUNCTION dune.save_building(in_building_id bigint, in_data dune.buildingsavedata)
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
instance BUILDINGINSTANCE;
instance_to_remove INTEGER;
instance_owner BuildingInstanceUpdateOwner;
BEGIN
-- ADD
IF array_length(in_data.in_add_building_data, 1) > 0 THEN
INSERT INTO building_instances(
"building_id",
"instance_id",
"building_type",
"transform",
"owner_entity_id",
"building_flags",
"health",
"shelter",
"stabilization_begin_timespan",
"stabilization_end_timespan",
"stabilization_state",
"sand_buildup"
)
SELECT
in_building_id,
add_data.instance_id,
add_data.building_type,
add_data.transform,
_building_validate_totem_owner_id(add_data.owner_entity_id),
add_data.building_flags,
add_data.health,
add_data.shelter,
add_data.stabilization_begin_timespan,
add_data.stabilization_end_timespan,
add_data.stabilization_state,
add_data.sand_buildup
FROM unnest(in_data.in_add_building_data) as add_data
ON CONFLICT ("building_id", "instance_id")
DO UPDATE SET
"building_type" = (instance).building_type,
"transform" = (instance).transform,
"owner_entity_id" = _building_validate_totem_owner_id((instance).owner_entity_id),
"building_flags" = (instance).building_flags,
"health" = (instance).health,
"shelter" = (instance).shelter,
"stabilization_begin_timespan" = (instance).stabilization_begin_timespan,
"stabilization_end_timespan" = (instance).stabilization_end_timespan,
"stabilization_state" = (instance).stabilization_state,
"sand_buildup" = (instance).sand_buildup;
END IF;
-- REMOVE
IF array_length(in_data.in_remove_building_data, 1) > 0 THEN
DELETE FROM building_instances
WHERE building_instances."building_id" = in_building_id AND building_instances."instance_id" = ANY(in_data.in_remove_building_data);
END IF;
-- OWNER. 99.99% of the time, this will only have 1 Owner Array.
IF array_length(in_data.in_building_owner_data, 1) > 0 THEN
FOREACH instance_owner IN ARRAY in_data.in_building_owner_data LOOP
WITH owner_changes_table AS
(
SELECT unnest(instance_owner.instances) AS instance_id, instance_owner.owner_entity_id AS owner_entity_id
)
UPDATE building_instances
SET owner_entity_id = _building_validate_totem_owner_id(owner_changes_table.owner_entity_id)
FROM owner_changes_table
WHERE building_instances.building_id = in_building_id AND building_instances.instance_id = owner_changes_table.instance_id;
END LOOP;
END IF;
-- STABILIZATION
IF array_length(in_data.in_building_stabilization_data, 1) > 0 THEN
WITH stabilization_changes_table AS
(
select * FROM unnest(in_data.in_building_stabilization_data)
)
UPDATE building_instances SET stabilization_begin_timespan = stabilization_changes_table.stabilization_begin_timespan, stabilization_end_timespan = stabilization_changes_table.stabilization_end_timespan, stabilization_state = stabilization_changes_table.stabilization_state
FROM stabilization_changes_table
WHERE building_instances.building_id = in_building_id AND building_instances.instance_id = stabilization_changes_table.instance_id;
END IF;
-- HEALTH
IF array_length(in_data.in_building_health_data, 1) > 0 THEN
WITH health_changes_table AS
(
select * FROM unnest(in_data.in_building_health_data)
)
UPDATE building_instances SET health = health_changes_table.health
FROM health_changes_table
WHERE building_instances.building_id = in_building_id AND building_instances.instance_id = health_changes_table.instance_id;
END IF;
-- SHELTER
IF array_length(in_data.in_building_shelter_data, 1) > 0 THEN
WITH shelter_changes_table AS
(
select * FROM unnest(in_data.in_building_shelter_data)
)
UPDATE building_instances SET shelter = shelter_changes_table.shelter
FROM shelter_changes_table
WHERE building_instances.building_id = in_building_id AND building_instances.instance_id = shelter_changes_table.instance_id;
END IF;
-- SAND BUILDUP
IF array_length(in_data.in_building_sand_buildup_data, 1) > 0 THEN
WITH sand_buildup_changes_table AS
(
select * FROM unnest(in_data.in_building_sand_buildup_data)
)
UPDATE building_instances SET sand_buildup = sand_buildup_changes_table.sand_buildup
FROM sand_buildup_changes_table
WHERE building_instances.building_id = in_building_id AND building_instances.instance_id = sand_buildup_changes_table.instance_id;
END IF;
-- BUILDING FLAGS
IF array_length(in_data.in_building_building_flags_data, 1) > 0 THEN
WITH building_flags_changes_table AS
(
select * FROM unnest(in_data.in_building_building_flags_data)
)
UPDATE building_instances SET building_flags = building_flags_changes_table.building_flags
FROM building_flags_changes_table
WHERE building_instances.building_id = in_building_id AND building_instances.instance_id = building_flags_changes_table.instance_id;
END IF;
-- BUILDING TRANSFORM
IF array_length(in_data.in_building_building_transform_data, 1) > 0 THEN
WITH building_flags_transform_table AS
(
select * FROM unnest(in_data.in_building_building_transform_data)
)
UPDATE building_instances SET transform = building_flags_transform_table.transform
FROM building_flags_transform_table
WHERE building_instances.building_id = in_building_id AND building_instances.instance_id = building_flags_transform_table.instance_id;
END IF;
END
$function$

View File

@@ -0,0 +1,50 @@
-- save_building_blueprint_copy(in_building_item_id bigint, in_building_blueprint_id bigint, in_building_blueprint_building_data dune.buildingblueprintpiecesaveitemcontainer[], in_building_blueprint_placeable_data dune.buildingblueprintplaceablesaveitemcontainer[], in_building_blueprint_pentashield_data dune.buildingblueprintpentashielditem[]) -> bigint
-- oid: 58544 kind: FUNCTION category: building_blueprint
CREATE OR REPLACE FUNCTION dune.save_building_blueprint_copy(in_building_item_id bigint, in_building_blueprint_id bigint, in_building_blueprint_building_data dune.buildingblueprintpiecesaveitemcontainer[], in_building_blueprint_placeable_data dune.buildingblueprintplaceablesaveitemcontainer[], in_building_blueprint_pentashield_data dune.buildingblueprintpentashielditem[])
RETURNS bigint
LANGUAGE plpgsql
AS $function$
DECLARE
return_id BIGINT;
BEGIN
IF in_building_blueprint_id != 0 THEN
DELETE FROM building_blueprints WHERE id = in_building_blueprint_id;
END IF;
INSERT INTO building_blueprints(id, item_id, player_id, building_blueprint_map)
VALUES(DEFAULT, in_building_item_id, NULL, '') RETURNING id INTO return_id;
-- All Building Pieces
INSERT INTO building_blueprint_instances(building_blueprint_id, instance_id, building_type, transform, provides_stability, health, hologram)
SELECT
return_id,
piece_data.instance_id,
container_data.building_type,
piece_data.transform,
piece_data.provides_stability,
piece_data.health,
True
FROM
unnest(in_building_blueprint_building_data) AS container_data
CROSS JOIN LATERAL unnest(container_data.building_pieces) AS piece_data;
-- All Placeables
INSERT INTO building_blueprint_placeables(building_blueprint_id, placeable_id, building_type, transform, hologram)
SELECT
return_id,
placeable_data.placeable_id,
container_data.building_type,
placeable_data.transform,
True
FROM
unnest(in_building_blueprint_placeable_data) AS container_data
CROSS JOIN LATERAL unnest(container_data.placeables) AS placeable_data;
-- Pentashields
INSERT INTO building_blueprint_pentashields("building_blueprint_id", "placeable_id", "scale")
SELECT return_id as building_blueprint_id, placeable_id, scale FROM unnest(in_building_blueprint_pentashield_data);
RETURN return_id;
END
$function$

View File

@@ -0,0 +1,10 @@
-- save_placeable(in_placeable_id bigint, in_data dune.placeablesavedata) -> void
-- oid: 58561 kind: FUNCTION category: building_blueprint
CREATE OR REPLACE FUNCTION dune.save_placeable(in_placeable_id bigint, in_data dune.placeablesavedata)
RETURNS void
LANGUAGE sql
BEGIN ATOMIC
INSERT INTO dune.placeables (id, owner_entity_id, health, building_type, has_hit_ground, has_buildable_support, is_hologram)
VALUES (save_placeable.in_placeable_id, dune._placeable_validate_totem_owner_id((save_placeable.in_data).in_owner_entity_id), (save_placeable.in_data).in_health, (save_placeable.in_data).in_building_type, (save_placeable.in_data).in_has_hit_ground, (save_placeable.in_data).in_has_buildable_support, (save_placeable.in_data).in_is_hologram) ON CONFLICT(id) DO UPDATE SET owner_entity_id = excluded.owner_entity_id, health = excluded.health, building_type = excluded.building_type, has_hit_ground = excluded.has_hit_ground, has_buildable_support = excluded.has_buildable_support, is_hologram = excluded.is_hologram;
END

View File

@@ -0,0 +1,10 @@
-- save_totem(in_id bigint, in_data dune.totemsavedata) -> void
-- oid: 58571 kind: FUNCTION category: building_blueprint
CREATE OR REPLACE FUNCTION dune.save_totem(in_id bigint, in_data dune.totemsavedata)
RETURNS void
LANGUAGE sql
BEGIN ATOMIC
INSERT INTO dune.totems (id, landclaim_vertical_level, last_backup_timestamp, landclaim_original_global_location, landclaim_original_global_yaw_rotation)
VALUES (save_totem.in_id, (save_totem.in_data).landclaim_vertical_level, (save_totem.in_data).last_backup_timestamp, (save_totem.in_data).landclaim_original_global_location, (save_totem.in_data).landclaim_original_global_yaw_rotation) ON CONFLICT(id) DO UPDATE SET landclaim_vertical_level = excluded.landclaim_vertical_level, last_backup_timestamp = excluded.last_backup_timestamp, landclaim_original_global_location = excluded.landclaim_original_global_location, landclaim_original_global_yaw_rotation = excluded.landclaim_original_global_yaw_rotation;
END

View File

@@ -0,0 +1,12 @@
-- update_server_building_favorites(in_account_id bigint, in_building_types text[]) -> void
-- oid: 58635 kind: FUNCTION category: building_blueprint
CREATE OR REPLACE FUNCTION dune.update_server_building_favorites(in_account_id bigint, in_building_types text[])
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
INSERT INTO building_favorites(account_id, building_types)
VALUES(in_account_id, in_building_types)
ON CONFLICT(account_id) DO UPDATE SET building_types = in_building_types WHERE building_favorites.account_id = in_account_id;
END; $function$

View File

@@ -0,0 +1,12 @@
-- update_server_learned_building_sets(in_account_id bigint, in_learned_building_sets text[]) -> void
-- oid: 58636 kind: FUNCTION category: building_blueprint
CREATE OR REPLACE FUNCTION dune.update_server_learned_building_sets(in_account_id bigint, in_learned_building_sets text[])
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
INSERT INTO building_progression(account_id, learned_building_sets)
VALUES(in_account_id, in_learned_building_sets)
ON CONFLICT(account_id) DO UPDATE SET learned_building_sets = in_learned_building_sets WHERE building_progression.account_id = in_account_id;
END; $function$

View File

@@ -0,0 +1,14 @@
-- delete_character(in_actor_id bigint) -> void
-- oid: 58210 kind: FUNCTION category: character_mod
CREATE OR REPLACE FUNCTION dune.delete_character(in_actor_id bigint)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
DELETE FROM actors WHERE id = in_actor_id;
DELETE FROM properties WHERE object_id = in_actor_id;
DELETE FROM fgl_data WHERE object_id = in_actor_id;
DELETE FROM actor_transform WHERE actor_id = in_actor_id;
END
$function$

View File

@@ -0,0 +1,16 @@
-- initialize_specialization_keystones(in_keystones text[]) -> TABLE(keystone_id smallint, keystone_name text)
-- oid: 58388 kind: FUNCTION category: character_mod
CREATE OR REPLACE FUNCTION dune.initialize_specialization_keystones(in_keystones text[])
RETURNS TABLE(keystone_id smallint, keystone_name text)
LANGUAGE plpgsql
AS $function$
BEGIN
LOCK TABLE specialization_keystones_map IN SHARE ROW EXCLUSIVE MODE;
-- Note: we filter the existing values before the insert, otherwise it bumps the generated id in specialization_keystones_map
INSERT INTO specialization_keystones_map (name)
SELECT in_keystone_name FROM UNNEST(in_keystones) in_keystone_name LEFT JOIN specialization_keystones_map k ON in_keystone_name = k.name
WHERE name IS NULL;
RETURN QUERY SELECT * from specialization_keystones_map;
END $function$

View File

@@ -0,0 +1,166 @@
-- login_account(in_user_id text, in_funcom_id text, in_platform_id text, in_platform_name text, in_minimum_returning_player_time_seconds integer, in_character_name text, in_return_dimension_index integer, in_home_dimension_index integer) -> SETOF dune.playerdescription
-- oid: 58471 kind: FUNCTION category: character_mod
CREATE OR REPLACE FUNCTION dune.login_account(in_user_id text, in_funcom_id text, in_platform_id text, in_platform_name text, in_minimum_returning_player_time_seconds integer, in_character_name text, in_return_dimension_index integer, in_home_dimension_index integer)
RETURNS SETOF dune.playerdescription
LANGUAGE plpgsql
AS $function$
DECLARE
user_account_id BigInt;
BEGIN
PERFORM update_returning_player_status(in_user_id, in_minimum_returning_player_time_seconds);
return query with
acc as (
INSERT INTO encrypted_accounts("id", "user", "platform_id", "platform_name", "encrypted_funcom_id")
VALUES (default, in_user_id, in_platform_id, in_platform_name, encrypt_user_data(in_funcom_id))
ON CONFLICT ("user") DO UPDATE SET
encrypted_funcom_id = excluded.encrypted_funcom_id,
platform_id = excluded.platform_id,
platform_name = excluded.platform_name
RETURNING id, encrypted_accounts.user
),
actor_ids as (
-- TODO: unite this with accounts. One table to rule them all (until we want multiple chars per account)
SELECT
coalesce(player_controller_id, nextval('actors_id_seq')) as controller,
coalesce(player_state_id, nextval('actors_id_seq')) as state,
coalesce(player_pawn_id, nextval('actors_id_seq')) as pawn
from acc left join player_state on player_state.account_id = acc.id
),
actors_insert as (
INSERT INTO actors("id", "owner_account_id")
select unnest(array[controller, pawn, state]), acc.id from actor_ids, acc
ON CONFLICT DO NOTHING
returning id
),
insert_actor_audit_log as (
insert into actor_audit("id", "class")
select
unnest(array[controller, pawn, state]) as id,
unnest(array['Controller', 'Pawn', 'State']) as clas
from actor_ids
on conflict do nothing
),
demo as (
UPDATE demo_users
SET demo_state = CASE
WHEN demo_playtime_seconds IS NOT NULL THEN 'Demo'::DemoState
ELSE demo_state
END
WHERE fls_id = in_user_id
RETURNING fls_id, demo_playtime_seconds, demo_state
),
player_state_insert as (
INSERT INTO encrypted_player_state(
"account_id", "encrypted_character_name", "online_status",
"player_controller_id", "player_pawn_id", "player_state_id",
"return_dimension_index", "home_dimension_index", "last_login_time"
)
select
id, case
when in_character_name is not null then encrypt_user_data(in_character_name)
when encrypted_player_state.encrypted_character_name is null then encrypt_user_data('<TEMP>')
else encrypted_player_state.encrypted_character_name
end,
'Online', controller, pawn, state, in_return_dimension_index, in_home_dimension_index, now()
from acc left join encrypted_player_state on acc.id = encrypted_player_state.account_id, actor_ids
ON CONFLICT ("account_id")
DO UPDATE SET
online_status = 'Online',
"return_dimension_index" = coalesce(in_return_dimension_index, encrypted_player_state.return_dimension_index),
"home_dimension_index" = coalesce(in_home_dimension_index, encrypted_player_state.home_dimension_index),
"last_login_time" = now()
RETURNING
account_id,
"return_dimension_index",
"home_dimension_index"
),
inserted_count_dummy as (
select count(*) from actors_insert
),
player_actors as (
select array_agg(full_actors.*) as actors
from
-- We need to refer 'returning' from inserts to ensure order of with statements
inserted_count_dummy,
actor_ids,
load_full_actors(array[actor_ids.controller, actor_ids.state, actor_ids.pawn]) as full_actors
),
pawn_info as (
select id, (map, partition_id, dimension_index)::ServerInfo as server_info
from actor_ids join actors on actors.id=actor_ids.pawn
),
respawn_locations as (
SELECT acc.id as account_id, get_respawn_locations(acc.id) as locations
FROM acc
),
this_player_tags as (
select
acc.id as account_id,
array_agg(tag) as tags
from acc join player_tags as tgs on tgs.account_id=acc.id
group by acc.id
),
keystones as (
select player_id, array_agg(keystone_id) as purchased_keystones
from purchased_specialization_keystones
group by player_id
),
tracks as (
select player_id, array_agg(track_info) as progression_tracks
from (
select player_id, (track_type, xp_amount, level)::SpecializationTrackInfo as track_info
from specialization_tracks
)
group by player_id
),
journey_nodes as (
SELECT acc.id as account_id, get_login_journey_nodes(acc.id) as journey_nodes_data
FROM acc
),
journey_nodes_cooldown as (
SELECT acc.id as account_id, get_login_journey_nodes_cooldown(acc.id) as journey_nodes_cooldown_data
FROM acc
)
select
acc.id,
player_actors.actors[1], player_actors.actors[2], player_actors.actors[3],
coalesce(pawn_info.server_info, (null, null, null)::ServerInfo),
(
coalesce(respawn_locations.locations, array[]::RespawnLocation[]),
player_state.pending_respawn_location_id
)::RespawnInfo,
coalesce(player_state.life_state, 'Alive'),
coalesce(this_player_tags.tags, array[]::Text[]),
player_state_insert.return_dimension_index,
player_state.death_location,
player_state_insert.home_dimension_index,
demo.demo_state,
demo.demo_playtime_seconds,
(progression_tracks, purchased_keystones, refund_id)::SpecializationInfo,
(
coalesce(journey_nodes.journey_nodes_data, array[]::JourneyNodeInfo[]),
coalesce(journey_nodes_cooldown.journey_nodes_cooldown_data, array[]::JourneyNodeCooldownInfo[]),
coalesce(journey_tracked_cards.tracked_journey_card, ''),
coalesce(journey_tracked_cards.tracked_landsraad_card, '')
)::JourneyInfo,
(player_state.last_returning_player_event_time AT TIME ZONE 'UTC')::TIMESTAMP,
(player_state.last_returning_player_awarded_time AT TIME ZONE 'UTC')::TIMESTAMP
from
acc left join player_state on player_state.account_id = acc.id
left join respawn_locations on respawn_locations.account_id = acc.id
left join this_player_tags on this_player_tags.account_id = acc.id
left join player_state_insert on player_state_insert.account_id = acc.id
left join demo on demo.fls_id = acc.user
left join journey_nodes on journey_nodes.account_id = acc.id
left join journey_nodes_cooldown on journey_nodes_cooldown.account_id = acc.id
left join journey_tracked_cards on journey_tracked_cards.player_id = player_state.player_controller_id
left join keystones on keystones.player_id = player_state.player_controller_id
left join tracks on tracks.player_id = player_state.player_controller_id
left join specialization_refund_id on specialization_refund_id.player_id = player_state.player_controller_id,
player_actors left join pawn_info on (player_actors.actors[3].id = pawn_info.id)
limit 1;
END
$function$

View File

@@ -0,0 +1,28 @@
-- permission_set_player_rank(in_actor_id bigint, in_player_id bigint, in_rank smallint, in_map_id text) -> void
-- oid: 58493 kind: FUNCTION category: character_mod
CREATE OR REPLACE FUNCTION dune.permission_set_player_rank(in_actor_id bigint, in_player_id bigint, in_rank smallint, in_map_id text)
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
found_actor_id BIGINT;
found_guild_id BIGINT;
BEGIN
SELECT permission_actor_id FROM permission_actor_rank WHERE permission_actor_id = in_actor_id AND player_id = in_player_id INTO found_actor_id;
IF NOT FOUND THEN
INSERT INTO permission_actor_rank("permission_actor_id", "player_id", "rank") VALUES(in_actor_id, in_player_id, in_rank);
ELSE
UPDATE permission_actor_rank SET rank = in_rank WHERE permission_actor_rank.permission_actor_id = in_actor_id AND player_id = in_player_id;
END IF;
SELECT guild_id FROM guild_members WHERE player_id = in_actor_id INTO found_guild_id;
IF NOT FOUND THEN
found_guild_id := 0;
END IF;
PERFORM permission_actor_create_or_update_base_marker(in_actor_id, in_player_id, in_rank);
PERFORM pg_notify('permission_notify_channel', format('set_rank#{"ActorId" : %s , "PlayerId" : %s, "PlayerGuildId" : %s, "Rank" : %s, "Map" : %s}', in_actor_id, in_player_id, found_guild_id, in_rank, in_map_id));
END
$function$

View File

@@ -0,0 +1,47 @@
-- player_state_update(in_data dune.playerstateupdatedata[]) -> void
-- oid: 58495 kind: FUNCTION category: character_mod
CREATE OR REPLACE FUNCTION dune.player_state_update(in_data dune.playerstateupdatedata[])
RETURNS void
LANGUAGE sql
AS $function$
-- online -> offline
with
update_data as (select * from unnest(in_data))
update encrypted_player_state as ps
set online_status = update_data.online_status
from update_data
where ps.player_controller_id = update_data.player_controller_id
and ps.server_id = update_data.current_server_id -- make sure we don't update if the player is already online somewhere else
and update_data.online_status != 'Online'
and ps.online_status != update_data.online_status; -- avoid unnecessary data changes
-- offline -> online
with
update_data as (select * from unnest(in_data))
update encrypted_player_state as ps
set online_status = update_data.online_status,
server_id = update_data.current_server_id
from update_data
where ps.player_controller_id = update_data.player_controller_id
and update_data.online_status = 'Online'
and (ps.server_id is null or ps.server_id != update_data.current_server_id or ps.online_status != update_data.online_status); -- avoid unnecessary data changes
with
update_data as (select * from unnest(in_data))
update encrypted_player_state as ps
set reconnect_grace_period_end = update_data.reconnect_grace_period_end
from update_data
where ps.player_controller_id = update_data.player_controller_id
and not update_data.reconnect_grace_period_end is null;
with
update_data as (select * from unnest(in_data))
update encrypted_player_state as ps
set
last_avatar_activity = (update_data.on_disconnect).last_online_time AT TIME ZONE 'UTC',
previous_server_partition_id = (update_data.on_disconnect).previous_server_partition_id
from update_data
where ps.player_controller_id = update_data.player_controller_id
and not update_data.on_disconnect is null;
$function$

View File

@@ -0,0 +1,26 @@
-- purchase_specialization_keystone(in_player_id bigint, in_keystone text) -> boolean
-- oid: 58501 kind: FUNCTION category: character_mod
CREATE OR REPLACE FUNCTION dune.purchase_specialization_keystone(in_player_id bigint, in_keystone text)
RETURNS boolean
LANGUAGE plpgsql
AS $function$
DECLARE
found_id SMALLINT;
inserted_id SMALLINT;
BEGIN
SELECT id FROM specialization_keystones_map INTO found_id WHERE name = in_keystone;
IF found_id IS NULL THEN
RETURN FALSE;
END IF;
INSERT INTO purchased_specialization_keystones (player_id, keystone_id) VALUES (in_player_id, found_id)
ON CONFLICT DO NOTHING
RETURNING keystone_id INTO inserted_id;
IF inserted_id IS NULL THEN
RETURN FALSE;
END IF;
RETURN TRUE;
END $function$

View File

@@ -0,0 +1,10 @@
-- reset_specialization_keystones(in_player_id bigint) -> void
-- oid: 58532 kind: FUNCTION category: character_mod
CREATE OR REPLACE FUNCTION dune.reset_specialization_keystones(in_player_id bigint)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
DELETE FROM purchased_specialization_keystones WHERE player_id = in_player_id;
END $function$

View File

@@ -0,0 +1,10 @@
-- reset_specialization_tracks(in_player_id bigint) -> void
-- oid: 58533 kind: FUNCTION category: character_mod
CREATE OR REPLACE FUNCTION dune.reset_specialization_tracks(in_player_id bigint)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
DELETE FROM specialization_tracks WHERE player_id = in_player_id;
END $function$

View File

@@ -0,0 +1,9 @@
-- returning_player_award_given(in_account_id bigint) -> void
-- oid: 58537 kind: FUNCTION category: character_mod
CREATE OR REPLACE FUNCTION dune.returning_player_award_given(in_account_id bigint)
RETURNS void
LANGUAGE sql
AS $function$
UPDATE player_state SET last_returning_player_awarded_time=now(), last_returning_player_event_time=NULL WHERE account_id=in_account_id;
$function$

View File

@@ -0,0 +1,15 @@
-- set_character_import_state(in_fls_id text, in_state dune.transferimportstate) -> void
-- oid: 58590 kind: FUNCTION category: character_mod
CREATE OR REPLACE FUNCTION dune.set_character_import_state(in_fls_id text, in_state dune.transferimportstate)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
INSERT INTO character_transfer_imports (fls_id, last_update, transfer_state)
VALUES (in_fls_id, now(), in_state)
ON CONFLICT (fls_id) DO UPDATE
SET last_update = now(),
transfer_state = EXCLUDED.transfer_state;
END;
$function$

View File

@@ -0,0 +1,9 @@
-- set_character_name(in_account_id bigint, in_name text) -> void
-- oid: 58591 kind: FUNCTION category: character_mod
CREATE OR REPLACE FUNCTION dune.set_character_name(in_account_id bigint, in_name text)
RETURNS void
LANGUAGE sql
AS $function$
update encrypted_player_state set encrypted_character_name=encrypt_user_data(in_name) where account_id=in_account_id;
$function$

View File

@@ -0,0 +1,11 @@
-- set_players_from_server_ids_offline(in_server_ids text[]) -> void
-- oid: 58595 kind: FUNCTION category: character_mod
CREATE OR REPLACE FUNCTION dune.set_players_from_server_ids_offline(in_server_ids text[])
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
UPDATE player_state SET online_status = 'Offline', last_avatar_activity = current_timestamp WHERE online_status <> 'Offline' AND server_id = ANY(in_server_ids);
END
$function$

View File

@@ -0,0 +1,11 @@
-- set_specialization_xp_and_level(in_player_id bigint, in_track_type dune.specializationtracktype, in_xp_amount integer, in_level real) -> void
-- oid: 58596 kind: FUNCTION category: character_mod
CREATE OR REPLACE FUNCTION dune.set_specialization_xp_and_level(in_player_id bigint, in_track_type dune.specializationtracktype, in_xp_amount integer, in_level real)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
INSERT INTO specialization_tracks (player_id, track_type, xp_amount, level) VALUES (in_player_id, in_track_type, in_xp_amount, in_level)
ON CONFLICT(player_id, track_type) DO UPDATE SET xp_amount = in_xp_amount, level = in_level;
END $function$

View File

@@ -0,0 +1,10 @@
-- update_player_tags(in_account_id bigint, tags_to_add text[], tags_to_remove text[]) -> void
-- oid: 58629 kind: FUNCTION category: character_mod
CREATE OR REPLACE FUNCTION dune.update_player_tags(in_account_id bigint, tags_to_add text[], tags_to_remove text[])
RETURNS void
LANGUAGE sql
AS $function$
insert into player_tags("account_id", "tag") select in_account_id, unnest(tags_to_add) on conflict do nothing;
delete from player_tags where account_id = in_account_id and tag = ANY(tags_to_remove);
$function$

View File

@@ -0,0 +1,26 @@
-- update_returning_player_status(in_user_id text, in_minimum_returning_player_time_seconds integer) -> void
-- oid: 58633 kind: FUNCTION category: character_mod
CREATE OR REPLACE FUNCTION dune.update_returning_player_status(in_user_id text, in_minimum_returning_player_time_seconds integer)
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
user_account_id BigInt;
last_login_time TIMESTAMPTZ;
last_award_time TIMESTAMPTZ;
BEGIN
SELECT INTO user_account_id, last_login_time, last_award_time id, ps.last_login_time, ps.last_returning_player_awarded_time
FROM accounts acc
JOIN player_state ps ON ps.account_id = acc.id
WHERE acc.user=in_user_id;
IF user_account_id IS NOT NULL THEN
IF last_award_time + INTERVAL '1 second' * in_minimum_returning_player_time_seconds > CURRENT_TIMESTAMP THEN
UPDATE player_state SET last_returning_player_event_time=NULL WHERE account_id=user_account_id;
ELSIF last_login_time + INTERVAL '1 second' * in_minimum_returning_player_time_seconds < CURRENT_TIMESTAMP THEN
UPDATE player_state SET last_returning_player_event_time=now() WHERE account_id=user_account_id;
END IF;
END IF;
END
$function$

View File

@@ -0,0 +1,13 @@
-- update_specialization_refund_id(in_player_id bigint, in_refund_id smallint, in_removed_keystones smallint[]) -> void
-- oid: 58638 kind: FUNCTION category: character_mod
CREATE OR REPLACE FUNCTION dune.update_specialization_refund_id(in_player_id bigint, in_refund_id smallint, in_removed_keystones smallint[])
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
DELETE FROM purchased_specialization_keystones WHERE player_id = in_player_id AND keystone_id = ANY(in_removed_keystones);
INSERT INTO specialization_refund_id (player_id, refund_id) VALUES(in_player_id, in_refund_id)
ON conflict (player_id) DO UPDATE SET refund_id = in_refund_id;
END $function$

View File

@@ -0,0 +1,12 @@
-- cleanup_orphaned_entities() -> trigger
-- oid: 58173 kind: FUNCTION category: cleanup
CREATE OR REPLACE FUNCTION dune.cleanup_orphaned_entities()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
DELETE FROM fgl_entities WHERE fgl_entities.entity_id = OLD.entity_id;
RETURN NULL;
END
$function$

View File

@@ -0,0 +1,12 @@
-- reset_all_players_from_server_ids_grace_period_and_logoff_timer(in_server_id text, in_reset_time timestamp without time zone) -> void
-- oid: 58528 kind: FUNCTION category: cleanup
CREATE OR REPLACE FUNCTION dune.reset_all_players_from_server_ids_grace_period_and_logoff_timer(in_server_id text, in_reset_time timestamp without time zone)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
UPDATE encrypted_player_state SET reconnect_grace_period_end = in_reset_time WHERE server_id = in_server_id AND reconnect_grace_period_end > in_reset_time;
UPDATE encrypted_player_state SET logoff_persistence_end_time = in_reset_time WHERE server_id = in_server_id AND logoff_persistence_end_time > in_reset_time;
END
$function$

View File

@@ -0,0 +1,13 @@
-- reset_server_all_player_access_codes(in_account_id bigint) -> void
-- oid: 58531 kind: FUNCTION category: cleanup
CREATE OR REPLACE FUNCTION dune.reset_server_all_player_access_codes(in_account_id bigint)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
DELETE FROM player_access_codes
WHERE account_id = in_account_id
AND is_resettable = true;
END
$function$

View File

@@ -0,0 +1,11 @@
-- wipe_old_events_log(in_days_limit integer) -> void
-- oid: 58650 kind: FUNCTION category: cleanup
CREATE OR REPLACE FUNCTION dune.wipe_old_events_log(in_days_limit integer)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
DELETE FROM game_events WHERE universe_time < to_timestamp(in_days_limit);
END
$function$

View File

@@ -0,0 +1,14 @@
-- load_communinet_player_data(in_account_id bigint) -> TABLE(is_active boolean, selected_channel_name text, channel_name text, is_tuned boolean)
-- oid: 58450 kind: FUNCTION category: communinet
CREATE OR REPLACE FUNCTION dune.load_communinet_player_data(in_account_id bigint)
RETURNS TABLE(is_active boolean, selected_channel_name text, channel_name text, is_tuned boolean)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
SELECT cp.is_active, cp.selected_channel_name, cpc.channel_name, cpc.is_tuned
FROM communinet_player AS cp JOIN communinet_player_channels as cpc
ON cp.account_id = cpc.account_id
WHERE cpc.account_id = in_account_id;
END; $function$

View File

@@ -0,0 +1,11 @@
-- remove_communinet_player_channel(in_account_id bigint, in_channel_name text) -> void
-- oid: 58517 kind: FUNCTION category: communinet
CREATE OR REPLACE FUNCTION dune.remove_communinet_player_channel(in_account_id bigint, in_channel_name text)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
DELETE FROM communinet_player_channels WHERE account_id = in_account_id AND channel_name = in_channel_name;
END
$function$

View File

@@ -0,0 +1,11 @@
-- update_communinet_player_channel(in_account_id bigint, in_channel_name text, in_is_tuned boolean) -> void
-- oid: 58615 kind: FUNCTION category: communinet
CREATE OR REPLACE FUNCTION dune.update_communinet_player_channel(in_account_id bigint, in_channel_name text, in_is_tuned boolean)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
INSERT INTO communinet_player_channels(account_id, channel_name, is_tuned) VALUES (in_account_id, in_channel_name, in_is_tuned)
ON CONFLICT(account_id, channel_name) DO UPDATE SET is_tuned = in_is_tuned WHERE communinet_player_channels.account_id = in_account_id AND communinet_player_channels.channel_name = in_channel_name;
END $function$

View File

@@ -0,0 +1,11 @@
-- update_communinet_player_data(in_account_id bigint, in_is_active boolean, in_selected_channel_name text) -> void
-- oid: 58616 kind: FUNCTION category: communinet
CREATE OR REPLACE FUNCTION dune.update_communinet_player_data(in_account_id bigint, in_is_active boolean, in_selected_channel_name text)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
INSERT INTO communinet_player(account_id, is_active, selected_channel_name) VALUES (in_account_id, in_is_active, in_selected_channel_name)
ON CONFLICT(account_id) DO UPDATE SET is_active = in_is_active, selected_channel_name = in_selected_channel_name WHERE communinet_player.account_id = in_account_id;
END $function$

View File

@@ -0,0 +1,46 @@
-- adjust_player_virtual_currency_balance(in_controller_id bigint, in_currency_id smallint, in_delta bigint) -> bigint
-- oid: 58129 kind: FUNCTION category: currency
CREATE OR REPLACE FUNCTION dune.adjust_player_virtual_currency_balance(in_controller_id bigint, in_currency_id smallint, in_delta bigint)
RETURNS bigint
LANGUAGE plpgsql
AS $function$
DECLARE
current_balance BIGINT;
current_delta BIGINT;
new_delta BIGINT;
fls_id TEXT;
function_oid oid;
BEGIN
SELECT INTO current_balance balance from player_virtual_currency_balances WHERE player_controller_id = in_controller_id AND currency_id = in_currency_id;
INSERT INTO player_virtual_currency_balances("player_controller_id", "currency_id", "balance")
VALUES (in_controller_id, in_currency_id, in_delta)
ON CONFLICT (player_controller_id, currency_id) DO UPDATE SET balance = (player_virtual_currency_balances.balance + in_delta)
RETURNING balance INTO current_balance;
IF in_currency_id = get_solaris_id() THEN
GET DIAGNOSTICS function_oid = PG_ROUTINE_OID;
PERFORM log_event_solaris(function_oid, 'update_solaris', in_controller_id, current_balance, in_delta);
END IF;
current_delta = 0;
IF current_balance < 0 THEN
SELECT acc."user"
INTO fls_id
FROM accounts acc
JOIN player_state ps on ps.account_id = acc.id
WHERE ps.account_id = in_player_id
LIMIT 1;
PERFORM log_cheating(COALESCE(fls_id, in_player_id::text), 'negative_solaris');
INSERT INTO player_virtual_currency_balances("player_controller_id", "currency_id", "balance")
VALUES (in_controller_id, in_currency_id, 0)
ON CONFLICT (player_controller_id, currency_id) DO UPDATE SET balance = 0;
current_delta = current_balance;
END IF;
new_delta = in_delta + current_delta;
RETURN new_delta;
END;
$function$

View File

@@ -0,0 +1,43 @@
-- dune_exchange_modify_user_solari_balance(in_controller_id bigint, in_solari_delta bigint) -> void
-- oid: 58248 kind: FUNCTION category: currency
CREATE OR REPLACE FUNCTION dune.dune_exchange_modify_user_solari_balance(in_controller_id bigint, in_solari_delta bigint)
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
user_id BIGINT;
current_balance BIGINT;
new_balance BIGINT;
delta_balance BIGINT;
fls_id TEXT;
function_oid oid;
BEGIN
SELECT INTO user_id dune_exchange_get_user_id(in_controller_id);
SELECT INTO current_balance balance from player_virtual_currency_balances WHERE currency_id = get_solaris_id() AND player_controller_id = in_controller_id;
IF current_balance < 0 THEN
SELECT acc."user"
INTO fls_id
FROM accounts acc
JOIN player_state ps on ps.account_id = acc.id
WHERE ps.player_controller_id = in_controller_id
LIMIT 1;
PERFORM log_cheating(COALESCE(fls_id, in_controller_id::text), 'exchange_negative_solaris');
UPDATE player_virtual_currency_balances SET balance = 0 WHERE currency_id = get_solaris_id() AND player_controller_id = in_controller_id;
current_balance = 0;
END IF;
delta_balance = in_solari_delta;
IF current_balance < in_solari_delta THEN
delta_balance = current_balance;
END IF;
UPDATE dune_exchange_users SET solari_balance = solari_balance + delta_balance WHERE id = user_id;
UPDATE player_virtual_currency_balances SET balance = balance - delta_balance WHERE currency_id = get_solaris_id() AND player_controller_id = in_controller_id RETURNING player_virtual_currency_balances.balance INTO new_balance;
GET DIAGNOSTICS function_oid = PG_ROUTINE_OID;
PERFORM log_event_solaris(function_oid, 'update_solaris', in_controller_id, new_balance, delta_balance);
END $function$

View File

@@ -0,0 +1,27 @@
-- dune_exchange_retrieve_solari_balance(in_owner_id bigint) -> bigint
-- oid: 58253 kind: FUNCTION category: currency
CREATE OR REPLACE FUNCTION dune.dune_exchange_retrieve_solari_balance(in_owner_id bigint)
RETURNS bigint
LANGUAGE plpgsql
AS $function$
DECLARE
current_balance BIGINT;
fls_id TEXT;
BEGIN
SELECT INTO current_balance solari_balance from dune_exchange_users WHERE owner_id = in_owner_id LIMIT 1;
IF current_balance < 0 THEN
SELECT acc."user"
INTO fls_id
FROM accounts acc
JOIN player_state ps on ps.account_id = acc.id
WHERE ps.player_controller_id = in_owner_id
LIMIT 1;
PERFORM log_cheating(COALESCE(fls_id, in_owner_id::text), 'exchange_negative_solaris');
UPDATE dune_exchange_users SET solari_balance = 0 WHERE owner_id = in_owner_id;
END IF;
RETURN (SELECT solari_balance FROM dune_exchange_users WHERE owner_id = in_owner_id LIMIT 1);
END; $function$

View File

@@ -0,0 +1,41 @@
-- dune_exchange_retrieve_solaris_from_item(in_controller_id bigint, in_order_id bigint) -> dune.duneexchangeretrievesolarisfromitemresult
-- oid: 58254 kind: FUNCTION category: currency
CREATE OR REPLACE FUNCTION dune.dune_exchange_retrieve_solaris_from_item(in_controller_id bigint, in_order_id bigint)
RETURNS dune.duneexchangeretrievesolarisfromitemresult
LANGUAGE plpgsql
AS $function$
DECLARE
result DuneExchangeRetrieveSolarisFromItemResult;
new_balance BIGINT;
function_oid oid;
BEGIN
WITH
delete_orders_prices AS (
DELETE FROM dune_exchange_orders
USING dune_exchange_fulfilled_orders
WHERE (dune_exchange_orders.id = dune_exchange_fulfilled_orders.order_id)
AND id = in_order_id AND (item_id IS NULL OR item_id = 0)
RETURNING item_price * dune_exchange_fulfilled_orders.stack_size AS total_price
),
total_price AS (
SELECT SUM(total_price) AS delta FROM delete_orders_prices
)
UPDATE player_virtual_currency_balances
SET balance = balance + total_price.delta
FROM total_price
WHERE currency_id = get_solaris_id() AND player_controller_id = in_controller_id
RETURNING
player_virtual_currency_balances.balance,
total_price.delta,
(SELECT original_order_id FROM dune_exchange_fulfilled_orders WHERE order_id = in_order_id)
INTO
new_balance,
result.total_item_value,
result.original_order_id;
GET DIAGNOSTICS function_oid = PG_ROUTINE_OID;
PERFORM log_event_solaris(function_oid, 'update_solaris', in_controller_id, new_balance, result.total_item_value);
RETURN result;
END $function$

View File

@@ -0,0 +1,23 @@
-- edit_guild_description(in_guild_id bigint, in_guild_desc text) -> void
-- oid: 58258 kind: FUNCTION category: currency
CREATE OR REPLACE FUNCTION dune.edit_guild_description(in_guild_id bigint, in_guild_desc text)
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
out_guild_description TEXT;
BEGIN
PERFORM guilds_get_exclusive_operation_lock();
-- check if guild exists
SELECT guild_description INTO out_guild_description FROM guilds WHERE guild_id = in_guild_id;
IF NOT FOUND THEN
RAISE EXCEPTION 'Trying to add invite to non existing guild %.', in_guild_id;
END IF;
UPDATE guilds SET guild_description = in_guild_desc WHERE guilds.guild_id = in_guild_id;
PERFORM pg_notify('guild_notify_channel', format('edit_guild_description#{"GuildId" : %s}', in_guild_id));
END
$function$

View File

@@ -0,0 +1,18 @@
-- get_player_virtual_currency_balances(in_controller_id bigint) -> TABLE(out_currency_id smallint, out_currency_balance bigint)
-- oid: 58345 kind: FUNCTION category: currency
CREATE OR REPLACE FUNCTION dune.get_player_virtual_currency_balances(in_controller_id bigint)
RETURNS TABLE(out_currency_id smallint, out_currency_balance bigint)
LANGUAGE plpgsql
AS $function$
BEGIN
return query (
with currencies as (select currency_id, balance from player_virtual_currency_balances where player_controller_id = in_controller_id),
bad_currencies as (select * from currencies where balance < 0),
target_account_id as (select account_id from player_state where player_controller_id = in_controller_id limit 1),
report_cheaters as (select currency_id, flag_player_as_cheater(target_account_id.account_id, 'negative_solaris') from bad_currencies, target_account_id),
fix_bad_currencies as (update player_virtual_currency_balances set balance = 0 from report_cheaters where player_controller_id = in_controller_id and player_virtual_currency_balances.currency_id = report_cheaters.currency_id)
select currency_id, balance from currencies
);
END;
$function$

View File

@@ -0,0 +1,14 @@
-- get_solaris_id() -> smallint
-- oid: 58351 kind: FUNCTION category: currency
CREATE OR REPLACE FUNCTION dune.get_solaris_id()
RETURNS smallint
LANGUAGE plpgsql
IMMUTABLE
AS $function$
DECLARE
solaris_id CONSTANT SMALLINT := 0;
BEGIN
return solaris_id;
END
$function$

View File

@@ -0,0 +1,48 @@
-- log_event_solaris(in_function_oid oid, in_message dune.logmessagetype, in_controller_id bigint, in_solaris_balance bigint, in_solaris_delta bigint) -> void
-- oid: 58470 kind: FUNCTION category: currency
CREATE OR REPLACE FUNCTION dune.log_event_solaris(in_function_oid oid, in_message dune.logmessagetype, in_controller_id bigint, in_solaris_balance bigint, in_solaris_delta bigint)
RETURNS void
LANGUAGE plpgsql
AS $function$
DECLARE
partition_id BIGINT = 0;
calling_function_name LogFunctionType;
fls_id TEXT;
fc_id BYTEA;
char_name BYTEA;
BEGIN
partition_id := coalesce(current_setting('dune.partition_id', true)::BIGINT, 0);
-- map calling function name to LogFunctionType (each calling function must be added to LogFunctionType)
SELECT proname::text::LogFunctionType
INTO calling_function_name
FROM pg_proc
WHERE oid = in_function_oid;
-- get the fls_id for the user performing the acction
SELECT acc."user"
INTO fls_id
FROM accounts acc
JOIN player_state ps on ps.account_id = acc.id
WHERE ps.player_controller_id = in_controller_id
LIMIT 1;
INSERT INTO event_log (
partition_id,
category,
function_name,
message,
event_time,
meta
) VALUES (
partition_id,
'solaris',
calling_function_name,
in_message,
now(),
json_build_object('fls_id', fls_id, 'event', calling_function_name::text, 'solaris_balance', in_solaris_balance, 'solaris_delta', in_solaris_delta)
);
END;
$function$

View File

@@ -0,0 +1,9 @@
-- debug_add_test_table_data(in_entry text) -> void
-- oid: 58187 kind: FUNCTION category: debug
CREATE OR REPLACE FUNCTION dune.debug_add_test_table_data(in_entry text)
RETURNS void
LANGUAGE sql
AS $function$
insert into debug_test_table("entry") VALUES (in_entry);
$function$

View File

@@ -0,0 +1,9 @@
-- debug_collect_test_table_data() -> SETOF text
-- oid: 58188 kind: FUNCTION category: debug
CREATE OR REPLACE FUNCTION dune.debug_collect_test_table_data()
RETURNS SETOF text
LANGUAGE sql
AS $function$
select entry from debug_test_table;
$function$

View File

@@ -0,0 +1,12 @@
-- debug_echo(in_text text, in_notices text[]) -> text
-- oid: 58189 kind: FUNCTION category: debug
CREATE OR REPLACE FUNCTION dune.debug_echo(in_text text, in_notices text[])
RETURNS text
LANGUAGE plpgsql
AS $function$
BEGIN
perform debug_raise_notices(in_notices);
return in_text;
END;
$function$

View File

@@ -0,0 +1,42 @@
-- debug_get_coriolis_seeds() -> TABLE(farm_seed integer, map_names text[], map_seeds integer[], partitions_ids bigint[], partitions_map text[], partitions_seeds integer[])
-- oid: 58190 kind: FUNCTION category: debug
CREATE OR REPLACE FUNCTION dune.debug_get_coriolis_seeds()
RETURNS TABLE(farm_seed integer, map_names text[], map_seeds integer[], partitions_ids bigint[], partitions_map text[], partitions_seeds integer[])
LANGUAGE plpgsql
AS $function$
begin
RETURN QUERY
WITH
map_seeds as (
SELECT array_agg(map_name) as map_name, array_agg(seed) as seed
FROM (
SELECT COALESCE(map_seed.map, partition.map) AS map_name, COALESCE(map_seed.world_reset_seed, -1) AS seed
FROM world_map_reset_seed AS map_seed FULL JOIN world_partition as partition ON map_seed.map = partition.map
GROUP BY map_seed.map, partition.map, map_seed.world_reset_seed
ORDER BY map_name ASC
) as maps_temp
),
partitions_seeds as (
SELECT array_agg(partition_id) as partition_id, array_agg(map_name) as map_name, array_agg(seed) as seed
FROM (
SELECT partition.partition_id as partition_id, partition.map as map_name, COALESCE(partition_seed.world_reset_seed, -1) AS seed
FROM world_partition_reset_seed AS partition_seed FULL JOIN world_partition as partition ON partition_seed.partition_id = partition.partition_id
GROUP BY partition.map, partition.partition_id, partition_seed.world_reset_seed
ORDER BY partition.partition_id ASC
) as partitions_temp
)
SELECT
COALESCE(world_reset_seed, -1),
COALESCE(map_seeds.map_name, array[]::TEXT[]),
COALESCE(map_seeds.seed, array[]::Integer[]),
COALESCE(partitions_seeds.partition_id, array[]::BigInt[]),
COALESCE(partitions_seeds.map_name, array[]::TEXT[]),
COALESCE(partitions_seeds.seed, array[]::Integer[])
FROM
world_farm_reset_seed,
map_seeds,
partitions_seeds;
end
$function$

View File

@@ -0,0 +1,12 @@
-- debug_raise_exception(in_exception text, in_notices text[]) -> void
-- oid: 58191 kind: FUNCTION category: debug
CREATE OR REPLACE FUNCTION dune.debug_raise_exception(in_exception text, in_notices text[])
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
perform debug_raise_notices(in_notices);
RAISE EXCEPTION '%', in_exception;
END;
$function$

View File

@@ -0,0 +1,16 @@
-- debug_raise_notices(in_notices text[]) -> void
-- oid: 58192 kind: FUNCTION category: debug
CREATE OR REPLACE FUNCTION dune.debug_raise_notices(in_notices text[])
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
IF array_length(in_notices, 1) IS NOT NULL THEN
FOR i IN 0..array_length(in_notices, 1)-1
LOOP
RAISE NOTICE '%', in_notices[i];
END LOOP;
END IF;
END;
$function$

View File

@@ -0,0 +1,9 @@
-- debug_reset_test_table() -> void
-- oid: 58193 kind: FUNCTION category: debug
CREATE OR REPLACE FUNCTION dune.debug_reset_test_table()
RETURNS void
LANGUAGE sql
AS $function$
truncate debug_test_table;
$function$

View File

@@ -0,0 +1,21 @@
-- debug_set_farm_seed(in_new_coriolis_seed integer) -> void
-- oid: 58194 kind: FUNCTION category: debug
CREATE OR REPLACE FUNCTION dune.debug_set_farm_seed(in_new_coriolis_seed integer)
RETURNS void
LANGUAGE plpgsql
AS $function$
begin
UPDATE world_farm_reset_seed SET world_reset_seed = in_new_coriolis_seed WHERE onerow_id = TRUE;
UPDATE world_map_reset_seed SET world_reset_seed = in_new_coriolis_seed;
INSERT INTO world_map_reset_seed SELECT map, in_new_coriolis_seed FROM world_partition GROUP BY map
ON CONFLICT(map) DO
UPDATE SET world_reset_seed = in_new_coriolis_seed;
UPDATE world_partition_reset_seed SET world_reset_seed = in_new_coriolis_seed;
INSERT INTO world_partition_reset_seed SELECT partition_id, in_new_coriolis_seed FROM world_partition GROUP BY partition_id
ON CONFLICT(partition_id) DO
UPDATE SET world_reset_seed = in_new_coriolis_seed;
end
$function$

View File

@@ -0,0 +1,18 @@
-- debug_set_map_seed(in_map text, in_new_coriolis_seed integer) -> void
-- oid: 58195 kind: FUNCTION category: debug
CREATE OR REPLACE FUNCTION dune.debug_set_map_seed(in_map text, in_new_coriolis_seed integer)
RETURNS void
LANGUAGE plpgsql
AS $function$
begin
INSERT INTO world_map_reset_seed (map, world_reset_seed) Values(in_server_info.map, in_new_coriolis_seed)
ON CONFLICT(map) DO
UPDATE SET world_reset_seed = in_new_coriolis_seed;
UPDATE world_partition_reset_seed SET world_reset_seed = in_new_coriolis_seed WHERE map = in_map;
INSERT INTO world_partition_reset_seed SELECT partition_id, in_new_coriolis_seed FROM world_partition WHERE map = in_map GROUP BY partition_id
ON CONFLICT(partition_id) DO
UPDATE SET world_reset_seed = in_new_coriolis_seed;
end
$function$

View File

@@ -0,0 +1,13 @@
-- debug_set_partition_seed(in_partition_id bigint, in_new_coriolis_seed integer) -> void
-- oid: 58196 kind: FUNCTION category: debug
CREATE OR REPLACE FUNCTION dune.debug_set_partition_seed(in_partition_id bigint, in_new_coriolis_seed integer)
RETURNS void
LANGUAGE plpgsql
AS $function$
begin
INSERT INTO world_partition_reset_seed (partition_id, world_reset_seed) Values(in_server_info.partition_id, in_new_coriolis_seed)
ON CONFLICT(partition_id) DO
UPDATE SET world_reset_seed = in_new_coriolis_seed;
end
$function$

Some files were not shown because too many files have changed in this diff Show More