from django.db import models from minecraft.models import MinecraftProfile from django.db.models.signals import post_save, post_delete from api.events import VaultContentsEvent, broadcast_server_event from minecraft.models import Item from django.conf import settings class VaultError(Exception): pass class VaultSlot(models.Model): player = models.ForeignKey(MinecraftProfile, related_name='vault_slots') quantity = models.IntegerField(default=-1) position = models.IntegerField() item = models.ForeignKey(Item, null=True, blank=True) class Meta: ordering = ['position'] def __unicode__(self): return "%s.%s: %s %s"%(self.player, self.position, self.quantity, self.item) @classmethod def getEmptySlots(cls, player): return cls.objects.filter(player=player, item=None) @classmethod def addToInventory(cls, player, item, quantity): neededQuantity = quantity stackTotal = item.metadata['stack'] slots = cls.findAvailableSlots(player, item, quantity) for s in slots: assert(neededQuantity >= 0) if neededQuantity == 0: break if s.item is None: s.item = item s.quantity = 0 availableCapacity = min(stackTotal-s.quantity, neededQuantity) s.quantity = min(stackTotal, neededQuantity) neededQuantity -= availableCapacity print "Used", availableCapacity, "in", s, "need", neededQuantity s.save() assert(neededQuantity == 0) @classmethod def findAvailableSlots(cls, player, item, quantity): stackTotal = item.metadata['stack'] neededQuantity = quantity slots = [] for slot in cls.objects.filter(player=player, item=item, quantity__lt=stackTotal): neededQuantity -= stackTotal-slot.quantity slots.append(slot) for slot in cls.objects.filter(player=player, item=None): neededQuantity -= stackTotal slots.append(slot) if neededQuantity > 0: raise VaultError, "Insufficient available slots." return slots def send_vault_delete(sender, instance, *args, **kwargs): slots = [ { 'item': None, 'quantity': -1, 'damage': None, 'data': None, 'position': instance.position } ] broadcast_server_event(VaultContentsEvent(instance.player.mc_username, slots)) def send_vault_update(sender, instance, created, *args, **kwargs): if created and instance.item: slots = [ { 'item': instance.item.material, 'quantity': instance.quantity, 'damage': instance.item.damage, 'data': instance.item.data, 'position': instance.position } ] broadcast_server_event(VaultContentsEvent(instance.player.mc_username, slots)) post_save.connect(send_vault_update, sender=VaultSlot, dispatch_uid='derp') post_delete.connect(send_vault_delete, sender=VaultSlot, dispatch_uid='derp') def create_initial_slots(sender, instance, created, *args, **kwargs): slots = instance.vault_slots.all() if len(slots) < settings.CAMINUS_VAULT_SLOTS: neededPositions = range(0, settings.CAMINUS_VAULT_SLOTS) for s in slots: neededPositions.remove(s.position) for pos in neededPositions: VaultSlot.objects.create(player=instance, position=pos) post_save.connect(create_initial_slots, sender=MinecraftProfile)