Official Community Forums
 
HomeHome  FAQFAQ  SearchSearch  MemberlistMemberlist  UsergroupsUsergroups  RegisterRegister  Log in  The Wiki  Website  github Project  

Share | 
 

 Noob Question: about accessing templates.py NAMESPACE variables from MarsContainer

View previous topic View next topic Go down 
AuthorMessage
TheWatcher
Experienced Newbie
Experienced Newbie


Posts : 21
Join date : 2011-10-18
Location : Blue Cone Rookery(actually, California)

PostSubject: Noob Question: about accessing templates.py NAMESPACE variables from MarsContainer   Wed 21 Nov - 16:35

Noob Question: about accessing templates.py NAMESPACE variables from MarsContainer

I need to access/modify 'StackSize' info variables that were set up in templates.py .
But I can't seem to get access to them from MarsContainer.py .
I've tried the template.get(...) and template.put(...) commands in the form of;

item.get(InventoryClient.ITEM_NAMESPACE, "StackSize")

but I get errors like:

.... System.MissingMemberException instance has no attribute 'get' .....


I've tried various ways to try to access the info but always get an error similar to the one above.

Can anyone tell me what I'm doing wrong?

Thanks for any help you can give me.

TheWatcher
Back to top Go down
Delurin
Head of Platform Development


Posts : 424
Join date : 2011-08-03

PostSubject: Re: Noob Question: about accessing templates.py NAMESPACE variables from MarsContainer   Tue 27 Nov - 9:28

It took me a little bit to figure out what you were asking.
On the client side by default the only things sent for an item are listed in the _HandleInventoryUpdate. It does not send the whole item entity to the client so you cant access the item properties. There are two ways you could get the data to the client...send the data separately by requesting the information or modifying the InventoryUpdateMessage but since it is a hardcode class you would need to modify both the server and client.

The other option which I recommend is to replace the inventoryupdatemessage with your own extendable version and process it like a normal extension message. That way you can send the information that you want and make easy changes to it in python instead of recompiling the client.
Back to top Go down
TheWatcher
Experienced Newbie
Experienced Newbie


Posts : 21
Join date : 2011-10-18
Location : Blue Cone Rookery(actually, California)

PostSubject: Re: Noob Question: about accessing templates.py NAMESPACE variables from MarsContainer   Tue 27 Nov - 10:56

I spent 80+ hours over the last 9 days learning about the inner workings of the engine. (And that was not going into the server source code any to speak of.) Last night, I had finally come to the conclusion that you indicate in your first paragraph. (The property data in the server items is not sent to the client.) And I didn't see any easy way to send property data back to the server from the client. Not only that, but the client code presently has the existing count value hardwired to the container slot and not to the items themselves. And that count value was hardwired to 0.

I'm going to have to think about what I'll do. I used to consider myself a fairly good 'C' programmer, but if it's going to take me 20 to 40 or 80 hours for each little thing I want to add.... Well, this is giving me a little self confidence crisis right now.

I need to get my head out of this for a day or so and see if I can recover.

Thanks for the reply and help.

TheWatcher
Back to top Go down
Delurin
Head of Platform Development


Posts : 424
Join date : 2011-08-03

PostSubject: Re: Noob Question: about accessing templates.py NAMESPACE variables from MarsContainer   Tue 27 Nov - 13:22

It is understandable...I think that the inventory system was something that they did a disappointing job architecting. That coupled with it being basically hard coded makes it extremely difficult to work with. At least now we have the capability to modify the system or at least by pass. If I have some time I will try to write some of the code you will need to put in the stacking.
The basic architecture I would recommend is to leave the bag system like it currently is.
ServerSide
Add a Property of stackSize and a property count to each item. -looks like you figured this out.
Replace the inventoryMessage with a new extension message.
Modify createItem to check if there is already and item and if the count is less than the stack size add to the count otherwise create a new item.
Create a new function to split a stack.
Modify MarsAbility to decrease/remove an item upon use if it is consumed

ClientSide
Replace _HandleInventoryUpdate handler
Add split ui? Not sure off the top of my head the best way to do this.
Add number to the icon -Looks like this is done

I will try to post tomorrow with some code snippets if i can


It may not be the easiest Game Engine to use but it is free and open source and the backend is incredibly efficient and scalable.
Back to top Go down
Delurin
Head of Platform Development


Posts : 424
Join date : 2011-08-03

PostSubject: Re: Noob Question: about accessing templates.py NAMESPACE variables from MarsContainer   Wed 28 Nov - 2:00

Ill post each file change as a separate post
Modify MarsItem and add these properties


Code:
    public void setCount(Integer count){
       lock.lock();
       try{
          setProperty("count",count);
       }finally{
          lock.unlock();
       }
    }
   
    public Integer getCount(){
       lock.lock();
       try{
          Integer count = (Integer)getProperty("count");
          if (count == null){
             return 1;
          }
          return count;
       }finally{
          lock.unlock();
       }
    }
   
   
    public void setStackSize(Integer stackSize){
       setProperty("stackSize",stackSize);
    }
   
    public Integer getStackSize(){
          Integer stackSize = (Integer)getProperty("stackSize");
          if (stackSize == null){
             return 1;
          }
          return stackSize;
    }
Back to top Go down
Delurin
Head of Platform Development


Posts : 424
Join date : 2011-08-03

PostSubject: Re: Noob Question: about accessing templates.py NAMESPACE variables from MarsContainer   Wed 28 Nov - 7:24

In MarsInventoryPlugin change the sendInvUpdate and sendInvUpdateHelper to this:
Code:
protected void sendInvUpdate(Long mobOid)
   {
      Log.debug("SendingInventoryUpdate");
      TargetedExtensionMessage invUpdateMsg = new TargetedExtensionMessage(mobOid);
      invUpdateMsg.setExtensionType("mv.INVENTORY_UPDATE_MSG");
      // go through each bag and place contents into inv update msg
      Bag rootBag = getBag(mobOid);
      Long[] items = rootBag.getItemsList();
      LinkedList<LinkedList<Object>> itemsList = new LinkedList<LinkedList<Object>>();
      for (int pos = 0; pos < items.length; pos++) {
         Long subBagOid = items[pos];
         if (subBagOid == null) {
            log.error("sendInvUpdate: sub bag oid is null");
            continue;
         }
         Bag subBag = getBag(subBagOid);
         if (subBag == null) {
            log.error("sendInvUpdate: sub bag obj is null");
            continue;
         }

         sendInvUpdateHelper(itemsList, pos, subBag);
      }
      invUpdateMsg.setProperty("inventory", itemsList);
      Engine.getAgent().sendBroadcast(invUpdateMsg);
   }

   protected void sendInvUpdateHelper(LinkedList<LinkedList<Object>> itemsList, int bagNum, Bag subBag) {
      Long[] items = subBag.getItemsList();
      
      for (int pos = 0; pos < items.length; pos++) {
         // get the item
         LinkedList<Object> itemList = new LinkedList<Object>();
         Long oid = items[pos];
         if (oid == null) {
            continue;
         }
         MarsItem item = getMarsItem(oid);
         if (item == null) {
            Log.warn("sendInvUpdateHelper: item is null, oid=" + oid);
            continue;
         }
         log.debug("sendInvUpdateHelper: adding bagNum=" + bagNum + ", bagPos=" + pos +
                  ", itemOid=" + oid + ", itemName=" + item.getName() + ",icon=" + item.getIcon() + ", count = " + item.getCount() + ", stacksize = " + item.getStackSize());
         itemList.add(item.getOid());
         itemList.add(item.getName());
         itemList.add(bagNum);
         itemList.add(pos);
         itemList.add(item.getIcon());
         itemList.add(item.getCount());
         itemList.add(item.getStackSize());
         itemsList.add(itemList);
      }
   }

This bypasses the hard coded inventory update message. You probably dont need to send the stack size.

Next replace the CreateItem and AddItem functions
Code:
   protected boolean createItem(Long playerOid, String itemName){
      Template itemTemplate = ObjectManagerClient.getTemplate(itemName);
      Log.debug("CreateItem");
      Long itemOid = null;
      if (itemTemplate != null){
      Map <String,Serializable>props = itemTemplate.getSubMap(InventoryClient.ITEM_NAMESPACE);
      if (props.containsKey("unique")){
         Log.debug("Item should be unique");
         itemOid = InventoryClient.findItem(playerOid, itemName);
         if (itemOid != null){
            //Should probably send a message to the player that they already have the item
            return false;
         }
      }
      if (props.containsKey("stackSize")){
         log.debug("item is stackable");
         int count = 1;
         if (props.containsKey("count")){
            count = (Integer)props.get("count");
         }
         ArrayList<String> templates  = new ArrayList<String>();
         templates.add(itemName);
         List<Long> itemOids = InventoryClient.findItems(playerOid, templates);
         for (Long tempItemOid : itemOids){
            MarsItem tempItem = getMarsItem(tempItemOid);
            lock.lock();
            try{
            if (tempItem.getCount() + 1 <= tempItem.getStackSize()){
               int space = tempItem.getStackSize() - tempItem.getCount();
               if (space >= count){
                  tempItem.setCount(tempItem.getCount() +count);
                  return true;
               }else{
                  count = count - space;
                  tempItem.setCount(tempItem.getCount() + space);
               }
            }
            }finally{
               lock.unlock();
            }
         }
         log.debug("No items to add item to or all are full");
         
      }
      }
      
      Template overrideTemplate = new Template();
      overrideTemplate.put(Namespace.OBJECT_MANAGER,
            ObjectManagerClient.TEMPL_PERSISTENT, true);
      itemOid = ObjectManagerClient.generateObject(
            itemName, overrideTemplate);
      // add to inventory
      Long bagOid = playerOid;
      Log.debug("processReqConcludedMsg: createitem: oid="
               + itemOid + ", bagOid=" + bagOid
               + ", adding to inventory");
      boolean rv = InventoryClient.addItem(bagOid, playerOid, bagOid,
            itemOid);
      Log.debug("processReqConcludedMsg: createitem: oid="
               + itemOid + ", added, rv=" + rv);

      return rv;

   }


   protected boolean addItem(Long mobOid, Long rootBagOid, Long itemOid) {
      lock.lock();
      try {
         // get bag
         Bag rootBag = getBag(rootBagOid);

         if (Log.loggingDebug)
            log.debug("addItem: found bag object: " + rootBag);

         // get item
         Entity item = getMarsItem(itemOid);
         if (item == null) {
            item = getBag(itemOid);
         }
         if (item == null) {
            Log.warn("addItem: item is null: oid=" + itemOid);
            return false;
         }
         Map <String,Serializable>props = item.getPropertyMap();
         if (props.containsKey("stackSize") && item.getName() != null){
            log.debug("item is stackable");
            int count = 1;
            if (props.containsKey("count")){
               count = (Integer)props.get("count");
            }
            log.debug("count = " + count);
            lock.unlock();
            ArrayList<String> templates  = new ArrayList<String>();
            templates.add(item.getName());
            List<Long> itemOids = InventoryClient.findItems(mobOid, templates);
            lock.lock();
            for (Long tempItemOid : itemOids){
               Log.debug("TempOid = " + tempItemOid);
               if (tempItemOid == null)
                  continue;
               MarsItem tempItem = getMarsItem(tempItemOid);
               

               if (tempItem.getCount() + 1 <= tempItem.getStackSize()){
                  int space = tempItem.getStackSize() - tempItem.getCount();
                  if (space >= count){
                     tempItem.setCount(tempItem.getCount() +count);
                     log.debug("count = " + count);
                     return true;
                  }else{
                     count = count - space;
                     tempItem.setCount(tempItem.getCount() + space);
                  }
               }
               
            }
            log.debug("No items to add item to or all are full");
            
         }
         log.debug("addItem: found item: " + item);
         Integer unique = (Integer)item.getProperty("unique");
         log.debug("unique = " + unique);
         if (unique != null && unique == 1 && findItem(mobOid, item.getName()) != null){
            return false;
         }
         // check each subbag and see if it can be added there
         Long[] subBags = rootBag.getItemsList();
         
         Integer pos = MarsInventoryPlugin.slotBagMap.get(item.getProperty("slot"));
         Long subBag = subBags[pos];
         if (addItemHelper(subBag, pos, item)) {
            Engine.getPersistenceManager().setDirty(rootBag);
            log.debug("autoEquip = " + item.getProperty("autoEquip"));
            
            Integer autoEquip = (Integer)item.getProperty("autoEquip");
            if (autoEquip != null && autoEquip == 1){
               MarsItem mItem = (MarsItem)item;
               log.debug("AddItem = " + mItem);
               mItem.activate(mobOid, mobOid);
               log.debug("Activated item");
            }
            //Send out a message adding the item?

            return true;
         }
         return false;
      } finally {
         lock.unlock();
      }
   }

This also add the unique and autoEquip properties to the item creation so if you add unique it will only allow one of the items to be in the inventory and if you add autoEquip which really should be autoactivate when the player receives the item it is automatically used.

Finally we need to change the removeItem/ removeItems
Code:
protected Long removeItem(Long mobOid, Long itemOid) {
      lock.lock();
      try {
         MarsItem item = getMarsItem(itemOid);
         if (item == null)
            return null;
         if (item.getCount() > 1){
            log.debug("item is stacked");
            item.setCount(item.getCount() - 1);
            return null;
          }
         unequipItem(item, mobOid);
         Long rootBagOid = mobOid;
         if (rootBagOid == null) {
            log.debug("removeItem: cant find rootBagOid");
            return null;
         }
         Boolean result = removeItemFromBag(rootBagOid, itemOid);
         if (result == true) {
            return itemOid;
         } else {
            return null;
         }
      }
      finally {
         lock.unlock();
      }
   }

   protected Long removeItem(Long mobOid, String template) {
      lock.lock();
      try {
         Long itemOid = findItem(mobOid, template);
         if (Log.loggingDebug)
            log.debug("removeItem: mobOid=" + mobOid + " template=" + template + " ItemOid=" + itemOid);
         
         MarsItem item = getMarsItem(itemOid);   
         if (item.getCount() > 1){
            log.debug("item is stacked");
            item.setCount(item.getCount() - 1);
            return null;
         }
            
         return removeItem(mobOid, itemOid);
      }
      finally {
         lock.unlock();
      }
   }

   protected ArrayList<Long> removeItems(Long mobOid, ArrayList<String> templateList) {
      lock.lock();
      try {
         if (Log.loggingDebug)
            log.debug("removeItems: mobOid=" + mobOid + " templateList=" + templateList);
         ArrayList<Long> itemList = findItems(mobOid, templateList);
         ArrayList<Long> returnItemList = new ArrayList<Long>();
         if (itemList.contains(null)) {
            return null;
         }
         for (Long itemOid : itemList) {
            Long removeOid = removeItem(mobOid, itemOid);
            if (removeOid != null){
               returnItemList.add(itemOid);
            }
         }
         return returnItemList;
      }
      finally {
         lock.unlock();
      }
   }
Back to top Go down
Delurin
Head of Platform Development


Posts : 424
Join date : 2011-08-03

PostSubject: Re: Noob Question: about accessing templates.py NAMESPACE variables from MarsContainer   Wed 28 Nov - 7:33

Now All we need to do is modify the client
In MarsContainer add these functions
Code:
def _HandleInventoryUpdateNew(message):
    global _inventory
    for container in _inventory.values():
        container.clear()
    ClientAPI.Log("Got InventoryUpdateMessage with %d entries" % len(message["inventory"]))
    for entry in message["inventory"]:
        ClientAPI.Log("InventoryUpdateEntry fields: %s, %s, %s, %s, %s, %s, %s" % (entry[0], entry[1], entry[2], entry[3], entry[4], entry[5],entry[6]))
   
        if not _inventory.has_key(int(entry[2])):
            _inventory[int(entry[2])] = {}
        invInfo = InvItemInfo()
        invInfo.itemId = long(entry[0])
        invInfo.name = entry[1]
   
   invInfo.icon = entry[4]
   invInfo.count = int(entry[5])
   invInfo.stackSize = int(entry[6])
        _inventory[int(entry[2])][int(entry[3])] = invInfo
    #
    # dispatch a ui event to tell the rest of the system
    #
    ClientAPI.Interface.DispatchEvent("UNIT_INVENTORY_UPDATE", [])
ClientAPI.Network.RegisterExtensionMessageHandler("mv.INVENTORY_UPDATE_MSG", _HandleInventoryUpdateNew)

Also add count, stackSize to the InvItemInfo class at the top
and change GetContainerItemInfo to this
Code:

def GetContainerItemInfo(containerId, slotId):
    item = _GetContainerItem(containerId, slotId)
    if item is None:
        return None
    # icon, count, locked, quality, readable
    return [item.icon, item.count, False, 1, False]

finally in MvContainer in interface add
Code:

       SetItemButtonCount(button,itemCount)
to Container_Update function after SetItemButtonTexture is called

You might also want to change SetItemButtonCount to only display the number greater than 1

It doesnt allow you to split the object which you could add if you want, but that is more a UI task than anything else.




Back to top Go down
TheWatcher
Experienced Newbie
Experienced Newbie


Posts : 21
Join date : 2011-10-18
Location : Blue Cone Rookery(actually, California)

PostSubject: Re: Noob Question: about accessing templates.py NAMESPACE variables from MarsContainer   Wed 28 Nov - 8:50

Wow! This is great. I'll try them out when I get home.

I already have something similar to some of the code you've posted, but I had not figured out most of it yet. So this is a great help.

Again, thanks for the help and for putting up with my whining.

TheWatcher

Back to top Go down
CobaltBlues
Moderator
Moderator
avatar

Posts : 202
Join date : 2011-11-21
Location : Chicago Land

PostSubject: Re: Noob Question: about accessing templates.py NAMESPACE variables from MarsContainer   Wed 28 Nov - 10:45

Delurin is probably the best Multiverse expert around. He's consistently worked with the platform for many years now.
Back to top Go down
http://www.multiversemmo.com
Guest
Guest



PostSubject: Walking Knowledgebase :D   Wed 28 Nov - 23:51

Including posts here and on the old forums Delurin has helped me on more than a couple of issues.

Great to have people here you can count on.



I'm definitely saving this thread in our team's twiki for when we get to the inventory. Very Happy

Thanks Delurin
Back to top Go down
Sponsored content




PostSubject: Re: Noob Question: about accessing templates.py NAMESPACE variables from MarsContainer   

Back to top Go down
 
Noob Question: about accessing templates.py NAMESPACE variables from MarsContainer
View previous topic View next topic Back to top 
Page 1 of 1
 Similar topics
-
» Silly noob question regarding "Sharing the Pain"
» noob question
» noob question regarding haywire grenades
» noob question on 3DS
» Noob question

Permissions in this forum:You cannot reply to topics in this forum
 :: Development :: Server Scripting and Development-
Jump to: