Graal Forums

Graal Forums (https://forums.graalonline.com/forums/index.php)
-   NPC Scripting (https://forums.graalonline.com/forums/forumdisplay.php?f=8)
-   -   SQL Item control serious lag! (https://forums.graalonline.com/forums/showthread.php?t=86266)

[email protected] 06-10-2009 04:28 PM

SQL Item control serious lag!
 
HTML Code:

  //Perform a function
public function getSQL(query) {
  temp.req = requestSQL(temp.query, true);
 
  if (!temp.req.completed) return null;
  if (temp.req.error != "") echo(temp.req.error);
 
  return temp.req;
}
 
  //EntryID/Account/ItemID
public function onItem(id, quantity, itemdata) { 
    //The players amount
  temp.rquantity = _getitem(temp.id, "quantity");
 
    //If the player has the item just modify the amount
  if (temp.rquantity != null) {
    temp.rquantity = temp.rquantity + temp.quantity;
    _setitem(temp.id, "quantity", temp.rquantity);
      //Update the item clientside
    _senditemtrigger(temp.id, {"quantity", temp.rquantity}, "itemflag");
  } else {
   
      //If not, re-load the variables & add to player
    temp.itemdata = this.onItemData(temp.id);
   
      //Report of possible glitch- item doesn't exist
    if (temp.itemdata == null) {
   
        //Clear the items data...
      _clearitem(temp.id);
     
        //Alert RC 
      echo("Invalid Item:" SPC temp.id);
      echo("Invalid Item: Item doesn't exist- possible hack?");
      echo("Invalid Item:" SPC this SPC this.level.name SPC this.x SPC this.y);
      return false;
    }
   
    temp.data = new TStaticVar();
      //Load the item data
    temp.data.loadvarsfromarray(temp.itemdata);
    for (temp.i: temp.data.getdynamicvarnames()) {
        //Set the item data
      _setitem(temp.id, temp.i[0], temp.i[1]);
    }
   
      //Now add the weapon to the player
    this.addWeapon(_get(temp.id, "useweapon")[0]);
   
      //Now set the quantity of the item
    _setitem(temp.id, "quantity", temp.quantity);
   
      //Now, let's add this item clientside
    temp.data = temp.data.savevarstoarray(false);
    _senditemtrigger(temp.id, temp.data);   
  }
}

  //Sends the item clientside
function _senditemtrigger(id, itemdata, mode) {
    //Let's set the method of the item
  temp.method = "ItemNew";
    //If the mode does exist, change method
  if (temp.mode == "itemflag") {
      //Let's just change an item flag not a full item
    temp.method = "ItemFlag";
  }

  this.triggerclient("weapon", "-Player", "UpdateVariable", temp.method, temp.id, temp.itemdata, temp.mode);
}

  //Adding a flag to an item
public function _setitem(id, flag, value) { 
  player.items.(@ temp.id).(@ temp.flag) = temp.value;
}

  //Returning a flag from an item
public function _getitem(id, flag) {
  temp.value = player.items.(@ temp.id).(@ temp.flag);
  if (temp.flag in {"sprite", "icon"}) {
    temp.value @= ".png";
  }
 
  return temp.value;
}

  //Deleting an item from a player
public function _clearitem(id) { 
    //First clear the item data
  player.items.(@ temp.id) = "";
  player.items.(@ temp.id).clearvars();
  player.items.clearemptyvars();
}

  //Get the item data from the server
public function onItemData(id) {
  return ("Control-Items").getItemData(temp.id);
}

  //Loading the players items from the SQL database
public function onLoadItems(toreturn) {
    //Load the players items from the SQL
  temp.query = this.getSQL("SELECT * FROM items WHERE account = '" @ this.account @ "'");

    //Create an array containing all the data
  temp.charitems = new TStaticVar();
  for (temp.row: temp.query.rows) {
      //Now, let's add this item clientside
    _senditemtrigger(temp.row.item_id, temp.row.item_data, "SQL");
      //and also make a list of the items the player has
    temp.charitems.items.(@ temp.row.item_id).loadvarsfromarray(temp.row.item_data);
  }
 
    //Return the item data  (temp.items.getdynamicvarnames)
  if (temp.toreturn) {
    return temp.charitems.items;
  }

    //Clear the players items variable
    //and then load it.
  player.items = new TStaticVar();
  player.items.copyFrom(temp.charitems.items); 
  this.onLoadWeapons();
}

  //Save the players items to the SQL
public function onSaveItems() {
    //Delete the items that the player has in the SQL
  this.getSQL("DELETE FROM items WHERE account = '" @ this.account @ "'");
 
    //Load the players items
  for (temp.i: this.onGetItemList()) {
      //Reset the item data
    temp.itemdata = new TStaticVar();
      //Load the vars and save to an array
    temp.itemdata = player.items.(@ temp.i).savevarstoarray(false);
   
      //If the flags don't exist, ignore the item
    if (temp.itemdata.size() == 0) continue;

      //And save it to the SQL
    this.getSQL("INSERT INTO items (account, item_id, item_data) VALUES ('" @ this.account @ "', '" @ temp.i @ "','" @ temp.itemdata @ "')");
  }
}

  //Returns the item list
public function onGetItemList() {
  return player.items.getdynamicvarnames();
}

  //Adds all the weapons from the items
public function onLoadWeapons() {
    //Load the items list
  for (temp.i: this.onGetItemList()) {
      //Now add the weapon to the player
    this.addWeapon(_getitem(temp.i, "useweapon").tokenize()[0]);
  }
}

Following the simple table

HTML Code:

Entry ID, Account, Item ID, Item Data
Well, right now it's loading 250< items from my character on login. That's not alot- right? Wrong
Here's the output
HTML Code:

1. 1.458490023 - Control-NPC (functions_projectiles)
2. 0.163530085 - Graal707396 (player_functions_login,player_functions_items,player_functions_health)

It's taking a while to load the items, can anyone think of a better solution?

It's also causing serious lag when sending all the item data clientside. Does anyone else have these kind of problems?

It's only happening when sending quite alot of data to the clientside

Here's a few examples of the item data

HTML Code:

  this.item_Overalls_Aqua = {
    {"id", "Overalls_Aqua"},
    {"category", "coat"},
    {"gender", "male"},
    {"icon", "bi_ico_coat_a_m_004-aqua.png"},
    {"iname", "Overalls (Aqua)"},
    {"iname_m", "Overalls (Aqua)"},
    {"info", "A aqua heavy duty pants that are worn over a tunic. Often adored by fat plumbers."},
    {"info_m", "Some aqua heavy duty pants that are worn over a tunic. Often adored by fat plumbers."},
    {"options", "wd"},
    {"sprite", "bi_coat_a_m_004-aqua.png"},
    {"useweapon", {"ControlDress", "coats", "sprite"}}
  };

  this.item_Overalls_Black = {
    {"id", "Overalls_Black"},
    {"category", "coat"},
    {"gender", "male"},
    {"icon", "bi_ico_coat_a_m_004-black.png"},
    {"iname", "Overalls (Black)"},
    {"iname_m", "Overalls (Black)"},
    {"info", "A black heavy duty pants that are worn over a tunic. Often adored by fat plumbers."},
    {"info_m", "Some black heavy duty pants that are worn over a tunic. Often adored by fat plumbers."},
    {"options", "wd"},
    {"sprite", "bi_coat_a_m_004-black.png"},
    {"useweapon", {"ControlDress", "coats", "sprite"}}
  };


DustyPorViva 06-10-2009 04:30 PM

More specifically, upon loading(most likely on login), the client can freeze up to >30 seconds, trying to load all the items. At least that was my personal experience. It wasn't slow-down or anything, but absolutely nothing happening and unable to do anything(screen stops refreshing).

Robin 06-10-2009 07:48 PM

So you're getting every item and sending it to the client?

Why would you do that?

[email protected] 06-10-2009 08:04 PM

Quote:

Originally Posted by Robin (Post 1498439)
So you're getting every item and sending it to the client?

Why would you do that?

What do you suggest... loading it in one big trigger?

Robin 06-10-2009 08:14 PM

Maybe I don't understand what you're doing here.. But as far as I can see, you're loading all of the player's items and then adding them as Weapons.. but you're sending the client all the data from the database?

I'm not going to pretend to know about the way the NPC Server works with SQL (Seeing as, this is the first time I've ever seen it mentioned) but when dealing with web development, game development, business databases, you tend to certainly not ever "SELECT * FROM `table`", limit your data, give the client a chance, load it in parts.

For example, I built a system to show different reports of user statistics of my company's app. It'd work fine in Firefox, but in IE6 (one of our main customer's only browser x-x) it would crash it, or make it hang.

By loading the page, then subsequently loading the data via AJAX and creating the flash based charts sequentially as they were needed, rather than every bit of data being downloaded at once, not only did it not crash anymore but it was FAST.

I'm thinking the problem here is a mixture of limitations of the client and the ineffciency of the code in relation to how you're pulling the data from the database.

Do you have control over the tables? i.e. the ability to add proper indexes and keys?

cbk1994 06-10-2009 09:32 PM

Well, I can't really see this being fast. You're getting the items from a place where, as far as I know, is not stored in memory, then loading the data from an array, which isn't exactly efficient.

There must be something I don't know, because I never even considered using SQL for an item system for this reason. Please correct me if I'm wrong ;).

Robin 06-10-2009 09:59 PM

If you properly index and normalise your database it can be very fast. Stefan could even hazard installing some kind of caching like Memcached for storing objects.

Codein 06-10-2009 10:24 PM

Hrm, yeah, I agree with Robin. I've been messing around, thought it'd be nice to test speeds, and SQL seems to be faster at retrieving data. However, I was using a very small sample of data (one row, two colums) and two variables in a text file.

Maybe someone could do something on Testbed with a larger sample or something.

Inverness 06-11-2009 01:30 AM

Are you using transactions when making changes to the database? And is your items table indexed by account?

If the answer is no to either then I have no sympathy for you because you decided to charge head-first into SQLite without learning how it works.

If you're saving the player's item data en masse to the database then you're doing it wrong. If you only load data from the SQL on login and only save on logout (or periodically en masse) then you're using it wrong.

[email protected] 06-11-2009 05:54 PM

Quote:

Originally Posted by Inverness (Post 1498537)
Are you using transactions when making changes to the database? And is your items table indexed by account?

If the answer is no to either then I have no sympathy for you because you decided to charge head-first into SQLite without learning how it works.

If you're saving the player's item data en masse to the database then you're doing it wrong. If you only load data from the SQL on login and only save on logout (or periodically en masse) then you're using it wrong.

Ahh- yes I am only loading/saving it on login/logout & loading it from the database. What do you suggest using to avoid this?


All times are GMT +2. The time now is 12:44 PM.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2026, vBulletin Solutions Inc.
Copyright (C) 1998-2019 Toonslab All Rights Reserved.