mirror of
https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
synced 2026-08-18 13:16:38 +01:00
316 lines
9.3 KiB
Plaintext
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)
|