-
Posts
2,146 -
Joined
-
Last visited
-
Days Won
149
Content Type
Profiles
Forums
Events
Everything posted by Magictallguy
-
"I would like to create a browser-based text RPG, using PHP and MySQL as the backend. It must have these features [describe them]" That depends on where you're using it. If you're using a browser version, chances are you'll be copy/pasting. If you're using a plugin with your editor (Junie for JetBrains, for example, or a Claude API extension in VSCode), then you can instruct it - after granting permissions - to add/edit/delete files at will Yes. Migration shims have existed for years. No public-facing AI is generative (even if it claims to be) as they're fed source material and "create" from that. Everything is regurgitated without context. So, with that in mind, the existence of a shim being publicly available (Git), and the simple ability to read, an AI could update PHP5 to PHP8 practices. Be sure to specify which version of PHP8. For example; 8.3 introduces a number of breaking changes to code that would otherwise be fine in PHP8.2 (current latest is 8.5.8 and I loooooooove the deprecations - can do so much more with so much less now! Let it be known that I bloody well hate AI and the ego a number of self-entitled "developers" (vibe coders) seem to pack with it. Studies by MIT have shown that those who depend on AI incur up to a 47% drop in connectivity and engagement, combined with a 32-ish% decrease in critical thinking and short-term memory recollection. I'm not stopping you from using it, nor am I trying to dissuade you. It is a tool like any other and, like any other, it can be misused. All I can advise, strongly, is that you don't let robots think for you
-
For legal reasons, as one of the site administrators; I must state that if you are seeking legal or medical advice, that you seek vetted professionals. This place is for the cause of our mental issues, not dealing with them 😛 Also, for context; here's a newscast from Helpnet Security, posted 5 days ago about a RAT attack that affected Claude users. CVE-2026-7574 and CVE-2026-7596 are just 2 recent entries into the exploit database concerning Claude. Final note; if we can stop casting unfounded accusations based on correlational data, that'd be awesome, thanks. You posted on MWG, your site was attacked afterwards. If I may make the suggestion; the sudden exposure on a relatively-high traffic website might have attracted a bad actor or two - the norm with most sites that gain traction.
-
That is a genius idea and I love every part of this
-
That rar contains 1 CSS file (comprised mostly of Bootstrap extracts) and 1 AI-generated image. Was that the intended upload?
-
It's a session thing. Try swapping to file-based sessions instead of DB sessions. And I've just realised we've fully hijacked a thread here. Apologies, OP!
-
You'll have to check your server's mail configuration. It appears your host has an ... alternative ... setup to the more commonly-found ones, so the default mail() call might not be enough
-
This is correct and the intended fix. If the .env is invalid or incorrectly generated, it's simply easier to make the site regenerate it after re-filling the form. Seeing as the installer checks to see if the .env file exists to get past that step, deleting an incorrect .env is the way to go - I didn't automate this to prevent a potential race condition which would introduce an endless loop
-
It's a dotfile, so you may need to toggle the "Show hidden files" option in cPanel's File Manager
-
See the .env.local file that ships with gRPG v2. It'll shed some light on what your .env needs to resemble
-
What a weird restriction!
-
Do you have anything like Sentry to automatically report errors to you? Coupled with user reports, such a tool can be invaluable
-
Awwww, hell yeah! Colour me keen. Samsung Galaxy S23 here. I will swear by Android ❤️
-
RSS feed to the forum - notifies me of spambot posts, too 😉 I'm actually somewhat excited to see how this project turns out. Keep up the good work! ^.^
-
Oi! That's lookin' really good!
-
Merry Calendar Change Day!
-
begins chanting Bring back the Marketplace! Bring back the Marketplace! Bring back the Marketplace!
-
You mentioned using phone data while connected to WiFi, so I'm unclear on whether your phone (on just WiFi) has the same result. As soon as you clarify that, we can start throwing (maybe educated?) guesses at the cause
-
MCCODES for 2025 comparing the 2 Contenders
Magictallguy replied to Uridium's topic in General Discussion
The installer has an extra comma in the query's column definitions Find: INSERT INTO `users` (`username`, `login_name`, `userpass`, `level`, `money`, `crystals`, `donatordays`, `user_level`, `energy`, `maxenergy`, `will`, `maxwill`, `brave`, `maxbrave`, `hp`, `maxhp`, `location`, `gender`, `signedup`, `email`, `bankmoney`, `lastip`, `lastip_signup`, `pass_salt`, , `display_pic`, `staffnotes`, `voted`, `user_notepad`) See that random blank column between `pass_salt` and `display_pic`? Remove it INSERT INTO `users` (`username`, `login_name`, `userpass`, `level`, `money`, `crystals`, `donatordays`, `user_level`, `energy`, `maxenergy`, `will`, `maxwill`, `brave`, `maxbrave`, `hp`, `maxhp`, `location`, `gender`, `signedup`, `email`, `bankmoney`, `lastip`, `lastip_signup`, `pass_salt`, `display_pic`, `staffnotes`, `voted`, `user_notepad`) Note: `lib/basic_error_handler.php` has a DEBUG constant. Set it to `true` and you'll see error messages This only applies if the project's directory is not the webroot (you have localhost/upload/{game-files}). The installer "expects" things to be at webroot -
I didn't add any >100 formatting, but that'd be easy enough. Hell, I might even update to use a checkbox for it so users can see the direct value if they need to, or just a "yup, this is guaranteed" output. Go sick 😄
-
I really like the ability to visualise how the crime formulae may result; so I took your idea and added the ability to select from an existing crime, or assume the default formula ((WILL*0.8)/2.5)+(LEVEL/4) and calculate as desired. I also stripped the jQuery dependence; pure vanilla JS, woo! Fair note to our more sensitive-eyed programmers; there's no dark mode by default. Note: Written in a PHP8.4 environment. Older versions may need to change the match() call to a switch() equivalent crime-formula.php <?php declare(strict_types=1); $_GET['action'] ??= null; $_GET['id'] = array_key_exists('id', $_GET) && is_numeric($_GET['id']) && (int)$_GET['id'] > 0 ? (int)$_GET['id'] : null; class CrimeFormula { private static ?self $inst = null; private ?database $db; private ?array $settings; /** * @param database $db * @param array $settings */ public function __construct(database $db, array $settings) { $this->db = $db; $this->settings = $settings; $this->run(); } /** * @return void */ private function run(): void { $response = match ($_GET['action']) { 'get-crime-by-id' => $this->getCrimeById($_GET['id']), default => [ 'type' => 'error', 'message' => 'No action given', ], }; if ($this->isAjax()) { header('Content-type: application/json'); echo json_encode($response); exit; } if (array_key_exists('location', $response)) { header('Location: ' . $response['location']); exit; } echo $this->template('crime-select', [ '%id%' => $_GET['id'], '%menu.opts:crimes%' => $this->renderMenuOptsCrimes($_GET['id']), ]); } /** * @param int|null $id * * @return array|null */ private function getCrimeById(?int $id): ?array { if (empty($id)) { return null; } $get_crime = $this->db->query( 'SELECT * FROM crimes WHERE crimeID = ' . $id . ' LIMIT 1', ); $row = $this->db->fetch_row($get_crime); $this->db->free_result($get_crime); return $row ?? null; } /** * @return bool */ private function isAjax(): bool { return array_key_exists('HTTP_X_REQUESTED_WITH', $_SERVER) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest'; } /** * @param string $fileName * @param array $replacements * * @return string|null */ private function template(string $fileName, array $replacements = []): ?string { $path = str_replace('/', DIRECTORY_SEPARATOR, __DIR__ . '/' . $fileName . '.html'); if (!file_exists($path)) { return null; } $content = file_get_contents($path); return strtr($content, $replacements); } /** * @param int|null $selected * * @return string */ private function renderMenuOptsCrimes(?int $selected = null): string { $ret = ''; $rows = $this->db->query( 'SELECT crimeID, crimeNAME, crimeBRAVE FROM crimes ORDER BY crimeBRAVE', ); while ($row = $this->db->fetch_row($rows)) { $ret .= sprintf( '<option value="%u" %s>%s [%s brave]</option>%s', $row['crimeID'], (int)$row['crimeID'] === $selected ? 'selected' : '', stripslashes(htmlspecialchars($row['crimeNAME'])), number_format((int)$row['crimeBRAVE']), PHP_EOL, ); } $this->db->free_result($rows); return $ret; } /** * @param database $db * @param array $settings * * @return self|null */ public static function getInstance(database $db, array $settings): ?self { if (self::$inst === null) { self::$inst = new self($db, $settings); } return self::$inst; } } global $db, $set; require_once __DIR__ . '/globals_nonauth.php'; $module = CrimeFormula::getInstance($db, $set); crime-select.html <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Crime Formula Tests</title> </head> <body> <div class="container" style="margin: 0 auto;"> <form id="crime-selection-form" method="get"> <div class="row py-2"> <div class="col"> <div class="form-group"> <label for="crime">Select Crime</label> <select name="crime" id="crime" class="form-control"> <option value="0" selected>--- None ---</option> %menu.opts:crimes% </select> </div> </div> </div> <div class="row py-2"> <div class="col-lg-6 col-md"> <div class="form-group"> <label for="level">Level</label> <input type="number" name="level" id="level" class="form-control" value="1" step="1"> </div> </div> <div class="col-lg-6 col-md"> <div class="form-group"> <label for="will">Will</label> <input type="number" name="will" id="will" class="form-control" value="100" step="1"> </div> </div> </div> </form> </div> <div class="container"> <span class="d-block m-1" id="crime-formula-raw"></span> <span class="d-block m-1" id="crime-formula-formatted"></span> <span class="d-block m-1" id="crime-response"></span> </div> <script> const apiCall = (path) => { return fetch(path, { headers: { 'credentials': 'same-origin', 'X-Requested-With': 'XMLHttpRequest', 'Content-Type': 'application/json' }, signal: AbortSignal.timeout(5000) }); }; const getCrime = (id, callback) => { apiCall(`crime-formula.php?action=get-crime-by-id&id=${id}`) .then(response => response.json()) .then(data => callback(data)); }; const responseElem = document.getElementById("crime-response"); const formulaRawElem = document.getElementById("crime-formula-raw"); const formulaFormattedElem = document.getElementById("crime-formula-formatted"); const updateCrimeInfo = (formula, will, level) => { let formulaFormatted = formula.replace('WILL', will).replace('LEVEL', level); formulaRawElem.innerText = formula; formulaFormattedElem.innerText = formulaFormatted; /* Dirty. Don't do this if you can avoid it. And certainly *never* trust user input with it. */ let amnt = eval(formulaFormatted); responseElem.innerText = amnt.toLocaleString(undefined, {maximumFractionDigits: 3}) + "%"; }; const getCrimeFullEvent = (e) => { e.stopPropagation(); e.preventDefault(); if ([undefined, null].includes(responseElem) || [undefined, null].includes(formulaRawElem) || [undefined, null].includes(formulaFormattedElem)) { console.error("Form element missing: crime-response/crime-formula-raw/crime-formula-formatted"); return; } let will = document.getElementById("will").value; let level = document.getElementById("level").value; let id = document.getElementById("crime").value; if ([undefined, null].includes(will)) { will = 100; } if ([undefined, null].includes(level)) { level = 1; } if ([undefined, null].includes(id)) { id = 0; } let formula = '((WILL*0.8)/2.5)+(LEVEL/4)'; if (id > 0) { getCrime(id, (data) => { if ([undefined, null].includes(data)) { console.error("Blank crime data response"); return false; } if (data.hasOwnProperty("type") && data.type !== "success") { console.error(data); return false; } updateCrimeInfo(data.crimePERCFORM, will, level); return true; }); } else { updateCrimeInfo(formula, will, level); } }; window.addEventListener("DOMContentLoaded", () => { const formElem = document.getElementById("crime-selection-form"); if ([undefined, null].includes(formElem)) { console.error("Form element missing: crime-selection-form"); return; } formElem.addEventListener("keyup", (e) => getCrimeFullEvent(e)); formElem.addEventListener("mouseup", (e) => getCrimeFullEvent(e)); }); </script> </body> </html> 2025-09-22 18-58-18.mp4
-
For anyone wanting to take this on, you're lookin' at CrateJS to re-wrap
-
Note: In higher-traffic areas, this may introduce race conditions. In that scenario, I'd recommend using the database (the one your project is already using) to track this information; amongst other things, most RDBMS support query queuing as default. For low-traffic areas and areas where you don't foresee an upsurge in activity (refer to your metrics), then this file-based approach may be perfectly sufficient for your needs
-
Technically, yes! It is certainly possible to run multiple sites that reference a single database. More often than not, though, the question is "why"? If, for example, I was to start a mafia-style game with MCC then I decided I wanted a sci-fi style game with gRPG; I could do the leg-work and make them compatible. That being said, what of the players? Someone playing a mafia-style game with [x] currency will likely be confused by having [y] currency in the sci-fi game. I'm a firm believer of "fit for purpose"; each project gets their own database(s) as necessary. If you want to make a merge of the open-source engines, you go right ahead 😄