فهرست منبع

Safecheck atcommand

-Add restriction for atcommand to prevent possible mapcrash from script
or console usage while waiting full portability.
-Upd athena-start for new default binname.
-Remove petstat as it was similar to getpetinfo and copy only missing
attribute level atribute into getpetinfo.
-Merge useatcmd and atcommand as they shared quite the same code, also
properly differenciate useatcmd from normal player call.
--Upd script-documentation about it thx Euphy.
lighta 11 سال پیش
والد
کامیت
55e776076b
7فایلهای تغییر یافته به همراه86 افزوده شده و 136 حذف شده
  1. 3 0
      .gitignore
  2. 4 2
      db/const.txt
  3. 12 23
      doc/script_commands.txt
  4. 3 3
      function.sh
  5. 33 13
      src/map/atcommand.c
  6. 1 1
      src/map/map.c
  7. 30 94
      src/map/script.c

+ 3 - 0
.gitignore

@@ -17,14 +17,17 @@
 /*.stackdump
 /*.suo
 /char-server_sql
+/char-server
 /config.log
 /config.status
 /core
 /ipch
 /login-server_sql
+/login-server
 /Makefile
 /Makefile.cache
 /map-server_sql
+/map-server
 /mapcache
 /nbproject
 

+ 4 - 2
db/const.txt

@@ -1399,11 +1399,13 @@ e_yut5	85
 e_yut6	86
 e_yut7	87
 
+PET_ID	0
 PET_CLASS	1
 PET_NAME	2
-PET_LEVEL	3
+PET_INTIMATE	3
 PET_HUNGRY	4
-PET_INTIMATE	5
+PET_RENAMED	5
+PET_LEVEL	6
 
 MOB_NAME	0
 MOB_LV	1

+ 12 - 23
doc/script_commands.txt

@@ -6514,8 +6514,8 @@ character belonged to an account which had GM level 99.
     input @player$;
     atcommand "@nuke "+@player$;
 
-This command has a lot of good uses, I am sure you can have some fun with this 
-one.
+Note that for atcommands bound using 'bindatcmd', this command will execute the
+original atcommand, not the script-bound atcommand.
 
 ---------------------------------------
 
@@ -6532,7 +6532,7 @@ The commands can also run without an attached rid.
 
 ---------------------------------------
 
-*bindatcmd "command","<NPC object name>::<event label>"{,<atcommand level>,<charcommand level>};
+*bindatcmd "<command>","<NPC object name>::<event label>"{,<atcommand level>,<charcommand level>};
 
 This command will bind a NPC event label to an atcommand. Upon execution of the
 atcommand, the user will invoke the NPC event label. Each atcommand is only allowed
@@ -6558,16 +6558,20 @@ OnAtcommand:
 
 ---------------------------------------
 
-*unbindatcmd "command";
+*unbindatcmd "<command>";
 
 This command will unbind a NPC event label from an atcommand.
 
 ---------------------------------------
 
-*useatcmd "command";
+*useatcmd "<command>";
 
-This command will execute an atcommand binding on the attached RID from a script. 
-The three .@atcmd_***** variables will NOT be set when invoking scripts-atcommands this way.
+This command will execute a script-bound atcommand for the attached RID. If the
+supplied command is not bound to any script, this command will act like 'atcommand'
+and attempt to execute a source-defined command.
+
+The three .@atcmd_***** variables will NOT be set when invoking script-bound atcommands
+in this way.
 
 ---------------------------------------
 \\
@@ -7604,23 +7608,8 @@ currently has active. Valid types are:
  3 - Pet friendly level (intimacy score). 1000 is full loyalty.
  4 - Pet hungry level. 100 is completely full.
  5 - Pet rename flag. 0 means this pet has not been named yet.
+ 6 - Pet level
 
----------------------------------------
-
-*petstat(<flag>)
-
-Returns current pet status, all are integers except name.
-Returns 0 or "" if the player doesn't have pets.
-
-Flags usable:
-- PET_CLASS
-- PET_NAME
-- PET_LEVEL
-- PET_HUNGRY
-- PET_INTIMATE
-
-Example:
-	set @i, petstat(PET_CLASS);
 
 ---------------------------------------
 

+ 3 - 3
function.sh

@@ -1,6 +1,6 @@
-L_SRV=login-server_sql
-C_SRV=char-server_sql
-M_SRV=map-server_sql
+L_SRV=login-server
+C_SRV=char-server
+M_SRV=map-server
 INST_PATH=/opt
 PKG=rathena
 PKG_PATH=$INST_PATH/$PKG

+ 33 - 13
src/map/atcommand.c

@@ -65,6 +65,7 @@ struct AtCommandInfo {
 	AtCommandFunc func;
 	char* at_groups;/* quick @commands "can-use" lookup */
 	char* char_groups;/* quick @charcommands "can-use" lookup */
+	int restriction; //prevent : 1 console, 2 script...
 };
 
 struct AliasInfo {
@@ -9042,14 +9043,18 @@ ACMD_FUNC(langtype)
 /**
  * Fills the reference of available commands in atcommand DBMap
  **/
-#define ACMD_DEF(x) { #x, atcommand_ ## x, NULL, NULL }
-#define ACMD_DEF2(x2, x) { x2, atcommand_ ## x, NULL, NULL }
+#define ACMD_DEF(x) { #x, atcommand_ ## x, NULL, NULL, 0 }
+#define ACMD_DEF2(x2, x) { x2, atcommand_ ## x, NULL, NULL, 0 }
+//define with restriction
+#define ACMD_DEFR(x, r) { #x, atcommand_ ## x, NULL, NULL, r }
+#define ACMD_DEF2R(x2, x, r) { x2, atcommand_ ## x, NULL, NULL, r }
 void atcommand_basecommands(void) {
 	/**
 	 * Command reference list, place the base of your commands here
+	 * TODO : all restricted command are crashing case, please look into it
 	 **/
 	AtCommandInfo atcommand_base[] = {
-		ACMD_DEF2("warp", mapmove),
+		ACMD_DEF2R("warp", mapmove, 1),
 		ACMD_DEF(where),
 		ACMD_DEF(jumpto),
 		ACMD_DEF(jump),
@@ -9067,7 +9072,7 @@ void atcommand_basecommands(void) {
 		ACMD_DEF(guildstorage),
 		ACMD_DEF(option),
 		ACMD_DEF(hide), // + /hide
-		ACMD_DEF(jobchange),
+		ACMD_DEFR(jobchange, 1),
 		ACMD_DEF(kill),
 		ACMD_DEF(alive),
 		ACMD_DEF(kami),
@@ -9083,7 +9088,7 @@ void atcommand_basecommands(void) {
 		ACMD_DEF(clearstorage),
 		ACMD_DEF(cleargstorage),
 		ACMD_DEF(clearcart),
-		ACMD_DEF2("blvl", baselevelup),
+		ACMD_DEF2R("blvl", baselevelup, 1),
 		ACMD_DEF2("jlvl", joblevelup),
 		ACMD_DEF(help),
 		ACMD_DEF(pvpoff),
@@ -9091,7 +9096,7 @@ void atcommand_basecommands(void) {
 		ACMD_DEF(gvgoff),
 		ACMD_DEF(gvgon),
 		ACMD_DEF(model),
-		ACMD_DEF(go),
+		ACMD_DEFR(go, 1),
 		ACMD_DEF(monster),
 		ACMD_DEF2("monstersmall", monster),
 		ACMD_DEF2("monsterbig", monster),
@@ -9140,11 +9145,11 @@ void atcommand_basecommands(void) {
 		ACMD_DEF(broadcast), // + /b and /nb
 		ACMD_DEF(localbroadcast), // + /lb and /nlb
 		ACMD_DEF(recallall),
-		ACMD_DEF(reload),
+		ACMD_DEFR(reload,2),
 		ACMD_DEF2("reloaditemdb", reload),
 		ACMD_DEF2("reloadmobdb", reload),
 		ACMD_DEF2("reloadskilldb", reload),
-		ACMD_DEF2("reloadscript", reload),
+		ACMD_DEF2R("reloadscript", reload,2),
 		ACMD_DEF2("reloadatcommand", reload),
 		ACMD_DEF2("reloadbattleconf", reload),
 		ACMD_DEF2("reloadstatusdb", reload),
@@ -9323,6 +9328,7 @@ void atcommand_basecommands(void) {
 		CREATE(atcommand, AtCommandInfo, 1);
 		safestrncpy(atcommand->command, atcommand_base[i].command, sizeof(atcommand->command));
 		atcommand->func = atcommand_base[i].func;
+		atcommand->restriction = atcommand_base[i].restriction;
 		strdb_put(atcommand_db, atcommand->command, atcommand);
 	}
 	return;
@@ -9423,7 +9429,14 @@ static void atcommand_get_suggestions(struct map_session_data* sd, const char *n
 	dbi_destroy(alias_iter);
 }
 
-/// Executes an at-command.
+/*
+ *  Executes an at-command
+ * \param type :
+ *  0 : script call (atcommand)
+ *  1 : normal player @atcommand
+ *  2 : console
+ *  3 : script call (useatcmd)
+ */
 bool is_atcommand(const int fd, struct map_session_data* sd, const char* message, int type)
 {
 	char charname[NAME_LENGTH], params[100];
@@ -9455,9 +9468,8 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
 	if ( *message != atcommand_symbol && *message != charcommand_symbol )
 		return false;
 
-	// type value 0 = server invoked: bypass restrictions
-	// 1 = player invoked
-	if ( type == 1) {
+	// type value 0|2 = script|console invoked: bypass restrictions
+	if ( type == 1 || type == 3) {
 		//Commands are disabled on maps flagged as 'nocommand'
 		if ( map[sd->bl.m].nocommand && pc_get_group_level(sd) < map[sd->bl.m].nocommand ) {
 			clif_displaymessage(fd, msg_txt(sd,143));
@@ -9524,7 +9536,7 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
 		params[0] = '\0';
 
 	// @commands (script based)
-	if(type == 1 && atcmd_binding_count > 0) {
+	if((type == 1 || type == 3) && atcmd_binding_count > 0) {
 		struct atcmd_binding_data * binding;
 
 		// Check if the command initiated is a character command
@@ -9562,6 +9574,14 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
 			return false;
 	}
 
+	//check restriction
+	if(info->restriction){
+		if(info->restriction&1 && type == 2) //console prevent
+			return true;
+		if(info->restriction&2 && (type == 0 || type == 3) ) //scripts prevent
+			return true;
+	}
+
 	// type == 1 : player invoked
 	if (type == 1) {
 		if ((*command == atcommand_symbol && info->at_groups[sd->group_pos] == 0) ||

+ 1 - 1
src/map/map.c

@@ -3302,7 +3302,7 @@ int parse_console(const char* buf){
 				sd.bl.y = y;
 			ShowNotice("Now at: '%s' Coords: %d %d\n", map, x, y);
 		}
-		else if( !is_atcommand(sd.fd, &sd, command, 0) )
+		else if( !is_atcommand(sd.fd, &sd, command, 2) )
 			ShowInfo("Console: Invalid atcommand.\n");
 	}
 	else if( n == 2 && strcmpi("server", type) == 0 ){

+ 30 - 94
src/map/script.c

@@ -6117,22 +6117,22 @@ BUILDIN_FUNC(countitem)
 	} else { // For countitem2() function
 		int nameid, iden, ref, attr, c1, c2, c3, c4;
 
-		nameid = id->nameid; 
-		iden = script_getnum(st,3); 
-		ref  = script_getnum(st,4); 
-		attr = script_getnum(st,5); 
-		c1 = (short)script_getnum(st,6); 
-		c2 = (short)script_getnum(st,7); 
-		c3 = (short)script_getnum(st,8); 
+		nameid = id->nameid;
+		iden = script_getnum(st,3);
+		ref  = script_getnum(st,4);
+		attr = script_getnum(st,5);
+		c1 = (short)script_getnum(st,6);
+		c2 = (short)script_getnum(st,7);
+		c3 = (short)script_getnum(st,8);
 		c4 = (short)script_getnum(st,9);
 
 		for(i = 0; i < MAX_INVENTORY; i++)
-			if (sd->status.inventory[i].nameid > 0 && sd->inventory_data[i] != NULL && 
-				sd->status.inventory[i].amount > 0 && sd->status.inventory[i].nameid == nameid && 
-				sd->status.inventory[i].identify == iden && sd->status.inventory[i].refine == ref && 
-				sd->status.inventory[i].attribute == attr && sd->status.inventory[i].card[0] == c1 && 
-				sd->status.inventory[i].card[1] == c2 && sd->status.inventory[i].card[2] == c3 && 
-				sd->status.inventory[i].card[3] == c4 ) 
+			if (sd->status.inventory[i].nameid > 0 && sd->inventory_data[i] != NULL &&
+				sd->status.inventory[i].amount > 0 && sd->status.inventory[i].nameid == nameid &&
+				sd->status.inventory[i].identify == iden && sd->status.inventory[i].refine == ref &&
+				sd->status.inventory[i].attribute == attr && sd->status.inventory[i].card[0] == c1 &&
+				sd->status.inventory[i].card[1] == c2 && sd->status.inventory[i].card[2] == c3 &&
+				sd->status.inventory[i].card[3] == c4 )
 	 	                        count += sd->status.inventory[i].amount;
 	}
 
@@ -12760,11 +12760,7 @@ BUILDIN_FUNC(nude)
 	return 0;
 }
 
-/*==========================================
- * gmcommand [MouseJstr]
- *------------------------------------------*/
-BUILDIN_FUNC(atcommand)
-{
+int atcommand_sub(struct script_state* st,int type){
 	TBL_PC dummy_sd;
 	TBL_PC* sd;
 	int fd;
@@ -12789,7 +12785,7 @@ BUILDIN_FUNC(atcommand)
 		}
 	}
 
-	if (!is_atcommand(fd, sd, cmd, 0)) {
+	if (!is_atcommand(fd, sd, cmd, type)) {
 		ShowWarning("script: buildin_atcommand: failed to execute command '%s'\n", cmd);
 		script_reportsrc(st);
 		return 1;
@@ -12798,6 +12794,13 @@ BUILDIN_FUNC(atcommand)
 	return 0;
 }
 
+/*==========================================
+ * gmcommand [MouseJstr]
+ *------------------------------------------*/
+BUILDIN_FUNC(atcommand) {
+	return atcommand_sub(st,0);
+}
+
 /*==========================================
  * Displays a message for the player only (like system messages like "you got an apple" )
  *------------------------------------------*/
@@ -12950,7 +12953,7 @@ BUILDIN_FUNC(recovery)
 /*==========================================
  * Get your pet info: getpetinfo(n)
  * n -> 0:pet_id 1:pet_class 2:pet_name
- * 3:friendly 4:hungry, 5: rename flag.
+ * 3:friendly 4:hungry, 5: rename flag.6:level
  *------------------------------------------*/
 BUILDIN_FUNC(getpetinfo)
 {
@@ -12973,6 +12976,7 @@ BUILDIN_FUNC(getpetinfo)
 		case 3: script_pushint(st,pd->pet.intimate); break;
 		case 4: script_pushint(st,pd->pet.hungry); break;
 		case 5: script_pushint(st,pd->pet.rename_flag); break;
+		case 6: script_pushint(st,(int)pd->pet.level); break;
 		default:
 			script_pushint(st,0);
 			break;
@@ -14922,35 +14926,6 @@ BUILDIN_FUNC(getd)
 	return 0;
 }
 
-// <--- [zBuffer] List of dynamic var commands
-// Pet stat [Lance]
-BUILDIN_FUNC(petstat)
-{
-	TBL_PC *sd = NULL;
-	struct pet_data *pd;
-	int flag = script_getnum(st,2);
-	sd = script_rid2sd(st);
-	if(!sd || !sd->status.pet_id || !sd->pd){
-		if(flag == 2)
-			script_pushconststr(st, "");
-		else
-			script_pushint(st,0);
-		return 0;
-	}
-	pd = sd->pd;
-	switch(flag){
-		case 1: script_pushint(st,(int)pd->pet.class_); break;
-		case 2: script_pushstrcopy(st, pd->pet.name); break;
-		case 3: script_pushint(st,(int)pd->pet.level); break;
-		case 4: script_pushint(st,(int)pd->pet.hungry); break;
-		case 5: script_pushint(st,(int)pd->pet.intimate); break;
-		default:
-			script_pushint(st,0);
-			break;
-	}
-	return 0;
-}
-
 BUILDIN_FUNC(callshop)
 {
 	TBL_PC *sd = NULL;
@@ -16596,7 +16571,7 @@ BUILDIN_FUNC(bg_get_data)
 //Checks NPC first, then if player is attached we check party
 int script_instancegetid(struct script_state* st)
 {
-	short instance_id = 0;	
+	short instance_id = 0;
 
 	struct npc_data *nd;
 	if( (nd = map_id2nd(st->oid)) && nd->instance_id > 0 )
@@ -16745,7 +16720,7 @@ BUILDIN_FUNC(instance_id)
 	}
 
 	script_pushint(st, instance_id);
-		
+
 	return 0;
 }
 
@@ -17400,45 +17375,8 @@ BUILDIN_FUNC(unbindatcmd) {
 	return 0;
 }
 
-BUILDIN_FUNC(useatcmd)
-{
-	TBL_PC dummy_sd;
-	TBL_PC* sd;
-	int fd;
-	const char* cmd;
-
-	cmd = script_getstr(st,2);
-
-	if( st->rid )
-	{
-		sd = script_rid2sd(st);
-		fd = sd->fd;
-	}
-	else
-	{ // Use a dummy character.
-		sd = &dummy_sd;
-		fd = 0;
-
-		memset(&dummy_sd, 0, sizeof(TBL_PC));
-		if( st->oid )
-		{
-			struct block_list* bl = map_id2bl(st->oid);
-			memcpy(&dummy_sd.bl, bl, sizeof(struct block_list));
-			if( bl->type == BL_NPC )
-				safestrncpy(dummy_sd.status.name, ((TBL_NPC*)bl)->name, NAME_LENGTH);
-		}
-	}
-
-	// compatibility with previous implementation (deprecated!)
-	if( cmd[0] != atcommand_symbol )
-	{
-		cmd += strlen(sd->status.name);
-		while( *cmd != atcommand_symbol && *cmd != 0 )
-			cmd++;
-	}
-
-	is_atcommand(fd, sd, cmd, 1);
-	return 0;
+BUILDIN_FUNC(useatcmd) {
+	return atcommand_sub(st,3);
 }
 
 BUILDIN_FUNC(checkre)
@@ -17742,7 +17680,7 @@ BUILDIN_FUNC(countbound)
 			j += sd->status.inventory[i].amount;
 		}
 	}
-	
+
 	script_pushint(st,j);
 	return 0;
 }
@@ -18336,8 +18274,6 @@ struct script_function buildin_func[] = {
 	// [zBuffer] List of dynamic var commands --->
 	BUILDIN_DEF(getd,"s"),
 	BUILDIN_DEF(setd,"sv"),
-	// <--- [zBuffer] List of dynamic var commands
-	BUILDIN_DEF(petstat,"i"),
 	BUILDIN_DEF(callshop,"s?"), // [Skotlex]
 	BUILDIN_DEF(npcshopitem,"sii*"), // [Lance]
 	BUILDIN_DEF(npcshopadditem,"sii*"),
@@ -18492,7 +18428,7 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(party_changeleader,"ii"),
 	BUILDIN_DEF(party_changeoption,"iii"),
 	BUILDIN_DEF(party_destroy,"i"),
-	
+
 	BUILDIN_DEF(is_clientver,"ii?"),
 	BUILDIN_DEF(getserverdef,"i"),
 	{NULL,NULL,NULL},