Import T5-AIO and T6 into combined repo
This commit is contained in:
+229
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
tws_bank.gsc — persistent per-player bank, MariaDB-backed. See NOTES.md
|
||||
for the DB-first / spawn-dispatch / command surface invariants.
|
||||
*/
|
||||
|
||||
#include maps\_utility;
|
||||
#include common_scripts\utility;
|
||||
|
||||
init()
|
||||
{
|
||||
if (GetDvar(#"zombiemode") != "1")
|
||||
return;
|
||||
|
||||
scripts\sp\tws_common::ensure_config();
|
||||
|
||||
bank_init();
|
||||
|
||||
scripts\sp\tws_common::register_spawn_handler(::bank_load);
|
||||
}
|
||||
|
||||
bank_init()
|
||||
{
|
||||
if (!isDefined(level.db_probe_done) || !level.db_probe_done)
|
||||
level thread bank_deferred_start();
|
||||
else
|
||||
bank_start();
|
||||
}
|
||||
|
||||
bank_deferred_start()
|
||||
{
|
||||
level waittill("db_probe_done");
|
||||
bank_start();
|
||||
}
|
||||
|
||||
bank_start()
|
||||
{
|
||||
if (!level.db_online)
|
||||
return;
|
||||
|
||||
bank_register_commands();
|
||||
}
|
||||
|
||||
bank_register_commands()
|
||||
{
|
||||
command::add_sv("bank", ::bank_cmd_bank);
|
||||
command::add_sv("deposit", ::bank_cmd_deposit);
|
||||
command::add_sv("withdraw", ::bank_cmd_withdraw);
|
||||
}
|
||||
|
||||
// DIAGNOSTIC STUB — bare minimum to isolate the connect-handshake crash.
|
||||
// Do not restore the getGuid / mysql body until this passes join.
|
||||
bank_load()
|
||||
{
|
||||
self endon("disconnect");
|
||||
self iPrintLnBold("^2bank_load: entered");
|
||||
self.bank = 0;
|
||||
self.bank_unavailable = false;
|
||||
self iPrintLnBold("^2bank_load: done");
|
||||
}
|
||||
|
||||
bank_available(player)
|
||||
{
|
||||
if (!level.db_online)
|
||||
{
|
||||
player iPrintLnBold("^1Bank offline");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is_true(player.bank_unavailable))
|
||||
{
|
||||
player iPrintLnBold("^1Bank unavailable for your account");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!isDefined(player.bank))
|
||||
{
|
||||
player iPrintLnBold("^3Bank still loading, try again");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bank_cmd_bank(args)
|
||||
{
|
||||
if (!bank_available(self))
|
||||
return;
|
||||
|
||||
self iPrintLnBold("Bank: " + self.bank + " Score: " + self.score);
|
||||
}
|
||||
|
||||
bank_cmd_deposit(args)
|
||||
{
|
||||
if (!bank_available(self))
|
||||
return;
|
||||
|
||||
if (args.size < 2)
|
||||
{
|
||||
self iPrintLnBold("Usage: deposit <amount>");
|
||||
return;
|
||||
}
|
||||
|
||||
amount = int(args[1]);
|
||||
|
||||
if (amount <= 0)
|
||||
{
|
||||
self iPrintLnBold("^1Amount must be positive");
|
||||
return;
|
||||
}
|
||||
|
||||
if (amount > self.score)
|
||||
{
|
||||
self iPrintLnBold("^1Not enough score");
|
||||
return;
|
||||
}
|
||||
|
||||
self thread bank_deposit_write(amount);
|
||||
}
|
||||
|
||||
bank_cmd_withdraw(args)
|
||||
{
|
||||
if (!bank_available(self))
|
||||
return;
|
||||
|
||||
if (args.size < 2)
|
||||
{
|
||||
self iPrintLnBold("Usage: withdraw <amount>");
|
||||
return;
|
||||
}
|
||||
|
||||
amount = int(args[1]);
|
||||
|
||||
if (amount <= 0)
|
||||
{
|
||||
self iPrintLnBold("^1Amount must be positive");
|
||||
return;
|
||||
}
|
||||
|
||||
if (amount > self.bank)
|
||||
{
|
||||
self iPrintLnBold("^1Insufficient balance");
|
||||
return;
|
||||
}
|
||||
|
||||
self thread bank_withdraw_write(amount);
|
||||
}
|
||||
|
||||
// upsert: first deposit creates the row, later ones increment
|
||||
bank_deposit_write(amount)
|
||||
{
|
||||
self endon("disconnect");
|
||||
|
||||
name = bank_display_name(self);
|
||||
server_id = bank_server_id();
|
||||
|
||||
q = mysql::prepared_statement(
|
||||
"INSERT INTO bank (guid, balance, last_name, last_server) VALUES (?, ?, ?, ?) " +
|
||||
"ON DUPLICATE KEY UPDATE balance = balance + VALUES(balance), " +
|
||||
"last_name = VALUES(last_name), last_server = VALUES(last_server)",
|
||||
self.bank_guid, amount, name, server_id);
|
||||
|
||||
q waittill("done", result, affected_rows, error);
|
||||
|
||||
if (isDefined(error) && error != "")
|
||||
{
|
||||
self iPrintLnBold("^1Deposit failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// score can change between dispatch and write completing — refund if so
|
||||
if (amount > self.score)
|
||||
{
|
||||
mysql::prepared_statement(
|
||||
"UPDATE bank SET balance = balance - ? WHERE guid = ?",
|
||||
amount, self.bank_guid);
|
||||
self iPrintLnBold("^1Deposit rolled back (score changed)");
|
||||
return;
|
||||
}
|
||||
|
||||
self.score -= amount;
|
||||
self.bank += amount;
|
||||
self iPrintLnBold("Deposited " + amount + " Bank: " + self.bank);
|
||||
}
|
||||
|
||||
// balance guard lives in the WHERE so concurrent commands can't overdraw
|
||||
bank_withdraw_write(amount)
|
||||
{
|
||||
self endon("disconnect");
|
||||
|
||||
q = mysql::prepared_statement(
|
||||
"UPDATE bank SET balance = balance - ? WHERE guid = ? AND balance >= ?",
|
||||
amount, self.bank_guid, amount);
|
||||
|
||||
q waittill("done", result, affected_rows, error);
|
||||
|
||||
if (isDefined(error) && error != "")
|
||||
{
|
||||
self iPrintLnBold("^1Withdraw failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isDefined(affected_rows) || affected_rows == 0)
|
||||
{
|
||||
self iPrintLnBold("^1Insufficient balance");
|
||||
self thread bank_load(); // re-sync in case memory drifted from DB
|
||||
return;
|
||||
}
|
||||
|
||||
self.score += amount;
|
||||
self.bank -= amount;
|
||||
self iPrintLnBold("Withdrew " + amount + " Bank: " + self.bank);
|
||||
}
|
||||
|
||||
bank_display_name(player)
|
||||
{
|
||||
if (isDefined(player.name))
|
||||
return player.name;
|
||||
if (isDefined(player.playername))
|
||||
return player.playername;
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
bank_server_id()
|
||||
{
|
||||
id = GetDvar("tws_server_id");
|
||||
if (id == "")
|
||||
return "unknown";
|
||||
return id;
|
||||
}
|
||||
Reference in New Issue
Block a user