Graal Forums

Graal Forums (http://forums.graalonline.com/forums/index.php)
-   Code Gallery (http://forums.graalonline.com/forums/forumdisplay.php?f=179)
-   -   Dump Useless Local NPCs (http://forums.graalonline.com/forums/showthread.php?t=134269017)

100Zero100 01-18-2014 07:17 PM

Dump Useless Local NPCs
 
I made this script in 2011-2012 and it worked a bit differently (some stuff was changed it seems). Basically the idea is to delete any putnpc2's that exist on the server, in levels that no longer exist.

The first time running the script on UN (2011-2012) reduced their local NPCs from ~4950 to ~690. Running it on UN earlier today reduced their local NPCs from ~6k to ~4k. Running it on Era about an hour ago reduced their local NPCs from > 10k (loadFolder only goes up to 10k entries) to ~3k after 2 presses (first press: ~6k. second press: ~3k). I've had good experiences with it reducing NPC server startup times as well as NC load times (for servers with slow NCs).

It's part of a bigger NPC. I just snipped this part since it seems the most universal.

Graal Script Code:

// NaS
const tempFolder "temp/";
const 
npcFolder "npcs/";
const 
prefix "npclocalnpc";
const 
ext ".nw";

function 
onCreated() {
 
purgeLocal();
}
function 
purgeLocal() {
 
temp.folder.loadFolder(npcFolder prefix "*",0);
 
temp.oldSize folder.size();
 for (
temp.fileNamefolder) {
  
temp.file removeEscapesFromFileName(fileName);
  
temp.tokens file.tokenize("_");
  
temp.endlen tokens[tokens.size() - 1].length() + tokens[tokens.size() - 2].length() + 3;
  
temp.lvl file.substring(prefix.length() + 1file.length() - prefix.length() - endlen) @ ext;
  if (!
levelExists(lvl)) {
   
moveFile(npcFolder fileNametempFolder fileName);
   
deleteFile(tempFolder fileName);
  }
 }
 
temp.folder.loadFolder(npcFolder prefix "*",0);
 
temp.newSize folder.size();
 echo(
format("Local NPC count went from %i to %i."oldSizenewSize));


Your NPC server needs rw to the npcs/npclocalnpc* and it also needs rw to some temporary folder (I put temp/, but it can be anything else; defined in const tempFolder). Likely needs 'r' to all of your levels in order for the levelExists() check to run. You can remove the rw when you're done.

Basically, since sometime in 2012 you can no longer deleteFile() anything in npcs/ (even with npc server rw and protectdbnpcs=false in server ops (I tested, jic)), but you can still moveFile() them to another folder and delete them there. It's an unfortunate nuisance, but so it is.

It outputs how many local NPCs were deleted in an echo(), so let me know if your results are interesting.

BlueMelon 01-18-2014 07:52 PM

vouch

best thing under atrius

xAndrewx 01-19-2014 08:10 AM

Hey Nas <3

Pretty cool- I suppose it only helps on server load up.

A plan for the future is to delete the levels if they are not being used and re-create the level when needed and keep the putnpcs (for houses / gang houses etc)

100Zero100 01-19-2014 01:16 PM

Quote:

Originally Posted by xAndrewx (Post 1725290)
Hey Nas <3

Pretty cool- I suppose it only helps on server load up.

A plan for the future is to delete the levels if they are not being used and re-create the level when needed and keep the putnpcs (for houses / gang houses etc)

Levels are not loaded into server memory by default. They are simply in the server's HDD and load when a player enters (and they unload from memory like 5-10 minutes later), same as all level NPCs inside of them. In addition, all this.savelocally putnpc2's function the same.

This script addresses only the putnpc2's that aren't this.savelocally that exist inside of levels that are now deleted. You could expand the script (simply make it recursive) to check the this.savelocally ones, but I saw no need (as they are not in the server's memory anyway). I suppose that could help with file browser opening speed, though (or you can just not give yourself rw to that part of the file browser in the first place! ie "-rw npcs/*/*").

The putnpc2's that don't save locally load up when the NPC server is loaded and are loaded into your NC when you load into the server, so they do create lag in NC loadtimes and NPC server restarting. Additionally, I suspect that a lot of the putnpc2's that exist in defunct levels could likely be the result of corrupt ex-staff who added them to do possibly malicious things (Delete levels, add gralats, whatever).

As an aside, if you wanted to get "serious" with putnpc removal, you may couple this script with another script (or slightly modify it) to detect which levels have the most NPCs, via the same methodology.

Here is a (hack-ish) quick version I made with the script I posted above:

Graal Script Code:

// NaS
const npcFolder "npcs/";
const 
prefix "npclocalnpc";
const 
ext ".nw";
const 
tempFolder "";

function 
onCreated() {
 
temp.folder.loadfolder("npcs/npclocalnpc*"0);
 echo(
"local npcs:" SPC folder.size());
 
npcInfo();
}
function 
npcInfo() {
 
temp.folder.loadFolder(npcFolder prefix "*",0);
 for (
temp.fileName:folder) {
  
temp.file removeescapesfromfilename(fileName);
  
temp.tokens file.tokenize("_");
  
temp.endlen tokens[tokens.size() - 1].length() + tokens[tokens.size() - 2].length() + 3;
  
temp.lvl file.substring(prefix.length() + 1file.length() - prefix.length() - endlen) @ ext;
  
  if (!(
lvl in temp.lvls)) {
   
temp.lvls.add(lvl);
  }
  
temp.(@lvl)++;
 }
 
temp.amount 0;
 
temp.biggest "";
 for (
temp.lvllvls) {
  if (
temp.(@lvl) > amount) {
   
amount temp.(@lvl);
   
biggest lvl;
  }
 }
 echo(
format("most putnpcs in %s with %i"biggestamount));


Like I said, it's a "hack-ish" fix I threw together (not going for efficiency on this one, just functionality). You run it and it simply echos which level has the most putnpc's.

When I ran it on UN (we had 4k putnpc2's left yesterday when I ran the first script), it got 1.1k hits in 1 level from an old quest. We dumped that level and ran it again and got about 800 NPCs from a spar tourney viewer (the tourney viewers weren't destroying on the serverside properly). We fixed the glitch and dumped that level. We did that for about 5 things.

Then we saw the bulk of the putnpc's left (I checked npcs/ myself for them, which was now loadable!) were of the classes: gralats, gralats_death, newhatdrop, and epdrop.

Those are items players can drop and give to other players. So I simply added an onInitialized() destroy(); clause on them, and rebooted the NPC server; let's be real, that kind of stuff shouldn't be expected to persist a server restart anyway. In the rare event that we reboot the npc server while a player was dropping a hat, we have logging for that anyway.

The remaining NPCs were from the playerhouse system, so we added this.savelocally to those NPCs. All-in-all, we only had about 60 putnpc's left after all of that. I went through them all personally (took about 10-15 min) and they were old BS classes that just forgot to destroy (or just had no script in them), so I just deleted them manually.

In total, the whole project took about 1-1.5 hours, but lowered UN's putnpc2 count from ~6k to 0. But I figure if you just want a quick-fix to remove a bunch of putnpc2's that nobody is using anymore, that script up top is a one-press solution to at least a few thousand!

Chompy 01-20-2014 09:16 PM

Did something like this on the Testbed server back in 2009. This was due the to the fact scripters loved to upload staff tools and write their name with thousands of staff blocks. Best part? putnpcs with non-existing classes

Graal Script Code:

/*
    Used to clear classes from levels.
    
    By classes I mean staffsigns, staffblocks etc.
    
    just edit 'temp.class' to what class to search for..
    Also remove the 'return;' to enable
      (Comment it out for fast toggling)
    
    -Chompy
*/

/*
  2.feb.09
  
  Most used classes:
  
  1. shared_blocks: 552 times
  
  -- After cleaning --
  
  Found 546x (shared_blocks) in new1.nw
  
  ------------------------------ 1th may
  
  Found 186x (shared_blocks) in firstscript1.nw
  Found 2x (shared_blocks) in jail_outside.nw
  Found 520x (shared_blocks) in era_sewerph-house14-1.nw
  Found 1x (shared_blocks) in ce_shop1.nw
  Found 1x (shared_blocks) in ******.nw
  Found 1x (shared_blocks) in ******.nw

*/

function onCreated() {
  
temp.paths findfiles("*.nw"1);
  
temp.class = "shared_blocks";
  
  return;
  
  for(
temp.path paths) {
    
temp.pos path.tokenize("/");
    
temp.lvl pos[pos.size()-1];
    
temp.lvl2 findlevel(lvl);
    
temp.blocks 0;
    for(
temp.lvl2.npcs) {
      if (class 
in n.joinedclasses) {
        
blocks ++;
        
n.destroy();
      }
    }
    if (
blocks 0) {
      echo(
"Found "blocks @"x ("@[email protected]") in "lvl2.name);
    }
  }


Simply you would do /stats in RC chat, then look for the classes that occured to the most, and put that class name in the script, and it would look through levels for that class and destroy it.

Very old script, never optimized it or anything, but it takes a little different approach than yours.

I think you only need r to the folders the levels are in if I'm not mistaken, can't remember. Found this in an old testbed server backup

NB! Yes, you have no idea how often I saw era weapons, levels and whatever era stuff on the testbed stuff. was so fun deleting it. Most popular server's stuff to mess around in 2009 on testbed.

Torankusu 03-11-2014 01:35 AM

Quote:

Originally Posted by 100Zero100 (Post 1725281)
(loadFolder only goes up to 10k entries)

I am using loadfolder for a different application, but am running into this issue.

I cannot decrease my amount and re-run the script, however.

Do you have any recommendations for checking entries > 10,000 ?


All times are GMT +2. The time now is 01:18 AM.

Powered by vBulletin® Version 3.8.3
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
Copyright (C) 1998-2008 Linux cyberjoueurs All Rights Reserved.