Browse files

common.showException() lets you report a python exception so it shows…

… up in the errors dialog

AutoTargeter is an order of magnitude more efficient so it shouldn't cause lag in fleet fights anymore
Fixed AutoTargeter's handling of reserved target slots (previously it would attempt to lock targets when reserved slots were full)
Added getCachedItem function to common.eve.state for getting the slimitem, ball, or flag name for a given id efficiently
Various function signature changes
  • Loading branch information...
1 parent dfad882 commit 00ffec1525d2726bf73b3c0992917d68a0912c35 @kg committed Dec 18, 2010
View
2 .gitignore
@@ -25,4 +25,6 @@
/EventNotifications/obj
/RemoteControl/bin
/RemoteControl/obj
+/JabberGateway/bin
+/JabberGateway/obj
/Common/evedata.db
View
99 AutoTargeter/autotargeter.py
@@ -2,13 +2,15 @@
from shootblues.common import log
from shootblues.common.eve import SafeTimer, runOnMainThread, getFlagName, getNamesOfIDs, isBallTargetable, isBallWarping, isPlayerJumping
from shootblues.common.service import forceStart, forceStop
+from shootblues.common.eve.state import TargetableCategories, getCachedItem
import uix
import json
import state
import base
import destiny
import uthread
import trinity
+import blue
from util import Memoized
prefs = {}
@@ -43,27 +45,6 @@ def notifyPrefsChanged(newPrefsJson):
FlagNeutralPlayer = set(["StandingNeutral"])
FlagFriendlyPlayer = set(["StandingGood", "StandingHigh", "SameFleet", "SameAlliance", "SameCorp"])
-TargetableCategories = set([const.categoryEntity, const.categoryDrone, const.categoryShip])
-
-class BallInfo:
- def __init__(self, ball, slimItem):
- self.id = slimItem.itemID
- self.ball = ball
- self.slimItem = slimItem
- self.flag = getFlagName(slimItem)
-
- def updateFlag(self):
- self.flag = getFlagName(self.slimItem)
-
- @property
- def isEligible(self):
- return (
- (getPref("TargetHostileNPCs", False) and self.flag in FlagHostileNPC) or
- (getPref("TargetHostilePlayers", False) and self.flag in FlagHostilePlayer) or
- (getPref("TargetNeutralPlayers", False) and self.flag in FlagNeutralPlayer) or
- (getPref("TargetFriendlyPlayers", False) and self.flag in FlagFriendlyPlayer)
- )
-
class AutoTargeterSvc:
__notifyevents__ = [
"DoBallsAdded",
@@ -86,25 +67,22 @@ def getDistance(self, targetID):
ballpark = eve.LocalSvc("michelle").GetBallpark()
return ballpark.DistanceBetween(eve.session.shipid, targetID)
- def makeTargetSorter(self, currentTargets):
- gd = Memoized(self.getDistance)
- gp = Memoized(getPriority)
-
+ def makeTargetSorter(self, currentTargets, gp, gd):
def targetSorter(lhs, rhs):
# Highest priority first
- priLhs = gp(targetID=lhs)
- priRhs = gp(targetID=rhs)
+ priLhs = gp(lhs.id)
+ priRhs = gp(rhs.id)
result = cmp(priRhs, priLhs)
if result == 0:
result = cmp(
- rhs in currentTargets,
- lhs in currentTargets
+ rhs.id in currentTargets,
+ lhs.id in currentTargets
)
if result == 0:
- distLhs = gd(lhs)
- distRhs = gd(rhs)
+ distLhs = gd(lhs.id)
+ distRhs = gd(rhs.id)
result = cmp(distLhs, distRhs)
return result
@@ -124,7 +102,7 @@ def getMaxTargets(self):
))
return max(maxTargets - reservedSlots, 0)
- def filterTargets(self, bis):
+ def filterTargets(self, bis, gp, gd):
targetSvc = sm.services['target']
ballpark = eve.LocalSvc("michelle").GetBallpark()
if not ballpark:
@@ -146,17 +124,20 @@ def filterTargets(self, bis):
maxTargetRange = self.getMaxTargetRange()
for bi in bis:
- if not isBallTargetable(bi.ball):
+ if not bi:
+ continue
+
+ if gp(bi.id) < 0:
continue
- if getPriority(slimItem=bi.slimItem) < 0:
+ if not isBallTargetable(bi.ball):
continue
- distance = ballpark.DistanceBetween(eve.session.shipid, bi.id)
+ distance = gd(bi.id)
if distance > maxTargetRange:
continue
- result.append(bi.id)
+ result.append(bi)
return result
@@ -165,7 +146,7 @@ def updateTargets(self):
self.__updateTimer = None
return
- ballpark = eve.LocalSvc("michelle").GetBallpark()
+ ballpark = sm.services["michelle"].GetBallpark()
if not ballpark:
return
@@ -176,16 +157,21 @@ def updateTargets(self):
maxTargets = self.getMaxTargets()
if maxTargets <= 0:
return
+
+ gd = Memoized(self.getDistance)
+ gp = Memoized(getPriority)
- currentTargets = self.filterTargets([
- self.__balls[id] for id in self.__lockedTargets
- if id in targetSvc.targets
- ])
+ currentTargets = [self.__balls.get(id, None) for id in self.__lockedTargets
+ if id in targetSvc.targets]
+ currentTargets = [bi.id for bi in self.filterTargets(currentTargets, gp, gd)]
exclusionSet = set(targetSvc.targeting + targetSvc.autoTargeting + currentTargets)
- targetSorter = self.makeTargetSorter(exclusionSet)
+ targetSorter = self.makeTargetSorter(exclusionSet, gp, gd)
+
+ startTime = blue.os.GetTime(1)
+ targets = self.filterTargets(self.__eligibleBalls, gp, gd)
- targets = self.filterTargets(self.__eligibleBalls)
targets.sort(targetSorter)
+ elapsed = (blue.os.GetTime(1) - startTime) / 10000000.0
currentlyTargeting = set([
id for id in (targetSvc.targeting + targetSvc.autoTargeting)
@@ -194,14 +180,13 @@ def updateTargets(self):
allLockedTargets = set(targetSvc.targeting + targetSvc.autoTargeting + targetSvc.targets)
maxNewTargets = max(maxTargets - len(allLockedTargets), 0)
- targets = set(targets[0:maxTargets])
+ targets = set([bi.id for bi in targets[0:maxTargets]])
- currentTargets.sort(targetSorter)
currentTargets = set(currentTargets)
targetsToUnlock = (currentTargets - targets) - currentlyTargeting
- targetsToLock = (targets - set(targetSvc.targets)) - currentlyTargeting
- targetsToLock = list(targetsToLock)[0:maxNewTargets]
+ targetsToLock = list((targets - set(targetSvc.targets)) - currentlyTargeting)
+ targetsToLock = targetsToLock[0:maxNewTargets]
if len(targetsToUnlock):
log("Unlocking %s", ", ".join(getNamesOfIDs(targetsToUnlock)))
@@ -224,7 +209,7 @@ def updateTargets(self):
self.tryLockTarget,
targetSvc, targetID
)
-
+
def tryLockTarget(self, targetSvc, targetID):
try:
targetSvc.TryLockTarget(targetID)
@@ -246,9 +231,7 @@ def populateBalls(self):
lst = []
for ballID, ball in ballpark.balls.iteritems():
- slimItem = ballpark.GetInvItem(ballID)
- if slimItem:
- lst.append((ball, slimItem))
+ lst.append((ball, ballpark.GetInvItem(ballID)))
self._DoBallsAdded(lst)
@@ -259,24 +242,32 @@ def DoBallsAdded(self, lst, **kwargs):
lst
)
+ def isEligible(self, cachedItem):
+ return (
+ (getPref("TargetHostileNPCs", False) and cachedItem.flag in FlagHostileNPC) or
+ (getPref("TargetHostilePlayers", False) and cachedItem.flag in FlagHostilePlayer) or
+ (getPref("TargetNeutralPlayers", False) and cachedItem.flag in FlagNeutralPlayer) or
+ (getPref("TargetFriendlyPlayers", False) and cachedItem.flag in FlagFriendlyPlayer)
+ )
+
def _DoBallsAdded(self, lst):
for (ball, slimItem) in lst:
if not slimItem.categoryID in TargetableCategories:
continue
if slimItem.itemID == eve.session.shipid:
continue
- bi = BallInfo(ball, slimItem)
+ bi = getCachedItem(slimItem.itemID, ball, slimItem)
self.__balls[slimItem.itemID] = bi
- if bi.isEligible:
+ if self.isEligible(bi):
self.__eligibleBalls.add(bi)
def populateEligibleBalls(self):
self.__eligibleBalls = set()
for ballInfo in self.__balls.itervalues():
- if ballInfo.isEligible:
+ if self.isEligible(ballInfo):
self.__eligibleBalls.add(ballInfo)
def DoBallRemove(self, ball, slimItem, *args, **kwargs):
View
4 Common/Common.cs
@@ -109,6 +109,10 @@ public Common (ScriptName name)
LogWindowInstance = null;
}
+ public void ShowError (ProcessInfo process, string errorText) {
+ Program.ShowErrorMessage(errorText, process);
+ }
+
public static IEnumerator<object> CreateNamedChannel (ProcessInfo process, string name) {
var channel = process.GetNamedChannel(name);
View
39 Common/common.eve.py
@@ -1,4 +1,4 @@
-from shootblues.common import log, onMainThread
+from shootblues.common import log, onMainThread, showException
ActionThreshold = (10000000L * 200) / 100
MainThreadQueue = []
@@ -42,31 +42,9 @@ def getName(id):
return result
-def getFlagName(slimItem):
- validCategories = [const.categoryShip, const.categoryDrone, const.categoryEntity]
- if slimItem.categoryID not in validCategories:
- return None
-
- stateSvc = eve.LocalSvc("state")
- props = stateSvc.GetProps()
-
- flag = stateSvc.CheckStates(slimItem, "flag")
- if flag:
- flagProps = props.get(flag, None)
- if flagProps:
- return flagProps[1]
-
- colorFlag = 0
- if slimItem.typeID:
- itemType = eve.LocalSvc("godma").GetType(slimItem.typeID)
- for attr in itemType.displayAttributes:
- if attr.attributeID == const.attributeEntityBracketColour:
- if attr.value == 1:
- return "HostileNPC"
- elif attr.value == 0:
- return "NeutralNPC"
-
- return None
+def getFlagName(id, slimItem=None):
+ from shootblues.common.eve.state import getCachedItem
+ return getCachedItem(id=id, slimItem=slimItem).flag
def getCharacterName(charID):
if not charID:
@@ -250,7 +228,7 @@ def activateModule(module, pulse=False, targetID=None, actionThreshold=ActionThr
def_effect = getattr(module, "def_effect", None)
- timestamp = blue.os.GetTime()
+ timestamp = blue.os.GetTime(1)
lastAction = int(getattr(module, "__last_action__", 0))
if (ActionThreshold is not None and
abs(lastAction - timestamp) <= ActionThreshold):
@@ -436,12 +414,11 @@ def delayedSyncState(self):
def tick(self):
try:
self.__handler()
- except:
- log("SafeTimer %r temporarily disabled due to error", self.getName())
+ except Exception:
+ showException()
+
self.__timer = None
runOnMainThread(self.delayedSyncState)
-
- raise
def __unload__():
global MainThreadQueue, MainThreadQueueRunning, MainThreadQueueInvoker
View
146 Common/common.eve.state.py
@@ -1,5 +1,83 @@
serviceInstance = None
+TargetableCategories = set([
+ const.categoryShip, const.categoryDrone,
+ const.categoryEntity, const.categoryStructure,
+ const.categoryStation
+])
+
+class ItemDataCache(object):
+ __slots__ = ("id", "_ball", "_slimItem", "_flag", "_flagCached")
+
+ def __init__(self, id, ball=None, slimItem=None):
+ self.id = id
+ self._ball = ball
+ self._slimItem = slimItem
+ self._flag = None
+ self._flagCached = False
+
+ @property
+ def ball(self):
+ if not self._ball:
+ ballpark = sm.services["michelle"].GetBallpark()
+ if not ballpark:
+ return None
+
+ self._ball = ballpark.GetBall(self.id)
+
+ return self._ball
+
+ @property
+ def slimItem(self):
+ if not self._slimItem:
+ ballpark = sm.services["michelle"].GetBallpark()
+ if not ballpark:
+ return None
+
+ self._slimItem = ballpark.GetInvItem(self.id)
+
+ return self._slimItem
+
+ def removedFromBallpark(self):
+ self._slimItem = None
+ self._ball = None
+
+ def clearFlag(self):
+ self._flag = None
+ self._flagCached = False
+
+ @property
+ def flag(self):
+ if not self._flagCached:
+ slimItem = self.slimItem
+ self._flag = None
+
+ if slimItem.categoryID in TargetableCategories:
+ stateSvc = sm.services["state"]
+ props = stateSvc.GetProps()
+
+ flag = stateSvc.CheckStates(slimItem, "flag")
+ if flag:
+ flagProps = props.get(flag, None)
+ if flagProps:
+ self._flag = flagProps[1]
+
+ colorFlag = 0
+ if slimItem.typeID:
+ itemType = eve.LocalSvc("godma").GetType(slimItem.typeID)
+ for attr in itemType.displayAttributes:
+ if attr.attributeID == const.attributeEntityBracketColour:
+ if attr.value == 1:
+ self._flag = "HostileNPC"
+ break
+ elif attr.value == 0:
+ self._flag = "NeutralNPC"
+ break
+
+ self._flagCached = True
+
+ return self._flag
+
def installStateMonitor():
global serviceInstance
@@ -13,26 +91,56 @@ class StateMonitorSvc:
__notifyevents__ = [
"DoBallsAdded",
"DoBallRemove",
- "DoBallClear"
+ "DoBallClear",
+ "OnStandingSet",
+ "OnStandingsModified",
+ "OnSessionChanged"
]
def __init__(self):
self.forceFields = []
+ self.objectCache = {}
- runOnMainThread(self.populateBalls)
+ runOnMainThread(self.populateBalls)
+ def flushCacheFor(self, id):
+ if self.objectCache.has_key(id):
+ del self.objectCache[id]
+
+ def flushCache(self):
+ self.objectCache = {}
+
+ def get(self, id, ball=None, slimItem=None):
+ result = self.objectCache.get(id, None)
+ if not result:
+ result = self.objectCache[id] = ItemDataCache(
+ id=id, ball=ball, slimItem=slimItem
+ )
+
+ return result
+
+ def OnStandingSet(self, fromID, toID, standing):
+ ce = self.objectCache.get(toID, None)
+ if ce:
+ ce.clearFlag()
+
+ def OnStandingsModified(self):
+ for obj in self.objectCache.values():
+ obj.clearFlag()
+
+ def OnSessionChanged(self, isRemote, session, change):
+ self.flushCache()
+
def populateBalls(self):
ballpark = eve.LocalSvc("michelle").GetBallpark()
if not ballpark:
return
- ids = list(ballpark.balls.keys())
-
lst = []
- for ballID in ids:
+ for ballID, ball in ballpark.balls.iteritems():
slimItem = ballpark.GetInvItem(ballID)
if slimItem:
- lst.append((ballpark.GetBall(ballID), slimItem))
+ lst.append((ball, slimItem))
self._DoBallsAdded(lst)
@@ -44,19 +152,45 @@ def DoBallsAdded(self, lst, **kwargs):
)
def _DoBallsAdded(self, lst):
+ ballpark = eve.LocalSvc("michelle").GetBallpark()
+ if not ballpark:
+ return
+
for (ball, slimItem) in lst:
if slimItem.groupID == const.groupForceField:
self.forceFields.append(slimItem.itemID)
def DoBallRemove(self, ball, slimItem, *args, **kwargs):
if slimItem and (slimItem.itemID in self.forceFields):
self.forceFields.remove(slimItem.itemID)
+
+ if slimItem:
+ ce = self.objectCache.get(slimItem.itemID, None)
+ if ce:
+ ce.removedFromBallpark()
def DoBallClear(self, solItem, **kwargs):
self.forceFields = []
+ for ce in self.objectCache.values():
+ ce.removedFromBallpark()
+
serviceInstance = forceStart("statemonitor", StateMonitorSvc)
+def getCachedItem(id=None, ball=None, slimItem=None):
+ if (not id):
+ if slimItem:
+ id = slimItem.itemID
+ else:
+ raise Exception("Must specify an id or a slimItem")
+
+ if not serviceInstance:
+ result = ItemDataCache(id, ball, slimItem)
+ else:
+ result = serviceInstance.get(id, ball, slimItem)
+
+ return result
+
def isItemInsideForceField(itemID):
from shootblues.common import log
View
19 Common/common.py
@@ -2,6 +2,8 @@
import types
import threading
import json
+import traceback
+import sys
_channels = {}
_pendingMessages = {}
@@ -59,6 +61,23 @@ def getFrameModule(i):
return None
+def showException(etype=None, value=None, tb=None):
+ if (not etype) or (not value) or (not tb):
+ exc_info = sys.exc_info()
+ if not etype:
+ etype = exc_info[0]
+ if not value:
+ value = exc_info[1]
+ if not tb:
+ tb = exc_info[2]
+
+ remoteCall(
+ "Common.Script.dll", "ShowError",
+ "".join(traceback.format_exception(
+ etype, value, tb
+ ))
+ )
+
def remoteCall(script, methodName, *args):
channel = getChannel("remotecall")
channel.send(json.dumps([script, methodName, args]))
View
25 DroneHelper/dronehelper.py
@@ -86,7 +86,7 @@ def checkUpdateTimer(self, droneID = None):
droneCount = len(drones)
if (droneCount > 0) and (self.__updateTimer == None):
- self.__updateTimer = SafeTimer(500, self.updateDrones)
+ self.__updateTimer = SafeTimer(1000, self.updateDrones)
elif (droneCount <= 0) and (self.__updateTimer != None):
self.__updateTimer = None
self.__lastAttackOrder = None
@@ -162,8 +162,8 @@ def getTargetSorter(self):
def targetSorter(lhs, rhs):
# Highest priority first
- priLhs = gp(targetID=lhs)
- priRhs = gp(targetID=rhs)
+ priLhs = gp(lhs)
+ priRhs = gp(rhs)
result = cmp(priRhs, priLhs)
if result == 0:
@@ -202,10 +202,10 @@ def filterTargets(self, ids):
if not (id in targetSvc.targets):
continue
- if getFlagName(invItem) != "HostileNPC":
+ if getFlagName(id) != "HostileNPC":
continue
- if getPriority(targetID=id) < 0:
+ if getPriority(id) < 0:
continue
if ballpark.DistanceBetween(eve.session.shipid, id) > controlRange:
@@ -230,7 +230,7 @@ def doAttack(self, idleOnly, targetID=None, dronesToAttack=[], oldTarget=None):
return
ballpark = eve.LocalSvc("michelle").GetBallpark()
- timestamp = blue.os.GetTime()
+ timestamp = blue.os.GetTime(1)
isCommonTarget = False
if not targetID:
targetID = self.getCommonTarget()
@@ -300,7 +300,7 @@ def doRecall(self, *dronesToRecall):
return
dronesToRecall = list(dronesToRecall)
- timestamp = blue.os.GetTime()
+ timestamp = blue.os.GetTime(1)
for droneID in list(dronesToRecall):
droneObj = self.getDroneObject(droneID)
@@ -310,7 +310,6 @@ def doRecall(self, *dronesToRecall):
(droneObj.state == const.entityFleeing) or
abs(droneObj.actionTimestamp - timestamp) <= ActionThreshold):
dronesToRecall.remove(droneID)
- log("drone state=%r, not recalling", droneObj.state)
if len(dronesToRecall):
entity = moniker.GetEntityAccess()
@@ -340,7 +339,7 @@ def updateDrones(self):
if not ballpark.GetBall(self.__lastAttackOrder):
self.__lastAttackOrder = None
- timestamp = blue.os.GetTime()
+ timestamp = blue.os.GetTime(1)
droneIDs = self.getDronesInLocalSpace()
dronesToRecall = []
dronesToAttack = []
@@ -389,9 +388,9 @@ def updateDrones(self):
if commonTarget == eve.session.shipid:
return
- oldPriority = getPriority(targetID=commonTarget)
+ oldPriority = getPriority(commonTarget)
newTarget = self.selectTarget()
- newPriority = getPriority(targetID=newTarget)
+ newPriority = getPriority(newTarget)
if commonTarget and (newPriority > oldPriority):
if ((commonTarget == self.__lastAttackOrder) or
@@ -418,7 +417,7 @@ def getDroneObject(self, droneID):
def OnDroneStateChange2(self, droneID, oldActivityState, newActivityState, timestamp=None):
if not timestamp:
- timestamp = blue.os.GetTime()
+ timestamp = blue.os.GetTime(1)
dronesInLocal = self.getDronesInLocalSpace()
if droneID not in dronesInLocal:
@@ -453,7 +452,7 @@ def OnDroneStateChange2(self, droneID, oldActivityState, newActivityState, times
self.checkUpdateTimer(droneID)
def OnDroneControlLost(self, droneID):
- timestamp = blue.os.GetTime()
+ timestamp = blue.os.GetTime(1)
drone = self.getDroneObject(droneID)
drone.setState(None, timestamp)
View
25 EnemyPrioritizer/enemyprioritizer.py
@@ -1,5 +1,5 @@
from shootblues.common import log
-from shootblues.common.eve import getFlagName
+from shootblues.common.eve.state import getCachedItem
import uix
import json
@@ -17,33 +17,28 @@ def adjustPriority(targetID, delta=1):
elif targetID in priorityBoosts:
del priorityBoosts[targetID]
-def getPriority(targetID=None, slimItem=None):
+def getPriority(id):
global priorities, priorityBoosts
- if targetID and not slimItem:
- ballpark = eve.LocalSvc('michelle').GetBallpark()
- if not ballpark:
- return 0
-
- slimItem = ballpark.GetInvItem(targetID)
+ ci = getCachedItem(id)
- if not slimItem:
+ if not ci.slimItem:
return -1
- targetID = slimItem.itemID
- charID = getattr(slimItem, "charID", None)
+ charID = getattr(ci.slimItem, "charID", None)
if charID:
priority = priorities.get("char:%d" % (charID,), 0)
else:
priority = 0
if priority == 0:
- priority = priorities.get("type:%d" % (slimItem.typeID,), 0)
+ priority = priorities.get("type:%d" % (ci.slimItem.typeID,), 0)
if priority == 0:
- priority = priorities.get("group:%d" % (slimItem.groupID,), 0)
+ priority = priorities.get("group:%d" % (ci.slimItem.groupID,), 0)
if priority == 0:
- flag = getFlagName(slimItem)
+ flag = ci.flag
+
if ((flag == "StandingGood") or
(flag == "StandingHigh") or
(flag == "SameGang") or
@@ -52,6 +47,6 @@ def getPriority(targetID=None, slimItem=None):
(flag == "SameCorp")):
priority = -1
- priority += priorityBoosts.get(targetID, 0)
+ priority += priorityBoosts.get(id, 0)
return priority
View
16 WeaponHelper/weaponhelper.py
@@ -51,10 +51,12 @@ def __init__(self):
self.__lastAttackOrder = None
def getTargetSorter(self, module):
- now = blue.os.GetTime()
+ now = blue.os.GetTime(1)
godma = eve.LocalSvc("godma")
ballpark = eve.LocalSvc("michelle").GetBallpark()
+ gp = Memoized(getPriority)
+
moduleAttrs = getModuleAttributes(module)
if getattr(module, "charge", None):
chargeObj = godma.GetItem(module.charge.itemID)
@@ -156,8 +158,8 @@ def _chanceToHitGetter(targetID):
if chanceToHitGetter:
def targetSorter(lhs, rhs):
# Highest priority first
- priLhs = getPriority(targetID=lhs)
- priRhs = getPriority(targetID=rhs)
+ priLhs = gp(lhs)
+ priRhs = gp(rhs)
result = cmp(priRhs, priLhs)
if result == 0:
@@ -176,8 +178,8 @@ def targetSorter(lhs, rhs):
log("Warning: Weapon without chance-to-hit attributes.")
def targetSorter(lhs, rhs):
# Highest priority first
- priLhs = getPriority(targetID=lhs)
- priRhs = getPriority(targetID=rhs)
+ priLhs = getPriority(lhs)
+ priRhs = getPriority(rhs)
result = cmp(priRhs, priLhs)
return targetSorter
@@ -191,10 +193,10 @@ def filterTargets(self, ids):
if not invItem:
continue
- if getFlagName(invItem) != "HostileNPC":
+ if getFlagName(id) != "HostileNPC":
continue
- if getPriority(targetID=id) < 0:
+ if getPriority(id) < 0:
continue
result.append(id)

0 comments on commit 00ffec1

Please sign in to comment.