Jump to content

Recommended Posts

Posted

Hi

It would be really helpful to get this coverted to LUA to assist in development of Steamworks/Multiplayer.
It's been tricky to use only the basic documentation to get it done, without an example.

https://www.leadwerks.com/learn/Steamworks_GetPacket?lang=cpp

Example

This example demonstrates lobbies, voice chat, and simple player movement.

 

#include "UltraEngine.h"
#include "Steamworks/Steamworks.h"
#include "ComponentSystem.h"

using namespace UltraEngine;

class Player : public Object
{
public:
    static inline std::map<uint64_t, shared_ptr<Player> > players;

    shared_ptr<Entity> entity;
    WString name;
    uint64_t userid;

    static std::shared_ptr<Player> Get(shared_ptr<World> world, const uint64_t userid)
    {
        if (players[userid]) return players[userid];
        auto player = std::make_shared<Player>();
        player->entity = CreatePivot(world);
        auto model = CreateCylinder(world, 0.25, 1.8);
        model->SetPosition(0, 0.9, 0);
        model->SetParent(player->entity);
        model->SetCollider(nullptr);
        player->userid = userid;
        players[userid] = player;
        return player;
    }

    static void Remove(const uint64_t userid)
    {
        players[userid] = nullptr;
    }
};

struct PlayerState
{
    Vec3 position;
    float yaw;
};

int main(int argc, const char* argv[])
{
    // Initialize Steam
    if (not Steamworks::Initialize())
    {
        RuntimeError("Steamworks failed to initialize.");
        return 1;
    }

    // Get the displays
    auto displays = GetDisplays();

    // Create a window
    auto window = CreateWindow("Ultra Engine", 0, 0, 1280 * displays[0]->scale, 720 * displays[0]->scale, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR);

    // Create a framebuffer
    auto framebuffer = CreateFramebuffer(window);

    // Create world
    auto world = CreateWorld();
    world->SetGravity(0, -18, 0);

    // Create lobby
    auto lobbyid = Steamworks::CreateLobby(Steamworks::LOBBY_PUBLIC);

    Print("Lobby: " + String(lobbyid));

    // Spawn local player
    auto player = Player::Get(world, Steamworks::GetUserId());
    player->entity->AddComponent<FirstPersonControls>();

    // Add lighting
    auto light = CreateDirectionalLight(world);
    light->SetRotation(55, 35, 0);

    // Add a floor
    auto floor = CreateBox(world, 50, 1, 50);
    floor->SetPosition(0, -0.5, 0);
    auto mtl = CreateMaterial();
    mtl->SetTexture(LoadTexture("https://github.com/UltraEngine/Documentation/raw/master/Assets/Materials/Developer/griid_gray.dds"));
    floor->SetMaterial(mtl);

    // Main loop
    while (not window->KeyDown(KEY_ESCAPE) and not window->Closed())
    {
        while (PeekEvent())
        {
            const auto e = WaitEvent();
            switch (e.id)
            {            
            case Steamworks::EVENT_LOBBYINVITEACCEPTED:
            case Steamworks::EVENT_LOBBYDATACHANGED:
            case Steamworks::EVENT_LOBBYUSERJOIN:
            case Steamworks::EVENT_LOBBYUSERLEAVE:
            case Steamworks::EVENT_LOBBYUSERDISCONNECT:
                auto info = e.source->As<Steamworks::LobbyEventInfo>();
                auto username = Steamworks::GetUserName(info->userid);
                switch (e.id)
                {
                case Steamworks::EVENT_LOBBYINVITEACCEPTED:
                    Print("Invite accepted to lobby " + String(info->lobbyid));
                    lobbyid = info->lobbyid;
                    if (not Steamworks::JoinLobby(info->lobbyid))
                    {
                        lobbyid = 0;
                        Print("Failed to join lobby");
                    }
                    break;

                case Steamworks::EVENT_LOBBYDATACHANGED:
                    Print("New lobby owner " + username);
                    break;

                case Steamworks::EVENT_LOBBYUSERJOIN:
                    Print("User " + username + " joined");

                    if (not Player::players[info->userid])
                    {
                        // Spawn remote player
                        Player::Get(world, info->userid);
                    }

                    break;
                case Steamworks::EVENT_LOBBYUSERLEAVE:
                    Print("User " + username + " left");

                    // Remove remote player
                    Player::Remove(info->userid);

                    break;
                case Steamworks::EVENT_LOBBYUSERDISCONNECT:
                    Print("User " + username + " disconnected");

                    // Remove remote player
                    Player::Remove(info->userid);

                    break;
                }
                break;
            }
        }

        // Receive player data
        PlayerState state;
        while (true)
        {
            auto pak = Steamworks::GetPacket();
            if (not pak) break;
            if (pak->data->GetSize() == sizeof(PlayerState))
            {
                auto player = Player::Get(world, pak->userid);
                if (player)
                {
                    pak->data->Peek(0, (const char*)&state, pak->data->GetSize());
                    player->entity->SetPosition(state.position);
                    player->entity->SetRotation(state.yaw);
                }
            }
        }

        //Receive text messages
        while (true)
        {
            auto pak = Steamworks::GetPacket(1);
            if (not pak) break;
            String s = pak->data->PeekString(0);
            Print(Steamworks::GetUserName(pak->userid) + ": " + WString(s));
        }

        // Send player data
        auto userid = Steamworks::GetUserId();
        auto player = Player::players[userid];
        state.position = player->entity->position;
        state.yaw = player->entity->rotation.y;
        Steamworks::BroadcastPacket(lobbyid, &state, sizeof(PlayerState), 0, Steamworks::P2PSEND_UNRELIABLENODELAY);

        // Enable voice chat when the C key is pressed
        bool record = window->KeyDown(KEY_C);
        Steamworks::RecordVoice(record);
        String title = "Ultra Engine";
        if (record) title += " (Microphone Enabled)";
        window->SetText(title);

        // Update world
        world->Update();

        // Render world
        world->Render(framebuffer);

        // Update Steamworks
        Steamworks::Update();
    }

    // Close Steam
    Steamworks::Shutdown();

    return 0;
}

 

  • Simple changed the title to Steamworks Example in LUA
Posted

Hi, I am going over this code now. However, I think it will take some time to update this and make a Lua version.

  • Like 1

Let's build cool stuff and have fun. :)

Posted

Ok thanks, no rush as I've almost got it working either way, just thought it may help others having clean code as part of documentation.

  • Upvote 1

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...