Commit b4fbf5da authored by Alvin Natawiguna's avatar Alvin Natawiguna
Browse files

Done...?

parent 52f7a3de
......@@ -20,7 +20,7 @@ Python
- Run ``` python server.py [port] ```
## Additional Information
- TODO: create a sample file, which consists of the database
- TODO: create a sample file, which consists of the database + the user used for authentication
Last Updated: 23 April 2015
import abc
import json
import socket
import pymongo
import game
class Command(object):
......@@ -55,7 +58,7 @@ class Command(object):
returns dict object
"""
if not self.__error:
if self.__error == None:
return {'status': 'ok'}
else:
if isinstance(self.__error, str):
......@@ -63,12 +66,15 @@ class Command(object):
else:
return {'status': 'error'}
def setStatus(self, error):
self.__error = error
class CommandFactory(object):
def __init__(self, **jsonObject):
def __init__(self, jsonObject):
super().__init__()
self.__json = jsonObject
self.game = game.Game.getInstance()
self.game = game.game_class.Game.getInstance()
def getCommand(self):
method = self.__json["method"]
......@@ -110,10 +116,13 @@ class CommandFactory(object):
return FindOfferCommand(self.__json["item"], self.__json["ip"], self.__json["port"])
else:
return RecvFindOfferCommand(self.__json["item"])
elif method == Command.METHOD_SENDACCEPT:
elif method == Command.METHOD_SENDACCEPT:
return SendAcceptCommand(self.game, self.__json["token"], self.__json["offer_token"])
elif method == Command.METHOD_ACCEPT:
return AcceptItemOfferCommand(self.__json["offer_token"], self.__json["ip"], self.__json["port"])
if 'ip' in self.__json and 'port' in self.__json:
return AcceptItemOfferCommand(self.__json["offer_token"], self.__json["ip"], self.__json["port"])
else:
return RecvAcceptItemOfferCommand(self.__json["offer_token"])
elif method == Command.METHOD_FETCHITEM:
return FetchOfferedItemCommand(self.game, self.__json["token"], self.__json["offer_token"])
elif method == Command.METHOD_CANCELOFFER:
......@@ -167,7 +176,7 @@ class JoinCommand(Command):
if not self.__error:
self.__error = True
super().getStatus()
return super().getStatus()
class ServerStatusCommand(Command):
DB_COLLECTION_SERVER = 'activeServers'
......@@ -179,12 +188,12 @@ class ServerStatusCommand(Command):
def execute(self):
try:
with pymongo.MongoClient() as client:
db = client.get_database(game.Game.DB_NAME)
assert db.authenticate(game.Game.DB_USERNAME, game.Game.DB_PASSWORD)
db = client.get_database(game.game_class.Game.DB_NAME)
assert db.authenticate(game.game_class.Game.DB_USERNAME, game.game_class.Game.DB_PASSWORD)
collection = db.get_collection(ServerStatusCommand.DB_COLLECTION_SERVER)
for server in enumerate(self.servers):
for idx, server in enumerate(self.servers):
collection.update_one({'ip': server['ip']}, {'$set': {'ip': server['ip'],'port': server['port']} })
except Exception:
......@@ -201,23 +210,27 @@ class SignupCommand(Command):
def execute(self):
try:
game.playerSignup(self.username, self.password)
hashed_pw = self.game.playerSignup(self.username, self.password)
with pymongo.MongoClient(game.Game.DB_URI) as client:
db = client.get_database(game.Game.DB_NAME)
db.users.insert({
game.Player.KEY_USERNAME: self.username,
game.Player.KEY_PASSWORD: bcrypt.hashpw(self.password, bcrypt.gensalt()),
game.Player.KEY_ITEMS: [],
with pymongo.MongoClient() as client:
db = client.get_database(game.game_class.Game.DB_NAME)
assert db.authenticate(game.game_class.Game.DB_USERNAME, game.game_class.Game.DB_PASSWORD)
result = db.users.insert_one({
game.player.Player.KEY_USERNAME: self.username,
game.player.Player.KEY_PASSWORD: hashed_pw.decode('utf-8'),
game.player.Player.KEY_ITEMS: [],
game.Player.KEY_CURRENTLOCATION: {
game.player.Player.KEY_CURRENTLOCATION: {
'x': 0,
'y': 0
}
})
except Exception as e:
self.__error = str(e)
super().__setattr__('__error', True)
print(self.__dict__)
class LoginCommand(Command):
......@@ -232,17 +245,17 @@ class LoginCommand(Command):
def execute(self):
try:
self.token = game.playerLogin(self.username, self.password)
self.token = self.game.playerLogin(self.username, self.password)
# should not fail. Not yet tested though .__.
self.player = game.getPlayer(token = self.token)
self.player = self.game.getPlayer(token = self.token)
if not self.player:
self.__error = True
except Exception as e:
self.__error = str(e)
def getStatus(self):
if not self.error and self.token:
if not self.__error and self.token:
return {
'status': 'ok',
'token': self.token,
......@@ -254,7 +267,7 @@ class LoginCommand(Command):
if not self.__error:
self.__error = True
super().getStatus()
return super().getStatus()
class InventoryQueryCommand(Command):
"""
......@@ -269,7 +282,7 @@ class InventoryQueryCommand(Command):
self.inventory = []
def execute(self):
player = game.getPlayer(token = self.token)
player = self.game.getPlayer(token = self.token)
if not player:
self.__error = True
......@@ -286,7 +299,7 @@ class InventoryQueryCommand(Command):
if not self.__error:
self.__error = True
super().getStatus()
return super().getStatus()
class MixItemCommand(Command):
......@@ -312,8 +325,8 @@ class MixItemCommand(Command):
# update the inventory in the db
with pymongo.MongoClient() as client:
db = client.get_database(game.Game.DB_NAME)
assert db.authenticate(game.Game.DB_USERNAME, game.Game.DB_PASSWORD)
db = client.get_database(game.game_class.Game.DB_NAME)
assert db.authenticate(game.game_class.Game.DB_USERNAME, game.game_class.Game.DB_PASSWORD)
request = [
pymongo.UpdateOne({
......@@ -377,7 +390,7 @@ class MixItemCommand(Command):
if not self.__error:
self.__error = True
super().getStatus()
return super().getStatus()
class MapQueryCommand(Command):
......@@ -406,7 +419,7 @@ class MapQueryCommand(Command):
if not self.__error:
self.__error = True
super().getStatus()
return super().getStatus()
class MoveCommand(Command):
......@@ -428,8 +441,8 @@ class MoveCommand(Command):
# TODO: update the player's position in the db
with pymongo.MongoClient() as client:
db = client.get_database(game.Game.DB_NAME)
assert db.authenticate(game.Game.DB_USERNAME, game.Game.DB_PASSWORD)
db = client.get_database(game.game_class.Game.DB_NAME)
assert db.authenticate(game.game_class.Game.DB_USERNAME, game.game_class.Game.DB_PASSWORD)
result = db.users.update_one({
'username': player.username
......@@ -453,7 +466,7 @@ class MoveCommand(Command):
'time': int(time.time())
}
else:
super().getStatus()
return super().getStatus()
# alias: Field
class GetItemFromFieldCommand(Command):
......@@ -474,9 +487,9 @@ class GetItemFromFieldCommand(Command):
try:
self.item = player.takeItem(location = player.currentLocation)
with pymongo.MongoClient(game.Game.DB_URI) as client:
db = client.get_database(game.Game.DB_NAME)
assert db.authenticate(game.Game.DB_USERNAME, game.Game.DB_PASSWORD)
with pymongo.MongoClient(game.game_class.Game.DB_URI) as client:
db = client.get_database(game.game_class.Game.DB_NAME)
assert db.authenticate(game.game_class.Game.DB_USERNAME, game.game_class.Game.DB_PASSWORD)
result = db.users.update_one({
'username': player.username,
......@@ -512,7 +525,7 @@ class GetItemFromFieldCommand(Command):
if not self.__error:
self.__error = True
super().getStatus()
return super().getStatus()
class MakeItemOfferCommand(Command):
......@@ -566,7 +579,7 @@ class TradeboxQueryCommand(Command):
if not self.__error:
self.__error = True
super().getStatus()
return super().getStatus()
class SendFindCommand(Command):
......@@ -593,7 +606,7 @@ class SendFindCommand(Command):
if not self.__error:
self.__error = True
super().getStatus()
return super().getStatus()
# NOTE: this is something that is sent by the server, not received by the server
class FindOfferCommand(Command):
......@@ -636,7 +649,7 @@ class FindOfferCommand(Command):
if not self.__error:
self.__error = True
super().getStatus()
return super().getStatus()
class RecvFindOfferCommand(Command):
......@@ -649,9 +662,9 @@ class RecvFindOfferCommand(Command):
def execute(self):
try:
with pymongo.MongoClient(game.Game.DB_URI) as client:
db = client.get_database(game.Game.DB_NAME)
assert db.authenticate(game.Game.DB_USERNAME, game.Game.DB_PASSWORD)
with pymongo.MongoClient(game.game_class.Game.DB_URI) as client:
db = client.get_database(game.game_class.Game.DB_NAME)
assert db.authenticate(game.game_class.Game.DB_USERNAME, game.game_class.Game.DB_PASSWORD)
cursor = db.offers.find({'offer_item.id' : self.item})
......@@ -675,7 +688,7 @@ class RecvFindOfferCommand(Command):
if not self.__error:
self.__error = True
super().getStatus()
return super().getStatus()
class SendItemAcceptOfferCommand(Command):
......@@ -691,8 +704,8 @@ class SendItemAcceptOfferCommand(Command):
player = self.game.getPlayer(self.token)
if player:
with pymongo.MongoClient() as client:
db = client.get_database(game.Game.DB_NAME)
assert db.authenticate(game.Game.DB_USERNAME, game.Game.DB_PASSWORD)
db = client.get_database(game.game_class.Game.DB_NAME)
assert db.authenticate(game.game_class.Game.DB_USERNAME, game.game_class.Game.DB_PASSWORD)
offer = db.offers.find_one({'id': self.offer_token})
if offer:
......@@ -796,7 +809,7 @@ class AcceptItemOfferCommand(Command):
if not self.__error:
self.__error = True
super().getStatus()
return super().getStatus()
class RecvAcceptItemOfferCommand(Command):
......@@ -808,8 +821,8 @@ class RecvAcceptItemOfferCommand(Command):
def execute(self):
try:
with pymongo.MongoClient() as client:
db = client.get_database(game.Game.DB_NAME)
assert db.authenticate(game.Game.DB_USERNAME, game.Game.DB_PASSWORD)
db = client.get_database(game.game_class.Game.DB_NAME)
assert db.authenticate(game.game_class.Game.DB_USERNAME, game.game_class.Game.DB_PASSWORD)
item = db.offers.find_one({'id' : self.offer_token})
......@@ -844,8 +857,8 @@ class FetchOfferedItemCommand(Command):
player = self.game.getPlayer(self.token)
if player:
with pymongo.MongoClient() as client:
db = client.get_database(game.Game.DB_NAME)
assert db.authenticate(game.Game.DB_USERNAME, game.Game.DB_PASSWORD)
db = client.get_database(game.game_class.Game.DB_NAME)
assert db.authenticate(game.game_class.Game.DB_USERNAME, game.game_class.Game.DB_PASSWORD)
offer = db.offers.find_one({'id': self.offer_token})
if offer: # offer is in DB
......@@ -898,8 +911,8 @@ class CancelItemOfferCommand(Command):
player = self.game.getPlayer(self.token)
if player:
with pymongo.MongoClient() as client:
db = client.get_database(game.Game.DB_NAME)
assert db.authenticate(game.Game.DB_USERNAME, game.Game.DB_PASSWORD)
db = client.get_database(game.game_class.Game.DB_NAME)
assert db.authenticate(game.game_class.Game.DB_USERNAME, game.game_class.Game.DB_PASSWORD)
offer = db.offers.find_one({'id': self.offer_token})
if offer: # offer is in DB
......
from . import game_object, game_class, item, player
\ No newline at end of file
......@@ -50,7 +50,7 @@ class Game(object):
self.offers = []
with open(mapFile) as map_file:
self.__loadMap(json.load(mapFile))
self.__loadMap(json.load(map_file))
self.__loadPlayers()
......@@ -67,17 +67,20 @@ class Game(object):
self.map = GameMap(json['name'], json['width'], json['height'], json['map'])
def __loadPlayers(self):
from .player import Player
self.players = []
with pymongo.MongoClient() as client:
db = client.get_database(Game.DB_NAME)
assert db.authenticate(Game.DB_USERNAME, Game.DB_PASSWORD)
# load the players from the db
cursor = db.get_collection(Game.DB_COLLECTION_USERS)
cursor = db.get_collection(Game.DB_COLLECTION_USERS).find()
for player in cursor.find({}):
location = Location(player['location']['x'], player['location']['y'])
players.append(Player(self, player['username'], player['password'].encode(), location))
for user in cursor:
print(user)
location = Location(user[Player.KEY_CURRENTLOCATION]['x'], user[Player.KEY_CURRENTLOCATION]['y'])
self.players.append(Player(self, user['username'], user['password'].encode(), location))
def __loadOffers(self):
pass
......@@ -92,8 +95,10 @@ class Game(object):
Returns the authentication token
"""
def playerLogin(self, username, password):
for idx, player in enumerate(self.players):
if player.username == username:
from .player import Player
for idx, user in enumerate(self.players):
if user.username == username:
break
else:
......@@ -104,11 +109,11 @@ class Game(object):
assert isinstance(password, bytes)
if bcrypt.hashpw(password, player.password) != player.password:
if bcrypt.hashpw(password, user.password.encode()) != user.password.encode():
raise ValueError('invalid password')
token = Player.__generateToken(username, password)
player.token = token
user.token = token
return token
......@@ -120,8 +125,10 @@ class Game(object):
password -- the Player's password in plaintext
"""
def playerSignup(self, username, password):
for idx, player in enumerate(self.players):
if player.username == username:
from .player import Player
for idx, user in enumerate(self.players):
if user.username == username:
raise ValueError('Username already exists')
else:
......@@ -130,7 +137,9 @@ class Game(object):
hashed_pass = bcrypt.hashpw(password, bcrypt.gensalt())
self.players.append(Player(username, hashed_pass))
self.players.append(Player(self, username, hashed_pass))
return hashed_pass
"""
Get a player object
......@@ -194,6 +203,8 @@ class Game(object):
For use with ...
"""
from .item import ItemOffer
with pymongo.MongoClient() as client:
db = client.get_database(Game.DB_NAME)
assert db.authenticate(Game.DB_USERNAME, Game.DB_PASSWORD)
......
......@@ -19,10 +19,10 @@ class GameObject(object):
raise ValueError('Invalid parameters')
def __selfInit(self, id):
this.__id = id
self.__id = id
def __copyInit(self, gameObject):
this.__id = gameObject.__id
self.__id = gameObject.__id
"""Generate the id of the GameObject"""
@classmethod
......
from enum import Enum
import game
import game.game_object
class ItemId(Enum):
HONEY = (0, 'R11')
......@@ -50,7 +50,7 @@ class ItemId(Enum):
return retval
class Item(game.GameObject):
class Item(game.game_object.GameObject):
"""docstring for Item"""
def __init__(self,
......@@ -71,7 +71,7 @@ class Item(game.GameObject):
else:
self.__selfInit(1)
elif game.GameObject.isValidId(id):
elif game.game_object.GameObject.isValidId(id):
super().__init__(id)
if isinstance(count, int):
......@@ -169,7 +169,7 @@ class Item(game.GameObject):
return self.__dict__ == other.__dict__
elif isinstance(other, ItemId):
return self.__id == other.index or self.__id == other.idStr
else
else:
raise TypeError("No comparision defined between Item and {}".format(other.__class__))
def __ne__(self, other):
......@@ -182,7 +182,7 @@ class Item(game.GameObject):
else:
raise TypeError('Invalid parameter(s)')
class ItemOffer(game.GameObject):
class ItemOffer(game.game_object.GameObject):
"""docstring for ItemOffer"""
def __init__(self, username: str, offer: Item, demand: Item, id = None, available = True):
......
{
"name" : "Bandar Behari",
"width" : 4,
"height" : 4,
"map" :
[
["R13", "R13", "R13", "R13"],
["R13", "R13", "R14", "R14"],
["R13", "R14", "R14", "R14"],
["R13", "R14", "R14", "R14"]
]
}
\ No newline at end of file
import game
import json
import time
import pymongo
class Player(game.GameObject):
from .game_object import GameObject
from .game_class import Game, Location
class Player(GameObject):
COUNT = 0
KEY_USERNAME = 'username'
......@@ -15,20 +17,20 @@ class Player(game.GameObject):
"""Creates a Player object, for logging in purposes
Attributes:
game -- the game.Game object related to the player
game -- the Game object related to the player
username -- the Player's username, for identification purposes
password -- the Player's password
location -- the Player's avatar's current position in the map
"""
def __init__(self,
game : game.game.Game,
gameInstance: Game,
username : str,
password : str,
location : game.Location = None
location : Location = None
):
super().__init__(Player.generateId())
self.game = game
self.game = gameInstance
self.username = username
self.password = password
......@@ -38,23 +40,23 @@ class Player(game.GameObject):
if not location:
# new user implied
self.currentgame.Location = game.Location(0, 0)
self.game.Location = Location(0, 0)
else:
# user already exists in db
self.currentgame.Location = location
self.game.Location = location
self.__loadProperties()
def __loadProperties(self):
with pymongo.MongoClient() as client:
db = client.get_database(game.Game.DB_NAME)
db = client.get_database(Game.DB_NAME)
assert db.authenticate(Game.DB_USERNAME, Game.DB_PASSWORD)
cursor = db.get_collection(game.Game.DB_COLLECTION_USERS).find_one({'username': self.username})
cursor = db.get_collection(Game.DB_COLLECTION_USERS).find({'username': self.username})
if cursor.count() == 1:
userDict = cursor.next()
__loadItems(db, userDict)
self.__loadItems(db, userDict)
else:
if cursor.count() == 0:
raise LookupError('player not found: {}'.format(self.username))
......@@ -62,12 +64,14 @@ class Player(game.GameObject):
raise LookupError('multiple players found for {}:{}'.format(self.username, cursor.count()))
def __loadItems(self, db, userDict):
from .item import Item
if 'items' in userDict:
for idx, item in enumerate(userDict['items']):
self.items.append(game.Item(id = item['id'], count = item['count']))
self.items.append(Item(id = item['id'], count = item['count']))
else:
# initialize empty inventory
db.get_collection(game.Game.DB_COLLECTION_USERS).update_one(
db.get_collection(Game.DB_COLLECTION_USERS).update_one(
{
'_id': userDict['_id']
},
......@@ -88,17 +92,19 @@ class Player(game.GameObject):
return inventory
def getTradebox(self):
from .item import Item, ItemOffer
with pymongo.MongoClient() as client:
db = client.get_database(game.Game.DB_NAME)
assert db.authenticate(game.Game.DB_USERNAME, game.Game.DB_PASSWORD)
db = client.get_database(Game.DB_NAME)
assert db.authenticate(Game.DB_USERNAME, Game.DB_PASSWORD)
myOffers = []
for offer in db.offers.find({'username': self.username}):
myOffers.append(game.ItemOffer(
myOffers.append(ItemOffer(
offer['username'],
game.Item(offer['demand']['id'], offer['demand']['count']),
game.Item(offer['offer']['id'], offer['offer']['count']),
Item(offer['demand']['id'], offer['demand']['count']),
Item(offer['offer']['id'], offer['offer']['count']),
offer['id']
))
......@@ -107,16 +113,16 @@ class Player(game.GameObject):
def moveTo(self,
x : int = None,
y : int = None,
location : game.Location = None):
if x is int and y is int:
location : Location = None):
if isinstance(x, int) and isinstance(y, int):
if x in range(0, self.game.map.width) and y in range(0, self.game.map.height):
self.currentgame.Location.x = x