Selaa lähdekoodia

Add 'jobs' and basic game element definition structure

Frans Bergman 7 vuotta sitten
vanhempi
commit
713570cd44
4 muutettua tiedostoa jossa 191 lisäystä ja 18 poistoa
  1. 63 10
      citybuilder/messagehandler.py
  2. 52 2
      citybuilder/player.py
  3. 14 6
      citybuilder/server.py
  4. 62 0
      config/game.yaml

+ 63 - 10
citybuilder/messagehandler.py

@@ -1,13 +1,66 @@
 import re
 import json
 
-handlers = {
-    "build": lambda player, message: {'result': 0}
-}
-
-def handle_message(connection, player, message):
-    handler = handlers[message['type']]
-    if handler:
-        connection.send_json(handler(player, message))
-    else:
-         connection.send_json({'result': 1})
+class MessageHandler:
+
+    def __init__(self, config):
+        self.handlers = {
+            "build": self.build,
+            "train": self.train,
+        }
+        self.config = config
+
+    def resource_check(self, player, cost):
+        cost = { k: cost[k] for k in cost.keys() if k != "time" }
+        for resource, required in cost.items():
+            if player.resources[resource] < required:
+                return False
+        for resource, required in cost.items():
+            player.resources[resource] -= required
+        return True
+
+    def build(self, player, message):
+        spec = self.config['building'][message['name']]
+        level_index = player.buildings[message['name']]
+        cost = spec['levels'][level_index]['cost']
+        if not self.resource_check(player, cost):
+            return {
+                'result': 1
+            }
+        player.add_job({
+            'type': "building",
+            'time': cost['time'],
+            'name': message['name'],
+        })
+
+    def train(self, player, message):
+        spec = self.config['unit'][message['name']]
+        if message['level'] > player.research[message['name']]:
+            return {
+                'result': 2
+            }
+        level_index = message['level'] - 1
+        cost = spec['levels'][level_index]['cost']
+        if not self.resource_check(player, cost):
+            return {
+                'result': 1
+            }
+        player.add_job({
+            'type': "unit",
+            'time': cost['time'],
+            'name': message['name'],
+            'level': message['level'],
+        })
+
+
+    def handle_message(self, connection, player, message):
+        handler = self.handlers[message['type']]
+        if handler:
+            result = handler(player, message)
+            if result is None:
+                result = {'result': 0}
+            result['context'] = message
+            connection.send_json(result)
+            player.update()
+        else:
+             connection.send_json({'result': 404})

+ 52 - 2
citybuilder/player.py

@@ -1,10 +1,49 @@
 from passlib.hash import pbkdf2_sha256
+import time
+import json
+
+
+class Unit:
+    def __init__(self, spec, level):
+        self.spec = spec
+        self.level = level
+
+
+class Job:
+    def __init__(self, player, product):
+        self.player = player
+        self.product = product
+        self.finish_time = time.time() + product['time']
+
+    def check_finish(self):
+        if time.time() > self.finish_time:
+            if self.product['type'] == "building":
+                self.player.buildings[self.product['name']] += 1
+            elif self.product['type'] == "unit":
+                self.player.units.append(Unit(self.product['spec'], self.product['level']))
+            return True
+        return False
+
 
 class Player:
-    def __init__(self, username, password):
+    def __init__(self, username, password, config):
         self.username = username
         self.set_password(password)
+        self.jobs = list()
+        self.buildings = { key: 0 for key in config['building'] }
+        self.units = list()
+        self.resources = {
+            'gold': 100,
+            'wood': 100,
+            'stone': 0,
+        }
+        self.research = {
+            'footman': 1,
+            'archer': 0,
+        }
 
+    def login(self, ws):
+        self.ws = ws
 
     def set_password(self, password):
         self.password = pbkdf2_sha256.encrypt(password, rounds=200000, salt_size=16)
@@ -12,5 +51,16 @@ class Player:
     def check_password(self, password):
         return pbkdf2_sha256.verify(password, self.password)
 
+    def add_job(self, product):
+        self.jobs.append(Job(self, product))
+
     def update(self):
-        pass
+        self.jobs = [job for job in self.jobs if not job.check_finish()]
+        self.ws.send_json({
+            'username': self.username,
+            'jobs': [{ 'product': job.product, 'finish_time': job.finish_time } for job in self.jobs],
+            'buildings': self.buildings,
+            'units': [unit.__dict__ for unit in self.units],
+            'resources': self.resources,
+            'research': self.research,
+        })

+ 14 - 6
citybuilder/server.py

@@ -1,6 +1,6 @@
 from SimpleWebSocketServer import SimpleWebSocketServer, WebSocket
 import json
-from citybuilder import messagehandler
+from citybuilder.messagehandler import MessageHandler
 from citybuilder.player import Player
 
 connections = {}
@@ -9,6 +9,7 @@ players = {}
 class MainServerSocket(WebSocket):
 
     def handleMessage(self):
+        global config
         try:
             print("Message received: " + self.data)
             message = json.loads(self.data)
@@ -17,21 +18,24 @@ class MainServerSocket(WebSocket):
                     if message['username'] in players and players[message['username']].check_password(message['password']):
                         connections[message['username']] = self
                         self.player = players[message['username']]
+                        self.player.login(self)
                         print(message['username'] + " logged in")
                     else:
-                        self.send_json({result: 1})
+                        self.send_json({'result': 1})
                 elif message['type'] == "register":
                     if message['username'] not in players:
                         connections[message['username']] = self
-                        players[message['username']] = Player(message['username'], message['password'])
+                        players[message['username']] = Player(message['username'], message['password'], config)
                         self.player = players[message['username']]
+                        self.player.login(self)
                     else:
-                        self.send_json({result: 2})
+                        self.send_json({'result': 2})
                 else:
-                    self.send_json({result: 3})
+                    self.send_json({'result': 3})
             else:
                 messagehandler.handle_message(self, self.player, message)
         except Exception as e:
+            print("Exception in message handling:")
             print(e)
 
     def send_json(self, data):
@@ -43,6 +47,10 @@ class MainServerSocket(WebSocket):
     def handleClose(self):
         print(self.address, 'closed')
 
-def run_server(config):
+def run_server(configuration):
+    global messagehandler
+    global config
+    config = configuration
+    messagehandler = MessageHandler(config)
     server = SimpleWebSocketServer('', config['server']['port'], MainServerSocket)
     server.serveforever()

+ 62 - 0
config/game.yaml

@@ -1,3 +1,65 @@
 game:
   server:
     port: 6060
+  building:
+    palace:
+      name: Palace
+      levels:
+        -
+          cost:
+            gold: 100
+            wood: 100
+            stone: 0
+            time: 30
+        -
+          cost:
+            gold: 500
+            wood: 500
+            stone: 100
+            time: 120
+    barracks:
+      name: Barracks
+      levels:
+        -
+          cost:
+            gold: 50
+            wood: 200
+            time: 300
+    library:
+      name: Library
+      levels:
+        -
+          cost:
+            gold: 1000
+            wood: 1000
+            time: 7200
+        -
+          cost:
+            gold: 10000
+            wood: 1000
+            stone: 1000
+            time: 43200 # 12 * 3600
+  unit:
+    footman:
+      name: Footman
+      levels:
+        -
+          hp: 10
+          damage: 3
+          range: 1
+          speed: 2
+          cost:
+            gold: 10
+            time: 10
+    archer:
+      name: Archer
+      levels:
+        -
+          hp: 6
+          damage: 2
+          range: 5
+          speed: 3
+          cost:
+            gold: 5
+            wood: 5
+            time: 10