예제 #1
0
    def startFactory(self):
        self.FPSInit(getFrameTime, 60)
        self.recvcount, self.sendcount, self.initedTime = 0, 0, time.time()
        self.clientCount = 0

        self.dispgroup = {}
        self.dispgroup["effectObjs"] = GameObjectGroup().initialize(
            gameObj=self, spriteClass=SpriteObj, teamcolor=(0x7F, 0x7F, 0x7F)
        )
        self.dispgroup["objplayers"] = []

        self.statObjN = Statistics()
        self.statCmpN = Statistics()
        self.statGState = Statistics()

        self.gameState = toGzJson(self.makeState())
        task.LoopingCall(self.printStat).start(1.0)
        task.LoopingCall(self.FPSRun).start(1.0 / 60)
        log.msg("Factory inited")
예제 #2
0
    def run(self):
        self.profile = ProfileMixin(g_profile)
        self.profile.begin()
        self.recvcount, self.sendcount = 0, 0
        Log.critical('GameLogicServer initing pid:%s', self.pid)
        self.FPSInit(getFrameTime, 60)

        self.dispgroup = {}
        self.dispgroup['effectObjs'] = GameObjectGroup().initialize(
            gameObj=self, spriteClass=SpriteObj, teamcolor=(0x7f, 0x7f, 0x7f))
        self.dispgroup['objplayers'] = []

        self.statObjN = Statistics()
        self.statCmpN = Statistics()
        self.statGState = Statistics()

        self.clients = {}  # clientid : team info
        self.gameState = toGzJson({
            'cmd': 'gameState',
            'frameinfo': {k: v for k, v in self.frameinfo.iteritems() if k in ['thisFrameTime']},
            'objplayers': [og.serialize() for og in self.dispgroup['objplayers']],
            'effectObjs': self.dispgroup['effectObjs'].serialize()
        })
        self.quit = False
        self.registerRepeatFn(self.prfps, 1)

        self.r2c = {}
        self.w2c = {}
        for c in self.channels:
            self.r2c[c.reader] = c
            self.w2c[c.writer] = c
        Log.info('GameLogicServer inited')

        for ch in self.channels:
            ch.writeTo(((0, 0), None))  # run server

        # main loop
        self.recvlist = [self.toMainCh.reader] + [
            c.reader for c in self.channels]
        self.sendlist = []

        while not self.quit:
            self.sendlist = [o.writer for o in self.channels if o.canSend()]
            inputready, outputready, exceptready = select.select(
                self.recvlist, self.sendlist, [], 0)

            if len(inputready) == 0 and len(outputready) == 0:
                self.FPSRun()
                self.FPSYield()

            for i in inputready:
                if i == self.toMainCh.reader:
                    self.quit = True
                    break
                else:
                    if i in self.r2c:
                        clientid, packet = self.r2c[i].readFrom()
                        cmdDict = fromGzJson(packet)
                        self.do1ClientCmd(self.r2c[i], clientid, cmdDict)
                    else:
                        Log.critical('invalid reader %s', i)

            for o in outputready:
                if o in self.w2c:
                    self.w2c[o].writeFromQueue()
                else:
                    Log.critical('invalid writer %s', i)

        for ch in self.channels:
            ch.writeTo(((0, -1), None))  # quit server

        Log.info('end doGame')
        self.prfps(0)
        self.profile.end()
예제 #3
0
class GameLogicServer(multiprocessing.Process, ShootingGameMixin, FPSMixin):

    def prfps(self, repeatinfo):
        self.diaplayScore()

        Log.critical('objs: %s', self.statObjN)
        Log.critical('cmps: %s', self.statCmpN)
        Log.critical('gamestatelen: %s', self.statGState)
        Log.critical('fps: %s', self.frameinfo.stat)
        Log.critical('clients %s ', len(self.clients))
        Log.critical('main channel %s ', self.toMainCh.getStatInfo())
        for c in self.channels:
            Log.critical('channel %s ', c.getStatInfo())

    def diaplayScore(self):
        teamscore = {}
        for j in self.dispgroup['objplayers']:
            if j.teamname in teamscore:
                teamscore[j.teamname]['teamscore'] += j.statistic['teamscore']
                teamscore[j.teamname]['member'] += 1
                teamscore[j.teamname]['objcount'] += len(j)
            else:
                teamscore[j.teamname] = dict(
                    teamscore=j.statistic['teamscore'],
                    color=j.teamcolor,
                    ai=j.__class__.__name__,
                    member=1,
                    objcount=len(j)
                )

        Log.info("{:12} {:15} {:>16} {:>8} {:>8} {:8}".format(
            'teamname', 'color', 'AI type', 'member', 'score', 'objcount'
        ))
        sortedinfo = sorted(
            teamscore.keys(), key=lambda x: -teamscore[x]['teamscore'])

        for j in sortedinfo:
            Log.info("{:12} {:15} {:>16} {:8} {:8.4f} {:8}".format(
                j,
                teamscore[j]['color'],
                teamscore[j]['ai'],
                teamscore[j]['member'],
                teamscore[j]['teamscore'],
                teamscore[j]['objcount']
            ))

    def getChannel(self):
        return self.forMainCh

    def doScore(self, resultdict):
        for src, targets in resultdict.iteritems():
            src.enabled = False
            if src.objtype != 'bounceball':
                self.dispgroup['effectObjs'].addSpriteExplosionEffect(src)
            else:
                # 충돌한 것이 bounceball 이면
                src.group.addBallExplosionEffect(
                    self.dispgroup['effectObjs'], src.group, src)
                srcLostScore = src.getDelScore(math.sqrt(src.level))
                src.group.statistic["teamscore"] -= srcLostScore
                uplevel = srcLostScore * 2 / len(targets)
                for target in targets:
                    if target.objtype != 'bounceball':
                        if target.group and target.group.hasBounceBall():
                            oldlevel = target.group[0].level
                            target.group[0].level += uplevel
                            inclevel = int(
                                target.group[0].level) - int(oldlevel)
                            for i in xrange(inclevel):
                                target.group.statistic[
                                    'act']['supershield'] += 1
                                target.group.AddSuperShield(
                                    target=target.group[0],
                                    expireFn=self.dispgroup[
                                        'effectObjs'].addSpriteExplosionEffect
                                )
                    if target.objtype not in ['bounceball', 'supershield', 'shield']:
                        target.group.statistic["teamscore"] += uplevel
        return

    def makeState(self):
        savelist = {
            'cmd': 'gameState',
            'frameinfo': {k: v for k, v in self.frameinfo.iteritems() if k in ['thisFrameTime']},
            'objplayers': [og.serialize() for og in self.dispgroup['objplayers']],
            'effectObjs': self.dispgroup['effectObjs'].serialize()
        }
        return savelist

    def saveState(self):
        try:
            savelist = toGzJson(self.makeState())
            self.gameState = savelist
        except zlib.error:
            Log.exception('zlib compress fail')
            return 0
        except ValueError:
            Log.exception('encode fail')
            return 0

        return len(savelist)

    def make1TeamCustom(self, teamname, aiclass, spriteClass, teamcolor, servermove):
        o = aiclass().initialize(
            teamcolor=teamcolor,
            teamname=teamname,
            effectObjs=self.dispgroup['effectObjs'],
            servermove=servermove,
            gameObj=self,
            spriteClass=spriteClass
        )
        o.makeMember()
        return o

    def __init__(self, servertype, channels):
        multiprocessing.Process.__init__(self)
        self.serverType = servertype
        self.channels = channels
        self.toMainCh, self.forMainCh = makeChannel()

    def run(self):
        self.profile = ProfileMixin(g_profile)
        self.profile.begin()
        self.recvcount, self.sendcount = 0, 0
        Log.critical('GameLogicServer initing pid:%s', self.pid)
        self.FPSInit(getFrameTime, 60)

        self.dispgroup = {}
        self.dispgroup['effectObjs'] = GameObjectGroup().initialize(
            gameObj=self, spriteClass=SpriteObj, teamcolor=(0x7f, 0x7f, 0x7f))
        self.dispgroup['objplayers'] = []

        self.statObjN = Statistics()
        self.statCmpN = Statistics()
        self.statGState = Statistics()

        self.clients = {}  # clientid : team info
        self.gameState = toGzJson({
            'cmd': 'gameState',
            'frameinfo': {k: v for k, v in self.frameinfo.iteritems() if k in ['thisFrameTime']},
            'objplayers': [og.serialize() for og in self.dispgroup['objplayers']],
            'effectObjs': self.dispgroup['effectObjs'].serialize()
        })
        self.quit = False
        self.registerRepeatFn(self.prfps, 1)

        self.r2c = {}
        self.w2c = {}
        for c in self.channels:
            self.r2c[c.reader] = c
            self.w2c[c.writer] = c
        Log.info('GameLogicServer inited')

        for ch in self.channels:
            ch.writeTo(((0, 0), None))  # run server

        # main loop
        self.recvlist = [self.toMainCh.reader] + [
            c.reader for c in self.channels]
        self.sendlist = []

        while not self.quit:
            self.sendlist = [o.writer for o in self.channels if o.canSend()]
            inputready, outputready, exceptready = select.select(
                self.recvlist, self.sendlist, [], 0)

            if len(inputready) == 0 and len(outputready) == 0:
                self.FPSRun()
                self.FPSYield()

            for i in inputready:
                if i == self.toMainCh.reader:
                    self.quit = True
                    break
                else:
                    if i in self.r2c:
                        clientid, packet = self.r2c[i].readFrom()
                        cmdDict = fromGzJson(packet)
                        self.do1ClientCmd(self.r2c[i], clientid, cmdDict)
                    else:
                        Log.critical('invalid reader %s', i)

            for o in outputready:
                if o in self.w2c:
                    self.w2c[o].writeFromQueue()
                else:
                    Log.critical('invalid writer %s', i)

        for ch in self.channels:
            ch.writeTo(((0, -1), None))  # quit server

        Log.info('end doGame')
        self.prfps(0)
        self.profile.end()

    def do1ClientCmd(self, ch, clientid, cmdDict):
        teaminfo = self.clients.get(clientid)
        if teaminfo is None:
            self.clients[clientid] = {}
            teaminfo = self.clients[clientid]

        cmd = cmdDict.get('cmd')

        if cmd == 'makeTeam':
            tn = cmdDict.get('teamname')
            o = self.make1TeamCustom(
                teamname=tn,
                aiclass=GameObjectGroup,
                teamcolor=cmdDict.get('teamcolor'),
                servermove=False,
                spriteClass=SpriteObj
            )
            self.dispgroup['objplayers'].append(o)
            teaminfo['teamid'] = o.ID
            teaminfo['teamname'] = tn
            ch.sendQueue.put((clientid, toGzJsonParams(
                cmd='teamInfo', teamname=tn, teamid=o.ID)))
            Log.debug('Join team %s %s', clientid, teaminfo)

        elif cmd == 'del':
            Log.debug('Leave team %s', teaminfo)
            try:
                self.delTeamByID(teaminfo['teamid'])
            except KeyError:
                pass
            del self.clients[clientid]

        elif cmd == 'reqState':
            ch.sendQueue.put((clientid, self.gameState))

        elif cmd == 'act':
            ch.sendQueue.put((clientid, toGzJsonParams(cmd='actACK')))

            actions = cmdDict.get('actions')
            tid = cmdDict['teamid']
            thisTeam = self.getTeamByID(tid)
            if thisTeam.servermove:
                Log.error('invalid client team %s', thisTeam)
                return
            actionjson = cmdDict['actions']
            actions = self.deserializeActions(actionjson)

            enemyTeamList = self.getEnemyTeamList(thisTeam)
            thisTeam.prepareActions(
                enemyTeamList,
                self.frameinfo.lastFPS,
                self.thistick
            )

            thisTeam.applyActions(actions)

        else:
            Log.warn('unknown cmd %s', cmdDict)

    def FPSMain(self):
        self.thistick = self.frameinfo.thisFrameTime

        objcount = sum([len(a) for a in self.dispgroup['objplayers']])
        self.statObjN.update(objcount)

        # 그룹내의 team 들을 automove 한다.
        for thisTeam in self.dispgroup['objplayers']:
            thisTeam.AutoMoveByTime(self.thistick)

        # make collision dictionary
        resultdict, cmpcount = self.makeCollisionDict()

        self.statCmpN.update(cmpcount)
        # do score
        self.doScore(resultdict)

        # 결과에 따라 삭제한다.
        for aa in self.dispgroup['objplayers']:
            aa.RemoveDisabled()

        self.dispgroup['effectObjs'].AutoMoveByTime(
            self.thistick).RemoveDisabled()

        self.statGState.update(self.saveState())
예제 #4
0
class GameLogicServer(ShootingGameMixin, FPSMixin, protocol.Factory):
    protocol = GameLogicProtocol

    def printStat(self):
        self.diaplayScore()
        log.msg("objs: ", self.statObjN)
        log.msg("cmps: ", self.statCmpN)
        log.msg("gamestatelen: ", self.statGState)
        log.msg("fps: ", self.frameinfo.stat)
        log.msg(self.getStatInfo())
        self.recvcount, self.sendcount, self.initedTime = 0, 0, time.time()

    def diaplayScore(self):
        teamscore = {}
        for j in self.dispgroup["objplayers"]:
            if j.teamname in teamscore:
                teamscore[j.teamname]["teamscore"] += j.statistic["teamscore"]
                teamscore[j.teamname]["member"] += 1
                teamscore[j.teamname]["objcount"] += len(j)
            else:
                teamscore[j.teamname] = dict(
                    teamscore=j.statistic["teamscore"],
                    color=j.teamcolor,
                    ai=j.__class__.__name__,
                    member=1,
                    objcount=len(j),
                )

        log.msg(
            "{:12} {:15} {:>16} {:>8} {:>8} {:8}".format("teamname", "color", "AI type", "member", "score", "objcount")
        )
        sortedinfo = sorted(teamscore.keys(), key=lambda x: -teamscore[x]["teamscore"])

        for j in sortedinfo:
            log.msg(
                "{:12} {:15} {:>16} {:8} {:8.4f} {:8}".format(
                    j,
                    teamscore[j]["color"],
                    teamscore[j]["ai"],
                    teamscore[j]["member"],
                    teamscore[j]["teamscore"],
                    teamscore[j]["objcount"],
                )
            )

    def getStatInfo(self):
        t = time.time() - self.initedTime
        return "clients:{} recv:{} {}/s send:{} {}/s".format(
            self.clientCount, self.recvcount, self.recvcount / t, self.sendcount, self.sendcount / t
        )

    def doScore(self, resultdict):
        for src, targets in resultdict.iteritems():
            src.enabled = False
            if src.objtype != "bounceball":
                self.dispgroup["effectObjs"].addSpriteExplosionEffect(src)
            else:
                # 충돌한 것이 bounceball 이면
                src.group.addBallExplosionEffect(self.dispgroup["effectObjs"], src.group, src)
                srcLostScore = src.getDelScore(math.sqrt(src.level))
                src.group.statistic["teamscore"] -= srcLostScore
                uplevel = srcLostScore * 2 / len(targets)
                for target in targets:
                    if target.objtype != "bounceball":
                        if target.group and target.group.hasBounceBall():
                            oldlevel = target.group[0].level
                            target.group[0].level += uplevel
                            inclevel = int(target.group[0].level) - int(oldlevel)
                            for i in xrange(inclevel):
                                target.group.statistic["act"]["supershield"] += 1
                                target.group.AddSuperShield(
                                    target=target.group[0],
                                    expireFn=self.dispgroup["effectObjs"].addSpriteExplosionEffect,
                                )
                    if target.objtype not in ["bounceball", "supershield", "shield"]:
                        target.group.statistic["teamscore"] += uplevel
        return

    def makeState(self):
        savelist = {
            "cmd": "gameState",
            "frameinfo": {"thisFrameTime": time.time()},
            "objplayers": [og.serialize() for og in self.dispgroup["objplayers"]],
            "effectObjs": self.dispgroup["effectObjs"].serialize(),
        }
        return savelist

    def saveState(self):
        try:
            savelist = toGzJson(self.makeState())
            self.gameState = savelist
        except zlib.error:
            log.msg("zlib compress fail")
            return 0
        except ValueError:
            log.msg("encode fail")
            return 0

        return len(savelist)

    def make1TeamCustom(self, teamname, aiclass, spriteClass, teamcolor, servermove):
        o = aiclass().initialize(
            teamcolor=teamcolor,
            teamname=teamname,
            effectObjs=self.dispgroup["effectObjs"],
            servermove=servermove,
            gameObj=self,
            spriteClass=spriteClass,
        )
        o.makeMember()
        return o

    def startFactory(self):
        self.FPSInit(getFrameTime, 60)
        self.recvcount, self.sendcount, self.initedTime = 0, 0, time.time()
        self.clientCount = 0

        self.dispgroup = {}
        self.dispgroup["effectObjs"] = GameObjectGroup().initialize(
            gameObj=self, spriteClass=SpriteObj, teamcolor=(0x7F, 0x7F, 0x7F)
        )
        self.dispgroup["objplayers"] = []

        self.statObjN = Statistics()
        self.statCmpN = Statistics()
        self.statGState = Statistics()

        self.gameState = toGzJson(self.makeState())
        task.LoopingCall(self.printStat).start(1.0)
        task.LoopingCall(self.FPSRun).start(1.0 / 60)
        log.msg("Factory inited")

    def do1ClientCmd(self, clinentprotocol, cmdDict):
        cmd = cmdDict.get("cmd")
        if cmd == "makeTeam":
            tn = cmdDict.get("teamname")
            o = self.make1TeamCustom(
                teamname=tn,
                aiclass=GameObjectGroup,
                teamcolor=cmdDict.get("teamcolor"),
                servermove=False,
                spriteClass=SpriteObj,
            )
            self.dispgroup["objplayers"].append(o)

            clinentprotocol.sendString(toGzJsonParams(cmd="teamInfo", teamname=tn, teamid=o.ID))

        elif cmd == "del":
            try:
                self.delTeamByID(cmdDict["teamid"])
            except KeyError:
                pass

        elif cmd == "reqState":
            clinentprotocol.sendString(self.gameState)

        elif cmd == "act":
            clinentprotocol.sendString(toGzJsonParams(cmd="actACK"))

            actions = cmdDict.get("actions")
            tid = cmdDict["teamid"]
            thisTeam = self.getTeamByID(tid)
            if thisTeam.servermove:
                log.msg("invalid client team ", thisTeam)
                return
            actionjson = cmdDict["actions"]
            actions = self.deserializeActions(actionjson)

            enemyTeamList = self.getEnemyTeamList(thisTeam)
            thisTeam.prepareActions(enemyTeamList, self.frameinfo.lastFPS, self.thistick)

            thisTeam.applyActions(actions)

        else:
            log.msg("unknown cmd ", cmdDict)

    def FPSMain(self):
        self.thistick = self.frameinfo.thisFrameTime

        objcount = sum([len(a) for a in self.dispgroup["objplayers"]])
        self.statObjN.update(objcount)

        # 그룹내의 team 들을 automove 한다.
        for thisTeam in self.dispgroup["objplayers"]:
            thisTeam.AutoMoveByTime(self.thistick)

        # make collision dictionary
        resultdict, cmpcount = self.makeCollisionDict()

        self.statCmpN.update(cmpcount)
        # do score
        self.doScore(resultdict)

        # 결과에 따라 삭제한다.
        for aa in self.dispgroup["objplayers"]:
            aa.RemoveDisabled()

        self.dispgroup["effectObjs"].AutoMoveByTime(self.thistick).RemoveDisabled()

        self.statGState.update(self.saveState())