Beispiel #1
0
    def __getitem__(self, n):
        from quarry.types import nbt

        block = self.registry.decode_block(self.palette[n])
        entry = nbt.TagCompound({'Name': nbt.TagString(block['name'])})
        if len(block) > 1:
            entry.value['Properties'] = nbt.TagCompound({
                key: nbt.TagString(value)
                for key, value in block.items() if key != "name"
            })

        return entry
Beispiel #2
0
def serverTick(app, server: ServerState):
    startTime = time.time()

    server.time += 1

    instData = (app.textures, app.cube, app.textureIndices)

    for i, dim in enumerate(server.dimensions):
        player = server.getLocalPlayer()
        chunkPos, _ = world.toChunkLocal(player.getBlockPos())
        if i == 0 and player.dimension == 'minecraft:overworld':
            dim.world.addTicket(chunkPos, 1)
        elif i == 1 and player.dimension == 'minecraft:the_nether':
            dim.world.addTicket(chunkPos, 1)

        dim.world.loadUnloadChunks(
            (app.textures, app.cube, app.textureIndices))
        dim.world.addChunkDetails(instData)
        dim.world.tickChunks(app)

    updateBlockBreaking(app, server)

    for dim in server.dimensions:
        doMobSpawning(app, server, dim)
        doMobDespawning(app, server, dim)

    # Ticking is done in stages so that collision detection works as expected:
    # First we update the player's Y position and resolve Y collisions,
    # then we update the player's X position and resolve X collisions,
    # and finally update the player's Z position and resolve Z collisions.

    # TODO: USE MOVE PACKETS

    # W makes the player go forward, S makes them go backwards,
    # and pressing both makes them stop!
    z = float(app.client.w) - float(app.client.s)
    # Likewise for side to side movement
    x = float(app.client.d) - float(app.client.a)

    for player in server.players:
        playerChunkPos = world.toChunkLocal(player.getBlockPos())[0]
        playerChunkPos = ChunkPos(playerChunkPos.x, 0, playerChunkPos.z)

        dim = server.getDimensionOf(player)

        player.tick(app, dim.world, dim.entities, 0.0, 0.0)

        if dim.world.getBlock(player.getBlockPos()) == 'nether_portal':
            if player.portalCooldown == 0:
                import quarry.types.nbt as quarrynbt

                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)

                player.portalCooldown = 80

                destDim = server.getDimension(player.dimension)
                destDim.world.addTicket(
                    world.toChunkLocal(player.getBlockPos())[0], 300)
                destDim.world.loadUnloadChunks(instData)
                destDim.world.addChunkDetails(instData)

                dest = getDestination(app, destDim.world, player.getBlockPos(),
                                      destDim.world.dimTy.logicalHeight)

                # TODO:
                network.s2cQueue.put(
                    network.RespawnS2C(quarrynbt.TagCompound({}),
                                       player.dimension, 0, 0, None, False,
                                       False, True))

                network.s2cQueue.put(
                    network.PlayerPositionAndLookS2C(dest.x, dest.y + 1,
                                                     dest.z, 0.0, 0.0, False,
                                                     False, False, False,
                                                     False,
                                                     server.getTeleportId()))
            else:
                player.portalCooldown = 80
    '''
    collideY(app, player)
    if player.onGround:
        player.velocity[0] = x
        player.velocity[2] = z
    else:
        player.velocity[0] += x / 10.0
        player.velocity[2] += z / 10.0
    collideXZ(app, player)
    '''

    # FIXME: types???
    entities = server.getLocalDimension(
    ).entities + server.players  #type:ignore

    # FIXME:
    player = server.getLocalPlayer()

    for dim in server.dimensions:
        for entity in dim.entities:
            entChunkPos = world.toChunkLocal(entity.getBlockPos())[0]
            entChunkPos = ChunkPos(entChunkPos.x, 0, entChunkPos.z)

            if entChunkPos not in dim.world.chunks or not dim.world.chunks[
                    entChunkPos].isTicking:
                continue

            againstWall = collide(dim.world, entity)

            if againstWall and entity.onGround:
                entity.velocity[1] = 0.40

            entity.tick(app, dim.world, entities, player.pos[0], player.pos[2])

            if entity.kind.name == 'item':
                dx = (player.pos[0] - entity.pos[0])**2
                dy = (player.pos[1] - entity.pos[1])**2
                dz = (player.pos[2] - entity.pos[2])**2
                if math.sqrt(dx + dy +
                             dz) < 2.0 and entity.extra.pickupDelay == 0:
                    player.pickUpItem(app, entity.extra.stack)
                    entity.health = 0.0

            if entity.pos[1] < -64.0:
                entity.hit(app, 10.0, (0.0, 0.0))

    if player.pos[1] < -64.0:
        player.hit(app, 10.0, (0.0, 0.0))

    network.s2cQueue.put(network.TimeUpdateS2C(0, server.time))

    for dim in server.dimensions:
        # HACK:
        for ent1, ent2 in zip(dim.entities, app.client.entities):
            ent1.variables = copy.copy(ent2.variables)

    network.s2cQueue.put(
        network.UpdateHealthS2C(server.getLocalPlayer().health, 20, 5.0))

    for windowId, openWindow in server.openWindows.items():
        if windowId != 0 and openWindow.kind == 'furnace':
            chunk, localPos = server.getLocalDimension().world.getChunk(
                openWindow.pos)
            furnace = typing.cast(Furnace, chunk.tileEntities[localPos])
            network.s2cQueue.put(
                network.WindowPropertyS2C(windowId, 0, furnace.fuelLeft))
            network.s2cQueue.put(network.WindowPropertyS2C(windowId, 1, 1600))
            network.s2cQueue.put(
                network.WindowPropertyS2C(windowId, 2, furnace.progress))
            network.s2cQueue.put(network.WindowPropertyS2C(windowId, 3, 200))

            for slotIdx, slot in enumerate((
                    furnace.inputSlot,
                    furnace.fuelSlot,
                    furnace.outputSlot,
            )):
                # FIXME: EMPTY SLOTS??
                if slot.stack.isEmpty():
                    itemId = 'stone'
                else:
                    itemId = slot.stack.item

                itemId = util.REGISTRY.encode('minecraft:item',
                                              'minecraft:' + itemId)
                network.s2cQueue.put(
                    network.SetSlotS2C(windowId, slotIdx, itemId,
                                       slot.stack.amount))

    app.client.entities = copy.deepcopy(server.getLocalDimension().entities)
    app.client.player.inventory = copy.deepcopy(
        server.getLocalPlayer().inventory)
    app.client.player.creative = server.getLocalPlayer().creative

    endTime = time.time()
    server.tickTimes[server.tickTimeIdx] = (endTime - startTime)
    server.tickTimeIdx += 1
    server.tickTimeIdx %= len(server.tickTimes)

    app.client.serverTickTimes = server.tickTimes
    app.client.serverTickTimeIdx = server.tickTimeIdx
Beispiel #3
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))