Files
caminus/api/events.py

173 lines
5.7 KiB
Python

from django.conf import settings
from django.core.cache import cache
import time
from minecraft.models import Server
from json import loads, dumps, JSONEncoder
import beanstalkc
from django.contrib.auth.models import User
class EventEncoder(JSONEncoder):
def default(self, obj):
if isinstance(obj, Event):
return {'type': obj.type, 'payload': obj.data}
return super(EventEncoder, self).default(obj)
class Event(object):
def __init__(self, type, data):
self.type = type
self.data = data
def __repr__(self):
return json.dumps(self, cls=EventEncoder)
class ChatEvent(Event):
def __init__(self, sender, message):
super(ChatEvent, self).__init__(type='chat', data={'sender': sender,
'message': message})
class VaultContentsEvent(Event):
def __init__(self, player, items):
super(VaultContentsEvent, self).__init__(type='vault-contents',
data={'player': player, 'items': items})
class QuitEvent(Event):
def __init__(self, player):
super(QuitEvent, self).__init__(type='quit', data={'player': player})
class JoinEvent(Event):
def __init__(self, player):
super(JoinEvent, self).__init__(type='join', data={'player': player})
class BroadcastEvent(Event):
def __init__(self, message):
super(BroadcastEvent, self).__init__(type='broadcast', data={'message':
message})
class PlayerDeathEvent(Event):
def __init__(self, player, message):
super(PlayerDeathEvent, self).__init__(type='player-death',
data={'player': player, 'message': message})
class ServerHeartbeatEvent(Event):
def __init__(self, server, data):
now = server.current_time()
t = now.second+now.minute*60+now.hour*60*60
super(ServerHeartbeatEvent, self).__init__(type='server-heartbeat',
data={'server': server.id, 'heartbeat': data, 'time': t,
'day-period': server.day_period()})
class KickEvent(Event):
def __init__(self, user, message):
super(KickEvent, self).__init__(type='player-kick',
data={'player': user, 'message': message})
class PlayerMessageEvent(Event):
def __init__(self, user, message):
super(PlayerMessageEvent, self).__init__(type='player-message',
data={'message': message, 'player': user})
class MarketOrderEvent(Event):
def __init__(self, orderID):
super(MarketOrderEvent, self).__init__(type='market-order',
data={'orderID': orderID})
def server_queue(server, users=[]):
queueName = 'caminus-broadcast-%s'%server.id
queue = beanstalkc.Connection(host=settings.CAMINUS_BEANSTALKD_HOST,
port=settings.CAMINUS_BEANSTALKD_PORT)
queue.use(queueName)
queue.watch(queueName)
if len(users) > 0:
for user in users:
queue.watch("caminus-user-%s"%user)
return queue
def send_server_event(server, event):
if settings.CAMINUS_USE_BEANSTALKD:
queue = server_queue(server)
json = dumps(event, cls=EventEncoder)
queue.put(json)
def broadcast_server_event(event):
for server in Server.objects.all():
send_server_event(server, event)
def server_broadcast(message, *args):
message = message%args
for server in Server.objects.all():
event = BroadcastEvent(message)
send_server_event(server, event)
send_web_event(event)
def user_message(user, message, *args):
player = user.minecraftprofile.mc_username
player_message(player, message, *args)
def player_message(playername, message, *args):
message = message%args
for server in Server.objects.all():
event = PlayerMessageEvent(playername, message)
send_server_event(server, event)
def web_queue(id):
queueName = 'caminus-web-%s'%id
queue = beanstalkc.Connection(host=settings.CAMINUS_BEANSTALKD_HOST,
port = settings.CAMINUS_BEANSTALKD_PORT)
queue.use(queueName)
queue.watch(queueName)
activeCache = cache.get('minecraft-web-queues')
if activeCache is None:
activeCache = {}
activeCache[id] = time.time()
for queueName,stamp in activeCache.iteritems():
if time.time()-stamp > 120:
del activeCache[queueName]
cache.set('minecraft-web-queues', activeCache, 3600)
return queue
def market_queue():
queueName = 'caminus-market'
queue = beanstalkc.Connection(host=settings.CAMINUS_BEANSTALKD_HOST,
port = settings.CAMINUS_BEANSTALKD_PORT)
queue.use(queueName)
queue.watch(queueName)
return queue
def queue_market_event(event):
queue = market_queue()
json = dumps({'stamp': time.time(), 'event': event}, cls=EventEncoder)
queue.put(json)
def send_web_event(event):
latest = cache.get('minecraft-web-events')
if latest is None:
latest = []
latest.append(dumps(event, cls=EventEncoder))
while len(latest) > 10:
latest.pop(0)
cache.set('minecraft-web-events', latest, 86400);
if settings.CAMINUS_USE_BEANSTALKD:
queue = beanstalkc.Connection(host=settings.CAMINUS_BEANSTALKD_HOST,
port = settings.CAMINUS_BEANSTALKD_PORT)
json = dumps({'stamp': time.time(), 'event':event}, cls=EventEncoder)
activeQueues = cache.get('minecraft-web-queues')
print "Active queues", repr(activeQueues)
if activeQueues is None:
activeQueues = {}
for tube in activeQueues.iterkeys():
queue.use('caminus-web-%s'%(tube))
print "Web queue", tube
pendingJob = queue.peek_ready()
while pendingJob:
pending = loads(pendingJob.body)
if time.time()-pending['stamp'] > 30:
pendingJob.delete()
pendingJob = queue.peek_ready()
else:
pendingJob = None
queue.put(json)
def chat(playername, message):
evt = ChatEvent(playername, message)
send_web_event(evt)