Files

316 lines
9.3 KiB
Plaintext

/**
* Client datum
*
* A datum that is created whenever a user joins a BYOND world, one will exist for every active connected
* player
*
* when they first connect, this client object is created and [/client/New] is called
*
* When they disconnect, this client object is deleted and [/client/Del] is called
*
* All client topic calls go through [/client/Topic] first, so a lot of our specialised
* topic handling starts here
*/
/client
/**
* This line makes clients parent type be a datum
*
* By default in byond if you define a proc on datums, that proc will exist on nearly every single type
* from icons to images to atoms to mobs to objs to turfs to areas, it won't however, appear on client
*
* instead by default they act like their own independent type so while you can do istype(icon, /datum)
* and have it return true, you can't do istype(client, /datum), it will always return false.
*
* This makes writing oo code hard, when you have to consider this extra special case
*
* This line prevents that, and has never appeared to cause any ill effects, while saving us an extra
* pain to think about
*
* This line is widely considdered black fucking magic, and the fact it works is a puzzle to everyone
* involved, including the current engine developer, lummox
*
* If you are a future developer and the engine source is now available and you can explain why this
* is the way it is, please do update this comment
*/
parent_type = /datum
show_verb_panel = FALSE
//? Intrinsics
/// did New() finish?
var/initialized = FALSE
/// Persistent round-by-round data holder
var/datum/client_data/persistent
/// Database data
var/datum/player_data/player
//? Connection
/// queued client security kick
var/queued_security_kick
/// currently age gate blocked
var/age_verification_open = FALSE
/// panic bunker is still resolving
var/panic_bunker_pending = FALSE
//* Actions *//
/// our action holder
var/datum/action_holder/action_holder
//* Context Menus *//
/// open context menu
var/datum/radial_menu/context_menu/context_menu
//* HUDs *//
/// active atom HUD providers associated to a list of ids or paths of atom huds that's providing it.
var/list/datum/atom_hud_provider/atom_hud_providers
//? Rendering
/// Click catcher
var/atom/movable/screen/click_catcher/click_catcher
/// Parallax holder
var/datum/parallax_holder/parallax_holder
/// the perspective we're currently using
var/datum/perspective/using_perspective
/// Client global planes
var/datum/plane_holder/client_global/global_planes
//? Viewport
/// what we *think* their current viewport size is in pixels
var/assumed_viewport_spx
/// what we *think* their current viewport size is in pixels
var/assumed_viewport_spy
/// what we *think* their current viewport zoom is
var/assumed_viewport_zoom
/// what we *think* their current viewport letterboxing setting is
var/assumed_viewport_box
/// current view x - for fast access
/// * This is in tiles.
var/current_viewport_width
/// current view y - for fast access
/// * This is in tiles.
var/current_viewport_height
/// if things are manipulating the viewport we don't want other things to touch it
var/viewport_rwlock = TRUE //? default block so we can release it during init_viewport
/// viewport update queued?
var/viewport_queued = FALSE
/// forced temporary view
var/temporary_viewsize_width
/// forced temporary view
var/temporary_viewsize_height
/// temporary view active?
var/using_temporary_viewsize = FALSE
//? Datum Menus
/// menu button statuses
var/list/menu_buttons_checked = list()
/// menu group statuses
var/list/menu_group_status = list()
//? Preferences
/// client preferences
var/datum/game_preferences/preferences
//? Throttling
/// block re-execution of expensive verbs
var/verb_throttle = 0
//? Cutscenes
/// active cutscene
var/datum/cutscene/cutscene
/// is the cutscene browser in use?
var/cutscene_browser = FALSE
/// is the cutscene system init'd?
var/cutscene_init = FALSE
/// is the cutscene browser ready?
var/cutscene_ready = FALSE
/// cutscene lockout: set after a browser synchronization command to delay the next one
/// since byond is deranged and will send winsets and browse calls out of order sometimes.
var/cutscene_lockout = FALSE
//* Mouse *//
/// updated by MouseMove()
var/mouse_control_last
/// updated by MouseMove()
var/mouse_params_last
/// updated by MouseMove()
var/list/mouse_params_last_unpacked
/// updated by atom/MouseEntered, atom/MouseExited
var/atom/mouse_predicted_last_atom
//* UI - Client *//
/// our tooltips system
var/datum/tooltip/tooltips
/// statpanel
var/datum/client_statpanel/tgui_stat
// todo: just have a client panel, don't make this separate
var/datum/client_view_playtime/legacy_playtime_viewer
//* UI - Map *//
/// Our action drawer
var/datum/action_drawer/action_drawer
/// Our actor HUD holder
var/datum/actor_hud_holder/actor_huds
//* Upload *//
/// currently prompting for upload
VAR_PRIVATE/upload_mutex = FALSE
/// How many things are waiting for upload?
VAR_PRIVATE/upload_mutex_waiting = 0
/// current upload prompt's max file size
VAR_PRIVATE/upload_current_sizelimit
////////////////
//ADMIN THINGS//
////////////////
///Contains admin info. Null if client is not an admin.
var/datum/admins/holder = null
var/datum/admins/deadmin_holder = null
var/buildmode = 0
///Used for admin AI interaction
var/AI_Interact = FALSE
///Contains the last message sent by this client - used to protect against copy-paste spamming.
var/last_message = ""
///contins a number of how many times a message identical to last_message was sent.
var/last_message_count = 0
///Internal counter for clients sending irc relay messages via ahelp to prevent spamming. Set to a number every time an admin reply is sent, decremented for every client send.
var/ircreplyamount = 0
/////////
//OTHER//
/////////
// todo: rename to `preferences` & put it next to `persistent` to sate my OCD ~silicons
///Player preferences datum for the client
var/datum/preferences/prefs = null
///when the client last died as a mouse
var/time_died_as_mouse = null
///////////////
//SOUND STUFF//
///////////////
/// world.time when ambience was played to this client, to space out ambience sounds.
var/time_last_ambience_played = 0
////////////
//SECURITY//
////////////
var/received_irc_pm = -99999
///IRC admin that spoke with them last.
var/irc_admin
var/mute_irc = 0
////////////////////////////////////
//things that require the database//
////////////////////////////////////
preload_rsc = PRELOAD_RSC
///Last ping of the client
var/lastping = 0
///Average ping of the client
var/avgping = 0
///Used for limiting the rate of topic sends by the client to avoid abuse
var/list/topiclimiter
///Used for limiting the rate of clicks sends by the client to avoid abuse
var/list/clicklimiter
///world.time they connected
var/connection_time
///world.realtime they connected
var/connection_realtime
///world.timeofday they connected
var/connection_timeofday
/client/vv_edit_var(var_name, var_value)
switch (var_name)
if (NAMEOF(src, holder))
return FALSE
if (NAMEOF(src, ckey))
return FALSE
if (NAMEOF(src, key))
return FALSE
if(NAMEOF(src, view))
change_view(var_value, TRUE)
return TRUE
return ..()
//* Is-rank helpers *//
/**
* are we a guest account?
*/
/client/proc/is_guest()
return IsGuestKey(key)
/**
* are we localhost?
*/
/client/proc/is_localhost()
return isnull(address) || (address in list("127.0.0.1", "::1"))
/**
* are we any sort of staff rank?
*/
/client/proc/is_staff()
return !isnull(holder)
//* Atom HUDs *//
/client/proc/add_atom_hud(datum/atom_hud/hud, source)
ASSERT(istext(source))
if(isnull(atom_hud_providers))
atom_hud_providers = list()
var/list/datum/atom_hud_provider/providers = hud.resolve_providers()
for(var/datum/atom_hud_provider/provider as anything in providers)
var/already_there = atom_hud_providers[provider]
if(already_there)
atom_hud_providers[provider] |= source
else
atom_hud_providers[provider] = list(source)
provider.add_client(src)
/client/proc/remove_atom_hud(datum/atom_hud/hud, source)
ASSERT(istext(source))
if(!length(atom_hud_providers))
return
if(!hud)
// remove all of source
for(var/datum/atom_hud_provider/provider as anything in atom_hud_providers)
if(!(source in atom_hud_providers[provider]))
continue
atom_hud_providers[provider] -= source
if(!length(atom_hud_providers[provider]))
atom_hud_providers -= provider
provider.remove_client(src)
return
hud = fetch_atom_hud(hud)
var/list/datum/atom_hud_provider/providers = hud.resolve_providers()
for(var/datum/atom_hud_provider/provider as anything in providers)
if(!length(atom_hud_providers[provider]))
continue
atom_hud_providers[provider] -= source
if(!length(atom_hud_providers[provider]))
atom_hud_providers -= provider
provider.remove_client(src)
// todo: add_atom_hud_provider, remove_atom_hud_provider
/client/proc/clear_atom_hud_providers()
for(var/datum/atom_hud_provider/provider as anything in atom_hud_providers)
provider.remove_client(src)
atom_hud_providers = null
//* Transfer *//
/**
* transfers us to a mob
*
* **never directly set ckey on a client or mob!**
*/
/client/proc/transfer_to(mob/moving_to)
var/mob/moving_from = mob
return moving_from.transfer_client_to(moving_to)