PDA

View Full Version : Multilines kick reason


Teyut
11-12-2006, 16:23
Hi !

When you use the kick command on a server con, you can give a reason for that kick using the following scheme:
kick (name | #userid) [reason]The problem is that the reason message is a one line message. If you want it to be displayed on multiple lines, you can count how many characters can fit on each lines of the kick popup dialog, and then format your reason message accordingly. That's painfull since HL characters don't have the same width, thus that won't work with dynamic reason messages.

A better solution could be to forge a kick packet which contains a multilines reason message. This can be done using the following kick_ML method: way:
#define SVC_DISCONNECT 2
/* SVC_DISCONNECT: ask the client to disconnect and show the given string in a popup dialog.
* -> (string) kick_reason: reason of the kick. It is shown to the client via
* a popup dialog. Its content can't be large.
*
* Note: such messages are sent when using the <kick> command, or when the client
* disconnect himself. In the latter, no popup dialog is shown.
*/
/* Kick with a multilines reason. Return 0 if an error has occured. */
kick_ML(id, line1[] = "", line2[] = "", line3[] = "") {
if(!is_valid_ent(id)) return 0

new msg_content[1024], pl_name[32], pl_userid, pl_authid[35]

/* grab logging infos */
pl_userid = get_user_userid(id)
get_user_name(id, pl_name, 31)
get_user_authid(id, pl_authid, 34)

/* do kick the player */
format(msg_content, 1023, "%s^n%s^n%s", line1, line2, line3)
message_begin(MSG_ONE, SVC_DISCONNECT, {0,0,0}, id)
write_string(msg_content)
message_end()

/* log the kick as <kick> command do */
log_message("Kick_ML: ^"%s<%d><%s><>^" was kicked by ^"Console^" (message ^"%s^" ^"%s^" ^"%s^")",
pl_name, pl_userid, pl_authid, line1, line2, line3)

return 1
}

There's only 3 lines available in the popup dialog. These lines should not contain a lot of text of course ... Here's a sample dialog:

http://img292.**************/img292/5623/kickmlxv5.th.jpg (http://img292.**************/my.php?image=kickmlxv5.jpg)

I needed to do that for a plugin, so I though someone could need it too. The main interesting thing here is not that the ^n escape character create a new line, but that the SVC_KICK message do kick the player and show the reason message (without checking if it's a multines one or not).

I didn't find informations about HL specific message types anywhere, so I though it could be usefull. Here are some others message types I found:
#define SVC_PRINT 8
/* SVC_PRINT: show the given string in the client console.
* -> (string) message: message to display in the client console.
*/
#define SVC_STUFFTEXT 9
/* SVC_STUFFTEXT: send command for the client to execute.
* -> (string) command_line: command to execute remotely.
*
* Note: commands correspond to the classic HL console commands.
*/


Sorry if such infos have already been posted before. I was just testing the layout of my post, and click on the "submit message" button instead of the "Preview Changes" one. I didn't want to post my message right now, but since you can't delete your own messages, I had no choice but to do it :x

Brad
11-12-2006, 16:38
Sounds interesting. Can you show a screen shot of it in action?

Teyut
11-12-2006, 16:50
Like I explained it above, I wasn't really ready to post my message when you saw it. The (almost) final version is now available, with a screenshot as you asked :wink: Its content is in french, but that shouldn't be a real problem :roll:

I'm sorry for the typo and english mistakes, but I'm unable to edit my message again without messing the Pwan code parts :(

k007
11-12-2006, 16:56
sweet dude

VEN
11-14-2006, 10:56
Correction: it's SVC_DISCONNECT, not SVC_KICK.

Brad
11-14-2006, 13:03
Is it possible to use color in the message?

Brad
12-08-2006, 00:11
My testing indicates that you can not use color in the message.

evilworm
02-28-2009, 19:06
Sorry for bringing up old topics, but I think this belongs here...

I'm using this kick method to kick players from the server after they have failed the admin-check in the client_authorized() function and there are no free slots, however it sometimes fails and crashes server with this message (totally random... sometimes crashes 3 times in 10 minutes, sometimes can go on for 3-4 mapchanges):


L 03/01/2009 - 01:29:53: FATAL ERROR (shutting down): MSG_ONE or MSG_ONE_UNRELIABLE with no target entity

FATAL ERROR (shutting down): MSG_ONE or MSG_ONE_UNRELIABLE with no target entity

Add "-debug" to the ./hlds_run command line to generate a debug.log to help with solving this problem
Sun Mar 1 01:29:53 EET 2009: Server restart in 10 seconds
I'm using the loopback method by register_clcmd(g_cmdSignal, "ackSignal") and then issuign Kick_ML. The function is_user_connected() always returns false, but is_user_connecting() - true. So the question is - how can I know if I can send message to the player with message_begin() if the player shows up as not connected? I also tried to check player with (pev(id,pev_flags) & FL_CLIENT), but it returns false, so it's useless.

Help would be appreciated!

Teyut
02-28-2009, 23:40
FATAL ERROR (shutting down): MSG_ONE or MSG_ONE_UNRELIABLE with no target entity
[...]
So the question is - how can I know if I can send message to the player with message_begin() if the player shows up as not connected?
From what I understand reading the AMXX/HLSDK source code, such crashes happen when the last parameter (player entity) of the MESSAGE_BEGIN macro is NULL. The AMXX core doesn't check for such a case before calling that macro (the result of INDEXENT should be checked before use in unicast messages) :?

I've fixed that bug in the kick_ML() method (see above) calling the is_valid_ent() method (engine module) before doing anything. If the kick can't work, the method will return 0. Note however that is_valid_ent() does almost the same things as is_user_connected(), so it may not really help you, but at least, it should fix that server crash (I haven't test the code actually).

If you really want to kick players that are connecting but are not yet connected, you'll need to find a way to retrieve the result of the HL engine method pfnPEntityOfEntIndex: if it's non-zero, then you may kick the player. But I haven't find an AMXX module which provides a direct access to that method.

Correction: it's SVC_DISCONNECT, not SVC_KICK.
Fixed, thanks. I didn't know where to find the correct names.

My testing indicates that you can not use color in the message.
Sorry about my lack of answer :? You were right: it's not possible (I guess it is with Source).

ConnorMcLeod
03-01-2009, 03:14
Fixed, thanks. I didn't know where to find the correct names.

/* Hardcoded message types for message_begin()
* Look in the actual HLSDK for details!
*/
#define SVC_NOP 1
#define SVC_DISCONNECT 2
#define SVC_EVENT 3
#define SVC_VERSION 4
#define SVC_SETVIEW 5
#define SVC_SOUND 6
#define SVC_TIME 7
#define SVC_PRINT 8
#define SVC_STUFFTEXT 9
#define SVC_SETANGLE 10
#define SVC_SERVERINFO 11
#define SVC_LIGHTSTYLE 12
#define SVC_UPDATEUSERINFO 13
#define SVC_DELTADESCRIPTION 14
#define SVC_CLIENTDATA 15
#define SVC_STOPSOUND 16
#define SVC_PINGS 17
#define SVC_PARTICLE 18
#define SVC_DAMAGE 19
#define SVC_SPAWNSTATIC 20
#define SVC_EVENT_RELIABLE 21
#define SVC_SPAWNBASELINE 22
#define SVC_TEMPENTITY 23
#define SVC_SETPAUSE 24
#define SVC_SIGNONNUM 25
#define SVC_CENTERPRINT 26
#define SVC_KILLEDMONSTER 27
#define SVC_FOUNDSECRET 28
#define SVC_SPAWNSTATICSOUND 29
#define SVC_INTERMISSION 30
#define SVC_FINALE 31
#define SVC_CDTRACK 32
#define SVC_RESTORE 33
#define SVC_CUTSCENE 34
#define SVC_WEAPONANIM 35
#define SVC_DECALNAME 36
#define SVC_ROOMTYPE 37
#define SVC_ADDANGLE 38
#define SVC_NEWUSERMSG 39
#define SVC_PACKETENTITIES 40
#define SVC_DELTAPACKETENTITIES 41
#define SVC_CHOKE 42
#define SVC_RESOURCELIST 43
#define SVC_NEWMOVEVARS 44
#define SVC_RESOURCEREQUEST 45
#define SVC_CUSTOMIZATION 46
#define SVC_CROSSHAIRANGLE 47
#define SVC_SOUNDFADE 48
#define SVC_FILETXFERFAILED 49
#define SVC_HLTV 50
#define SVC_DIRECTOR 51
#define SVC_VOICEINIT 52
#define SVC_VOICEDATA 53
#define SVC_SENDEXTRAINFO 54
#define SVC_TIMESCALE 55

evilworm
03-01-2009, 06:18
Player entity parameter is not NULL, I checked that with debug output to log, but I'm not sure abut INDEXENT output. The is_valid_ent() will not work, because it first checks if player is ingame and then checks INDEXENT. By the way, as I said, I'm doing the kick from the client_authorized() function, which sometimes fails. I guess it's too early to call message_begin() here. However client_putinserver() is not guaranteed to happen before client_authorized(), so I cannot call that one either. Just had a thought that I sould check which one of the functions is called last and execute kick from there (some kinda emulation of OnClientPreAdminCheck function from SourceMod).

Teyut
03-01-2009, 15:36
Player entity parameter is not NULL, I checked that with debug output to log, but I'm not sure abut INDEXENT output.
The player entity is the result of INDEXENT (it's a pointer). The only reason why the MESSAGE_BEGIN macro (the HLSDK macro) throws that fatal error is when the player entity parameter is NULL with unicast messages.

Just had a thought that I sould check which one of the functions is called last and execute kick from there (some kinda emulation of OnClientPreAdminCheck function from SourceMod).
Don't forget to also implement the client_disconnect forward to handle clients that disconnect between the two events.

Fixed, thanks. I didn't know where to find the correct names.

/* Hardcoded message types for message_begin()
* Look in the actual HLSDK for details!
*/
Thanks, but as the preterit tense should have implied: I've already found them :wink:.

Owyn
11-01-2009, 10:48
so not to get error with MSG_ONE you only need to check if (FNullEnt(INDEXENT(iEnt)))
?

that would be easy, make a new native in engine to check only this and use it, woudn't it?

hleV
11-01-2009, 10:51
This is awesome. I wonder which is better: SVC_KICK or SVC_DISCONNECT?

Arkshine
11-01-2009, 10:57
SVC_KICK doesn't exist, it's only SVC_DISCONNECT.

Owyn
11-01-2009, 11:12
sure it is) but it has problems if you wanna use it before client_putinserver()

just edit engine module and add a new native to check only INDEXENT or add a check if (FNullEnt(INDEXENT(iEnt))) into static cell AMX_NATIVE_CALL message_begin(AMX *amx, cell *params) /* 4 param */why nobody did this before?

xPaw
11-01-2009, 12:36
sure it is) but it has problems if you wanna use it before client_putinserver()?

SVC_KICK doesn't exist, it's only SVC_DISCONNECT.

Arkshine
11-01-2009, 12:38
sure it is) but it has problems if you wanna use it before client_putinserver()

just edit engine module and add a new native to check only INDEXENT or add a check if (FNullEnt(INDEXENT(iEnt))) into static cell AMX_NATIVE_CALL message_begin(AMX *amx, cell *params) /* 4 param */why nobody did this before?

Check yourself you pass a valid player index.

Owyn
11-01-2009, 13:01
Check yourselfthat's what i did, now i have no problems, just shared a solution =) *it may looks like u haven't read whole thread, there is no way to check it before client_putinserver() *just noticing**


2xPaw, (http://forums.alliedmods.net/member.php?u=39377)

This is awesomesure it is)

ConnorMcLeod
11-01-2009, 14:30
I suppose is_valid_ent returns true even when players are not connected.

Owyn
11-01-2009, 14:41
I suppose is_valid_ent returns true even when players are not connected.
nope it doesn't, it also checks MF_IsPlayerIngame

xPaw
11-01-2009, 14:58
is_user_connecting ?

Owyn
11-01-2009, 15:14
is_user_connecting - Returns 1 if a player has not yet connected, 0 otherwise. (c) func_wiki

static cell AMX_NATIVE_CALL is_user_connecting(AMX *amx, cell *params) /* 1 param */
{
int index = params[1];

if (index < 1 || index > gpGlobals->maxClients)
return 0;

CPlayer* pPlayer = GET_PLAYER_POINTER_I(index);

return (!pPlayer->ingame && pPlayer->initialized && (GETPLAYERUSERID(pPlayer->pEdict) > 0)) ? 1 : 0;
}conditions:
PutInServer not passed
client_connect passed
has userid

nothing more

xPaw
11-01-2009, 15:27
What are you trying todo..

ConnorMcLeod
11-01-2009, 17:09
if( is_user_connecting(id) && get_user_userid(id) != -1 )

Owyn
11-02-2009, 03:25
i was trying to say is_user_connecting doesn't do the thing,

+
ConnorMcLeod,
is_user_connecting() already checks if userid is bigger than zero

ConnorMcLeod
11-02-2009, 05:32
So what is the problem with is_user_connecting ?

Owyn
11-02-2009, 09:06
look at previous pages

ConnorMcLeod
11-02-2009, 09:20
is_user_connecting is exactly what you want.

connect passed
putinserver not passed
userid exists

^SmileY
02-01-2014, 11:12
Hi, sorry for bumb in this topic, but this will cause the server shutdown?
I tested and this is crashing the server:


FATAL ERROR (shutting down): MSG_ONE or MSG_ONE_UNRELIABLE with no target entity



] rcon status
NET Ports: server 27015, client 27005
Server IP address 192.168.1.2:27015
hostname: MaxiGames PUG #01 - MaxiGames
version : 48/1.1.2.7/Stdio 6132 insecure (10)
tcp/ip : 200.98.140.160:27041
map : de_dust2 at: 0 x, 0 y, 0 z
players : 0 active (12 max)

# name userid uniqueid frag time ping loss adr
0 users



] rcon version
Protocol version 48
Exe version 1.1.2.7/Stdio (cstrike)
Exe build: 10:03:21 Aug 8 2013 (6132)




] rcon meta list
Currently loaded plugins:
description stat pend file vers src load unlod
[ 1] AMX Mod X RUN - amxmodx_mm_i386. v1.8.3-d ini Start ANY
[ 2] FakeMeta RUN - fakemeta_amxx_i3 v1.8.3-d pl1 ANY ANY
[ 3] CStrike RUN - cstrike_amxx_i38 v1.8.3-d pl1 ANY ANY
[ 4] CSX RUN - csx_amxx_i386.so v1.8.3-d pl1 ANY ANY
[ 5] Ham Sandwich RUN - hamsandwich_amxx v1.8.3-d pl1 ANY ANY
[ 6] MySQL RUN - mysql_amxx_i386. v1.8.3-d pl1 ANY ANY
[ 7] Orpheu RUN - orpheu_amxx_i386 v2.5.1 pl1 ANY ANY
7 plugins, 7 running

ConnorMcLeod
02-01-2014, 11:15
Don't use this.
Message is only a part of the kick process.
Doing this and server won't be informed that client has been kicked, it can make some problems on dll or engine.

^SmileY
02-01-2014, 17:14
Don't use this.
Message is only a part of the kick process.
Doing this and server won't be informed that client has been kicked, it can make some problems on dll or engine.

Thanks... I still using and server is crashing.
I do not using more this.

For Multi lines kick reason, any possibility to do this?
I tried to use a normal kick + console_print to show informations for players, but the console_print wont working when i kick player checked in client_authorized.

ConnorMcLeod
02-01-2014, 21:54
Try this and tell me if it is working without crashing :

user_kick(id, fmt[] = "", any:...)
{
if( fmt[0] )
{
new szKickMsg[192], len = vformat(szKickMsg, charsmax(szKickMsg), fmt, 3), bool:bMultiLines;

for(--len; len>=0; len--)
{
if( szKickMsg[len] == '^n' )
{
if( !bMultiLines )
{
bMultiLines = true:
message_begin(MSG_ONE, SVC_DISCONNECT, _, id);
write_string(szKickMsg);
message_end();
}

szKickMsg[len] = '\';
}
}

server_cmd("kick #%d %s", get_user_userid(id), szKickMsg);
if( bMultiLines )
{
server_exec();
}
}
else
{
server_cmd("kick #%d", get_user_userid(id));
}
}

meTaLiCroSS
02-01-2014, 22:13
Try this and tell me if it is working without crashing :

user_kick(id, fmt[] = "", any:...)
{
if( fmt[0] )
{
new szKickMsg[192], len = vformat(szKickMsg, charsmax(szKickMsg), fmt, 3);

message_begin(MSG_ONE, SVC_DISCONNECT, _, id);
write_string(szKickMsg);
message_end();

for(--len; len>=0; len--)
{
if( szKickMsg[len] == '^n' )
{
szKickMsg[len] = '|';
}
}

server_cmd("kick #%d %s", get_user_userid(id), szKickMsg);
server_exec();
}
else
{
server_cmd("kick #%d", get_user_userid(id));
}
}


What about an Orpheu way? Just saying..

^SmileY
02-02-2014, 01:01
I not tested, but if the problem is the


message_begin(MSG_ONE, SVC_DISCONNECT, _, id); write_string(szKickMsg); message_end()


For engine, i do not using it but the orpheu way is to more sexy :)

fysiks
02-02-2014, 01:48
For engine, i do not using it but the orpheu way is to more sexy :)

You clearly have no idea what you are talking about. If you are not using the engine module and you are using AMX Mod X then you are probably doing something wrong.

ConnorMcLeod
02-02-2014, 04:30
What about an Orpheu way? Just saying..

This way is simple and, if it works fine, efficient, why would we bother to search for a way implying orpheu ?

Function edited again so message is only sent when there are more than one line.

^SmileY
02-02-2014, 10:50
You clearly have no idea what you are talking about. If you are not using the engine module and you are using AMX Mod X then you are probably doing something wrong.

Really? I not talking about ENGINE, it is about this


Don't use this.
Message is only a part of the kick process.
Doing this and server won't be informed that client has been kicked, it can make some problems on dll or engine.

ConnorMcLeod
02-03-2014, 01:14
Don't use this.
Message is only a part of the kick process.
Doing this and server won't be informed that client has been kicked, it can make some problems on dll or engine.

That's why i made that stock that seems to fix the problem, but you seems to be bound.

^SmileY
02-03-2014, 05:09
I tested and work reall thanks, is not the problem using this. The really problem with a original posted method, is the random crash in ramdom moments (I think the player is not fully connected to server)

Beacause i using this in client_authorized function.

EDIT:
Tested again and is broken (I think i not uploaded the code to correct folder, and used the old method to multi lines kick)
This will sendind a message, but in this way:

"Hi,\You're Kicked from this server:\ for being AFK"

Sorry, not worked

^SmileY
03-06-2014, 08:41
Up :(

hleV
03-11-2014, 07:07
You're supposed to put ^n for new line, not \.

^SmileY
03-11-2014, 08:17
You're supposed to put ^n for new line, not \.

Same problem not worked

ConnorMcLeod
03-11-2014, 16:27
user_kick(id, "Hi,^nYou're Kicked from this server:^n for being AFK"); // i don't fixe english

^SmileY
03-11-2014, 22:57
user_kick(id, "Hi,^nYou're Kicked from this server:^n for being AFK"); // i don't fixe english

"Hi,\You're Kicked from this server:\ for being AFK"

I not used this, it is as output from message

Ps. Again I used the both ^n and \n and out put not worked.

:roll:

Arkshine
03-12-2014, 05:36
Because \ needs to be escaped.

You could try something like : replace_all( szKickMsg, charsmax( szKickMsg ), "\", "\\" ); before calling server_cmd().

^SmileY
03-14-2014, 09:06
Because \ needs to be escaped.

You could try something like : replace_all( szKickMsg, charsmax( szKickMsg ), "\", "\\" ); before calling server_cmd().

I will try :3

hleV
03-14-2014, 09:35
You may want to try replacing MSG_ONE with MSG_ONE_UNRELIABLE, as I remember having problems with MSG_ONE and SVC_DISCONNECT in the past.

^SmileY
03-14-2014, 10:33
You may want to try replacing MSG_ONE with MSG_ONE_UNRELIABLE, as I remember having problems with MSG_ONE and SVC_DISCONNECT in the past.

I will testing when go to my home, i not have much time to do this..

:grrr: We need Oprpheu way :bacon!::bacon!::bacon!:

hleV
03-14-2014, 11:21
We don't need an Orpheu way.

^SmileY
04-25-2014, 11:16
Because \ needs to be escaped.

You could try something like : replace_all( szKickMsg, charsmax( szKickMsg ), "\", "\\" ); before calling server_cmd().

Hi again, i tried and not worked. But i tested this:


stock Disconnect(const id,const sReason[] = "",any:...)
{
if(sReason[0])
{
new sMessage[192];
vformat(sMessage,charsmax(sMessage),sReason,3 );

// Replaced MSG_ONE by MSG_ONE_UNRELIABLE..
message_begin(MSG_ONE_UNRELIABLE,SVC_DISCONNE CT,{0,0,0},id);
write_string(sMessage);

server_cmd("kick #%i",get_user_userid(id));

message_end();
}
else server_cmd("kick #%i",get_user_userid(id));
}


Using:


new sName[32];
get_user_name(id,sName,charsmax(sName));

Disconnect(id,"Bye ^n%s",sName);


And work, but is the correct way?