From b9e154e50bde9511d434e5a80bdbbc273e4dafe7 Mon Sep 17 00:00:00 2001 From: Jackz Date: Fri, 11 Nov 2022 11:05:46 -0600 Subject: [PATCH] Minor tweaks --- plugins/l4d2-info-cmd.smx | Bin 8089 -> 8092 bytes plugins/l4d2_detections.smx | Bin 9675 -> 9675 bytes scripting/include/netprops.inc | 127 +++++++ scripting/include/socket.inc | 668 +++++++++++++++++++++++++++++++++ scripting/include/tentdev.inc | 95 +++++ scripting/l4d2-info-cmd.sp | 2 + scripting/l4d2_detections.sp | 4 +- 7 files changed, 894 insertions(+), 2 deletions(-) create mode 100644 scripting/include/netprops.inc create mode 100644 scripting/include/socket.inc create mode 100644 scripting/include/tentdev.inc diff --git a/plugins/l4d2-info-cmd.smx b/plugins/l4d2-info-cmd.smx index e8e737a35784281daef4cb49342823afa87360d3..c898c5c25e9921e52c700a4555cec60051564a4a 100644 GIT binary patch delta 7460 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 iq*lc!A@>L}V|Fe;<*o z_feQdAx@#0!qY;tHQEsa?WBQr)-+9d<+nt^uHKnvCyY$*e+%Rt*pm| z5Ghm6)8b=VlE*9i)*ElU5tRD(Q&^96vaXmmy@XcKd9(fcr)z!qgw&zdx!Hbvg@)g( z<*k+ay>e|W-Fz+Hr{$R;{FlqKP>b)MVxC1>Joy GhaEd$jnee<|i!ti{h6@`UvM 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 diff --git a/plugins/l4d2_detections.smx b/plugins/l4d2_detections.smx index 2a88a155072818f2d12b4457c8779cd0e91786ea..8864c789b43d08b196323bdf46df292472841b29 100644 GIT binary patch delta 9430 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 F{{sTay;}eP delta 9446 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 w%K5ikPv>{;ULbD?Upnm + +enum SocketType { + SOCKET_TCP = 1, + SOCKET_UDP, + SOCKET_RAW +} + +enum { + EMPTY_HOST = 1, + NO_HOST, + CONNECT_ERROR, + SEND_ERROR, + BIND_ERROR, + RECV_ERROR, + LISTEN_ERROR +} + + +/*************************************************************************************************/ +/******************************************** options ********************************************/ +/*************************************************************************************************/ + + +/** + * Options available for SocketSetOption() + * + * @note modifying these options is not required for normal operation, you can skip the whole + * section in most cases. + */ +enum SocketOption { +/** + * If this option is set the socket extension will try to concatenate SocketReceive callbacks. + * + * This will possibly lower the amount of callbacks passed to SourceMod plugins and improve the + * performance. The socket extension will preserve the packet order. + * + * @note this doesn't prevent multiple callbacks, it only reduces them for high load. + * @note this will not truncate packets below 4096 bytes, setting it lower will be ignored + * @note set this option if you expect lots of data in a short timeframe + * @note don't forget to set your buffer sizes at least to the value passed to this function, but + * always at least to 4096 + * + * @param int 0(=default) to disable or max. chunk size including \0 terminator in bytes + * @return bool true on success + */ + ConcatenateCallbacks = 1, +/** + * If this option is set the socket extension will enforce a mutex lock in the GameFrame() hook. + * + * This will ensure that callbacks will be processed every gameframe as fast as possible with the + * drawback of potentially creating lag. It's not recommended to set this option for most cases. + * If this option is not set the gameframe will be skipped if quietly obtaining a lock fails. + * + * @note combine this with CallbacksPerFrame for best performance + * @note this option will affect all sockets from all plugins, use it with caution! + * + * @param bool whether to force locking or not + * @return bool true on success + */ + ForceFrameLock, +/** + * This will specify the maximum amount of callbacks processed in every gameframe. + * + * The default value for this option is 1, setting it higher will possibly increase networking + * performance but may cause lag if it's set too high. + * The amount of callbacks actually being processed is limited by not being able to quietly obtain + * a lock (see ForceFrameLock) and the amount of callbacks in the queue. + * + * @note this option will affect all sockets from all plugins, use it with caution! + * + * @param int maximum amount of callbacks per gameframe + * @return bool true on success + */ + CallbacksPerFrame, +/** + * If this option is set the socket will be allowed to send broadcast messages in case the protocol + * supports it. This is a wrapper for setting SO_BROADCAST. + * + * @param bool whether to allow broadcasting or not + * @return bool true on success + */ + SocketBroadcast, +/** + * If this option is set SocketBind() will allow reusing local adresses in case the protocol + * supports it. This is a wrapper for setting SO_REUSEADDR. + * + * @param bool whether to allow broadcasting or not + * @return bool true on success + */ + SocketReuseAddr, +/** + * If this option is set the socket will try to keep the connection alive by periodically sending + * messages if the protocol supports it. This is a wrapper for setting SO_KEEPALIVE. + * + * @param bool whether to allow broadcasting or not + * @return bool true on success + */ + SocketKeepAlive, +/** + * This option specifies how long a socket will wait if it's being closed and its send buffer is + * still filled. This is a wrapper for setting SO_LINGER. + * + * @param int 0 (=default) to disable or time in s + * @return bool true on success + */ + SocketLinger, +/** + * If this option is set out-of-band data will be inlined into the normal receive stream. This is a + * wrapper for setting SO_OOBINLINE. + * + * @param bool whether to inline out-of-band data or not + * @return bool true on success + */ + SocketOOBInline, +/** + * This option specifies how large the send buffer will be. This is a wrapper for setting + * SO_SNDBUF. + * + * @param int size in bytes + * @return bool true on success + */ + SocketSendBuffer, +/** + * This option specifies how large the receive buffer will be. This is a wrapper for setting + * SO_RCVBUF. + * + * @param int size in bytes + * @return bool true on success + */ + SocketReceiveBuffer, +/** + * If this option is set outgoing messages will ignore the default routing facilities if the + * protocol implementation supports it. The remote site should be directly connected to the sender. + * This is a wrapper for setting SO_DONTROUTE. + * + * @param bool whether to skip default routing or not + * @return bool true on success + */ + SocketDontRoute, +/** + * This option specifies the minimum amount of data to receive before processing it. This is a + * wrapper for setting SO_RCVLOWAT. + * + * @note this can probably block the extension, use it with caution! + * + * @param int size in bytes + * @return bool true on success + */ + SocketReceiveLowWatermark, +/** + * This option specifies how long a socket will try to receive data before it times out and + * processes the data. This is a wrapper for setting SO_RCVTIMEO. + * + * @param int 0 (=default) to disable or time in ms + * @return bool true on success + */ + SocketReceiveTimeout, +/** + * This option specifies the minimum amount of data required in the send buffer before starting to + * send it. This is a wrapper for setting SO_SNDLOWAT. + * + * @note this can probably block the extension, use it with caution! + * + * @param int size in bytes + * @return bool true on success + */ + SocketSendLowWatermark, +/** + * This option specifies how long a socket will try to send data before it times out and + * retries it later. This is a wrapper for setting SO_SNDTIMEO. + * + * @param int 0 (=default) to disable or time in ms + * @return bool true on success + */ + SocketSendTimeout, +/** + * If this option is set the socket extension will display debugging messages in the server console/logs. + * + * @param bool whether to enable debugging or not + * @return bool true on success + */ + DebugMode +} + +// Methodmap +methodmap Socket < Handle { + /** + * Creates a new socket. + * + * @note this function may be relatively expensive, reuse sockets if possible + * + * @param SocketType protocol The protocol to use, SOCKET_TCP is default + * @param SocketErrorCB efunc The error callback + * @return Handle The socket handle. Returns INVALID_HANDLE on failure + */ + public native Socket(SocketType protocol=SOCKET_TCP, SocketErrorCB efunc); + + /** + * Binds the socket to a local address + * + * @param String hostname The hostname (or IP) to bind the socket to. + * @param int port The port to bind the socket to. + * @return bool true on success + */ + public native bool Bind(const char[] hostname, int port); + + /** + * Connects a socket + * + * @note this native is threaded, it may be still running after it executed, use the connect callback + * @note invokes the SocketError callback with errorType = CONNECT_ERROR or EMPTY_HOST if it fails + * @note invokes the SocketConnect callback if it succeeds + * + * @param SocketConnectCB cfunc The connect callback + * @param SocketReceiveCB rfunc The receive callback + * @param SocketDisconnectCB dfunc The disconnect callback + * @param String hostname The hostname (or IP) to connect to. + * @param int port The port to connect to. + */ + public native void Connect(SocketConnectCB cfunc, SocketReceiveCB rfunc, SocketDisconnectCB dfunc, const char[] hostname, int port); + + /** + * Disconnects a socket + * + * @note this will not close the handle, the socket will be reset to a state similar to after SocketCreate() + * @note this won't trigger any disconnect/error callbacks + * + * @return bool true on success + */ + public native bool Disconnect(); + + /** + * Makes a socket listen for incoming connections + * + * @param SocketIncomingCB ifunc The callback for incoming connections + * @return bool true on success + */ + public native bool Listen(SocketIncomingCB ifunc); + + /** + * Sends data through the socket. + * + * @note specify size for binary safe operation + * @note if size is not specified the \0 terminator will not be included + * @note This native is threaded, it may be still running after it executed (not atomic). + * @note Use the SendqueueEmpty callback to determine when all data has been successfully sent. + * @note The socket extension will ensure that the data will be send in the correct order and split + * the data if required. + * + * @param String data The data to send. + */ + public native void Send(const char[] data, int size = -1); + + /** + * Sends UDP data through the socket to a specific destination. + * + * @note specify size for binary safe operation + * @note if size is not specified the \0 terminator will not be included + * @note This native is threaded, it may be still running after it executed (not atomic). + * @note Use the SendqueueEmpty callback to determine when all data has been successfully sent. + * @note The socket extension will ensure that the data will be send in the correct order and split + * the data if required. + * + * @param String data The data to send. + * @param String hostname The hostname (or IP) to send to. + * @param int port The port to send to. + */ + public native void SendTo(const char[] data, int size = -1, const char[] hostname, int port); + + /** + * Set a socket option. + * + * @param SocketOption option The option to modify (see enum SocketOption for details). + * @param int value The value to set the option to. + * @return int 1 on success. + */ + public native int SetOption(SocketOption option, int value); + + /** + * Defines the callback function for when the socket receives data + * + * @note this is only useful and required for child-sockets spawned by listen-sockets + * (otherwise you already set it in SocketConnect()) + * + * @param SocketReceiveCB rfunc The receive callback + */ + public native void SetReceiveCallback(SocketReceiveCB rfunc); + + /** + * Defines the callback function for when the socket sent all items in its send queue + * + * @note this must be called AFTER sending (queueing) the data + * @note if no send-data is queued this will fire the callback itself + * @note the callback is guaranteed to fire + * + * @param SocketDisconnectCB dfunc The disconnect callback + */ + public native void SetSendqueueEmptyCallback(SocketSendqueueEmptyCB sfunc); + + /** + * Defines the callback function for when the socket was properly disconnected by the remote side + * + * @note this is only useful and required for child-sockets spawned by listen-sockets + * (otherwise you already set it in SocketConnect()) + * + * @param SocketDisconnectCB dfunc The disconnect callback + */ + public native void SetDisconnectCallback(SocketDisconnectCB dfunc); + + /** + * Defines the callback function for when the socket triggered an error + * + * @note this is only useful and required for child-sockets spawned by listen-sockets + * (otherwise you already set it in SocketCreate()) + * + * @param SocketErrorCB efunc The error callback + */ + public native void SetErrorCallback(SocketErrorCB efunc); + + /** + * Sets the argument being passed to callbacks + * + * @param any arg The argument to set + */ + public native void SetArg(any arg); + + /** + * Retrieve the local system's hostname as the command "hostname" does. + * + * @param dest Destination string buffer to copy to. + * @param destLen Destination buffer length (includes null terminator). + * + * @return 1 on success + */ + public static native int GetHostName(char[] dest, int destLen); + + /** + * Returns whether a socket is connected or not. + * + * @return bool The connection status + */ + property bool Connected { + public native get(); + } +} + + +/*************************************************************************************************/ +/******************************************* callbacks *******************************************/ +/*************************************************************************************************/ + +/** + * triggered if a normal sockets finished connecting and is ready to be used + * + * @param socket The socket handle pointing to the calling socket + * @param arg The argument set by SocketSetArg() + * @noreturn + */ +typedef SocketConnectCB = function void (Socket socket, any arg); + +/** + * triggered if a listening socket received an incoming connection and is ready to be used + * + * @note The child-socket won't work until receive-, disconnect-, and errorcallback for it are set. + * + * @param Socket socket The socket handle pointing to the calling listen-socket + * @param Socket newSocket The socket handle to the newly spawned child socket + * @param String remoteIP The remote IP + * @param any arg The argument set by SocketSetArg() for the listen-socket + * @noreturn + */ +typedef SocketIncomingCB = function void (Socket socket, Socket newSocket, const char[] remoteIP, int remotePort, any arg); + +/** + * triggered if a socket receives data + * + * @note This is binary safe if you always use dataSize for operations on receiveData[] + * @note packets may be split up into multiple chunks -> multiple calls to the receive callback + * @note if not set otherwise by SocketSetOption(..., ConcatenateCallbacks, ...) receiveData will + * never be longer than 4096 characters including \0 terminator + * + * @param Socket socket The socket handle pointing to the calling socket + * @param String receiveData The data which arrived, 0-terminated at receiveData[dataSize] + * @param int dataSize The length of the arrived data excluding the 0-termination + * @param any arg The argument set by SocketSetArg() for the socket + * @noreturn + */ +typedef SocketReceiveCB = function void (Socket socket, const char[] receiveData, const int dataSize, any arg); + +/** + * called after a socket sent all items in its send queue successfully + * + * @param Socket socket The socket handle pointing to the calling socket + * @param any arg The argument set by SocketSetArg() for the socket + * @noreturn + */ +typedef SocketSendqueueEmptyCB = function void (Socket socket, any arg); + +/** + * called if a socket has been properly disconnected by the remote side + * + * @note You should call CloseHandle(socket) or reuse the socket before this function ends + * + * @param Socket socket The socket handle pointing to the calling socket + * @param any arg The argument set by SocketSetArg() for the socket + * @noreturn + */ +typedef SocketDisconnectCB = function void (Socket socket, any arg); + +/** + * called if an unrecoverable error occured, close the socket without an additional call to a disconnect callback + * + * @note You should call CloseHandle(socket) or reuse the socket before this function ends + * + * @param Socket socket The socket handle pointing to the calling socket + * @param int errorType The error type, see defines above + * @param int errorNum The errno, see errno.h for details + * @param any arg The argument set by SocketSetArg() for the socket + * @noreturn + */ +typedef SocketErrorCB = function void (Socket socket, const int errorType, const int errorNum, any arg); + +/*************************************************************************************************/ +/******************************************** natives ********************************************/ +/*************************************************************************************************/ + + +/** + * Returns whether a socket is connected or not. + * + * @param socket Socket handle to check + * @return bool The connection status + */ +native bool SocketIsConnected(Handle socket); + + +/** + * Creates a new socket. + * + * @note this function may be relatively expensive, reuse sockets if possible + * + * @param SocketType protocol The protocol to use, SOCKET_TCP is default + * @param SocketErrorCB efunc The error callback + * @return Socket The socket handle. Returns INVALID_HANDLE on failure + */ +native Socket SocketCreate(SocketType protocol=SOCKET_TCP, SocketErrorCB efunc); + +/** + * Binds the socket to a local address + * + * @param Handle socket The handle of the socket to be used. + * @param String hostname The hostname (or IP) to bind the socket to. + * @param int port The port to bind the socket to. + * @return bool true on success + */ +native bool SocketBind(Handle socket, const char[] hostname, int port); + +/** + * Connects a socket + * + * @note this native is threaded, it may be still running after it executed, use the connect callback + * @note invokes the SocketError callback with errorType = CONNECT_ERROR or EMPTY_HOST if it fails + * @note invokes the SocketConnect callback if it succeeds + * + * @param Handle socket The handle of the socket to be used. + * @param SocketConnectCB cfunc The connect callback + * @param SocketReceiveCB rfunc The receive callback + * @param SocketDisconnectCB dfunc The disconnect callback + * @param String hostname The hostname (or IP) to connect to. + * @param int port The port to connect to. + * @noreturn + */ +native void SocketConnect(Handle socket, SocketConnectCB cfunc, SocketReceiveCB rfunc, SocketDisconnectCB dfunc, const char[] hostname, int port); + +/** + * Disconnects a socket + * + * @note this will not close the handle, the socket will be reset to a state similar to after SocketCreate() + * @note this won't trigger any disconnect/error callbacks + * + * @noreturn + */ +native bool SocketDisconnect(Handle socket); + +/** + * Makes a socket listen for incoming connections + * + * @param Handle socket The handle of the socket to be used. + * @param SocketIncomingCB ifunc The callback for incoming connections + * @return bool true on success + */ +native bool SocketListen(Handle socket, SocketIncomingCB ifunc); + +/** + * Sends data through the socket. + * + * @note specify size for binary safe operation + * @note if size is not specified the \0 terminator will not be included + * @note This native is threaded, it may be still running after it executed (not atomic). + * @note Use the SendqueueEmpty callback to determine when all data has been successfully sent. + * @note The socket extension will ensure that the data will be send in the correct order and split + * the data if required. + * + * @param Handle socket The handle of the socket to be used. + * @param String data The data to send. + * @noreturn + */ +native void SocketSend(Handle socket, const char[] data, int size=-1); + +/** + * Sends UDP data through the socket to a specific destination. + * + * @note specify size for binary safe operation + * @note if size is not specified the \0 terminator will not be included + * @note This native is threaded, it may be still running after it executed (not atomic). + * @note Use the SendqueueEmpty callback to determine when all data has been successfully sent. + * @note The socket extension will ensure that the data will be send in the correct order and split + * the data if required. + * + * @param Handle socket The handle of the socket to be used. + * @param String data The data to send. + * @param String hostname The hostname (or IP) to send to. + * @param int port The port to send to. + * @noreturn + */ +native void SocketSendTo(Handle socket, const char[] data, int size=-1, const char[] hostname, int port); + +/** + * Set a socket option. + * + * @param Handle socket The handle of the socket to be used. May be INVALID_HANDLE if not essential. + * @param SocketOption option The option to modify (see enum SocketOption for details). + * @param cellt_ value The value to set the option to. + * @return int 1 on success. + */ +native int SocketSetOption(Handle socket, SocketOption option, int value); + + +/** + * Defines the callback function for when the socket receives data + * + * @note this is only useful and required for child-sockets spawned by listen-sockets + * (otherwise you already set it in SocketConnect()) + * + * @param Handle socket The handle of the socket to be used. + * @param SocketReceiveCB rfunc The receive callback + * @noreturn + */ +native void SocketSetReceiveCallback(Handle socket, SocketReceiveCB rfunc); + +/** + * Defines the callback function for when the socket sent all items in its send queue + * + * @note this must be called AFTER sending (queueing) the data + * @note if no send-data is queued this will fire the callback itself + * @note the callback is guaranteed to fire + * + * @param Handle socket The handle of the socket to be used. + * @param SocketDisconnectCB dfunc The disconnect callback + * @noreturn + */ +native void SocketSetSendqueueEmptyCallback(Handle socket, SocketSendqueueEmptyCB sfunc); + +/** + * Defines the callback function for when the socket was properly disconnected by the remote side + * + * @note this is only useful and required for child-sockets spawned by listen-sockets + * (otherwise you already set it in SocketConnect()) + * + * @param Handle socket The handle of the socket to be used. + * @param SocketDisconnectCB dfunc The disconnect callback + * @noreturn + */ +native void SocketSetDisconnectCallback(Handle socket, SocketDisconnectCB dfunc); + +/** + * Defines the callback function for when the socket triggered an error + * + * @note this is only useful and required for child-sockets spawned by listen-sockets + * (otherwise you already set it in SocketCreate()) + * + * @param Handle socket The handle of the socket to be used. + * @param SocketErrorCB efunc The error callback + * @noreturn + */ +native void SocketSetErrorCallback(Handle socket, SocketErrorCB efunc); + + +/** + * Sets the argument being passed to callbacks + * + * @param Handle socket The handle of the socket to be used. + * @param any arg The argument to set + * @noreturn + */ +native void SocketSetArg(Handle socket, any arg); + +/** + * Retrieve the local system's hostname as the command "hostname" does. + * + * @param dest Destination string buffer to copy to. + * @param destLen Destination buffer length (includes null terminator). + * + * @return 1 on success + */ +native int SocketGetHostName(char[] dest, int destLen); + +/** + * _________________Do not edit below this line!_______________________ + */ +public Extension __ext_socket = +{ + name = "Socket", + file = "socket.ext", +#if defined AUTOLOAD_EXTENSIONS + autoload = 1, +#else + autoload = 0, +#endif +#if defined REQUIRE_EXTENSIONS + required = 1, +#else + required = 0, +#endif +}; + +#if !defined REQUIRE_EXTENSIONS +public void __ext_socket_SetNTVOptional() +{ + MarkNativeAsOptional("Socket.Socket"); + MarkNativeAsOptional("Socket.Bind"); + MarkNativeAsOptional("Socket.Connect"); + MarkNativeAsOptional("Socket.Disconnect"); + MarkNativeAsOptional("Socket.Listen"); + MarkNativeAsOptional("Socket.Send"); + MarkNativeAsOptional("Socket.SendTo"); + MarkNativeAsOptional("Socket.SetOption"); + MarkNativeAsOptional("Socket.SetReceiveCallback"); + MarkNativeAsOptional("Socket.SetSendqueueEmptyCallback"); + MarkNativeAsOptional("Socket.SetDisconnectCallback"); + MarkNativeAsOptional("Socket.SetErrorCallback"); + MarkNativeAsOptional("Socket.SetArg"); + MarkNativeAsOptional("Socket.GetHostName"); + MarkNativeAsOptional("Socket.Connected.get"); + MarkNativeAsOptional("SocketIsConnected"); + MarkNativeAsOptional("SocketCreate"); + MarkNativeAsOptional("SocketBind"); + MarkNativeAsOptional("SocketConnect"); + MarkNativeAsOptional("SocketDisconnect"); + MarkNativeAsOptional("SocketListen"); + MarkNativeAsOptional("SocketSend"); + MarkNativeAsOptional("SocketSendTo"); + MarkNativeAsOptional("SocketSetOption"); + MarkNativeAsOptional("SocketSetReceiveCallback"); + MarkNativeAsOptional("SocketSetSendqueueEmptyCallback"); + MarkNativeAsOptional("SocketSetDisconnectCallback"); + MarkNativeAsOptional("SocketSetErrorCallback"); + MarkNativeAsOptional("SocketSetArg"); + MarkNativeAsOptional("SocketGetHostName"); +} +#endif diff --git a/scripting/include/tentdev.inc b/scripting/include/tentdev.inc new file mode 100644 index 0000000..1c9d1bf --- /dev/null +++ b/scripting/include/tentdev.inc @@ -0,0 +1,95 @@ +#if defined _ted_included_ + #endinput +#endif +#define _ted_included_ + +#define VERSION "0.1.1" + + +/** + * Sets the value of a netprop. + * + * @param client Client with a selected entity. + * @param sNetprop Netprop name. + * @param sValue Value to set the netprop to. + * @return True on success. + */ +native TED_SetNetprop(client, const String:sNetprop[], const String:sValue[]); + +/** + * Sets the selected entity for a client. + * + * @param client Client to select the entity + * @param sNetprop Entity index + * @return True on success. + */ +native TED_SelectEntity(client, entity); + +/** + * Adds a netprop to the ignore list of a specific client. + * The client is being notified through TED_OnNetpropHint(). + * + * @param client This clients ignore list will be changed. + * @param sNetprop Name of the netprop to be ignored, e.g. m_iHealth + * @return True on success. + */ +native TED_IgnoreNetprop(client, const String:sNetprop[]); + +/** + * Removes a netprop from the ignore list of a specific client + * The client is being notified through TED_OnNetpropHint(). + * + * @param client This clients ignore list will be changed. + * @param sNetprop Name of the netprop to be removed from the list + * @return True on success. + */ +native TED_UnignoreNetprop(client, const String:sNetprop[]); + +/** + * Shows all netprops and their values for the selected entity + * This will feed all information through TED_OnShow(). + * + * @param client The client issuing the action. He will see the output. + * @return True on success. + */ +native TED_ShowNetprops(client); + +/** + * Repeatedly shows all changed netprops for the selected entity + * This will feed all information through TED_OnCompare(). + * + * @param client The client issuing the action. He will see the output. + * @return True on success. + */ +native TED_WatchNetprops(client); + +/** + * Stops watching a entity + * + * @param client The client issuing the action. He will see the output. + * @return True on success. + */ +native TED_StopWatchNetprops(client); + +/** + * Saves the current state of netprops for later manual comparison. + * + * @param client The client issuing the action. + * @return True on success. + */ +native TED_SaveNetprops(client); + +/** + * Compares the current state of netprops with the saved state and outputs any differences. + * This will feed all information through TED_OnCompare(). + * + * @param client The client issuing the action. He will see the output. + * @return True on success. + */ +native TED_CompareNetprops(client); + + +forward TED_OnCompare(client, const String:sNetprop[], const String:sOld[], const String:sNow[], iOffset); +forward TED_OnNetpropHint(client, const String:sText[], const String:sNetprop[]); +forward TED_OnShow(client, const String:sNetprop[], const String:sValue[], iOffset); +forward TED_OnInfo(client, const String:sText[]); \ No newline at end of file diff --git a/scripting/l4d2-info-cmd.sp b/scripting/l4d2-info-cmd.sp index ae7dfae..1d36488 100644 --- a/scripting/l4d2-info-cmd.sp +++ b/scripting/l4d2-info-cmd.sp @@ -30,6 +30,8 @@ public Plugin myinfo = url = "https://github.com/Jackzmc/sourcemod-plugins" }; + +// Socket infoSocket; //TODO: Transition state public OnPluginStart() diff --git a/scripting/l4d2_detections.sp b/scripting/l4d2_detections.sp index 3ed01f6..35aaef9 100644 --- a/scripting/l4d2_detections.sp +++ b/scripting/l4d2_detections.sp @@ -119,7 +119,7 @@ public void OnPluginStart() { } public void OnClientPutInServer(int client) { - CreateTimer(20.0, Timer_ClearDoubleKitDetection, _, GetClientUserId(client)); + CreateTimer(20.0, Timer_ClearDoubleKitDetection, GetClientUserId(client)); } // Called on map changes too, we want this: @@ -193,7 +193,7 @@ public void Event_HealSuccess(Event event, const char[] name, bool dontBroadcast int target = GetClientOfUserId(event.GetInt("subject")); int amount = event.GetInt("health_restored"); int orgHealth = GetClientHealth(target) - amount; - PrintToConsoleAll("[Debug] %N healed %N (+%d health, was %d)", client, target, amount, orgHealth); + PrintToConsoleAll("[Debug] %N healed %N (+%d health, was perm. %d)", client, target, amount, orgHealth); } }