Пример #1
0
    def pickUpItem(self, app, newItem: Stack):
        """Adds an item to the player's inventory."""

        if newItem.isEmpty(): return

        # Prioritize existing stacks of the item first
        for (i, slot) in enumerate(self.inventory):
            stack = slot.stack
            if stack.isInfinite() and stack.item == newItem.item:
                # It just stacks into an infinite slot, so no change
                return
            elif newItem.isInfinite() and stack.item == newItem.item:
                # ditto
                return
            elif stack.amount > 0 and stack.item == newItem.item:
                self.inventory[i].stack.amount += newItem.amount
                return

        # If that fails, then just add the item to the next open space
        for (i, slot) in enumerate(self.inventory):
            if slot.isEmpty():
                self.inventory[i].stack = newItem
                return

        # TODO: Full inventory??
        1 / 0
Пример #2
0
def craftingGuiPostClick(slots: List[Slot], is3x3: bool, app, slotIdx,
                         prevOutput: Stack):
    if is3x3:
        totalCraftSlots = 9 + 1
    else:
        totalCraftSlots = 4 + 1

    if slotIdx == 0 and prevOutput != slots[0].stack:
        # Something was crafted
        for slot in slots[1:totalCraftSlots]:
            if slot.stack.amount > 0:
                slot.stack.amount -= 1

    def toid(s):
        return None if s.isEmpty() else s.item

    rowLen = round(math.sqrt(totalCraftSlots - 1))

    c = []

    for rowIdx in range(rowLen):
        row = []
        for colIdx in range(rowLen):
            row.append(toid(slots[1 + rowIdx * rowLen + colIdx].stack))
        c.append(row)

    slots[0].stack = Stack('', 0)

    for r in app.recipes:
        if r.isCraftedBy(c):
            slots[0].stack = copy.copy(r.outputs)
            break
Пример #3
0
class ItemData:
    stack: Stack
    age: int
    pickupDelay: int

    def __init__(self):
        self.stack = Stack('stone', 1)
        self.age = 6000
        # TODO: should increase if dropped by player or fox
        self.pickupDelay = 10

    def tick(self, entity: 'Entity'):
        self.age -= 1
        if self.age == 0:
            entity.health = 0

        if self.pickupDelay > 0:
            self.pickupDelay -= 1

    def toNbt(self) -> nbt.TAG_Compound:
        tag = nbt.TAG_Compound()
        tag.tags.append(nbt.TAG_Short(self.age, 'Age'))
        tag.tags.append(nbt.TAG_Short(self.pickupDelay, 'PickupDelay'))

        item = self.stack.toNbt()
        assert (item is not None)
        item.name = 'Item'
        tag.tags.append(item)

        return tag

    def fromNbt(self, tag: nbt.TAG_Compound):
        self.age = tag['Age'].value
        self.pickupDelay = tag['PickupDelay'].value
        self.stack = Stack.fromNbt(tag['Item'])
Пример #4
0
    def __init__(self,
                 app,
                 creative: bool = False,
                 tag: Optional[nbt.TAG_Compound] = None):
        self.dimension = 'minecraft:overworld'

        # FIXME: ID
        super().__init__(app, 1, 'player', 0.0, 0.0, 0.0, nbt=tag)

        self.reach = 4.0

        self.creative = creative
        self.flying = False

        self.portalCooldown = 80

        if self.creative:
            if len(app.itemTextures) > 36:
                # TODO:
                1 / 0

            self.inventory = [
                Slot(stack=Stack(name, -1)) for name in app.itemTextures
            ]

            while len(self.inventory) < 36:
                self.inventory.append(Slot(stack=Stack('', 0)))
        else:
            self.inventory = [Slot() for _ in range(36)]

        if tag is not None:
            for stackTag in tag["Inventory"]:
                (stack, slotIdx) = Stack.fromNbt(stackTag, getSlot=True)
                self.inventory[slotIdx].stack = stack

            gameMode = tag['playerGameType'].value
            if gameMode == 0:
                self.creative = False
            elif gameMode == 1:
                self.creative = True
            else:
                raise Exception(f'Invalid game mode {gameMode}')

            self.flying = tag['abilities']['flying'].value != 0

            self.dimension = tag['dimension'].value
Пример #5
0
def drawStack(client: ClientState, canvas, x, y, stack: Stack):
    #slotWidth = CLIENT_DATA.itemTextures['air'].width + 6

    slotWidth = getSlotCenterAndSize(client, 0)[2]

    if not stack.isEmpty():
        tex = CLIENT_DATA.itemTextures[stack.item]
        image = tex
        canvas.create_image(x, y, image=image)

        # Slots that are infinite or with a single item just don't have a number displayed
        if not stack.isInfinite() and stack.amount != 1:
            cornerX = x + 0.3 * slotWidth
            cornerY = y + 0.2 * slotWidth

            qty = stack.amount

            drawTextOutlined(canvas, cornerX, cornerY, text=str(qty), font='Arial 12 bold')
Пример #6
0
def getSlotsInWindow(server: ServerState,
                     windowId: int) -> Tuple[Stack, List[Slot]]:
    if windowId == 0:
        player = server.getLocalPlayer()

        if player.entityId not in server.craftSlots:
            server.craftSlots[player.entityId] = [Slot(
                canInput=False)] + [Slot() for _ in range(4)]

        # TODO: Armor slots
        baseSlots = server.craftSlots[player.entityId] + [
            Slot() for _ in range(4)
        ]
    else:
        window = server.openWindows[windowId]

        player = None
        for p in server.players:
            if p.entityId == window.playerId:
                player = p
                break

        if player is None:
            raise Exception(
                f'Window click from nonexistent player {window.playerId}')

        if window.kind == 'furnace':
            (chunk,
             localPos) = server.getLocalDimension().world.getChunk(window.pos)
            furnace: world.Furnace = chunk.tileEntities[localPos]

            baseSlots = [
                furnace.inputSlot, furnace.fuelSlot, furnace.outputSlot
            ]
        elif window.kind == 'crafting':
            if player.entityId not in server.craftSlots:
                server.craftSlots[player.entityId] = [Slot(
                    canInput=False)] + [Slot() for _ in range(9)]

            baseSlots = server.craftSlots[player.entityId]
        else:
            raise Exception(f'Unknown window kind {window.kind}')

    slots = baseSlots + player.inventory[9:36] + player.inventory[0:9]

    if player.entityId not in server.heldItems:
        server.heldItems[player.entityId] = Stack('', 0)

    return (server.heldItems[player.entityId], slots)
Пример #7
0
def updateBlockBreaking(app, server: ServerState):
    pos = server.breakingBlockPos

    if server.breakingBlock == 0.0:
        return

    wld = server.getLocalDimension().world

    blockId = wld.getBlock(pos)
    blockState = wld.getBlockState(pos)

    if blockId == 'air':
        print(f'Invalid mining at {server.breakingBlockPos}')
        return

    # HACK:
    player = server.getLocalPlayer()

    toolStack = player.inventory[player.hotbarIdx].stack
    if toolStack.isEmpty():
        tool = ''
    else:
        tool = toolStack.item

    hardness = resources.getHardnessAgainst(blockId, tool)

    # TODO: Sound effect packets

    if server.breakingBlock >= hardness:
        if blockId == 'oak_log':
            blockState['axis'] = 'y'
        mcBlockId = util.REGISTRY.encode_block(
            {'name': 'minecraft:' + blockId} | blockState)

        network.s2cQueue.put(
            network.AckPlayerDiggingS2C(pos, mcBlockId,
                                        network.DiggingAction.FINISH_DIGGING,
                                        True))

        droppedItem = resources.getBlockDrop(app, blockId, tool)

        resources.getDigSound(app, blockId).play()

        wld.setBlock((app.textures, app.cube, app.textureIndices), pos, 'air')

        server.breakingBlock = 0.0

        if droppedItem is not None:
            stack = Stack(droppedItem, 1)

            entityId = server.getEntityId()

            xVel = ((random.random() - 0.5) * 0.1)
            yVel = ((random.random() - 0.5) * 0.1)
            zVel = ((random.random() - 0.5) * 0.1)

            # TODO: UUID
            network.s2cQueue.put(
                network.SpawnEntityS2C(entityId, None, 37, float(pos.x),
                                       float(pos.y), float(pos.z), 0.0, 0.0, 1,
                                       int(xVel * 8000), int(yVel * 8000),
                                       int(zVel * 8000)))

            itemId = util.REGISTRY.encode('minecraft:item',
                                          'minecraft:' + stack.item)

            network.s2cQueue.put(
                network.EntityMetadataS2C(
                    entityId,
                    {(6, 7): {
                         'item': itemId,
                         'count': stack.amount
                     }}))

            ent = Entity(app, entityId, 'item', float(pos.x), float(pos.y),
                         float(pos.z))
            ent.extra.stack = stack
            ent.velocity = [xVel, yVel, zVel]

            server.getLocalDimension().entities.append(ent)
Пример #8
0
def sendChatMessage(app, text: str):
    if hasattr(app, 'server'):
        if text.startswith('/'):
            text = text.removeprefix('/')

            parts = text.split()

            server: ServerState = app.server

            dim = server.getLocalDimension()
            wld, entities = dim.world, dim.entities

            print(f"COMMAND {text}")

            if parts[0] == 'pathfind':
                player: Player = server.getLocalPlayer()
                target = player.getBlockPos()
                for ent in entities:
                    ent.updatePath(wld, target)
            elif parts[0] == 'give':
                itemId = parts[1]
                if len(parts) == 3:
                    amount = int(parts[2])
                else:
                    amount = 1
                server.getLocalPlayer().pickUpItem(app, Stack(itemId, amount))
            elif parts[0] == 'time':
                if parts[1] == 'set':
                    if parts[2] == 'day':
                        server.time = 1000
                    elif parts[2] == 'night':
                        server.time = 13000
                    elif parts[2] == 'midnight':
                        server.time = 18000
                    else:
                        server.time = int(parts[2])
                elif parts[1] == 'add':
                    server.time += int(parts[2])
            elif parts[0] == 'gamemode':
                if parts[1] == 'creative':
                    server.getLocalPlayer().creative = True
                elif parts[1] == 'survival':
                    server.getLocalPlayer().creative = False
            elif parts[0] == 'summon':
                player = server.getLocalPlayer()
                ent = Entity(app, server.getEntityId(), parts[1],
                             player.pos[0] + 0.5, player.pos[1] + 0.5,
                             player.pos[2] + 0.5)
                app.entities.append(ent)
            elif parts[0] == 'explode':
                power = int(parts[1])

                player = server.getLocalPlayer()

                pos = world.nearestBlockPos(player.pos[0], player.pos[1],
                                            player.pos[2])

                wld.explodeAt(pos, power,
                              (app.textures, app.cube, app.textureIndices))
            elif parts[0] == 'dimension':
                player = server.getLocalPlayer()

                if player.dimension == 'minecraft:overworld':
                    player.dimension = 'minecraft:the_nether'
                elif player.dimension == 'minecraft:the_nether':
                    player.dimension = 'minecraft:overworld'
                else:
                    raise Exception(player.dimension)

                import quarry.types.nbt as quarrynbt

                player.portalCooldown = 80

                # TODO:
                network.s2cQueue.put(
                    network.RespawnS2C(quarrynbt.TagCompound({}),
                                       player.dimension, 0, 0, None, False,
                                       False, True))
            elif parts[0] == 'chunkstates':
                for dim in server.dimensions:
                    print(f'== DIMENSION {dim} ==')
                    for pos, chunk in dim.world.chunks.items():
                        print(f'{pos} - {chunk.worldgenStage}')
            elif parts[0] == 'killall':
                toRemove = []
                idx = 0
                dim = server.getLocalDimension()
                while idx < len(dim.entities):
                    if dim.entities[idx].kind.name != 'player':
                        toRemove.append(dim.entities[idx].entityId)
                        dim.entities.pop(idx)
                    else:
                        idx += 1

                network.s2cQueue.put(network.DestroyEntitiesS2C(toRemove))
            elif parts[0] == 'tp':
                # TODO:
                '''
                player = server.getLocalPlayer()
                player.pos[0] = float(parts[1])
                player.pos[1] = float(parts[2])
                player.pos[2] = float(parts[3])
                '''
    else:
        network.c2sQueue.put(network.ChatMessageC2S(text))
Пример #9
0
 def fromNbt(self, tag: nbt.TAG_Compound):
     self.age = tag['Age'].value
     self.pickupDelay = tag['PickupDelay'].value
     self.stack = Stack.fromNbt(tag['Item'])
Пример #10
0
 def __init__(self):
     self.stack = Stack('stone', 1)
     self.age = 6000
     # TODO: should increase if dropped by player or fox
     self.pickupDelay = 10