diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2025-04-30 12:49:47 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2025-04-30 12:49:47 +1000 |
commit | d3d4345e057d95d784e34be9b23e7fe07fb9a7c1 (patch) | |
tree | f59fa890e5be1d590e42a337448cecfc6b61850a /source/game | |
parent | 86e229012f84744a1e878124d9a6e2991c0460bb (diff) | |
parent | 885502bf11057e7de961f178bc85ce93a9f40723 (diff) |
Merge branch 'main' into pr/218
Diffstat (limited to 'source/game')
29 files changed, 188 insertions, 61 deletions
diff --git a/source/game/CMakeLists.txt b/source/game/CMakeLists.txt index 11e0024..b1a519c 100644 --- a/source/game/CMakeLists.txt +++ b/source/game/CMakeLists.txt @@ -250,6 +250,7 @@ SET (star_game_HEADERS scripting/StarPlayerLuaBindings.hpp scripting/StarRootLuaBindings.hpp scripting/StarScriptedAnimatorLuaBindings.hpp + scripting/StarSongbookLuaBindings.hpp scripting/StarStatusControllerLuaBindings.hpp scripting/StarTeamClientLuaBindings.hpp scripting/StarWorldLuaBindings.hpp @@ -491,6 +492,7 @@ SET (star_game_SOURCES scripting/StarPlayerLuaBindings.cpp scripting/StarRootLuaBindings.cpp scripting/StarScriptedAnimatorLuaBindings.cpp + scripting/StarSongbookLuaBindings.cpp scripting/StarStatusControllerLuaBindings.cpp scripting/StarTeamClientLuaBindings.cpp scripting/StarWorldLuaBindings.cpp diff --git a/source/game/StarChatProcessor.cpp b/source/game/StarChatProcessor.cpp index 2082529..0dd0c48 100644 --- a/source/game/StarChatProcessor.cpp +++ b/source/game/StarChatProcessor.cpp @@ -122,7 +122,7 @@ StringList ChatProcessor::activeChannels() const { return channels; } -void ChatProcessor::broadcast(ConnectionId sourceConnectionId, String const& text) { +void ChatProcessor::broadcast(ConnectionId sourceConnectionId, String const& text, JsonObject data) { RecursiveMutexLocker locker(m_mutex); ChatReceivedMessage message = { @@ -132,6 +132,8 @@ void ChatProcessor::broadcast(ConnectionId sourceConnectionId, String const& tex text }; + message.data = std::move(data); + if (handleCommand(message)) return; @@ -139,7 +141,7 @@ void ChatProcessor::broadcast(ConnectionId sourceConnectionId, String const& tex pair.second.pendingMessages.append(message); } -void ChatProcessor::message(ConnectionId sourceConnectionId, MessageContext::Mode mode, String const& channelName, String const& text) { +void ChatProcessor::message(ConnectionId sourceConnectionId, MessageContext::Mode mode, String const& channelName, String const& text, JsonObject data) { RecursiveMutexLocker locker(m_mutex); ChatReceivedMessage message = { @@ -149,6 +151,8 @@ void ChatProcessor::message(ConnectionId sourceConnectionId, MessageContext::Mod text }; + message.data = std::move(data); + if (handleCommand(message)) return; @@ -158,11 +162,17 @@ void ChatProcessor::message(ConnectionId sourceConnectionId, MessageContext::Mod } } -void ChatProcessor::whisper(ConnectionId sourceConnectionId, ConnectionId targetClientId, String const& text) { +void ChatProcessor::whisper(ConnectionId sourceConnectionId, ConnectionId targetClientId, String const& text, JsonObject data) { RecursiveMutexLocker locker(m_mutex); ChatReceivedMessage message = { - {MessageContext::Whisper}, sourceConnectionId, connectionNick(sourceConnectionId), text}; + {MessageContext::Whisper}, + sourceConnectionId, + connectionNick(sourceConnectionId), + text + }; + + message.data = std::move(data); if (handleCommand(message)) return; diff --git a/source/game/StarChatProcessor.hpp b/source/game/StarChatProcessor.hpp index 89bb5f5..1c42b75 100644 --- a/source/game/StarChatProcessor.hpp +++ b/source/game/StarChatProcessor.hpp @@ -41,9 +41,9 @@ public: StringList clientChannels(ConnectionId clientId) const; StringList activeChannels() const; - void broadcast(ConnectionId sourceConnectionId, String const& text); - void message(ConnectionId sourceConnectionId, MessageContext::Mode context, String const& channelName, String const& text); - void whisper(ConnectionId sourceConnectionId, ConnectionId targetClientId, String const& text); + void broadcast(ConnectionId sourceConnectionId, String const& text, JsonObject data = {}); + void message(ConnectionId sourceConnectionId, MessageContext::Mode context, String const& channelName, String const& text, JsonObject data = {}); + void whisper(ConnectionId sourceConnectionId, ConnectionId targetClientId, String const& text, JsonObject data = {}); // Shorthand for passing ServerConnectionId as sourceConnectionId to // broadcast / message / whisper diff --git a/source/game/StarChatTypes.cpp b/source/game/StarChatTypes.cpp index 79dfc4f..56fa6d9 100644 --- a/source/game/StarChatTypes.cpp +++ b/source/game/StarChatTypes.cpp @@ -56,6 +56,7 @@ ChatReceivedMessage::ChatReceivedMessage(Json const& json) : ChatReceivedMessage fromNick = json.getString("fromNick", ""); portrait = json.getString("portrait", ""); text = json.getString("text", ""); + data = json.getObject("data", JsonObject()); } Json ChatReceivedMessage::toJson() const { @@ -67,7 +68,8 @@ Json ChatReceivedMessage::toJson() const { {"fromConnection", fromConnection}, {"fromNick", fromNick.empty() ? Json() : fromNick}, {"portrait", portrait.empty() ? Json() : portrait}, - {"text", text} + {"text", text}, + {"data", data} }; } @@ -78,7 +80,8 @@ DataStream& operator>>(DataStream& ds, ChatReceivedMessage& receivedMessage) { ds.read(receivedMessage.fromNick); ds.read(receivedMessage.portrait); ds.read(receivedMessage.text); - + if (ds.streamCompatibilityVersion() >= 5) + ds.read(receivedMessage.data); return ds; } @@ -88,7 +91,8 @@ DataStream& operator<<(DataStream& ds, ChatReceivedMessage const& receivedMessag ds.write(receivedMessage.fromNick); ds.write(receivedMessage.portrait); ds.write(receivedMessage.text); - + if (ds.streamCompatibilityVersion() >= 5) + ds.write(receivedMessage.data); return ds; } diff --git a/source/game/StarChatTypes.hpp b/source/game/StarChatTypes.hpp index 3feb413..3c23d7c 100644 --- a/source/game/StarChatTypes.hpp +++ b/source/game/StarChatTypes.hpp @@ -55,6 +55,8 @@ struct ChatReceivedMessage { String portrait; String text; + + JsonObject data; }; DataStream& operator>>(DataStream& ds, ChatReceivedMessage& receivedMessage); diff --git a/source/game/StarItemBag.cpp b/source/game/StarItemBag.cpp index 8abdd6f..1f8f74f 100644 --- a/source/game/StarItemBag.cpp +++ b/source/game/StarItemBag.cpp @@ -234,17 +234,22 @@ auto ItemBag::itemsFitWhere(ItemConstPtr const& items, uint64_t max) const -> It return ItemsFitWhereResult(); List<size_t> slots; + StableHashSet<size_t> taken; uint64_t count = std::min(items->count(), max); while (true) { if (count == 0) break; - size_t slot = bestSlotAvailable(items, false); + size_t slot = bestSlotAvailable(items, false, [&](size_t i) { + return !taken.contains(i); + }); if (slot == NPos) break; - else + else { slots.append(slot); + taken.insert(slot); + } uint64_t available = stackTransfer(at(slot), items); if (available != 0) @@ -350,9 +355,11 @@ uint64_t ItemBag::stackTransfer(ItemConstPtr const& to, ItemConstPtr const& from return std::min(to->maxStack() - to->count(), from->count()); } -size_t ItemBag::bestSlotAvailable(ItemConstPtr const& item, bool stacksOnly) const { +size_t ItemBag::bestSlotAvailable(ItemConstPtr const& item, bool stacksOnly, std::function<bool(size_t)> test) const { // First look for any slots that can stack, before empty slots. for (size_t i = 0; i < m_items.size(); ++i) { + if (!test(i)) + continue; auto const& storedItem = at(i); if (storedItem && stackTransfer(storedItem, item) != 0) return i; @@ -369,4 +376,8 @@ size_t ItemBag::bestSlotAvailable(ItemConstPtr const& item, bool stacksOnly) con return NPos; } +size_t ItemBag::bestSlotAvailable(ItemConstPtr const& item, bool stacksOnly) const { + return bestSlotAvailable(item, stacksOnly, [](size_t) { return true; }); +} + } diff --git a/source/game/StarItemBag.hpp b/source/game/StarItemBag.hpp index 7b0246d..7480d7c 100644 --- a/source/game/StarItemBag.hpp +++ b/source/game/StarItemBag.hpp @@ -109,6 +109,7 @@ private: // Returns the slot that contains the item already and has the *highest* // stack count but not full, or an empty slot, or NPos for no room. + size_t bestSlotAvailable(ItemConstPtr const& item, bool stacksOnly, std::function<bool(size_t)> test) const; size_t bestSlotAvailable(ItemConstPtr const& item, bool stacksOnly) const; List<ItemPtr> m_items; diff --git a/source/game/StarMonster.cpp b/source/game/StarMonster.cpp index d9ce986..98f4642 100644 --- a/source/game/StarMonster.cpp +++ b/source/game/StarMonster.cpp @@ -144,7 +144,7 @@ void Monster::init(World* world, EntityId entityId, EntityMode mode) { m_scriptComponent.addCallbacks("entity", LuaBindings::makeEntityCallbacks(this)); m_scriptComponent.addCallbacks("animator", LuaBindings::makeNetworkedAnimatorCallbacks(&m_networkedAnimator)); m_scriptComponent.addCallbacks("status", LuaBindings::makeStatusControllerCallbacks(m_statusController.get())); - m_scriptComponent.addCallbacks("behavior", LuaBindings::makeBehaviorLuaCallbacks(&m_behaviors)); + m_scriptComponent.addCallbacks("behavior", LuaBindings::makeBehaviorCallbacks(&m_behaviors)); m_scriptComponent.addActorMovementCallbacks(m_movementController.get()); m_scriptComponent.init(world); } diff --git a/source/game/StarNetPackets.cpp b/source/game/StarNetPackets.cpp index 4b16ce8..a121beb 100644 --- a/source/game/StarNetPackets.cpp +++ b/source/game/StarNetPackets.cpp @@ -495,14 +495,20 @@ ChatSendPacket::ChatSendPacket() : sendMode(ChatSendMode::Broadcast) {} ChatSendPacket::ChatSendPacket(String text, ChatSendMode sendMode) : text(std::move(text)), sendMode(sendMode) {} +ChatSendPacket::ChatSendPacket(String text, ChatSendMode sendMode, JsonObject data) : text(std::move(text)), sendMode(sendMode), data(std::move(data)) {} + void ChatSendPacket::read(DataStream& ds) { ds.read(text); ds.read(sendMode); + if (ds.streamCompatibilityVersion() >= 5) + ds.read(data); } void ChatSendPacket::write(DataStream& ds) const { ds.write(text); ds.write(sendMode); + if (ds.streamCompatibilityVersion() >= 5) + ds.write(data); } CelestialRequestPacket::CelestialRequestPacket() {} diff --git a/source/game/StarNetPackets.hpp b/source/game/StarNetPackets.hpp index 8db5c03..63a7ee8 100644 --- a/source/game/StarNetPackets.hpp +++ b/source/game/StarNetPackets.hpp @@ -371,12 +371,14 @@ struct FlyShipPacket : PacketBase<PacketType::FlyShip> { struct ChatSendPacket : PacketBase<PacketType::ChatSend> { ChatSendPacket(); ChatSendPacket(String text, ChatSendMode sendMode); + ChatSendPacket(String text, ChatSendMode sendMode, JsonObject data); void read(DataStream& ds) override; void write(DataStream& ds) const override; String text; ChatSendMode sendMode; + JsonObject data; }; struct CelestialRequestPacket : PacketBase<PacketType::CelestialRequest> { diff --git a/source/game/StarNpc.cpp b/source/game/StarNpc.cpp index 388f6e5..7c1cf63 100644 --- a/source/game/StarNpc.cpp +++ b/source/game/StarNpc.cpp @@ -2,6 +2,8 @@ #include "StarDataStreamExtra.hpp" #include "StarWorld.hpp" #include "StarRoot.hpp" +#include "StarSongbook.hpp" +#include "StarSongbookLuaBindings.hpp" #include "StarDamageManager.hpp" #include "StarDamageDatabase.hpp" #include "StarLogging.hpp" @@ -76,6 +78,8 @@ Npc::Npc(NpcVariant const& npcVariant) if (!m_statusController->statusProperty("effectDirectives")) m_statusController->setStatusProperty("effectDirectives", speciesDefinition->effectDirectives()); + m_songbook = make_shared<Songbook>(species()); + m_effectEmitter = make_shared<EffectEmitter>(); m_hitDamageNotificationLimiter = 0; @@ -185,7 +189,8 @@ void Npc::init(World* world, EntityId entityId, EntityMode mode) { { return m_npcVariant.scriptConfig.query(name, def); })); m_scriptComponent.addCallbacks("entity", LuaBindings::makeEntityCallbacks(this)); m_scriptComponent.addCallbacks("status", LuaBindings::makeStatusControllerCallbacks(m_statusController.get())); - m_scriptComponent.addCallbacks("behavior", LuaBindings::makeBehaviorLuaCallbacks(&m_behaviors)); + m_scriptComponent.addCallbacks("behavior", LuaBindings::makeBehaviorCallbacks(&m_behaviors)); + m_scriptComponent.addCallbacks("songbook", LuaBindings::makeSongbookCallbacks(m_songbook.get())); m_scriptComponent.addActorMovementCallbacks(m_movementController.get()); m_scriptComponent.init(world); } @@ -199,6 +204,8 @@ void Npc::uninit() { m_scriptComponent.removeCallbacks("config"); m_scriptComponent.removeCallbacks("entity"); m_scriptComponent.removeCallbacks("status"); + m_scriptComponent.removeCallbacks("behavior"); + m_scriptComponent.removeCallbacks("songbook"); m_scriptComponent.removeActorMovementCallbacks(); } m_tools->uninit(); @@ -359,6 +366,8 @@ void Npc::destroy(RenderCallback* renderCallback) { if (renderCallback && m_deathParticleBurst.get()) renderCallback->addParticles(m_humanoid.particles(*m_deathParticleBurst.get()), position()); + + m_songbook->stop(); } void Npc::damagedOther(DamageNotification const& damage) { @@ -503,6 +512,7 @@ void Npc::render(RenderCallback* renderCallback) { renderCallback->addDrawables(m_tools->renderObjectPreviews(aimPosition(), walkingDirection(), inToolRange(), favoriteColor()), renderLayer); m_effectEmitter->render(renderCallback); + m_songbook->render(renderCallback); } void Npc::renderLightSources(RenderCallback* renderCallback) { @@ -571,6 +581,8 @@ void Npc::tickShared(float dt) { if (m_hitDamageNotificationLimiter) m_hitDamageNotificationLimiter--; + m_songbook->update(*entityMode(), world()); + m_effectEmitter->setSourcePosition("normal", position()); m_effectEmitter->setSourcePosition("mouth", position() + mouthOffset()); m_effectEmitter->setSourcePosition("feet", position() + feetOffset()); @@ -814,6 +826,8 @@ void Npc::setupNetStates() { m_netGroup.addNetElement(m_statusController.get()); m_netGroup.addNetElement(m_armor.get()); m_netGroup.addNetElement(m_tools.get()); + m_songbook->setCompatibilityVersion(6); + m_netGroup.addNetElement(m_songbook.get()); m_netGroup.setNeedsStoreCallback(bind(&Npc::setNetStates, this)); m_netGroup.setNeedsLoadCallback(bind(&Npc::getNetStates, this, _1)); @@ -1075,10 +1089,13 @@ bool Npc::consumeEnergy(float energy) { void Npc::queueUIMessage(String const&) {} bool Npc::instrumentPlaying() { - return false; // TODO: remove this from tool user entirely + return m_songbook->instrumentPlaying(); } -void Npc::instrumentEquipped(String const&) {} +void Npc::instrumentEquipped(String const& instrumentKind) { + if (canUseTool()) + m_songbook->keepAlive(instrumentKind, mouthPosition()); +} void Npc::interact(InteractAction const&) {} @@ -1102,6 +1119,10 @@ StatusController* Npc::statusController() { return m_statusController.get(); } +Songbook* Npc::songbook() { + return m_songbook.get(); +} + void Npc::setCameraFocusEntity(Maybe<EntityId> const&) { // players only } diff --git a/source/game/StarNpc.hpp b/source/game/StarNpc.hpp index 0b22702..21c562c 100644 --- a/source/game/StarNpc.hpp +++ b/source/game/StarNpc.hpp @@ -25,6 +25,7 @@ namespace Star { +STAR_CLASS(Songbook); STAR_CLASS(Item); STAR_CLASS(RenderCallback); STAR_CLASS(Npc); @@ -165,6 +166,7 @@ public: void requestEmote(String const& emote) override; ActorMovementController* movementController() override; StatusController* statusController() override; + Songbook* songbook(); void setCameraFocusEntity(Maybe<EntityId> const& cameraFocusEntity) override; void playEmote(HumanoidEmote emote) override; @@ -246,6 +248,7 @@ private: ArmorWearerPtr m_armor; ToolUserPtr m_tools; + SongbookPtr m_songbook; NetElementBool m_disableWornArmor; diff --git a/source/game/StarPlayer.cpp b/source/game/StarPlayer.cpp index 43add67..facde2e 100644 --- a/source/game/StarPlayer.cpp +++ b/source/game/StarPlayer.cpp @@ -3,6 +3,7 @@ #include "StarJsonExtra.hpp" #include "StarRoot.hpp" #include "StarSongbook.hpp" +#include "StarSongbookLuaBindings.hpp" #include "StarEmoteProcessor.hpp" #include "StarSpeciesDatabase.hpp" #include "StarDamageManager.hpp" @@ -331,6 +332,7 @@ void Player::init(World* world, EntityId entityId, EntityMode mode) { p.second->addActorMovementCallbacks(m_movementController.get()); p.second->addCallbacks("player", LuaBindings::makePlayerCallbacks(this)); p.second->addCallbacks("status", LuaBindings::makeStatusControllerCallbacks(m_statusController.get())); + p.second->addCallbacks("songbook", LuaBindings::makeSongbookCallbacks(m_songbook.get())); if (m_client) p.second->addCallbacks("celestial", LuaBindings::makeCelestialCallbacks(m_client)); p.second->init(world); @@ -362,6 +364,7 @@ void Player::uninit() { p.second->removeCallbacks("player"); p.second->removeCallbacks("mcontroller"); p.second->removeCallbacks("status"); + p.second->removeCallbacks("songbook"); p.second->removeCallbacks("world"); if (m_client) p.second->removeCallbacks("celestial"); @@ -2272,7 +2275,7 @@ bool Player::instrumentPlaying() { void Player::instrumentEquipped(String const& instrumentKind) { if (canUseTool()) - m_songbook->keepalive(instrumentKind, mouthPosition()); + m_songbook->keepAlive(instrumentKind, mouthPosition()); } void Player::interact(InteractAction const& action) { diff --git a/source/game/StarPlayerStorage.cpp b/source/game/StarPlayerStorage.cpp index 7687e97..6be4460 100644 --- a/source/game/StarPlayerStorage.cpp +++ b/source/game/StarPlayerStorage.cpp @@ -173,7 +173,7 @@ Json PlayerStorage::savePlayer(PlayerPtr const& player) { VersionedJson versionedJson = entityFactory->storeVersionedJson(EntityType::Player, playerCacheData); auto fileName = strf("{}.player", uuidFileName(uuid)); VersionedJson::writeFile(versionedJson, File::relativeTo(m_storageDirectory, fileName)); - Logger::info("Saved player {} to {}", Text::stripEscapeCodes(player->name()), fileName); + Logger::debug("Saved player {} to {}", Text::stripEscapeCodes(player->name()), fileName); } return newPlayerData; } diff --git a/source/game/StarSkyParameters.cpp b/source/game/StarSkyParameters.cpp index e2ed885..3d540b8 100644 --- a/source/game/StarSkyParameters.cpp +++ b/source/game/StarSkyParameters.cpp @@ -175,6 +175,8 @@ void SkyParameters::read(DataStream& ds) { ds >> sunType; if (ds.streamCompatibilityVersion() >= 3) ds >> settings; + else + settings = JsonObject(); } void SkyParameters::write(DataStream& ds) const { diff --git a/source/game/StarSongbook.cpp b/source/game/StarSongbook.cpp index 68db655..72f2b2b 100644 --- a/source/game/StarSongbook.cpp +++ b/source/game/StarSongbook.cpp @@ -158,7 +158,7 @@ void Songbook::render(RenderCallback* renderCallback) { m_pendingAudio.clear(); } -void Songbook::keepalive(String const& instrument, Vec2F const& position) { +void Songbook::keepAlive(String const& instrument, Vec2F const& position) { if (instrument != m_instrument) { m_instrument = instrument; m_dataUpdated = true; @@ -681,11 +681,11 @@ void Songbook::play(Json const& song, String const& timeSource) { m_activeCooldown = 3; } -bool Songbook::active() { +bool Songbook::active() const { return m_activeCooldown > 0; } -bool Songbook::instrumentPlaying() { +bool Songbook::instrumentPlaying() const { if (!active()) return false; if (m_timeSourceInstance) { @@ -698,6 +698,18 @@ bool Songbook::instrumentPlaying() { return false; } +Maybe<String> Songbook::timeSource() const { + return m_timeSource; +} + +Maybe<String> Songbook::instrument() const { + return m_instrument; +} + +Json Songbook::song() const { + return m_song; +} + double Songbook::fundamentalFrequency(double p) { return 55.0 * pow(2.0, (p - 69.0) / 12.0 + 3.0); } diff --git a/source/game/StarSongbook.hpp b/source/game/StarSongbook.hpp index 89a4bfd..6f15242 100644 --- a/source/game/StarSongbook.hpp +++ b/source/game/StarSongbook.hpp @@ -24,12 +24,16 @@ public: // instrument needs to tell the songbook what type it is, and needs to keep // calling it to signal // the instrument is still equiped - void keepalive(String const& instrument, Vec2F const& position); + void keepAlive(String const& instrument, Vec2F const& position); void stop(); - void play(Json const& song, String const& timesource); - bool active(); - bool instrumentPlaying(); + void play(Json const& song, String const& timeSource); + bool active() const; + bool instrumentPlaying() const; + + Maybe<String> timeSource() const; + Maybe<String> instrument() const; + Json song() const; private: struct Note { diff --git a/source/game/StarStagehand.cpp b/source/game/StarStagehand.cpp index d85f77b..1207d91 100644 --- a/source/game/StarStagehand.cpp +++ b/source/game/StarStagehand.cpp @@ -43,7 +43,7 @@ void Stagehand::init(World* world, EntityId entityId, EntityMode mode) { return m_config.query(name, def); })); m_scriptComponent.addCallbacks("entity", LuaBindings::makeEntityCallbacks(this)); - m_scriptComponent.addCallbacks("behavior", LuaBindings::makeBehaviorLuaCallbacks(&m_behaviors)); + m_scriptComponent.addCallbacks("behavior", LuaBindings::makeBehaviorCallbacks(&m_behaviors)); m_scriptComponent.init(world); } } diff --git a/source/game/StarUniverseClient.cpp b/source/game/StarUniverseClient.cpp index af33508..b41d19e 100644 --- a/source/game/StarUniverseClient.cpp +++ b/source/game/StarUniverseClient.cpp @@ -71,7 +71,7 @@ PlayerPtr UniverseClient::mainPlayer() const { return m_mainPlayer; } -Maybe<String> UniverseClient::connect(UniverseConnection connection, bool allowAssetsMismatch, String const& account, String const& password) { +Maybe<String> UniverseClient::connect(UniverseConnection connection, bool allowAssetsMismatch, String const& account, String const& password, bool const& forceLegacy) { auto& root = Root::singleton(); auto assets = root.assets(); @@ -85,9 +85,11 @@ Maybe<String> UniverseClient::connect(UniverseConnection connection, bool allowA { auto protocolRequest = make_shared<ProtocolRequestPacket>(StarProtocolVersion); - protocolRequest->setCompressionMode(PacketCompressionMode::Enabled); - // Signal that we're OpenStarbound. Vanilla Starbound only compresses - // packets above 64 bytes - by forcing it, we can communicate this. + if (!forceLegacy) { + protocolRequest->setCompressionMode(PacketCompressionMode::Enabled); + // Signal that we're OpenStarbound. Vanilla Starbound only compresses + // packets above 64 bytes - by forcing it, we can communicate this. + } connection.pushSingle(protocolRequest); } connection.sendAll(timeout); @@ -101,7 +103,7 @@ Maybe<String> UniverseClient::connect(UniverseConnection connection, bool allowA NetCompatibilityRules compatibilityRules; compatibilityRules.setVersion(LegacyVersion); - bool legacyServer = protocolResponsePacket->compressionMode() != PacketCompressionMode::Enabled; + bool legacyServer = forceLegacy || (protocolResponsePacket->compressionMode() != PacketCompressionMode::Enabled); if (!legacyServer) { auto compressedSocket = as<CompressedPacketSocket>(&connection.packetSocket()); if (protocolResponsePacket->info) { @@ -484,10 +486,13 @@ bool UniverseClient::flying() const { return false; } -void UniverseClient::sendChat(String const& text, ChatSendMode sendMode, Maybe<bool> speak) { +void UniverseClient::sendChat(String const& text, ChatSendMode sendMode, Maybe<bool> speak, Maybe<JsonObject> data) { if (speak.value(!text.beginsWith("/"))) m_mainPlayer->addChatMessage(text); - m_connection->pushSingle(make_shared<ChatSendPacket>(text, sendMode)); + auto packet = make_shared<ChatSendPacket>(text, sendMode); + if (data) + packet->data = std::move(*data); + m_connection->pushSingle(packet); } List<ChatReceivedMessage> UniverseClient::pullChatMessages() { diff --git a/source/game/StarUniverseClient.hpp b/source/game/StarUniverseClient.hpp index b770b07..b1c589f 100644 --- a/source/game/StarUniverseClient.hpp +++ b/source/game/StarUniverseClient.hpp @@ -41,7 +41,7 @@ public: PlayerPtr mainPlayer() const; // Returns error if connection failed - Maybe<String> connect(UniverseConnection connection, bool allowAssetsMismatch, String const& account = "", String const& password = ""); + Maybe<String> connect(UniverseConnection connection, bool allowAssetsMismatch, String const& account = "", String const& password = "", bool const& forceLegacy = false); bool isConnected() const; void disconnect(); Maybe<String> disconnectReason() const; @@ -80,7 +80,7 @@ public: SkyConstPtr currentSky() const; bool flying() const; - void sendChat(String const& text, ChatSendMode sendMode, Maybe<bool> speak = {}); + void sendChat(String const& text, ChatSendMode sendMode, Maybe<bool> speak = {}, Maybe<JsonObject> data = {}); List<ChatReceivedMessage> pullChatMessages(); uint16_t players(); diff --git a/source/game/StarUniverseServer.cpp b/source/game/StarUniverseServer.cpp index f32f650..977dc71 100644 --- a/source/game/StarUniverseServer.cpp +++ b/source/game/StarUniverseServer.cpp @@ -1064,16 +1064,19 @@ void UniverseServer::processChat() { for (auto const& p : take(m_pendingChat)) { if (auto clientContext = m_clients.get(p.first)) { for (auto const& chat : p.second) { + auto& message = get<0>(chat); + auto sendMode = get<1>(chat); + auto& data = get<2>(chat); if (clientContext->remoteAddress()) - Logger::info("Chat: <{}> {}", clientContext->playerName(), chat.first); + Logger::info("Chat: <{}> {}", clientContext->playerName(), message); auto team = m_teamManager->getTeam(clientContext->playerUuid()); - if (chat.second == ChatSendMode::Broadcast) - m_chatProcessor->broadcast(p.first, chat.first); - else if (chat.second == ChatSendMode::Party && team.isValid()) - m_chatProcessor->message(p.first, MessageContext::Mode::Party, team.value().hex(), chat.first); + if (sendMode == ChatSendMode::Broadcast) + m_chatProcessor->broadcast(p.first, message, std::move(data)); + else if (sendMode == ChatSendMode::Party && team.isValid()) + m_chatProcessor->message(p.first, MessageContext::Mode::Party, team.value().hex(), message, std::move(data)); else - m_chatProcessor->message(p.first, MessageContext::Mode::Local, printWorldId(clientContext->playerWorldId()), chat.first); + m_chatProcessor->message(p.first, MessageContext::Mode::Local, printWorldId(clientContext->playerWorldId()), message, std::move(data)); } } } @@ -1527,7 +1530,7 @@ void UniverseServer::packetsReceived(UniverseConnectionServer*, ConnectionId cli } else if (auto chatSend = as<ChatSendPacket>(packet)) { RecursiveMutexLocker locker(m_mainLock); - m_pendingChat[clientId].append({std::move(chatSend->text), chatSend->sendMode}); + m_pendingChat[clientId].append(make_tuple(std::move(chatSend->text), chatSend->sendMode, std::move(chatSend->data))); } else if (auto clientContextUpdatePacket = as<ClientContextUpdatePacket>(packet)) { clientContext->readUpdate(std::move(clientContextUpdatePacket->updateData)); diff --git a/source/game/StarUniverseServer.hpp b/source/game/StarUniverseServer.hpp index f3db6fc..ddf7d0c 100644 --- a/source/game/StarUniverseServer.hpp +++ b/source/game/StarUniverseServer.hpp @@ -254,7 +254,7 @@ private: HashMap<ConnectionId, String> m_pendingDisconnections; HashMap<ConnectionId, List<WorkerPoolPromise<CelestialResponse>>> m_pendingCelestialRequests; List<pair<WorldId, UniverseFlagAction>> m_pendingFlagActions; - HashMap<ConnectionId, List<pair<String, ChatSendMode>>> m_pendingChat; + HashMap<ConnectionId, List<tuple<String, ChatSendMode, JsonObject>>> m_pendingChat; Maybe<WorkerPoolPromise<CelestialCoordinate>> m_nextRandomizedStarterWorld; Map<WorldId, List<WorldServerThread::Message>> m_pendingWorldMessages; diff --git a/source/game/scripting/StarBehaviorLuaBindings.cpp b/source/game/scripting/StarBehaviorLuaBindings.cpp index 8866746..4bf16f2 100644 --- a/source/game/scripting/StarBehaviorLuaBindings.cpp +++ b/source/game/scripting/StarBehaviorLuaBindings.cpp @@ -4,7 +4,7 @@ namespace Star { -LuaCallbacks LuaBindings::makeBehaviorLuaCallbacks(List<BehaviorStatePtr>* list) { +LuaCallbacks LuaBindings::makeBehaviorCallbacks(List<BehaviorStatePtr>* list) { LuaCallbacks callbacks; callbacks.registerCallback("behavior", [list](Json const& config, JsonObject const& parameters, LuaTable context, Maybe<LuaUserData> blackboard) -> BehaviorStateWeakPtr { diff --git a/source/game/scripting/StarBehaviorLuaBindings.hpp b/source/game/scripting/StarBehaviorLuaBindings.hpp index d2a882b..01c04ab 100644 --- a/source/game/scripting/StarBehaviorLuaBindings.hpp +++ b/source/game/scripting/StarBehaviorLuaBindings.hpp @@ -9,6 +9,6 @@ STAR_CLASS(Root); STAR_CLASS(UniverseClient); namespace LuaBindings { - LuaCallbacks makeBehaviorLuaCallbacks(List<BehaviorStatePtr>* list); + LuaCallbacks makeBehaviorCallbacks(List<BehaviorStatePtr>* list); } } diff --git a/source/game/scripting/StarPlayerLuaBindings.cpp b/source/game/scripting/StarPlayerLuaBindings.cpp index 5af86d0..ea2bae5 100644..100755 --- a/source/game/scripting/StarPlayerLuaBindings.cpp +++ b/source/game/scripting/StarPlayerLuaBindings.cpp @@ -496,6 +496,10 @@ LuaCallbacks LuaBindings::makePlayerCallbacks(Player* player) { return QuestStateNames.getRight(player->questManager()->getQuest(questId)->state()); }); + callbacks.registerCallback("questObjectives", [player](String const& questId) -> Maybe<JsonArray> { + return player->questManager()->getQuest(questId)->objectiveList(); + }); + callbacks.registerCallback("callQuest", [player](String const& questId, String const& func, LuaVariadic<LuaValue> const& args) -> Maybe<LuaValue> { if (!player->questManager()->hasQuest(questId)) return {}; @@ -522,8 +526,11 @@ LuaCallbacks LuaBindings::makePlayerCallbacks(Player* player) { return player->questManager()->trackedQuestId(); }); - callbacks.registerCallback("setTrackedQuest", [player](Maybe<String> const& questId) { - return player->questManager()->setAsTracked(questId); + callbacks.registerCallback("setTrackedQuest", [player](String const& questId) { + if (!player->questManager()->isCurrent(questId)) + return player->questManager()->setAsTracked(questId); + else + return player->questManager()->setAsTracked({}); }); callbacks.registerCallback("canTurnInQuest", [player](String const& questId) { diff --git a/source/game/scripting/StarRootLuaBindings.cpp b/source/game/scripting/StarRootLuaBindings.cpp index c45ef46..4e60595 100644 --- a/source/game/scripting/StarRootLuaBindings.cpp +++ b/source/game/scripting/StarRootLuaBindings.cpp @@ -66,13 +66,12 @@ LuaCallbacks LuaBindings::makeRootCallbacks() { callbacks.registerCallbackWithSignature<Maybe<String>, String, Maybe<String>>("materialMiningSound", bind(RootCallbacks::materialMiningSound, root, _1, _2)); callbacks.registerCallbackWithSignature<Maybe<String>, String, Maybe<String>>("materialFootstepSound", bind(RootCallbacks::materialFootstepSound, root, _1, _2)); - callbacks.registerCallback("assetsByExtension", [root](LuaEngine& engine, String const& extension) -> LuaTable { - auto& extensions = root->assets()->scanExtension(extension); - auto table = engine.createTable(extensions.size(), 0); - size_t i = 0; - for (auto& file : extensions) - table.set(++i, file); - return table; + callbacks.registerCallback("assetsByExtension", [root](String const& extension) -> CaseInsensitiveStringSet { + return root->assets()->scanExtension(extension); + }); + + callbacks.registerCallback("assetsScan", [root]( Maybe<String> const& a, Maybe<String> const& b) -> StringList { + return b ? root->assets()->scan(a.value(), *b) : root->assets()->scan(a.value()); }); callbacks.registerCallback("assetOrigin", [root](String const& path) -> Maybe<String> { @@ -116,12 +115,12 @@ LuaCallbacks LuaBindings::makeRootCallbacks() { return table; }); - callbacks.registerCallback("assetSourceMetadata", [root](LuaEngine& engine, String const& assetSourcePath) { + callbacks.registerCallback("assetSourceMetadata", [root](String const& assetSourcePath) { auto assets = root->assets(); return assets->assetSourceMetadata(assetSourcePath); }); - callbacks.registerCallback("itemFile", [root](LuaEngine& engine, String const& itemName) -> Maybe<String> { + callbacks.registerCallback("itemFile", [root](String const& itemName) -> Maybe<String> { return root->itemDatabase()->itemFile(itemName); }); diff --git a/source/game/scripting/StarScriptableThread.cpp b/source/game/scripting/StarScriptableThread.cpp index cbd32ad..6bbfece 100644 --- a/source/game/scripting/StarScriptableThread.cpp +++ b/source/game/scripting/StarScriptableThread.cpp @@ -14,9 +14,9 @@ namespace Star { ScriptableThread::ScriptableThread(Json parameters) : Thread("ScriptableThread: " + parameters.getString("name")), // TODO m_stop(false), + m_parameters(std::move(parameters)), m_errorOccurred(false), - m_shouldExpire(true), - m_parameters(std::move(parameters)) { + m_shouldExpire(true) { m_luaRoot = make_shared<LuaRoot>(); m_name = m_parameters.getString("name"); @@ -78,8 +78,6 @@ void ScriptableThread::passMessage(Message&& message) { void ScriptableThread::run() { try { - auto& root = Root::singleton(); - double updateMeasureWindow = m_parameters.getDouble("updateMeasureWindow",0.5); TickRateApproacher tickApproacher(1.0f / m_timestep, updateMeasureWindow); diff --git a/source/game/scripting/StarSongbookLuaBindings.cpp b/source/game/scripting/StarSongbookLuaBindings.cpp new file mode 100644 index 0000000..7831ed6 --- /dev/null +++ b/source/game/scripting/StarSongbookLuaBindings.cpp @@ -0,0 +1,21 @@ +#include "StarSongbookLuaBindings.hpp" +#include "StarLuaConverters.hpp" + +namespace Star { + +LuaCallbacks LuaBindings::makeSongbookCallbacks(Songbook* songbook) { + LuaCallbacks callbacks; + + callbacks.registerCallbackWithSignature<void, Json, String>("play", bind(mem_fn(&Songbook::play), songbook, _1, _2)); + callbacks.registerCallbackWithSignature<void, String, Vec2F>("keepAlive", bind(mem_fn(&Songbook::keepAlive), songbook, _1, _2)); + callbacks.registerCallbackWithSignature<void>("stop", bind(mem_fn(&Songbook::stop), songbook)); + callbacks.registerCallbackWithSignature<bool>("active", bind(mem_fn(&Songbook::active), songbook)); + callbacks.registerCallbackWithSignature<Maybe<String>>("band", bind(mem_fn(&Songbook::timeSource), songbook)); + callbacks.registerCallbackWithSignature<Maybe<String>>("instrument", bind(mem_fn(&Songbook::instrument), songbook)); + callbacks.registerCallbackWithSignature<bool>("instrumentPlaying", bind(mem_fn(&Songbook::instrumentPlaying), songbook)); + callbacks.registerCallbackWithSignature<Json>("song", bind(mem_fn(&Songbook::song), songbook)); + + return callbacks; +} + +} diff --git a/source/game/scripting/StarSongbookLuaBindings.hpp b/source/game/scripting/StarSongbookLuaBindings.hpp new file mode 100644 index 0000000..cc55ec6 --- /dev/null +++ b/source/game/scripting/StarSongbookLuaBindings.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include "StarLua.hpp" +#include "StarSongbook.hpp" + +namespace Star { + +namespace LuaBindings { + LuaCallbacks makeSongbookCallbacks(Songbook* songbook); +} +} |