203 lines
8.1 KiB
Python
203 lines
8.1 KiB
Python
from piston.handler import AnonymousBaseHandler, BaseHandler
|
|
import time
|
|
from django.core.cache import cache
|
|
from django.conf import settings
|
|
import appversion
|
|
from minecraft.models import MinecraftProfile
|
|
from local.models import Quote
|
|
from minecraft.models import MOTD, Server, PlayerSession
|
|
from django.db.models import F
|
|
from django.http import HttpResponse
|
|
from urllib2 import urlopen
|
|
import json
|
|
from datetime import datetime
|
|
from models import cachePlayerList
|
|
from events import server_queue, web_queue, chat, server_broadcast, send_web_event, QuitEvent, JoinEvent, PlayerDeathEvent, ServerHeartbeatEvent
|
|
from bounty.models import Bounty
|
|
from vault.models import VaultSlot
|
|
|
|
class MOTDHandler(AnonymousBaseHandler):
|
|
allowed_methods = ('GET',)
|
|
|
|
def read(self, request, username):
|
|
motd = "No MOTD configured!"
|
|
motdList = MOTD.objects.all()
|
|
if len(motdList) > 0:
|
|
motd = motdList[0].text
|
|
quote = Quote.objects.order_by('?')
|
|
if len(quote) > 0:
|
|
motd += "\n"+'"'+quote[0].text+'"'
|
|
return {"motd":motd.split('\n')}
|
|
|
|
class NewPlayerSessionHandler(BaseHandler):
|
|
allowed_methods = ('POST',)
|
|
|
|
def create(self, request, playername):
|
|
try:
|
|
profile = MinecraftProfile.objects.all().filter(mc_username__iexact=playername)[0]
|
|
except IndexError, e:
|
|
return {'success': False, 'error': 'User not found', 'permissions': []}
|
|
if profile.user.is_active:
|
|
if profile.isBanned():
|
|
return {'success': False, 'error': 'Your account is banned.', 'permissions': []}
|
|
ip = request.POST['ip']
|
|
server = request.server
|
|
profile = MinecraftProfile.objects.get(mc_username__exact=playername)
|
|
session = PlayerSession.objects.create(server=server, player=profile, ip=ip)
|
|
send_web_event(JoinEvent(playername))
|
|
return {'success': True, 'error': '', 'permissions': profile.serverPermissions(), 'sessionId': session.id}
|
|
else:
|
|
return {'success': False, 'error': 'Your account is inactive.', 'permissions': []}
|
|
|
|
class ClosePlayerSessionHandler(BaseHandler):
|
|
allowed_methods = ('GET',)
|
|
|
|
def read(self, request, playername):
|
|
sessions = PlayerSession.objects.all().filter(player__mc_username__iexact=playername, end=None)
|
|
for session in sessions:
|
|
session.end = datetime.now()
|
|
session.save()
|
|
send_web_event(QuitEvent(playername))
|
|
return {'valid': True}
|
|
|
|
class EconomyHandler(BaseHandler):
|
|
allowed_methods = ('PUT','GET')
|
|
|
|
def read(self, request, playername):
|
|
player = MinecraftProfile.objects.get(mc_username__exact=playername)
|
|
return {'balance': player.currencyaccount.balance}
|
|
|
|
def update(self, request, playername):
|
|
player = MinecraftProfile.objects.get(mc_username__exact=playername)
|
|
delta = request.POST['delta']
|
|
newBalance = player.currencyaccount.balance+float(delta)
|
|
if newBalance >= 0:
|
|
player.currencyaccount.balance = F('balance')+float(delta)
|
|
player.currencyaccount.save()
|
|
return {'success': True, 'balance': newBalance, 'message': ""}
|
|
else:
|
|
return {'success': False, 'balance': player.currencyaccount.balance, 'message': "Insufficient balance"}
|
|
|
|
class ServerPingHandler(BaseHandler):
|
|
allowed_methods = ('GET',)
|
|
|
|
def read(self, request):
|
|
return {'identity': request.server, 'api-version': 2, 'server-version': appversion.version()}
|
|
|
|
class ServerEventHandler(BaseHandler):
|
|
allowed_methods = ('GET', 'POST', 'PUT')
|
|
|
|
def read(self, request):
|
|
queue = server_queue(request.server)
|
|
queue.watch('caminus-broadcast-%s'%request.server.id)
|
|
events = []
|
|
job = queue.reserve(timeout=30)
|
|
while job:
|
|
job.bury()
|
|
events.append({'id': job.jid, 'event': json.loads(job.body)})
|
|
job = queue.reserve(timeout=0)
|
|
return {'events': events}
|
|
|
|
def create(self, request):
|
|
queue = server_queue(request.server)
|
|
try:
|
|
queue.delete(int(request.POST['job']))
|
|
except Exception, e:
|
|
pass
|
|
return {'result': 'success'}
|
|
|
|
def update(self, request):
|
|
events = json.loads(request.POST['events'])['events']
|
|
for evt in events:
|
|
print repr(evt)
|
|
if evt['type'] == 'chat':
|
|
chat(evt['payload']['sender'], evt['payload']['message'])
|
|
if evt['type'] == 'player-death':
|
|
send_web_event(PlayerDeathEvent(evt['payload']['player'],
|
|
evt['payload']['message']))
|
|
if evt['type'] == 'heartbeat':
|
|
cache.set('caminus-server-heartbeat-%s'%(request.server.id), evt['payload'], 86400)
|
|
send_web_event(ServerHeartbeatEvent(request.server, evt['payload']))
|
|
if evt['type'] == 'player-murder':
|
|
bounties = Bounty.objects.filter(target__mc_username=evt['payload']['player'])
|
|
killer = MinecraftProfile.objects.get(mc_username=evt['payload']['killer'])
|
|
for bounty in bounties:
|
|
bounty.close(killer)
|
|
if len(bounties) > 0:
|
|
server_broadcast("The bounty on %s has been collected."%(evt['payload']['player']))
|
|
return {'result': 'success'}
|
|
|
|
class ChatHandler(BaseHandler):
|
|
allowed_methods = ('POST',)
|
|
|
|
def create(self, request):
|
|
chat(request.user.minecraftprofile.mc_username, request.POST['message'])
|
|
server_broadcast("<%s> %s"%(request.user.minecraftprofile.mc_username,
|
|
request.POST['message']))
|
|
|
|
class PollHandler(BaseHandler):
|
|
allowed_methods = ('GET',)
|
|
|
|
def read(self, request, timestamp):
|
|
serverInfo = cache.get('caminus-server-info')
|
|
if serverInfo == None:
|
|
cachePlayerList()
|
|
pollData = {'server-info': {}, 'user-info': {}}
|
|
pollData['server-info'] = cache.get('caminus-server-info')
|
|
if not request.user.is_anonymous():
|
|
pollData['user-info']['balance'] = request.user.minecraftprofile.currencyaccount.balance
|
|
pollData['events'] = []
|
|
pollData['poll-id'] = timestamp
|
|
if timestamp == "0" and settings.CAMINUS_USE_BEANSTALKD:
|
|
pollData['poll-id'] = time.time()
|
|
latestEvents = cache.get('minecraft-web-events')
|
|
if not latestEvents:
|
|
latestEvents = []
|
|
for e in latestEvents:
|
|
pollData['events'].append(json.loads(e))
|
|
else:
|
|
eventQueue = web_queue(timestamp)
|
|
event = eventQueue.reserve(timeout=30)
|
|
if event:
|
|
eventData = json.loads(event.body)
|
|
pollData['events'].append(eventData['event'])
|
|
event.delete()
|
|
return pollData
|
|
|
|
class VaultHandler(BaseHandler):
|
|
allowed_methods = ('PUT','GET')
|
|
|
|
def read(self, request, playername):
|
|
player = MinecraftProfile.objects.get(mc_username__exact=playername)
|
|
items = []
|
|
for slot in player.vault_slots.all():
|
|
items.append({'item': slot.item, 'quantity':
|
|
slot.quantity, 'damage': slot.damage, 'data': slot.data,
|
|
'position': slot.position})
|
|
return {'items': items}
|
|
|
|
def update(self, request, playername):
|
|
player = MinecraftProfile.objects.get(mc_username__exact=playername)
|
|
vaultContents = json.loads(request.POST['contents'])['items']
|
|
stacks = player.vault_slots.all()
|
|
for stack in vaultContents:
|
|
updated = False
|
|
slot,created = VaultSlot.objects.get_or_create(player=player,
|
|
position=stack['position'])
|
|
if slot.item != stack['item']:
|
|
slot.item = stack['item']
|
|
updated = True
|
|
if slot.quantity != stack['quantity']:
|
|
slot.quantity = stack['quantity']
|
|
updated = True
|
|
if slot.damage != stack['damage']:
|
|
slot.damage = stack['damage']
|
|
updated = True
|
|
if slot.data != stack['data']:
|
|
slot.data = stack['data']
|
|
updated = True
|
|
if updated:
|
|
print "Saving slot %s(%s): %s"%(slot.position, slot.id, slot.item)
|
|
slot.save()
|
|
return {'success': True}
|