Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
Commits on Source (1)
from abc import abstractmethod, ABCMeta
import json
from game.player import Player
from game.map import Map
from game.item import Item
class Command(object):
__metaclass__ = ABCMeta
"""
Abstract base class for commands
"""
METHOD_SERVERSTATUS = "serverStatus"
METHOD_SIGNUP = "signup"
METHOD_LOGIN = "login"
METHOD_INVENTORY = "inventory"
METHOD_MIXITEM = "mixitem"
METHOD_MAP = "map"
METHOD_MOVE = "move"
METHOD_FIELD = "field"
METHOD_OFFER = "offer"
METHOD_TRADEBOX = "tradebox"
METHOD_SENDFIND = "sendfind"
METHOD_FINDOFFER = "findoffer"
METHOD_SENDACCEPT = "sendaccept"
METHOD_ACCEPT = "accept"
METHOD_FETCHITEM = "fetchitem"
METHOD_CANCELOFFER = "canceloffer"
def __init__(self):
super().__init__()
self.__error = None
"""
Executes the command
"""
@abstractmethod
def execute(self):
pass
def getStatus(self):
if not self.__error:
return {'status': 'ok'}
else:
if isinstance(self.__error, str):
return {'status': 'fail', 'description': self.__error}
else:
return {'status': 'error'}
class CommandFactory(object):
def __init__(self, jsonObject):
super().__init__()
self.__json = jsonObject
def getCommand(self):
method = self.__json["method"]
if method == Command.METHOD_SERVERSTATUS:
return ServerStatusCommand(self.__json['server'])
elif method == Command.METHOD_SIGNUP:
return SignupCommand(self.__json["username"], self.__json["password"])
elif method == Command.METHOD_LOGIN:
return LoginCommand(self.__json["username"], self.__json["password"])
elif method == Command.METHOD_INVENTORY:
return InventoryQueryCommand(self.__json["token"])
elif method == Command.METHOD_MIXITEM:
return MixItemCommand(self.__json["token"], self.__json["item1"], self.__json["item2"])
elif method == Command.METHOD_MAP:
return MapQueryCommand(self.__json["token"])
elif method == Command.METHOD_MOVE:
return MoveCommand(self.__json["token"], self.__json["x"], self.__json["y"])
elif method == Command.METHOD_FIELD:
return GetItemFromFieldCommand(self.__json["token"])
elif method == Command.METHOD_OFFER:
return MakeItemOfferCommand(self.__json["token"],
self.__json["offered_item"],
self.__json["n1"],
self.__json["demanded_item"],
self.__json["n2"])
elif method == Command.METHOD_TRADEBOX:
return TradeboxQueryCommand(self.__json["token"])
elif method == Command.METHOD_SENDFIND:
return SendFindCommand(self.__json["token"], self.__json["item"])
elif method == Command.METHOD_FINDOFFER:
return FindOfferCommand(self.__json["item"])
elif method == Command.METHOD_SENDACCEPT:
return SendAcceptCommand(self.__json["token"], self.__json["offer_token"])
elif method == Command.METHOD_ACCEPT:
return AcceptItemOfferCommand(self.__json["offer_token"])
elif method == Command.METHOD_FETCHITEM:
return FetchOfferedItemCommand(self.__json["token"], self.__json["offer_token"])
elif method == Command.METHOD_CANCELOFFER:
return CancelItemOfferCommand(self.__json["token"], self.__json["offer_token"])
else:
raise ValueError("Unknown method: {}".format(method))
# SERVER COMMANDS #
class ServerStatusCommand(Command):
def __init__(self, serverList):
super().__init__()
self.__servers = serverList
def execute(self):
try:
for server in servers:
# TODO: put the data into the db
print ("{}{}".format(server['ip'], server['port']))
except Exception:
self.__error = True
class SignupCommand(Command):
def __init__(self, username, password):
super().__init__()
self.username = username
self.password = password
def execute(self):
pass
class LoginCommand(Command):
def __init__(self, username, password):
super().__init__()
self.username = username
self.password = password
self.player = None
def execute(self):
# TODO: find the player in the Game object, and generate the apropriate token
pass
def getStatus(self):
if not self.error and self.player:
return {
'status': 'ok',
'token': self.__player.__id,
'x': self.__player.currentLocation.x,
'y': self.__player.currentLocation.y,
'time': int(time.time())
}
else:
if not self.__error:
self.__error = True
super().getStatus()
class InventoryQueryCommand(Command):
"""
docstring for InventoryQueryCommand
"""
def __init__(self, token):
super().__init__()
self.token = token
self.inventory = []
def execute(self):
# TODO: get the inventory from the game class
pass
def getStatus(self):
if not self.error and self.inventory:
return {
'status': 'ok',
'inventory': self.inventory
}
else:
if not self.__error:
self.__error = True
super().getStatus()
class MixItemCommand(Command):
def __init__(self, token, item1_id, item2_id):
super().__init__()
self.token = token
self.item1 = item1_id
self.item2 = item2_id
self.result = None
def execute(self):
# TODO: mix the items
pass
def getStatus(self):
if self.result:
return {
'status': 'ok',
'item': self.result
}
else:
if not self.__error:
self.__error = True
super().getStatus()
class MapQueryCommand(Command):
def __init__(self, token):
super().__init__()
self.token = token
self.map = None
def execute(self):
# TODO: get the map info
pass
def getStatus(self):
if self.map:
return {
'status': 'ok',
'name': self.map.name,
'width': self.map.width,
'height': self.map.height
}
else:
if not self.__error:
self.__error = True
super().getStatus()
class MoveCommand(Command):
def __init__(self, token, x, y):
super().__init__()
self.token = token
self.x = x
self.y = y
def execute(self):
# TODO: move the player
pass
def getStatus(self):
if not self.__error:
return {
'status': 'ok',
'time': int(time.time())
}
else:
super().getStatus()
# alias: Field
class GetItemFromFieldCommand(Command):
def __init__(self, token):
super().__init__()
self.token = token
self.item = None
def execute(self):
# TODO: get the item from the player's current position
pass
def getStatus(self):
if not self.__error and self.result:
return {
'status': ok,
'item': self.item
}
else:
if not self.__error:
self.__error = True
super().getStatus()
class MakeItemOfferCommand(Command):
def __init__(self, token, offer_item, offer_itemCount, demand_item, demand_itemCount):
super().__init__()
self.token = token
self.offer_item = Item(id=offer_item, count=offer_itemCount)
self.demand_item = Item(id=demand_item, count=demand_itemCount)
def execute(self):
# TODO: make the offer
pass
class TradeboxQueryCommand(Command):
def __init__(self, token):
super().__init__()
self.token = token
self.result = None
def execute(self):
# TODO: get the tradebox of the player
pass
def getStatus(self):
if not self.__error and self.result:
return {
'status': 'ok',
'offers': self.result
}
else:
if not self.__error:
self.__error = True
super().getStatus()
class SendFindCommand(Command):
def __init__(self, token, itemId):
super().__init__()
self.token = token
self.item = itemId
self.result = None
def execute(self):
# TODO: get the offers for an item
pass
def getStatus(self):
if not self.__error and self.result:
return {
'status': 'ok',
'offers': self.result
}
else:
if not self.__error:
self.__error = True
super().getStatus()
# NOTE: this is something that is sent by the server, not received by the server
class FindOfferCommand(Command):
def __init__(self, item, ip, port):
super().__init__()
self.item = item
self.ip = ip
self.port = port
self.result = None
def execute(self):
# TODO: create a connection to such server, and send the query
pass
def getStatus(self):
if not self.__error and self.result:
return {
'status': 'ok',
'offers': self.result
}
else:
if not self.__error:
self.__error = True
super().getStatus()
class SendItemAcceptOfferCommand(Command):
def __init__(self, token, offer_token):
super().__init__()
self.token = token
self.offer_token = offer_token
def execute(self):
# TODO: accept the player's offer
pass
# NOTE: this is something that is sent by the server, not received by the server
class AcceptItemOfferCommand(Command):
def __init__(self, offer_token):
super().__init__()
self.token = token
self.offer_token = offer_token
def execute(self):
# TODO: accept the player's offer from other server
pass
class FetchOfferedItemCommand(Command):
def __init__(self, token, offer_token):
super().__init__()
self.token = token
self.offer_token = offer_token
def execute(self):
# TODO: fetch the player's offer
pass
class CancelItemOfferCommand(Command):
def __init__(self, token, offer_token):
super().__init__()
self.token = token
self.offer_token = offer_token
def execute(self):
# TODO: cancel the player's offer
pass
\ No newline at end of file
import pymongo
class Game(object):
DEFAULT_ID = 0
def __init__(self, id=Game.DEFAULT_ID):
super().__init__()
__loadGameData()
def __loadGameData(self):
pass
\ No newline at end of file
import abc
class GameObject(object):
__metaclass__ = abc.ABCMeta;
"""Represents a basic GameObject, with an id
Attributes:
id -- the GameObject's id
"""
def __init__(self, id=None, gameObject=None):
super().__init__()
if isinstance(gameObject, GameObject):
self.__copyInit(gameObject)
elif GameObject.isValidId(id):
self.__selfInit(id)
else:
raise ValueError('Invalid parameters')
def __selfInit(self, id):
this.__id = id
def __copyInit(self, gameObject):
this.__id = gameObject.__id
"""Generate the id of the GameObject"""
@classmethod
def generateId(self):
raise NotImplementedError();
@classmethod
def isValidId(self, id):
return isinstance(id, str) or isinstance(id, int)
def __str__(self):
return "[GameObject {id}]".format(id = self.id)
\ No newline at end of file
from game_object import GameObject
from enum import Enum
class ItemId(Enum):
HONEY = (0, 'R11')
HERBS = (1, 'R12')
CLAY = (2, 'R13')
MINERAL = (3, 'R14')
POTION = (4, 'R21')
INCENSE = (5, 'R22')
GEMS = (6, 'R23')
LIFE_ELIXIR = (7, 'R31')
MANA_CRYSTAL = (8, 'R32')
PHILOSOPHER_STONE = (9, 'R41')
def __init__(self, index: int, idStr: str):
assert isinstance(index, int) and isinstance(idStr, str)
this.index = index
this.id = idStr
class Item(GameObject):
"""docstring for Item"""
def __init__(self,
id: int = None,
itemId: ItemId = None,
item: Item = None,
count: int = None):
if isinstance(item, Item):
super().__init__(item.id)
super().__copyInit(item)
self.__copyInit(item)
elif isinstance(itemId, ItemId):
super().__init__(itemId.id)
if isinstance(count, int):
self.__selfInit(count)
else:
self.__selfInit(1)
elif GameObject.isValidId(id):
super().__init__(id)
if isinstance(count, int):
self.__selfInit(count)
else:
self.__selfInit(1)
else:
raise TypeError('Invalid constructor parameter(s) for Item')
def __selfInit(self, count: int):
if count > 0:
self.__count = count
else:
self.__count = 1
def __copyInit(self, item: Item):
self.__count = item.__count
def count(self, newVal: int = None):
if isinstance(newVal, int): # setter
if newVal >= 0:
self.__count = newVal
else:
raise ValueError('Item count cannot be negative')
elif not newVal: # getter
return __count
else: # some other param
raise TypeError('Invalid parameter for newVal')
"""Number of items used in a single mix"""
__MIX_USAGE = 3
@classmethod
def mixItems(self, item1: Item, item2: Item) -> Item:
if not isinstance(item1, Item):
raise TypeError('item1 is not an Item')
if not isinstance(item2, Item):
raise TypeError('item2 is not an Item')
if item1.__count >= __MIX_USAGE and item2.__count >= __MIX_USAGE:
# define the recipe here
result = None
# Level 1 mix
if Item.isEqual(item1, ItemId.HONEY) and Item.isEqual(item2, ItemId.HERBS):
result = Item(itemId=ItemId.POTION)
elif Item.isEqual(item1, ItemId.HERBS) and Item.isEqual(item2, ItemId.CLAY):
result = Item(itemId=ItemId.INCENSE)
elif Item.isEqual(item1, ItemId.CLAY) and Item.isEqual(item2, ItemId.MINERAL):
result = Item(itemId=ItemId.GEMS)
# Level 2 mix
elif Item.isEqual(item1, ItemId.POTION) and Item.isEqual(item2, ItemId.INCENSE):
result = Item(itemId=ItemId.LIFE_ELIXIR)
elif Item.isEqual(item1, ItemId.INCENSE) and Item.isEqual(item2, ItemId.GEMS):
result = Item(itemId=ItemId.MANA_CRYSTAL)
# Level 3 mix
elif Item.isEqual(item1, ItemId.LIFE_ELIXIR) and Item.isEqual(item2, ItemId.MANA_CRYSTAL):
result = Item(itemId=ItemId.PHILOSOPHER_STONE)
else:
raise ValueError('Unknown recipe for item {} and {}'.format(item1.id, item2.id))
# reduce
item1.__count -= __MIX_USAGE
item2.__count -= __MIX_USAGE
return result
else:
if item1.__count < __MIX_USAGE:
raise ValueError('not enough items for item1')
else:
raise ValueError('not enough items for item2')
@classmethod
def isEqual(self, item: Item, itemId: ItemId) -> boolean:
if isinstance(item, Item) and isinstance(itemId, ItemId):
return item.__id == itemId.index || item.__id == itemId.id
else:
raise TypeError('Invalid parameter(s)')
\ No newline at end of file
from game_object import GameObject
from ... import Game
from location import Location
import json
import time
class Player(GameObject):
DEFAULT_NAME = "Player"
"""Creates a Player object, for logging in purposes
Attributes:
username -- the Player's username, for identification purposes
password -- the Player's password
currentLocation -- the
"""
def __init__(self,
token : str = None
username : str,
password : str = None,
location : Location = None,
sprite = None):
assert isinstance(token, str) or isinstance(password, str)
if token:
super().__init__(token)
else:
super().__init__(__generateToken(username, password))
self.username = username
self.password = password
self.currentLocation = location
self.sprite = sprite
def moveTo(self,
x : int = None,
y : int = None,
location : Location = None):
if x is int and y is int:
self.location.x = x
self.location.y = y
elif location is Location:
self.location = location
else:
raise ValueError('Invalid parameter')
def takeItem(self,
x : int = None,
y : int = None,
location : Location = None,
offerId : str = None):
if x is int and y is int:
# do some item getting here
pass
elif location is Location:
# do some item gathering here
pass
elif offerId is str:
# do lookup
pass
else:
raise TypeError('Invalid parameter')
def addItem(self,
item: Item = None,
id: string = None,
count: int = 1):
if isinstance(item, Item):
pass
elif isinstance(id, str) and isinstance(count, int):
pass
else:
raise TypeError('Invalid parameter')
def mixItems(self,
item1: Item,
item2: Item):
pass
def makeOffer(self,
offer: Item,
demand: Item):
pass
def cancelOffer(self, offerId: str):
pass
def acceptOffer(self, offerId: str):
pass
@classmethod
def generateId(self):
# not used; token is used instead, generated from time and password, hashed together
raise NotImplementedError('use __generateId(password) instead of this')
@classmethod
def __generateToken(self, username, password):
assert isinstance(self.password, str) and isinstance(self.username, str)
text = username
text += ':'
text += password
text += str(int(time.time()))
return bcrypt.hashpw(text.encode(), bcrypt.gensalt())
\ No newline at end of file
import socket
import threading
import socketserver
import json
import time
from command import CommandFactory, Command
class RequestHandler(socketserver.BaseRequestHandler):
BUFSIZE = 4096
def handle(self):
data = self.getData()
# check if the request is not empty (aka pings)
if not data:
pass
else:
try:
jsonObject = json.loads(data)
# throw it into the command processor
factory = CommandFactory(jsonObject)
command = factory.getCommand()
command.execute()
response = command.getStatus()
self.request.sendall(json.dumps(response))
except ValueError, e:
pass # TODO: log the error
def getData(self, timeout = 3):
total_data = []
end = False
self.request.setblocking(0)
begin = time.time()
while not end:
# if got some data, break after wait sec
if total_data and time.time() - begin > timeout:
end = True
else:
# if no data, break after 2x the timeout
if time.time() - begin > timeout * 2:
end = True
else:
try:
data = self.request.recv(RequestHandler.BUFSIZE, 'ascii')
if not data:
time.sleep(0.1)
else:
total_data.append(data)
begin = time.time()
except Exception, e:
# TODO: log the error
end = True
return ''.join(total_data)
class ThreadedTcpServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
if __name__ == '__main__':
pass
\ No newline at end of file