Some checks failed
Deploy MineGeo to Dokploy / deploy (push) Failing after 6m30s
98 lines
3.8 KiB
PL/PgSQL
98 lines
3.8 KiB
PL/PgSQL
-- Capture IDs are unique, but multiple captures can still share a camera
|
|
-- position or the same six image files. Deduplicate before sampling rounds.
|
|
create or replace function public.game_viewpoint_pool(p_manifest jsonb, p_root text)
|
|
returns jsonb language sql immutable security invoker set search_path = '' as $$
|
|
with by_location as (
|
|
select distinct on (
|
|
floor((p->>'x')::numeric), floor((p->>'y')::numeric), floor((p->>'z')::numeric)
|
|
) p, n
|
|
from jsonb_array_elements(p_manifest->'viewpoints') with ordinality points(p, n)
|
|
order by floor((p->>'x')::numeric), floor((p->>'y')::numeric),
|
|
floor((p->>'z')::numeric), n
|
|
), by_media as (
|
|
select distinct on (
|
|
coalesce(p->>'assetRoot', p_root), coalesce(p->>'assetId', p->>'id')
|
|
) p, n from by_location
|
|
order by coalesce(p->>'assetRoot', p_root), coalesce(p->>'assetId', p->>'id'), n
|
|
)
|
|
select coalesce(jsonb_agg(p order by n), '[]'::jsonb) from by_media;
|
|
$$;
|
|
revoke all on function public.game_viewpoint_pool(jsonb, text)
|
|
from public, anon, authenticated;
|
|
grant execute on function public.game_viewpoint_pool(jsonb, text) to service_role;
|
|
|
|
create or replace function public.create_game(
|
|
p_dataset uuid, p_difficulty text, p_owner uuid, p_access_hash text
|
|
) returns uuid language plpgsql security invoker set search_path = '' as $$
|
|
declare
|
|
sid uuid;
|
|
revision uuid;
|
|
rev public.revisions;
|
|
vp jsonb;
|
|
locations jsonb;
|
|
n integer := 0;
|
|
settings jsonb;
|
|
begin
|
|
settings := public.resolve_difficulty_preset(p_difficulty);
|
|
revision := public.playable_map_revision(p_dataset, p_owner);
|
|
select * into rev from public.revisions where id = revision;
|
|
if not found then raise exception 'Map unavailable'; end if;
|
|
locations := public.game_viewpoint_pool(rev.manifest, rev.asset_root);
|
|
if jsonb_array_length(locations) < 5 then
|
|
raise exception 'Map needs at least five distinct panorama locations';
|
|
end if;
|
|
insert into public.game_sessions(
|
|
revision_id, owner_id, access_hash, difficulty, difficulty_settings
|
|
) values (rev.id, p_owner, p_access_hash, p_difficulty, settings)
|
|
returning id into sid;
|
|
for vp in select value from jsonb_array_elements(locations) order by random() limit 5
|
|
loop
|
|
insert into public.game_rounds(session_id, round_number, viewpoint)
|
|
values (sid, n, vp);
|
|
n := n + 1;
|
|
end loop;
|
|
return sid;
|
|
end;
|
|
$$;
|
|
|
|
create or replace function public.create_map_room(
|
|
p_dataset uuid, p_difficulty text, p_name text, p_limit integer,
|
|
p_access_hash text, p_owner uuid
|
|
) returns uuid language plpgsql security invoker set search_path = '' as $$
|
|
declare
|
|
rid uuid;
|
|
revision uuid;
|
|
pid uuid := gen_random_uuid();
|
|
rev public.revisions;
|
|
vp jsonb;
|
|
locations jsonb;
|
|
n integer := 0;
|
|
settings jsonb;
|
|
begin
|
|
if p_limit is null or p_limit not between 2 and 16 then
|
|
raise exception 'Choose between 2 and 16 players';
|
|
end if;
|
|
settings := public.resolve_difficulty_preset(p_difficulty);
|
|
revision := public.playable_map_revision(p_dataset, p_owner);
|
|
select * into rev from public.revisions where id = revision;
|
|
if not found then raise exception 'Map unavailable'; end if;
|
|
locations := public.game_viewpoint_pool(rev.manifest, rev.asset_root);
|
|
if jsonb_array_length(locations) < 5 then
|
|
raise exception 'Map needs at least five distinct panorama locations';
|
|
end if;
|
|
insert into public.multiplayer_rooms(
|
|
revision_id, host_player_id, difficulty, difficulty_settings, player_limit
|
|
) values (rev.id, pid, p_difficulty, settings, p_limit)
|
|
returning id into rid;
|
|
insert into public.multiplayer_players(id, room_id, access_hash, display_name)
|
|
values (pid, rid, p_access_hash, btrim(p_name));
|
|
for vp in select value from jsonb_array_elements(locations) order by random() limit 5
|
|
loop
|
|
insert into public.multiplayer_rounds(room_id, round_number, viewpoint)
|
|
values (rid, n, vp);
|
|
n := n + 1;
|
|
end loop;
|
|
return rid;
|
|
end;
|
|
$$;
|