fix errors on insertion to game, fix db creation of game

This commit is contained in:
lbenedar
2026-04-23 19:03:56 +03:00
parent f46ff8333e
commit 07025afefc
36 changed files with 1820 additions and 693 deletions

View File

@@ -19,6 +19,7 @@ DROP TABLE IF EXISTS system;
DROP TABLE IF EXISTS package_warnings_data_error; DROP TABLE IF EXISTS package_warnings_data_error;
DROP TABLE IF EXISTS package_warnings_data_warning; DROP TABLE IF EXISTS package_warnings_data_warning;
DROP TABLE IF EXISTS package_warnings_data; DROP TABLE IF EXISTS package_warnings_data;
DROP TRIGGER IF EXISTS tr_delete_package_warnings_to_data_package_warnings_data;
DROP TABLE IF EXISTS package_warnings; DROP TABLE IF EXISTS package_warnings;
DROP TABLE IF EXISTS news; DROP TABLE IF EXISTS news;
DROP TABLE IF EXISTS folder_packs; DROP TABLE IF EXISTS folder_packs;

View File

@@ -397,15 +397,30 @@ CREATE TABLE IF NOT EXISTS package_warnings (
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
); );
CREATE TABLE IF NOT EXISTS package_warnings_to_data (
package_warnings_id INTEGER,
package_warnings_data_id TEXT,
PRIMARY KEY (package_warnings_id, package_warnings_data_id),
FOREIGN KEY (package_warnings_id) REFERENCES package_warnings(id) ON DELETE CASCADE,
FOREIGN KEY (package_warnings_data_id) REFERENCES package_warnings_data(id) ON DELETE CASCADE
);
CREATE TRIGGER tr_delete_package_warnings_to_data_package_warnings_data
AFTER DELETE ON package_warnings_to_data
FOR EACH ROW
BEGIN
DELETE FROM package_warnings_data
WHERE id = OLD.id
AND NOT EXISTS (SELECT 1 FROM package_warnings_to_data WHERE package_warnings_data_id = OLD.package_warnings_data_id);
END;
CREATE TABLE IF NOT EXISTS package_warnings_data ( CREATE TABLE IF NOT EXISTS package_warnings_data (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
type VARCHAR(128) NOT NULL, type VARCHAR(128) NOT NULL,
manifest VARCHAR(128) NOT NULL, manifest VARCHAR(128) NOT NULL,
reinstallable BOOLEAN NOT NULL, reinstallable BOOLEAN NOT NULL
package_warnings_id INTEGER,
FOREIGN KEY (package_warnings_id) REFERENCES package_warnings(id) ON DELETE CASCADE
); );
CREATE TABLE IF NOT EXISTS package_warnings_data_warning ( CREATE TABLE IF NOT EXISTS package_warnings_data_warning (
@@ -510,6 +525,9 @@ CREATE TABLE IF NOT EXISTS world (
owned BOOLEAN NOT NULL DEFAULT FALSE, owned BOOLEAN NOT NULL DEFAULT FALSE,
has_storage BOOLEAN NOT NULL DEFAULT FALSE, has_storage BOOLEAN NOT NULL DEFAULT FALSE,
created_at TEXT DEFAULT (datetime('now')),
updated_at TEXT DEFAULT (datetime('now')),
setup_id INTEGER, setup_id INTEGER,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
); );

View File

@@ -1,3 +1,191 @@
DROP TABLE IF EXISTS modules_languages; DROP TRIGGER IF EXISTS tr_delete_package_warnings_to_data_package_warnings_data;
DROP TABLE IF EXISTS modules_compatibility; DROP TRIGGER IF EXISTS tr_delete_game_to_systems_system;
DROP TABLE IF EXISTS modules; DROP TRIGGER IF EXISTS tr_delete_game_to_module_module;
DROP TABLE IF EXISTS token_turn_maker;
DROP TABLE IF EXISTS token_occludable;
DROP TABLE IF EXISTS token_light_darkness;
DROP TABLE IF EXISTS token_light_animation;
DROP TABLE IF EXISTS token_light;
DROP TABLE IF EXISTS token_bar_2;
DROP TABLE IF EXISTS token_bar_1;
DROP TABLE IF EXISTS token_texture;
DROP TABLE IF EXISTS token_sight;
DROP TABLE IF EXISTS ring_subject;
DROP TABLE IF EXISTS ring_colors;
DROP TABLE IF EXISTS ring;
DROP TABLE IF EXISTS token;
DROP TABLE IF EXISTS actor;
DROP TABLE IF EXISTS sound;
DROP TABLE IF EXISTS playlist;
DROP TABLE IF EXISTS table_result_range;
DROP TABLE IF EXISTS table_result;
DROP TABLE IF EXISTS table_;
DROP TABLE IF EXISTS journal_page_video;
DROP TABLE IF EXISTS journal_page_title;
DROP TABLE IF EXISTS journal_page_text;
DROP TABLE IF EXISTS journal_page;
DROP TABLE IF EXISTS journal;
DROP TABLE IF EXISTS setting;
DROP TABLE IF EXISTS item;
DROP TABLE IF EXISTS world_folder;
DROP TABLE IF EXISTS macro;
DROP TABLE IF EXISTS hotbar;
DROP TABLE IF EXISTS user;
DROP TABLE IF EXISTS face;
DROP TABLE IF EXISTS back;
DROP TABLE IF EXISTS card;
DROP TABLE IF EXISTS ownership_string;
DROP TABLE IF EXISTS card_deck;
DROP TABLE IF EXISTS combatant;
DROP TABLE IF EXISTS combat_groups;
DROP TABLE IF EXISTS combat;
DROP TABLE IF EXISTS message_rolls;
DROP TABLE IF EXISTS message_whisper;
DROP TABLE IF EXISTS speaker;
DROP TABLE IF EXISTS stats;
DROP TABLE IF EXISTS message;
CREATE TABLE IF NOT EXISTS pack_new (
id INTEGER PRIMARY KEY,
key_ VARCHAR(128) NOT NULL,
name VARCHAR(128) NOT NULL,
label VARCHAR(128) NOT NULL,
banner VARCHAR(128) NOT NULL,
path VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
system VARCHAR(128) NOT NULL,
package_type VARCHAR(128) NOT NULL,
package_name VARCHAR(128) NOT NULL,
module_id TEXT,
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE
);
ALTER TABLE pack_new ADD COLUMN system_id TEXT REFERENCES system(id) ON DELETE CASCADE;
ALTER TABLE pack_new ADD COLUMN world_id TEXT REFERENCES world(id) ON DELETE CASCADE;
INSERT INTO pack_new (id, key_, name, label, banner, path, type, system, package_type, package_name, module_id, system_id, world_id)
SELECT id, key_, name, label, banner, path, type, system, package_type, package_name, module_id, system_id, world_id FROM pack;
DROP TABLE IF EXISTS pack;
ALTER TABLE pack_new RENAME TO pack;
CREATE TABLE IF NOT EXISTS package_warnings_new (
id INTEGER PRIMARY KEY AUTOINCREMENT,
key_ TEXT NOT NULL,
setup_id INTEGER,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
);
INSERT INTO package_warnings_new (id, key_, setup_id)
SELECT id, key_, setup_id FROM package_warnings;
DROP TABLE IF EXISTS package_warnings;
ALTER TABLE package_warnings_new RENAME TO package_warnings;
DROP TABLE IF EXISTS active_users;
DROP TABLE IF EXISTS system_update;
DROP INDEX IF EXISTS idx_core_update_game_id;
CREATE TABLE IF NOT EXISTS core_update_new (
id INTEGER PRIMARY KEY AUTOINCREMENT,
has_update BOOLEAN NOT NULL DEFAULT FALSE,
can_update BOOLEAN NOT NULL DEFAULT FALSE,
could_reach_website BOOLEAN NOT NULL DEFAULT FALSE,
slow_response BOOLEAN NOT NULL DEFAULT FALSE,
will_disable_modules BOOLEAN NOT NULL DEFAULT FALSE,
version VARCHAR(64) NOT NULL,
channel VARCHAR(64) NOT NULL,
setup_id INTEGER UNIQUE,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
);
INSERT INTO core_update_new (id, has_update, can_update, could_reach_website, slow_response, will_disable_modules, version, channel, setup_id)
SELECT id, has_update, can_update, could_reach_website, slow_response, will_disable_modules, version, channel, setup_id FROM core_update;
DROP TABLE IF EXISTS core_update;
ALTER TABLE core_update_new RENAME TO core_update;
DROP TABLE IF EXISTS game_to_systems;
DROP INDEX IF EXISTS idx_world_game_id;
CREATE TABLE IF NOT EXISTS world_new (
id TEXT PRIMARY KEY,
title VARCHAR(128) NOT NULL,
description VARCHAR(128) NOT NULL,
version VARCHAR(128) NOT NULL,
system VARCHAR(128) NOT NULL,
background VARCHAR(128) NOT NULL,
join_theme VARCHAR(128) NOT NULL,
core_version VARCHAR(128) NOT NULL,
system_version VARCHAR(128) NOT NULL,
last_played VARCHAR(128) NOT NULL,
playtime INTEGER NOT NULL,
availability INTEGER NOT NULL,
next_session DATETIME NOT NULL,
socket BOOLEAN NOT NULL DEFAULT FALSE,
protected BOOLEAN NOT NULL DEFAULT FALSE,
exclusive_ BOOLEAN NOT NULL DEFAULT FALSE,
persistent_storage BOOLEAN NOT NULL DEFAULT FALSE,
locked BOOLEAN NOT NULL DEFAULT FALSE,
owned BOOLEAN NOT NULL DEFAULT FALSE,
has_storage BOOLEAN NOT NULL DEFAULT FALSE,
created_at TEXT DEFAULT (datetime('now')),
updated_at TEXT DEFAULT (datetime('now')),
setup_id INTEGER,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
);
INSERT INTO world_new (id, title, description, version, system, background, join_theme, core_version, system_version, last_played, playtime, availability, next_session, socket, protected, exclusive_, persistent_storage, locked, owned, has_storage, created_at, updated_at, setup_id)
SELECT id, title, description, version, system, background, join_theme, core_version, system_version, last_played, playtime, availability, next_session, socket, protected, exclusive_, persistent_storage, locked, owned, has_storage, created_at, updated_at, setup_id FROM world;
DROP TABLE IF EXISTS world;
ALTER TABLE world_new RENAME TO world;
DROP INDEX IF EXISTS idx_release_game_id;
CREATE TABLE IF NOT EXISTS release_new (
id INTEGER PRIMARY KEY AUTOINCREMENT,
generation INTEGER NOT NULL,
build INTEGER NOT NULL,
node_version INTEGER NOT NULL,
max_generation INTEGER NOT NULL,
max_stable_generation INTEGER NOT NULL,
time DATETIME NOT NULL,
channel VARCHAR(128) NOT NULL,
suffix VARCHAR(128) NOT NULL,
setup_id INTEGER UNIQUE,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
);
INSERT INTO release_new (id, generation, build, node_version, max_generation, max_stable_generation, time, channel, suffix, setup_id)
SELECT id, generation, build, node_version, max_generation, max_stable_generation, time, channel, suffix, setup_id FROM release_;
DROP TABLE IF EXISTS release_;
ALTER TABLE release_new RENAME TO release_;
DROP TABLE IF EXISTS game_options;
DROP INDEX IF EXISTS idx_files_game_id;
DROP TABLE IF EXISTS files_new;
CREATE TABLE IF NOT EXISTS files_new (
id INTEGER PRIMARY KEY AUTOINCREMENT,
setup_id INTEGER UNIQUE,
FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE
);
INSERT INTO files_new (id, setup_id)
SELECT id, setup_id FROM files;
DROP TABLE IF EXISTS files;
ALTER TABLE files_new RENAME TO files;
DROP TABLE IF EXISTS addresses;
DROP TABLE IF EXISTS game;
CREATE TRIGGER tr_delete_package_warnings_to_data_package_warnings_data
AFTER DELETE ON package_warnings_to_data
FOR EACH ROW
BEGIN
DELETE FROM package_warnings_data
WHERE id = OLD.id
AND NOT EXISTS (SELECT 1 FROM package_warnings_to_data WHERE package_warnings_data_id = OLD.package_warnings_data_id);
END;

View File

@@ -1,5 +1,5 @@
CREATE TABLE IF NOT EXISTS game ( CREATE TABLE IF NOT EXISTS game (
id INTEGER PRIMARY KEY AUTOINCREMENT id INTEGER PRIMARY KEY AUTOINCREMENT,
demo_mode BOOLEAN NOT NULL DEFAULT FALSE, demo_mode BOOLEAN NOT NULL DEFAULT FALSE,
idle_logout BOOLEAN NOT NULL DEFAULT FALSE, idle_logout BOOLEAN NOT NULL DEFAULT FALSE,
@@ -20,6 +20,8 @@ CREATE TABLE IF NOT EXISTS addresses (
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
); );
ALTER TABLE files ADD COLUMN game_id INTEGER REFERENCES game(id) ON DELETE CASCADE;
CREATE UNIQUE INDEX idx_files_game_id ON files(game_id);
CREATE TABLE IF NOT EXISTS game_options ( CREATE TABLE IF NOT EXISTS game_options (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
@@ -32,22 +34,280 @@ CREATE TABLE IF NOT EXISTS game_options (
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
); );
CREATE TABLE IF NOT EXISTS macro ( ALTER TABLE release_ ADD COLUMN game_id INTEGER REFERENCES game(id) ON DELETE CASCADE;
id TEXT PRIMARY KEY, CREATE UNIQUE INDEX idx_release_game_id ON release_(game_id);
ALTER TABLE world ADD COLUMN game_id INTEGER REFERENCES game(id) ON DELETE CASCADE;
CREATE UNIQUE INDEX idx_world_game_id ON world(game_id);
command VARCHAR(128) NOT NULL, CREATE TABLE IF NOT EXISTS game_to_systems (
name VARCHAR(128) NOT NULL, game_id INTEGER,
type VARCHAR(128) NOT NULL, system_id TEXT,
img VARCHAR(128) NOT NULL,
author VARCHAR(128) NOT NULL, PRIMARY KEY (game_id, system_id),
scope VARCHAR(128) NOT NULL, FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE,
folder VARCHAR(128) NOT NULL, FOREIGN KEY (system_id) REFERENCES system(id) ON DELETE CASCADE
sort INTEGER NOT NULL, );
CREATE TRIGGER tr_delete_game_to_systems_system
AFTER DELETE ON game_to_systems
FOR EACH ROW
BEGIN
DELETE FROM system
WHERE id = OLD.id
AND NOT EXISTS (SELECT 1 FROM game_to_systems WHERE system_id = OLD.system_id);
END;
ALTER TABLE core_update ADD COLUMN game_id INTEGER REFERENCES game(id) ON DELETE CASCADE;
CREATE UNIQUE INDEX idx_core_update_game_id ON core_update(game_id);
CREATE TABLE IF NOT EXISTS system_update (
id INTEGER PRIMARY KEY AUTOINCREMENT,
has_update BOOLEAN NOT NULL DEFAULT FALSE,
version VARCHAR(128) NOT NULL,
game_id INTEGER UNIQUE,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS active_users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
value VARCHAR(128) NOT NULL,
game_id INTEGER, game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
); );
CREATE TABLE IF NOT EXISTS game_to_module (
game_id INTEGER,
module_id TEXT,
PRIMARY KEY (game_id, module_id),
FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
CREATE TRIGGER tr_delete_game_to_module_module
AFTER DELETE ON game_to_module
FOR EACH ROW
BEGIN
DELETE FROM module
WHERE id = OLD.id
AND NOT EXISTS (SELECT 1 FROM game_to_module WHERE module_id = OLD.module_id);
END;
ALTER TABLE package_warnings ADD COLUMN game_id INTEGER REFERENCES game(id) ON DELETE CASCADE;
ALTER TABLE pack ADD COLUMN game_id INTEGER REFERENCES game(id) ON DELETE CASCADE;
CREATE TABLE IF NOT EXISTS message (
id TEXT PRIMARY KEY,
blind BOOLEAN NOT NULL,
emote BOOLEAN NOT NULL,
style INTEGER NOT NULL,
timestamp DATETIME NOT NULL,
content VARCHAR(128) NOT NULL,
author VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
flavor VARCHAR(128) NOT NULL,
sound VARCHAR(128) NOT NULL,
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS stats (
id INTEGER PRIMARY KEY AUTOINCREMENT,
core_version VARCHAR(128) NOT NULL,
system_id VARCHAR(128) NOT NULL,
system_version VARCHAR(128) NOT NULL,
last_modified_by VARCHAR(128) NOT NULL,
modified_time DATETIME NOT NULL,
message_id TEXT UNIQUE,
FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS speaker (
id INTEGER PRIMARY KEY AUTOINCREMENT,
scene VARCHAR(128) NOT NULL,
actor VARCHAR(128) NOT NULL,
token VARCHAR(128) NOT NULL,
alias VARCHAR(128) NOT NULL,
message_id TEXT UNIQUE,
FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS message_whisper (
id INTEGER PRIMARY KEY AUTOINCREMENT,
value VARCHAR(128) NOT NULL,
message_id TEXT,
FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS message_rolls (
id INTEGER PRIMARY KEY AUTOINCREMENT,
value VARCHAR(128) NOT NULL,
message_id TEXT,
FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS combat (
id TEXT PRIMARY KEY,
type VARCHAR(128) NOT NULL,
scene VARCHAR(128) NOT NULL,
round INTEGER NOT NULL,
turn INTEGER NOT NULL,
sort INTEGER NOT NULL,
active INTEGER NOT NULL,
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
ALTER TABLE stats ADD COLUMN combat_id TEXT REFERENCES combat(id) ON DELETE CASCADE;
CREATE UNIQUE INDEX idx_stats_combat_id ON stats(combat_id);
CREATE TABLE IF NOT EXISTS combat_groups (
id INTEGER PRIMARY KEY AUTOINCREMENT,
value VARCHAR(128) NOT NULL,
combat_id TEXT,
FOREIGN KEY (combat_id) REFERENCES combat(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS combatant (
id TEXT PRIMARY KEY,
token_id VARCHAR(128) NOT NULL,
scene_id VARCHAR(128) NOT NULL,
actor_id VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
img VARCHAR(128) NOT NULL,
group_ VARCHAR(128) NOT NULL,
initiative INTEGER NOT NULL,
hidden BOOLEAN NOT NULL,
defeated BOOLEAN NOT NULL,
combat_id TEXT,
FOREIGN KEY (combat_id) REFERENCES combat(id) ON DELETE CASCADE
);
ALTER TABLE stats ADD COLUMN combatant_id TEXT REFERENCES combatant(id) ON DELETE CASCADE;
CREATE UNIQUE INDEX idx_stats_combatant_id ON stats(combatant_id);
CREATE TABLE IF NOT EXISTS card_deck (
id TEXT PRIMARY KEY,
name VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
description VARCHAR(128) NOT NULL,
img VARCHAR(128) NOT NULL,
folder VARCHAR(128) NOT NULL,
width INTEGER NOT NULL,
height INTEGER NOT NULL,
rotation INTEGER NOT NULL,
sort INTEGER NOT NULL,
display_count BOOLEAN NOT NULL,
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
ALTER TABLE stats ADD COLUMN card_deck_id TEXT REFERENCES card_deck(id) ON DELETE CASCADE;
CREATE UNIQUE INDEX idx_stats_card_deck_id ON stats(card_deck_id);
CREATE TABLE IF NOT EXISTS ownership_string (
id INTEGER PRIMARY KEY AUTOINCREMENT,
key_ VARCHAR(128) NOT NULL,
value INTEGER NOT NULL,
card_deck_id TEXT UNIQUE,
FOREIGN KEY (card_deck_id) REFERENCES card_deck(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS card (
id TEXT PRIMARY KEY,
name VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
suit VARCHAR(128) NOT NULL,
description VARCHAR(128) NOT NULL,
origin VARCHAR(128) NOT NULL,
width INTEGER NOT NULL,
height INTEGER NOT NULL,
rotation INTEGER NOT NULL,
value INTEGER NOT NULL,
face INTEGER NOT NULL,
sort INTEGER NOT NULL,
drawn BOOLEAN NOT NULL,
card_deck_id TEXT,
FOREIGN KEY (card_deck_id) REFERENCES card_deck(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS back (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(128) NOT NULL,
text VARCHAR(128) NOT NULL,
card_id TEXT UNIQUE,
FOREIGN KEY (card_id) REFERENCES card(id) ON DELETE CASCADE
);
ALTER TABLE stats ADD COLUMN card_id TEXT REFERENCES card(id) ON DELETE CASCADE;
CREATE UNIQUE INDEX idx_stats_card_id ON stats(card_id);
CREATE TABLE IF NOT EXISTS face (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(128) NOT NULL,
img VARCHAR(128) NOT NULL,
text VARCHAR(128) NOT NULL,
card_id TEXT,
FOREIGN KEY (card_id) REFERENCES card(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS user (
id TEXT PRIMARY KEY,
name VARCHAR(128) NOT NULL,
avatar VARCHAR(128) NOT NULL,
character VARCHAR(128) NOT NULL,
color VARCHAR(128) NOT NULL,
pronouns VARCHAR(128) NOT NULL,
role INTEGER NOT NULL,
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
ALTER TABLE stats ADD COLUMN user_id TEXT REFERENCES user(id) ON DELETE CASCADE;
CREATE UNIQUE INDEX idx_stats_user_id ON stats(user_id);
CREATE TABLE IF NOT EXISTS hotbar (
id INTEGER PRIMARY KEY AUTOINCREMENT,
key_ INTEGER NOT NULL,
value VARCHAR(128) NOT NULL,
user_id TEXT,
FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS macro ( CREATE TABLE IF NOT EXISTS macro (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
@@ -64,6 +324,163 @@ CREATE TABLE IF NOT EXISTS macro (
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
); );
ALTER TABLE stats ADD COLUMN macro_id TEXT REFERENCES macro(id) ON DELETE CASCADE;
CREATE UNIQUE INDEX idx_stats_macro_id ON stats(macro_id);
ALTER TABLE ownership_string ADD COLUMN macro_id TEXT REFERENCES macro(id) ON DELETE CASCADE;
CREATE TABLE IF NOT EXISTS world_folder (
id TEXT PRIMARY KEY,
name VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
folder VARCHAR(128) NOT NULL,
sorting VARCHAR(128) NOT NULL,
description VARCHAR(128) NOT NULL,
color VARCHAR(128) NOT NULL,
sort INTEGER NOT NULL,
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
ALTER TABLE stats ADD COLUMN world_folder_id TEXT REFERENCES world_folder(id) ON DELETE CASCADE;
CREATE UNIQUE INDEX idx_stats_world_folder_id ON stats(world_folder_id);
CREATE TABLE IF NOT EXISTS item (
id TEXT PRIMARY KEY,
img VARCHAR(128) NOT NULL,
name VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
folder VARCHAR(128) NOT NULL,
sort INTEGER NOT NULL,
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
ALTER TABLE stats ADD COLUMN item_id TEXT REFERENCES item(id) ON DELETE CASCADE;
CREATE UNIQUE INDEX idx_stats_item_id ON stats(item_id);
ALTER TABLE ownership_string ADD COLUMN item_id TEXT REFERENCES item(id) ON DELETE CASCADE;
CREATE TABLE IF NOT EXISTS setting (
id TEXT PRIMARY KEY,
key_ VARCHAR(128) NOT NULL,
value VARCHAR(128) NOT NULL,
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
ALTER TABLE stats ADD COLUMN setting_id TEXT REFERENCES setting(id) ON DELETE CASCADE;
CREATE UNIQUE INDEX idx_stats_setting_id ON stats(setting_id);
CREATE TABLE IF NOT EXISTS journal (
id TEXT PRIMARY KEY,
name VARCHAR(128) NOT NULL,
sort INTEGER NOT NULL,
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS journal_page (
id TEXT PRIMARY KEY,
name VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
src VARCHAR(128) NOT NULL,
sort INTEGER NOT NULL,
journal_id TEXT,
FOREIGN KEY (journal_id) REFERENCES journal(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS journal_page_text (
id INTEGER PRIMARY KEY AUTOINCREMENT,
content VARCHAR(128) NOT NULL,
markdown VARCHAR(128) NOT NULL,
format INTEGER NOT NULL,
journal_page_id TEXT,
FOREIGN KEY (journal_page_id) REFERENCES journal_page(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS journal_page_title (
id INTEGER PRIMARY KEY AUTOINCREMENT,
show BOOLEAN NOT NULL,
level INTEGER NOT NULL,
journal_page_id TEXT,
FOREIGN KEY (journal_page_id) REFERENCES journal_page(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS journal_page_video (
id INTEGER PRIMARY KEY AUTOINCREMENT,
controls BOOLEAN NOT NULL,
volume REAL NOT NULL,
journal_page_id TEXT,
FOREIGN KEY (journal_page_id) REFERENCES journal_page(id) ON DELETE CASCADE
);
ALTER TABLE stats ADD COLUMN journal_page_id TEXT REFERENCES journal_page(id) ON DELETE CASCADE;
CREATE UNIQUE INDEX idx_stats_journal_page_id ON stats(journal_page_id);
ALTER TABLE ownership_string ADD COLUMN journal_page_id TEXT REFERENCES journal_page(id) ON DELETE CASCADE;
ALTER TABLE ownership_string ADD COLUMN journal_id TEXT REFERENCES journal(id) ON DELETE CASCADE;
CREATE TABLE IF NOT EXISTS table_ (
id TEXT PRIMARY KEY,
name VARCHAR(128) NOT NULL,
description VARCHAR(128) NOT NULL,
formula VARCHAR(128) NOT NULL,
img VARCHAR(128) NOT NULL,
folder VARCHAR(128) NOT NULL,
sort INTEGER NOT NULL,
replacement BOOLEAN NOT NULL,
display_roll BOOLEAN NOT NULL,
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
ALTER TABLE stats ADD COLUMN table_id TEXT REFERENCES table_(id) ON DELETE CASCADE;
CREATE UNIQUE INDEX idx_stats_table_id ON stats(table_id);
ALTER TABLE ownership_string ADD COLUMN table_id TEXT REFERENCES table_(id) ON DELETE CASCADE;
CREATE TABLE IF NOT EXISTS table_result (
id TEXT PRIMARY KEY,
type VARCHAR(128) NOT NULL,
img VARCHAR(128) NOT NULL,
description VARCHAR(128) NOT NULL,
name VARCHAR(128) NOT NULL,
weight INTEGER NOT NULL,
drawn BOOLEAN NOT NULL,
table_id TEXT,
FOREIGN KEY (table_id) REFERENCES table_(id) ON DELETE CASCADE
);
ALTER TABLE stats ADD COLUMN table_result_id TEXT REFERENCES table_result(id) ON DELETE CASCADE;
CREATE UNIQUE INDEX idx_stats_table_result_id ON stats(table_result_id);
CREATE TABLE IF NOT EXISTS table_result_range (
id INTEGER PRIMARY KEY AUTOINCREMENT,
value INTEGER NOT NULL,
table_result_id TEXT,
FOREIGN KEY (table_result_id) REFERENCES table_result(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS playlist ( CREATE TABLE IF NOT EXISTS playlist (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
@@ -82,6 +499,10 @@ CREATE TABLE IF NOT EXISTS playlist (
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
); );
ALTER TABLE stats ADD COLUMN playlist_id TEXT REFERENCES playlist(id) ON DELETE CASCADE;
CREATE UNIQUE INDEX idx_stats_playlist_id ON stats(playlist_id);
ALTER TABLE ownership_string ADD COLUMN playlist_id TEXT REFERENCES playlist(id) ON DELETE CASCADE;
CREATE TABLE IF NOT EXISTS sound ( CREATE TABLE IF NOT EXISTS sound (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
@@ -113,8 +534,13 @@ CREATE TABLE IF NOT EXISTS actor (
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
); );
ALTER TABLE stats ADD COLUMN actor_id TEXT REFERENCES actor(id) ON DELETE CASCADE;
CREATE UNIQUE INDEX idx_stats_actor_id ON stats(actor_id);
ALTER TABLE ownership_string ADD COLUMN actor_id TEXT REFERENCES actor(id) ON DELETE CASCADE;
ALTER TABLE item ADD COLUMN actor_id TEXT REFERENCES actor(id) ON DELETE CASCADE;
CREATE TABLE IF NOT EXISTS token ( CREATE TABLE IF NOT EXISTS token (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(128) NOT NULL, name VARCHAR(128) NOT NULL,
actor_link BOOLEAN NOT NULL, actor_link BOOLEAN NOT NULL,
@@ -179,6 +605,43 @@ CREATE TABLE IF NOT EXISTS token_sight (
FOREIGN KEY (token_id) REFERENCES token(id) ON DELETE CASCADE FOREIGN KEY (token_id) REFERENCES token(id) ON DELETE CASCADE
); );
CREATE TABLE IF NOT EXISTS token_texture (
id INTEGER PRIMARY KEY AUTOINCREMENT,
src VARCHAR(128) NOT NULL,
fit VARCHAR(128) NOT NULL,
tint VARCHAR(128) NOT NULL,
scale_x REAL NOT NULL,
scale_y REAL NOT NULL,
offset_x REAL NOT NULL,
offset_y REAL NOT NULL,
rotation REAL NOT NULL,
anchor_x REAL NOT NULL,
anchor_y REAL NOT NULL,
alpha_threshold REAL NOT NULL,
token_id INTEGER UNIQUE,
FOREIGN KEY (token_id) REFERENCES token(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS token_bar_1 (
id INTEGER PRIMARY KEY AUTOINCREMENT,
attribute VARCHAR(128) NOT NULL,
token_id INTEGER UNIQUE,
FOREIGN KEY (token_id) REFERENCES token(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS token_bar_2 (
id INTEGER PRIMARY KEY AUTOINCREMENT,
attribute VARCHAR(128) NOT NULL,
token_id INTEGER UNIQUE,
FOREIGN KEY (token_id) REFERENCES token(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS token_light ( CREATE TABLE IF NOT EXISTS token_light (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -221,43 +684,6 @@ CREATE TABLE IF NOT EXISTS token_light_darkness (
FOREIGN KEY (token_light_id) REFERENCES token_light(id) ON DELETE CASCADE FOREIGN KEY (token_light_id) REFERENCES token_light(id) ON DELETE CASCADE
); );
CREATE TABLE IF NOT EXISTS token_texture (
id INTEGER PRIMARY KEY AUTOINCREMENT,
src VARCHAR(128) NOT NULL,
fit VARCHAR(128) NOT NULL,
tint VARCHAR(128) NOT NULL,
scale_x REAL NOT NULL,
scale_y REAL NOT NULL,
offset_x REAL NOT NULL,
offset_y REAL NOT NULL,
rotation REAL NOT NULL,
anchor_x REAL NOT NULL,
anchor_y REAL NOT NULL,
alpha_threshold REAL NOT NULL,
token_id INTEGER UNIQUE,
FOREIGN KEY (token_id) REFERENCES token(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS token_bar_1 (
id INTEGER PRIMARY KEY AUTOINCREMENT,
attribute VARCHAR(128) NOT NULL,
token_id INTEGER UNIQUE,
FOREIGN KEY (token_id) REFERENCES token(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS token_bar_2 (
id INTEGER PRIMARY KEY AUTOINCREMENT,
attribute VARCHAR(128) NOT NULL,
token_id INTEGER UNIQUE,
FOREIGN KEY (token_id) REFERENCES token(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS token_occludable ( CREATE TABLE IF NOT EXISTS token_occludable (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -278,384 +704,3 @@ CREATE TABLE IF NOT EXISTS token_turn_maker (
token_id INTEGER UNIQUE, token_id INTEGER UNIQUE,
FOREIGN KEY (token_id) REFERENCES token(id) ON DELETE CASCADE FOREIGN KEY (token_id) REFERENCES token(id) ON DELETE CASCADE
); );
CREATE TABLE IF NOT EXISTS table_ (
id TEXT PRIMARY KEY,
name VARCHAR(128) NOT NULL,
description VARCHAR(128) NOT NULL,
formula VARCHAR(128) NOT NULL,
img VARCHAR(128) NOT NULL,
folder VARCHAR(128) NOT NULL,
sort INTEGER NOT NULL,
replacement BOOLEAN NOT NULL,
display_roll BOOLEAN NOT NULL,
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS table_result (
id TEXT PRIMARY KEY,
type VARCHAR(128) NOT NULL,
img VARCHAR(128) NOT NULL,
description VARCHAR(128) NOT NULL,
name VARCHAR(128) NOT NULL,
weight INTEGER NOT NULL,
drawn BOOLEAN NOT NULL,
table_id INTEGER,
FOREIGN KEY (table_id) REFERENCES table_(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS table_result_range (
id INTEGER PRIMARY KEY AUTOINCREMENT,
range_ INTEGER NOT NULL,
table_result_id INTEGER,
FOREIGN KEY (table_result_id) REFERENCES table_result(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS user (
id TEXT PRIMARY KEY,
name VARCHAR(128) NOT NULL,
avatar VARCHAR(128) NOT NULL,
character VARCHAR(128) NOT NULL,
color VARCHAR(128) NOT NULL,
pronouns VARCHAR(128) NOT NULL,
role INTEGER NOT NULL,
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS setting (
id TEXT PRIMARY KEY,
key_ VARCHAR(128) NOT NULL,
value VARCHAR(128) NOT NULL,
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS hotbar (
id INTEGER PRIMARY KEY,
key_ INTEGER NOT NULL,
value VARCHAR(128) NOT NULL,
user_id TEXT,
FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS active_users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
users VARCHAR(128) NOT NULL,
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS item (
id TEXT PRIMARY KEY,
img VARCHAR(128) NOT NULL,
name VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
folder VARCHAR(128) NOT NULL,
sort INTEGER NOT NULL,
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE,
actor_id TEXT,
FOREIGN KEY (actor_id) REFERENCES actor(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS journal (
id TEXT PRIMARY KEY,
name VARCHAR(128) NOT NULL,
sort INTEGER NOT NULL,
game_id INTEGER UNIQUE,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS world_folder (
id TEXT PRIMARY KEY,
name VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
folder VARCHAR(128) NOT NULL,
sorting VARCHAR(128) NOT NULL,
description VARCHAR(128) NOT NULL,
color VARCHAR(128) NOT NULL,
sort INTEGER NOT NULL,
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS message (
id TEXT PRIMARY KEY,
blind BOOLEAN NOT NULL,
emote BOOLEAN NOT NULL,
style INTEGER NOT NULL,
timestamp DATETIME NOT NULL,
content VARCHAR(128) NOT NULL,
author VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
flavor VARCHAR(128) NOT NULL,
sound VARCHAR(128) NOT NULL,
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS combat (
id TEXT PRIMARY KEY,
type VARCHAR(128) NOT NULL,
scene VARCHAR(128) NOT NULL,
round INTEGER NOT NULL,
turn INTEGER NOT NULL,
sort INTEGER NOT NULL,
active INTEGER NOT NULL,
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS card_deck (
id TEXT PRIMARY KEY,
name VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
description VARCHAR(128) NOT NULL,
img VARCHAR(128) NOT NULL,
folder VARCHAR(128) NOT NULL,
width INTEGER NOT NULL,
height INTEGER NOT NULL,
rotation INTEGER NOT NULL,
sort INTEGER NOT NULL,
display_count BOOLEAN NOT NULL,
game_id INTEGER,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS combatant (
id TEXT PRIMARY KEY,
token_id VARCHAR(128) NOT NULL,
scene_id VARCHAR(128) NOT NULL,
actor_id VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
img VARCHAR(128) NOT NULL,
group_ VARCHAR(128) NOT NULL,
initiative INTEGER NOT NULL,
hidden BOOLEAN NOT NULL,
defeated BOOLEAN NOT NULL,
combat_id TEXT,
FOREIGN KEY (combat_id) REFERENCES combat(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS stats (
id INTEGER PRIMARY KEY AUTOINCREMENT,
core_version VARCHAR(128) NOT NULL,
system_id VARCHAR(128) NOT NULL,
system_version VARCHAR(128) NOT NULL,
last_modified_by VARCHAR(128) NOT NULL,
modified_time DATETIME NOT NULL,
message_id TEXT UNIQUE,
FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE,
combat_id TEXT UNIQUE,
FOREIGN KEY (combat_id) REFERENCES combat(id) ON DELETE CASCADE,
combatant_id TEXT UNIQUE,
FOREIGN KEY (combatant_id) REFERENCES combatant(id) ON DELETE CASCADE,
card_deck_id TEXT UNIQUE,
FOREIGN KEY (card_deck_id) REFERENCES card_deck(id) ON DELETE CASCADE,
card_id TEXT UNIQUE,
FOREIGN KEY (card_id) REFERENCES card(id) ON DELETE CASCADE,
user_id TEXT UNIQUE,
FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE CASCADE,
macro_id TEXT UNIQUE,
FOREIGN KEY (macro_id) REFERENCES macro(id) ON DELETE CASCADE,
world_folder_id TEXT UNIQUE,
FOREIGN KEY (world_folder_id) REFERENCES world_folder(id) ON DELETE CASCADE,
item_id TEXT UNIQUE,
FOREIGN KEY (item_id) REFERENCES item(id) ON DELETE CASCADE,
setting_id TEXT UNIQUE,
FOREIGN KEY (setting_id) REFERENCES setting(id) ON DELETE CASCADE,
journal_page_id TEXT UNIQUE,
FOREIGN KEY (journal_page_id) REFERENCES journal_page(id) ON DELETE CASCADE,
table_id TEXT UNIQUE,
FOREIGN KEY (table_id) REFERENCES table_(id) ON DELETE CASCADE,
table_result_id TEXT UNIQUE,
FOREIGN KEY (table_result_id) REFERENCES table_result(id) ON DELETE CASCADE,
playlist_id TEXT UNIQUE,
FOREIGN KEY (playlist_id) REFERENCES playlist(id) ON DELETE CASCADE,
actor_id TEXT UNIQUE,
FOREIGN KEY (actor_id) REFERENCES actor(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS speaker (
id INTEGER PRIMARY KEY AUTOINCREMENT,
scene VARCHAR(128) NOT NULL,
actor VARCHAR(128) NOT NULL,
token VARCHAR(128) NOT NULL,
alias VARCHAR(128) NOT NULL,
message_id TEXT UNIQUE,
FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS combat_groups (
id TEXT PRIMARY KEY,
groups_ VARCHAR(128) NOT NULL,
combat_id TEXT,
FOREIGN KEY (combat_id) REFERENCES combat(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS card (
id TEXT PRIMARY KEY,
name VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
suit VARCHAR(128) NOT NULL,
description VARCHAR(128) NOT NULL,
origin VARCHAR(128) NOT NULL,
width INTEGER NOT NULL,
height INTEGER NOT NULL,
rotation INTEGER NOT NULL,
value INTEGER NOT NULL,
face INTEGER NOT NULL,
sort INTEGER NOT NULL,
drawn BOOLEAN NOT NULL,
card_deck_id TEXT,
FOREIGN KEY (card_deck_id) REFERENCES card_deck(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS back (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(128) NOT NULL,
text VARCHAR(128) NOT NULL,
card_id TEXT UNIQUE,
FOREIGN KEY (card_id) REFERENCES card(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS face (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(128) NOT NULL,
img VARCHAR(128) NOT NULL,
text VARCHAR(128) NOT NULL,
card_id TEXT,
FOREIGN KEY (card_id) REFERENCES card(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS message_whisper (
id TEXT PRIMARY KEY,
value VARCHAR(128) NOT NULL,
message_id TEXT,
FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS message_rolls (
id TEXT PRIMARY KEY,
value VARCHAR(128) NOT NULL,
message_id TEXT,
FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS journal_page (
id TEXT PRIMARY KEY,
name VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
src VARCHAR(128) NOT NULL,
sort INTEGER NOT NULL,
journal_id TEXT,
FOREIGN KEY (journal_id) REFERENCES journal(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS journal_page_text (
id INTEGER PRIMARY KEY AUTOINCREMENT,
content VARCHAR(128) NOT NULL,
markdown VARCHAR(128) NOT NULL,
format INTEGER NOT NULL,
journal_page_id TEXT,
FOREIGN KEY (journal_page_id) REFERENCES journal_page(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS journal_page_title (
id INTEGER PRIMARY KEY AUTOINCREMENT,
show BOOLEAN NOT NULL,
level INTEGER NOT NULL,
journal_page_id TEXT,
FOREIGN KEY (journal_page_id) REFERENCES journal_page(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS journal_page_video (
id INTEGER PRIMARY KEY AUTOINCREMENT,
controls BOOLEAN NOT NULL,
volume REAL NOT NULL,
journal_page_id TEXT,
FOREIGN KEY (journal_page_id) REFERENCES journal_page(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS ownership_string (
id INTEGER PRIMARY KEY AUTOINCREMENT,
key_ VARCHAR(128) NOT NULL,
value INTEGER NOT NULL,
macro_id TEXT,
FOREIGN KEY (macro_id) REFERENCES macro(id) ON DELETE CASCADE,
item_id TEXT,
FOREIGN KEY (item_id) REFERENCES item(id) ON DELETE CASCADE,
journal_id TEXT,
FOREIGN KEY (journal_id) REFERENCES journal(id) ON DELETE CASCADE,
playlist_id TEXT,
FOREIGN KEY (playlist_id) REFERENCES playlist(id) ON DELETE CASCADE,
actor_id TEXT,
FOREIGN KEY (actor_id) REFERENCES actor(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS system_update (
id INTEGER PRIMARY KEY AUTOINCREMENT,
has_update BOOLEAN NOT NULL DEFAULT FALSE,
version VARCHAR(128) NOT NULL,
game_id INTEGER UNIQUE,
FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE
);

View File

@@ -6,4 +6,5 @@ var (
ErrActionNotFound = errors.New("Action doesn't found") ErrActionNotFound = errors.New("Action doesn't found")
ErrObjTypeNotMatch = errors.New("Provided value type didn't match obj field type") ErrObjTypeNotMatch = errors.New("Provided value type didn't match obj field type")
ErrObjNotPointer = errors.New("Passed obj is not pointer") ErrObjNotPointer = errors.New("Passed obj is not pointer")
ErrUserChannelIsClosed = errors.New("User channel is closed")
) )

View File

@@ -1,6 +1,8 @@
package actions package actions
import ( import (
"gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/temp_models/db"
"gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/temp_models/json"
"gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/transport" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/transport"
"gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/types" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/types"
) )
@@ -22,8 +24,18 @@ func (msg WsSessionMsg) Action(tr *transport.FoundryTransport, status *types.Fou
close(tr.ReadChan.Reconnect()) close(tr.ReadChan.Reconnect())
return nil return nil
} }
// tr.Logger.Warn("World is started. Please, return to setup page to fully initialize database")
// go msg.OnActiveWorld(tr) // select {
// case <-tr.LoggedInChan:
// return ErrUserChannelIsClosed
// default:
// tr.LoggedInChan <- true
// }
// time.Sleep(3 * time.Second)
// types.CloseChannel(tr.LoggedInChan)
go msg.OnActiveWorld(tr)
return nil return nil
} }
@@ -37,13 +49,27 @@ func (msg WsSessionMsg) Action(tr *transport.FoundryTransport, status *types.Fou
} }
func (msg WsSessionMsg) OnActiveWorld(tr *transport.FoundryTransport) error { func (msg WsSessionMsg) OnActiveWorld(tr *transport.FoundryTransport) error {
wsMsg := types.NewWsMessage("world", tr.CurrWsId) msgJson, err := tr.GetJsonData("world")
tr.CurrWsId++
answer, err := tr.HandleWebsocketRequest(wsMsg)
if err != nil { if err != nil {
return err return err
} }
tr.Logger.Info("World data", "answer", string(answer))
tr.Logger.Info("Game data received")
gameJson, err := json.ParseGame(msgJson)
if err != nil {
return err
}
var foundryStateDb db.Game
gameJson.ToDB(&foundryStateDb)
err = foundryStateDb.Insert(tr.DB)
if err != nil {
tr.ReadChan.Err() <- &types.FoundryError{Direction: types.WriterCode, Err: err, Type: types.DbCode}
}
tr.Logger.Info("Game data succesfully inserted to DB")
return nil return nil
} }

View File

@@ -1,5 +1,15 @@
package db package db
import (
"context"
"database/sql"
"errors"
"fmt"
"github.com/jmoiron/sqlx"
"golang.org/x/sync/errgroup"
)
type Actor struct { type Actor struct {
ID string ID string
@@ -8,8 +18,60 @@ type Actor struct {
Type string Type string
Folder string Folder string
Sort int Sort int
PrototypeToken Token PrototypeToken *Token
Stats Stats Stats Stats
Items []*Item Items []*Item
Ownership []OwnershipString Ownership []OwnershipString
} }
func (a *Actor) Query(data *InsertId[uint]) {
data.query = fmt.Sprintf(`
INSERT INTO actor (%s, id, img, name, type, folder, sort)
VALUES ($1, $2, $3, $4, $5, $6, $7)`, data.fieldName)
}
func (a *Actor) InsertObjects(tx *sqlx.Tx) error {
group, ctx := errgroup.WithContext(context.Background())
relId := InsertId[string]{id: a.ID, fieldName: "actor_id"}
InsertWithCtxParallel(group, ctx, tx, a.PrototypeToken, relId)
InsertWithCtxParallel(group, ctx, tx, a.Stats, relId)
InsertSliceParallel(group, tx, a.Ownership, relId)
InsertSliceParallel(group, tx, a.Items, relId)
err := group.Wait()
if err != nil && !errors.Is(err, sql.ErrNoRows) {
return err
}
return nil
}
func (a *Actor) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, a.ID, a.Img, a.Name, a.Type, a.Folder, a.Sort}
_, err := tx.Exec(data.query, args...)
if err != nil {
return err
}
return a.InsertObjects(tx)
}
func (a *Actor) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, a.ID, a.Img, a.Name, a.Type, a.Folder, a.Sort}
_, err := tx.ExecContext(ctx, data.query, args...)
if err != nil {
return err
}
return a.InsertObjects(tx)
}

View File

@@ -23,7 +23,7 @@ type CardDeck struct {
Sort int Sort int
DisplayCount bool DisplayCount bool
Stats Stats Stats Stats
Ownership Ownership Ownership []OwnershipString
Cards []*Card Cards []*Card
} }
@@ -38,7 +38,7 @@ func (c *CardDeck) InsertObjects(tx *sqlx.Tx) error {
relId := InsertId[string]{id: c.ID, fieldName: "card_deck_id"} relId := InsertId[string]{id: c.ID, fieldName: "card_deck_id"}
InsertWithCtxParallel(group, ctx, tx, c.Stats, relId) InsertWithCtxParallel(group, ctx, tx, c.Stats, relId)
InsertWithCtxParallel(group, ctx, tx, c.Ownership, relId) InsertSliceParallel(group, tx, c.Ownership, relId)
InsertSliceParallel(group, tx, c.Cards, relId) InsertSliceParallel(group, tx, c.Cards, relId)
err := group.Wait() err := group.Wait()

View File

@@ -41,9 +41,9 @@ type Game struct {
Items []*Item Items []*Item
Settings []*Setting Settings []*Setting
Journals []*Journal Journals []*Journal
Tables []*Table // Tables []*Table
Playlists []*Playlist Playlists []*Playlist
Actors []Actor // Actors []*Actor
// Scenes []Scene // Scenes []Scene
} }
@@ -62,22 +62,25 @@ func (g *Game) InsertObjects(tx *sqlx.Tx) error {
InsertWithCtxParallel(group, ctx, tx, g.World, relDataString) InsertWithCtxParallel(group, ctx, tx, g.World, relDataString)
InsertWithCtxParallel(group, ctx, tx, g.System, relDataString) InsertWithCtxParallel(group, ctx, tx, g.System, relDataString)
InsertSimpleSliceParallel(group, tx, g.ActiveUsers, &InsertId[uint]{id: g.ID, fieldName: "game_id", tableName: "active_users"}) InsertSimpleSliceParallel(group, tx, g.ActiveUsers,
&InsertId[uint]{id: g.ID, fieldName: "game_id", tableName: "active_users"})
InsertSliceParallel(group, tx, g.Modules, relData) InsertSliceParallel(group, tx, g.Modules, relData)
InsertSliceParallel(group, tx, g.PackageWarnings, relData) InsertSliceParallel(group, tx, g.PackageWarnings, relData)
InsertSliceParallel(group, tx, g.Packs, relDataString) InsertSliceParallel(group, tx, g.Packs, relDataString)
InsertSliceParallel(group, tx, g.Messages, relData) // InsertSliceParallel(group, tx, g.Messages, relData)
InsertSliceParallel(group, tx, g.Combats, relData) // InsertSliceParallel(group, tx, g.Combats, relData)
InsertSliceParallel(group, tx, g.CardDeck, relData) // InsertSliceParallel(group, tx, g.CardDeck, relData)
InsertSliceParallel(group, tx, g.Users, relData) // InsertSliceParallel(group, tx, g.Users, relData)
InsertSliceParallel(group, tx, g.Macros, relData) // InsertSliceParallel(group, tx, g.Macros, relData)
InsertSliceParallel(group, tx, g.Folders, relData) // InsertSliceParallel(group, tx, g.Folders, relData)
InsertSliceParallel(group, tx, g.Items, relData) // InsertSliceParallel(group, tx, g.Items,
InsertSliceParallel(group, tx, g.Settings, relData) // InsertId[string]{id: strconv.FormatUint(uint64(g.ID), 10), fieldName: "game_id"})
InsertSliceParallel(group, tx, g.Journals, relData) // InsertSliceParallel(group, tx, g.Settings, relData)
InsertSliceParallel(group, tx, g.Tables, relData) // InsertSliceParallel(group, tx, g.Journals, relData)
InsertSliceParallel(group, tx, g.Playlists, relData) // InsertSliceParallel(group, tx, g.Tables, relData)
// InsertSliceParallel(group, tx, g.Playlists, relData)
// InsertSliceParallel(group, tx, g.Actors, relData)
err := group.Wait() err := group.Wait()
if err != nil && !errors.Is(err, sql.ErrNoRows) { if err != nil && !errors.Is(err, sql.ErrNoRows) {

View File

@@ -15,14 +15,14 @@ type Index struct {
Type string Type string
} }
func (i *Index) Query(data *InsertId[uint]) { func (i *Index) Query(data *InsertId[string]) {
data.query = ` data.query = `
INSERT INTO index_ (pack_id, id, folder, img, name, type) INSERT INTO index_ (pack_id, id, folder, img, name, type)
VALUES ($1, $2, $3, $4, $5, $6) VALUES ($1, $2, $3, $4, $5, $6)
RETURNING id` RETURNING id`
} }
func (i *Index) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { func (i *Index) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" { if data.query == "" {
return ErrNoQuery return ErrNoQuery
} }
@@ -37,7 +37,7 @@ func (i *Index) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
return nil return nil
} }
func (i *Index) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { func (i *Index) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" { if data.query == "" {
return ErrNoQuery return ErrNoQuery
} }

View File

@@ -22,7 +22,7 @@ type Item struct {
Ownership []OwnershipString Ownership []OwnershipString
} }
func (i *Item) Query(data *InsertId[uint]) { func (i *Item) Query(data *InsertId[string]) {
data.query = fmt.Sprintf(` data.query = fmt.Sprintf(`
INSERT INTO world_folder (%s, id, img, name, type, folder, sort) INSERT INTO world_folder (%s, id, img, name, type, folder, sort)
VALUES ($1, $2, $3, $4, $5, $6, $7) VALUES ($1, $2, $3, $4, $5, $6, $7)
@@ -43,7 +43,7 @@ func (i *Item) InsertObjects(tx *sqlx.Tx) error {
return nil return nil
} }
func (i *Item) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { func (i *Item) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" { if data.query == "" {
return ErrNoQuery return ErrNoQuery
} }
@@ -58,7 +58,7 @@ func (i *Item) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
return i.InsertObjects(tx) return i.InsertObjects(tx)
} }
func (i *Item) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { func (i *Item) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" { if data.query == "" {
return ErrNoQuery return ErrNoQuery
} }

View File

@@ -1,5 +1,15 @@
package db package db
import (
"context"
"database/sql"
"errors"
"fmt"
"github.com/jmoiron/sqlx"
"golang.org/x/sync/errgroup"
)
type Light struct { type Light struct {
ID uint ID uint
@@ -20,6 +30,60 @@ type Light struct {
LightDarkness LightDarkness LightDarkness LightDarkness
} }
func (l *Light) Query(data *InsertId[uint]) {
data.query = fmt.Sprintf(`
INSERT INTO token_light (%s, color, priority, angle, negative, alpha, bright, coloration, dim,
attenuation, luminosity, saturation, contrast, shadows)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)
RETURNING id`, data.fieldName)
}
func (l *Light) InsertObjects(tx *sqlx.Tx) error {
group, ctx := errgroup.WithContext(context.Background())
relId := InsertId[uint]{id: l.ID, fieldName: "token_light_id"}
InsertWithCtxParallel(group, ctx, tx, l.LightAnimation, relId)
InsertWithCtxParallel(group, ctx, tx, l.LightDarkness, relId)
err := group.Wait()
if err != nil && !errors.Is(err, sql.ErrNoRows) {
return err
}
return nil
}
func (l *Light) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, l.Color, l.Priority, l.Angle, l.Negative, l.Alpha, l.Bright, l.Coloration, l.Dim,
l.Attenuation, l.Luminosity, l.Saturation, l.Contrast, l.Shadows}
err := tx.QueryRowx(data.query, args...).Scan(&l.ID)
if err != nil {
return err
}
return nil
}
func (l *Light) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, l.Color, l.Priority, l.Angle, l.Negative, l.Alpha, l.Bright, l.Coloration, l.Dim,
l.Attenuation, l.Luminosity, l.Saturation, l.Contrast, l.Shadows}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&l.ID)
if err != nil {
return err
}
return nil
}
type LightAnimation struct { type LightAnimation struct {
ID uint ID uint
@@ -27,9 +91,84 @@ type LightAnimation struct {
Intensity int Intensity int
Reverse bool Reverse bool
} }
func (l LightAnimation) Query(data *InsertId[uint]) {
data.query = fmt.Sprintf(`
INSERT INTO token_light_animation (%s, speed, intensity, reverse)
VALUES ($1, $2, $3, $4)
RETURNING id`, data.fieldName)
}
func (l LightAnimation) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, l.Speed, l.Intensity, l.Reverse}
err := tx.QueryRowx(data.query, args...).Scan(&l.ID)
if err != nil {
return err
}
return nil
}
func (l LightAnimation) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, l.Speed, l.Intensity, l.Reverse}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&l.ID)
if err != nil {
return err
}
return nil
}
type LightDarkness struct { type LightDarkness struct {
ID uint ID uint
Min float64 Min float64
Max float64 Max float64
} }
func (l LightDarkness) Query(data *InsertId[uint]) {
data.query = fmt.Sprintf(`
INSERT INTO token_light_darkness (%s, min, max)
VALUES ($1, $2, $3, $4)
RETURNING id`, data.fieldName)
}
func (l LightDarkness) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, l.Min, l.Max}
err := tx.QueryRowx(data.query, args...).Scan(&l.ID)
if err != nil {
return err
}
return nil
}
func (l LightDarkness) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, l.Min, l.Max}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&l.ID)
if err != nil {
return err
}
return nil
}

View File

@@ -4,7 +4,7 @@ import (
"context" "context"
"database/sql" "database/sql"
"errors" "errors"
"fmt" "strings"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
@@ -49,12 +49,19 @@ type Module struct {
} }
func (m *Module) Query(data *InsertId[uint]) { func (m *Module) Query(data *InsertId[uint]) {
data.query = fmt.Sprintf(` data.query = `
INSERT INTO module (%s, id, title, description, url, license, readme, bugs, INSERT INTO module (setup_id, id, title, description, url, license, readme, bugs,
changelog, version, manifest, download, socket, protected, exclusive_, persistent_storage, changelog, version, manifest, download, socket, protected, exclusive_, persistent_storage,
core_translation, library, locked, owned, has_storage, active, availability) core_translation, library, locked, owned, has_storage, active, availability)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17,
$18, $19, $20, $21, $22, $23)`, data.fieldName) $18, $19, $20, $21, $22, $23)
ON CONFLICT(id) DO NOTHING`
}
func (m *Module) ConnectGameQuery(data *InsertId[uint]) {
data.query = `
INSERT INTO game_to_module (game_id, module_id)
VALUES ($1, $2)`
} }
func (m *Module) InsertObjects(tx *sqlx.Tx) error { func (m *Module) InsertObjects(tx *sqlx.Tx) error {
@@ -65,19 +72,19 @@ func (m *Module) InsertObjects(tx *sqlx.Tx) error {
InsertWithCtxParallel(group, ctx, tx, m.Relationships, relId) InsertWithCtxParallel(group, ctx, tx, m.Relationships, relId)
InsertWithCtxParallel(group, ctx, tx, m.Compatibility, relId) InsertWithCtxParallel(group, ctx, tx, m.Compatibility, relId)
// scriptRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "scripts"} scriptRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "scripts"}
// InsertSimpleSliceParallel(group, tx, m.Scripts, scriptRelId) InsertSimpleSliceParallel(group, tx, m.Scripts, scriptRelId)
// esModulesRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "es_modules"} esModulesRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "es_modules"}
// InsertSimpleSliceParallel(group, tx, m.Esmodules, esModulesRelId) InsertSimpleSliceParallel(group, tx, m.Esmodules, esModulesRelId)
// tagsRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "tags"} tagsRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "tags"}
// InsertSimpleSliceParallel(group, tx, m.Tags, tagsRelId) InsertSimpleSliceParallel(group, tx, m.Tags, tagsRelId)
// InsertSliceParallel(group, tx, m.Authors, relId) InsertSliceParallel(group, tx, m.Authors, relId)
// InsertSliceParallel(group, tx, m.Media, relId) InsertSliceParallel(group, tx, m.Media, relId)
// InsertSliceParallel(group, tx, m.Styles, relId) InsertSliceParallel(group, tx, m.Styles, relId)
// InsertSliceParallel(group, tx, m.Languages, relId) InsertSliceParallel(group, tx, m.Languages, relId)
// InsertSliceParallel(group, tx, m.Packs, relId) InsertSliceParallel(group, tx, m.Packs, relId)
// InsertSliceParallel(group, tx, m.PackFolders, relId) InsertSliceParallel(group, tx, m.PackFolders, relId)
err := group.Wait() err := group.Wait()
if err != nil && !errors.Is(err, sql.ErrNoRows) { if err != nil && !errors.Is(err, sql.ErrNoRows) {
@@ -86,21 +93,56 @@ func (m *Module) InsertObjects(tx *sqlx.Tx) error {
return nil return nil
} }
func (m *Module) ConnectGame(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, m.ID}
_, err := tx.Exec(data.query, args...)
return err
}
func (m *Module) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { func (m *Module) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" { if data.query == "" {
return ErrNoQuery return ErrNoQuery
} }
args := []any{data.id, m.ID, m.Title, m.Description, m.URL, m.License, m.Readme, m.Bugs, setupID := sql.NullInt64{Int64: int64(data.id), Valid: strings.EqualFold(data.fieldName, "setup_id")}
args := []any{setupID, data.id, m.ID, m.Title, m.Description, m.URL, m.License, m.Readme, m.Bugs,
m.Changelog, m.Version, m.Manifest, m.Download, m.Socket, m.Protected, m.Exclusive, m.PersistentStorage, m.Changelog, m.Version, m.Manifest, m.Download, m.Socket, m.Protected, m.Exclusive, m.PersistentStorage,
m.CoreTranslation, m.Library, m.Locked, m.Owned, m.HasStorage, m.Active, m.Availability} m.CoreTranslation, m.Library, m.Locked, m.Owned, m.HasStorage, m.Active, m.Availability}
_, err := tx.Exec(data.query, args...) res, err := tx.Exec(data.query, args...)
if err != nil { if err != nil {
return err return err
} }
return m.InsertObjects(tx) rowsAffected, err := res.RowsAffected()
if rowsAffected != 0 {
err = m.InsertObjects(tx)
if err != nil {
return err
}
}
dataCopy := *data
m.ConnectGameQuery(&dataCopy)
return m.ConnectGame(tx, &dataCopy)
}
func (m *Module) ConnectGameCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, m.ID}
_, err := tx.ExecContext(ctx, data.query, args...)
return err
} }
func (m *Module) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { func (m *Module) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
@@ -108,14 +150,27 @@ func (m *Module) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint
return ErrNoQuery return ErrNoQuery
} }
args := []any{data.id, m.ID, m.Title, m.Description, m.URL, m.License, m.Readme, m.Bugs, setupID := sql.NullInt64{Int64: int64(data.id), Valid: strings.EqualFold(data.fieldName, "setup_id")}
args := []any{setupID, data.id, m.ID, m.Title, m.Description, m.URL, m.License, m.Readme, m.Bugs,
m.Changelog, m.Version, m.Manifest, m.Download, m.Socket, m.Protected, m.Exclusive, m.PersistentStorage, m.Changelog, m.Version, m.Manifest, m.Download, m.Socket, m.Protected, m.Exclusive, m.PersistentStorage,
m.CoreTranslation, m.Library, m.Locked, m.Owned, m.HasStorage, m.Active, m.Availability} m.CoreTranslation, m.Library, m.Locked, m.Owned, m.HasStorage, m.Active, m.Availability}
_, err := tx.ExecContext(ctx, data.query, args...) res, err := tx.ExecContext(ctx, data.query, args...)
if err != nil { if err != nil {
return err return err
} }
return m.InsertObjects(tx) rowsAffected, err := res.RowsAffected()
if rowsAffected != 0 {
err = m.InsertObjects(tx)
if err != nil {
return err
}
}
dataCopy := *data
m.ConnectGameQuery(&dataCopy)
return m.ConnectGameCtx(ctx, tx, &dataCopy)
} }

View File

@@ -16,7 +16,7 @@ type GameOptions struct {
func (g *GameOptions) Query(data *InsertId[uint]) { func (g *GameOptions) Query(data *InsertId[uint]) {
data.query = ` data.query = `
INSERT INTO featured_content (game_id, language, update_channel, port) INSERT INTO game_options (game_id, language, update_channel, port)
VALUES ($1, $2, $3, $4) VALUES ($1, $2, $3, $4)
RETURNING id` RETURNING id`
} }

View File

@@ -5,16 +5,14 @@ import (
"database/sql" "database/sql"
"errors" "errors"
"fmt" "fmt"
"strconv"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )
type Pack struct { type Pack struct {
ID uint ID string
Key string
Name string Name string
Label string Label string
Banner string Banner string
@@ -30,18 +28,17 @@ type Pack struct {
func (p *Pack) Query(data *InsertId[string]) { func (p *Pack) Query(data *InsertId[string]) {
data.query = fmt.Sprintf(` data.query = fmt.Sprintf(`
INSERT INTO pack (%s, key_, name, label, banner, path, type, system, package_type, package_name) INSERT INTO pack (%s, id, name, label, banner, path, type, system, package_type, package_name)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`, data.fieldName)
RETURNING id`, data.fieldName)
} }
func (p *Pack) InsertObjects(tx *sqlx.Tx) error { func (p *Pack) InsertObjects(tx *sqlx.Tx) error {
group, ctx := errgroup.WithContext(context.Background()) group, ctx := errgroup.WithContext(context.Background())
InsertWithCtxParallel(group, ctx, tx, p.Ownership, InsertWithCtxParallel(group, ctx, tx, p.Ownership,
InsertId[string]{id: strconv.FormatUint(uint64(p.ID), 10), fieldName: "pack_id"}) InsertId[string]{id: p.ID, fieldName: "pack_id"})
relId := InsertId[uint]{id: p.ID, fieldName: "pack_id"} relId := InsertId[string]{id: p.ID, fieldName: "pack_id"}
InsertSliceParallel(group, tx, p.Index, relId) InsertSliceParallel(group, tx, p.Index, relId)
InsertSliceParallel(group, tx, p.Folders, relId) InsertSliceParallel(group, tx, p.Folders, relId)
@@ -57,9 +54,10 @@ func (p *Pack) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
return ErrNoQuery return ErrNoQuery
} }
args := []any{data.id, p.Key, p.Name, p.Label, p.Banner, p.Path, p.Type, p.System, p.PackageType, p.PackageName} args := []any{data.id, p.ID, p.Name, p.Label, p.Banner, p.Path, p.Type,
p.System, p.PackageType, p.PackageName}
err := tx.QueryRowx(data.query, args...).Scan(&p.ID) _, err := tx.Exec(data.query, args...)
if err != nil { if err != nil {
return err return err
} }
@@ -72,9 +70,10 @@ func (p *Pack) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string
return ErrNoQuery return ErrNoQuery
} }
args := []any{data.id, p.Key, p.Name, p.Label, p.Banner, p.Path, p.Type, p.System, p.PackageType, p.PackageName} args := []any{data.id, p.ID, p.Name, p.Label, p.Banner, p.Path, p.Type,
p.System, p.PackageType, p.PackageName}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&p.ID) _, err := tx.ExecContext(ctx, data.query, args...)
if err != nil { if err != nil {
return err return err
} }
@@ -92,13 +91,13 @@ type PackFolder struct {
Sort int Sort int
} }
func (p *PackFolder) Query(data *InsertId[uint]) { func (p *PackFolder) Query(data *InsertId[string]) {
data.query = fmt.Sprintf(` data.query = fmt.Sprintf(`
INSERT INTO pack_folder (%s, id, description, name, sorting, type, sort) INSERT INTO pack_folder (%s, id, description, name, sorting, type, sort)
VALUES ($1, $2, $3, $4, $5, $6, $7)`, data.fieldName) VALUES ($1, $2, $3, $4, $5, $6, $7)`, data.fieldName)
} }
func (p *PackFolder) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { func (p *PackFolder) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" { if data.query == "" {
return ErrNoQuery return ErrNoQuery
} }
@@ -113,7 +112,7 @@ func (p *PackFolder) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
return nil return nil
} }
func (p *PackFolder) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { func (p *PackFolder) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" { if data.query == "" {
return ErrNoQuery return ErrNoQuery
} }

View File

@@ -83,8 +83,26 @@ func (p *PackageWarningsData) InsertObjects(tx *sqlx.Tx) error {
func (p *PackageWarningsData) Query(data *InsertId[uint]) { func (p *PackageWarningsData) Query(data *InsertId[uint]) {
data.query = ` data.query = `
INSERT INTO package_warnings_data (package_warnings_id, id, type, reinstallable, manifest) INSERT INTO package_warnings_data (id, type, reinstallable, manifest)
VALUES ($1, $2, $3, $4, $5)` VALUES ($1, $2, $3, $4)
ON CONFLICT(id) DO NOTHING`
}
func (p *PackageWarningsData) ConnectGameQuery(data *InsertId[uint]) {
data.query = `
INSERT INTO package_warnings_to_data (package_warnings_id, package_warnings_data_id)
VALUES ($1, $2)`
}
func (p *PackageWarningsData) ConnectGame(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, p.ID}
_, err := tx.Exec(data.query, args...)
return err
} }
func (p *PackageWarningsData) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { func (p *PackageWarningsData) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
@@ -92,14 +110,36 @@ func (p *PackageWarningsData) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
return ErrNoQuery return ErrNoQuery
} }
args := []any{data.id, p.ID, p.Type, p.Reinstallable, p.Manifest} args := []any{p.ID, p.Type, p.Reinstallable, p.Manifest}
_, err := tx.Exec(data.query, args...) res, err := tx.Exec(data.query, args...)
if err != nil { if err != nil {
return err return err
} }
return p.InsertObjects(tx) rowsAffected, err := res.RowsAffected()
if rowsAffected != 0 {
err = p.InsertObjects(tx)
}
if err != nil {
return err
}
dataCopy := *data
p.ConnectGameQuery(&dataCopy)
return p.ConnectGame(tx, &dataCopy)
}
func (p *PackageWarningsData) ConnectGameCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, p.ID}
_, err := tx.ExecContext(ctx, data.query, args...)
return err
} }
func (p *PackageWarningsData) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { func (p *PackageWarningsData) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
@@ -107,12 +147,23 @@ func (p *PackageWarningsData) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *
return ErrNoQuery return ErrNoQuery
} }
args := []any{data.id, p.ID, p.Type, p.Reinstallable, p.Manifest} args := []any{p.ID, p.Type, p.Reinstallable, p.Manifest}
_, err := tx.ExecContext(ctx, data.query, args...) res, err := tx.ExecContext(ctx, data.query, args...)
if err != nil { if err != nil {
return err return err
} }
return p.InsertObjects(tx) rowsAffected, err := res.RowsAffected()
if rowsAffected != 0 {
err = p.InsertObjects(tx)
}
if err != nil {
return err
}
dataCopy := *data
p.ConnectGameQuery(&dataCopy)
return p.ConnectGameCtx(ctx, tx, &dataCopy)
} }

View File

@@ -1,5 +1,15 @@
package db package db
import (
"context"
"database/sql"
"errors"
"fmt"
"github.com/jmoiron/sqlx"
"golang.org/x/sync/errgroup"
)
type Ring struct { type Ring struct {
ID uint ID uint
@@ -9,6 +19,57 @@ type Ring struct {
Subject Subject Subject Subject
} }
func (r *Ring) Query(data *InsertId[uint]) {
data.query = fmt.Sprintf(`
INSERT INTO ring (%s, enabled, effects)
VALUES ($1, $2, $3)
RETURNING id`, data.fieldName)
}
func (r *Ring) InsertObjects(tx *sqlx.Tx) error {
group, ctx := errgroup.WithContext(context.Background())
relId := InsertId[uint]{id: r.ID, fieldName: "ring_id"}
InsertWithCtxParallel(group, ctx, tx, r.RingColors, relId)
InsertWithCtxParallel(group, ctx, tx, r.Subject, relId)
err := group.Wait()
if err != nil && !errors.Is(err, sql.ErrNoRows) {
return err
}
return nil
}
func (r *Ring) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, r.Enabled, r.Effects}
err := tx.QueryRowx(data.query, args...).Scan(&r.ID)
if err != nil {
return err
}
return nil
}
func (r *Ring) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, r.Enabled, r.Effects}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&r.ID)
if err != nil {
return err
}
return nil
}
type RingColors struct { type RingColors struct {
ID uint ID uint
@@ -16,9 +77,83 @@ type RingColors struct {
Background string Background string
} }
func (r RingColors) Query(data *InsertId[uint]) {
data.query = fmt.Sprintf(`
INSERT INTO ring_colors (%s, ring, background)
VALUES ($1, $2, $3)
RETURNING id`, data.fieldName)
}
func (r RingColors) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, r.Ring, r.Background}
err := tx.QueryRowx(data.query, args...).Scan(&r.ID)
if err != nil {
return err
}
return nil
}
func (r RingColors) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, r.Ring, r.Background}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&r.ID)
if err != nil {
return err
}
return nil
}
type Subject struct { type Subject struct {
ID uint ID uint
Scale int Scale int
Texture string Texture string
} }
func (s Subject) Query(data *InsertId[uint]) {
data.query = fmt.Sprintf(`
INSERT INTO ring_colors (%s, scale, texture)
VALUES ($1, $2, $3)
RETURNING id`, data.fieldName)
}
func (s Subject) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, s.Scale, s.Texture}
err := tx.QueryRowx(data.query, args...).Scan(&s.ID)
if err != nil {
return err
}
return nil
}
func (s Subject) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, s.Scale, s.Texture}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&s.ID)
if err != nil {
return err
}
return nil
}

View File

@@ -21,7 +21,7 @@ type Scene struct {
Grid SceneGrid Grid SceneGrid
TokenVision bool TokenVision bool
Drawings []SceneDrawing Drawings []SceneDrawing
Tokens []Token Tokens []*Token
Lights []SceneLight Lights []SceneLight
Notes []Note Notes []Note
Sounds []ScenesSound Sounds []ScenesSound
@@ -119,7 +119,7 @@ type SceneLight struct {
Rotation int Rotation int
Walls bool Walls bool
Vision bool Vision bool
Config Light Config *Light
Hidden bool Hidden bool
Elevation int Elevation int
} }

View File

@@ -4,7 +4,7 @@ import (
"context" "context"
"database/sql" "database/sql"
"errors" "errors"
"fmt" "strings"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
@@ -48,12 +48,18 @@ type System struct {
} }
func (s *System) Query(data *InsertId[string]) { func (s *System) Query(data *InsertId[string]) {
data.query = fmt.Sprintf(` data.query = `
INSERT INTO system (%s, id, title, description, url, license, bugs, changelog, version, manifest, INSERT INTO system (setup_id, id, title, description, url, license, bugs, changelog, version, manifest,
download, background, primary_token_attribute, availability, socket, protected, exclusive_, download, background, primary_token_attribute, availability, socket, protected, exclusive_,
persistent_storage, locked, owned, has_storage) persistent_storage, locked, owned, has_storage)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21)`, VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21)
data.fieldName) ON CONFLICT(id) DO NOTHING`
}
func (s *System) ConnectGameQuery(data *InsertId[string]) {
data.query = `
INSERT INTO game_to_systems (game_id, system_id)
VALUES ($1, $2)`
} }
func (s *System) InsertObjects(tx *sqlx.Tx) error { func (s *System) InsertObjects(tx *sqlx.Tx) error {
@@ -86,22 +92,57 @@ func (s *System) InsertObjects(tx *sqlx.Tx) error {
return nil return nil
} }
func (s *System) ConnectGame(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, s.ID}
_, err := tx.Exec(data.query, args...)
return err
}
func (s *System) Insert(tx *sqlx.Tx, data *InsertId[string]) error { func (s *System) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" { if data.query == "" {
return ErrNoQuery return ErrNoQuery
} }
args := []any{data.id, s.ID, s.Title, s.Description, s.URL, s.License, s.Bugs, setupID := sql.NullString{String: data.id, Valid: strings.EqualFold(data.fieldName, "setup_id")}
args := []any{setupID, s.ID, s.Title, s.Description, s.URL, s.License, s.Bugs,
s.Changelog, s.Version, s.Manifest, s.Download, s.Background, s.Changelog, s.Version, s.Manifest, s.Download, s.Background,
s.PrimaryTokenAttribute, s.Availability, s.Socket, s.Protected, s.Exclusive, s.PrimaryTokenAttribute, s.Availability, s.Socket, s.Protected, s.Exclusive,
s.PersistentStorage, s.Locked, s.Owned, s.HasStorage} s.PersistentStorage, s.Locked, s.Owned, s.HasStorage}
_, err := tx.Exec(data.query, args...) res, err := tx.Exec(data.query, args...)
if err != nil { if err != nil {
return err return err
} }
return s.InsertObjects(tx) rowsAffected, err := res.RowsAffected()
if rowsAffected != 0 {
err = s.InsertObjects(tx)
if err != nil {
return err
}
}
dataCopy := *data
s.ConnectGameQuery(&dataCopy)
return s.ConnectGame(tx, &dataCopy)
}
func (s *System) ConnectGameCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, s.ID}
_, err := tx.ExecContext(ctx, data.query, args...)
return err
} }
func (s *System) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { func (s *System) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
@@ -109,15 +150,28 @@ func (s *System) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[stri
return ErrNoQuery return ErrNoQuery
} }
args := []any{data.id, s.ID, s.Title, s.Description, s.URL, s.License, s.Bugs, setupID := sql.NullString{String: data.id, Valid: strings.EqualFold(data.fieldName, "setup_id")}
args := []any{setupID, s.ID, s.Title, s.Description, s.URL, s.License, s.Bugs,
s.Changelog, s.Version, s.Manifest, s.Download, s.Background, s.Changelog, s.Version, s.Manifest, s.Download, s.Background,
s.PrimaryTokenAttribute, s.Availability, s.Socket, s.Protected, s.Exclusive, s.PrimaryTokenAttribute, s.Availability, s.Socket, s.Protected, s.Exclusive,
s.PersistentStorage, s.Locked, s.Owned, s.HasStorage} s.PersistentStorage, s.Locked, s.Owned, s.HasStorage}
_, err := tx.ExecContext(ctx, data.query, args...) res, err := tx.ExecContext(ctx, data.query, args...)
if err != nil { if err != nil {
return err return err
} }
return s.InsertObjects(tx) rowsAffected, err := res.RowsAffected()
if rowsAffected != 0 {
err = s.InsertObjects(tx)
if err != nil {
return err
}
}
dataCopy := *data
s.ConnectGameQuery(&dataCopy)
return s.ConnectGameCtx(ctx, tx, &dataCopy)
} }

View File

@@ -1,5 +1,15 @@
package db package db
import (
"context"
"database/sql"
"errors"
"fmt"
"github.com/jmoiron/sqlx"
"golang.org/x/sync/errgroup"
)
type Token struct { type Token struct {
ID uint ID uint
@@ -16,16 +26,76 @@ type Token struct {
Alpha int Alpha int
Width float64 Width float64
Height float64 Height float64
Ring Ring Ring *Ring
Sight TokenSight Sight *TokenSight
Texture TokenTexture Texture *TokenTexture
Bar1 TokenBar Bar1 TokenBar
Bar2 TokenBar Bar2 TokenBar
Light Light Light *Light
Occludable TokenOccludable Occludable TokenOccludable
TurnMarker TokenTurnMarker TurnMarker TokenTurnMarker
} }
func (t *Token) Query(data *InsertId[string]) {
data.query = fmt.Sprintf(`
INSERT INTO token (%s, name, actor_link_ append_number, prepend_adjective, lock_rotation, random_img, display_name,
display_bars, disposition, rotation, alpha, width, height)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)
RETURNING id`, data.fieldName)
}
func (t *Token) InsertObjects(tx *sqlx.Tx) error {
group, ctx := errgroup.WithContext(context.Background())
relId := InsertId[uint]{id: t.ID, fieldName: "token_id"}
InsertWithCtxParallel(group, ctx, tx, t.Ring, relId)
InsertWithCtxParallel(group, ctx, tx, t.Sight, relId)
InsertWithCtxParallel(group, ctx, tx, t.Texture, relId)
InsertWithCtxParallel(group, ctx, tx, t.Bar1, InsertId[uint]{id: t.ID, fieldName: "token_id", tableName: "token_bar_1"})
InsertWithCtxParallel(group, ctx, tx, t.Bar1, InsertId[uint]{id: t.ID, fieldName: "token_id", tableName: "token_bar_2"})
InsertWithCtxParallel(group, ctx, tx, t.Light, relId)
InsertWithCtxParallel(group, ctx, tx, t.Occludable, relId)
InsertWithCtxParallel(group, ctx, tx, t.TurnMarker, relId)
err := group.Wait()
if err != nil && !errors.Is(err, sql.ErrNoRows) {
return err
}
return nil
}
func (t *Token) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, t.Name, t.ActorLink, t.AppendNumber, t.PrependAdjective, t.LockRotation, t.RandomImg,
t.DisplayName, t.DisplayBars, t.Disposition, t.Rotation, t.Alpha, t.Width, t.Height}
err := tx.QueryRowx(data.query, args...).Scan(&t.ID)
if err != nil {
return err
}
return t.InsertObjects(tx)
}
func (t *Token) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, t.Name, t.ActorLink, t.AppendNumber, t.PrependAdjective, t.LockRotation, t.RandomImg,
t.DisplayName, t.DisplayBars, t.Disposition, t.Rotation, t.Alpha, t.Width, t.Height}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&t.ID)
if err != nil {
return err
}
return t.InsertObjects(tx)
}
type TokenTexture struct { type TokenTexture struct {
ID uint ID uint
@@ -42,6 +112,43 @@ type TokenTexture struct {
AlphaThreshold float64 AlphaThreshold float64
} }
func (t *TokenTexture) Query(data *InsertId[uint]) {
data.query = fmt.Sprintf(`
INSERT INTO token_texture (%s, src, fit, tint, scale_x, scale_y, offset_x, offset_y, rotation, anchor_x, anchor_y, alpha_threshold)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
RETURNING id`, data.fieldName)
}
func (t *TokenTexture) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, t.Src, t.Fit, t.Tint, t.ScaleX, t.ScaleY, t.OffsetX, t.OffsetY, t.Rotation, t.AnchorX, t.AnchorY, t.AlphaThreshold}
err := tx.QueryRowx(data.query, args...).Scan(&t.ID)
if err != nil {
return err
}
return nil
}
func (t *TokenTexture) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, t.Src, t.Fit, t.Tint, t.ScaleX, t.ScaleY, t.OffsetX, t.OffsetY, t.Rotation, t.AnchorX, t.AnchorY, t.AlphaThreshold}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&t.ID)
if err != nil {
return err
}
return nil
}
type TokenSight struct { type TokenSight struct {
ID uint ID uint
@@ -54,18 +161,129 @@ type TokenSight struct {
Enabled bool Enabled bool
} }
func (t *TokenSight) Query(data *InsertId[uint]) {
data.query = fmt.Sprintf(`
INSERT INTO token_sight (%s, color, vision_mode, range_, angle, attenuation, brightness, enabled)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
RETURNING id`, data.fieldName)
}
func (t *TokenSight) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, t.Color, t.VisionMode, t.Range, t.Angle, t.Attenuation, t.Brightness, t.Enabled}
err := tx.QueryRowx(data.query, args...).Scan(&t.ID)
if err != nil {
return err
}
return nil
}
func (t *TokenSight) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, t.Color, t.VisionMode, t.Range, t.Angle, t.Attenuation, t.Brightness, t.Enabled}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&t.ID)
if err != nil {
return err
}
return nil
}
type TokenBar struct { type TokenBar struct {
ID uint ID uint
Attribute string Attribute string
} }
func (t TokenBar) Query(data *InsertId[uint]) {
data.query = fmt.Sprintf(`
INSERT INTO %s (%s, attribute)
VALUES ($1, $2)
RETURNING id`, data.tableName, data.fieldName)
}
func (t TokenBar) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, t.Attribute}
err := tx.QueryRowx(data.query, args...).Scan(&t.ID)
if err != nil {
return err
}
return nil
}
func (t TokenBar) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, t.Attribute}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&t.ID)
if err != nil {
return err
}
return nil
}
type TokenOccludable struct { type TokenOccludable struct {
ID uint ID uint
Radius int Radius int
} }
func (t TokenOccludable) Query(data *InsertId[uint]) {
data.query = fmt.Sprintf(`
INSERT INTO token_occludable (%s, radius)
VALUES ($1, $2)
RETURNING id`, data.fieldName)
}
func (t TokenOccludable) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, t.Radius}
err := tx.QueryRowx(data.query, args...).Scan(&t.ID)
if err != nil {
return err
}
return nil
}
func (t TokenOccludable) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, t.Radius}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&t.ID)
if err != nil {
return err
}
return nil
}
type TokenTurnMarker struct { type TokenTurnMarker struct {
ID uint ID uint
@@ -74,3 +292,40 @@ type TokenTurnMarker struct {
Src string Src string
Disposition bool Disposition bool
} }
func (t TokenTurnMarker) Query(data *InsertId[uint]) {
data.query = fmt.Sprintf(`
INSERT INTO token_turn_maker (%s, mode, animation, src, disposition)
VALUES ($1, $2, $3, $4, $5)
RETURNING id`, data.fieldName)
}
func (t TokenTurnMarker) Insert(tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, t.Mode, t.Animation, t.Src, t.Disposition}
err := tx.QueryRowx(data.query, args...).Scan(&t.ID)
if err != nil {
return err
}
return nil
}
func (t TokenTurnMarker) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error {
if data.query == "" {
return ErrNoQuery
}
args := []any{data.id, t.Mode, t.Animation, t.Src, t.Disposition}
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&t.ID)
if err != nil {
return err
}
return nil
}

View File

@@ -7,6 +7,7 @@ import (
"time" "time"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/mattn/go-sqlite3"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )
@@ -172,3 +173,14 @@ func DeleteAllSeq(db *sqlx.DB) error {
return nil return nil
} }
func IsErrUniqueConstraint(err error) {
if sqliteErr, ok := err.(sqlite3.Error); ok {
// SQLITE_CONSTRAINT_UNIQUE (extended code 2067)
// or SQLITE_CONSTRAINT (basic code 19)
if sqliteErr.ExtendedCode == sqlite3.ErrConstraintUnique ||
sqliteErr.Code == sqlite3.ErrConstraint {
fmt.Println("Record already exists")
}
}
}

View File

@@ -48,10 +48,14 @@ type World struct {
func (w *World) Query(data *InsertId[string]) { func (w *World) Query(data *InsertId[string]) {
data.query = fmt.Sprintf(` data.query = fmt.Sprintf(`
INSERT INTO world (%s, id, title, description, version, system, background, join_theme, INSERT INTO world (%[1]s, id, title, description, version, system, background, join_theme,
core_version, system_version, last_played, playtime, availability, next_session, socket, core_version, system_version, last_played, playtime, availability, next_session, socket,
protected, exclusive_, persistent_storage, locked, owned, has_storage) protected, exclusive_, persistent_storage, locked, owned, has_storage)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21)`, VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21)
ON CONFLICT(id) DO UPDATE SET
%[1]s = EXCLUDED.%[1]s,
updated_at = datetime('now')
RETURNING (created_at == updated_at) AS was_inserted`,
data.fieldName) data.fieldName)
} }
@@ -92,13 +96,17 @@ func (w *World) Insert(tx *sqlx.Tx, data *InsertId[string]) error {
w.CoreVersion, w.SystemVersion, w.LastPlayed, w.Playtime, w.Availability, w.NextSession, w.Socket, w.CoreVersion, w.SystemVersion, w.LastPlayed, w.Playtime, w.Availability, w.NextSession, w.Socket,
w.Protected, w.Exclusive, w.PersistentStorage, w.Locked, w.Owned, w.HasStorage} w.Protected, w.Exclusive, w.PersistentStorage, w.Locked, w.Owned, w.HasStorage}
_, err := tx.Exec(data.query, args...) var isInserted bool
err := tx.QueryRowx(data.query, args...).Scan(&isInserted)
if err != nil { if err != nil {
return err return err
} }
if isInserted {
return w.InsertObjects(tx) return w.InsertObjects(tx)
} }
return nil
}
func (w *World) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { func (w *World) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error {
if data.query == "" { if data.query == "" {
@@ -109,10 +117,14 @@ func (w *World) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[strin
w.CoreVersion, w.SystemVersion, w.LastPlayed, w.Playtime, w.Availability, w.NextSession, w.Socket, w.CoreVersion, w.SystemVersion, w.LastPlayed, w.Playtime, w.Availability, w.NextSession, w.Socket,
w.Protected, w.Exclusive, w.PersistentStorage, w.Locked, w.Owned, w.HasStorage} w.Protected, w.Exclusive, w.PersistentStorage, w.Locked, w.Owned, w.HasStorage}
_, err := tx.ExecContext(ctx, data.query, args...) var isInserted bool
err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&isInserted)
if err != nil { if err != nil {
return err return err
} }
if isInserted {
return w.InsertObjects(tx) return w.InsertObjects(tx)
} }
return nil
}

View File

@@ -18,24 +18,28 @@ type Actor struct {
// ActorsEffects []any `json:"effects"` // ActorsEffects []any `json:"effects"`
} }
func (a *Actor) ToDB(dest *db.Actor) bool { func (a *Actor) ToDB(dest **db.Actor) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.Img = a.Img actor := &db.Actor{
dest.Name = a.Name Img: a.Img,
dest.Type = a.Type Name: a.Name,
dest.Folder = a.Folder Type: a.Type,
dest.Sort = a.Sort Folder: a.Folder,
dest.ID = a.ID Sort: a.Sort,
ID: a.ID,
}
a.PrototypeToken.ToDB(&dest.PrototypeToken) a.PrototypeToken.ToDB(&actor.PrototypeToken)
a.Stats.ToDB(&dest.Stats) a.Stats.ToDB(&actor.Stats)
OwnershipToDB(&dest.Ownership, a.Ownership) OwnershipToDB(&actor.Ownership, a.Ownership)
CopySliceToDB(&dest.Items, a.Items) CopySliceToDB(&actor.Items, a.Items)
*dest = actor
return true return true
} }

View File

@@ -13,7 +13,7 @@ type CardDeck struct {
Rotation int `json:"rotation"` Rotation int `json:"rotation"`
DisplayCount bool `json:"displayCount"` DisplayCount bool `json:"displayCount"`
Stats Stats `json:"_stats"` Stats Stats `json:"_stats"`
Ownership Ownership `json:"ownership"` Ownership map[string]int `json:"ownership,omitempty"`
Folder string `json:"folder"` Folder string `json:"folder"`
Sort int `json:"sort"` Sort int `json:"sort"`
ID string `json:"_id"` ID string `json:"_id"`
@@ -41,8 +41,8 @@ func (c *CardDeck) ToDB(dest **db.CardDeck) bool {
} }
c.Stats.ToDB(&cardDeck.Stats) c.Stats.ToDB(&cardDeck.Stats)
c.Ownership.ToDB(&cardDeck.Ownership)
OwnershipToDB(&cardDeck.Ownership, c.Ownership)
CopySliceToDB(&cardDeck.Cards, c.Cards) CopySliceToDB(&cardDeck.Cards, c.Cards)
*dest = cardDeck *dest = cardDeck

View File

@@ -1,6 +1,7 @@
package json package json
import ( import (
"encoding/json"
"sync" "sync"
"gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/temp_models/db" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/temp_models/db"
@@ -40,6 +41,19 @@ type Game struct {
// Template Template `json:"template"` // Template Template `json:"template"`
} }
func ParseGame(data []byte) (*Game, error) {
var modelGame []Game
err := json.Unmarshal(data, &modelGame)
if err != nil {
return nil, err
}
if len(modelGame) > 1 {
return nil, ErrorSetupMoreThanOne
}
return &modelGame[0], nil
}
func (g *Game) ToDB(dest *db.Game) bool { func (g *Game) ToDB(dest *db.Game) bool {
dest.UserID = g.UserID dest.UserID = g.UserID
dest.DemoMode = g.DemoMode dest.DemoMode = g.DemoMode

View File

@@ -39,6 +39,8 @@ func (j *JournalPage) ToDB(dest **db.JournalPage) bool {
OwnershipToDB(&journalPage.Ownership, j.Ownership) OwnershipToDB(&journalPage.Ownership, j.Ownership)
*dest = journalPage
return true return true
} }

View File

@@ -20,27 +20,31 @@ type Light struct {
Color string `json:"color"` Color string `json:"color"`
} }
func (l *Light) ToDB(dest *db.Light) bool { func (l *Light) ToDB(dest **db.Light) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.Alpha = l.Alpha light := &db.Light{
dest.Angle = l.Angle Alpha: l.Alpha,
dest.Bright = l.Bright Angle: l.Angle,
dest.Coloration = l.Coloration Bright: l.Bright,
dest.Dim = l.Dim Coloration: l.Coloration,
dest.Attenuation = l.Attenuation Dim: l.Dim,
dest.Luminosity = l.Luminosity Attenuation: l.Attenuation,
dest.Saturation = l.Saturation Luminosity: l.Luminosity,
dest.Contrast = l.Contrast Saturation: l.Saturation,
dest.Shadows = l.Shadows Contrast: l.Contrast,
dest.Negative = l.Negative Shadows: l.Shadows,
dest.Priority = l.Priority Negative: l.Negative,
dest.Color = l.Color Priority: l.Priority,
Color: l.Color,
}
l.LightAnimation.ToDB(&dest.LightAnimation) l.LightAnimation.ToDB(&light.LightAnimation)
l.LightDarkness.ToDB(&dest.LightDarkness) l.LightDarkness.ToDB(&light.LightDarkness)
*dest = light
return true return true
} }

View File

@@ -36,7 +36,7 @@ func (p *Pack) ToDB(dest **db.Pack) bool {
System: p.System, System: p.System,
PackageType: p.PackageType, PackageType: p.PackageType,
PackageName: p.PackageName, PackageName: p.PackageName,
Key: p.Id, ID: p.Id,
} }
p.Ownership.ToDB(&pack.Ownership) p.Ownership.ToDB(&pack.Ownership)

View File

@@ -45,6 +45,8 @@ func (p *Playlist) ToDB(dest **db.Playlist) bool {
CopySliceToDB(&playlist.Sounds, p.Sounds) CopySliceToDB(&playlist.Sounds, p.Sounds)
*dest = playlist
return true return true
} }

View File

@@ -9,15 +9,20 @@ type Ring struct {
Subject Subject `json:"subject"` Subject Subject `json:"subject"`
} }
func (r *Ring) ToDB(dest *db.Ring) bool { func (r *Ring) ToDB(dest **db.Ring) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.Enabled = r.Enabled ring := &db.Ring{
dest.Effects = r.Effects Enabled: r.Enabled,
r.RingColors.ToDB(&dest.RingColors) Effects: r.Effects,
r.Subject.ToDB(&dest.Subject) }
r.RingColors.ToDB(&ring.RingColors)
r.Subject.ToDB(&ring.Subject)
*dest = ring
return true return true
} }

View File

@@ -41,6 +41,8 @@ func (t *Table) ToDB(dest **db.Table) bool {
CopySliceToDB(&table.Results, t.Results) CopySliceToDB(&table.Results, t.Results)
*dest = table
return true return true
} }

View File

@@ -29,33 +29,37 @@ type Token struct {
// DetectionModes []any `json:"detectionModes"` // DetectionModes []any `json:"detectionModes"`
} }
func (t *Token) ToDB(dest *db.Token) bool { func (t *Token) ToDB(dest **db.Token) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.DisplayName = t.DisplayName token := &db.Token{
dest.DisplayBars = t.DisplayBars DisplayName: t.DisplayName,
dest.Disposition = t.Disposition DisplayBars: t.DisplayBars,
dest.Name = t.Name Disposition: t.Disposition,
dest.ActorLink = t.ActorLink Name: t.Name,
dest.AppendNumber = t.AppendNumber ActorLink: t.ActorLink,
dest.PrependAdjective = t.PrependAdjective AppendNumber: t.AppendNumber,
dest.Width = t.Width PrependAdjective: t.PrependAdjective,
dest.Height = t.Height Width: t.Width,
dest.LockRotation = t.LockRotation Height: t.Height,
dest.Rotation = t.Rotation LockRotation: t.LockRotation,
dest.Alpha = t.Alpha Rotation: t.Rotation,
dest.RandomImg = t.RandomImg Alpha: t.Alpha,
RandomImg: t.RandomImg,
}
t.Ring.ToDB(&dest.Ring) t.Ring.ToDB(&token.Ring)
t.Sight.ToDB(&dest.Sight) t.Sight.ToDB(&token.Sight)
t.Texture.ToDB(&dest.Texture) t.Texture.ToDB(&token.Texture)
t.Bar1.ToDB(&dest.Bar1) t.Bar1.ToDB(&token.Bar1)
t.Bar2.ToDB(&dest.Bar2) t.Bar2.ToDB(&token.Bar2)
t.Light.ToDB(&dest.Light) t.Light.ToDB(&token.Light)
t.Occludable.ToDB(&dest.Occludable) t.Occludable.ToDB(&token.Occludable)
t.TurnMarker.ToDB(&dest.TurnMarker) t.TurnMarker.ToDB(&token.TurnMarker)
*dest = token
return true return true
} }
@@ -74,22 +78,26 @@ type TokenTexture struct {
AlphaThreshold float64 `json:"alphaThreshold"` AlphaThreshold float64 `json:"alphaThreshold"`
} }
func (t *TokenTexture) ToDB(dest *db.TokenTexture) bool { func (t *TokenTexture) ToDB(dest **db.TokenTexture) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.Src = t.Src texture := &db.TokenTexture{
dest.ScaleX = t.ScaleX Src: t.Src,
dest.ScaleY = t.ScaleY ScaleX: t.ScaleX,
dest.OffsetX = t.OffsetX ScaleY: t.ScaleY,
dest.OffsetY = t.OffsetY OffsetX: t.OffsetX,
dest.Rotation = t.Rotation OffsetY: t.OffsetY,
dest.AnchorX = t.AnchorX Rotation: t.Rotation,
dest.AnchorY = t.AnchorY AnchorX: t.AnchorX,
dest.Fit = t.Fit AnchorY: t.AnchorY,
dest.Tint = t.Tint Fit: t.Fit,
dest.AlphaThreshold = t.AlphaThreshold Tint: t.Tint,
AlphaThreshold: t.AlphaThreshold,
}
*dest = texture
return true return true
} }
@@ -104,18 +112,22 @@ type TokenSight struct {
Brightness float64 Brightness float64
} }
func (t *TokenSight) ToDB(dest *db.TokenSight) bool { func (t *TokenSight) ToDB(dest **db.TokenSight) bool {
if dest == nil { if dest == nil {
return false return false
} }
dest.Color = t.Color sight := &db.TokenSight{
dest.Enabled = t.Enabled Color: t.Color,
dest.Range = t.Range Enabled: t.Enabled,
dest.Angle = t.Angle Range: t.Range,
dest.VisionMode = t.VisionMode Angle: t.Angle,
dest.Attenuation = t.Attenuation VisionMode: t.VisionMode,
dest.Brightness = t.Brightness Attenuation: t.Attenuation,
Brightness: t.Brightness,
}
*dest = sight
return true return true
} }

View File

@@ -20,33 +20,22 @@ func (tr *FoundryTransport) FillDBWithFoundryData() {
// return // return
// } // }
// err = tr.InitWorldsData(idState) err = tr.InitWorldsData()
// if err != nil { if err != nil {
// tr.ReadChan.Err() <- &types.FoundryError{Direction: types.WriterCode, Err: err, Type: types.DbCode} tr.ReadChan.Err() <- &types.FoundryError{Direction: types.WriterCode, Err: err, Type: types.DbCode}
// return return
// } }
} }
func (tr *FoundryTransport) InitSetupData() error { func (tr *FoundryTransport) InitSetupData() error {
db.DeleteAll(tr.DB) db.DeleteAll(tr.DB)
db.DeleteAllSeq(tr.DB) db.DeleteAllSeq(tr.DB)
for k := range requests.PathToSetupState {
err := tr.InsertJsonDataToDB(k) return tr.InsertSetupToDB()
if err != nil {
return err
}
}
return nil
} }
func (tr *FoundryTransport) InsertJsonDataToDB(statePath string) error { func (tr *FoundryTransport) InsertSetupToDB() error {
_, ok1 := requests.PathToSetupState[statePath] msgJson, err := tr.GetJsonDataByType(requests.SetupPath)
_, ok2 := requests.PathToWorldState[statePath]
if !ok1 && !ok2 {
return ErrorStateTypeNotExist
}
msgJson, err := tr.GetJsonData(statePath)
if err != nil { if err != nil {
return err return err
} }
@@ -67,35 +56,49 @@ func (tr *FoundryTransport) InsertJsonDataToDB(statePath string) error {
return nil return nil
} }
// func (tr *FoundryTransport) InitWorldsData(idState int64) error { func (tr *FoundryTransport) InitWorldsData() error {
// worlds, err := tr.Models.FoundryState.GetWorlds(idState) worlds := []string{"kingmaker"} //TODO: get world name from database
// if err != nil {
// return err
// }
// tr.Logger.Debug("Worlds", "len", len(worlds))
// for i := range worlds { for i := range worlds {
// worldName := worlds[i].TextId worldName := worlds[i]
// tr.InitWorldData(worldName) tr.InitWorldData(worldName)
// _, err = tr.Http.PostReturnToSetup() _, err := tr.Http.PostReturnToSetup()
// if err != nil { if err != nil {
// return err return err
// } }
// } }
// return nil return nil
// } }
// func (tr *FoundryTransport) InitWorldData(worldName string) error { func (tr *FoundryTransport) InitWorldData(worldName string) error {
// tr.Logger.Debug("World name", "name", worldName) tr.Logger.Debug("World name", "name", worldName)
// err := tr.LaunchWorld(worldName) err := tr.LaunchWorld(worldName)
// if err != nil { if err != nil {
// return err return err
// } }
// for k := range requests.PathToWorldState { return tr.InsertGameToDB()
// err := tr.InsertJsonDataToDB(k) }
// if err != nil {
// return err func (tr *FoundryTransport) InsertGameToDB() error {
// } err := tr.ConnectToWorld()
// } if err != nil {
// return nil return err
// } }
msgJson, err := tr.GetJsonData("world")
if err != nil {
return err
}
tr.Logger.Info("Game data received")
gameJson, err := json.ParseGame(msgJson)
if err != nil {
return err
}
var foundryStateDb db.Game
gameJson.ToDB(&foundryStateDb)
return foundryStateDb.Insert(tr.DB)
}

View File

@@ -8,4 +8,6 @@ var (
ErrorTimeout = errors.New("Answer has not been received after timeout") ErrorTimeout = errors.New("Answer has not been received after timeout")
ErrorStateTypeNotExist = errors.New("State type does not exists") ErrorStateTypeNotExist = errors.New("State type does not exists")
ErrorAuthPassWrong = errors.New("Authentication password is wrong") ErrorAuthPassWrong = errors.New("Authentication password is wrong")
ErrorChannelIsClosed = errors.New("Channel has been closed")
ErrorUserIsNotConnected = errors.New("User is not connected")
) )

View File

@@ -17,6 +17,7 @@ type FoundryTransport struct {
ChanMutex sync.Mutex ChanMutex sync.Mutex
ReadChan types.ReadChannels ReadChan types.ReadChannels
ExchangeChan types.ExchangeChannels ExchangeChan types.ExchangeChannels
LoggedInChan chan bool
Http *requests.FoundryHttpRequest Http *requests.FoundryHttpRequest
ReconnectTimeout time.Duration ReconnectTimeout time.Duration

View File

@@ -31,13 +31,7 @@ func (tr *FoundryTransport) InitWebSocketConnection() error {
dialer := websocket.DefaultDialer dialer := websocket.DefaultDialer
dialer.ReadBufferSize = 128 * 1024 * 1024 dialer.ReadBufferSize = 128 * 1024 * 1024
dialer.WriteBufferSize = 128 * 1024 * 1024 dialer.WriteBufferSize = 128 * 1024 * 1024
// dialer.Jar = tr.Http.Jar
// ur, err := url.Parse(fmt.Sprintf("http://%s", tr.Http.Host))
// if err != nil {
// return err
// }
// fmt.Printf("TEST:%v:%v\n", u.String(), dialer.Jar.Cookies(&u))
wsConn, resp, err := dialer.Dial(u.String(), wsHeader) wsConn, resp, err := dialer.Dial(u.String(), wsHeader)
if err != nil { if err != nil {
return err return err
@@ -47,8 +41,6 @@ func (tr *FoundryTransport) InitWebSocketConnection() error {
for i := range cookies { for i := range cookies {
fmt.Printf("TEST%d: %v\n", i, cookies[i]) fmt.Printf("TEST%d: %v\n", i, cookies[i])
} }
// fmt.Printf("TEST1: %v\n")
// fmt.Printf("TEST2: %v\n", wsHeader)
tr.WsConn = wsConn tr.WsConn = wsConn
tr.CurrWsId = 0 tr.CurrWsId = 0
@@ -118,19 +110,47 @@ func (tr *FoundryTransport) ListenWebSocket() {
} }
} }
func (tr *FoundryTransport) ConnectToWorld() error {
err := tr.LogInToWorld()
if err != nil {
return err
}
tr.Logger.Info("World is started. Succesfully logged into world")
tr.LoggedInChan = make(chan bool)
close(tr.ReadChan.Reconnect())
val, ok := <-tr.LoggedInChan
if !ok {
return ErrorChannelIsClosed
}
if !val {
return ErrorUserIsNotConnected
}
return nil
}
func (tr *FoundryTransport) SendOnlyCodeRequest(code string) error { func (tr *FoundryTransport) SendOnlyCodeRequest(code string) error {
tr.Logger.Debug("WS: Data has been send\n", "msg", types.CodesRespToReq[code]) tr.Logger.Debug("WS: Data has been send\n", "msg", types.CodesRespToReq[code])
return tr.WsConn.WriteMessage(websocket.TextMessage, []byte(types.CodesRespToReq[code])) return tr.WsConn.WriteMessage(websocket.TextMessage, []byte(types.CodesRespToReq[code]))
} }
func (tr *FoundryTransport) GetJsonData(stateType string) ([]byte, error) { func (tr *FoundryTransport) GetJsonDataByType(stateType string) ([]byte, error) {
msg := types.NewWsMessageByPage(stateType, tr.CurrWsId) msg := types.NewWsMessageByPage(stateType, tr.CurrWsId)
tr.CurrWsId++ tr.CurrWsId++
return tr.HandleWebsocketRequest(msg) return tr.HandleWebsocketRequest(msg)
} }
func (tr *FoundryTransport) GetJsonData(msg string) ([]byte, error) {
wsMsg := types.NewWsMessage(msg, tr.CurrWsId)
tr.CurrWsId++
return tr.HandleWebsocketRequest(wsMsg)
}
func (tr *FoundryTransport) CloseWebSocketConn() error { func (tr *FoundryTransport) CloseWebSocketConn() error {
tr.Logger.Debug("Websocket has been closed") tr.Logger.Debug("Websocket has been closed")
return tr.WsConn.Close() return tr.WsConn.Close()