From 9da77307afc890178ee2f8144b36ed69dd761811 Mon Sep 17 00:00:00 2001 From: Sky Johnson Date: Fri, 4 Oct 2024 12:06:21 -0500 Subject: [PATCH] char logic change, huge db optimization --- database/auth.db | Bin 36864 -> 45056 bytes database/blueprints.db | Bin 16384 -> 16384 bytes database/fights.db | Bin 24576 -> 45056 bytes database/live.db | Bin 90112 -> 188416 bytes database/scripts/create.php | 106 +++++++++++++++++++---- public/assets/css/dragon.css | 7 ++ src/auth.php | 3 +- src/components.php | 10 ++- src/controllers/auth.php | 1 + src/controllers/char.php | 1 - src/database.php | 39 +++++++-- src/helpers.php | 39 +++++++-- src/models/char.php | 26 ------ src/models/user.php | 16 ++++ templates/components/char_bar.php | 4 + templates/components/debug_query_log.php | 5 ++ templates/layouts/basic.php | 2 + templates/pages/chars/select.php | 5 +- 18 files changed, 202 insertions(+), 62 deletions(-) create mode 100644 templates/components/debug_query_log.php diff --git a/database/auth.db b/database/auth.db index 414a797717f98616657f19564ce1b7fb04ca1ba8..5c2b22dde10a43378ffea81b1789673d7dc7ae2c 100644 GIT binary patch delta 583 zcmZozz|`=7NhdhaC$l6~AuYcsH?c&)m_dMniHX5ML4kpRfenbcffxo@C+Zk0vN7o8 z?c(MC!NA3Rnt{)k|1AF^-ru~|yr+0>@u={udPhLD_4<3b#rCTsDgFmg`r=haH(if3mNHkC;j`aoME-sa2-tOkc+S+b;!Bs{PVQFUNDnCnP%&qR)z*x zgt&mQ$jJYb0f>;nX1Rh#{DN%E!kop~l@K+r82Ddp7Ib*PKlzot49hnL{%@NF3*PW^ UaWFEAbAtV{s6b&+g8+mC0Nz`xNB{r; delta 1088 zcmb_aOHUI~6u#4`*lByYATb2Nv{A$$uX*(`EEKSm(pG3GZLPbR&h#;TOzE_g;sR#j zP8VeUfMM%`n8pppjcbfcw!1KMiNGz1+g{C+@!&Hc^BHB0gLSrz@yGb=mXle9m4m} z3}3XmyVh;EX1DA2;d3+G1shx1(*doc^J;HjAEsq%yik;CN2aX+FTP*--8nt^y9SDkKi&!v?84`472GU(Jg|mt5Q`p4_l4OWyRq!K*`P>cx=%7 zp-sDsSwRn_Em|;LaJV;eDbGwZS(^!YQtSSiBC}Ta1^LEcf?ZGMmdQB3mJ6?t6LF@I zAOoRPGbOLCOw-||B$o-)D{GZiC1s{bnjNFaF_Ljo?n%}=$xxTHv~k=D`aNx8hH3EC zYF??z3d)sLrK}d3Q~7jJsf&8uaeIUJRFa8VIkf0sjz5XULS;EnSF(ev1v2z-#$U}Q z8kra;uEZOQkeR#Z-JwrKU6fg-~`S!s6!zxVTBib4g3PW3qzY;Zse#SjwL$ zv8p+~S}2T{rJCM!I5r-K#3(nnTyxI{h3G;oFXmD-Jw2G<=6ovelLLM+T31Jcaw+Ir zDy1uhFq>(tdS(}LDW%k`&}*}*=>j)9NnIF`tKHIu&b%QQ#+Zq5iW0Av93%h1rt=d1 z=91OeFdTgW=o|WJJZI6m;oL(bHoPDE?Ho?vz1YdbOdWU+VJJQQ`3|6W=o8v+bvt*^ zSRd}eWaWaz<7uUYU&Dv7w(EaJZPNE2444l9I%suAzM|^{W-y$rG7j4^x&T0L4A@sF zK95}?G-&4dG$#opMTr7SbAps{iwxkZPh2xZw=_zXx3-eAn~uj+Y#q4IXWp5 diff --git a/database/blueprints.db b/database/blueprints.db index 16c4108939c89ac62046aa5063ea80f7928c814b..553cf727fab188a64ef1a83b180f2b9f98b2ec6c 100644 GIT binary patch delta 184 zcmZo@U~Fh$oRG=MDaF9U!o7)8YGdOHj?Efeub8;nD;e3v#l;!>11HPyW=)>SB``UU zkB_~$G^wPrAa(LZK6#enoct0HWAZ{?&&hmznye|MMTsSo&+#d-fmlhIlkNDGC%bTq zfpsP(Cj$kOCp+>ha1^BGrItX|vZm!HmllJ~sp0csD@rZSECw0tH2DOd#$;iBb(Wmc Q~(0Lqd)8vp#5)8l!D6g2x7{GCyu*t%z>PsqdiZsWd-Bw-p&}-?&t)e9)Wr?&=50+zw#0p@qG1>IA z+UuVCEqdyw=&>KDm(JLj1h5Bk*dFK~DFQstjG5m&^BCm3{-x!|QuKpp=*Hqj>5GzO zm3|PSR4P@}-xKwhJ@or>_C`Hh_g)vhtdzd>tj|dD*d>U0WQr5A8Q1 zH&mRoMHVg&vH|KJzO3xl_V=w1li0l&$Sfjzu1*K;Hh*l{_xe{W6~CuW*R_APJL0r+ zblmKmi&yr!Xr6UXj@qi*vEA-IQ*qg;X3_1Fu4tdNTDs96^#jqh->4(gqt#0N;_=eF z<>I{41C^Y4FNCJ^P7lt_dv|``X+(IFK0jWVch>)t&bz&{Q~PGmx}IBa@5+rD=~D0J z%r-W#ITv2KAXhA9z2M<8f zpEWsImP%O~=;TNnufp8SNgIdmtz!;Y)q7|P2!nSrGMwJ^yh-GGzZpV8Ig)YY#(pqb ziV}zRPtCJdSA2Ij-G1Or#%o2!!Q}F4B*)9qccZz{FfdIZl4E}yFP-jg059@Q&0!=x zf1EeByCM2A3Oqk9M$+kB_z@bW^=&vS57A^{qXF#*))=Q`w_KN{ui z(pgZtxgzPtvL_DJWwLv8Y|pmd%d<{LU8x*>@O8I&e5!|>guOMR)#d8d_D=2To^^Sz zY|Er7CskIKbE@pDeR_3Di?*(@r(0^Ur`CB=VaIO=>bs^hmTxC=-pE023D>QWJGw4xEVz2>eumnfH0M|LtY<-< z=;q=y(XHmPsw0YvYBIX9BqkASe<#q<>s%0YTw$e71~JuO9dP5vuBtZqSLy$#NcRU) zE+xvWjwi)ljy*S2b$s#r;wa?hfdB#sAbpGeZOr zKmY**5I_I{1Q0*~0R;H}e{ui;1Q0*~0R#|0009ILKmdWw7vTQ?=C3g`L;wK<5I_I{ z1Q0*~0R#|0fcyXC00IagfB*srAb delta 629 zcmY+BF-yZh7>4hfTrW+Ul2A0-Hnq-5wGng@UAstibtqMe6ap5F#cs{k(enL*I*TA3 z99)WHaqt(2g5V&fBK`o+<}Rt>LLOei_dUGVd5v|3_$q4}2%$K8#bfkVH!K4ckFl#$EUbV_F>=#hnx zcePx|&os)PXq1m>HvH#JUkdqFiSp%Cluwil-?~N%2H#q3HN2YJ@Y+z4=lBQ*in3Vg z%xF0fX*s~O__z_xbNZxqID;wi^hSwNCdAXRlH;_V5IW939jGK8)$XAZRA|G4T8;kCn;Nxj8~YdHuB-0p$vM05>6gGH=1IP(!br+t89pQrs_KD^ki0oC4M)B%7_;XW Di-*fd diff --git a/database/live.db b/database/live.db index 8720f4aaf85d8eeb1aa23cfcf7f973b46496b3e7..a18505cd8dc192b457735f3870ae09b916bf9a38 100644 GIT binary patch delta 3646 zcmbtXYiv_h9KWZ%x3_m|d)IB{Yz)>r##jpjnS+2KL?+IJWZB9dN;KG%wyc$|E$yA# zB=OP-o0=fZoA^ykAbv6?E>{!dCxS5~e2_qxfPj$5ON~sv@CYM#&bg1?+Yb5QP446T zU%%fu_kYg+oc$-5{U<8h`nPu{#kjCLlN*kRLI+hv*=*DnL7*rqfbKQu*00v-whmu_ zT9f{PK_VM}A1i|VWB$J46%O(&Y((uv?qi{V1R!> z@efe^zxf)c9dbmiD&{GE9x3K{FS4`SInGV&Z&Ca$1apO_>p&eRpY5%6Ih`dQtma|q z$Rmn>q{d?a%>ifZKb;ghJMTxGQ|QnX54v9a*3NP15^7Dj(?I8UD8 zWXvq9-P+gHInX6+>v^?nN3~GqGTm82^AG7KGlj1K`T%=p3d3Msp~20s6&Lf`%cF%H=zOKSOVETuKyJU{mml2`VfNj;}50B*I zcm#?PZb3p;Yn_oQ6#`n2;FRc)&s-J&tNe5M5&-S;>8r~@yE1om764ZM>Dr5u^EJi+ zTYVsGaM_j042AQlks z4|aFARd5{UYn2LvJ=?Yqc41{SlNM1j61|-MGm&hyIp8KAph(B^dsApeVa6HK4rA1C zJAT^HoOI%O>2`ffd2J4gKkhl~idNpP9I3Q(zi}V4C)u>4gZZ64Lbux|?LM2sbHbB# z|Lor34&eoBy6~$kU1wUQ zht=<7%p?=aM%$z`9Pp5vjPZ@XJ5mJ}B*MaKQETV4v}) ziAz45ibrB3chz>|!uTdT13NDS4CmlPXfX@x>%oD2@i5>6Paw01!*lVqhU3|JcvXi@}eMD}nSst4n!t!Bq(@3K-U0lZ1e# z2xhBI^-L-+Xk>A<7POkOKAJIpDxQL1-{^gm%1yDEPMcX92#xVvyj#nk0pPhgEEsq0sG=Nbf z(X`^KR|~Dlmw}hqVSJ-5>qP?Xx3W*wEs4H0dDh$5vS?cv)$TZ*6_&V|Ns6E1z3#K_ zg6oFi{WvFjY;%u{A^rm&llMpv?MYY-H8qZ8yO>QlBjZLH!oWqq>hjX96|W>sm) zJQieOXHWu#nr9&sH?`&(;qt4W2dsH5gsZ87g^d9g27_Q?l_<~L6+oMO?(ShJ)yl$6 zXeno{e8gNNDdzQ5At6-Js)d=8U~-TN=`I9^1}xwRs5Km$$r95ABi(G?R0Yg0=sIk7ytkO delta 1280 zcmZ`&U1$_n6u#%)JHPvLck?&9Y3z=P(XEjZDpX$z#;{OON=!DOw5d#H$L!)}lkTi& z)lz306I)De1ih5fhd!t;p)^RDQu-jYV4!)h4;F;JM5#3NC4Fj&h4#)YHd~1Y&N-L) zzI*=Wo(p#(7w$-VMvfdV)g1H0RCUs-nR`(J0iXk>i4f`$+9C9*Bp3GVZS6rX+aQTg zz@7vEV^3};6PH;_T#vB_h_WnVS$2z^V@H;}6nlRcbRx}AH5CF;n*{LC)M=+$(A#uf zC%Aa2`|sOHL!U8|PtLR-MyO*#=|wq}z2)TxPL#c|yR_tkzZ$bDOr@nE%7E7?}r z94uND+i6@8P3>Cndajx@O4%}EkJvK%lie3xe!~t%$u@Xe4ULfu{Fjfkl0JAQAXbT? zgncrd0elT98TLNkPVe#{~(f25KSp zHNZcan+ZrX>-8a^T{<2?krnoRTd;|H}k?38dbw@zoM^fbMUUAOiTT%GXZ94$yeK45O)fQc;Zd zc9@aE0OMBWWS}a)Re`?;yxp>5^!7sC2+?5b$4^`3vQu-L&&uF%ZXlmC^8*JD=gek= z!zgU$oq0Hf-;wxA9$o~Q|DK28?m2}jMkWLEW1FET9IG1M4i1w4!zdI9x88exec('CREATE INDEX idx_sessions_user_id ON sessions (user_id)'); created_or_error($r, 'sessions'); @@ -86,20 +87,21 @@ if ($database === AUTH) { token TEXT NOT NULL UNIQUE, created INTEGER NOT NULL )'); + $db->exec('CREATE INDEX idx_tokens_user_id ON tokens (user_id)'); created_or_error($r, 'tokens'); eln(green('Created database: ') . 'auth.db'); - exit(0); + if ($database !== 'reset') exit(0); } /* The Fights database is used to store information about fights. A fight is a battle between two characters; players or NPCs. */ -if ($database === FIGHTS) { - if ($drop) { +if ($database === FIGHTS || $database === 'reset') { + if ($drop || $database === 'reset') { unlink(__DIR__ . '/../' . FIGHTS); eln(red('Dropped database: ') . 'fights.db'); } @@ -148,6 +150,8 @@ if ($database === FIGHTS) { created DATETIME DEFAULT CURRENT_TIMESTAMP, updated DATETIME DEFAULT CURRENT_TIMESTAMP )'); + // create an index for char_id + $db->exec('CREATE INDEX idx_pve_char_id ON pve (char_id)'); created_or_error($r, 'pve'); @@ -191,6 +195,10 @@ if ($database === FIGHTS) { created DATETIME DEFAULT CURRENT_TIMESTAMP, updated DATETIME DEFAULT CURRENT_TIMESTAMP )'); + // Create an index for char1_id + $db->exec('CREATE INDEX idx_pvp_char1_id ON pvp (char1_id)'); + // Create an index for char2_id + $db->exec('CREATE INDEX idx_pvp_char2_id ON pvp (char2_id)'); created_or_error($r, 'pvp'); @@ -201,6 +209,8 @@ if ($database === FIGHTS) { fight_id INTEGER NOT NULL, info TEXT NOT NULL )'); + // Create an index for fight_id + $db->exec('CREATE INDEX idx_pve_logs_fight_id ON pve_logs (fight_id)'); created_or_error($r, 'pve_logs'); @@ -211,19 +221,21 @@ if ($database === FIGHTS) { fight_id INTEGER NOT NULL, info TEXT NOT NULL )'); + // Create an index for fight_id + $db->exec('CREATE INDEX idx_pvp_logs_fight_id ON pvp_logs (fight_id)'); created_or_error($r, 'pvp_logs'); eln(green('Created database: ') . 'fights.db'); - exit(0); + if ($database !== 'reset') exit(0); } /* The Blueprints database is used to store information about items, weapons, armor, etc. */ -if ($database === BPS) { - if ($drop) { +if ($database === BPS || $database === 'reset') { + if ($drop || $database === 'reset') { unlink(__DIR__ . '/../' . BPS); eln(red('Dropped database: ') . 'blueprints.db'); } @@ -294,20 +306,38 @@ if ($database === BPS) { eln(green('Created database: ') . 'blueprints.db'); - exit(0); + if ($database !== 'reset') exit(0); } /* The Live database is used to store information about players, NPCs, guilds, etc. */ -if ($database === LIVE) { - if ($drop) { +if ($database === LIVE || $database === 'reset') { + if ($drop || $database === 'reset') { unlink(__DIR__ . '/../' . LIVE); eln(red('Dropped database: ') . 'live.db'); } $db = new SQLite3(__DIR__ . '/../' . LIVE); + // Blog posts + $db->exec('DROP TABLE IF EXISTS blog'); + $r = $db->exec('CREATE TABLE blog ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + author_id INTEGER NOT NULL, + title TEXT NOT NULL, + slug TEXT NOT NULL UNIQUE, + content TEXT NOT NULL, + created DATETIME DEFAULT CURRENT_TIMESTAMP, + updated DATETIME DEFAULT CURRENT_TIMESTAMP + )'); + // Create an index for author_id + $db->exec('CREATE INDEX idx_blog_author_id ON blog (author_id)'); + // Create an index for the slug + $db->exec('CREATE INDEX idx_blog_slug ON blog (slug)'); + + created_or_error($r, 'blog'); + // Characters $db->exec('DROP TABLE IF EXISTS characters'); $r = $db->exec('CREATE TABLE characters ( @@ -322,8 +352,8 @@ if ($database === LIVE) { max_hp INTEGER NOT NULL DEFAULT 20, current_mp INTEGER NOT NULL DEFAULT 10, max_mp INTEGER NOT NULL DEFAULT 10, - current_tp INTEGER NOT NULL DEFAULT 0, - max_tp INTEGER NOT NULL DEFAULT 0, + current_tp INTEGER NOT NULL DEFAULT 1, + max_tp INTEGER NOT NULL DEFAULT 1, power INTEGER NOT NULL DEFAULT 0, accuracy INTEGER NOT NULL DEFAULT 0, penetration INTEGER NOT NULL DEFAULT 0, @@ -337,6 +367,8 @@ if ($database === LIVE) { inv_slots INTEGER NOT NULL DEFAULT 10, attrib_points INTEGER NOT NULL DEFAULT 0 )'); + // Create an index for user_id + $db->exec('CREATE INDEX idx_characters_user_id ON characters (user_id)'); created_or_error($r, 'characters'); @@ -367,6 +399,8 @@ if ($database === LIVE) { max_hp INTEGER NOT NULL DEFAULT 0, max_mp INTEGER NOT NULL DEFAULT 0 )'); + // Create an index for char_id + $db->exec('CREATE INDEX idx_char_gear_char_id ON char_gear (char_id)'); created_or_error($r, 'char_gear'); @@ -376,18 +410,22 @@ if ($database === LIVE) { char_id INTEGER NOT NULL, item_id INTEGER NOT NULL )'); + // Create an index for char_id + $db->exec('CREATE INDEX idx_inventory_char_id ON inventory (char_id)'); created_or_error($r, 'inventory'); // Player wallet - $db->exec('DROP TABLE IF EXISTS char_wallets'); - $r = $db->exec('CREATE TABLE char_wallets ( - char_id INTEGER NOT NULL, + $db->exec('DROP TABLE IF EXISTS wallets'); + $r = $db->exec('CREATE TABLE wallets ( + user_id INTEGER NOT NULL, silver INTEGER NOT NULL DEFAULT 10, stargem INTEGER NOT NULL DEFAULT 0 )'); + // Create an index for user_id + $db->exec('CREATE INDEX idx_wallets_user_id ON wallets (user_id)'); - created_or_error($r, 'char_wallets'); + created_or_error($r, 'wallets'); // Player bank $db->exec('DROP TABLE IF EXISTS char_bank'); @@ -399,6 +437,8 @@ if ($database === LIVE) { can_collect INTEGER NOT NULL DEFAULT 1, last_collected DATETIME DEFAULT CURRENT_TIMESTAMP )'); + // Create an index for char_id + $db->exec('CREATE INDEX idx_bank_char_id ON bank (char_id)'); created_or_error($r, 'bank'); @@ -408,6 +448,10 @@ if ($database === LIVE) { char_id INTEGER NOT NULL, item_id INTEGER NOT NULL )'); + // Create an index for char_id + $db->exec('CREATE INDEX idx_banked_items_char_id ON banked_items (char_id)'); + // Create an index for item_id + $db->exec('CREATE INDEX idx_banked_items_item_id ON banked_items (item_id)'); created_or_error($r, 'banked_items'); @@ -423,6 +467,8 @@ if ($database === LIVE) { created DATETIME DEFAULT CURRENT_TIMESTAMP, updated DATETIME DEFAULT CURRENT_TIMESTAMP )'); + // Create an index for the x, y location + $db->exec('CREATE INDEX idx_towns_location ON towns (x, y)'); created_or_error($r, 'towns'); @@ -443,6 +489,8 @@ if ($database === LIVE) { created DATETIME DEFAULT CURRENT_TIMESTAMP, updated DATETIME DEFAULT CURRENT_TIMESTAMP )'); + // Create an index for the x, y location + $db->exec('CREATE INDEX idx_shops_location ON shops (x, y)'); created_or_error($r, 'shops'); @@ -459,6 +507,8 @@ if ($database === LIVE) { created DATETIME DEFAULT CURRENT_TIMESTAMP, updated DATETIME DEFAULT CURRENT_TIMESTAMP )'); + // Create an index for the x, y location + $db->exec('CREATE INDEX idx_inns_location ON inns (x, y)'); created_or_error($r, 'inns'); @@ -474,6 +524,8 @@ if ($database === LIVE) { created DATETIME DEFAULT CURRENT_TIMESTAMP, updated DATETIME DEFAULT CURRENT_TIMESTAMP )'); + // Create an index for leader_id + $db->exec('CREATE INDEX idx_guilds_leader_id ON guilds (leader_id)'); created_or_error($r, 'guilds'); @@ -485,6 +537,8 @@ if ($database === LIVE) { name TEXT NOT NULL, permissions TEXT NOT NULL )'); + // Create an index for guild_id + $db->exec('CREATE INDEX idx_guild_ranks_guild_id ON guild_ranks (guild_id)'); created_or_error($r, 'guild_ranks'); @@ -498,6 +552,10 @@ if ($database === LIVE) { donated INTEGER NOT NULL DEFAULT 0, joined DATETIME DEFAULT CURRENT_TIMESTAMP )'); + // Create an index for guild_id + $db->exec('CREATE INDEX idx_guild_members_guild_id ON guild_members (guild_id)'); + // Create an index for char_id + $db->exec('CREATE INDEX idx_guild_members_char_id ON guild_members (char_id)'); created_or_error($r, 'guild_members'); @@ -514,6 +572,8 @@ if ($database === LIVE) { created DATETIME DEFAULT CURRENT_TIMESTAMP, updated DATETIME DEFAULT CURRENT_TIMESTAMP )'); + // Create an index for the x, y location + $db->exec('CREATE INDEX idx_npcs_location ON npcs (x, y)'); created_or_error($r, 'npcs'); @@ -524,6 +584,8 @@ if ($database === LIVE) { town_id INTEGER NOT NULL, rep INTEGER NOT NULL DEFAULT 0 )'); + // Create an index for char_id + $db->exec('CREATE INDEX idx_char_town_rep_char_id ON char_town_rep (char_id)'); created_or_error($r, 'char_town_rep'); @@ -568,6 +630,8 @@ if ($database === LIVE) { trait_id INTEGER NOT NULL, value INTEGER NOT NULL DEFAULT 0 )'); + // Create an index for char_id + $db->exec('CREATE INDEX idx_char_traits_char_id ON char_traits (char_id)'); created_or_error($r, 'char_traits'); @@ -579,12 +643,16 @@ if ($database === LIVE) { y INTEGER NOT NULL, currently INTEGER NOT NULL DEFAULT 0 )'); + // Create an index for char_id + $db->exec('CREATE INDEX idx_char_locations_char_id ON char_locations (char_id)'); + // Create an index for x, y location + $db->exec('CREATE INDEX idx_char_locations_location ON char_locations (x, y)'); created_or_error($r, 'char_locations'); eln(green('Created database: ') . 'live.db'); - exit(0); + if ($database !== 'reset') exit(0); } function created_or_error(bool $result, string $table): void diff --git a/public/assets/css/dragon.css b/public/assets/css/dragon.css index a408291..8a5e3f7 100644 --- a/public/assets/css/dragon.css +++ b/public/assets/css/dragon.css @@ -258,3 +258,10 @@ span.badge { top: 0; left: 0; } + +#debug-query-log { + padding: 2rem; + font-size: 14px; + color: #666; + font-family: monospace; +} diff --git a/src/auth.php b/src/auth.php index 11b8f8c..9b503d4 100644 --- a/src/auth.php +++ b/src/auth.php @@ -63,8 +63,7 @@ function must_have_character(): void { // If there is a character selected, make sure the session is up to date. if ($_SESSION['user']['char_id'] !== 0) { - $char = db_query(db_live(), 'SELECT * FROM characters WHERE id = :c', [':c' => $_SESSION['user']['char_id']])->fetchArray(SQLITE3_ASSOC); - $_SESSION['char'] = $char; + char(); return; } diff --git a/src/components.php b/src/components.php index 5e6445f..dd29d1f 100644 --- a/src/components.php +++ b/src/components.php @@ -19,7 +19,7 @@ function c_logout_button(): string */ function c_char_bar(): string { - if (!char()) return ''; + if (char() === false) return ''; return render('components/char_bar', ['char' => char()]); } @@ -30,3 +30,11 @@ function c_left_nav(int $activeTab): string { return render('components/left_nav', ['activeTab' => $activeTab]); } + +/** + * Render the debug query log. + */ +function c_debug_query_log(): string +{ + return render('components/debug_query_log'); +} diff --git a/src/controllers/auth.php b/src/controllers/auth.php index 2633d32..ff89057 100644 --- a/src/controllers/auth.php +++ b/src/controllers/auth.php @@ -84,6 +84,7 @@ function auth_controller_register_post(): void if ($user === false) router_error(400); $_SESSION['user'] = user_find($u); + wallet_create($_SESSION['user']['id']); redirect('/character/create-first'); } diff --git a/src/controllers/char.php b/src/controllers/char.php index e961e87..02e82f8 100644 --- a/src/controllers/char.php +++ b/src/controllers/char.php @@ -67,7 +67,6 @@ function char_controller_create_post(): void // Create the auxiliary tables char_location_create($char); - char_wallet_create($char); char_gear_create($char); // Set the character as the user's selected character diff --git a/src/database.php b/src/database.php index 1b89641..5382ae3 100644 --- a/src/database.php +++ b/src/database.php @@ -1,11 +1,28 @@ exec('PRAGMA cache_size = 32000'); + // Enable WAL mode + $db->exec('PRAGMA journal_mode = WAL'); + // Move temp store to memory + $db->exec('PRAGMA temp_store = MEMORY'); + + return $db; +} + /** * Return a connection to the auth database. */ function db_auth(): SQLite3 { - return $GLOBALS['db_auth'] ??= new SQLite3(__DIR__ . '/../database/auth.db'); + return $GLOBALS['db_auth'] ??= db_open(__DIR__ . '/../database/auth.db'); } /** @@ -13,7 +30,7 @@ function db_auth(): SQLite3 */ function db_live(): SQLite3 { - return $GLOBALS['db_live'] ??= new SQLite3(__DIR__ . '/../database/live.db'); + return $GLOBALS['db_live'] ??= db_open(__DIR__ . '/../database/live.db'); } @@ -22,7 +39,7 @@ function db_live(): SQLite3 */ function db_fights(): SQLite3 { - return $GLOBALS['db_fights'] ??= new SQLite3(__DIR__ . '/../database/fights.db'); + return $GLOBALS['db_fights'] ??= db_open(__DIR__ . '/../database/fights.db'); } @@ -31,7 +48,7 @@ function db_fights(): SQLite3 */ function db_blueprints(): SQLite3 { - return $GLOBALS['db_blueprints'] ??= new SQLite3(__DIR__ . '/../database/blueprints.db'); + return $GLOBALS['db_blueprints'] ??= db_open(__DIR__ . '/../database/blueprints.db'); } /** @@ -43,6 +60,7 @@ function db_query(SQLite3 $db, string $query, array $params = []): SQLite3Result $stmt = $db->prepare($query); if (!empty($params)) foreach ($params as $key => $value) $stmt->bindValue($key, $value, getSQLiteType($value)); $GLOBALS['queries']++; + db_log($query); return $stmt->execute(); } @@ -52,6 +70,7 @@ function db_query(SQLite3 $db, string $query, array $params = []): SQLite3Result function db_exec(SQLite3 $db, string $query): bool { $GLOBALS['queries']++; + db_log($query); return $db->exec($query); } @@ -61,7 +80,9 @@ function db_exec(SQLite3 $db, string $query): bool */ function db_exists(SQLite3 $db, string $table, string $column, mixed $value): bool { - $result = db_query($db, "SELECT 1 FROM $table WHERE $column = :v LIMIT 1", [':v' => $value]); + $query = "SELECT 1 FROM $table WHERE $column = :v LIMIT 1"; + $result = db_query($db, $query, [':v' => $value]); + db_log($query); return $result->fetchArray(SQLITE3_NUM) !== false; } @@ -77,3 +98,11 @@ function getSQLiteType(mixed $value): int default => SQLITE3_TEXT }; } + +/** + * Log the given query string to the db debug log. + */ +function db_log(string $query): void +{ + if (env('debug', false)) $GLOBALS['query_log'][] = $query; +} diff --git a/src/helpers.php b/src/helpers.php index e1b4a85..ebc4dd3 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -129,13 +129,23 @@ function user_selected_char(): int /** * If the current user has a selected char and the data is in the session, retrieve either the full array of data - * or a specific field. + * or a specific field. If there is no character data, populate it. */ function char(string $field = ''): mixed { - if (empty($_SESSION['char'])) return false; - if ($field === '') return $_SESSION['char']; - return $_SESSION['char'][$field] ?? false; + // If there is no user, return false + if (empty($_SESSION['user'])) return false; + + if (empty($GLOBALS['char'])) { + $GLOBALS['char'] = db_query( + db_live(), + "SELECT * FROM characters WHERE id = :c", + [':c' => user_selected_char()] + )->fetchArray(SQLITE3_ASSOC); + } + + if ($field === '') return $GLOBALS['char']; + return $GLOBALS['char'][$field] ?? false; } /** @@ -145,7 +155,7 @@ function change_user_character(int $char_id): void { $_SESSION['user']['char_id'] = $char_id; db_query(db_auth(), "UPDATE users SET char_id = :c WHERE id = :u", [':c' => $char_id, ':u' => user('id')]); - $_SESSION['char'] = char_find($char_id); + $GLOBALS['char'] = char_find($char_id); } /** @@ -157,3 +167,22 @@ function percent(int $num, int $denom, int $precision = 4): int $p = ($num / $denom) * 100; return $p < 0 ? 0 : round($p, $precision); } + +/** + * Access the account wallet. On first execution it will populate $GLOBALS['wallet'] with the wallet data. This way + * the data is up to date with every request without having to query the database every use within, for example, a + * template. Will return false if the field does not exist, or the entire wallet array if no field is specified. + */ +function wallet(string $field = ''): array|int|false +{ + if (empty($GLOBALS['wallet'])) { + $GLOBALS['wallet'] = db_query( + db_live(), + "SELECT * FROM wallets WHERE user_id = :u", + [':u' => user('id')] + )->fetchArray(SQLITE3_ASSOC); + } + + if ($field === '') return $GLOBALS['wallet']; + return $GLOBALS['wallet'][$field] ?? false; +} diff --git a/src/models/char.php b/src/models/char.php index 76502b0..a10da4c 100644 --- a/src/models/char.php +++ b/src/models/char.php @@ -61,22 +61,6 @@ function char_location_create(int $char_id, int $x = 0, int $y = 0, int $current } } -/** - * Creates a character's wallet. A character's wallet is where they store their currencies. Can optionally specify the - * starting balances of the wallet. Returns the created wallet's ID. If a currency is set to -1, the starting_silver - * or starting_star_gems fields from the env will be used. - */ -function char_wallet_create(int $char_id, int $silver = -1, int $starGems = -1): void -{ - if (db_query(db_live(), "INSERT INTO char_wallets (char_id, silver, stargem) VALUES (:p, :s, :sg)", [ - ':p' => $char_id, - ':s' => $silver === -1 ? env('start_silver', 10) : $silver, - ':sg' => $starGems === -1 ? env('start_star_gems', 0) : $starGems - ]) === false) { - throw new Exception('Failed to create character wallet. (cwc)'); - } -} - /** * Create the character's gear table. A character's gear is where they store their equipped items. * @TODO: implement initial gear @@ -152,16 +136,6 @@ function char_get_location(int $char_id): array return $location; } -/** - * Get a character's wallet by their character ID. Returns the wallet's data as an associative array. - */ -function char_get_wallet(int $char_id): array -{ - $wallet = db_query(db_live(), "SELECT * FROM char_wallets WHERE char_id = :p", [':p' => $char_id])->fetchArray(SQLITE3_ASSOC); - if ($wallet === false) throw new Exception('Wallet not found. (cgw)'); - return $wallet; -} - /** * See if a character name exists. */ diff --git a/src/models/user.php b/src/models/user.php index 0245406..80a7506 100644 --- a/src/models/user.php +++ b/src/models/user.php @@ -35,3 +35,19 @@ function user_delete(string|int $user): SQLite3Result|false { return db_query(db_auth(), "DELETE FROM users WHERE username = :u OR email = :u OR id = :u", [':u' => $user]); } + +/** + * Creates a character's wallet. A character's wallet is where they store their currencies. Can optionally specify the + * starting balances of the wallet. Returns the created wallet's ID. If a currency is set to -1, the starting_silver + * or starting_star_gems fields from the env will be used. + */ +function wallet_create(int $user_id, int $silver = -1, int $starGems = -1): void +{ + if (db_query(db_live(), "INSERT INTO wallets (user_id, silver, stargem) VALUES (:u, :s, :sg)", [ + ':u' => $user_id, + ':s' => $silver === -1 ? env('start_silver', 10) : $silver, + ':sg' => $starGems === -1 ? env('start_star_gems', 0) : $starGems + ]) === false) { + throw new Exception('Failed to create wallet. (wc)'); + } +} diff --git a/templates/components/char_bar.php b/templates/components/char_bar.php index 0b29357..b826f44 100644 --- a/templates/components/char_bar.php +++ b/templates/components/char_bar.php @@ -27,4 +27,8 @@
+ +
+ Silver +
diff --git a/templates/components/debug_query_log.php b/templates/components/debug_query_log.php new file mode 100644 index 0000000..003f99e --- /dev/null +++ b/templates/components/debug_query_log.php @@ -0,0 +1,5 @@ +
+

Query Log

+

queries were executed.

+ $query

"; ?> +
diff --git a/templates/layouts/basic.php b/templates/layouts/basic.php index 00b9a18..5598f18 100644 --- a/templates/layouts/basic.php +++ b/templates/layouts/basic.php @@ -49,6 +49,8 @@

v

+ +