Exemple #1
0
def drawMainInventory(client: ClientState, canvas):
    # FIXME: 
    player = client.getPlayer()
    assert(player is not None)

    for i in range(9, 36):
        slot = player.inventory[i]

        (x, y, _) = getSlotCenterAndSize(client, i)

        drawSlot(client, canvas, x, y, slot)
Exemple #2
0
def updatePlayerPos(client: ClientState):
    player: Player = client.player

    playerChunkPos = world.toChunkLocal(player.getBlockPos())[0]
    playerChunkPos = ChunkPos(playerChunkPos.x, 0, playerChunkPos.z)

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

    ticks = min((time.perf_counter() - client.lastFrameTime) / 0.05, 2)

    if playerChunkPos in client.world.chunks and client.world.chunks[
            playerChunkPos].isTicking:
        if x != 0.0 or z != 0.0:
            mag = math.sqrt(x * x + z * z)
            x /= mag
            z /= mag

            newX = math.cos(client.cameraYaw) * x - math.sin(
                client.cameraYaw) * z
            newZ = math.sin(client.cameraYaw) * x + math.cos(
                client.cameraYaw) * z

            x, z = newX, newZ

            x *= player.walkSpeed
            z *= player.walkSpeed

        #player.tick(app, app.world, app.entities, 0.0, 0.0)
        if player.flying:
            if client.space:
                player.velocity[1] = 0.2
            elif client.shift:
                player.velocity[1] = -0.2
            else:
                player.velocity[1] = 0.0

        collideY(client.world, player, ticks, useGravity=False)
        if player.onGround:
            player.velocity[0] = x
            player.velocity[2] = z
        else:
            player.velocity[0] += x / 10.0
            player.velocity[2] += z / 10.0
            player.velocity[0] *= 0.9
            player.velocity[2] *= 0.9

        collideXZ(client.world, player, ticks)

    client.cameraPos = copy.copy(player.pos)
    client.cameraPos[1] += player.height
Exemple #3
0
def drawHud(client: ClientState, canvas, startTime):
    # Indicates the center of the screen
    canvas.create_oval(client.width / 2 - 1, client.height / 2 - 1, 
        client.width / 2 + 1, client.height / 2 + 1)

    drawHealthbar(client, canvas)

    drawHotbar(client, canvas)

    if client.showDebugInfo:
        clientTickTime = sum(client.tickTimes) / len(client.tickTimes) * 1000.0
        serverTickTime = sum(client.serverTickTimes) / len(client.serverTickTimes) * 1000.0

        drawTextOutlined(canvas, 10, 30, text=f'Tick: (C) {clientTickTime:.2f}ms (S) {serverTickTime:.2f}ms', anchor='nw')
        
        global frameTimes
        global frameTimeIdx

        endTime = time.time()
        frameTimes[frameTimeIdx] = (endTime - startTime)
        frameTimeIdx += 1
        frameTimeIdx %= len(frameTimes)
        frameTime = sum(frameTimes) / len(frameTimes) * 1000.0

        drawTextOutlined(canvas, 10, 10, text=f'Frame Time: {frameTime:.2f}ms', anchor='nw')

        drawTextOutlined(canvas, 10, 50, text=f"Eyes: {client.cameraPos[0]:.2f}, {client.cameraPos[1]:.2f}, {client.cameraPos[2]:.2f}", anchor='nw')
        
        chunkX = math.floor(client.cameraPos[0] / 16)
        chunkY = math.floor(client.cameraPos[1] / world.CHUNK_HEIGHT)
        chunkZ = math.floor(client.cameraPos[2] / 16)

        drawTextOutlined(canvas, 10, 140, text=f'Chunk coords: {chunkX}, {chunkY}, {chunkZ}', anchor='nw')

        # FIXME:
        player = client.getPlayer()
        if player is not None:
            drawTextOutlined(canvas, 10, 90, text=f"Feet: {player.pos[0]:.2f}, {player.pos[1]:.2f}, {player.pos[2]:.2f}", anchor='nw')

            feetPos = (client.cameraPos[0], client.cameraPos[1] - player.height + 0.1, client.cameraPos[2])
            feetBlockPos = world.nearestBlockPos(feetPos[0], feetPos[1], feetPos[2])
            (ckPos, ckLocal) = world.toChunkLocal(feetBlockPos)
            if ckPos in client.world.chunks:
                lightLevel = client.world.getLightLevel(feetBlockPos)
                blockLightLevel = client.world.getBlockLightLevel(world.nearestBlockPos(feetPos[0], feetPos[1], feetPos[2]))
                drawTextOutlined(canvas, 10, 190, text=f'Sky {lightLevel}, Block {blockLightLevel}', anchor='nw')

                biome = client.world.chunks[ckPos].biomes[ckLocal.x // 4, ckLocal.y // 4, ckLocal.z // 4]

                drawTextOutlined(canvas, 10, 230, text=f'Biome: {biome.name}', anchor='nw')
Exemple #4
0
def clientTick(client: ClientState, instData):
    startTime = time.time()

    client.time += 1

    if not client.local:
        chunkPos, _ = world.toChunkLocal(client.player.getBlockPos())

        client.world.tickets[chunkPos] = 1

        client.world.loadUnloadChunks(instData)
        client.world.addChunkDetails(instData, needUrgent=False)

    client.world.flushLightChanges()

    player: Player = client.player

    if not player.onGround:
        player.velocity[1] -= GRAVITY

    playerChunkPos = world.toChunkLocal(player.getBlockPos())[0]
    playerChunkPos = ChunkPos(playerChunkPos.x, 0, playerChunkPos.z)

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

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

        entity.clientTick()

        #collide(client, entity)

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

    client.lastTickTime = endTime
Exemple #5
0
def drawHotbar(client: ClientState, canvas):
    # FIXME: 
    player = client.getPlayer()
    assert(player is not None)

    #slotWidth = CLIENT_DATA.itemTextures['air'].width + 7
    slotWidth = getSlotCenterAndSize(client, 0)[2]

    margin = 10

    for (i, slot) in enumerate(player.inventory[:9]):
        x = (i - 4) * slotWidth + client.width / 2

        y = client.height - margin - slotWidth / 2

        drawSlot(client, canvas, x, y, slot)
    
    x = (player.hotbarIdx - 4) * slotWidth + client.width / 2
    y = client.height - margin - slotWidth
    canvas.create_rectangle(x - slotWidth / 2, y,
        x + slotWidth / 2,
        y + slotWidth,
        outline='white')
Exemple #6
0
 def __init__(self, cid, sock, addr):
     self.state = ClientState()
     self.connection = ClientConnection(cid, sock, addr)
Exemple #7
0
def renderInstancesGl(client: ClientState, canvas):
    glViewport(0, 0, client.width, client.height)

    view = glViewMat(client.cameraPos, client.cameraYaw, client.cameraPitch)

    th = math.tan(0.5 * math.radians(70.0));
    zf = 100.0;
    zn = 0.1;

    projection = np.array([
        [(client.height / client.width) / th, 0.0, 0.0, 0.0],
        [0.0, 1.0 / th, 0.0, 0.0],
        [0.0, 0.0, zf / (zf - zn), 1.0],
        [0.0, 0.0, -(zf * zn) / (zf - zn), 0.0],
    ], dtype='float32')

    #glBindVertexArray(app.cubeVao)

    chunkMeshes = []

    for (pos, chunk) in client.world.chunks.items():
        if not chunk.isVisible: continue 

        [cx, cy, cz] = chunk.pos
        cx *= 16
        cy *= world.CHUNK_HEIGHT
        cz *= 16

        for i in range(len(chunk.meshes)):
            chunkMeshes.append((chunk.meshes[i], chunk.transMeshes[i], pos, i))
    
    breakingBlockAmount = 0.0

    if hasattr(client, 'player'):
        player = client.getPlayer()
        if client.breakingBlock != 0.0 and player is not None:
            toolStack = player.inventory[player.hotbarIdx].stack
            if toolStack.isEmpty():
                tool = ''
            else:
                tool = toolStack.item

            blockId = client.world.getBlock(client.breakingBlockPos)

            if blockId != 'air':
                hardness = getHardnessAgainst(blockId, tool)

                breakingBlockAmount = client.breakingBlock / hardness

        b = math.floor(breakingBlockAmount * 10.0)
        b = min(b, len(CLIENT_DATA.breakTextures) - 1)
    else:
        b = 0

    CLIENT_DATA.chunkProgram.useProgram()
    glUniformMatrix4fv(CLIENT_DATA.chunkProgram.getUniformLocation("view"), 1, GL_FALSE, view) #type:ignore
    glUniformMatrix4fv(CLIENT_DATA.chunkProgram.getUniformLocation("projection"), 1, GL_FALSE, projection) #type:ignore
    glUniform1f(CLIENT_DATA.chunkProgram.getUniformLocation("atlasWidth"), CLIENT_DATA.atlasWidth)
    glUniform1i(CLIENT_DATA.chunkProgram.getUniformLocation("gameTime"), client.time)

    glUniform1i(CLIENT_DATA.chunkProgram.getUniformLocation("blockTexture"), 0)
    glUniform1i(CLIENT_DATA.chunkProgram.getUniformLocation("breakTexture"), 1)

    glActiveTexture(GL_TEXTURE0)
    glBindTexture(GL_TEXTURE_2D, CLIENT_DATA.textureAtlas)

    glActiveTexture(GL_TEXTURE1)
    glBindTexture(GL_TEXTURE_2D, CLIENT_DATA.breakTextures[b])

    (cp, lp) = world.toChunkLocal(client.breakingBlockPos)
    breakBlockIdx = lp.x * 16 * 16 + (lp.y % world.MESH_HEIGHT) * 16 + lp.z
    breakBlockLoc = CLIENT_DATA.chunkProgram.getUniformLocation("breakBlockIdx")

    glBindFramebuffer(GL_FRAMEBUFFER, CLIENT_DATA.translucentFb)
    glViewport(0, 0, client.width, client.height)

    glClearColor(0.2, 0.1, 0.1, 1.0)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) #type:ignore
    
    for _m, transMesh, pos, i in chunkMeshes:
        if breakingBlockAmount > 0.0 and cp == pos and (lp.y // world.MESH_HEIGHT) == i:
            glUniform1i(breakBlockLoc, breakBlockIdx)
        else:
            glUniform1i(breakBlockLoc, -1)
        
        glBindVertexArray(transMesh.vao)

        glDrawArrays(GL_TRIANGLES, 0, transMesh.dataLen)
    
    glBindFramebuffer(GL_FRAMEBUFFER, 0)

    for mesh, _t, pos, i in chunkMeshes:
        if breakingBlockAmount > 0.0 and cp == pos and (lp.y // world.MESH_HEIGHT) == i:
            glUniform1i(breakBlockLoc, breakBlockIdx)
        else:
            glUniform1i(breakBlockLoc, -1)

        glBindVertexArray(mesh.vao)

        glDrawArrays(GL_TRIANGLES, 0, mesh.dataLen)

    CLIENT_DATA.transProgram.useProgram()

    glUniform1i(CLIENT_DATA.transProgram.getUniformLocation("transTexture"), 0)
    glActiveTexture(GL_TEXTURE0)
    glBindTexture(GL_TEXTURE_2D, CLIENT_DATA.transColorTex)

    glUniform1i(CLIENT_DATA.transProgram.getUniformLocation("depthTexture"), 1)
    glActiveTexture(GL_TEXTURE1)
    glBindTexture(GL_TEXTURE_2D, CLIENT_DATA.transDepthTex)

    glBindVertexArray(CLIENT_DATA.fullscreenVao)
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, ctypes.c_void_p(0)) #type:ignore

    drawEntities(client, view, projection)

    # https://learnopengl.com/Advanced-OpenGL/Cubemaps
    glDisable(GL_CULL_FACE)
    glDepthFunc(GL_LEQUAL)
    CLIENT_DATA.skyProgram.useProgram()
    view[3, 0:3] = 0.0
    glUniformMatrix4fv(CLIENT_DATA.skyProgram.getUniformLocation("view"), 1, GL_FALSE, view) #type:ignore
    glUniformMatrix4fv(CLIENT_DATA.skyProgram.getUniformLocation("projection"), 1, GL_FALSE, projection) #type:ignore
    glUniform1i(CLIENT_DATA.skyProgram.getUniformLocation("gameTime"), client.time)
    glUniform1i(CLIENT_DATA.skyProgram.getUniformLocation("sunTex"), 0)

    glActiveTexture(GL_TEXTURE0)
    glBindTexture(GL_TEXTURE_2D, CLIENT_DATA.sunTex)

    glBindVertexArray(CLIENT_DATA.skyboxVao)
    glDrawArrays(GL_TRIANGLES, 0, 36)
    glBindVertexArray(0)

    glEnable(GL_CULL_FACE)
    glDepthFunc(GL_LESS)
Exemple #8
0
def cullInstance(client: ClientState, toCamMat: ndarray, inst: Instance, blockPos: Optional[BlockPos]) -> List[Tuple[Any, Face, Color]]:
    """
    This converts the instance's vertices to points in camera space, and then:

    For all blocks, the following happens:
        - Faces pointing away from the camera are removed
        - Faces that are hidden 'underground' are removed
        - The color of each face is adjusted based on lighting
        - ~~A "fog" is applied~~ NOT IMPLEMENTED! TODO:

    For anything else:
        - Normal back face culling is applied
    
    Then the faces are clipped, which may remove, modify, or split faces.
    Then a list of faces, their vertices, and their colors are returned
    """

    vertices = [toCamMat @ v for v in inst.worldSpaceVertices()]

    faces = []

    skipNext = False

    for (faceIdx, (face, color)) in enumerate(zip(inst.model.faces, inst.texture)):
        if skipNext:
            skipNext = False
            continue 

        if blockPos is not None:
            if not inst.visibleFaces[faceIdx]:
                continue
            
            if isBackBlockFace(client, blockPos, faceIdx):
                skipNext = True
                continue

            light = blockFaceLight(client, blockPos, faceIdx)
            r = int(color[1:3], base=16)
            g = int(color[3:5], base=16)
            b = int(color[5:7], base=16)

            brightness = (light + 1) / 16
            r *= brightness
            g *= brightness
            b *= brightness

            if blockPos == client.breakingBlockPos and client.breakingBlock != 0.0:
                avg = (r + g + b) / 3.0

                player = client.getPlayer()
                assert(player is not None)

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

                hardness = getHardnessAgainst(client.world.getBlock(blockPos), tool)

                desaturation = client.breakingBlock / hardness
                r += (avg - r) * desaturation
                g += (avg - g) * desaturation
                b += (avg - b) * desaturation

            r = max(0.0, min(255.0, r))
            g = max(0.0, min(255.0, g))
            b = max(0.0, min(255.0, b))

            color = '#{:02X}{:02X}{:02X}'.format(int(r), int(g), int(b))
        else:
            # Backface culling (surprisingly expensive)
            '''
            backFace = isBackFace(
                vertices[face[0]], 
                vertices[face[1]],
                vertices[face[2]]
            )
            if backFace:
                continue
            '''

        for clippedFace in clip(client, vertices, face):
            faces.append([vertices, clippedFace, color])

    return faces