mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2026-07-19 04:08:55 +01:00
[MIRROR] reimplements attack and player logs (#12553)
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
bb90e792ca
commit
99afe463dc
+25
-12
@@ -76,7 +76,7 @@ CREATE TABLE IF NOT EXISTS `erro_feedback` (
|
||||
`var_value` int(16) DEFAULT NULL,
|
||||
`details` text,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
-- Table structure for table `erro_player`
|
||||
CREATE TABLE IF NOT EXISTS `erro_player` (
|
||||
@@ -93,7 +93,7 @@ CREATE TABLE IF NOT EXISTS `erro_player` (
|
||||
KEY `discord_id` (`discord_id`),
|
||||
KEY `computerid` (`computerid`),
|
||||
KEY `ip` (`ip`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
-- Table structure for table `erro_poll_option`
|
||||
CREATE TABLE IF NOT EXISTS `erro_poll_option` (
|
||||
@@ -107,7 +107,7 @@ CREATE TABLE IF NOT EXISTS `erro_poll_option` (
|
||||
`descmid` varchar(32) DEFAULT NULL,
|
||||
`descmax` varchar(32) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
-- Table structure for table `erro_poll_question`
|
||||
CREATE TABLE IF NOT EXISTS `erro_poll_question` (
|
||||
@@ -118,7 +118,7 @@ CREATE TABLE IF NOT EXISTS `erro_poll_question` (
|
||||
`question` varchar(255) NOT NULL,
|
||||
`adminonly` tinyint(1) DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
-- Table structure for table `erro_poll_textreply`
|
||||
CREATE TABLE IF NOT EXISTS `erro_poll_textreply` (
|
||||
@@ -130,7 +130,7 @@ CREATE TABLE IF NOT EXISTS `erro_poll_textreply` (
|
||||
`replytext` text NOT NULL,
|
||||
`adminrank` varchar(32) NOT NULL DEFAULT 'Player',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
-- Table structure for table `erro_poll_vote`
|
||||
CREATE TABLE IF NOT EXISTS `erro_poll_vote` (
|
||||
@@ -143,7 +143,7 @@ CREATE TABLE IF NOT EXISTS `erro_poll_vote` (
|
||||
`adminrank` varchar(32) NOT NULL,
|
||||
`rating` int(2) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
-- Table structure for table `erro_privacy`
|
||||
CREATE TABLE IF NOT EXISTS `erro_privacy` (
|
||||
@@ -152,7 +152,20 @@ CREATE TABLE IF NOT EXISTS `erro_privacy` (
|
||||
`ckey` varchar(32) NOT NULL,
|
||||
`option` varchar(128) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
-- Dumping structure for table ss13.erro_dialog
|
||||
CREATE TABLE IF NOT EXISTS `erro_dialog` (
|
||||
`mid` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`time` datetime NOT NULL,
|
||||
`ckey` varchar(32) NOT NULL,
|
||||
`color` varchar(16) DEFAULT NULL,
|
||||
`mob` varchar(128) DEFAULT NULL,
|
||||
`area` varchar(128) DEFAULT NULL,
|
||||
`type` varchar(32) NOT NULL,
|
||||
`message` text NOT NULL,
|
||||
PRIMARY KEY (`mid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
-- Table structure for table `death`
|
||||
CREATE TABLE IF NOT EXISTS `death` (
|
||||
@@ -172,7 +185,7 @@ CREATE TABLE IF NOT EXISTS `death` (
|
||||
`fireloss` INT(11) NOT NULL,
|
||||
`oxyloss` INT(11) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
|
||||
-- Table structure for table `karma`
|
||||
@@ -188,7 +201,7 @@ CREATE TABLE IF NOT EXISTS `karma` (
|
||||
`spenderip` TEXT NOT NULL,
|
||||
`time` DATETIME NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
-- Table structure for table `karmatotals`
|
||||
CREATE TABLE IF NOT EXISTS `karmatotals` (
|
||||
@@ -196,7 +209,7 @@ CREATE TABLE IF NOT EXISTS `karmatotals` (
|
||||
`byondkey` TEXT NOT NULL,
|
||||
`karma` INT(11) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
-- Table structure for table `library`
|
||||
CREATE TABLE IF NOT EXISTS `library` (
|
||||
@@ -206,7 +219,7 @@ CREATE TABLE IF NOT EXISTS `library` (
|
||||
`content` TEXT NOT NULL,
|
||||
`category` TEXT NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ;
|
||||
|
||||
-- Table structure for table `population`
|
||||
CREATE TABLE IF NOT EXISTS `population` (
|
||||
@@ -215,7 +228,7 @@ CREATE TABLE IF NOT EXISTS `population` (
|
||||
`admincount` INT(11) NULL DEFAULT NULL,
|
||||
`time` DATETIME NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
-- Table structure for table `vr_player_hours`
|
||||
CREATE TABLE IF NOT EXISTS `vr_player_hours` (
|
||||
|
||||
@@ -38,6 +38,33 @@
|
||||
#define LOG_SPEECH_INDICATORS (1 << 22)
|
||||
#define LOG_TRANSPORT (1 << 23)
|
||||
|
||||
GLOBAL_ALIST_INIT(logtype_to_string, alist(
|
||||
LOG_ATTACK = "ATTACK",
|
||||
LOG_SAY = "SAY",
|
||||
LOG_WHISPER = "WHISPER",
|
||||
LOG_EMOTE = "EMOTE",
|
||||
LOG_DSAY = "DEADSAY",
|
||||
LOG_PDA = "PDA",
|
||||
LOG_CHAT = "CHAT",
|
||||
LOG_COMMENT = "COMMENT",
|
||||
LOG_TELECOMMS = "RADIO",
|
||||
LOG_OOC = "OOC",
|
||||
LOG_LOOC = "LOOC",
|
||||
LOG_ADMIN = "ADMIN",
|
||||
LOG_OWNERSHIP = "OWNERSHIP",
|
||||
LOG_GAME = "GAME",
|
||||
LOG_ADMIN_PRIVATE = "ADMIN_PRIV",
|
||||
LOG_ASAY = "ASAY",
|
||||
LOG_MECHA = "MECH",
|
||||
LOG_VIRUS = "VIRUS",
|
||||
LOG_SHUTTLE = "SHUTTLE",
|
||||
LOG_ECON = "ECON",
|
||||
LOG_VICTIM = "VICTIM",
|
||||
LOG_RADIO_EMOTE = "RADIO_EMOTE",
|
||||
LOG_SPEECH_INDICATORS = "SPEECH_INDICATOR",
|
||||
LOG_TRANSPORT = "TRANSPORT"
|
||||
))
|
||||
|
||||
//Individual logging panel pages
|
||||
#define INDIVIDUAL_GAME_LOG (LOG_GAME)
|
||||
#define INDIVIDUAL_ATTACK_LOG (LOG_ATTACK | LOG_VICTIM)
|
||||
|
||||
@@ -29,11 +29,11 @@
|
||||
var/postfix = "[sobject][saddition][hp]"
|
||||
|
||||
var/message = "[what_done] [starget][postfix]"
|
||||
user.log_message(message, LOG_ATTACK, color="red")
|
||||
user.log_message(message, LOG_ATTACK, color="#ff0000")
|
||||
|
||||
if(user != target)
|
||||
var/reverse_message = "was [what_done] by [ssource][postfix]"
|
||||
target.log_message(reverse_message, LOG_VICTIM, color="orange", log_globally=FALSE)
|
||||
target.log_message(reverse_message, LOG_VICTIM, color="#ffb300", log_globally=FALSE)
|
||||
|
||||
/// Log for vore interactions
|
||||
/proc/log_vore(text, list/data)
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/proc/db_log_insert(mob/log_target, message, type, color)
|
||||
set waitfor = FALSE
|
||||
if(!ismob(log_target))
|
||||
return
|
||||
if(!SSdbcore.IsConnected())
|
||||
return
|
||||
var/datum/db_query/query_insert = SSdbcore.NewQuery("INSERT INTO erro_dialog (mid, time, ckey, mob, area, type, color, message) VALUES (null, NOW(), :sender_ckey, :sender_mob, :message_area, :message_type, :message_color, :message_content)",
|
||||
list("sender_ckey" = log_target.ckey, "sender_mob" = log_target.real_name, "message_area" = "[loc_name(log_target)]", "message_type" = "[type]", "message_color" = color, "message_content" = message))
|
||||
if(!query_insert.Execute())
|
||||
log_sql("Error during logging: "+query_insert.ErrorMsg())
|
||||
qdel(query_insert)
|
||||
return
|
||||
qdel(query_insert)
|
||||
@@ -13,42 +13,30 @@
|
||||
return
|
||||
|
||||
// Cannot use the list as a map if the key is a number, so we stringify it (thank you BYOND)
|
||||
var/smessage_type = num2text(message_type, MAX_BITFLAG_DIGITS)
|
||||
|
||||
if(HAS_CONNECTED_PLAYER(src))
|
||||
if(!islist(persistent_client.logging[smessage_type]))
|
||||
persistent_client.logging[smessage_type] = list()
|
||||
|
||||
if(!islist(logging[smessage_type]))
|
||||
logging[smessage_type] = list()
|
||||
|
||||
var/colored_message = message
|
||||
if(color)
|
||||
if(color[1] == "#")
|
||||
colored_message = "<font color=[color]>[message]</font>"
|
||||
else
|
||||
colored_message = "<font color='[color]'>[message]</font>"
|
||||
var/smessage_type = GLOB.logtype_to_string[message_type]
|
||||
|
||||
//This makes readability a bit better for admins.
|
||||
switch(message_type)
|
||||
if(LOG_WHISPER)
|
||||
colored_message = "(WHISPER) [colored_message]"
|
||||
if(LOG_OOC)
|
||||
colored_message = "(OOC) [colored_message]"
|
||||
if(LOG_LOOC)
|
||||
colored_message = "(LOOC) [colored_message]"
|
||||
if(LOG_ASAY)
|
||||
colored_message = "(ASAY) [colored_message]"
|
||||
if(LOG_EMOTE)
|
||||
colored_message = "(EMOTE) [colored_message]"
|
||||
if(LOG_RADIO_EMOTE)
|
||||
colored_message = "(RADIOEMOTE) [colored_message]"
|
||||
var/list/timestamped_message = list(
|
||||
"time" = world.timeofday,
|
||||
"name" = name,
|
||||
"ckey" = ckey,
|
||||
"loc" = loc_name(src),
|
||||
"event_id" = LAZYLEN(logging[smessage_type]),
|
||||
"message" = message,
|
||||
"color" = color
|
||||
)
|
||||
|
||||
var/list/timestamped_message = list("\[[time_stamp(format = "YYYY-MM-DD hh:mm:ss")]\] [key_name_and_tag(src)] [loc_name(src)] (Event #[LAZYLEN(logging[smessage_type])])" = colored_message)
|
||||
|
||||
logging[smessage_type] += timestamped_message
|
||||
if(!CONFIG_GET(flag/database_logging))
|
||||
if(!islist(logging[smessage_type]))
|
||||
logging[smessage_type] = list()
|
||||
UNTYPED_LIST_ADD(logging[smessage_type], timestamped_message)
|
||||
|
||||
if(HAS_CONNECTED_PLAYER(src))
|
||||
persistent_client.logging[smessage_type] += timestamped_message
|
||||
if(CONFIG_GET(flag/database_logging))
|
||||
db_log_insert(src, message, smessage_type, color)
|
||||
else
|
||||
if(!islist(persistent_client.logging[smessage_type]))
|
||||
persistent_client.logging[smessage_type] = list()
|
||||
UNTYPED_LIST_ADD(persistent_client.logging[smessage_type], timestamped_message)
|
||||
|
||||
..()
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
* * log_globally - boolean checking whether or not we write this log to the log file
|
||||
* * forced_by - source that forced the dialogue if any
|
||||
*/
|
||||
/atom/proc/log_talk(message, message_type, tag = null, log_globally = TRUE, forced_by = null, custom_say_emote = null)
|
||||
/atom/proc/log_talk(message, message_type, tag = null, log_globally = TRUE, forced_by = null, custom_say_emote = null, color)
|
||||
var/prefix = tag ? "([tag]) " : ""
|
||||
var/suffix = forced_by ? " FORCED by [forced_by]" : ""
|
||||
log_message("[prefix][custom_say_emote ? "*[custom_say_emote]*, " : ""]\"[message]\"[suffix]", message_type, log_globally = log_globally)
|
||||
log_message("[prefix][custom_say_emote ? "*[custom_say_emote]*, " : ""]\"[message]\"[suffix]", message_type, color, log_globally)
|
||||
|
||||
/// Logging for generic spoken messages
|
||||
/proc/log_say(text, list/data)
|
||||
|
||||
@@ -151,13 +151,8 @@ Proc for attack log creation, because really why not
|
||||
add_attack_logs(user,M,what_done,admin_notify)
|
||||
return
|
||||
|
||||
var/user_str = key_name(user)
|
||||
var/target_str = key_name(target)
|
||||
|
||||
if(ismob(user))
|
||||
user.attack_log += text("\[[time_stamp()]\] [span_red("Attacked [target_str]: [what_done]")]")
|
||||
if(ismob(target))
|
||||
target.attack_log += text("\[[time_stamp()]\] [span_orange("Attacked by [user_str]: [what_done]")]")
|
||||
log_combat(user, target, what_done)
|
||||
if(admin_notify)
|
||||
msg_admin_attack("[key_name_admin(user)] vs [target_str]: [what_done]")
|
||||
|
||||
@@ -729,7 +729,7 @@
|
||||
/datum/config_entry/flag/allow_simple_mob_recolor
|
||||
|
||||
/// Chatlogs are now saved by calling the chatlogging library instead of letting the clients handle it
|
||||
/// REQUIRES an database
|
||||
/// REQUIRES a database
|
||||
/datum/config_entry/flag/chatlog_database_backend
|
||||
default = FALSE
|
||||
|
||||
@@ -737,6 +737,11 @@
|
||||
/// REQUIRES chatlog_database_backend to be enabled
|
||||
/datum/config_entry/string/chatlog_database_api_endpoint
|
||||
|
||||
/// Enables logging dialogue and attack logs to the database
|
||||
/// REQUIRES a database
|
||||
/datum/config_entry/flag/database_logging
|
||||
default = FALSE
|
||||
|
||||
/datum/config_entry/flag/forbid_admin_profiling
|
||||
|
||||
/datum/config_entry/flag/pixel_size_limit
|
||||
|
||||
@@ -44,6 +44,11 @@ SUBSYSTEM_DEF(dbcore)
|
||||
|
||||
/datum/controller/subsystem/dbcore/Initialize()
|
||||
Connect()
|
||||
if(IsConnected() && CONFIG_GET(flag/database_logging))
|
||||
var/datum/db_query/query_truncate = NewQuery("TRUNCATE erro_dialog")
|
||||
if(!query_truncate.Execute())
|
||||
log_sql("ERROR TRYING TO CLEAR erro_dialog: "+query_truncate.ErrorMsg())
|
||||
qdel(query_truncate)
|
||||
return SS_INIT_SUCCESS
|
||||
|
||||
/datum/controller/subsystem/dbcore/stat_entry(msg)
|
||||
|
||||
@@ -41,7 +41,6 @@ SUBSYSTEM_DEF(mobs)
|
||||
// Lets handle all of these while we have time, should always remain extremely small...
|
||||
if(length(death_list)) // Don't contact DB if this list is empty
|
||||
if(CONFIG_GET(flag/sql_enabled))
|
||||
establish_db_connection()
|
||||
if(!SSdbcore.IsConnected())
|
||||
log_game("SQL ERROR during death reporting. Failed to connect.")
|
||||
else
|
||||
|
||||
@@ -20,7 +20,6 @@ SUBSYSTEM_DEF(persist)
|
||||
if(!CONFIG_GET(flag/time_off))
|
||||
return
|
||||
|
||||
establish_db_connection()
|
||||
if(!SSdbcore.IsConnected())
|
||||
src.currentrun.Cut()
|
||||
return
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(M.client)
|
||||
playercount += 1
|
||||
establish_db_connection()
|
||||
if(!SSdbcore.IsConnected())
|
||||
log_game("SQL ERROR during population polling. Failed to connect.")
|
||||
else
|
||||
@@ -47,7 +46,6 @@
|
||||
log_game("Round ended without any feedback being generated. No feedback was sent to the database.")
|
||||
return
|
||||
|
||||
establish_db_connection()
|
||||
if(!SSdbcore.IsConnected())
|
||||
log_game("SQL ERROR during feedback reporting. Failed to connect.")
|
||||
else
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/handle_melee_contact(var/obj/item/W, var/mob/living/user, var/inc_damage = null)
|
||||
if(!action_checks(user))
|
||||
return inc_damage
|
||||
chassis.log_message("Attacked by [W]. Attacker - [user]")
|
||||
chassis.log_message("Attacked by [W]. Attacker - [user]", LOG_GAME)
|
||||
if(prob(chassis.deflect_chance*deflect_coeff))
|
||||
to_chat(user, span_danger("\The [W] bounces off \the [chassis]'s armor."))
|
||||
chassis.log_append_to_last("Armor saved.")
|
||||
|
||||
@@ -2803,7 +2803,7 @@
|
||||
src.log_append_to_last("Armor saved.")
|
||||
src.occupant_message(span_notice("\The [user]'s attack is stopped by the armor."))
|
||||
visible_message(span_infoplain(span_bold("\The [user]") + " rebounds off [src.name]'s armor!"))
|
||||
user.attack_log += text("\[[time_stamp()]\] [span_red("attacked [src.name]")]")
|
||||
add_attack_logs(user, src, "attacked")
|
||||
playsound(src, 'sound/weapons/slash.ogg', 50, 1, -1)
|
||||
|
||||
else if(damage < damage_minimum)//Pathetic damage levels just don't harm MECH. //CHOMPedit temp_damage_minimum -> damage_minimum
|
||||
@@ -2818,7 +2818,7 @@
|
||||
if(damage > internal_damage_minimum) //Only decently painful attacks trigger a chance of mech damage.
|
||||
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
|
||||
visible_message(span_danger("[user] [attack_message] [src]!"))
|
||||
user.attack_log += text("\[[time_stamp()]\] [span_red("attacked [src.name]")]")
|
||||
add_attack_logs(user, src, "attacked")
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
@@ -285,7 +285,7 @@
|
||||
else
|
||||
deflect_chance = initial(deflect_chance)
|
||||
src.occupant_message(span_red("You disable [src] defence mode."))
|
||||
src.log_message("Toggled defence mode.")
|
||||
src.log_message("Toggled defence mode.", LOG_GAME)
|
||||
return
|
||||
|
||||
|
||||
@@ -363,7 +363,7 @@
|
||||
return
|
||||
if(src.occupant.client)
|
||||
src.zoom = !src.zoom
|
||||
src.log_message("Toggled zoom mode.")
|
||||
src.log_message("Toggled zoom mode.", LOG_GAME)
|
||||
if(src.zoom)
|
||||
src.occupant_message(span_blue("Zoom mode enabled."))
|
||||
else
|
||||
@@ -390,7 +390,7 @@
|
||||
if(src.occupant)
|
||||
if(get_charge() > 0)
|
||||
thrusters = !thrusters
|
||||
src.log_message("Toggled thrusters.")
|
||||
src.log_message("Toggled thrusters.", LOG_GAME)
|
||||
if(src.thrusters)
|
||||
src.occupant_message(span_blue("Thrusters enabled."))
|
||||
else
|
||||
|
||||
@@ -645,75 +645,6 @@ GLOBAL_VAR_INIT(world_topic_spam_protect_time, world.timeofday)
|
||||
if (src.status != s)
|
||||
src.status = s
|
||||
|
||||
#define FAILED_DB_CONNECTION_CUTOFF 5
|
||||
GLOBAL_VAR_INIT(failed_db_connections, 0)
|
||||
|
||||
/hook/startup/proc/connectDB()
|
||||
if(!CONFIG_GET(flag/sql_enabled))
|
||||
log_sql("SQL connection disabled in config.")
|
||||
else if(!setup_database_connection())
|
||||
log_sql("Your server failed to establish a connection with the feedback database.")
|
||||
else
|
||||
log_sql("Feedback database connection established.")
|
||||
return 1
|
||||
|
||||
/proc/setup_database_connection()
|
||||
if(!CONFIG_GET(flag/sql_enabled))
|
||||
return 0
|
||||
if(GLOB.failed_db_connections > FAILED_DB_CONNECTION_CUTOFF) //If it failed to establish a connection more than 5 times in a row, don't bother attempting to conenct anymore.
|
||||
return 0
|
||||
|
||||
if(!SSdbcore)
|
||||
SSdbcore = new()
|
||||
|
||||
var/user = CONFIG_GET(string/feedback_login)
|
||||
var/pass = CONFIG_GET(string/feedback_password)
|
||||
var/db = CONFIG_GET(string/feedback_database)
|
||||
var/address = CONFIG_GET(string/address)
|
||||
var/port = CONFIG_GET(number/port)
|
||||
|
||||
SSdbcore.Connect("dbi:mysql:[db]:[address]:[port]","[user]","[pass]")
|
||||
. = SSdbcore.IsConnected()
|
||||
if ( . )
|
||||
GLOB.failed_db_connections = 0 //If this connection succeeded, reset the failed connections counter.
|
||||
return
|
||||
GLOB.failed_db_connections++ //If it failed, increase the failed connections counter.
|
||||
log_sql(SSdbcore.ErrorMsg())
|
||||
return
|
||||
|
||||
//This proc ensures that the connection to the feedback database (global variable dbcon) is established
|
||||
/proc/establish_db_connection()
|
||||
if(GLOB.failed_db_connections > FAILED_DB_CONNECTION_CUTOFF)
|
||||
return 0
|
||||
|
||||
if(!SSdbcore || !SSdbcore.IsConnected())
|
||||
return setup_database_connection()
|
||||
else
|
||||
return 1
|
||||
|
||||
// Cleans up DB connections and recreates them
|
||||
/proc/reset_database_connections()
|
||||
var/list/results = list("-- Resetting DB connections --")
|
||||
GLOB.failed_db_connections = 0
|
||||
|
||||
if(SSdbcore?.IsConnected())
|
||||
SSdbcore.Disconnect()
|
||||
results += "SSdbcore was connected and asked to disconnect"
|
||||
else
|
||||
results += "SSdbcore was not connected"
|
||||
|
||||
if(!CONFIG_GET(flag/sql_enabled))
|
||||
results += "stopping because config.sql_enabled = false"
|
||||
else
|
||||
. = setup_database_connection()
|
||||
if(.)
|
||||
results += "SUCCESS: set up a connection successfully with setup_database_connection()"
|
||||
else
|
||||
results += "FAIL: failed to connect to the database with setup_database_connection()"
|
||||
|
||||
results += "-- DB Reset End --"
|
||||
log_sql(results.Join("\n"))
|
||||
|
||||
// Things to do when a new z-level was just made.
|
||||
/world/proc/max_z_changed()
|
||||
if(!istype(GLOB.players_by_zlevel, /list))
|
||||
@@ -784,8 +715,6 @@ GLOBAL_VAR_INIT(failed_db_connections, 0)
|
||||
/world/proc/on_tickrate_change()
|
||||
SStimer?.reset_buckets()
|
||||
|
||||
#undef FAILED_DB_CONNECTION_CUTOFF
|
||||
|
||||
/proc/auxtools_stack_trace(msg)
|
||||
CRASH(msg)
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
if(!check_rights(R_MOD,0) && !check_rights(R_BAN)) return
|
||||
|
||||
establish_db_connection()
|
||||
if(!SSdbcore.IsConnected())
|
||||
return
|
||||
|
||||
@@ -126,7 +125,6 @@
|
||||
if(job)
|
||||
sql += " AND job = '[job]'"
|
||||
|
||||
establish_db_connection()
|
||||
if(!SSdbcore.IsConnected())
|
||||
return
|
||||
|
||||
@@ -224,7 +222,6 @@
|
||||
|
||||
var/sql = "SELECT ckey FROM erro_ban WHERE id = [id]"
|
||||
|
||||
establish_db_connection()
|
||||
if(!SSdbcore.IsConnected())
|
||||
return
|
||||
|
||||
@@ -276,7 +273,6 @@
|
||||
if(!check_rights_for(user, R_BAN))
|
||||
return
|
||||
|
||||
establish_db_connection()
|
||||
if(!SSdbcore.IsConnected())
|
||||
to_chat(usr, span_filter_adminlog("[span_red("Failed to establish database connection")]"))
|
||||
return
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
var/ckeytext = ckey(key)
|
||||
|
||||
if(!establish_db_connection())
|
||||
if(!SSdbcore.IsConnected())
|
||||
var/msg = "Ban database connection failure. Key [ckeytext] not checked"
|
||||
log_world(msg)
|
||||
message_admins(msg)
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
/atom/var/lastattacker = null
|
||||
/mob/var/lastattacked = null
|
||||
/mob/var/attack_log = list( )
|
||||
/mob/var/dialogue_log = list( )
|
||||
|
||||
/proc/log_and_message_admins(var/message as text, var/mob/user = usr)
|
||||
log_admin(user ? "[key_name(user)] [message]" : "EVENT [message]")
|
||||
@@ -17,30 +15,3 @@
|
||||
|
||||
log_admin("[english_list(user_keys)] [message]")
|
||||
message_admins("[english_list(user_keys)] [message]")
|
||||
/* Old procs
|
||||
/proc/admin_attack_log(var/mob/attacker, var/mob/victim, var/attacker_message, var/victim_message, var/admin_message)
|
||||
if(victim)
|
||||
victim.attack_log += text("\[[time_stamp()]\]" + span_orange(" [key_name(attacker)] - [victim_message]"))
|
||||
if(attacker)
|
||||
attacker.attack_log += text("\[[time_stamp()]\]" + span_red(" [key_name(victim)] - [attacker_message]"))
|
||||
|
||||
msg_admin_attack("[key_name(attacker)] [admin_message] [key_name(victim)] (INTENT: [attacker? uppertext(attacker.a_intent) : "N/A"]) (<A href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[attacker.x];Y=[attacker.y];Z=[attacker.z]'>JMP</a>)")
|
||||
|
||||
/proc/admin_attacker_log_many_victims(var/mob/attacker, var/list/mob/victims, var/attacker_message, var/victim_message, var/admin_message)
|
||||
if(!victims || !victims.len)
|
||||
return
|
||||
|
||||
for(var/mob/victim in victims)
|
||||
admin_attack_log(attacker, victim, attacker_message, victim_message, admin_message)
|
||||
|
||||
/proc/admin_inject_log(mob/attacker, mob/victim, obj/item, reagents, amount_transferred, violent=0)
|
||||
if(violent)
|
||||
violent = "violently "
|
||||
else
|
||||
violent = ""
|
||||
admin_attack_log(attacker,
|
||||
victim,
|
||||
"used \the [weapon] to [violent]inject - [reagents] - [amount_transferred]u transferred",
|
||||
"was [violent]injected with \the [weapon] - [reagents] - [amount_transferred]u transferred",
|
||||
"used \the [weapon] to [violent]inject [reagents] ([amount_transferred]u transferred) into")
|
||||
*/
|
||||
|
||||
@@ -1,65 +1,84 @@
|
||||
/client/proc/cmd_admin_check_player_logs(mob/living/M as mob in GLOB.mob_list)
|
||||
set category = "Admin.Logs"
|
||||
set name = "Check Player Attack Logs"
|
||||
set desc = "Check a player's attack logs."
|
||||
|
||||
show_cmd_admin_check_player_logs(M)
|
||||
ADMIN_VERB_ONLY_CONTEXT_MENU(cmd_admin_check_player_logs, R_ADMIN|R_MOD, "Check Mob Logs", mob/living/player in GLOB.mob_list)
|
||||
user.show_cmd_admin_check_player_logs(player.logging, player.name, player.ckey, player.mind?.special_role)
|
||||
|
||||
//Views specific attack logs belonging to one player.
|
||||
/client/proc/show_cmd_admin_check_player_logs(mob/living/M)
|
||||
var/dat = span_bold("[M]'s Attack Log:<HR>")
|
||||
dat += span_bold("Viewing attack logs of [M]") + " - (Played by ([key_name(M)]).<br>"
|
||||
if(M.mind)
|
||||
dat += span_bold("Current Antag?:") + " [(M.mind.special_role)?"Yes":"No"]<br>"
|
||||
dat += "<br>" + span_bold("Note:") + " This is arranged from earliest to latest. <br><br>"
|
||||
/client/proc/show_cmd_admin_check_player_logs(list/mob_data, target_name, target_ckey, target_special)
|
||||
if(CONFIG_GET(flag/database_logging))
|
||||
var/datum/db_query/query = SSdbcore.NewQuery("SELECT mid,time,ckey,mob,area,color,type,message from erro_dialog WHERE ckey = :t_ckey", list("t_ckey" = ckey))
|
||||
if(!query.Execute())
|
||||
to_chat(src, span_admin("Database query error"))
|
||||
qdel(query)
|
||||
return
|
||||
|
||||
var/list/data = list()
|
||||
while(query.NextRow())
|
||||
var/list/timestamped_message = list(
|
||||
"event_id" = query.item[1],
|
||||
"time" = query.item[2],
|
||||
"ckey" = query.item[3],
|
||||
"name" = query.item[4],
|
||||
"loc" = query.item[5],
|
||||
"color" = query.item[6],
|
||||
"message" = query.item[8]
|
||||
)
|
||||
var/entry_type = query.item[7]
|
||||
if(!islist(data[entry_type]))
|
||||
data[entry_type] = list()
|
||||
UNTYPED_LIST_ADD(data[entry_type], timestamped_message)
|
||||
qdel(query)
|
||||
if(!length(data))
|
||||
to_chat(src, span_admin("No data found."))
|
||||
return
|
||||
admin_log_view_target(data, target_name, target_ckey, target_special)
|
||||
return
|
||||
if(!length(mob_data))
|
||||
to_chat(src, span_admin("No data found."))
|
||||
return
|
||||
admin_log_view_target(mob_data, target_name, target_ckey, target_special)
|
||||
|
||||
if(!isemptylist(M.attack_log))
|
||||
dat += "<fieldset style='border: 2px solid white; display: inline'>"
|
||||
for(var/l in M.attack_log)
|
||||
dat += "[l]<br>"
|
||||
ADMIN_VERB(persistent_client_logs, R_ADMIN|R_MOD, "Check Player Logs", "Displays the client logs of the selected ckey.", ADMIN_CATEGORY_LOGS)
|
||||
var/mob/living/selected_key = tgui_input_list(user, "Select a ckey to check their logs", "Ckey", GLOB.persistent_clients_by_ckey)
|
||||
if(!selected_key)
|
||||
return
|
||||
|
||||
dat += "</fieldset>"
|
||||
var/datum/persistent_client/selected = GLOB.persistent_clients_by_ckey[selected_key]
|
||||
|
||||
else
|
||||
dat += span_italics("No attack logs found for [M].")
|
||||
user.show_cmd_admin_check_player_logs(selected.logging, selected.mob?.name, selected_key, selected.mob?.mind?.special_role)
|
||||
|
||||
var/datum/browser/popup = new(usr, "admin_attack_log", "[src]", 650, 650, src)
|
||||
popup.set_content(jointext(dat,null))
|
||||
popup.open()
|
||||
/client/proc/admin_log_view_target(list/log_data, name, ckey, special, use_db)
|
||||
var/datum/player_log_viwer/log_view = new(log_data, name, ckey, special)
|
||||
log_view.tgui_interact(mob)
|
||||
|
||||
onclose(usr, "admin_attack_log")
|
||||
/datum/player_log_viwer
|
||||
var/list/log_data
|
||||
var/target_name
|
||||
var/target_ckey
|
||||
var/special_role
|
||||
|
||||
feedback_add_details("admin_verb","PL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
/datum/player_log_viwer/tgui_close(mob/user)
|
||||
. = ..()
|
||||
log_data = null
|
||||
|
||||
/client/proc/cmd_admin_check_dialogue_logs(mob/living/M as mob in GLOB.mob_list)
|
||||
set category = "Admin.Logs"
|
||||
set name = "Check Player Dialogue Logs"
|
||||
set desc = "Check a player's dialogue logs."
|
||||
show_cmd_admin_check_dialogue_logs(M)
|
||||
/datum/player_log_viwer/New(list/data, name, ckey, special)
|
||||
. = ..()
|
||||
log_data = data
|
||||
target_name = name
|
||||
target_ckey = ckey
|
||||
special_role = special
|
||||
|
||||
//Views specific dialogue logs belonging to one player.
|
||||
/client/proc/show_cmd_admin_check_dialogue_logs(mob/living/M)
|
||||
var/dat = span_bold("[M]'s Dialogue Log:<HR>")
|
||||
dat += span_bold("Viewing say and emote logs of [M]") + " - (Played by ([key_name(M)]).<br>"
|
||||
if(M.mind)
|
||||
dat += span_bold("Current Antag?:") + " [(M.mind.special_role)?"Yes":"No"]<br>"
|
||||
dat += "<br>" + span_bold("Note:") + " This is arranged from earliest to latest. <br><br>"
|
||||
/datum/player_log_viwer/tgui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "PlayerLogViewer")
|
||||
ui.open()
|
||||
|
||||
if(!isemptylist(M.dialogue_log))
|
||||
dat += "<fieldset style='border: 2px solid white; display: inline'>"
|
||||
/datum/player_log_viwer/tgui_state(mob/user)
|
||||
return ADMIN_STATE(R_ADMIN|R_MOD)
|
||||
|
||||
for(var/d in M.dialogue_log)
|
||||
dat += "[d]<br>"
|
||||
|
||||
dat += "</fieldset>"
|
||||
else
|
||||
dat += span_italics("No dialogue logs found for [M].")
|
||||
var/datum/browser/popup = new(usr, "admin_dialogue_log", "[src]", 650, 650, src)
|
||||
popup.set_content(jointext(dat,null))
|
||||
popup.open()
|
||||
|
||||
onclose(usr, "admin_dialogue_log")
|
||||
|
||||
|
||||
feedback_add_details("admin_verb","PDL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
/datum/player_log_viwer/tgui_static_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
|
||||
return list(
|
||||
"entries" = log_data,
|
||||
"name" = target_name,
|
||||
"ckey" = target_ckey,
|
||||
"special" = special_role
|
||||
)
|
||||
|
||||
@@ -20,8 +20,6 @@ GLOBAL_LIST_INIT(admin_verbs_admin, list(
|
||||
/client/proc/cmd_admin_pm_context, //right-click adminPM interface,
|
||||
/client/proc/cmd_admin_pm_panel, //admin-pm list,
|
||||
/client/proc/cmd_admin_subtle_message, //send an message to somebody as a 'voice in their head',
|
||||
/client/proc/cmd_admin_check_player_logs, //checks a player's attack logs,
|
||||
/client/proc/cmd_admin_check_dialogue_logs, //checks a player's dialogue logs,
|
||||
/datum/admins/proc/access_news_network, //allows access of newscasters,
|
||||
/client/proc/jumptocoord, //we ghost and jump to a coordinate,
|
||||
/client/proc/Getmob, //teleports a mob to our location,
|
||||
@@ -174,8 +172,6 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
|
||||
/datum/admins/proc/toggleguests,
|
||||
/datum/admins/proc/announce,
|
||||
/client/proc/cmd_admin_subtle_message,
|
||||
/client/proc/cmd_admin_check_player_logs,
|
||||
/client/proc/cmd_admin_check_dialogue_logs,
|
||||
/datum/admins/proc/access_news_network,
|
||||
/client/proc/cmd_admin_direct_narrate,
|
||||
/client/proc/cmd_admin_world_narrate,
|
||||
@@ -277,8 +273,6 @@ GLOBAL_LIST_INIT(admin_verbs_event_manager, list(
|
||||
/client/proc/cmd_admin_pm_context, //right-click adminPM interface,
|
||||
/client/proc/cmd_admin_pm_panel, //admin-pm list,
|
||||
/client/proc/cmd_admin_subtle_message, //send an message to somebody as a 'voice in their head',
|
||||
/client/proc/cmd_admin_check_player_logs, //checks a player's attack logs,
|
||||
/client/proc/cmd_admin_check_dialogue_logs, //checks a player's dialogue logs,
|
||||
/datum/admins/proc/access_news_network, //allows access of newscasters,
|
||||
/client/proc/jumptocoord, //we ghost and jump to a coordinate,
|
||||
/client/proc/Getmob, //teleports a mob to our location,
|
||||
|
||||
@@ -683,7 +683,6 @@ ADMIN_VERB(removetickets, R_ADMIN, "Security Tickets", "Allows one to remove tic
|
||||
|
||||
var/dat = "<HEAD><TITLE>Book Inventory Management</TITLE></HEAD><BODY>\n"
|
||||
dat += "<h3>ADMINISTRATIVE MANAGEMENT</h3>"
|
||||
establish_db_connection()
|
||||
|
||||
if(!SSdbcore.IsConnected())
|
||||
dat += span_red(span_bold("ERROR") + ": Unable to contact External Archive. Please contact your system administrator for assistance.")
|
||||
|
||||
@@ -69,7 +69,7 @@ DEBUG
|
||||
GLOB.jobban_keylist=list()
|
||||
log_admin("jobban_keylist was empty")
|
||||
else
|
||||
if(!establish_db_connection())
|
||||
if(!SSdbcore.IsConnected())
|
||||
log_sql("Database connection failed. Reverting to the legacy ban system.")
|
||||
CONFIG_SET(flag/ban_legacy_system, TRUE)
|
||||
jobban_loadbanfile()
|
||||
|
||||
@@ -39,4 +39,4 @@
|
||||
if((M.mind && M.mind.special_role && A && A.can_hear_aooc) || isobserver(M)) // Antags must have their type be allowed to AOOC to see AOOC. This prevents, say, ERT from seeing AOOC.
|
||||
to_chat(M, span_ooc(span_aooc("[create_text_tag("aooc", "Antag-OOC:", M.client)] <EM>[player_display]:</EM> " + span_message("[msg]"))))
|
||||
|
||||
src.mob.log_talk("(AOOC) [msg]", LOG_OOC)
|
||||
src.mob.log_talk("(AOOC) [msg]", LOG_OOC, color="#ff0000")
|
||||
|
||||
@@ -31,7 +31,6 @@ GLOBAL_VAR_INIT(inactive_keys, "None<br>")
|
||||
if(GLOB.checked_for_inactives)
|
||||
return
|
||||
|
||||
establish_db_connection()
|
||||
if(!SSdbcore.IsConnected())
|
||||
return
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
else
|
||||
log_admin("Database already disconnected")
|
||||
|
||||
establish_db_connection()
|
||||
var/errno = SSdbcore.ErrorMsg()
|
||||
if(errno)
|
||||
log_admin("Database connection returned error message `[errno]`. Aborting.")
|
||||
|
||||
@@ -437,7 +437,6 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
// Returns null if no DB connection can be established, or -1 if the requested key was not found in the database
|
||||
|
||||
/proc/get_player_age(key)
|
||||
establish_db_connection()
|
||||
if(!SSdbcore.IsConnected())
|
||||
return null
|
||||
|
||||
@@ -458,7 +457,6 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
if ( IsGuestKey(src.key) )
|
||||
return
|
||||
|
||||
establish_db_connection()
|
||||
if(!SSdbcore.IsConnected())
|
||||
return
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
message_admins("[key_name_admin(src)] has attempted to post a link in OOC: [msg]")
|
||||
return
|
||||
|
||||
src.mob.log_talk(msg, LOG_OOC)
|
||||
src.mob.log_talk(msg, LOG_OOC, color="#0051ff")
|
||||
|
||||
if(msg)
|
||||
handle_spam_prevention(MUTE_OOC)
|
||||
@@ -125,7 +125,7 @@
|
||||
message_admins("[key_name_admin(src)] has attempted to post a link in OOC: [msg]")
|
||||
return
|
||||
|
||||
src.mob.log_message(msg, LOG_LOOC)
|
||||
src.mob.log_message(msg, LOG_LOOC, color="#53cbff")
|
||||
|
||||
if(msg)
|
||||
handle_spam_prevention(MUTE_LOOC)
|
||||
|
||||
@@ -235,8 +235,7 @@
|
||||
else
|
||||
to_chat(victim, span_danger("Searing hot oil scorches your [E ? E.name : "flesh"]!"))
|
||||
|
||||
user.attack_log += text("\[[time_stamp()]\] [span_red("Has [cook_type] \the [victim] ([victim.ckey]) in \a [src]")]")
|
||||
victim.attack_log += text("\[[time_stamp()]\] [span_orange("Has been [cook_type] in \a [src] by [user.name] ([user.ckey])")]")
|
||||
add_attack_logs(user, victim, "has been [cook_type] with [src]")
|
||||
msg_admin_attack("[key_name_admin(user)] [cook_type] \the [victim] ([victim.ckey]) in \a [src]. (<A href='byond://?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)")
|
||||
|
||||
//Coat the victim in some oil
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
<A href='byond://?src=\ref[src];setauthor=1'>Filter by Author: [author]</A><BR>
|
||||
<A href='byond://?src=\ref[src];search=1'>\[Start Search\]</A><BR>"}
|
||||
if(1)
|
||||
establish_db_connection()
|
||||
if(!SSdbcore.IsConnected())
|
||||
dat += span_red(span_bold("ERROR") + ": Unable to contact External Archive. Please contact your system administrator for assistance.") + "<BR>"
|
||||
else if(!SQLquery)
|
||||
@@ -263,7 +262,6 @@
|
||||
<A href='byond://?src=\ref[src];switchscreen=0'>No.</A><BR>"}
|
||||
if(8)
|
||||
dat += "<h3>External Archive</h3>" //VOREStation Edit
|
||||
establish_db_connection()
|
||||
|
||||
//dat += "<h3>" + span_red("arning: System Administrator has slated this archive for removal. Personal uploads should be taken to the NT board of internal literature.") + "</h3>" //VOREStation Removal
|
||||
|
||||
@@ -302,7 +300,6 @@
|
||||
var/dat = "<HEAD><TITLE>Book Inventory Management</TITLE></HEAD><BODY>\n" // <META HTTP-EQUIV='Refresh' CONTENT='10'>
|
||||
|
||||
dat += "<h3>ADMINISTRATIVE MANAGEMENT</h3>"
|
||||
establish_db_connection()
|
||||
|
||||
if(!SSdbcore.IsConnected())
|
||||
dat += span_red(span_bold("ERROR") + ": Unable to contact External Archive. Please contact your system administrator for assistance.")
|
||||
@@ -423,7 +420,6 @@
|
||||
if(scanner.cache.unique)
|
||||
tgui_alert_async(usr, "This book has been rejected from the database. Aborting!")
|
||||
else
|
||||
establish_db_connection()
|
||||
if(!SSdbcore.IsConnected())
|
||||
tgui_alert_async(usr, "Connection to Archive has been severed. Aborting.")
|
||||
else
|
||||
@@ -448,7 +444,6 @@
|
||||
|
||||
if(href_list["targetid"])
|
||||
var/sqlid = sanitizeSQL(href_list["targetid"])
|
||||
establish_db_connection()
|
||||
if(!SSdbcore.IsConnected())
|
||||
tgui_alert_async(usr, "Connection to Archive has been severed. Aborting.")
|
||||
if(bibledelay)
|
||||
@@ -480,7 +475,6 @@
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
var/sqlid = sanitizeSQL(href_list["delid"])
|
||||
establish_db_connection()
|
||||
if(!SSdbcore.IsConnected())
|
||||
tgui_alert_async(usr, "Connection to Archive has been severed. Aborting.")
|
||||
else
|
||||
|
||||
@@ -65,7 +65,6 @@
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
T = get_turf(M) //Where is the body located?
|
||||
attack_log = M.attack_log //preserve our attack logs by copying them to our ghost
|
||||
gender = M.gender
|
||||
if(M.mind && M.mind.name)
|
||||
name = M.mind.name
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
if(!message)
|
||||
return
|
||||
|
||||
log_talk("(GHOST SAY) [message]", LOG_SAY)
|
||||
log_talk("(GHOST SAY) [message]", LOG_SAY, color="#9c00bc")
|
||||
|
||||
if (client)
|
||||
if(message)
|
||||
@@ -20,7 +20,7 @@
|
||||
if(!message)
|
||||
return
|
||||
|
||||
log_message("(GHOST EMOTE) [message]", LOG_EMOTE)
|
||||
log_message("(GHOST EMOTE) [message]", LOG_EMOTE, color="#9c00bc")
|
||||
|
||||
if(client)
|
||||
if(message)
|
||||
|
||||
@@ -423,12 +423,12 @@ GLOBAL_LIST_EMPTY(channel_to_radio_key)
|
||||
blooploop(message, extrarange = -6, volume = 25, sound_preference = /datum/preference/toggle/whisper_sounds)
|
||||
// playsound(T, pick(voice_sounds_list), 25, TRUE, extrarange = -6, falloff = 1 , is_global = TRUE, frequency = voice_freq, ignore_walls = TRUE, preference = /datum/preference/toggle/whisper_sounds) //CHOMPEdit - ignore_walls = TRUE
|
||||
|
||||
log_talk(message, LOG_WHISPER)
|
||||
log_talk(message, LOG_WHISPER, color="#aeaeae")
|
||||
else
|
||||
if(do_sound && message)
|
||||
blooploop(message, volume = 75)
|
||||
// playsound(T, pick(voice_sounds_list), 75, TRUE, falloff = 1 , is_global = TRUE, frequency = voice_freq, ignore_walls = TRUE, preference = /datum/preference/toggle/say_sounds) //CHOMPEdit - ignore_walls = TRUE
|
||||
log_talk(message, LOG_SAY)
|
||||
log_talk(message, LOG_SAY, color="#c0c0c0")
|
||||
return 1
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
@@ -67,7 +67,6 @@
|
||||
if(!client) return 0
|
||||
|
||||
if(href_list["privacy_poll"])
|
||||
establish_db_connection()
|
||||
if(!SSdbcore.IsConnected())
|
||||
return
|
||||
var/voted = 0
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
|
||||
/mob/new_player/proc/handle_privacy_poll()
|
||||
establish_db_connection()
|
||||
if(!SSdbcore.IsConnected())
|
||||
return
|
||||
var/voted = 0
|
||||
@@ -47,7 +46,6 @@
|
||||
var/optiontext
|
||||
|
||||
/mob/new_player/proc/handle_player_polling()
|
||||
establish_db_connection()
|
||||
if(SSdbcore.IsConnected())
|
||||
var/isadmin = 0
|
||||
if(src.client && check_rights_for(src.client, R_HOLDER))
|
||||
@@ -81,7 +79,6 @@
|
||||
|
||||
/mob/new_player/proc/poll_player(var/pollid = -1)
|
||||
if(pollid == -1) return
|
||||
establish_db_connection()
|
||||
if(SSdbcore.IsConnected())
|
||||
|
||||
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM erro_poll_question WHERE id = [pollid]")
|
||||
@@ -343,7 +340,6 @@
|
||||
|
||||
if(!isnum(pollid) || !isnum(optionid))
|
||||
return
|
||||
establish_db_connection()
|
||||
if(SSdbcore.IsConnected())
|
||||
|
||||
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM erro_poll_question WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime")
|
||||
@@ -415,7 +411,6 @@
|
||||
|
||||
if(!isnum(pollid) || !istext(replytext))
|
||||
return
|
||||
establish_db_connection()
|
||||
if(SSdbcore.IsConnected())
|
||||
|
||||
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT starttime, endtime, question, polltype FROM erro_poll_question WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime")
|
||||
@@ -474,7 +469,6 @@
|
||||
|
||||
if(!isnum(pollid) || !isnum(optionid))
|
||||
return
|
||||
establish_db_connection()
|
||||
if(SSdbcore.IsConnected())
|
||||
|
||||
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT starttime, endtime, question, polltype FROM erro_poll_question WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime")
|
||||
|
||||
@@ -366,7 +366,7 @@
|
||||
G.client?.prefs?.read_preference(/datum/preference/toggle/ghost_see_whisubtle))
|
||||
if(client?.prefs?.read_preference(/datum/preference/toggle/whisubtle_vis) || check_rights_for(G.client, R_HOLDER))
|
||||
to_chat(G, span_psay("[formatted_name] thinks, \"[message]\""))
|
||||
M.log_talk("(PSAY) [message]", LOG_SAY)
|
||||
M.log_talk("(PSAY) [message]", LOG_SAY, color="#d900ff")
|
||||
else //There wasn't anyone to send the message to, pred or prey, so let's just say it instead and correct our psay just in case.
|
||||
M.forced_psay = FALSE
|
||||
M.say(message)
|
||||
@@ -480,7 +480,7 @@
|
||||
G.client?.prefs?.read_preference(/datum/preference/toggle/ghost_see_whisubtle))
|
||||
if(client?.prefs?.read_preference(/datum/preference/toggle/whisubtle_vis) || check_rights_for(G.client, R_HOLDER))
|
||||
to_chat(G, span_pemote("[formatted_name] [message]"))
|
||||
M.log_talk(message, LOG_SAY)
|
||||
M.log_talk(message, LOG_SAY, color="#d900ff")
|
||||
else //There wasn't anyone to send the message to, pred or prey, so let's just emote it instead and correct our psay just in case.
|
||||
M.forced_psay = FALSE
|
||||
M.me_verb(message)
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
type = MESSAGE_TYPE_NIF,
|
||||
html = span_nif(span_bold("\[[icon2html(nif.big_icon, CS.client)]NIF\]") + message))
|
||||
|
||||
sender.log_talk("NSAY (NIF:[nif.human.real_name]): [message]", LOG_SAY)
|
||||
sender.log_talk("NSAY (NIF:[nif.human.real_name]): [message]", LOG_SAY, color="#ff00c8")
|
||||
|
||||
/datum/nifsoft/soulcatcher/proc/emote_into(var/message, var/mob/living/sender, var/mob/eyeobj, var/whisper)
|
||||
var/sender_name = eyeobj ? eyeobj.name : sender.name
|
||||
@@ -135,7 +135,7 @@
|
||||
type = MESSAGE_TYPE_NIF,
|
||||
html = span_nif(span_bold("\[[icon2html(nif.big_icon,CS.client)]NIF\]") + message))
|
||||
|
||||
sender.log_message("NME (NIF:[nif.human.real_name]): [message]", LOG_EMOTE)
|
||||
sender.log_message("NME (NIF:[nif.human.real_name]): [message]", LOG_EMOTE, color="#ff00c8")
|
||||
|
||||
/datum/nifsoft/soulcatcher/proc/show_settings(var/mob/living/carbon/human/H)
|
||||
set waitfor = FALSE
|
||||
|
||||
@@ -179,7 +179,7 @@
|
||||
PM.receive_message(list("sent" = 0, "owner" = "[pda.owner]", "job" = "[pda.ownjob]", "message" = "[t]", "target" = "\ref[pda]"), "\ref[pda]")
|
||||
|
||||
SStgui.update_user_uis(U, P) // Update the sending user's PDA UI so that they can see the new message
|
||||
U.log_message("(PDA: [src.name] | [U.real_name]) sent \"[t]\" to [P.name]", LOG_PDA)
|
||||
U.log_message("(PDA: [src.name] | [U.real_name]) sent \"[t]\" to [P.name]", LOG_PDA, color="#00ff00")
|
||||
to_chat(U, "[icon2html(pda,U.client)] <b>Sent message to [P.owner] ([P.ownjob]), </b>\"[t]\"")
|
||||
else
|
||||
to_chat(U, span_notice("ERROR: Messaging server is not responding.\n\n\
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
if(user in target) //no wrapping closets that you are inside - it's not physically possible
|
||||
return
|
||||
|
||||
user.attack_log += text("\[[time_stamp()]\] [span_blue("Has used [src.name] on \ref[target]")]")
|
||||
add_attack_logs(user, target, "has been wrapped with [src]")
|
||||
|
||||
if (istype(target, /obj/item) && !(istype(target, /obj/item/storage) && !istype(target,/obj/item/storage/box)))
|
||||
var/obj/item/O = target
|
||||
|
||||
@@ -363,7 +363,6 @@ GLOBAL_DATUM(blackbox, /obj/machinery/blackbox_recorder)
|
||||
if(!feedback) return
|
||||
|
||||
round_end_data_gathering() //round_end time logging and some other data processing
|
||||
establish_db_connection()
|
||||
if(!SSdbcore.IsConnected()) return
|
||||
var/round_id
|
||||
|
||||
|
||||
@@ -383,7 +383,7 @@
|
||||
else
|
||||
destroy_shields()
|
||||
my_tool.set_ready_state(TRUE)
|
||||
my_tool.log_message("Power lost.")
|
||||
my_tool.log_message("Power lost.", LOG_GAME)
|
||||
else
|
||||
my_tool.set_ready_state(TRUE)
|
||||
|
||||
@@ -409,5 +409,5 @@
|
||||
..()
|
||||
my_mecha.use_power(my_tool.energy_drain)
|
||||
if(!active && shield_health < shield_regen_amount)
|
||||
my_tool.log_message("Shield overloaded.")
|
||||
my_tool.log_message("Shield overloaded.", LOG_GAME)
|
||||
my_mecha.use_power(my_tool.energy_drain * 4)
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
take_charge(user, skipcharge)
|
||||
|
||||
before_cast(targets) //applies any overlays and effects
|
||||
user.attack_log += text("\[[time_stamp()]\] [span_red("[user.real_name] ([user.ckey]) cast the spell [name].")]")
|
||||
add_attack_logs(user, targets, "casted the spell [name]")
|
||||
if(prob(critfailchance))
|
||||
critfail(targets, user)
|
||||
else
|
||||
|
||||
@@ -283,7 +283,7 @@
|
||||
else
|
||||
user.add_spell(S)
|
||||
to_chat(user, span_notice("you rapidly read through the arcane book. Suddenly you realize you understand [spellname]!"))
|
||||
user.attack_log += text("\[[time_stamp()]\] [span_orange("[user.real_name] ([user.ckey]) learned the spell [spellname] ([S]).")]")
|
||||
add_attack_logs(user, src, "learned the spell [spellname] ([S]).")
|
||||
onlearned(user)
|
||||
|
||||
/obj/item/spellbook/oneuse/proc/recoil(mob/user as mob)
|
||||
|
||||
@@ -418,7 +418,7 @@
|
||||
if(!damage)
|
||||
return
|
||||
visible_message(span_danger("[user] [attack_message] the [src]!"))
|
||||
user.attack_log += text("\[[time_stamp()]\] [span_red("attacked [src.name]")]")
|
||||
add_attack_logs(user, src, "attacked")
|
||||
user.do_attack_animation(src)
|
||||
src.health -= damage
|
||||
if(mechanical && prob(10))
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
for(var/mob/living/carbon/brain/caught_soul/CS as anything in brainmobs)
|
||||
to_chat(CS, message)
|
||||
|
||||
sender.log_talk("NSAY (NIF:[owner.real_name]): [message]", LOG_SAY)
|
||||
sender.log_talk("NSAY (SC:[owner.real_name]): [message]", LOG_SAY, color="#ff006f")
|
||||
|
||||
// Forwards the emotes of captured souls
|
||||
/obj/soulgem/proc/use_emote(var/message, var/mob/living/sender, var/mob/eyeobj, var/whisper)
|
||||
@@ -127,7 +127,7 @@
|
||||
for(var/mob/living/carbon/brain/caught_soul/CS as anything in brainmobs)
|
||||
to_chat(CS, message)
|
||||
|
||||
sender.log_message("NME (NIF:[owner.real_name]): [message]", LOG_EMOTE)
|
||||
sender.log_message("NME (SC:[owner.real_name]): [message]", LOG_EMOTE, color="#ff006f")
|
||||
|
||||
// The capture function which transfers the given mob's mind into the soulcatcher
|
||||
/obj/soulgem/proc/catch_mob(var/mob/M, var/custom_name)
|
||||
|
||||
@@ -590,6 +590,11 @@ JUKEBOX_TRACK_FILES config/jukebox.json
|
||||
# REQUIRES chatlog_database_backend to be enabled
|
||||
#CHATLOG_DATABASE_API_ENDPOINT https://example.com
|
||||
|
||||
# Logs player logs inside the Database. Reduces memory usage, but increases cpu load
|
||||
# REQUIRES an database
|
||||
# Uncomment to enable
|
||||
#DATABASE_LOGGING
|
||||
|
||||
## Uncomment to block granting profiling privileges to users with R_DEBUG, for performance purposes
|
||||
#FORBID_ADMIN_PROFILING
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import { formatTime } from 'tgui-core/format';
|
||||
|
||||
export function stripHtml(str: string) {
|
||||
return str.replace(/<[^>]+>/g, '');
|
||||
}
|
||||
|
||||
export function displayTime(time: string | number): string {
|
||||
if (typeof time === 'number') return formatTime(time);
|
||||
const d = new Date(time);
|
||||
return d.toLocaleTimeString();
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
import { useState } from 'react';
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import { Window } from 'tgui/layouts';
|
||||
import { Box, Button, Input, Section, Stack, Tabs } from 'tgui-core/components';
|
||||
import { displayTime, stripHtml } from './function';
|
||||
import type { Data, ExtendedLogEntry } from './types';
|
||||
|
||||
export const PlayerLogViewer = (props) => {
|
||||
const { data } = useBackend<Data>();
|
||||
|
||||
const [activeTab, setActiveTab] = useState('');
|
||||
const [search, setSearch] = useState('');
|
||||
const [searchRegex, setSearchRegex] = useState(false);
|
||||
const [caseSensitive, setCaseSensitive] = useState(false);
|
||||
if (!search && searchRegex) {
|
||||
setSearchRegex(false);
|
||||
}
|
||||
|
||||
const { entries, name, ckey, special } = data;
|
||||
|
||||
const allEntries = Object.entries(entries)
|
||||
.flatMap(([category, logs]) =>
|
||||
logs.map((entry) => ({ ...entry, category: category })),
|
||||
)
|
||||
.sort((a, b) => {
|
||||
if (a.time !== b.time)
|
||||
return displayTime(a.time).localeCompare(displayTime(b.time));
|
||||
return a.event_id - b.event_id;
|
||||
});
|
||||
|
||||
const entriesWithAll: Record<string, ExtendedLogEntry[]> = {
|
||||
ALL: allEntries,
|
||||
...entries,
|
||||
};
|
||||
|
||||
if (!activeTab && Object.keys(entriesWithAll).length > 0) {
|
||||
setActiveTab('ALL');
|
||||
}
|
||||
|
||||
return (
|
||||
<Window width={800} height={600}>
|
||||
<Window.Content>
|
||||
<Stack vertical fill>
|
||||
<Stack.Item>
|
||||
<Section title="General Information">
|
||||
<Stack vertical>
|
||||
<Stack.Item>
|
||||
{`Viewing logs of `}
|
||||
<Box inline bold>
|
||||
{name}
|
||||
</Box>
|
||||
{`, played by `}
|
||||
<Box inline bold>
|
||||
{ckey ?? '<No Player>'}
|
||||
</Box>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
{`Characrer special role: `}
|
||||
<Box inline color={special ? 'green' : 'red'}>
|
||||
{special ? special : '<None>'}
|
||||
</Box>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Tabs scrollable>
|
||||
{Object.keys(entriesWithAll).map((entry) => (
|
||||
<Tabs.Tab
|
||||
selected={entry === activeTab}
|
||||
key={entry}
|
||||
onClick={() => setActiveTab(entry)}
|
||||
>
|
||||
{entry}
|
||||
</Tabs.Tab>
|
||||
))}
|
||||
</Tabs>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<Section
|
||||
fill
|
||||
scrollable
|
||||
title={`Active Log: ${activeTab}`}
|
||||
buttons={
|
||||
<Stack>
|
||||
<Stack.Item>
|
||||
<Input
|
||||
width="200px"
|
||||
placeholder="Search"
|
||||
value={search}
|
||||
onChange={setSearch}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
icon="code"
|
||||
tooltip="RegEx Search"
|
||||
selected={searchRegex}
|
||||
onClick={() => setSearchRegex(!searchRegex)}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
icon="font"
|
||||
selected={caseSensitive}
|
||||
tooltip="Case Sensitive"
|
||||
onClick={() => setCaseSensitive(!caseSensitive)}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Button
|
||||
icon="trash"
|
||||
tooltip="Clear Search"
|
||||
color="bad"
|
||||
onClick={() => {
|
||||
setSearch('');
|
||||
setSearchRegex(false);
|
||||
}}
|
||||
/>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
}
|
||||
>
|
||||
<Stack fill vertical>
|
||||
{entriesWithAll[activeTab] ? (
|
||||
entriesWithAll[activeTab]
|
||||
.filter((entry) => {
|
||||
if (!search) return true;
|
||||
|
||||
const cleanMessage = stripHtml(entry.message);
|
||||
if (searchRegex) {
|
||||
try {
|
||||
const regex = new RegExp(
|
||||
search,
|
||||
caseSensitive ? 'g' : 'gi',
|
||||
);
|
||||
return regex.test(cleanMessage);
|
||||
} catch {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (caseSensitive) return cleanMessage.includes(search);
|
||||
return cleanMessage
|
||||
.toLowerCase()
|
||||
.includes(search.toLowerCase());
|
||||
}
|
||||
})
|
||||
.map((log_entry) => (
|
||||
<Stack.Item
|
||||
key={`${log_entry.category}-${log_entry.event_id}`}
|
||||
>
|
||||
<Box inline>{displayTime(log_entry.time)}</Box>
|
||||
<Box inline preserveWhitespace bold>
|
||||
{` ${log_entry.name}/${log_entry.ckey}`}
|
||||
</Box>
|
||||
<Box inline preserveWhitespace>
|
||||
{` at (${log_entry.loc}): `}
|
||||
</Box>
|
||||
<Box inline preserveWhitespace color={log_entry.color}>
|
||||
{stripHtml(log_entry.message)}
|
||||
</Box>
|
||||
</Stack.Item>
|
||||
))
|
||||
) : (
|
||||
<Box color="red" textAlign="center">
|
||||
No Entry Selected.
|
||||
</Box>
|
||||
)}
|
||||
</Stack>
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
export type Data = {
|
||||
entries: Record<string, LogEntry[]>;
|
||||
name: string | null;
|
||||
ckey: string;
|
||||
special: string | null;
|
||||
};
|
||||
|
||||
type LogEntry = {
|
||||
event_id: number;
|
||||
time: number | string;
|
||||
ckey: string | null;
|
||||
name: string;
|
||||
loc: string | null;
|
||||
color: string | null;
|
||||
message: string;
|
||||
};
|
||||
|
||||
export type ExtendedLogEntry = { category: string } & Required<LogEntry>;
|
||||
@@ -440,6 +440,7 @@
|
||||
#include "code\_helpers\logging\attack.dm"
|
||||
#include "code\_helpers\logging\debug.dm"
|
||||
#include "code\_helpers\logging\game.dm"
|
||||
#include "code\_helpers\logging\log_to_db.dm"
|
||||
#include "code\_helpers\logging\mob.dm"
|
||||
#include "code\_helpers\logging\pda.dm"
|
||||
#include "code\_helpers\logging\research.dm"
|
||||
|
||||
Reference in New Issue
Block a user