From a94d66a1bbafa98446d5c488b4afd88aeae98896 Mon Sep 17 00:00:00 2001 From: Lord Lag Date: Fri, 26 Feb 2016 16:46:59 +0000 Subject: [PATCH 01/31] Borer standard Returns Cortical borer's brain devour, and therefor all zombie abilities. Was removed in new code due to players being awful. --- code/modules/mob/living/simple_animal/borer/borer_powers.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/living/simple_animal/borer/borer_powers.dm b/code/modules/mob/living/simple_animal/borer/borer_powers.dm index f6b87bfd444..001197d9700 100644 --- a/code/modules/mob/living/simple_animal/borer/borer_powers.dm +++ b/code/modules/mob/living/simple_animal/borer/borer_powers.dm @@ -126,7 +126,7 @@ src << "They are no longer in range!" return -/* + /mob/living/simple_animal/borer/verb/devour_brain() set category = "Abilities" set name = "Devour Brain" @@ -150,7 +150,7 @@ src << "It only takes a few moments to render the dead host brain down into a nutrient-rich slurry..." replace_brain() -*/ + // BRAIN WORM ZOMBIES AAAAH. /mob/living/simple_animal/borer/proc/replace_brain() From 4324d83c7ce1ff05a209549f36bc61f0c4ba41a5 Mon Sep 17 00:00:00 2001 From: Lord Lag Date: Sat, 27 Feb 2016 15:30:03 +0000 Subject: [PATCH 02/31] Revert "Borer standard" This reverts commit a94d66a1bbafa98446d5c488b4afd88aeae98896. --- code/modules/mob/living/simple_animal/borer/borer_powers.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/living/simple_animal/borer/borer_powers.dm b/code/modules/mob/living/simple_animal/borer/borer_powers.dm index 001197d9700..f6b87bfd444 100644 --- a/code/modules/mob/living/simple_animal/borer/borer_powers.dm +++ b/code/modules/mob/living/simple_animal/borer/borer_powers.dm @@ -126,7 +126,7 @@ src << "They are no longer in range!" return - +/* /mob/living/simple_animal/borer/verb/devour_brain() set category = "Abilities" set name = "Devour Brain" @@ -150,7 +150,7 @@ src << "It only takes a few moments to render the dead host brain down into a nutrient-rich slurry..." replace_brain() - +*/ // BRAIN WORM ZOMBIES AAAAH. /mob/living/simple_animal/borer/proc/replace_brain() From cc9079a69d4143e0f27cc7fec888d114be8cba48 Mon Sep 17 00:00:00 2001 From: Lord Lag Date: Sat, 27 Feb 2016 15:55:52 +0000 Subject: [PATCH 03/31] Return of borers Borers brought up to spec. --- code/game/objects/items/devices/scanners.dm | 6 +++--- code/modules/mob/living/carbon/human/life.dm | 6 +++--- code/modules/mob/living/simple_animal/borer/borer_powers.dm | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index c0275461962..691f56de1b3 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -178,9 +178,9 @@ REAGENT SCANNER user.show_message(text("\red Warning: [D.form] Detected\nName: [D.name].\nType: [D.spread].\nStage: [D.stage]/[D.max_stages].\nPossible Cure: [D.cure]")) // if (M.reagents && M.reagents.get_reagent_amount("inaprovaline")) // user.show_message("\blue Bloodstream Analysis located [M.reagents:get_reagent_amount("inaprovaline")] units of rejuvenation chemicals.") - if (M.has_brain_worms()) - user.show_message("\red Subject suffering from aberrant brain activity. Recommend further scanning.") - else if (M.getBrainLoss() >= 100 || !M.has_brain()) +// if (M.has_brain_worms()) +// user.show_message("\red Subject suffering from aberrant brain activity. Recommend further scanning.") //Cortical borer disable + if (M.getBrainLoss() >= 100 || !M.has_brain()) user.show_message("\red Subject is brain dead.") else if (M.getBrainLoss() >= 60) user.show_message("\red Severe brain damage detected. Subject likely to have mental retardation.") diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 51f6a9a04f9..293be2d0dda 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1635,13 +1635,13 @@ holder2.icon_state = "hudxeno" else if(foundVirus) holder.icon_state = "hudill" - else if(has_brain_worms()) - var/mob/living/simple_animal/borer/B = has_brain_worms() + /* else if(has_brain_worms()) + var/mob/living/simple_animal/borer/B = has_brain_worms() //Cotrical borer disable if(B.controlling) holder.icon_state = "hudbrainworm" else holder.icon_state = "hudhealthy" - holder2.icon_state = "hudbrainworm" + holder2.icon_state = "hudbrainworm" */ else holder.icon_state = "hudhealthy" if(virus2.len) diff --git a/code/modules/mob/living/simple_animal/borer/borer_powers.dm b/code/modules/mob/living/simple_animal/borer/borer_powers.dm index f6b87bfd444..001197d9700 100644 --- a/code/modules/mob/living/simple_animal/borer/borer_powers.dm +++ b/code/modules/mob/living/simple_animal/borer/borer_powers.dm @@ -126,7 +126,7 @@ src << "They are no longer in range!" return -/* + /mob/living/simple_animal/borer/verb/devour_brain() set category = "Abilities" set name = "Devour Brain" @@ -150,7 +150,7 @@ src << "It only takes a few moments to render the dead host brain down into a nutrient-rich slurry..." replace_brain() -*/ + // BRAIN WORM ZOMBIES AAAAH. /mob/living/simple_animal/borer/proc/replace_brain() From 44f21210429396cdaf410407859fa24d53f952e6 Mon Sep 17 00:00:00 2001 From: skull132 Date: Wed, 2 Mar 2016 22:44:00 +0200 Subject: [PATCH 04/31] Remove forumdb Unused object and vars. Cleans them up, as well as removes the config file. --- code/controllers/configuration.dm | 42 ------------------------------- code/global.dm | 10 -------- code/world.dm | 1 - config/example/forumdbconfig.txt | 19 -------------- 4 files changed, 72 deletions(-) delete mode 100644 config/example/forumdbconfig.txt diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index ea01ad942fa..c7e24f54627 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -777,48 +777,6 @@ var/list/gamemode_cache = list() else log_misc("Unknown setting in configuration: '[name]'") -/datum/configuration/proc/loadforumsql(filename) // -- TLE - var/list/Lines = file2list(filename) - for(var/t in Lines) - if(!t) continue - - t = trim(t) - if (length(t) == 0) - continue - else if (copytext(t, 1, 2) == "#") - continue - - var/pos = findtext(t, " ") - var/name = null - var/value = null - - if (pos) - name = lowertext(copytext(t, 1, pos)) - value = copytext(t, pos + 1) - else - name = lowertext(t) - - if (!name) - continue - - switch (name) - if ("address") - forumsqladdress = value - if ("port") - forumsqlport = value - if ("database") - forumsqldb = value - if ("login") - forumsqllogin = value - if ("password") - forumsqlpass = value - if ("activatedgroup") - forum_activated_group = value - if ("authenticatedgroup") - forum_authenticated_group = value - else - log_misc("Unknown setting in configuration: '[name]'") - /datum/configuration/proc/pick_mode(mode_name) // I wish I didn't have to instance the game modes in order to look up // their information, but it is the only way (at least that I know of). diff --git a/code/global.dm b/code/global.dm index 626960698b1..f701cfef194 100644 --- a/code/global.dm +++ b/code/global.dm @@ -195,16 +195,6 @@ var/sqllogin = "root" var/sqlpass = "" var/sqllogging = 0 // Should we log deaths, population stats, etc.? -// Forum MySQL configuration. (for use with forum account/key authentication) -// These are all default values that will load should the forumdbconfig.txt file fail to read for whatever reason. -var/forumsqladdress = "localhost" -var/forumsqlport = "3306" -var/forumsqldb = "tgstation" -var/forumsqllogin = "root" -var/forumsqlpass = "" -var/forum_activated_group = "2" -var/forum_authenticated_group = "10" - // For FTP requests. (i.e. downloading runtime logs.) // However it'd be ok to use for accessing attack logs and such too, which are even laggier. var/fileaccess_timer = 0 diff --git a/code/world.dm b/code/world.dm index 88dea018a5f..afdaa5bfa6b 100644 --- a/code/world.dm +++ b/code/world.dm @@ -535,7 +535,6 @@ var/world_topic_spam_protect_time = world.timeofday config.load("config/config.txt") config.load("config/game_options.txt","game_options") config.loadsql("config/dbconfig.txt") - config.loadforumsql("config/forumdbconfig.txt") /hook/startup/proc/loadMods() world.load_mods() diff --git a/config/example/forumdbconfig.txt b/config/example/forumdbconfig.txt deleted file mode 100644 index 61a2a2d6ecd..00000000000 --- a/config/example/forumdbconfig.txt +++ /dev/null @@ -1,19 +0,0 @@ -# This configuration file is for the forum database, if you need to set up -# population, death, etc. tracking see 'dbconfig.txt' -# The login credentials for this will likely differ from those in dbconfig.txt! - -# Server the MySQL database can be found at -# Examples: localhost, 200.135.5.43, www.mysqldb.com, etc. -ADDRESS localhost - -# MySQL server port (default is 3306) -PORT 3306 - -# Database the forum data may be found in -DATABASE tgstation13 - -# Username/Login used to access the database -LOGIN mylogin - -# Password used to access the database -PASSWORD mypassword \ No newline at end of file From d46499a310962389aa594df91827fcc54effb91f Mon Sep 17 00:00:00 2001 From: skull132 Date: Thu, 3 Mar 2016 06:55:18 +0200 Subject: [PATCH 05/31] DBConnection object modifications Renames the variables of the DBConnection object to make differentiating them easier. Reworks the `DBConnection/New()` and `Connect()` methods to allow for the automatic creation of the dbi handler string. Adds a con_database variable to DBConnection to enable this. DBConnection objects now also house the current database they're using for this purpose. Moves the constructor for dbcon under `/hook/startup/proc/connectDB()`, as it needs to be called after the SQL config has been read by `datum/global_init/New()` --- code/defines/procs/dbcore.dm | 56 +++++++++++++++++++----------------- code/global.dm | 3 +- code/world.dm | 11 +++---- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/code/defines/procs/dbcore.dm b/code/defines/procs/dbcore.dm index cd5f5dcdbd9..c1915051633 100644 --- a/code/defines/procs/dbcore.dm +++ b/code/defines/procs/dbcore.dm @@ -31,39 +31,40 @@ #define BLOB 14 // TODO: Investigate more recent type additions and see if I can handle them. - Nadrew - -// Deprecated! See global.dm for new configuration vars -/* -var/DB_SERVER = "" // This is the location of your MySQL server (localhost is USUALLY fine) -var/DB_PORT = 3306 // This is the port your MySQL server is running on (3306 is the default) -*/ - DBConnection var/_db_con // This variable contains a reference to the actual database connection. - var/dbi // This variable is a string containing the DBI MySQL requires. - var/user // This variable contains the username data. - var/password // This variable contains the password data. - var/default_cursor // This contains the default database cursor data. - // - var/server = "" - var/port = 3306 + var/con_dbi // This variable is a string containing the DBI MySQL requires. + var/con_user // This variable contains the username data. + var/con_password // This variable contains the password data. + var/con_cursor // This contains the default database cursor data. + var/con_server = "" + var/con_port = 3306 + var/con_database = "" + +DBConnection/New(server, port = 3306, database, username, password_handler, cursor_handler = Default_Cursor, dbi_handler) + con_user = username + con_password = password_handler + con_cursor = cursor_handler + con_server = server + con_port = port + con_database = database + + if (dbi_handler) + con_dbi = dbi_handler + else + con_dbi = "dbi:mysql:[database]:[server]:[port]" -DBConnection/New(dbi_handler, username, password_handler, cursor_handler) - dbi = dbi_handler - user = username - password = password_handler - default_cursor = cursor_handler _db_con = _dm_db_new_con() -DBConnection/proc/Connect(dbi_handler = dbi, user_handler = user, password_handler = password, cursor_handler) +DBConnection/proc/Connect(dbi_handler = con_dbi, user_handler = con_user, password_handler = con_password, cursor_handler) if (!sqllogging) return 0 if (!src) return 0 - cursor_handler = default_cursor + cursor_handler = con_cursor if (!cursor_handler) cursor_handler = Default_Cursor - return _dm_db_connect(_db_con,dbi_handler, user_handler, password_handler, cursor_handler, null) + return _dm_db_connect(_db_con, dbi_handler, user_handler, password_handler, cursor_handler, null) DBConnection/proc/Disconnect() return _dm_db_close(_db_con) @@ -80,12 +81,13 @@ DBConnection/proc/Quote(str) DBConnection/proc/ErrorMsg() return _dm_db_error_msg(_db_con) -DBConnection/proc/SelectDB(database_name,dbi) - if(IsConnected()) Disconnect() - //return Connect("[dbi?"[dbi]":"dbi:mysql:[database_name]:[DB_SERVER]:[DB_PORT]"]",user,password) - return Connect("[dbi?"[dbi]":"dbi:mysql:[database_name]:[sqladdress]:[sqlport]"]", user, password) +DBConnection/proc/SelectDB(database_name, new_dbi) + if (IsConnected()) + Disconnect() + con_database = database_name + return Connect(new_dbi ? new_dbi : "dbi:mysql:[database_name]:[con_server]:[con_port]", con_user, con_password) -DBConnection/proc/NewQuery(sql_query, cursor_handler = default_cursor) +DBConnection/proc/NewQuery(sql_query, cursor_handler = con_cursor) return new/DBQuery(sql_query, src, cursor_handler) DBQuery diff --git a/code/global.dm b/code/global.dm index f701cfef194..ed69df69f45 100644 --- a/code/global.dm +++ b/code/global.dm @@ -202,7 +202,8 @@ var/custom_event_msg = null // Database connections. A connection is established on world creation. // Ideally, the connection dies when the server restarts (After feedback logging.). -var/DBConnection/dbcon = new() // Feedback database (New database) +// Feedback database. Constructor in /hook/startup/proc/connectDB() +var/DBConnection/dbcon // Reference list for disposal sort junctions. Filled up by sorting junction's New() /var/list/tagger_locations = list() diff --git a/code/world.dm b/code/world.dm index afdaa5bfa6b..f0315fde9c0 100644 --- a/code/world.dm +++ b/code/world.dm @@ -646,6 +646,9 @@ var/failed_db_connections = 0 var/failed_old_db_connections = 0 /hook/startup/proc/connectDB() + //Construct the database object now that configs are loaded + dbcon = new(sqladdress, sqlport, sqldb, sqllogin, sqlpass) + if(!setup_database_connection()) world.log << "Your server failed to establish a connection with the feedback database." else @@ -660,13 +663,7 @@ proc/setup_database_connection() if(!dbcon) dbcon = new() - var/user = sqllogin - var/pass = sqlpass - var/db = sqldb - var/address = sqladdress - var/port = sqlport - - dbcon.Connect("dbi:mysql:[db]:[address]:[port]","[user]","[pass]") + dbcon.Connect() . = dbcon.IsConnected() if ( . ) failed_db_connections = 0 //If this connection succeeded, reset the failed connections counter. From 8383f1c03b2f15d5ed71b6be49c8de915ac1f7c3 Mon Sep 17 00:00:00 2001 From: skull132 Date: Thu, 3 Mar 2016 07:04:49 +0200 Subject: [PATCH 06/31] Generalizing establish_db_connection() and setup_database_connection() Both procs are now generalized, and accept a DBConnection object as an argument. Due to this generalization, all instances of `establish_db_connection()` must be renamed to `establish_db_connection(dbcon)`. Also added variable `failed_connections` to the definition of DBConnection. --- code/controllers/news_controller.dm | 4 +-- code/defines/procs/dbcore.dm | 1 + code/defines/procs/statistics.dm | 8 ++--- code/game/jobs/whitelist.dm | 4 +-- code/game/machinery/requests_console.dm | 6 ++-- code/modules/admin/DB ban/ban_mirroring.dm | 2 +- code/modules/admin/DB ban/functions.dm | 8 ++--- code/modules/admin/IsBanned.dm | 2 +- code/modules/admin/admin_ranks.dm | 2 +- code/modules/admin/banjob.dm | 2 +- .../admin/permissionverbs/permissionedit.dm | 4 +-- code/modules/admin/player_notes_sql.dm | 10 +++--- .../admin/verbs/check_customitem_activity.dm | 2 +- code/modules/admin/verbs/warning.dm | 12 +++---- code/modules/client/client procs.dm | 4 +-- code/modules/library/lib_machines.dm | 8 ++--- code/modules/mob/new_player/new_player.dm | 4 +-- code/modules/mob/new_player/poll.dm | 12 +++---- code/modules/research/message_server.dm | 2 +- code/world.dm | 32 ++++++++++--------- 20 files changed, 66 insertions(+), 63 deletions(-) diff --git a/code/controllers/news_controller.dm b/code/controllers/news_controller.dm index 1598fc8a226..f8d9ce3c808 100644 --- a/code/controllers/news_controller.dm +++ b/code/controllers/news_controller.dm @@ -27,7 +27,7 @@ var/global/datum/news_controller/news_controller //Stores a new article for publishing. /datum/news_controller/proc/update() - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) error("SQL database connection failed. News_controller failed to retreive information.") fails++ @@ -52,7 +52,7 @@ var/global/datum/news_controller/news_controller //Publish the stored article. /datum/news_controller/proc/publish() - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) error("SQL database connection failed. News_controller failed to retreive information.") fails++ diff --git a/code/defines/procs/dbcore.dm b/code/defines/procs/dbcore.dm index c1915051633..88335bd0aa4 100644 --- a/code/defines/procs/dbcore.dm +++ b/code/defines/procs/dbcore.dm @@ -40,6 +40,7 @@ DBConnection var/con_server = "" var/con_port = 3306 var/con_database = "" + var/failed_connections = 0 DBConnection/New(server, port = 3306, database, username, password_handler, cursor_handler = Default_Cursor, dbi_handler) con_user = username diff --git a/code/defines/procs/statistics.dm b/code/defines/procs/statistics.dm index 01c97f4fcfc..8eaf7a90a27 100644 --- a/code/defines/procs/statistics.dm +++ b/code/defines/procs/statistics.dm @@ -6,7 +6,7 @@ proc/sql_poll_population() for(var/mob/M in player_list) if(M.client) playercount += 1 - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) log_game("SQL ERROR during population polling. Failed to connect.") else @@ -49,7 +49,7 @@ proc/sql_report_death(var/mob/living/carbon/human/H) var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") var/coord = "[H.x], [H.y], [H.z]" //world << "INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.bruteloss], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()])" - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) log_game("SQL ERROR during death reporting. Failed to connect.") else @@ -83,7 +83,7 @@ proc/sql_report_cyborg_death(var/mob/living/silicon/robot/H) var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") var/coord = "[H.x], [H.y], [H.z]" //world << "INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.bruteloss], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()])" - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) log_game("SQL ERROR during death reporting. Failed to connect.") else @@ -113,7 +113,7 @@ proc/sql_commit_feedback() log_game("Round ended without any feedback being generated. No feedback was sent to the database.") return - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) log_game("SQL ERROR during feedback reporting. Failed to connect.") else diff --git a/code/game/jobs/whitelist.dm b/code/game/jobs/whitelist.dm index b6f16388be7..28b216654d3 100644 --- a/code/game/jobs/whitelist.dm +++ b/code/game/jobs/whitelist.dm @@ -9,7 +9,7 @@ var/list/whitelist = list() /proc/load_whitelist() if (config.sql_whitelists) - establish_db_connection() + establish_db_connection(dbcon) if (!dbcon.IsConnected()) //Continue with the old code if we have no database. @@ -43,7 +43,7 @@ var/list/whitelist = list() /proc/load_alienwhitelist() if (config.sql_whitelists) - establish_db_connection() + establish_db_connection(dbcon) if (!dbcon.IsConnected()) //Continue with the old code if we have no database. diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index 7f24da000a9..7fc553fdf81 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -211,7 +211,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() if(11) //form database dat += text("NanoTrasen Corporate Forms

") - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) dat += text("ERROR: Unable to contact external database. Please contact your system administrator for assistance.") log_game("SQL database connection failed. Attempted to fetch form information.") @@ -377,7 +377,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() if(href_list["print"]) var/printid = sanitizeSQL(href_list["print"]) - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) alert("Connection to the database lost. Aborting.") @@ -405,7 +405,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() if(href_list["whatis"]) var/whatisid = sanitizeSQL(href_list["whatis"]) - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) alert("Connection to the database lost. Aborting.") if(!whatisid) diff --git a/code/modules/admin/DB ban/ban_mirroring.dm b/code/modules/admin/DB ban/ban_mirroring.dm index 588acbdfccb..d6af7bafbba 100644 --- a/code/modules/admin/DB ban/ban_mirroring.dm +++ b/code/modules/admin/DB ban/ban_mirroring.dm @@ -6,7 +6,7 @@ if (!ckey || !address || !computer_id || !ban_id) return - establish_db_connection() + establish_db_connection(dbcon) if (!dbcon.IsConnected()) error("Ban database connection failure while attempting to mirror. Key passed for mirror handling: [ckey].") diff --git a/code/modules/admin/DB ban/functions.dm b/code/modules/admin/DB ban/functions.dm index e36fc4ff21f..d266eaf7295 100644 --- a/code/modules/admin/DB ban/functions.dm +++ b/code/modules/admin/DB ban/functions.dm @@ -4,7 +4,7 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = if(!check_rights(R_MOD,0) && !check_rights(R_BAN)) return - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) return @@ -122,7 +122,7 @@ datum/admins/proc/DB_ban_unban(var/ckey, var/bantype, var/job = "") if(job) sql += " AND job = '[job]'" - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) return @@ -217,7 +217,7 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) var/sql = "SELECT ckey FROM ss13_ban WHERE id = [id]" - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) return @@ -269,7 +269,7 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) if(!check_rights(R_BAN)) return - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) usr << "\red Failed to establish database connection" return diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index da4f2af534b..37eb7cc691b 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -34,7 +34,7 @@ world/IsBanned(key,address,computer_id) var/ckeytext = ckey(key) - if(!establish_db_connection()) + if(!establish_db_connection(dbcon)) error("Ban database connection failure. Key [ckeytext] not checked") log_misc("Ban database connection failure. Key [ckeytext] not checked") return diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm index 27eb8b6d3f3..3049976dfad 100644 --- a/code/modules/admin/admin_ranks.dm +++ b/code/modules/admin/admin_ranks.dm @@ -102,7 +102,7 @@ var/list/admin_ranks = list() //list of all ranks with associated rights else //The current admin system uses SQL - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) error("Failed to connect to database in load_admins(). Reverting to legacy system.") log_misc("Failed to connect to database in load_admins(). Reverting to legacy system.") diff --git a/code/modules/admin/banjob.dm b/code/modules/admin/banjob.dm index ae04799354c..96899fc6d9c 100644 --- a/code/modules/admin/banjob.dm +++ b/code/modules/admin/banjob.dm @@ -65,7 +65,7 @@ DEBUG jobban_keylist=list() log_admin("jobban_keylist was empty") else - if(!establish_db_connection()) + if(!establish_db_connection(dbcon)) error("Database connection failed. Reverting to the legacy ban system.") log_misc("Database connection failed. Reverting to the legacy ban system.") config.ban_legacy_system = 1 diff --git a/code/modules/admin/permissionverbs/permissionedit.dm b/code/modules/admin/permissionverbs/permissionedit.dm index 0969fa35d88..1af56750311 100644 --- a/code/modules/admin/permissionverbs/permissionedit.dm +++ b/code/modules/admin/permissionverbs/permissionedit.dm @@ -54,7 +54,7 @@ usr << "\red You do not have permission to do this!" return - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) usr << "\red Failed to establish database connection" @@ -104,7 +104,7 @@ usr << "\red You do not have permission to do this!" return - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) usr << "\red Failed to establish database connection" return diff --git a/code/modules/admin/player_notes_sql.dm b/code/modules/admin/player_notes_sql.dm index 1d447110771..cfd42df4b7c 100644 --- a/code/modules/admin/player_notes_sql.dm +++ b/code/modules/admin/player_notes_sql.dm @@ -12,7 +12,7 @@ else query_details[":a_ckey"] = user.ckey - establish_db_connection() + establish_db_connection(dbcon) if (!dbcon.IsConnected()) alert("SQL connection failed while trying to add a note!") return @@ -36,7 +36,7 @@ if (!note_id || !note_edit) return - establish_db_connection() + establish_db_connection(dbcon) if (!dbcon.IsConnected()) error("SQL connection failed while attempting to delete a note!") return @@ -93,7 +93,7 @@ player_ckey = ckey(player_ckey) admin_ckey = ckey(admin_ckey) - establish_db_connection() + establish_db_connection(dbcon) if (!dbcon.IsConnected()) error("SQL connection failed while attempting to view a player's notes!") return @@ -187,7 +187,7 @@ if (!ckey) return "No ckey given!" - establish_db_connection() + establish_db_connection(dbcon) if (!dbcon.IsConnected()) return "Unable to establish database connection! Aborting!" @@ -231,7 +231,7 @@ note_list >> note_keys msg_scopes("Establishing DB connection!") - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) msg_scopes("No DB connection!") return diff --git a/code/modules/admin/verbs/check_customitem_activity.dm b/code/modules/admin/verbs/check_customitem_activity.dm index 8d701e26734..e9bbaded60b 100644 --- a/code/modules/admin/verbs/check_customitem_activity.dm +++ b/code/modules/admin/verbs/check_customitem_activity.dm @@ -29,7 +29,7 @@ var/inactive_keys = "None
" if(checked_for_inactives) return - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) return diff --git a/code/modules/admin/verbs/warning.dm b/code/modules/admin/verbs/warning.dm index b19454d04de..3ad7a81bfff 100644 --- a/code/modules/admin/verbs/warning.dm +++ b/code/modules/admin/verbs/warning.dm @@ -9,7 +9,7 @@ if (!warned_ckey || !istext(warned_ckey)) return - establish_db_connection() + establish_db_connection(dbcon) if (!dbcon.IsConnected()) usr << "Error: warn(): Database Connection failed, reverting to legacy systems." usr.client.warn_legacy(warned_ckey) @@ -110,7 +110,7 @@ var/dcolor = "#ffaaaa" //dark colour, severity = 1 var/ecolor = "#e3e3e3" //gray colour, expired = 1 - establish_db_connection() + establish_db_connection(dbcon) if (!dbcon.IsConnected()) alert("Connection to the SQL database lost. Aborting. Please alert an Administrator or a member of staff.") return @@ -172,7 +172,7 @@ if (!warning_id) return - establish_db_connection() + establish_db_connection(dbcon) if (!dbcon.IsConnected()) alert("Connection to SQL database failed while attempting to update your warning's status!") return @@ -191,7 +191,7 @@ var/count = 0 var/count_expire = 0 - establish_db_connection() + establish_db_connection(dbcon) if (!dbcon.IsConnected()) return @@ -239,7 +239,7 @@ var/dcolor = "#ffdddd" //dark colour, severity = 1 var/ecolor = "#e3e3e3" //gray colour, expired = 1 - establish_db_connection() + establish_db_connection(dbcon) if (!dbcon.IsConnected()) alert("Connection to the SQL database lost. Aborting. Please alert the database admin!") return @@ -342,7 +342,7 @@ if(!warning_id || !warning_edit) return - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) alert("Connection to the SQL database lost. Aborting. Please alert the database admin!") return diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 09127b10095..672c15387fe 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -203,7 +203,7 @@ // 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() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) return null @@ -223,7 +223,7 @@ if ( IsGuestKey(src.key) ) return - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) return diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index fd86f484ac9..7bbdaed4749 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -43,7 +43,7 @@ datum/borrowbook // Datum used to keep track of who has borrowed what when and f Filter by Author: [author]
\[Start Search\]
"} if(1) - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) dat += "ERROR: Unable to contact External Archive. Please contact your system administrator for assistance.
" else if(!SQLquery) @@ -189,7 +189,7 @@ datum/borrowbook // Datum used to keep track of who has borrowed what when and f (Return to main menu)
"} if(4) dat += "

External Archive

" - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) dat += "ERROR: Unable to contact External Archive. Please contact your system administrator for assistance." else @@ -332,7 +332,7 @@ datum/borrowbook // Datum used to keep track of who has borrowed what when and f if(scanner.cache.unique) alert("This book has been rejected from the database. Aborting!") else - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) alert("Connection to Archive has been severed. Aborting.") else @@ -355,7 +355,7 @@ datum/borrowbook // Datum used to keep track of who has borrowed what when and f if(href_list["targetid"]) var/sqlid = sanitizeSQL(href_list["targetid"]) - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) alert("Connection to Archive has been severed. Aborting.") if(bibledelay) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index c5716172a08..ca7d753590c 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -41,7 +41,7 @@ output += "

Observe

" if(!IsGuestKey(src.key)) - establish_db_connection() + establish_db_connection(dbcon) if(dbcon.IsConnected()) var/isadmin = 0 @@ -181,7 +181,7 @@ return if(href_list["privacy_poll"]) - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) return var/voted = 0 diff --git a/code/modules/mob/new_player/poll.dm b/code/modules/mob/new_player/poll.dm index 953119961e0..6051d178b4b 100644 --- a/code/modules/mob/new_player/poll.dm +++ b/code/modules/mob/new_player/poll.dm @@ -1,6 +1,6 @@ /mob/new_player/proc/handle_privacy_poll() - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) return var/voted = 0 @@ -47,7 +47,7 @@ var/optiontext /mob/new_player/proc/handle_player_polling() - establish_db_connection() + establish_db_connection(dbcon) if(dbcon.IsConnected()) var/isadmin = 0 if(src.client && src.client.holder) @@ -81,7 +81,7 @@ /mob/new_player/proc/poll_player(var/pollid = -1) if(pollid == -1) return - establish_db_connection() + establish_db_connection(dbcon) if(dbcon.IsConnected()) var/DBQuery/select_query = dbcon.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM ss13_poll_question WHERE id = [pollid]") @@ -342,7 +342,7 @@ if(!isnum(pollid) || !isnum(optionid)) return - establish_db_connection() + establish_db_connection(dbcon) if(dbcon.IsConnected()) var/DBQuery/select_query = dbcon.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM ss13_poll_question WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime") @@ -412,7 +412,7 @@ if(!isnum(pollid) || !istext(replytext)) return - establish_db_connection() + establish_db_connection(dbcon) if(dbcon.IsConnected()) var/DBQuery/select_query = dbcon.NewQuery("SELECT starttime, endtime, question, polltype FROM ss13_poll_question WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime") @@ -470,7 +470,7 @@ if(!isnum(pollid) || !isnum(optionid)) return - establish_db_connection() + establish_db_connection(dbcon) if(dbcon.IsConnected()) var/DBQuery/select_query = dbcon.NewQuery("SELECT starttime, endtime, question, polltype FROM ss13_poll_question WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime") diff --git a/code/modules/research/message_server.dm b/code/modules/research/message_server.dm index 9655f3b3dcd..9144cd11d98 100644 --- a/code/modules/research/message_server.dm +++ b/code/modules/research/message_server.dm @@ -297,7 +297,7 @@ var/obj/machinery/blackbox_recorder/blackbox if(!feedback) return round_end_data_gathering() //round_end time logging and some other data processing - establish_db_connection() + establish_db_connection(dbcon) if(!dbcon.IsConnected()) return var/round_id diff --git a/code/world.dm b/code/world.dm index f0315fde9c0..bc23a3a54ea 100644 --- a/code/world.dm +++ b/code/world.dm @@ -649,37 +649,39 @@ var/failed_old_db_connections = 0 //Construct the database object now that configs are loaded dbcon = new(sqladdress, sqlport, sqldb, sqllogin, sqlpass) - if(!setup_database_connection()) + if (!setup_database_connection(dbcon)) world.log << "Your server failed to establish a connection with the feedback database." else world.log << "Feedback database connection established." return 1 -proc/setup_database_connection() - - if(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. +/proc/setup_database_connection(var/DBConnection/con) + if (!con) return 0 - if(!dbcon) - dbcon = new() + if (con.failed_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 - dbcon.Connect() - . = dbcon.IsConnected() + con.Connect() + . = con.IsConnected() if ( . ) - failed_db_connections = 0 //If this connection succeeded, reset the failed connections counter. + con.failed_connections = 0 //If this connection succeeded, reset the failed connections counter. else - failed_db_connections++ //If it failed, increase the failed connections counter. - world.log << dbcon.ErrorMsg() + con.failed_connections++ //If it failed, increase the failed connections counter. + world.log << con.ErrorMsg() return . //This proc ensures that the connection to the feedback database (global variable dbcon) is established -proc/establish_db_connection() - if(failed_db_connections > FAILED_DB_CONNECTION_CUTOFF) +/proc/establish_db_connection(var/DBConnection/con) + if (!con) return 0 - if(!dbcon || !dbcon.IsConnected()) - return setup_database_connection() + if (con.failed_connections > FAILED_DB_CONNECTION_CUTOFF) + return 0 + + if (!con.IsConnected()) + return setup_database_connection(con) else return 1 From 202b21609245db3ba2d697c793543ca79b3d1509 Mon Sep 17 00:00:00 2001 From: skull132 Date: Fri, 4 Mar 2016 01:37:41 +0200 Subject: [PATCH 07/31] More reworking of DB handling sqllogging depracted in favour of config.sql_enabled. Database loading is done through /hook/startup/proc/load_databases, with initialize_database_object() being a generalized proc to read any generic database config file. (TODO: config examples in relaiton to last remark.) --- code/controllers/configuration.dm | 42 +------------------------- code/defines/procs/dbcore.dm | 4 +-- code/defines/procs/statistics.dm | 12 ++++---- code/global.dm | 11 +------ code/world.dm | 50 +++++++++++++++++++++++++++---- 5 files changed, 54 insertions(+), 65 deletions(-) diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index c7e24f54627..f347605febe 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -277,7 +277,7 @@ var/list/gamemode_cache = list() config.log_access = 1 if ("sql_enabled") - config.sql_enabled = text2num(value) + config.sql_enabled = 1 if ("log_say") config.log_say = 1 @@ -737,46 +737,6 @@ var/list/gamemode_cache = list() else log_misc("Unknown setting in configuration: '[name]'") -/datum/configuration/proc/loadsql(filename) // -- TLE - var/list/Lines = file2list(filename) - for(var/t in Lines) - if(!t) continue - - t = trim(t) - if (length(t) == 0) - continue - else if (copytext(t, 1, 2) == "#") - continue - - var/pos = findtext(t, " ") - var/name = null - var/value = null - - if (pos) - name = lowertext(copytext(t, 1, pos)) - value = copytext(t, pos + 1) - else - name = lowertext(t) - - if (!name) - continue - - switch (name) - if ("address") - sqladdress = value - if ("port") - sqlport = value - if ("database") - sqldb = value - if ("login") - sqllogin = value - if ("password") - sqlpass = value - if ("enable_stat_tracking") - sqllogging = 1 - else - log_misc("Unknown setting in configuration: '[name]'") - /datum/configuration/proc/pick_mode(mode_name) // I wish I didn't have to instance the game modes in order to look up // their information, but it is the only way (at least that I know of). diff --git a/code/defines/procs/dbcore.dm b/code/defines/procs/dbcore.dm index 88335bd0aa4..67dc76a8e24 100644 --- a/code/defines/procs/dbcore.dm +++ b/code/defines/procs/dbcore.dm @@ -58,7 +58,7 @@ DBConnection/New(server, port = 3306, database, username, password_handler, curs _db_con = _dm_db_new_con() DBConnection/proc/Connect(dbi_handler = con_dbi, user_handler = con_user, password_handler = con_password, cursor_handler) - if (!sqllogging) + if (!config.sql_enabled) return 0 if (!src) return 0 @@ -71,7 +71,7 @@ DBConnection/proc/Disconnect() return _dm_db_close(_db_con) DBConnection/proc/IsConnected() - if(!sqllogging) + if(!config.sql_enabled) return 0 var/success = _dm_db_is_connected(_db_con) return success diff --git a/code/defines/procs/statistics.dm b/code/defines/procs/statistics.dm index 8eaf7a90a27..e807e4cbbce 100644 --- a/code/defines/procs/statistics.dm +++ b/code/defines/procs/statistics.dm @@ -1,5 +1,5 @@ proc/sql_poll_population() - if(!sqllogging) + if(!config.sql_enabled) return var/admincount = admins.len var/playercount = 0 @@ -18,15 +18,15 @@ proc/sql_poll_population() proc/sql_report_round_start() // TODO - if(!sqllogging) + if(!config.sql_enabled) return proc/sql_report_round_end() // TODO - if(!sqllogging) + if(!config.sql_enabled) return proc/sql_report_death(var/mob/living/carbon/human/H) - if(!sqllogging) + if(!config.sql_enabled) return if(!H) return @@ -60,7 +60,7 @@ proc/sql_report_death(var/mob/living/carbon/human/H) proc/sql_report_cyborg_death(var/mob/living/silicon/robot/H) - if(!sqllogging) + if(!config.sql_enabled) return if(!H) return @@ -94,7 +94,7 @@ proc/sql_report_cyborg_death(var/mob/living/silicon/robot/H) proc/statistic_cycle() - if(!sqllogging) + if(!config.sql_enabled) return while(1) sql_poll_population() diff --git a/code/global.dm b/code/global.dm index ed69df69f45..ccb57713b0e 100644 --- a/code/global.dm +++ b/code/global.dm @@ -187,22 +187,13 @@ var/datum/subsystem/alarm/alarm_manager = new() // Alarm Manager, the manager fo var/list/awaydestinations = list() // Away missions. A list of landmarks that the warpgate can take you to. -// MySQL configuration -var/sqladdress = "localhost" -var/sqlport = "3306" -var/sqldb = "tgstation" -var/sqllogin = "root" -var/sqlpass = "" -var/sqllogging = 0 // Should we log deaths, population stats, etc.? - // For FTP requests. (i.e. downloading runtime logs.) // However it'd be ok to use for accessing attack logs and such too, which are even laggier. var/fileaccess_timer = 0 var/custom_event_msg = null -// Database connections. A connection is established on world creation. +// Database connections. A connection is established along with /hook/startup/proc/load_databases(). // Ideally, the connection dies when the server restarts (After feedback logging.). -// Feedback database. Constructor in /hook/startup/proc/connectDB() var/DBConnection/dbcon // Reference list for disposal sort junctions. Filled up by sorting junction's New() diff --git a/code/world.dm b/code/world.dm index bc23a3a54ea..6148324b93b 100644 --- a/code/world.dm +++ b/code/world.dm @@ -534,7 +534,6 @@ var/world_topic_spam_protect_time = world.timeofday config = new /datum/configuration() config.load("config/config.txt") config.load("config/game_options.txt","game_options") - config.loadsql("config/dbconfig.txt") /hook/startup/proc/loadMods() world.load_mods() @@ -642,12 +641,10 @@ var/world_topic_spam_protect_time = world.timeofday src.status = s #define FAILED_DB_CONNECTION_CUTOFF 5 -var/failed_db_connections = 0 -var/failed_old_db_connections = 0 -/hook/startup/proc/connectDB() - //Construct the database object now that configs are loaded - dbcon = new(sqladdress, sqlport, sqldb, sqllogin, sqlpass) +/hook/startup/proc/load_databases() + //Construct the database object from an init file. + dbcon = initialize_database_object("config/dbconfig.txt") if (!setup_database_connection(dbcon)) world.log << "Your server failed to establish a connection with the feedback database." @@ -655,8 +652,48 @@ var/failed_old_db_connections = 0 world.log << "Feedback database connection established." return 1 +/proc/initialize_database_object(var/filename) + if (!filename) + return 0 + + var/list/data = list("address", "port", "database", "login", "password") + + var/list/Lines = file2list(filename) + for (var/t in Lines) + if (!t) + continue + + t = trim(t) + if (length(t) == 0) + continue + else if (copytext(t, 1, 2) == "#") + continue + + var/pos = findtext(t, " ") + var/name = null + var/value = null + + name = lowertext(copytext(t, 1, pos)) + value = copytext(t, pos + 1) + + if (!name) + continue + + if (name in data) + data[name] = value + else + log_misc("Unknown setting while setting up database connection. Filename: '[filename]', value: '[value]'.") + + //Validate the data before proceeding. + for (var/d in data) + if (!data[d] || data[d] == null) + return 0 + + return new/DBConnection(data["address"], data["port"], data["database"], data["login"], data["password"]) + /proc/setup_database_connection(var/DBConnection/con) if (!con) + error("No DBConnection object passed to setup_database_connection().") return 0 if (con.failed_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. @@ -675,6 +712,7 @@ var/failed_old_db_connections = 0 //This proc ensures that the connection to the feedback database (global variable dbcon) is established /proc/establish_db_connection(var/DBConnection/con) if (!con) + error("No DBConnection object passed to establish_db_connection() proc.") return 0 if (con.failed_connections > FAILED_DB_CONNECTION_CUTOFF) From 8c30b617e3f55ffe910c83f701b934caf42746da Mon Sep 17 00:00:00 2001 From: skull132 Date: Sat, 5 Mar 2016 00:53:36 +0200 Subject: [PATCH 08/31] Webinterface Config Settings Configuration settings for using the webinterface in future updates. --- code/controllers/configuration.dm | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index f347605febe..94d55548fbc 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -208,6 +208,10 @@ var/list/gamemode_cache = list() var/aggressive_changelog = 0 + //Webinterface settings + var/webinterface_enabled = 0 + var/webinterface_url = "" + /datum/configuration/New() var/list/L = typesof(/datum/game_mode) - /datum/game_mode for (var/T in L) @@ -674,6 +678,12 @@ var/list/gamemode_cache = list() if("show_auxiliary_roles") config.show_auxiliary_roles = 1 + if("use_webinterface") + config.webinterface_enabled = 1 + + if("webinterface_url") + config.webinterface_url = 1 + else log_misc("Unknown setting in configuration: '[name]'") From ce5d2009a2040cca61656e9bcf812d8c4a5389b1 Mon Sep 17 00:00:00 2001 From: skull132 Date: Sat, 5 Mar 2016 00:54:16 +0200 Subject: [PATCH 09/31] User Linking With Webinterface Enables the user to link their account to a forum account, for use later. --- code/modules/client/client procs.dm | 98 ++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 672c15387fe..5bcafd01bb9 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -74,7 +74,63 @@ if(href_list["warnview"]) warnings_check() - ..() //redirect to hsrc.Topic() + if(href_list["linkingrequest"]) + if (!config.webinterface_enabled) + return + + if (!href_list["linkingaction"]) + return + + var/request_id = text2num(href_list["linkingrequest"]) + + establish_db_connection(dbcon) + if (!dbcon.IsConnected()) + usr << "\red Action failed! Database link could not be established!" + return + + + var/DBQuery/check_query = dbcon.NewQuery("SELECT player_ckey, status FROM ss13_player_linking WHERE id = :id") + check_query.Execute(list(":id" = request_id)) + + if (!check_query.NextRow()) + usr << "\red No request found!" + return + + if (ckey(check_query.item[1]) != ckey || check_query.item[2] != "new") + usr << "\red Request authentication failed!" + return + + var/query_contents = "" + var/list/query_details[] + var/feedback_message = "" + switch (href_list["linkingaction"]) + if ("accept") + query_contents = "UPDATE ss13_player_linking SET status = :new_status, updated_at = NOW() WHERE id = :id" + query_details[":new_status"] = "confirmed" + query_details[":id"] = request_id + + feedback_message = "Account successfully linked!" + if ("deny") + query_contents = "UPDATE ss13_player_linking SET status = :new_status, deleted_at = NOW() WHERE id = :id" + query_details[":new_status"] = "rejected" + query_details[":id"] = request_id + + feedback_message = "Link request rejected!" + else + usr << "\red Invalid command sent." + return + + var/DBQuery/update_query = dbcon.NewQuery(query_contents) + update_query.Execute(query_details) + + if (href_list["linkingaction"] == "accept" && config.webinterface_url) + if(alert("To complete the process, you have to visit the website. Do you ",,"Yes","No") == "Yes") + usr << link("[config.webinterface_url]user/link") + + usr << feedback_message + return + + ..() //redirect to hsrc.() /client/proc/handle_spam_prevention(var/message, var/mute_type) if(config.automute_on && !holder && src.last_message == message) @@ -175,6 +231,8 @@ log_client_to_db() + check_linking_requests() + send_resources() nanomanager.send_resources(src) @@ -288,6 +346,44 @@ #undef UPLOAD_LIMIT #undef MIN_CLIENT_VERSION +/client/proc/check_linking_requests() + if (!config.webinterface_enabled || !config.sql_enabled) + return + + establish_db_connection(dbcon) + if (!dbcon.IsConnected()) + return + + var/list/requests = list() + var/list/query_details = list(":ckey" = ckey) + + var/DBQuery/select_query = dbcon.NewQuery("SELECT id, forum_id, forum_username, datediff(Now(), created_at) as request_age FROM ss13_player_linking WHERE status = 'new' AND player_ckey = :ckey AND deleted_at IS NULL") + select_query.Execute(query_details) + + while (select_query.NextRow()) + requests.Add(list(list("id" = text2num(select_query.item[1]), "forum_id" = text2num(select_query.item[2]), "forum_username" = select_query.item[3], "request_age" = select_query.item[4]))) + + if (!requests.len) + return + + var/dat = "
You have active requests to check!
" + var/i = 0 + for (var/list/request in requests) + var/linked_forum_name = null + if (config.forumurl) + linked_forum_name = "[request["forum_username"]]" + + dat += "
" + dat += "#[i] - Request to link [key] to a forum account with the username of: [linked_forum_name ? linked_forum_name : request["forum_username"]].
" + dat += "The request is [request["request_age"]] days old.
" + dat += "OPTIONS: Accept Request | Deny Request" + + i++ + + usr << browse(dat, "window=LinkingRequests") + return + + //checks if a client is afk //3000 frames = 5 minutes /client/proc/is_afk(duration=3000) From 62f3eae9fd4516d1a73687afa1c49a66182f7255 Mon Sep 17 00:00:00 2001 From: skull132 Date: Sat, 5 Mar 2016 01:36:11 +0200 Subject: [PATCH 10/31] Fix linkingaction Fixes the data it sends via the request. --- code/modules/client/client procs.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 5bcafd01bb9..9e567160b61 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -376,7 +376,7 @@ dat += "
" dat += "#[i] - Request to link [key] to a forum account with the username of: [linked_forum_name ? linked_forum_name : request["forum_username"]].
" dat += "The request is [request["request_age"]] days old.
" - dat += "OPTIONS: Accept Request | Deny Request" + dat += "OPTIONS: Accept Request | Deny Request" i++ From e64f0de1551a69e301357d2a550943926fab67f0 Mon Sep 17 00:00:00 2001 From: skull132 Date: Sat, 5 Mar 2016 01:44:28 +0200 Subject: [PATCH 11/31] routeAPI attribute Do this as a standalone proc, and in a more secure fashion later! --- code/modules/client/client procs.dm | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 9e567160b61..f32656b1749 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -130,6 +130,26 @@ usr << feedback_message return + if (href_list["routeAPI"]) + var/linkURI = "" + + switch (href_list["routeAPI"]) + if ("forums/members") + if (!href_list["routeAttribute"]) + return + + if (!config.forumurl) + return + + linkURI = "[config.forumurl]memberlist.php?" + + linkURI += list2params(list("mode" = "viewprofile", "u" = href_list["routeAttribute"])) + + if (linkURI) + usr << link(linkURI) + else + return + ..() //redirect to hsrc.() /client/proc/handle_spam_prevention(var/message, var/mute_type) @@ -369,17 +389,17 @@ var/dat = "
You have active requests to check!
" var/i = 0 for (var/list/request in requests) + i++ + var/linked_forum_name = null if (config.forumurl) - linked_forum_name = "[request["forum_username"]]" + linked_forum_name = "[request["forum_username"]]" dat += "
" dat += "#[i] - Request to link [key] to a forum account with the username of: [linked_forum_name ? linked_forum_name : request["forum_username"]].
" dat += "The request is [request["request_age"]] days old.
" dat += "OPTIONS: Accept Request | Deny Request" - i++ - usr << browse(dat, "window=LinkingRequests") return From 5fd128b63791a2aa452a2e4f568ab218875d2550 Mon Sep 17 00:00:00 2001 From: skull132 Date: Sat, 5 Mar 2016 01:52:53 +0200 Subject: [PATCH 12/31] usr -> src fix --- code/modules/client/client procs.dm | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index f32656b1749..5abc3cc2a1c 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -85,7 +85,7 @@ establish_db_connection(dbcon) if (!dbcon.IsConnected()) - usr << "\red Action failed! Database link could not be established!" + src << "\red Action failed! Database link could not be established!" return @@ -93,11 +93,11 @@ check_query.Execute(list(":id" = request_id)) if (!check_query.NextRow()) - usr << "\red No request found!" + src << "\red No request found!" return if (ckey(check_query.item[1]) != ckey || check_query.item[2] != "new") - usr << "\red Request authentication failed!" + src << "\red Request authentication failed!" return var/query_contents = "" @@ -117,7 +117,7 @@ feedback_message = "Link request rejected!" else - usr << "\red Invalid command sent." + src << "\red Invalid command sent." return var/DBQuery/update_query = dbcon.NewQuery(query_contents) @@ -125,9 +125,9 @@ if (href_list["linkingaction"] == "accept" && config.webinterface_url) if(alert("To complete the process, you have to visit the website. Do you ",,"Yes","No") == "Yes") - usr << link("[config.webinterface_url]user/link") + src << link("[config.webinterface_url]user/link") - usr << feedback_message + src << feedback_message return if (href_list["routeAPI"]) @@ -146,7 +146,7 @@ linkURI += list2params(list("mode" = "viewprofile", "u" = href_list["routeAttribute"])) if (linkURI) - usr << link(linkURI) + src << link(linkURI) else return @@ -400,7 +400,7 @@ dat += "The request is [request["request_age"]] days old.
" dat += "OPTIONS: Accept Request | Deny Request" - usr << browse(dat, "window=LinkingRequests") + src << browse(dat, "window=LinkingRequests") return From ed0e7ca4118ba20598b54267159796b58edd8c38 Mon Sep 17 00:00:00 2001 From: skull132 Date: Sat, 5 Mar 2016 02:58:35 +0200 Subject: [PATCH 13/31] Infrastructure for Processing Weblinks Should make the functions that rely on feeding links for the user about the webinterface easier and faster. Simply need to modify the `process_webAPI_link()` proc and call the specific hyperlinks. --- code/modules/client/client procs.dm | 138 ++++++++++++++++------------ 1 file changed, 77 insertions(+), 61 deletions(-) diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 5abc3cc2a1c..82f11d47365 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -101,7 +101,7 @@ return var/query_contents = "" - var/list/query_details[] + var/list/query_details = list(":new_status", ":id") var/feedback_message = "" switch (href_list["linkingaction"]) if ("accept") @@ -123,32 +123,17 @@ var/DBQuery/update_query = dbcon.NewQuery(query_contents) update_query.Execute(query_details) - if (href_list["linkingaction"] == "accept" && config.webinterface_url) - if(alert("To complete the process, you have to visit the website. Do you ",,"Yes","No") == "Yes") - src << link("[config.webinterface_url]user/link") + if (href_list["linkingaction"] == "accept" && alert("To complete the process, you have to visit the website. Do you want to do so now?",,"Yes","No") == "Yes") + process_webAPI_link("interface/user/link") src << feedback_message + check_linking_requests() return if (href_list["routeAPI"]) - var/linkURI = "" + process_webAPI_link(href_list["routeAPI"], href_list["routeAttributes"]) - switch (href_list["routeAPI"]) - if ("forums/members") - if (!href_list["routeAttribute"]) - return - - if (!config.forumurl) - return - - linkURI = "[config.forumurl]memberlist.php?" - - linkURI += list2params(list("mode" = "viewprofile", "u" = href_list["routeAttribute"])) - - if (linkURI) - src << link(linkURI) - else - return + return ..() //redirect to hsrc.() @@ -366,44 +351,6 @@ #undef UPLOAD_LIMIT #undef MIN_CLIENT_VERSION -/client/proc/check_linking_requests() - if (!config.webinterface_enabled || !config.sql_enabled) - return - - establish_db_connection(dbcon) - if (!dbcon.IsConnected()) - return - - var/list/requests = list() - var/list/query_details = list(":ckey" = ckey) - - var/DBQuery/select_query = dbcon.NewQuery("SELECT id, forum_id, forum_username, datediff(Now(), created_at) as request_age FROM ss13_player_linking WHERE status = 'new' AND player_ckey = :ckey AND deleted_at IS NULL") - select_query.Execute(query_details) - - while (select_query.NextRow()) - requests.Add(list(list("id" = text2num(select_query.item[1]), "forum_id" = text2num(select_query.item[2]), "forum_username" = select_query.item[3], "request_age" = select_query.item[4]))) - - if (!requests.len) - return - - var/dat = "
You have active requests to check!
" - var/i = 0 - for (var/list/request in requests) - i++ - - var/linked_forum_name = null - if (config.forumurl) - linked_forum_name = "[request["forum_username"]]" - - dat += "
" - dat += "#[i] - Request to link [key] to a forum account with the username of: [linked_forum_name ? linked_forum_name : request["forum_username"]].
" - dat += "The request is [request["request_age"]] days old.
" - dat += "OPTIONS: Accept Request | Deny Request" - - src << browse(dat, "window=LinkingRequests") - return - - //checks if a client is afk //3000 frames = 5 minutes /client/proc/is_afk(duration=3000) @@ -460,12 +407,81 @@ ) -mob/proc/MayRespawn() +/mob/proc/MayRespawn() return 0 -client/proc/MayRespawn() +/client/proc/MayRespawn() if(mob) return mob.MayRespawn() // Something went wrong, client is usually kicked or transfered to a new mob at this point return 0 + +/client/proc/check_linking_requests() + if (!config.webinterface_enabled || !config.sql_enabled) + return + + establish_db_connection(dbcon) + if (!dbcon.IsConnected()) + return + + var/list/requests = list() + var/list/query_details = list(":ckey" = ckey) + + var/DBQuery/select_query = dbcon.NewQuery("SELECT id, forum_id, forum_username, datediff(Now(), created_at) as request_age FROM ss13_player_linking WHERE status = 'new' AND player_ckey = :ckey AND deleted_at IS NULL") + select_query.Execute(query_details) + + while (select_query.NextRow()) + requests.Add(list(list("id" = text2num(select_query.item[1]), "forum_id" = text2num(select_query.item[2]), "forum_username" = select_query.item[3], "request_age" = select_query.item[4]))) + + if (!requests.len) + return + + var/dat = "
You have active requests to check!
" + var/i = 0 + for (var/list/request in requests) + i++ + + var/linked_forum_name = null + if (config.forumurl) + var/route_attributes = list2params(list("mode" = "viewprofile", "u" = request["forum_id"])) + linked_forum_name = "[request["forum_username"]]" + + dat += "
" + dat += "#[i] - Request to link your current key ([key]) to a forum account with the username of: [linked_forum_name ? linked_forum_name : request["forum_username"]].
" + dat += "The request is [request["request_age"]] days old.
" + dat += "OPTIONS: Accept Request | Deny Request" + + src << browse(dat, "window=LinkingRequests") + return + +/client/proc/process_webAPI_link(var/route, var/attributes) + if (!route) + return + + var/linkURI = "" + + switch (route) + if ("forums/members") + if (!attributes) + return + + if (!config.forumurl) + return + + linkURI = "[config.forumurl]memberlist.php?" + + linkURI += attributes + + if ("interface/user/link") + if (!config.webinterface_url) + return + + linkURI = "[config.webinterface_url]user/link" + + else + log_misc("Unrecognized routeAPI call used. Route sent: '[route]'.") + return + + src << link(linkURI) + return From bc26d508e118e3eb2d60b0ddb1da32b38694196d Mon Sep 17 00:00:00 2001 From: skull132 Date: Sat, 5 Mar 2016 03:10:48 +0200 Subject: [PATCH 14/31] view_linking_requests() verb Adds the verb to call the proc whenever. --- code/modules/client/client procs.dm | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 82f11d47365..92234716690 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -417,6 +417,14 @@ // Something went wrong, client is usually kicked or transfered to a new mob at this point return 0 +//I honestly can't find a good place for this atm. +//If the webinterface interaction gets more features, I'll move it. - Skull132 +/client/verb/view_linking_requests() + set name = "View Linking Requests" + set category = "OOC" + + check_linking_requests() + /client/proc/check_linking_requests() if (!config.webinterface_enabled || !config.sql_enabled) return From 9143d5077a4220d30061d8fdea0ad64548488523 Mon Sep 17 00:00:00 2001 From: skull132 Date: Mon, 7 Mar 2016 19:00:28 +0200 Subject: [PATCH 15/31] webint_procs.dm Initial Commit Starting to create a bit of a library to hold functions related to the web interface. --- baystation12.dme | 1 + code/modules/web_interface/webint_procs.dm | 35 ++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 code/modules/web_interface/webint_procs.dm diff --git a/baystation12.dme b/baystation12.dme index aede49368ad..7b37efa3483 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -1715,6 +1715,7 @@ #include "code\modules\virus2\helpers.dm" #include "code\modules\virus2\isolator.dm" #include "code\modules\virus2\items_devices.dm" +#include "code\modules\web_interface\webint_procs.dm" #include "code\TriDimension\controller.dm" #include "code\TriDimension\controller_presets.dm" #include "code\TriDimension\Movement.dm" diff --git a/code/modules/web_interface/webint_procs.dm b/code/modules/web_interface/webint_procs.dm new file mode 100644 index 00000000000..236a0ae0623 --- /dev/null +++ b/code/modules/web_interface/webint_procs.dm @@ -0,0 +1,35 @@ +/* + * Contains general purpose procs used with Aurora's web interface and related functions. + */ + +/* + * /proc/validate_webint_attributes() + * Used to validate parametres sent to procs that are meant to communicate with the web interface. + * Most commonly in Topic() calls, so that href tomfoolery is negated. + * + * Arguments: + * - var/list/required_attributes - A list of required attributes. This is what the other arguments will be tested against. Cannot be null. + * - var/list/attributes_list - The attributes to be validated, passed in a list form. Can be null. + * - var/attributes_text - The attributes to be validated, passed in a text form. (Formatted according to list2params() convention.) + * This overrides attributes_list if both are present. Can be null. + * + * Returns: + * 1 - if all required attributes are present, and no erronious ones exist. + * 0 - if certain required attributes are missing, or there are extras. + */ + +/proc/webint_validate_attributes(var/list/required_attributes, var/list/attributes_list, var/attributes_text) + if (!required_attributes || !istype(required_attributes) || !required_attributes.len) + return 0 + + if (attributes_text) + attributes_list = params2list(attributes_text) + + if (!attributes_list || !attributes_list.len) + return 0 + + for (var/attribute in attributes_list) + if (!(attribute in required_attributes)) + return 0 + + return 1 From 61e93b1d790996587f545b090637ef7db19d984d Mon Sep 17 00:00:00 2001 From: skull132 Date: Mon, 7 Mar 2016 19:01:03 +0200 Subject: [PATCH 16/31] Naming Standardization webint shall be the common word used now, replaced all instances of webinterface or webAPI with that one phrase. Should make it easier to read and search. --- code/controllers/configuration.dm | 14 ++++++------- code/modules/client/client procs.dm | 32 ++++++++++++++--------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 94d55548fbc..4a9f8c3bd55 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -208,9 +208,9 @@ var/list/gamemode_cache = list() var/aggressive_changelog = 0 - //Webinterface settings - var/webinterface_enabled = 0 - var/webinterface_url = "" + //Web interface settings + var/webint_enabled = 0 + var/webint_url = "" /datum/configuration/New() var/list/L = typesof(/datum/game_mode) - /datum/game_mode @@ -678,11 +678,11 @@ var/list/gamemode_cache = list() if("show_auxiliary_roles") config.show_auxiliary_roles = 1 - if("use_webinterface") - config.webinterface_enabled = 1 + if("use_webint") + config.webint_enabled = 1 - if("webinterface_url") - config.webinterface_url = 1 + if("webint_url") + config.webint_url = 1 else log_misc("Unknown setting in configuration: '[name]'") diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 92234716690..b4197f621e8 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -75,7 +75,7 @@ warnings_check() if(href_list["linkingrequest"]) - if (!config.webinterface_enabled) + if (!config.webint_enabled) return if (!href_list["linkingaction"]) @@ -124,14 +124,14 @@ update_query.Execute(query_details) if (href_list["linkingaction"] == "accept" && alert("To complete the process, you have to visit the website. Do you want to do so now?",,"Yes","No") == "Yes") - process_webAPI_link("interface/user/link") + process_webint_link("interface/user/link") src << feedback_message check_linking_requests() return - if (href_list["routeAPI"]) - process_webAPI_link(href_list["routeAPI"], href_list["routeAttributes"]) + if (href_list["routeWebInt"]) + process_webint_link(href_list["routeWebInt"], href_list["routeAttributes"]) return @@ -418,7 +418,7 @@ return 0 //I honestly can't find a good place for this atm. -//If the webinterface interaction gets more features, I'll move it. - Skull132 +//If the webint interaction gets more features, I'll move it. - Skull132 /client/verb/view_linking_requests() set name = "View Linking Requests" set category = "OOC" @@ -426,7 +426,7 @@ check_linking_requests() /client/proc/check_linking_requests() - if (!config.webinterface_enabled || !config.sql_enabled) + if (!config.webint_enabled || !config.sql_enabled) return establish_db_connection(dbcon) @@ -453,7 +453,7 @@ var/linked_forum_name = null if (config.forumurl) var/route_attributes = list2params(list("mode" = "viewprofile", "u" = request["forum_id"])) - linked_forum_name = "[request["forum_username"]]" + linked_forum_name = "[request["forum_username"]]" dat += "
" dat += "#[i] - Request to link your current key ([key]) to a forum account with the username of: [linked_forum_name ? linked_forum_name : request["forum_username"]].
" @@ -463,33 +463,33 @@ src << browse(dat, "window=LinkingRequests") return -/client/proc/process_webAPI_link(var/route, var/attributes) +/client/proc/process_webint_link(var/route, var/attributes) if (!route) return - var/linkURI = "" + var/linkURL = "" switch (route) if ("forums/members") - if (!attributes) + if (!webint_validate_attributes(list("mode", "u"), attributes_text = attributes)) return if (!config.forumurl) return - linkURI = "[config.forumurl]memberlist.php?" + linkURL = "[config.forumurl]memberlist.php?" - linkURI += attributes + linkURL += attributes if ("interface/user/link") - if (!config.webinterface_url) + if (!config.webint_url) return - linkURI = "[config.webinterface_url]user/link" + linkURL = "[config.webint_url]user/link" else - log_misc("Unrecognized routeAPI call used. Route sent: '[route]'.") + log_misc("Unrecognized process_webint_link() call used. Route sent: '[route]'.") return - src << link(linkURI) + src << link(linkURL) return From e9c61c5fd90829d9fd667487ce57bbf61c7cb7ac Mon Sep 17 00:00:00 2001 From: Lord Lag Date: Tue, 8 Mar 2016 22:14:59 +0000 Subject: [PATCH 17/31] Adds #183, Vaurca is back to P (not fixed), Slime damage tweaked. --- code/modules/clothing/glasses/glasses.dm | 18 +++++++++++ code/modules/clothing/glasses/hud.dm | 30 ++++++++++++++++++ code/modules/mob/language/station.dm | 2 +- .../modules/mob/living/carbon/metroid/life.dm | 10 +++--- .../mob/living/carbon/metroid/metroid.dm | 2 ++ html/changelogs/[Lord Lag]-[Adds #183].yml | 6 ++++ icons/mob/eyes.dmi | Bin 7356 -> 7700 bytes icons/obj/clothing/glasses.dmi | Bin 7184 -> 7802 bytes 8 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 html/changelogs/[Lord Lag]-[Adds #183].yml diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index c9de540257d..22537d7b183 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -110,6 +110,24 @@ prescription = 1 body_parts_covered = 0 +/obj/item/clothing/glasses/regular/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/clothing/glasses/hud/health)) + user.drop_item() + del(W) + user << "You attach a set of medical HUDs to your glasses." + var/turf/T = get_turf(src) + new /obj/item/clothing/glasses/hud/health/prescription(T) + user.drop_from_inventory(src) + del(src) + if(istype(W, /obj/item/clothing/glasses/hud/security)) + user.drop_item() + del(W) + user << "You attach a set of security HUDs to your glasses." + var/turf/T = get_turf(src) + new /obj/item/clothing/glasses/hud/security/prescription(T) + user.drop_from_inventory(src) + del(src) + /obj/item/clothing/glasses/regular/scanners name = "Scanning Goggles" desc = "A very oddly shaped pair of goggles with bits of wire poking out the sides. A soft humming sound emanates from it." diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm index fb3d94ee89d..d775891d287 100644 --- a/code/modules/clothing/glasses/hud.dm +++ b/code/modules/clothing/glasses/hud.dm @@ -20,6 +20,21 @@ /obj/item/clothing/glasses/hud/health/process_hud(var/mob/M) process_med_hud(M, 1) +/obj/item/clothing/glasses/hud/health/prescription + name = "prescription glasses/HUD assembly" + desc = "A medical HUD clipped onto the side of prescription glasses." + prescription = 1 + icon_state = "healthhudpresc" + item_state = "healthhudpresc" + +/obj/item/clothing/glasses/hud/health/prescription/attack_self(mob/user) + user << "You detach a set of medical HUDs form your glasses." + var/turf/T = get_turf(src) + new /obj/item/clothing/glasses/hud/health(T) + new /obj/item/clothing/glasses/regular(T) + user.drop_item(src) + del(src) + /obj/item/clothing/glasses/hud/security name = "Security HUD" desc = "A heads-up display that scans the humans in view and provides accurate data about their ID status and security records." @@ -27,6 +42,21 @@ body_parts_covered = 0 var/global/list/jobs[0] +/obj/item/clothing/glasses/hud/security/prescription + name = "prescription glasses/HUD assembly" + desc = "A security HUD clipped onto the side of prescription glasses." + prescription = 1 + icon_state = "sechudpresc" + item_state = "sechudpresc" + +/obj/item/clothing/glasses/hud/security/prescription/attack_self(mob/user) + user << "You detach a set of security HUDs form your glasses." + var/turf/T = get_turf(src) + new /obj/item/clothing/glasses/hud/health(T) + new /obj/item/clothing/glasses/regular(T) + user.drop_item(src) + del(src) + /obj/item/clothing/glasses/hud/security/jensenshades name = "Augmented shades" desc = "Polarized bioneural eyewear, designed to augment your vision." diff --git a/code/modules/mob/language/station.dm b/code/modules/mob/language/station.dm index 13ca46882c8..7aa3d9cd425 100644 --- a/code/modules/mob/language/station.dm +++ b/code/modules/mob/language/station.dm @@ -71,7 +71,7 @@ desc = "Vaurca native language made of clicks and sputters, \"It's a bugs life.\"" speech_verb = "clicks" colour = "vaurca" - key = "m" + key = "p" flags = WHITELISTED syllables = list("kic","klic","\'tic","kit","lit","xic","vil","xrit","tshh","qix","qlit","zix","\'","!") diff --git a/code/modules/mob/living/carbon/metroid/life.dm b/code/modules/mob/living/carbon/metroid/life.dm index 06b4bbae6ca..638137cbd09 100644 --- a/code/modules/mob/living/carbon/metroid/life.dm +++ b/code/modules/mob/living/carbon/metroid/life.dm @@ -52,13 +52,13 @@ //Account for massive pressure differences - if(bodytemperature < (T0C + 5)) // start calculating temperature damage etc + if(bodytemperature < hurt_temperature) // start calculating temperature damage etc - if(bodytemperature <= (T0C - 50)) // hurt temperature - if(bodytemperature <= 50) // sqrting negative numbers is bad + if(bodytemperature <= die_temperature) + if(bodytemperature <= 50) adjustToxLoss(200) else - adjustToxLoss(round(sqrt(bodytemperature)) * 2) + adjustToxLoss(30) updatehealth() @@ -234,7 +234,7 @@ if(issilicon(L) && (rabid || attacked)) // They can't eat silicons, but they can glomp them in defence targets += L // Possible target found! - if(istype(L, /mob/living/carbon/human) && dna) //Ignore slime(wo)men + if(istype(L, /mob/living/carbon/human)) //Ignore slime(wo)men var/mob/living/carbon/human/H = L if(H.species.name == "Slime") continue diff --git a/code/modules/mob/living/carbon/metroid/metroid.dm b/code/modules/mob/living/carbon/metroid/metroid.dm index c2e41118b5a..36ce63cea00 100644 --- a/code/modules/mob/living/carbon/metroid/metroid.dm +++ b/code/modules/mob/living/carbon/metroid/metroid.dm @@ -48,6 +48,8 @@ var/Atkcool = 0 // attack cooldown var/SStun = 0 // NPC stun variable. Used to calm them down when they are attacked while feeding, or they will immediately re-attach var/Discipline = 0 // if a slime has been hit with a freeze gun, or wrestled/attacked off a human, they become disciplined and don't attack anymore for a while. The part about freeze gun is a lie + var/hurt_temperature = T0C-50 // slime keeps taking damage when its bodytemperature is below this + var/die_temperature = 50 // slime dies instantly when its bodytemperature is below this ///////////TIME FOR SUBSPECIES diff --git a/html/changelogs/[Lord Lag]-[Adds #183].yml b/html/changelogs/[Lord Lag]-[Adds #183].yml new file mode 100644 index 00000000000..d521601d9d1 --- /dev/null +++ b/html/changelogs/[Lord Lag]-[Adds #183].yml @@ -0,0 +1,6 @@ +author: Lord Lag + +delete-after: True + +changes: + - rscadd: "Glasses may once again be combined with HUDs" diff --git a/icons/mob/eyes.dmi b/icons/mob/eyes.dmi index b68ccd373c51314ec6920588282b4535c70cf643..9c36e5e59c08ec15e2ca0ed8fcef0f633e839411 100644 GIT binary patch literal 7700 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 RS^@zdeO*JHa;--%{sSb9wjKZg literal 7356 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 Jzi#vJzW|c3_JaTb diff --git a/icons/obj/clothing/glasses.dmi b/icons/obj/clothing/glasses.dmi index 43bea2af31892939b067442632a05c174a4f7ef1..3e20f69244ee06068e9af0d91266035b4ee506d1 100644 GIT binary patch literal 7802 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 HhuHrGZSLqZ literal 7184 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 Date: Thu, 10 Mar 2016 19:59:52 +0000 Subject: [PATCH 18/31] Fixes #210 --- code/modules/mob/language/monkey.dm | 2 +- code/modules/mob/language/station.dm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/mob/language/monkey.dm b/code/modules/mob/language/monkey.dm index ce276a358ab..f41a484cfce 100644 --- a/code/modules/mob/language/monkey.dm +++ b/code/modules/mob/language/monkey.dm @@ -19,4 +19,4 @@ /datum/language/tajaran/monkey name = "Farwa" desc = "Meow meow meow." - key = "9" + key = "^" diff --git a/code/modules/mob/language/station.dm b/code/modules/mob/language/station.dm index 7aa3d9cd425..990d966c227 100644 --- a/code/modules/mob/language/station.dm +++ b/code/modules/mob/language/station.dm @@ -71,7 +71,7 @@ desc = "Vaurca native language made of clicks and sputters, \"It's a bugs life.\"" speech_verb = "clicks" colour = "vaurca" - key = "p" + key = "9" flags = WHITELISTED syllables = list("kic","klic","\'tic","kit","lit","xic","vil","xrit","tshh","qix","qlit","zix","\'","!") From 23ce751ec7377d40a648f8152e8baa2ea0fdb103 Mon Sep 17 00:00:00 2001 From: Lord Lag Date: Thu, 10 Mar 2016 20:01:20 +0000 Subject: [PATCH 19/31] Update [Lord Lag]-[Adds #183].yml --- html/changelogs/[Lord Lag]-[Adds #183].yml | 1 + 1 file changed, 1 insertion(+) diff --git a/html/changelogs/[Lord Lag]-[Adds #183].yml b/html/changelogs/[Lord Lag]-[Adds #183].yml index d521601d9d1..880a41ea0ad 100644 --- a/html/changelogs/[Lord Lag]-[Adds #183].yml +++ b/html/changelogs/[Lord Lag]-[Adds #183].yml @@ -4,3 +4,4 @@ delete-after: True changes: - rscadd: "Glasses may once again be combined with HUDs" + - bugfix: ":9 is the new new Vaurcese hotkey." From 6bb74a7a87c775012701c5c7bb81ada61717d0a8 Mon Sep 17 00:00:00 2001 From: skull132 Date: Mon, 14 Mar 2016 19:24:49 +0200 Subject: [PATCH 20/31] dbcore.dm - Better INT Management `parseArguments()` will now identify 0 as an itneger properly, instead of slotting it under null. --- code/defines/procs/dbcore.dm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/defines/procs/dbcore.dm b/code/defines/procs/dbcore.dm index 67dc76a8e24..166896587cf 100644 --- a/code/defines/procs/dbcore.dm +++ b/code/defines/procs/dbcore.dm @@ -197,12 +197,12 @@ DBQuery/proc/parseArguments(var/query_to_parse = null, var/list/argument_list, v var/argument = argument_list[placeholder] - if (isnull(argument)) - argument = "NULL" - else if (istext(argument)) + if (istext(argument)) argument = dbcon.Quote(argument) else if (isnum(argument)) - argument = "'[argument]'" + argument = "[argument]" + else if (isnull(argument)) + argument = "NULL" else log_debug("parseArguments() failed! Cannot identify argument!") return 0 From 760c6895d2194869dec8104cdfa011a82b771d2b Mon Sep 17 00:00:00 2001 From: Lord Lag Date: Sat, 19 Mar 2016 15:26:48 +0000 Subject: [PATCH 21/31] Update [Lord Lag]-[Adds #183].yml --- html/changelogs/[Lord Lag]-[Adds #183].yml | 1 + 1 file changed, 1 insertion(+) diff --git a/html/changelogs/[Lord Lag]-[Adds #183].yml b/html/changelogs/[Lord Lag]-[Adds #183].yml index 880a41ea0ad..7b85cc94043 100644 --- a/html/changelogs/[Lord Lag]-[Adds #183].yml +++ b/html/changelogs/[Lord Lag]-[Adds #183].yml @@ -4,4 +4,5 @@ delete-after: True changes: - rscadd: "Glasses may once again be combined with HUDs" + - rscadd: "Borers have a full compliment of abilities once more." - bugfix: ":9 is the new new Vaurcese hotkey." From b294a52dcc564dc9aa38d9d55c4d4d297700bf89 Mon Sep 17 00:00:00 2001 From: Lord Lag Date: Sun, 20 Mar 2016 14:50:19 +0000 Subject: [PATCH 22/31] Fixes 120 replaces the temperature gun with the old-fashioned Freeze ray. --- .../projectiles/guns/energy/temperature.dm | 19 ++++++++++--------- .../modules/projectiles/projectile/special.dm | 6 +++--- html/changelogs/[Lord Lag]-[Fixes #120].yml | 7 +++++++ 3 files changed, 20 insertions(+), 12 deletions(-) create mode 100644 html/changelogs/[Lord Lag]-[Fixes #120].yml diff --git a/code/modules/projectiles/guns/energy/temperature.dm b/code/modules/projectiles/guns/energy/temperature.dm index 47bc2cfc00b..34801b4574b 100644 --- a/code/modules/projectiles/guns/energy/temperature.dm +++ b/code/modules/projectiles/guns/energy/temperature.dm @@ -1,18 +1,18 @@ /obj/item/weapon/gun/energy/temperature - name = "temperature gun" + name = "freeze ray" icon_state = "freezegun" fire_sound = 'sound/weapons/pulse3.ogg' - desc = "A gun that changes temperatures. It has a small label on the side, 'More extreme temperatures will cost more charge!'" - var/temperature = T20C - var/current_temperature = T20C - charge_cost = 100 + desc = "For when somebody won't let it go." + //var/temperature = T20C + //var/current_temperature = T20C + charge_cost = 25 //20 shots, exact replica of old code (WAS 100) origin_tech = "combat=3;materials=4;powerstorage=3;magnets=2" slot_flags = SLOT_BELT|SLOT_BACK projectile_type = /obj/item/projectile/temp - cell_type = /obj/item/weapon/cell/high - + cell_type = /obj/item/weapon/cell/crap //WAS High, but brought down to match energy use +/* /obj/item/weapon/gun/energy/temperature/New() ..() processing_objects.Add(src) @@ -38,7 +38,7 @@ user << browse(dat, "window=freezegun;size=450x300;can_resize=1;can_close=1;can_minimize=1") onclose(user, "window=freezegun", src) - +*/ /obj/item/weapon/gun/energy/temperature/Topic(href, href_list) if (..()) @@ -47,7 +47,7 @@ src.add_fingerprint(usr) - +/* if(href_list["temp"]) var/amount = text2num(href_list["temp"]) if(amount > 0) @@ -77,3 +77,4 @@ temperature += 10 else temperature = current_temperature +*/ \ No newline at end of file diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index f2578d3f60b..bfba9472313 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -28,7 +28,7 @@ name ="high-ex round" icon_state= "bolter" damage = 15 - + on_hit(var/atom/target, var/blocked = 0) explosion(target, -1, 0, 2) sleep(0) @@ -44,13 +44,13 @@ damage_type = BURN nodamage = 1 check_armour = "energy" - var/temperature = 300 + //var/temperature = 300 on_hit(var/atom/target, var/blocked = 0)//These two could likely check temp protection on the mob if(istype(target, /mob/living)) var/mob/M = target - M.bodytemperature = temperature + M.bodytemperature = -273 return 1 /obj/item/projectile/meteor diff --git a/html/changelogs/[Lord Lag]-[Fixes #120].yml b/html/changelogs/[Lord Lag]-[Fixes #120].yml new file mode 100644 index 00000000000..f14cc1ab746 --- /dev/null +++ b/html/changelogs/[Lord Lag]-[Fixes #120].yml @@ -0,0 +1,7 @@ +author: Lord Lag + +delete-after: True + +changes: + - tweak: "The broken Temperature gun has been replaced with the Freeze ray" + From 997665bca7d8e9585e9bf4a334d20a9f2ee41bc5 Mon Sep 17 00:00:00 2001 From: skull132 Date: Mon, 21 Mar 2016 23:04:10 +0200 Subject: [PATCH 23/31] webint_procs.dm - webint_start_singlesignon() Proc for creating a unique signin token for the website and shoving it into the database. --- code/modules/web_interface/webint_procs.dm | 61 ++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/code/modules/web_interface/webint_procs.dm b/code/modules/web_interface/webint_procs.dm index 236a0ae0623..332dcf19a54 100644 --- a/code/modules/web_interface/webint_procs.dm +++ b/code/modules/web_interface/webint_procs.dm @@ -32,4 +32,65 @@ if (!(attribute in required_attributes)) return 0 + if (attributes_list[attribute] && required_attributes[attribute]) + if (istype(required_attributes, /list)) + if (!(attributes_list[attribute] in required_attributes[attribute])) + return 0 + + else + if (attributes_list[attribute] != required_attributes[attribute]) + return 0 + return 1 + +/* + * /proc/webint_start_singlesignon() + * Used to insert a token into the web_sso database and to enable a user to navigate to a page on the website and be automatically logged in. Hashes the user's save file for a unique token. Additional security managed on the website's end. + * + * Arguments: + * - var/user - Must be a mob or a client. The player object that's going to be using the request. + * - var/list/attributes - The attributes to which we route the URL as we call user.process_webint_link(). + * Validated here with webint_validate_attributes(). + * Must contain the 'location' key. + * + * Returns: + * 0 - if one of the checks is failed and the operation cancelled. + * string - if everything works, it will return the attributes with the added token and ckey value. + */ + +/proc/webint_start_singlesignon(var/client/user, var/attributes) + if (!istype(user)) + return 0 + + var/list/permitted_locations = list("user_dashboard", "contract_overview", "contract_details") + + if (!webint_validate_attributes(list("location" = permitted_locations, "contract"), attributes_text = attributes)) + return 0 + + var/token = "" + var/list/alphabet = alphabet_uppercase + alphabet.Add(list("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z")) + alphabet.Add(list("1", "2", "3", "4", "5", "6", "7", "8", "9", "0")) + + for (var/i = 0, i <= 24, i++) + token += alphabet[rand(1, alphabet.len)] + + attributes += "&" + attributes += list2params(list("ckey" = user.ckey, "token" = token)) + + establish_db_connection(dbcon) + if (!dbcon.IsConnected()) + alert("An error occured while attempting to connect to the database!") + return 0 + + var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO ss13_web_sso (ckey, token, ip, created_at) VALUES (:ckey, :token, :ip, NOW())") + insert_query.Execute(list(":ckey" = user.ckey, ":token" = token, ":ip" = user.address)) + + if (insert_query.ErrorMsg()) + alert("An error occured while trying to upload the session data!") + return 0 + + if (alert("This will take you to the webpage and log you in. Do you wish to proceed?",,"Yes","No") == "No") + return 0 + + return attributes From e03eaa86a55dc969cc84ed7ab6f98c714ceaf7e2 Mon Sep 17 00:00:00 2001 From: skull132 Date: Mon, 21 Mar 2016 23:05:31 +0200 Subject: [PATCH 24/31] client procs.dm - sso_server addition Adds a new route for the webint url parser. Also reverts to checking for config.webint_url as opposed to running double checks for config.webint_enabled and then for the url. If the URL is present, we're enabling the webint. --- code/modules/client/client procs.dm | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index b4197f621e8..3a936f7eb0c 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -75,7 +75,7 @@ warnings_check() if(href_list["linkingrequest"]) - if (!config.webint_enabled) + if (!config.webint_url) return if (!href_list["linkingaction"]) @@ -426,7 +426,7 @@ check_linking_requests() /client/proc/check_linking_requests() - if (!config.webint_enabled || !config.sql_enabled) + if (!config.webint_url || !config.sql_enabled) return establish_db_connection(dbcon) @@ -487,8 +487,20 @@ linkURL = "[config.webint_url]user/link" + if ("interface/login/sso_server") + //This also validates the attributes as it runs + var/new_attributes = webint_start_singlesignon(src, attributes) + if (!new_attributes) + return + + if (!config.webint_url) + return + + linkURL = "[config.webint_url]login/sso_server?" + linkURL += new_attributes + else - log_misc("Unrecognized process_webint_link() call used. Route sent: '[route]'.") + log_debug("Unrecognized process_webint_link() call used. Route sent: '[route]'.") return src << link(linkURL) From a5cb959166c6a75e77b11c58f6c0d641ebed8c3a Mon Sep 17 00:00:00 2001 From: skull132 Date: Mon, 21 Mar 2016 23:06:02 +0200 Subject: [PATCH 25/31] Remove config.webint_enabled Depracted in favour of using config.webint_url in general. Just checks if it's defined, and if so, we'll consider it active and in use. --- code/controllers/configuration.dm | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 4a9f8c3bd55..c5e6c42c38a 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -209,7 +209,6 @@ var/list/gamemode_cache = list() var/aggressive_changelog = 0 //Web interface settings - var/webint_enabled = 0 var/webint_url = "" /datum/configuration/New() @@ -678,11 +677,8 @@ var/list/gamemode_cache = list() if("show_auxiliary_roles") config.show_auxiliary_roles = 1 - if("use_webint") - config.webint_enabled = 1 - if("webint_url") - config.webint_url = 1 + config.webint_url = value else log_misc("Unknown setting in configuration: '[name]'") From 7e266649ea010a6a5f1666e9bdeeb0ed7ac0c211 Mon Sep 17 00:00:00 2001 From: skull132 Date: Mon, 21 Mar 2016 23:07:04 +0200 Subject: [PATCH 26/31] Syndicate Contracts - Initial Implementation Adds SQL database based syndicate contracts to be viewed from any uplink. These can be used as IC traitor objectives, but hopefully with more RP and stuff. --- code/game/objects/items/devices/uplinks.dm | 115 +++++++++++++++++++++ nano/templates/uplink.tmpl | 80 +++++++++++++- 2 files changed, 190 insertions(+), 5 deletions(-) diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm index c8f23054e4d..888dd0bb4de 100644 --- a/code/game/objects/items/devices/uplinks.dm +++ b/code/game/objects/items/devices/uplinks.dm @@ -257,6 +257,16 @@ datum/nano_item_lists if(href_list["menu"]) nanoui_menu = text2num(href_list["menu"]) update_nano_data(href_list["id"]) + if(href_list["contract_interact"]) + var/list/params = list("location" = "contract_details", "contract" = href_list["contract_interact"]) + usr.client.process_webint_link("interface/login/sso_server", list2params(params)) + if(href_list["contract_page"]) + nanoui_data["contracts_current_page"] = text2num(href_list["contract_page"]) + update_nano_data() + if(href_list["contract_view"]) + nanoui_data["contracts_view"] = text2num(href_list["contract_view"]) + nanoui_data["contracts_current_page"] = 1 + update_nano_data() interact(usr) return 1 @@ -292,6 +302,111 @@ datum/nano_item_lists nanoui_data["exploit_exists"] = 1 break + if(nanoui_menu == 2) + nanoui_data["contracts_found"] = 0 + + establish_db_connection(dbcon) + + if (dbcon.IsConnected()) + nanoui_data["contracts"] = list() + + if (!nanoui_data["contracts_current_page"]) + nanoui_data["contracts_current_page"] = 1 + + if (!nanoui_data["contracts_view"]) + nanoui_data["contracts_view"] = 1 + + var/query_details[0] + + switch (nanoui_data["contracts_view"]) + if (1) + query_details[":status"] = "open" + if (2) + query_details[":status"] = "closed" + else + nanoui_data["contracts_view"] = 1 + query_details[":status"] = "open" + + var/DBQuery/index_query = dbcon.NewQuery("SELECT count(*) as Total_Contracts FROM ss13_syndie_contracts WHERE deleted_at IS NULL AND status = :status") + index_query.Execute(query_details) + + var/pages = 0 + + if (index_query.NextRow()) + var/total_contracts = text2num(index_query.item[1]) + + pages = total_contracts / 10 + + if (total_contracts % 10) + pages++ + + pages = round(pages) + + var/list/contracts_pages = list() + + for (var/i = 1, i <= pages, i++) + contracts_pages.Add(i) + + for (var/a in contracts_pages) + + nanoui_data["contracts_pages"] = contracts_pages + + if (nanoui_data["contracts_current_page"] > pages) + return + + query_details[":offset"] = (nanoui_data["contracts_current_page"] - 1) * 10 + + var/DBQuery/list_query = dbcon.NewQuery("SELECT contract_id, contractee_name, title FROM ss13_syndie_contracts WHERE deleted_at IS NULL AND status = :status LIMIT 10 OFFSET :offset") + list_query.Execute(query_details) + + var/list/contracts = list() + while (list_query.NextRow()) + contracts.Add(list(list("id" = list_query.item[1], + "contractee" = list_query.item[2], + "title" = list_query.item[3]))) + + nanoui_data["contracts"] = contracts + + nanoui_data["contracts_found"] = 1 + + if(nanoui_menu == 21) + nanoui_data["contracts_found"] = 0 + + establish_db_connection(dbcon) + + if (dbcon.IsConnected()) + var/query_details[0] + query_details[":contract_id"] = text2num(id) + + var/DBQuery/select_query = dbcon.NewQuery("SELECT contract_id, contractee_name, status, title, description, reward_other FROM ss13_syndie_contracts WHERE contract_id = :contract_id") + select_query.Execute(query_details) + + if (select_query.NextRow()) + nanoui_data["contracts_found"] = 1 + + var/contract[0] + contract["id"] = select_query.item[1] + contract["contractee"] = select_query.item[2] + + switch (select_query.item[3]) + if ("open") + contract["status"] = "1" + else + contract["status"] = "0" + + contract["title"] = html_encode(select_query.item[4]) + contract["description"] = select_query.item[5] + + var/list/nano_blacklist = list("/" = " ", "_" = " ", "\n" = "
") + + for (var/a in nano_blacklist) + contract["description"] = replacetext(contract["description"], a, nano_blacklist[a]) + + contract["description"] = html_encode(contract["description"]) + contract["reward_other"] = select_query.item[6] + + nanoui_data["contract"] = contract + // I placed this here because of how relevant it is. // You place this in your uplinkable item to check if an uplink is active or not. // If it is, it will display the uplink menu and return 1, else it'll return false. diff --git a/nano/templates/uplink.tmpl b/nano/templates/uplink.tmpl index e981155622d..d51aebcbc3a 100644 --- a/nano/templates/uplink.tmpl +++ b/nano/templates/uplink.tmpl @@ -1,5 +1,5 @@ - @@ -13,12 +13,13 @@ Used In File(s): \code\game\objects\items\devices\uplinks.dm
{{:helper.link('Request Items', 'gear', {'menu' : 0}, null, 'fixedLeftWider')}} {{:helper.link('Exploitable Information', 'gear', {'menu' : 1}, null, 'fixedLeftWider')}} + {{:helper.link('Extranet Contract Database', 'gear', {'menu' : 2}, null, 'fixedLeftWider')}} {{:helper.link('Return', 'arrowreturn-1-w', {'return' : 1}, null, 'fixedLeft')}} {{:helper.link('Close', 'gear', {'lock' : "1"}, null, 'fixedLeft')}}

- + {{if data.menu == 0}}

Request items:

Each item costs a number of tele-crystals as indicated by the number following their name. @@ -39,7 +40,7 @@ Used In File(s): \code\game\objects\items\devices\uplinks.dm
{{:helper.link( itemValue.Name, 'gear', {'buy_item' : itemValue.obj_path, 'cost' : itemValue.Cost}, itemValue.Cost > data.crystals ? 'disabled' : null, null)}} - {{:itemValue.Cost}}
- + {{if itemValue.Cost <= data.crystals}}
{{:itemValue.Description}} @@ -52,7 +53,7 @@ Used In File(s): \code\game\objects\items\devices\uplinks.dm
{{:helper.link('Buy Random (??)' , 'gear', {'buy_item' : 'random'}, data.crystals <= 0 ? 'disabled' : null, null)}}
- + {{else data.menu == 1}}

Information Record List:


@@ -65,7 +66,7 @@ Used In File(s): \code\game\objects\items\devices\uplinks.dm {{:helper.link(value.Name, 'gear', {'menu' : 11, 'id' : value.id}, null, null)}}
{{/for}} - + {{else data.menu == 11}}

Information Record:


@@ -96,4 +97,73 @@ Used In File(s): \code\game\objects\items\devices\uplinks.dm + +{{else data.menu == 2}} +

Available Contracts:

+
+ {{if data.contracts_found == 1}} +
+
+ + {{if data.contracts_view == 1}} + + {{else}} + + {{/if}} + {{for data.contracts}} + + {{/for}} +
IDContractorTitle
Available Contracts
Closed Contracts
{{:value.id}}{{:value.contractee}}{{:value.title}}{{:helper.link('View', null, {'menu' : 21, 'id' : value.id}, null, 'fixedLeft')}}
+
+
+ {{for data.contracts_pages}} + {{:helper.link(value, null, {'contract_page' : value}, null, null)}} + {{/for}} +

+ {{if data.contracts_view == 1}} + {{:helper.link('View Expired Contracts', 'gear', {'contract_view' : 2}, null, null)}} + {{else}} + {{:helper.link('View Open Contracts', 'gear', {'contract_view' : 1}, null, null)}} + {{/if}} +
+
+
+
+ {{else}} +
+
No Contracts Available.
+
+ {{/if}} + +{{else data.menu == 21}} +

Viewing Contract:

+
+
+
+
+ {{if data.contracts_found == 1}} + ID: #{{:data.contract.id}}
+ Contractee: {{:data.contract.contractee}}
+ Status: + {{if data.contract.status == 1}} + Open
+ {{else}} + Closed
+ {{/if}} + Title: {{:data.contract.title}}
+
+ Description: {{:data.contract.description}}
+ Reward: {{:data.contract.reward_other}}
+ {{else}} + Failed to retreive contract information! + {{/if}} +
+ +
+
+

+ {{if data.contracts_found == 1}} + {{:helper.link('View Reports And Updates', 'extlink', {'contract_interact' : data.contract.id}, null, null)}} + {{/if}} + {{/if}} From 899f8cdbec5234fe705f0375d6d05f0a1a17d6d1 Mon Sep 17 00:00:00 2001 From: skull132 Date: Wed, 23 Mar 2016 16:36:46 +0200 Subject: [PATCH 27/31] contract_uplink device & data parsing fix A contract_uplink device has been added, for rounds where no TCs are to be given to antags, but access to the database is neat. Namely: heist. The blacklist was removed, the issue proved to be carriage return characters breaking nanoUI. They are now removed. --- code/game/objects/items/devices/uplinks.dm | 32 ++++++++++++++++++---- maps/exodus-2.dmm | 3 +- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm index 888dd0bb4de..2fbf1f99732 100644 --- a/code/game/objects/items/devices/uplinks.dm +++ b/code/game/objects/items/devices/uplinks.dm @@ -213,6 +213,9 @@ datum/nano_item_lists data["welcome"] = welcome data["crystals"] = uses data["menu"] = nanoui_menu + //Small hack for the contract_uplink device, to make sure the data is initialized properly. + if(nanoui_menu == 2) + update_nano_data() if(!nanoui_items) generate_items() data["nano_items"] = nanoui_items @@ -397,12 +400,9 @@ datum/nano_item_lists contract["title"] = html_encode(select_query.item[4]) contract["description"] = select_query.item[5] - var/list/nano_blacklist = list("/" = " ", "_" = " ", "\n" = "
") - - for (var/a in nano_blacklist) - contract["description"] = replacetext(contract["description"], a, nano_blacklist[a]) - contract["description"] = html_encode(contract["description"]) + contract["description"] = replacetext(contract["description"], "\n", "
") + contract["description"] = replacetext(contract["description"], ascii2text(13), "") contract["reward_other"] = select_query.item[6] nanoui_data["contract"] = contract @@ -447,3 +447,25 @@ datum/nano_item_lists ..() hidden_uplink = new(src) hidden_uplink.uses = 10 + +/* + * A simple device for accessing the SQL based contract database + */ + +/obj/item/device/contract_uplink + name = "contract uplink" + desc = "A small device used for access restricted sites in the remote corners of the Extranet." + icon = 'icons/obj/radio.dmi' + icon_state = "radio" + flags = CONDUCT + w_class = 2 + +/obj/item/device/contract_uplink/New() + ..() + hidden_uplink = new(src) + hidden_uplink.uses = 0 + hidden_uplink.nanoui_menu = 2 + +/obj/item/device/contract_uplink/attack_self(mob/user as mob) + if (hidden_uplink) + hidden_uplink.trigger(user) diff --git a/maps/exodus-2.dmm b/maps/exodus-2.dmm index 89715d75d1c..41c60b2de09 100644 --- a/maps/exodus-2.dmm +++ b/maps/exodus-2.dmm @@ -1977,6 +1977,7 @@ "Ma" = (/obj/machinery/vending/cigarette{name = "hacked cigarette machine"; prices = list(); products = list(/obj/item/weapon/storage/fancy/cigarettes = 10, /obj/item/weapon/storage/box/matches = 10, /obj/item/weapon/flame/lighter/zippo = 4, /obj/item/clothing/mask/smokable/cigarette/cigar/havana = 2)},/turf/simulated/shuttle/floor{icon_state = "floor6"},/area/syndicate_station/start) "Mb" = (/obj/structure/bed/chair,/obj/effect/landmark{name = "CCIAAgent"},/turf/unsimulated/floor{icon_state = "floor"},/area/centcom/control) "Mc" = (/obj/machinery/suit_cycler/syndicate{locked = 0},/turf/simulated/shuttle/plating,/area/skipjack_station/start) +"Md" = (/obj/item/device/contract_uplink,/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/skipjack_station/start) "Mj" = (/turf/unsimulated/beach/sand{tag = "icon-desert"; icon_state = "desert"},/turf/unsimulated/beach/sand{tag = "icon-coconuts"; icon_state = "coconuts"},/area/centcom/holding) "Mk" = (/obj/structure/table/standard,/obj/item/weapon/FixOVein{pixel_x = -6; pixel_y = 1},/turf/unsimulated/floor{tag = "icon-whitecorner"; name = "plating"; icon_state = "whitecorner"},/area/centcom/holding) "Ml" = (/obj/structure/table/standard,/obj/item/weapon/retractor{pixel_x = 0; pixel_y = 6},/obj/item/weapon/scalpel,/turf/unsimulated/floor{dir = 2; icon_state = "whitehall"; tag = "icon-whitehall (SOUTHEAST)"},/area/centcom/holding) @@ -2234,7 +2235,7 @@ dCmumumumumumumumuaMaMaMaMaMlwKjKjlxaMaMaMlwaMaMaMaMaMlxaMaMaMlwKjKjlxaMaMaMaMmt dCmumumumumuaMaMaMaMaMaMaMaMlylDlClyaMaMaMlylFlGlGlGlHlyaMaMaMlylIlJlyaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMCNJULiLjKaLlLkEFEGEGEGEHEHEHEIEJLmELEMEHEHEHCNCNCNLnDVDVEwEPEQExERESCNaMaMaMaMaMaMaMETEVEVBVDYDZEaNtNsEAEVEVEWaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM dCmumumumumuaMaMaMaMaMaMaMaMlylLlKlyaMaMlwlylylNlMlPlOlylxaMaMlylQlRlyaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMCNJUJUJULlLWEZEZEZEZEZEHLXFbFcFdFeFfFgFbLXEHCNCNCNCNCNCNLYFiNqFkERESCNaMaMaMaMaMaMaMaMaMaMETATEUEUEUATEWaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM dCmumumumumuaMaMaMaMaMaMaMaMlylTlSlyaMaMlylylUlWlVlWlXlylyaMaMlylYlZlyaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMCNMjJULlLWEZEZEZEZEZEZEHFbFmFnFdFeFfFnFoFbEHMkMmMlMoMnCNDVFhFkDVDVEwFuaMaMaMaMaMaMaMaMaMaMaMETEVEVEVEWaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM -dCmumumumumuaMaMaMaMaMaMaMaMlymalylylylylymcmbmbmbmbmbmdlylylylylymelyaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMCNJULlLWEZEZEZEZEZEZEZEHFvFbFvFdFeFfFvFbFvEHFwDVDVDVDVMuDVDVDVDVDVFyFzaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM +dCmumumumumuaMaMaMaMaMaMaMaMlymalylylylylymcmbmbMdmbmbmdlylylylylymelyaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMCNJULlLWEZEZEZEZEZEZEZEHFvFbFvFdFeFfFvFbFvEHFwDVDVDVDVMuDVDVDVDVDVFyFzaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM dCmumumumumuaMaMaMaMaMaMaMaMlymgmfmjmhmllymmmbmbmbmbmbmmlymomnmqmpoTlyaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMCNLlLWEZEZEZEZEZEZEZEZEHFAFbFbFdFeFfFbFbFBEHFCFDFEFFMGCNDVDVDVDVDVMHFIaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM dCmumuaMaMaMaMaMaMaMaMaMaMaMlypvpspspspwlypNpEpPpOpNpEpPlyqBpspsqNpvlyaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMAHCNCNCNCNCNCNCNCNCNCNCNEHFJFKFKFdFeFfFLFLFMEHMTFOFPFQMUCNFSFTFUMWMVMXCNaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM dCmumuaMaMaMaMaMaMaMaMaMaMaMsUpvpspspspspOmbmbmbmbmbmbmbpOpspstEpspvsUaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMEHFeFeFeFeFeFeFeFeFeFeFeEHEHNbEHEHFeEHEHNbEHEHEHEHEHEHEHCNCNCNCNCNCNCNCNaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM From 610070184479e5b46731b22de531e99ff6baf0ac Mon Sep 17 00:00:00 2001 From: skull132 Date: Thu, 24 Mar 2016 02:08:05 +0200 Subject: [PATCH 28/31] Contract Uplink Fix The uplink is now spawned per raider, instead of being on the map. can't have it on the map as its init causes issues. --- code/game/antagonist/outsider/raider.dm | 3 ++- maps/exodus-2.dmm | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/game/antagonist/outsider/raider.dm b/code/game/antagonist/outsider/raider.dm index fcb0e1d2b73..42b481970a0 100644 --- a/code/game/antagonist/outsider/raider.dm +++ b/code/game/antagonist/outsider/raider.dm @@ -220,6 +220,8 @@ var/datum/antagonist/raider/raiders player.equip_to_slot_or_del(new new_suit(player),slot_wear_suit) equip_weapons(player) + player.equip_to_storage(new /obj/item/device/contract_uplink) + var/obj/item/weapon/card/id/id = create_id("Visitor", player, equip = 0) id.name = "[player.real_name]'s Passport" id.assignment = "Visitor" @@ -311,4 +313,3 @@ var/datum/antagonist/raider/raiders player.internals.icon_state = "internal1" return 1 - diff --git a/maps/exodus-2.dmm b/maps/exodus-2.dmm index 41c60b2de09..89715d75d1c 100644 --- a/maps/exodus-2.dmm +++ b/maps/exodus-2.dmm @@ -1977,7 +1977,6 @@ "Ma" = (/obj/machinery/vending/cigarette{name = "hacked cigarette machine"; prices = list(); products = list(/obj/item/weapon/storage/fancy/cigarettes = 10, /obj/item/weapon/storage/box/matches = 10, /obj/item/weapon/flame/lighter/zippo = 4, /obj/item/clothing/mask/smokable/cigarette/cigar/havana = 2)},/turf/simulated/shuttle/floor{icon_state = "floor6"},/area/syndicate_station/start) "Mb" = (/obj/structure/bed/chair,/obj/effect/landmark{name = "CCIAAgent"},/turf/unsimulated/floor{icon_state = "floor"},/area/centcom/control) "Mc" = (/obj/machinery/suit_cycler/syndicate{locked = 0},/turf/simulated/shuttle/plating,/area/skipjack_station/start) -"Md" = (/obj/item/device/contract_uplink,/turf/simulated/shuttle/floor{icon_state = "floor4"},/area/skipjack_station/start) "Mj" = (/turf/unsimulated/beach/sand{tag = "icon-desert"; icon_state = "desert"},/turf/unsimulated/beach/sand{tag = "icon-coconuts"; icon_state = "coconuts"},/area/centcom/holding) "Mk" = (/obj/structure/table/standard,/obj/item/weapon/FixOVein{pixel_x = -6; pixel_y = 1},/turf/unsimulated/floor{tag = "icon-whitecorner"; name = "plating"; icon_state = "whitecorner"},/area/centcom/holding) "Ml" = (/obj/structure/table/standard,/obj/item/weapon/retractor{pixel_x = 0; pixel_y = 6},/obj/item/weapon/scalpel,/turf/unsimulated/floor{dir = 2; icon_state = "whitehall"; tag = "icon-whitehall (SOUTHEAST)"},/area/centcom/holding) @@ -2235,7 +2234,7 @@ dCmumumumumumumumuaMaMaMaMaMlwKjKjlxaMaMaMlwaMaMaMaMaMlxaMaMaMlwKjKjlxaMaMaMaMmt dCmumumumumuaMaMaMaMaMaMaMaMlylDlClyaMaMaMlylFlGlGlGlHlyaMaMaMlylIlJlyaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMCNJULiLjKaLlLkEFEGEGEGEHEHEHEIEJLmELEMEHEHEHCNCNCNLnDVDVEwEPEQExERESCNaMaMaMaMaMaMaMETEVEVBVDYDZEaNtNsEAEVEVEWaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM dCmumumumumuaMaMaMaMaMaMaMaMlylLlKlyaMaMlwlylylNlMlPlOlylxaMaMlylQlRlyaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMCNJUJUJULlLWEZEZEZEZEZEHLXFbFcFdFeFfFgFbLXEHCNCNCNCNCNCNLYFiNqFkERESCNaMaMaMaMaMaMaMaMaMaMETATEUEUEUATEWaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM dCmumumumumuaMaMaMaMaMaMaMaMlylTlSlyaMaMlylylUlWlVlWlXlylyaMaMlylYlZlyaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMCNMjJULlLWEZEZEZEZEZEZEHFbFmFnFdFeFfFnFoFbEHMkMmMlMoMnCNDVFhFkDVDVEwFuaMaMaMaMaMaMaMaMaMaMaMETEVEVEVEWaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM -dCmumumumumuaMaMaMaMaMaMaMaMlymalylylylylymcmbmbMdmbmbmdlylylylylymelyaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMCNJULlLWEZEZEZEZEZEZEZEHFvFbFvFdFeFfFvFbFvEHFwDVDVDVDVMuDVDVDVDVDVFyFzaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM +dCmumumumumuaMaMaMaMaMaMaMaMlymalylylylylymcmbmbmbmbmbmdlylylylylymelyaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMCNJULlLWEZEZEZEZEZEZEZEHFvFbFvFdFeFfFvFbFvEHFwDVDVDVDVMuDVDVDVDVDVFyFzaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM dCmumumumumuaMaMaMaMaMaMaMaMlymgmfmjmhmllymmmbmbmbmbmbmmlymomnmqmpoTlyaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMCNLlLWEZEZEZEZEZEZEZEZEHFAFbFbFdFeFfFbFbFBEHFCFDFEFFMGCNDVDVDVDVDVMHFIaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM dCmumuaMaMaMaMaMaMaMaMaMaMaMlypvpspspspwlypNpEpPpOpNpEpPlyqBpspsqNpvlyaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMAHCNCNCNCNCNCNCNCNCNCNCNEHFJFKFKFdFeFfFLFLFMEHMTFOFPFQMUCNFSFTFUMWMVMXCNaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM dCmumuaMaMaMaMaMaMaMaMaMaMaMsUpvpspspspspOmbmbmbmbmbmbmbpOpspstEpspvsUaMaMaMaMmtaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMEHFeFeFeFeFeFeFeFeFeFeFeEHEHNbEHEHFeEHEHNbEHEHEHEHEHEHEHCNCNCNCNCNCNCNCNaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaMaM From 2855adee1e539c78bc0f6dc0cd3c85423dcbf9bf Mon Sep 17 00:00:00 2001 From: skull132 Date: Thu, 24 Mar 2016 20:44:53 +0200 Subject: [PATCH 29/31] The changelogging Log harder. --- html/changelogs/skull132-webinterface.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 html/changelogs/skull132-webinterface.yml diff --git a/html/changelogs/skull132-webinterface.yml b/html/changelogs/skull132-webinterface.yml new file mode 100644 index 00000000000..a7b6f19766f --- /dev/null +++ b/html/changelogs/skull132-webinterface.yml @@ -0,0 +1,8 @@ +author: Skull132 + +delete-after: True + +changes: + - rscadd: "Integrated the web interface with the game. Players can now create linking requests from the web interface, and accept them ingame. This will be used for more feature integration between the two later." + - rscadd: "Integrated the syndicate contract database with the game. Players can interact with contracts from the web interface (create new ones, post comments, report completion, etcetera), and review the contracts from syndicate uplinks. This means that antags with access to an uplink can now roleplay with contracts, fulfilling missions and so forth." + - rscadd: "Heisters now spawn with contract uplinks, which are effectively syndicate uplinks without the telecrystals, for checking up on the contracts database." From c1e179415883ba882a1b60d16984e03406daa931 Mon Sep 17 00:00:00 2001 From: skull132 Date: Thu, 24 Mar 2016 23:18:28 +0200 Subject: [PATCH 30/31] Config example catch-up --- config/example/config.txt | 40 +++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/config/example/config.txt b/config/example/config.txt index 7f94edde443..8653c533180 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -31,7 +31,7 @@ JOBS_HAVE_MINIMAL_ACCESS ## log OOC channel LOG_OOC -## log client Say +## log client Say LOG_SAY ## log admin actions @@ -93,7 +93,7 @@ MOD_JOB_TEMPBAN_MAX 1440 ## probablities for game modes chosen in "secret" and "random" modes -## +## ## default probablity is 1, increase to make that mode more likely to be picked ## set to 0 to disable that mode PROBABILITY EXTENDED 1 @@ -213,7 +213,7 @@ GUEST_BAN ##Remove the # mark infront of this to forbid admins from posssessing the singularity. #FORBID_SINGULO_POSSESSION -## Remove the # to show a popup 'reply to' window to every non-admin that recieves an adminPM. +## Remove the # to show a popup 'reply to' window to every non-admin that recieves an adminPM. ## The intention is to make adminPMs more visible. (although I fnd popups annoying so this defaults to off) #POPUP_ADMIN_PM @@ -255,21 +255,6 @@ USEALIENWHITELIST ## Password used for authorizing ircbot and other external tools. #COMMS_PASSWORD -## Uncomment to enable sending data to the IRC bot. -#USE_IRC_BOT - -## Uncomment if the IRC bot requires using world.Export() instead of nudge.py/libnudge -#IRC_BOT_EXPORT - -## Host where the IRC bot is hosted. Port 45678 needs to be open. -#IRC_BOT_HOST localhost - -## IRC channel to send information to. Leave blank to disable. -#MAIN_IRC #main - -## IRC channel to send adminhelps to. Leave blank to disable adminhelps-to-irc. -#ADMIN_IRC #admin - ## Path to the python2 executable on the system. Leave blank for default. ## Default is "python" on Windows, "/usr/bin/env python2" on UNIX. #PYTHON_PATH @@ -290,7 +275,7 @@ CHARACTER_SLOTS 10 ## Uncomment to use overmap system for zlevel travel #USE_OVERMAP -## Defines which Z-levels the station exists on. +## Defines which Z-levels the station exists on. STATION_LEVELS 1 ## Defines which Z-levels are used for admin functionality, such as Central Command and the Syndicate Shuttle @@ -369,4 +354,19 @@ STARLIGHT 0 #AGGRESSIVE_CHANGELOG ## Uncomment to override default brain health. -#DEFAULT_BRAIN_HEALTH 400 \ No newline at end of file +#DEFAULT_BRAIN_HEALTH 400 + +## Uncomment this to house whitelists on the SQL database. +# SQL_WHITELISTS + +## Uncomment this to use the discord bot. +# USE_DISCORD_BOT + +## The host address of the discord bot. +# DISCORD_BOT_HOST + +## The port number which the discord bot is listening for nudges. +# DISCORD_BOT_PORT + +## Uncomment this and fill in the web interface's URL to use the web interface. +# WEBINT_URL http://www.address.com/ From c709b8b927c86b2d34f0c7cab53a506f41f09991 Mon Sep 17 00:00:00 2001 From: skull132 Date: Fri, 25 Mar 2016 00:27:01 +0200 Subject: [PATCH 31/31] Fixing contract uplink spawn --- code/game/antagonist/outsider/raider.dm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/code/game/antagonist/outsider/raider.dm b/code/game/antagonist/outsider/raider.dm index 42b481970a0..1e4a481e4dc 100644 --- a/code/game/antagonist/outsider/raider.dm +++ b/code/game/antagonist/outsider/raider.dm @@ -220,7 +220,10 @@ var/datum/antagonist/raider/raiders player.equip_to_slot_or_del(new new_suit(player),slot_wear_suit) equip_weapons(player) - player.equip_to_storage(new /obj/item/device/contract_uplink) + //Try to equip it, del if we fail. + var/obj/item/device/contract_uplink/new_uplink = new() + if (!player.equip_to_appropriate_slot(new_uplink)) + qdel(new_uplink) var/obj/item/weapon/card/id/id = create_id("Visitor", player, equip = 0) id.name = "[player.real_name]'s Passport"