Simple Posted April 5, 2025 Posted April 5, 2025 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; } Quote
Josh Posted April 5, 2025 Posted April 5, 2025 Hi, I am going over this code now. However, I think it will take some time to update this and make a Lua version. 1 Quote Let's build cool stuff and have fun.
Simple Posted April 6, 2025 Author Posted April 6, 2025 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. 1 Quote
Recommended Posts
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.