Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes regarding storage implementation on ManaMarket #9

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion config.py.template
Original file line number Diff line number Diff line change
Expand Up @@ -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.
2 changes: 2 additions & 0 deletions data_template/delisted.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" ?>
<items/>
2 changes: 2 additions & 0 deletions data_template/stack.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" ?>
<items/>
307 changes: 240 additions & 67 deletions main.py

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion net/packet_out.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ def whisper(nick, message):

def chat(text):
chat_packet = PacketOut(CMSG_CHAT_MESSAGE)
mes = player_node.name + " : " + text
#TODO Find another automated manner to get ManaMarket name (previous didn't work either)
# Maybe a temp solution would be setting as a variable in config.py
mes = "ManaMarket"+" : "+text
chat_packet.write_int16(len(mes) + 4 + 1)
# chat_packet = PacketOut(CMSG_CHAT_MESSAGE)
chat_packet.write_string(mes, len(mes) + 1)
return str(chat_packet)

Expand Down
14 changes: 14 additions & 0 deletions net/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@
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
Expand All @@ -41,6 +48,10 @@
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
Expand All @@ -62,3 +73,6 @@

inventory_offset = 2
storage_offset = 1
MAX_STORAGE = 300
MAX_INVENTORY = 99
MAX_AMOUNT = 30000
117 changes: 117 additions & 0 deletions storage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#!/usr/bin/python

"""
Copyright 2011, Dipesh Amin <[email protected]>
Copyright 2011, Stefan Beller <[email protected]>

This file is part of tradey, a trading bot in the mana world
see www.themanaworld.org

Storage Access class by Fernanda Monteiro <[email protected]>
"""

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.mapserv = 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 index

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, index, amount):
packet = PacketOut(CMSG_MOVE_TO_STORAGE)
packet.write_int16(index + inventory_offset)
packet.write_int32(amount)
self.mapserv.sendall(str(packet))
return 0

def storage_get(self, index, amount):
packet = PacketOut(CMSG_MOVE_FROM_STORAGE)
packet.write_int16(index + storage_offset)
packet.write_int32(amount)
self.mapserv.sendall(str(packet))
return 0

def storage_open(self):
self.timer = time.time()
self.mapserv.sendall(chat("@storage"))

def storage_close(self):
self.reset()
self.mapserv.sendall(str(PacketOut(CMSG_CLOSE_STORAGE)))

if __name__ == '__main__':
print "Do not run this file directly. Run main.py"

83 changes: 75 additions & 8 deletions tradey.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,20 @@ def save(self):

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
self.u_id.add(id_itter)
return id_itter
while self.id_itter in self.u_id:
self.id_itter += 1
self.u_id.add(self.id_itter)
return self.id_itter

def remove_id(self, uid):
# Free up used id's.
Expand All @@ -85,7 +86,6 @@ def add_item(self, name, item_id, amount, price):
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()
Expand All @@ -107,11 +107,78 @@ def remove_item_uid(self, uid):

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()
return 1
self.get_next_id()
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()))
self.save()

def saveData(commitmessage = "commit"):
# This assumes the current working directory is the tradey directory.
os.chdir("data")
Expand Down
23 changes: 23 additions & 0 deletions utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import mutex
import threading
from net.packet_out import *
from threading import _Timer

allowed_chars = "abcdefghijklmnoprstquvwxyzABCDEFGHIJKLMNOPRSTQUVWXYZ1234567890-_+=!@$%^&*();'<>,.?/~`| "

Expand Down Expand Up @@ -86,6 +87,15 @@ def add_item(self, item_id, amount, price, name):
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):
Expand Down Expand Up @@ -129,5 +139,18 @@ def stop(self):
self.Active = False
self.shop_broadcast.join()

class CustomTimer(_Timer):
def __init__(self, interval, function, args=[], kwargs={}):
self._original_function = function
super(CustomTimer, self).__init__(interval, self._do_execute, args, kwargs)
self._result = None

def _do_execute(self, *a, **kw):
self._result = self._original_function(*a, **kw)

def join(self):
super(CustomTimer, self).join()
return self._result

if __name__ == '__main__':
print "Do not run this file directly. Run main.py"