00001 //#include <types.h> 00002 00003 #include <sys/types.h> 00004 00005 #include <ctype.h> 00006 #include <stdio.h> 00007 #include <stdlib.h> 00008 #include <string.h> 00009 #include <time.h> 00010 #include "merc.h" 00011 #include "tables.h" 00012 #include "olc.h" 00013 00014 00015 /*From: Christopher Feist <Christopher.Feist.feist@nt.com> 00016 00017 Recently I have been working on OLC delete commands since they would 00018 be really handy. 00019 00020 I have come up with working versions of oedit_delete 00021 and medit_delete. redit_delete is still in the works and I dont 00022 think im going to bother with aedit_delete. 00023 00024 The basic premise is that you remove the vnum from the appropriate 00025 hash and then delete all resets which refer to said vnum. This is 00026 of course much easier to say then to do. The tricky part is 00027 getting resets for objects inside other objects. Both of the 00028 delete functions handle these cases. 00029 00030 I specificaly do not free up the index data because doing that 00031 would require me to eliminate every instance of said vnum from 00032 the mud. (because pIndexData still points to this memory location) 00033 This isnt too bad for mobiles but for objects it really 00034 really bites. If someone wants to code it up ill gladly take it 00035 however. :) 00036 00037 I am submitting the two delete functions so that other muds besides 00038 Aeon can test them and maybe force out any small bugs that I havent 00039 caught. I STRONGLY suggest you read and understand what is happening 00040 before you put these in. You will also have to add the hooks in 00041 to call the functions yourself. (That should prevent most copy/paste 00042 implementors from doing dumb things :P) 00043 00044 If you are trying to understand what is happening here I reccomend 00045 uncommenting the debug code in oedit delete as it spews alot less 00046 output then the medit delete code. I admit that neither of these 00047 routines are particularily elegant coding examples however they 00048 do work. 00049 00050 Lastly on Aeon there is a small glitch in medit_delete whereby 00051 the person deleting the mobile somehow has his mount set to 00052 a predictable value sometime after the exit of the function. 00053 (i.e its something in our code not the function) 00054 00055 Unfortunatly I havent been able to figureout how/why/where this happens. 00056 If anyone knows how to break on the change of the value 00057 of a dereferenced pointer in gdb an example would be REALLY REALLY 00058 appreciated. For those of you who have muds without mount code 00059 (or with mount code) you will have to get rid of that little 00060 section at the bottom of medit_delete since our mount code 00061 isnt taken from a stock snippet. 00062 00063 Enjoy. 00064 00065 Narbo 00066 00067 Coder @ Aeon 00068 telnet://mud.aeon.org:4000 00069 */ 00070 //OEDIT( oedit_delete ) 00071 OEDIT (CHAR_DATA *ch, char *argument) 00072 { 00073 OBJ_INDEX_DATA *pObj; 00074 OBJ_INDEX_DATA *iObj; 00075 OBJ_INDEX_DATA *sObj; 00076 RESET_DATA *pReset = NULL; 00077 RESET_DATA *prev = NULL; 00078 ROOM_INDEX_DATA *pRoom = NULL; 00079 char arg[MIL]; 00080 char buf[MSL]; 00081 int index, count, iHash, i; 00082 00083 if ( argument[0] == '\0' ) 00084 { 00085 send_to_char( "Syntax: oedit delete [vnum]\n\r", ch ); 00086 return FALSE; 00087 } 00088 00089 one_argument( argument, arg ); 00090 00091 if( is_number( arg ) ) 00092 { 00093 index = atoi( arg ); 00094 pObj = get_obj_index( index ); 00095 } 00096 else 00097 { 00098 send_to_char( "That is not a number.\n\r", ch ); 00099 return FALSE; 00100 } 00101 00102 SET_BIT( pObj->area->area_flags, AREA_CHANGED ); 00103 00104 /* Remove it from the object list */ 00105 00106 iHash = index % MAX_KEY_HASH; 00107 00108 /* DEBUG CODE - uncomment this if you have doubts */ 00109 /* printf("\nObject hash for location %d:\n", iHash); 00110 for ( tObj = obj_index_hash[iHash]; tObj != NULL; tObj = tObj->next ) 00111 printf("name: %s vnum: %d\n", tObj->name, tObj->vnum ); */ 00112 00113 sObj = obj_index_hash[iHash]; 00114 00115 if( sObj->next == NULL ) /* only entry */ 00116 obj_index_hash[iHash] = NULL; 00117 else if( sObj == pObj ) /* first entry */ 00118 obj_index_hash[iHash] = pObj->next; 00119 else /* everything else */ 00120 { 00121 for( iObj = sObj; iObj != NULL; iObj = iObj->next ) 00122 { 00123 if( iObj == pObj ) 00124 { 00125 sObj->next = pObj->next; 00126 break; 00127 } 00128 sObj = iObj; 00129 } 00130 } 00131 00132 /* If you uncomment this you also need to 00133 find every instance of the object that exists in 00134 the mud and extract them otherwise each of thier 00135 pIndexData will be pointing at free memory. 00136 (Which may or may not contain the actual info) 00137 As it is all the objects will be removed the reboot/login 00138 automatically by fread_obj when it cant find the index */ 00139 00140 /* free_string( pObj->name ); 00141 free_string( pObj->short_descr ); 00142 free_string( pObj->description ); 00143 00144 for( pAf = pObj->affected; pAf; pAf = pAf->next ) 00145 free_affect( pAf ); 00146 00147 for( pExtra = pObj->extra_descr; pExtra; pExtra = pExtra->next ) 00148 free_extra_descr( pExtra ); 00149 00150 free( pObj ); */ 00151 00152 /* DEBUG CODE - uncomment this if you have doubts */ 00153 /* printf("\nObject hash for location %d after removal:\n", iHash); 00154 for ( tObj = obj_index_hash[iHash]; tObj != NULL; tObj = tObj->next ) 00155 printf("name: %s vnum: %d\n", tObj->name, tObj->vnum ); */ 00156 00157 /* DEBUG CODE */ 00158 // printf( "\ntop_vnum_obj before: %d\n", top_vnum_obj ); 00159 00160 if( top_vnum_obj == index ) 00161 for( i = 1; i < index; i++ ) 00162 if( get_obj_index( i ) ) 00163 top_vnum_obj = i; 00164 00165 /* DEBUG CODE */ 00166 // printf( "top_vnum_obj after: %d\n", top_vnum_obj ); 00167 00168 top_obj_index--; 00169 00170 /* Now crush all resets */ 00171 count = 0; 00172 for( iHash = 0; iHash < MAX_KEY_HASH; iHash++ ) 00173 { 00174 for( pRoom = room_index_hash[iHash]; pRoom; pRoom = pRoom->next ) 00175 { 00176 prev = pRoom->reset_first; 00177 for( pReset = pRoom->reset_first; pReset; pReset = pReset->next ) 00178 { 00179 switch( pReset->command ) 00180 { 00181 case 'O': 00182 case 'E': 00183 case 'P': 00184 case 'G': 00185 if( ( pReset->arg1 == index ) || 00186 ( ( pReset->command == 'P' ) && ( 00187 pReset->arg3 == index ) ) ) 00188 { 00189 // printf("\nprev: %d prev->next: %d\n", 00190 //prev, prev->next ); 00191 00192 /* DEBUG CODE - uncomment this if you have 00193 doubts */ 00194 /* printf("\nReset info for room %d:\n", 00195 pRoom->vnum ); 00196 for( tReset = pRoom->reset_first; tReset; 00197 tReset = tReset->next ) 00198 printf("command: %c vnum: %d 00199 memloc:%d\n", tReset->command, tReset->arg1, tReset ); */ 00200 00201 if( pRoom->reset_first == pReset ) 00202 { 00203 pRoom->reset_first = pReset->next; 00204 if( !pRoom->reset_first ) 00205 pRoom->reset_last = NULL; 00206 } 00207 else if( pRoom->reset_last == pReset ) 00208 { 00209 pRoom->reset_last = prev; 00210 prev->next = NULL; 00211 } 00212 else 00213 { 00214 prev->next = prev->next->next; 00215 } 00216 00217 count++; 00218 SET_BIT( pRoom->area->area_flags, 00219 AREA_CHANGED ); 00220 00221 /* DEBUG CODE - uncomment this if you have 00222 doubts */ 00223 /* printf("\nReset info for room %d after 00224 removal:\n", pRoom->vnum ); 00225 for( tReset = pRoom->reset_first; tReset; 00226 tReset = tReset->next ) 00227 printf("command: %c vnum: %d 00228 memloc:%d\n", tReset->command, tReset->arg1, tReset ); */ 00229 00230 // printf("\nprev: %d prev->next: %d\n", 00231 //prev, prev->next ); 00232 } 00233 } 00234 prev = pReset; 00235 } 00236 } 00237 } 00238 00239 sprintf( buf, "Removed object vnum {R%d{x and {R%d{x resets.\n\r", index, 00240 count ); 00241 send_to_char( buf, ch ); 00242 return TRUE; 00243 } 00244 00245 /* 00246 MEDIT( medit_delete ) 00247 { 00248 MOB_INDEX_DATA *pMob; 00249 MOB_INDEX_DATA *sMob; 00250 MOB_INDEX_DATA *iMob; 00251 RESET_DATA *pReset = NULL; 00252 RESET_DATA *prev= NULL; 00253 ROOM_INDEX_DATA *pRoom = NULL; 00254 char arg[MIL]; 00255 char buf[MSL]; 00256 int index, count, iHash, i; 00257 int dobj[100]; I highly doubt one mobile will have 100 unique object 00258 resets 00259 bool foundmob = FALSE; 00260 bool exist = FALSE; 00261 bool foundobj = FALSE; 00262 00263 if ( argument[0] == '\0' ) 00264 { 00265 send_to_char( "Syntax: medit delete [vnum]\n\r", ch ); 00266 return FALSE; 00267 } 00268 00269 one_argument( argument, arg ); 00270 00271 if( is_number( arg ) ) 00272 { 00273 index = atoi( arg ); 00274 pMob = get_mob_index( index ); 00275 } 00276 else 00277 { 00278 send_to_char( "That is not a number.\n\r", ch ); 00279 return FALSE; 00280 } 00281 00282 if( !pMob ) 00283 { 00284 send_to_char( "No such mobile.\n\r", ch ); 00285 return FALSE; 00286 } 00287 00288 SET_BIT( pMob->area->area_flags, AREA_CHANGED ); 00289 00290 Remove it from the object list 00291 00292 iHash = index % MAX_KEY_HASH; 00293 00294 DEBUG CODE - uncomment this if you have doubts */ 00295 /* printf("\nMobile hash for location %d:\n", iHash); 00296 for ( tMob = mob_index_hash[iHash]; tMob != NULL; tMob = tMob->next ) 00297 printf("short_desc: %s vnum: %d\n", tMob->short_descr, tMob->vnum ); 00298 00299 00300 sMob = mob_index_hash[iHash]; 00301 00302 if( sMob->next == NULL ) only entry 00303 mob_index_hash[iHash] = NULL; 00304 else if( sMob == pMob ) first entry 00305 mob_index_hash[iHash] = pMob->next; 00306 else everything else 00307 { 00308 for( iMob = sMob; iMob != NULL; iMob = iMob->next ) 00309 { 00310 if( iMob == pMob ) 00311 { 00312 sMob->next = pMob->next; 00313 break; 00314 } 00315 } 00316 } 00317 00318 See oedit_delete for why i dont free pMob here */ 00319 00320 /* DEBUG CODE - uncomment this if you have doubts */ 00321 /* printf("\nMobile hash for location %d after removal:\n", iHash); 00322 for ( tMob = mob_index_hash[iHash]; tMob != NULL; tMob = tMob->next ) 00323 printf("short_desc: %s vnum: %d\n", tMob->short_descr, tMob->vnum ); 00324 00325 00326 if( top_vnum_mob == index ) 00327 for( i = 1; i < index; i++ ) 00328 if( get_obj_index( i ) ) 00329 top_vnum_obj = i; 00330 00331 top_mob_index--; 00332 00333 Now crush all resets 00334 count = 0; 00335 for( iHash = 0; iHash < MAX_KEY_HASH; iHash++ ) 00336 { 00337 for( pRoom = room_index_hash[iHash]; pRoom; pRoom = pRoom->next ) 00338 { 00339 dobj[0] = -1; 00340 prev = pRoom->reset_first; 00341 for( pReset = pRoom->reset_first; pReset; pReset = pReset->next ) 00342 { 00343 switch( pReset->command ) 00344 { 00345 case 'M': 00346 if( pReset->arg1 == index ) 00347 { 00348 foundmob = TRUE; 00349 00350 DEBUG CODE - uncomment this if you have 00351 doubts 00352 printf("\nReset info for room %d:\n", 00353 pRoom->vnum ); 00354 for( tReset = pRoom->reset_first; tReset; 00355 tReset = tReset->next ) 00356 printf("command: %c vnum: %d\n", 00357 tReset->command, tReset->arg1 ); 00358 00359 if( pRoom->reset_first == pReset ) 00360 { 00361 pRoom->reset_first = pReset->next; 00362 if( !pRoom->reset_first ) 00363 pRoom->reset_last = NULL; 00364 } 00365 else if( pRoom->reset_last == pReset ) 00366 { 00367 pRoom->reset_last = prev; 00368 prev->next = NULL; 00369 } 00370 else 00371 prev->next = prev->next->next; 00372 00373 count++; 00374 SET_BIT( pRoom->area->area_flags, 00375 AREA_CHANGED ); 00376 00377 DEBUG CODE - uncomment this if you have 00378 doubts 00379 printf("\nReset info for room %d after 00380 removal:\n", pRoom->vnum ); 00381 for( tReset = pRoom->reset_first; tReset; 00382 tReset = tReset->next ) 00383 printf("command: %c vnum: %d\n", 00384 tReset->command, tReset->arg1 ); 00385 00386 } 00387 else 00388 foundmob = FALSE; 00389 00390 break; 00391 case 'E': 00392 case 'G': 00393 if( foundmob ) 00394 { 00395 // printf( "Removing: command: %c vnum: 00396 %d\n", pReset->command, pReset->arg1 ); 00397 00398 DEBUG CODE - uncomment this if you have 00399 doubts 00400 * printf("\nReset info for room %d:\n", 00401 pRoom->vnum ); 00402 for( tReset = pRoom->reset_first; tReset; 00403 tReset = tReset->next ) 00404 printf("command: %c vnum: %d\n", 00405 tReset->command, tReset->arg1 ); 00406 00407 exist = FALSE; 00408 00409 for( i = 0; dobj[i] != -1; i++ ) 00410 { 00411 if( dobj[i] == pReset->arg1 ) 00412 { 00413 exist = TRUE; 00414 break; 00415 } 00416 } 00417 00418 if( !exist ) 00419 { 00420 dobj[i] = pReset->arg1; 00421 dobj[i + 1] = -1; 00422 00423 DEBUG CODE 00424 for( i = 0; dobj[i] != -1; i++ ) 00425 printf( "dobj[%d] : %d\n", i, 00426 dobj[i] ); 00427 } 00428 00429 if( pRoom->reset_first == pReset ) 00430 { 00431 pRoom->reset_first = pReset->next; 00432 if( !pRoom->reset_first ) 00433 pRoom->reset_last = NULL; 00434 } 00435 else if( pRoom->reset_last == pReset ) 00436 { 00437 pRoom->reset_last = prev; 00438 prev->next = NULL; 00439 } 00440 else 00441 prev->next = prev->next->next; 00442 00443 count++; 00444 SET_BIT( pRoom->area->area_flags, 00445 AREA_CHANGED ); 00446 00447 DEBUG CODE - uncomment this if you have 00448 doubts 00449 printf("\nReset info for room %d after 00450 removal:\n", pRoom->vnum ); 00451 for( tReset = pRoom->reset_first; tReset; 00452 tReset = tReset->next ) 00453 printf("command: %c vnum: %d\n", 00454 tReset->command, tReset->arg1 ); 00455 } 00456 00457 break; 00458 case 'P': 00459 foundobj = FALSE; 00460 00461 for( i = 0; dobj[i] != -1; i++ ) 00462 if( dobj[i] == pReset->arg3 ) 00463 foundobj = TRUE; 00464 00465 if( foundobj ) 00466 { 00467 printf( "Removing: command: %c vnum: %d\n", 00468 pReset->command, pReset->arg1 ); 00469 00470 * DEBUG CODE - uncomment this if you have 00471 doubts 00472 printf("\nReset info for room %d:\n", 00473 pRoom->vnum ); 00474 for( tReset = pRoom->reset_first; tReset; 00475 tReset = tReset->next ) 00476 printf("command: %c vnum: %d\n", 00477 tReset->command, tReset->arg1 ); 00478 00479 if( pRoom->reset_first == pReset ) 00480 { 00481 pRoom->reset_first = pReset->next; 00482 if( !pRoom->reset_first ) 00483 pRoom->reset_last = NULL; 00484 } 00485 else if( pRoom->reset_last == pReset ) 00486 { 00487 pRoom->reset_last = prev; 00488 prev->next = NULL; 00489 } 00490 else 00491 prev->next = prev->next->next; 00492 00493 count++; 00494 SET_BIT( pRoom->area->area_flags, 00495 AREA_CHANGED ); 00496 00497 DEBUG CODE - uncomment this if you have 00498 doubts 00499 printf("\nReset info for room %d after 00500 removal:\n", pRoom->vnum ); 00501 for( tReset = pRoom->reset_first; tReset; 00502 tReset = tReset->next ) 00503 printf("command: %c vnum: %d\n", 00504 tReset->command, tReset->arg1 ); 00505 } 00506 } 00507 prev = pReset; 00508 } 00509 } 00510 } 00511 00512 This is a dumb way to fix what is probably someone elses problem 00513 * The reason for the kludge is that sometime after the exit of 00514 medit_delete 00515 ch->mount becomes 0x10000000 and I have no idea how or where 00516 00517 if( ch->mount == NULL ) 00518 medit_delete_kludge = ch; 00519 00520 sprintf( buf, "Removed mobile vnum ^C%d^x and ^C%d^x resets.\n\r", index, 00521 count ); 00522 send_to_char( buf, ch ); 00523 return TRUE; 00524 } 00525 */ 00526 /* 00527 -- 00528 00529 0o0o0o0o0o0o0o0o0o0o0o00o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0 00530 o Chris Feist GCS/GMUd-s+:-a--C++++USUH$ULU+++P++L++E-W-N++o?Kw-- o 00531 o Dept 7M52 O?M++V-PS+PEY+PGP+t+5+X-Rtv+b++DI++D++Ge++@hr--!y+ 0 00532 0 SS7 Verification o 00533 o feist@nortel.ca George Bush: "It's amazing how many people beat you 0 00534 0 at golf now that you're no longer president." o 00535 o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0o0 00536 */
1.4.0