summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMeistache <crie.fernanda@gmail.com>2015-02-08 19:18:52 -0200
committerMeistache <crie.fernanda@gmail.com>2015-02-08 19:18:52 -0200
commita1af615d49a9565c4f656a20337edb273e2c960a (patch)
tree52b15a031bf4209283258fb33e5bc5fcc3d4dd07
parentbeaf7f36bb2c609de5fcad1c06e37e26147c0cb0 (diff)
downloadmanamarket-a1af615d49a9565c4f656a20337edb273e2c960a.tar.gz
manamarket-a1af615d49a9565c4f656a20337edb273e2c960a.tar.bz2
manamarket-a1af615d49a9565c4f656a20337edb273e2c960a.tar.xz
manamarket-a1af615d49a9565c4f656a20337edb273e2c960a.zip
Changes regarding storage implementation on ManaMarket
-rw-r--r--config.py.template2
-rw-r--r--data_template/delisted.xml2
-rw-r--r--data_template/stack.xml2
-rwxr-xr-xmain.py273
-rw-r--r--net/packet_out.py5
-rw-r--r--net/protocol.py14
-rw-r--r--storage.py114
-rw-r--r--tradey.py80
-rw-r--r--utils.py9
9 files changed, 424 insertions, 77 deletions
diff --git a/config.py.template b/config.py.template
index e55b2f6..d8af804 100644
--- a/config.py.template
+++ b/config.py.template
@@ -2,7 +2,7 @@ server = "server.themanaworld.org"
port = 6901
account = ""
password = ""
-relist_time = 604800 # Time in seconds before an item needs to be relisted.
+delist_time = 604800 # Time in seconds before an item needs to be relisted.
character = 0 #slot character is in, 0 for first, 1 for second, 2 for third
admin = ""
#nosell = [] # Items which can't be sold - just add the itemid to the list.
diff --git a/data_template/delisted.xml b/data_template/delisted.xml
new file mode 100644
index 0000000..8208566
--- /dev/null
+++ b/data_template/delisted.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" ?>
+<items/>
diff --git a/data_template/stack.xml b/data_template/stack.xml
new file mode 100644
index 0000000..8208566
--- /dev/null
+++ b/data_template/stack.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" ?>
+<items/>
diff --git a/main.py b/main.py
index 5592a52..a259c4c 100755
--- a/main.py
+++ b/main.py
@@ -41,6 +41,7 @@ from net.packet import *
from net.protocol import *
from net.packet_out import *
from player import *
+from storage import *
import tradey
import utils
import eliza
@@ -50,12 +51,37 @@ shop_broadcaster = utils.Broadcast()
trader_state = utils.TraderState()
ItemDB = utils.ItemDB()
player_node = Player('')
+storage = Storage()
beingManager = BeingManager()
user_tree = tradey.UserTree()
sale_tree = tradey.ItemTree()
+stack_tree = tradey.StackTree()
+delisted_tree = tradey.DelistedTree()
ItemLog = utils.ItemLog()
+DelistedLog = utils.DelistedLog()
logger = logging.getLogger('ManaLogger')
+def do_delist():
+ cleaned = 0
+ for elem in sale_tree.root:
+ item = Item()
+ item.index = player_node.find_inventory_index(int(elem.get('itemId')))
+ item.itemId = int(elem.get('itemId'))
+ item.amount = int(elem.get('amount'))
+ if time.time() - float(elem.get('add_time')) > config.delist_time:
+ try:
+ storage.storage_send(mapserv, item.index, item.amount)
+ except:
+ print("Couldn't send item to storage")
+ return -10
+ storage.add_item(item)
+ player_node.remove_item(item.index, item.amount)
+ delisted_tree.add_item(elem.get('name'), item.itemId, item.amount)
+ sale_tree.remove_item_uid(elem.get('uid'))
+ DelistedLog.add_item(item.itemId, item.amount, elem.get('name'))
+ cleaned += 1
+ logger.info("Delisting routine done. %d items added to delisted.xml", cleaned)
+
def process_whisper(nick, msg, mapserv):
msg = filter(lambda x: x in utils.allowed_chars, msg)
if len(msg) == 0:
@@ -90,7 +116,7 @@ def process_whisper(nick, msg, mapserv):
mapserv.sendall(whisper(nick, "No items for sale."))
for elem in sale_tree.root:
- if time.time() - float(elem.get('add_time')) < config.relist_time: # Check if an items time is up.
+ if time.time() - float(elem.get('add_time')) < config.delist_time: # Check if an items time is up.
msg = "[selling] [" + elem.get("uid") + "] " + elem.get("amount") + " [@@" + \
elem.get("itemId") + "|" + ItemDB.getItem(int(elem.get("itemId"))).name + "@@] for " + elem.get("price") + "gp each"
mapserv.sendall(whisper(nick, msg))
@@ -131,10 +157,7 @@ def process_whisper(nick, msg, mapserv):
items_for_sale = False
for elem in sale_tree.root:
if elem.get('name') == nick:
- if time.time() - float(elem.get('add_time')) > config.relist_time:
- msg = "[expired] ["
- else:
- msg = "[selling] ["
+ msg = "[selling] ["
msg += elem.get("uid") + "] " + elem.get("amount") + " [@@" + elem.get("itemId") + "|" + \
ItemDB.getItem(int(elem.get("itemId"))).name + "@@] for " + elem.get("price") + "gp each"
@@ -145,8 +168,38 @@ def process_whisper(nick, msg, mapserv):
mapserv.sendall(whisper(nick, msg))
+ for elem in stack_tree.root:
+ if elem.get('name') == nick:
+ msg = "[waiting] ["
+
+ msg += elem.get("uid") + "] " + elem.get("amount") + " [@@" + elem.get("itemId") + "|" + \
+ ItemDB.getItem(int(elem.get("itemId"))).name + "@@] for " + elem.get("price") + "gp each"
+
+ if items_for_sale == False:
+ mapserv.sendall(whisper(nick, "Your have the following items waiting for sale:"))
+ items_for_sale = True
+
+ mapserv.sendall(whisper(nick, msg))
+
if items_for_sale == False:
mapserv.sendall(whisper(nick, "You have no items for sale."))
+
+ items_for_getback == False
+ for elem in delisted_tree.root:
+ if elem.get('name') == nick:
+ msg = "[expired] ["
+
+ msg += elem.get("uid") + "] " + elem.get("amount") + " [@@" + elem.get("itemId") + "|" + \
+ ItemDB.getItem(int(elem.get("itemId"))).name + "@@]"
+
+ if items_for_getback == False:
+ mapserv.sendall(whisper(nick, "Your have the following items waiting for getback:"))
+ items_for_getback = True
+
+ mapserv.sendall(whisper(nick, msg))
+
+ if items_for_sale == False:
+ mapserv.sendall(whisper(nick, "You have no expired items."))
money = int(user.get('money'))
mapserv.sendall(whisper(nick, "You have " + str(money) + "gp to collect."))
@@ -157,7 +210,7 @@ def process_whisper(nick, msg, mapserv):
# Sends help information
if len(broken_string) == 1:
mapserv.sendall(whisper(nick, "Welcome to ManaMarket!"))
- mapserv.sendall(whisper(nick, "The basic commands for the bot are: !list, !find <id> or <Item Name>, !buy <amount> <uid>, !add <amount> <price> <Item Name>, !money, !relist <uid>, !info, !getback <uid> "))
+ mapserv.sendall(whisper(nick, "The basic commands for the bot are: !list, !find <id> or <Item Name>, !buy <amount> <uid>, !add <amount> <price> <Item Name>, !money, !info, !getback <uid> "))
mapserv.sendall(whisper(nick, "For a detailed description of each command, type !help <command> e.g. !help !buy"))
mapserv.sendall(whisper(nick, "For example to purchase an item shown in the list as:"))
mapserv.sendall(whisper(nick, "[selling] [6] 5 [@@640|Iron Ore@@] for 1000gp each"))
@@ -189,8 +242,6 @@ def process_whisper(nick, msg, mapserv):
mapserv.sendall(whisper(nick, "!add <amount> <price> <Item Name> - Add an item to the sell list (requires that you have an account)."))
elif broken_string[1] == '!money':
mapserv.sendall(whisper(nick, "!money - Allows you to collect money for any sales made on your behalf."))
- elif broken_string[1] == '!relist':
- mapserv.sendall(whisper(nick, "!relist <uid> - Allows you to relist an item which has expired."))
elif broken_string[1] == '!info':
mapserv.sendall(whisper(nick, "!info - Displays basic information about your account."))
elif broken_string[1] == '!getback':
@@ -238,20 +289,32 @@ def process_whisper(nick, msg, mapserv):
if item.isdigit(): # an id
for elem in sale_tree.root:
- if ((time.time() - float(elem.get('add_time'))) < config.relist_time) \
- and int(elem.get("itemId")) == int(item): # Check if an items time is up.
+ if int(elem.get("itemId")) == int(item):
msg = "[selling] [" + elem.get("uid") + "] " + elem.get("amount") + " [@@" + elem.get("itemId") + "|" \
+ ItemDB.getItem(int(elem.get("itemId"))).name + "@@] for " + elem.get("price") + "gp each"
mapserv.sendall(whisper(nick, msg))
items_found = True
+ if not items_found: # if no items on list, gives priority to stack
+ for elem in stack_tree.root:
+ if int(elem.get("itemId")) == int(item):
+ msg = "[selling] [" + elem.get("uid") + "] " + elem.get("amount") + " [@@" + elem.get("itemId") + "|" \
+ + ItemDB.getItem(int(elem.get("itemId"))).name + "@@] for " + elem.get("price") + "gp each"
+ mapserv.sendall(whisper(nick, msg))
+ items_found = True
else: # an item name
for elem in sale_tree.root:
- if ((time.time() - float(elem.get('add_time'))) < config.relist_time) \
- and item.lower() in ItemDB.getItem(int(elem.get("itemId"))).name.lower(): # Check if an items time is up.
+ if item.lower() in ItemDB.getItem(int(elem.get("itemId"))).name.lower():
msg = "[selling] [" + elem.get("uid") + "] " + elem.get("amount") + " [@@" + elem.get("itemId") + "|" \
+ ItemDB.getItem(int(elem.get("itemId"))).name + "@@] for " + elem.get("price") + "gp each"
mapserv.sendall(whisper(nick, msg))
items_found = True
+ if not items_found: # if no items on list, gives priority to stack
+ for elem in stack_tree.root:
+ if item.lower() in ItemDB.getItem(int(elem.get("itemId"))).name.lower():
+ msg = "[selling] [" + elem.get("uid") + "] " + elem.get("amount") + " [@@" + elem.get("itemId") + "|" \
+ + ItemDB.getItem(int(elem.get("itemId"))).name + "@@] for " + elem.get("price") + "gp each"
+ mapserv.sendall(whisper(nick, msg))
+ items_found = True
if not items_found:
mapserv.sendall(whisper(nick, "Item not found."))
@@ -267,6 +330,8 @@ def process_whisper(nick, msg, mapserv):
if trader_state.Trading.test():
mapserv.sendall(whisper(nick, "I'm busy with a trade."))
+ elif storage.Open.test():
+ mapserv.sendall(whisper(nick, "I'm busy with storage."))
else:
mapserv.sendall(whisper(nick, "I'm free."))
@@ -283,7 +348,12 @@ def process_whisper(nick, msg, mapserv):
if broken_string[1].isdigit():
uid = int(broken_string[1])
- item_info = sale_tree.get_uid(uid)
+ if uid <= MAX_INVENTORY:
+ item_info = sale_tree.get_uid(uid)
+ elif uid > MAX_INVENTORY and uid <= MAX_STORAGE:
+ item_info = stack_tree.get_uid(uid)
+ else:
+ item_info = delisted_tree.get_uid(uid)
if item_info == -10:
mapserv.sendall(whisper(nick, "Item not found. Please check the uid number and try again."))
@@ -480,6 +550,9 @@ def process_whisper(nick, msg, mapserv):
if not trader_state.Trading.testandset():
mapserv.sendall(whisper(nick, "I'm currently busy with a trade. Try again shortly"))
return
+ if not storage.Open.testandset():
+ mapserv.sendall(whisper(nick, "I'm currently busy with storage. Try again shortly"))
+ return
trader_state.item = item
player_id = beingManager.findId(nick)
@@ -501,7 +574,10 @@ def process_whisper(nick, msg, mapserv):
if broken_string[1].isdigit() and broken_string[2].isdigit():
amount = int(broken_string[1])
uid = int(broken_string[2])
- item_info = sale_tree.get_uid(uid)
+ if uid <= MAX_INVENTORY:
+ item_info = sale_tree.get_uid(uid)
+ else:
+ item_info = stack_tree.get_uid(uid)
if item_info == -10:
mapserv.sendall(whisper(nick, "Item not found. Please check the uid number and try again."))
@@ -526,6 +602,9 @@ def process_whisper(nick, msg, mapserv):
if not trader_state.Trading.testandset():
mapserv.sendall(whisper(nick, "I'm currently busy with a trade. Try again shortly"))
return
+ if not storage.Open.testandset():
+ mapserv.sendall(whisper(nick, "I'm currently buse with storage. Try again shortly"))
+ return
trader_state.item = item
player_id = beingManager.findId(nick)
@@ -560,43 +639,6 @@ def process_whisper(nick, msg, mapserv):
elif check == -10:
mapserv.sendall(whisper(nick, "User removal failed. Please check spelling."))
- elif broken_string[0] == "!relist":
- # Relist an item which has expired - !relist <uid>.
- if user == -10 or len(broken_string) != 2:
- mapserv.sendall(whisper(nick, "Syntax incorrect."))
- return
-
- if int(user.get("accesslevel")) < 5:
- mapserv.sendall(whisper(nick, "You don't have the correct permissions."))
- return
-
- if broken_string[1].isdigit():
- uid = int(broken_string[1])
- item_info = sale_tree.get_uid(uid)
-
- if item_info == -10:
- mapserv.sendall(whisper(nick, "Item not found. Please check the uid number and try again."))
- return
-
- if item_info.get('name') != nick:
- mapserv.sendall(whisper(nick, "That doesn't belong to you!"))
- return
-
- time_relisted = int(item_info.get('relisted'))
-
- if int(item_info.get('relisted')) < 3:
- sale_tree.get_uid(uid).set('add_time', str(time.time()))
- sale_tree.get_uid(uid).set('relisted', str(time_relisted + 1))
- sale_tree.save()
- mapserv.sendall(whisper(nick, "The item has been successfully relisted."))
- user_tree.get_user(nick).set('last_use', str(time.time()))
- user_tree.save()
- else:
- mapserv.sendall(whisper(nick, "This item can no longer be relisted. Please collect it using !getback "+str(uid)+"."))
- return
- else:
- mapserv.sendall(whisper(nick, "Syntax incorrect."))
-
elif broken_string[0] == "!getback":
# Trade the player back uid, remove from sale_items if trade successful - !getback <uid>.
if user == -10 or len(broken_string) != 2:
@@ -609,7 +651,12 @@ def process_whisper(nick, msg, mapserv):
if broken_string[1].isdigit():
uid = int(broken_string[1])
- item_info = sale_tree.get_uid(uid)
+ if uid <= MAX_INVENTORY:
+ item_info = sale_tree.get_uid(uid)
+ elif uid > MAX_INVENTORY and uid <= MAX_STORAGE:
+ item_info = stack_tree.get_uid(uid)
+ else:
+ item_info = delisted_tree.get_uid(uid)
if item_info == -10:
mapserv.sendall(whisper(nick, "Item not found. Please check the uid number and try again."))
@@ -630,6 +677,9 @@ def process_whisper(nick, msg, mapserv):
if not trader_state.Trading.testandset():
mapserv.sendall(whisper(nick, "I'm currently busy with a trade. Try again shortly"))
return
+ if not storage.Open.testandset():
+ mapserv.sendall(whisper(nick, "I'm currently busy with storage. Try again shortly"))
+ return
trader_state.item = item
player_id = beingManager.findId(nick)
@@ -785,6 +835,12 @@ def main():
logger.info("Trade Cancelled - Timeout.")
trader_state.timer = time.time()
mapserv.sendall(str(PacketOut(CMSG_TRADE_CANCEL_REQUEST)))
+
+ # The same applies to storage, now
+ if storage.Open.test():
+ if time.time() - storage.timer > 2*60:
+ logger.info("Storage operation cancelled - Timeout.")
+ mapserv.sendall(str(PacketOut(CMSG_CLOSE_STORAGE)))
for packet in pb:
if packet.is_type(SMSG_MAP_LOGIN_SUCCESS): # connected
@@ -868,12 +924,17 @@ def main():
err = packet.read_int8()
if err == 0:
- if item.index in player_node.inventory:
- player_node.inventory[item.index].amount += item.amount
- else:
- player_node.inventory[item.index] = item
+ if len(player_node.inventory) <= MAX_INVENTORY:
+ if item.index in player_node.inventory:
+ player_node.inventory[item.index].amount += item.amount
+ else:
+ player_node.inventory[item.index] = item
+ placement = "Inventory"
+ else: # If only one slot left, move to stack
+ item.index = storage.add_item(item)
+ placement = "Storage"
- logger.info("Picked up: %s, Amount: %s, Index: %s", ItemDB.getItem(item.itemId).name, str(item.amount), str(item.index))
+ logger.info("Picked up: %s, Amount: %s, Index: %s - %s", ItemDB.getItem(item.itemId).name, str(item.amount), str(item.index), placement)
elif packet.is_type(SMSG_PLAYER_INVENTORY_REMOVE):
index = packet.read_int16() - inventory_offset
@@ -882,6 +943,24 @@ def main():
logger.info("Remove item: %s, Amount: %s, Index: %s", ItemDB.getItem(player_node.inventory[index].itemId).name, str(amount), str(index))
player_node.remove_item(index, amount)
+ # Now taking an item from stack if inventory was full before
+ if len(player_node.inventory) == MAX_INVENTORY-1:
+ elem = stack_tree.get_uid(stack_tree.next_id)
+ index = storage.find_storage_index(int(elem.get('itemId')))
+ storage.storage_open(mapserv)
+ try:
+ storage.storage_get(mapserv, index, elem.get('amount'))
+ except:
+ print ("Couldn't remove item from storage")
+ storage.storage_close(mapserv)
+ pass
+
+ storage.storage_close(mapserv)
+ storage.remove_item(index, int(elem.get('amount')))
+ sale_tree.add_item(elem.get('name'), int(elem.get('itemId')), int(elem.get('amount')), int(elem.get('price')))
+ stack_tree.remove_item_uid(stack_tree.next_id)
+
+
elif packet.is_type(SMSG_PLAYER_INVENTORY):
player_node.inventory.clear() # Clear the inventory - incase of new index.
packet.skip(2)
@@ -920,6 +999,49 @@ def main():
else:
logger.info("Inventory Check Passed.")
+ # IMO the best moment to run delisting
+ storage.storage_open(mapserv)
+ do_delist()
+ storage.storage_close(mapserv)
+
+ elif packet.is_type(SMSG_PLAYER_STORAGE_ITEMS):
+ storage.storage.clear() # Clear storage - same as inventory.
+ packet.skip(2)
+ number = (len(packet.data)-2) / 18
+ for loop in range(number):
+ item = Item()
+ item.index = packet.read_int16() - storage_offset
+ item.itemId = packet.read_int16()
+ packet.skip(2)
+ item.amount = packet.read_int16()
+ packet.skip(10)
+ storage.storage[item.index] = item
+
+ elif packet.is_type(SMSG_PLAYER_STORAGE_EQUIP):
+ packet.read_int16()
+ number = (len(packet.data)) / 20
+ for loop in range(number):
+ item = Item()
+ item.index = packet.read_int16() - storage_offset
+ item.itemId = packet.read_int16()
+ packet.skip(16)
+ item.amount = 1
+ storage.storage[item.index] = item
+
+ logger.info("Storage information received:")
+ for item in storage.storage:
+ logger.info("Name: %s, Id: %s, Index: %s, Amount: %s.", \
+ ItemDB.getItem(storage.storage[item].itemId).name, \
+ storage.storage[item].itemId, item, storage.storage[item].amount)
+
+ errorOccured = storage.check_storage(stack_tree, delisted_tree)
+ if errorOccured:
+ logger.info(errorOccured)
+ shop_broadcaster.stop()
+ sys.exit(1)
+ else:
+ logger.info("Storage Check Passed.")
+
elif packet.is_type(SMSG_TRADE_REQUEST):
name = packet.read_string(24)
logger.info("Trade request: " + name)
@@ -1060,24 +1182,39 @@ def main():
elif packet.is_type(SMSG_TRADE_COMPLETE):
commitMessage=""
- # The sale_tree is only ammended after a complete trade packet.
+ # we get here which tree it should be through UID
+ if trader_state.item.get == 1:
+ if len(player_node.inventory) <= MAX_INVENTORY:
+ tree = sale_tree
+ else:
+ tree = stack_tree
+ elif trader_state.item.get == 0:
+ if trader_state.item.uid <= MAX_INVENTORY:
+ tree = sale_tree
+ elif trader_state.item.uid > MAX_INVENTORY \
+ and trader_state.item.uid <= MAX_STORAGE:
+ tree = stack_tree
+ else:
+ tree = delisted_tree
+
+ # The trees are only ammended after a complete trade packet.
if trader_state.item and trader_state.money == 0:
if trader_state.item.get == 1: # !add
- sale_tree.add_item(trader_state.item.player, trader_state.item.id, trader_state.item.amount, trader_state.item.price)
+ tree.add_item(trader_state.item.player, trader_state.item.id, trader_state.item.amount, trader_state.item.price)
user_tree.get_user(trader_state.item.player).set('used_stalls', \
str(int(user_tree.get_user(trader_state.item.player).get('used_stalls')) + 1))
user_tree.get_user(trader_state.item.player).set('last_use', str(time.time()))
commitMessage = "Add"
elif trader_state.item.get == 0: # !buy \ !getback
- seller = sale_tree.get_uid(trader_state.item.uid).get('name')
- item = sale_tree.get_uid(trader_state.item.uid)
+ seller = tree.get_uid(trader_state.item.uid).get('name')
+ item = tree.get_uid(trader_state.item.uid)
current_amount = int(item.get("amount"))
- sale_tree.get_uid(trader_state.item.uid).set("amount", str(current_amount - trader_state.item.amount))
+ tree.get_uid(trader_state.item.uid).set("amount", str(current_amount - trader_state.item.amount))
if int(item.get("amount")) == 0:
- user_tree.get_user(sale_tree.get_uid(trader_state.item.uid).get('name')).set('used_stalls', \
- str(int(user_tree.get_user(sale_tree.get_uid(trader_state.item.uid).get('name')).get('used_stalls'))-1))
- sale_tree.remove_item_uid(trader_state.item.uid)
+ user_tree.get_user(tree.get_uid(trader_state.item.uid).get('name')).set('used_stalls', \
+ str(int(user_tree.get_user(tree.get_uid(trader_state.item.uid).get('name')).get('used_stalls'))-1))
+ tree.remove_item_uid(trader_state.item.uid)
current_money = int(user_tree.get_user(seller).get("money"))
user_tree.get_user(seller).set("money", str(current_money + trader_state.item.price * trader_state.item.amount))
@@ -1090,7 +1227,7 @@ def main():
user_tree.get_user(trader_state.money).set('money', str(0))
commitMessage = "Money"
- sale_tree.save()
+ tree.save()
user_tree.save()
tradey.saveData(commitMessage)
@@ -1102,6 +1239,10 @@ def main():
logger.info(errorOccured)
shop_broadcaster.stop()
sys.exit(1)
+
+ elif packet.is_type(SMSG_PLAYER_STORAGE_CLOSE):
+ storage.reset()
+
else:
pass
diff --git a/net/packet_out.py b/net/packet_out.py
index 1d6e2d2..fea93d4 100644
--- a/net/packet_out.py
+++ b/net/packet_out.py
@@ -15,9 +15,8 @@ def whisper(nick, message):
def chat(text):
chat_packet = PacketOut(CMSG_CHAT_MESSAGE)
- mes = player_node.name + " : " + text
- chat_packet.write_int16(len(mes) + 4 + 1)
- chat_packet.write_string(mes, len(mes) + 1)
+ chat_packet.write_int16(len(text) + 4 + 1)
+ chat_packet.write_string(text, len(text) + 1)
return str(chat_packet)
def sit(val):
diff --git a/net/protocol.py b/net/protocol.py
index 4a4b74f..cfc17e0 100644
--- a/net/protocol.py
+++ b/net/protocol.py
@@ -23,6 +23,13 @@ SMSG_PLAYER_EQUIPMENT = 0x00a4
SMSG_PLAYER_STAT_UPDATE_1 = 0x00b0
SMSG_PLAYER_STAT_UPDATE_2 = 0x00b1
+SMSG_PLAYER_STORAGE_EQUIP = 0x00a6
+SMSG_PLAYER_STORAGE_ITEMS = 0x01f0
+SMSG_PLAYER_STORAGE_STATUS = 0x00f2
+SMSG_PLAYER_STORAGE_ADD = 0x00f4
+SMSG_PLAYER_STORAGE_REMOVE = 0x00f6
+SMSG_PLAYER_STORAGE_CLOSE = 0x00f8
+
SMSG_BEING_VISIBLE = 0x0078
SMSG_BEING_MOVE = 0x007b
SMSG_BEING_REMOVE = 0x0080
@@ -41,6 +48,10 @@ CMSG_PLAYER_CHANGE_DEST = 0x0085
CMSG_PLAYER_EMOTE = 0x00bf
SMSG_WALK_RESPONSE = 0x0087
+CMSG_MOVE_TO_STORAGE = 0x00f3
+CMSG_MOVE_FROM_STORAGE = 0x00f5
+CMSG_CLOSE_STORAGE = 0x00f7
+
CMSG_TRADE_REQUEST = 0x00e4
CMSG_TRADE_RESPONSE = 0x00e6
CMSG_TRADE_ITEM_ADD_REQUEST = 0x00e8
@@ -62,3 +73,6 @@ SMSG_ITEM_REMOVE = 0x00a1
inventory_offset = 2
storage_offset = 1
+MAX_STORAGE = 300
+MAX_INVENTORY = 99
+MAX_AMOUNT = 30000
diff --git a/storage.py b/storage.py
new file mode 100644
index 0000000..a098ac6
--- /dev/null
+++ b/storage.py
@@ -0,0 +1,114 @@
+#!/usr/bin/python
+
+"""
+ Copyright 2011, Dipesh Amin <yaypunkrock@gmail.com>
+ Copyright 2011, Stefan Beller <stefanbeller@googlemail.com>
+
+ This file is part of tradey, a trading bot in the mana world
+ see www.themanaworld.org
+
+ Storage Access class by Fernanda Monteiro <crie.fernanda@gmail.com>
+"""
+
+from utils import ItemDB
+from net.packet_out import chat
+from net.protocol import *
+from net.packet import *
+import time
+import copy
+import mutex
+
+class Storage:
+ def __init__(self):
+ self.storage = {}
+ self.timer = 0
+ self.Open = mutex.mutex()
+ def reset(self):
+ self.Open.unlock()
+ self.timer = 0
+
+ def find_storage_index(self, item_id):
+ for item in self.storage:
+ if item > 1:
+ if self.storage[item].itemId == item_id:
+ return item
+ return -10 # Not found - bug somewhere!
+
+ def add_item(self, item):
+ if not item.itemId or item.amount <= 0:
+ return -10 # Not an item - something is messy
+
+ index = self.find_storage_index(item.itemId)
+ if ItemDB().getItem(item.itemId).type != 'equip-ammo' and 'equip':
+ if index != -10:
+ if (item.amount > MAX_AMOUNT - self.storage[index].amount):
+ return -10
+ self.storage[index].amount += item.amount
+ return 0
+
+ index = len(self.storage)
+ self.storage[index] = item
+ self.storage[index].amount = item.amount
+ return index
+
+ def remove_item(self, index, amount):
+ if index in self.storage:
+ self.storage[index].amount -= amount
+ if self.storage[index].amount == 0:
+ del self.storage[index]
+
+ def check_storage(self, stack_tree, delisted_tree):
+ # Check the inventory state.
+ test_node = copy.deepcopy(self.storage)
+ for elem in stack_tree.root:
+ item_found = False
+ for item in test_node:
+ if int(elem.get('itemId')) == test_node[item].itemId \
+ and int(elem.get('amount')) <= test_node[item].amount:
+ test_node[item].amount -= int(elem.get('amount'))
+ if test_node[item].amount == 0:
+ del test_node[item]
+ item_found = True
+ break
+
+ if not item_found:
+ return "Server and client storage out of sync."
+
+ for elem in delisted_tree.root:
+ item_found = False
+ for item in test_node:
+ if int(elem.get('itemId')) == test_node[item].itemId \
+ and int(elem.get('amount')) <= test_node[item].amount:
+ test_node[item].amount -= int(elem.get('amount'))
+ if test_node[item].amount == 0:
+ del test_node[item]
+ item_found = True
+ break
+
+ if not item_found:
+ return "Server and client storage out of sync."
+
+ def storage_send(self, mapserv, index, amount):
+ packet = PacketOut(CMSG_MOVE_TO_STORAGE)
+ packet.write_int16(index + inventory_offset)
+ packet.write_int32(amount)
+ mapserv.sendall(str(packet))
+ return 0
+
+ def storage_get(self, mapserv, index, amount):
+ packet = PacketOut(CMSG_MOVE_FROM_STORAGE)
+ packet.write_int16(index + storage_offset)
+ packet.write_int32(amount)
+ mapserv.sendall(str(packet))
+ return 0
+
+ def storage_open(self, mapserv):
+ mapserv.sendall(chat("@storage"))
+ self.timer = time.time()
+
+ def storage_close(self, mapserv):
+ mapserv.sendall(str(PacketOut(CMSG_CLOSE_STORAGE)))
+
+if __name__ == '__main__':
+ print "Do not run this file directly. Run main.py"
+
diff --git a/tradey.py b/tradey.py
index 01f855e..4172a63 100644
--- a/tradey.py
+++ b/tradey.py
@@ -61,19 +61,20 @@ class UserTree:
class ItemTree:
def __init__(self):
- self.tree = ElementTree(file="data/sale.xml")
+ self.save_file = 'data/sale.xml'
+ self.tree = ElementTree(file=self.save_file)
self.root = self.tree.getroot()
self.u_id = set()
+ self.id_itter = 1
for elem in self.root:
self.u_id.add(int(elem.get("uid")))
def getId(self):
- id_itter = 1
- while id_itter in self.u_id:
- id_itter += 1
+ while self.id_itter in self.u_id:
+ self.id_itter += 1
self.u_id.add(id_itter)
- return id_itter
+ return self.id_itter
def remove_id(self, uid):
# Free up used id's.
@@ -85,7 +86,6 @@ class ItemTree:
user.set("itemId", str(item_id))
user.set("price", str(price))
user.set("add_time", str(time.time()))
- user.set("relisted", str(0))
user.set("amount", str(amount))
user.set("uid", str(self.getId()))
self.save()
@@ -107,11 +107,77 @@ class ItemTree:
def save(self):
# Be sure to call save() after any changes to the tree.
- f = open('data/sale.xml', 'w')
+ f = open(self.save_file, 'w')
dom = xml.dom.minidom.parseString(clean_xml(tostring(self.root)))
f.write(dom.toprettyxml(' '))
f.close()
+class StackTree(ItemTree):
+ def __init__(self):
+ self.save_file = 'data/stack.xml'
+ self.tree = ElementTree(file=self.save_file)
+ self.root = self.tree.getroot()
+ self.u_id = set()
+ self.id_itter = 101
+ self.next_id = self.id_itter
+
+ for elem in self.root:
+ self.u_id.add(int(elem.get("uid")))
+
+ def add_item(self, name, item_id, amount, price):
+ user = SubElement(self.root, "item")
+ user.set("name", name)
+ user.set("itemId", str(item_id))
+ user.set("price", str(price))
+ user.set("amount", str(amount))
+ user.set("uid", str(self.getId()))
+ self.save()
+
+ # Here we take the oldest id put into stack.xml so we have FIFO
+ def get_next_id(self):
+ if len(self.u_id) == 0:
+ self.next_id = self.id_itter
+ return
+ else:
+ # TODO Here I'm handling rotation (gets a high number then
+ # back to 101). Any better manners to do this?
+ if min(self.u_id) - self.next_id < 0:
+ next_uid = self.next_id - min(self.u_id)
+ self.next_id = self.id_itter + next_uid + 1
+ else:
+ next_uid = min(self.u_id) - self.next_id
+ self.next_id += next_uid
+ return
+
+
+ def remove_item_uid(self, uid):
+ for elem in self.root:
+ if elem.get("uid") == str(uid):
+ self.root.remove(elem)
+ self.remove_id(uid)
+ self.save()
+ self.get_next_id()
+ return 1
+ return -10
+
+class DelistedTree(ItemTree):
+ def __init__(self):
+ self.save_file = 'data/delisted.xml'
+ self.tree = ElementTree(file=self.save_file)
+ self.root = self.tree.getroot()
+ self.u_id = set()
+ self.id_itter = 301
+
+ for elem in self.root:
+ self.u_id.add(int(elem.get("uid")))
+
+ def add_item(self, name, item_id, amount):
+ user = SubElement(self.root, "item")
+ user.set("name", name)
+ user.set("itemId", str(item_id))
+ user.set("amount", str(amount))
+ user.set("uid", str(self.getId()))
+
def saveData(commitmessage = "commit"):
# This assumes the current working directory is the tradey directory.
os.chdir("data")
diff --git a/utils.py b/utils.py
index 52d51b6..542b7af 100644
--- a/utils.py
+++ b/utils.py
@@ -86,6 +86,15 @@ class ItemLog:
file_node.write(str(item_id)+" "+str(amount)+" "+str(price)+" "+str(time.time())+" "+name+"\n")
file_node.close()
+class DelistedLog:
+ def __init__(self):
+ self.log_file = 'data/logs/delisted.log'
+
+ def add_item(self, item_id, amount, name):
+ file_node = open(self.log_file, 'a')
+ file_node.write(str(item_id)+" "+str(amount)+" "+str(time.time())+" "+name+"\n")
+ file_node.close()
+
class TraderState:
""" Stores information regarding a trade request"""
def __init__(self):