diff options
author | Vladimir Krasheninnikov <boba09@list.ru> | 2025-03-16 12:49:29 +0100 |
---|---|---|
committer | Vladimir Krasheninnikov <boba09@list.ru> | 2025-03-16 12:49:29 +0100 |
commit | e8309c463d58b2ff8aab2e14a5b1e5f5065cecda (patch) | |
tree | 005e6a4915092ff9c9e861638ae9c076cf9077ed | |
parent | 76d4ddd57c65269052c4784e5ffa94bfb574c6ba (diff) | |
parent | 6f51c2c129ab50872a4944e5218fcf97f89abb1d (diff) |
Merge branch 'main' of https://github.com/KrashV/OpenStarbound
-rw-r--r-- | doc/lua/openstarbound/root.md | 4 | ||||
-rw-r--r-- | source/CMakeLists.txt | 4 | ||||
-rw-r--r-- | source/game/StarArmorWearer.cpp | 2 | ||||
-rw-r--r-- | source/game/StarHumanoid.cpp | 112 | ||||
-rw-r--r-- | source/game/StarHumanoid.hpp | 9 | ||||
-rw-r--r-- | source/game/StarPlayerStorage.cpp | 13 | ||||
-rw-r--r-- | source/game/scripting/StarRootLuaBindings.cpp | 5 |
7 files changed, 110 insertions, 39 deletions
diff --git a/doc/lua/openstarbound/root.md b/doc/lua/openstarbound/root.md index e87a0fe..1009c8f 100644 --- a/doc/lua/openstarbound/root.md +++ b/doc/lua/openstarbound/root.md @@ -61,6 +61,10 @@ Returns the asset source path of an asset, or nil if the asset doesn't exist. If Without metadata: Returns an array with all the asset source paths. With metadata: Returns a table, key/value being source path/metadata. +#### `Json` root.assetSourceMetadata(`String` path) + +Returns the metadata of an asset source. + #### `Image` root.assetImage(`String` image) Returns an image. diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 131c6ad..98b9c6c 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -297,8 +297,8 @@ if(STAR_COMPILER_GNU) set(CMAKE_SKIP_BUILD_RPATH TRUE) elseif(STAR_COMPILER_CLANG) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wuninitialized -Wno-parentheses-equality -Wno-deprecated-declarations") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -Wall -Wextra -Wuninitialized -Wno-parentheses-equality -Wno-deprecated-declarations") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wuninitialized -Wno-parentheses-equality -Wno-deprecated-declarations -Wno-nan-infinity-disabled") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -Wall -Wextra -Wuninitialized -Wno-parentheses-equality -Wno-deprecated-declarations -Wno-nan-infinity-disabled") if(STAR_SYSTEM_MACOS) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") diff --git a/source/game/StarArmorWearer.cpp b/source/game/StarArmorWearer.cpp index c95eaad..ef67686 100644 --- a/source/game/StarArmorWearer.cpp +++ b/source/game/StarArmorWearer.cpp @@ -100,10 +100,12 @@ void ArmorWearer::setupHumanoidClothingDrawables(Humanoid& humanoid, bool forceN if (backNeedsSync) { humanoid.setBackArmorFrameset(backArmor->frameset(humanoid.identity().gender)); humanoid.setBackArmorDirectives(backArmor->directives()); + humanoid.setBackRotatesWithHead(backArmor->instanceValue("rotateWithHead", false).optBool().value()); } bodyHidden = bodyHidden || backArmor->hideBody(); } else { humanoid.setBackArmorFrameset(""); + humanoid.setBackRotatesWithHead(false); } if (chestNeedsSync || legsNeedsSync) { diff --git a/source/game/StarHumanoid.cpp b/source/game/StarHumanoid.cpp index f3ac164..b56c432 100644 --- a/source/game/StarHumanoid.cpp +++ b/source/game/StarHumanoid.cpp @@ -258,6 +258,7 @@ Humanoid::Humanoid(Json const& config) { m_primaryHand.holdingItem = false; m_altHand.holdingItem = false; + m_backRotatesWithHead = false; m_movingBackwards = false; m_altHand.angle = 0; m_facingDirection = Direction::Left; @@ -288,6 +289,12 @@ void Humanoid::setIdentity(HumanoidIdentity const& identity) { m_backArmFrameset = getBackArmFromIdentity(); m_frontArmFrameset = getFrontArmFromIdentity(); m_vaporTrailFrameset = getVaporTrailFrameset(); + if (m_useBodyMask) { + m_bodyMaskFrameset = getBodyMaskFromIdentity(); + } + if (m_useBodyHeadMask) { + m_bodyHeadMaskFrameset = getBodyHeadMaskFromIdentity(); + } } HumanoidIdentity const& Humanoid::identity() const { @@ -317,6 +324,8 @@ void Humanoid::loadConfig(Json merger) { m_feetOffset = jsonToVec2F(config.get("feetOffset")) / TilePixels; m_bodyFullbright = config.getBool("bodyFullbright", false); + m_useBodyMask = config.getBool("useBodyMask", false); + m_useBodyHeadMask = config.getBool("useBodyHeadMask", false); m_headArmorOffset = jsonToVec2F(config.get("headArmorOffset")) / TilePixels; m_chestArmorOffset = jsonToVec2F(config.get("chestArmorOffset")) / TilePixels; @@ -470,6 +479,10 @@ void Humanoid::setHeadRotation(float headRotation) { m_headRotationTarget = headRotation; } +void Humanoid::setBackRotatesWithHead(bool backRotatesWithHead) { + m_backRotatesWithHead = backRotatesWithHead; +} + void Humanoid::setRotation(float rotation) { m_rotation = rotation; } @@ -606,11 +619,12 @@ List<Drawable> Humanoid::render(bool withItems, bool withRotationAndScale) { if (backHand.recoil) backArmFrameOffset += m_recoilOffset; - auto addDrawable = [&](Drawable drawable, bool forceFullbright = false) { + auto addDrawable = [&](Drawable drawable, bool forceFullbright = false) -> Drawable& { if (m_facingDirection == Direction::Left) drawable.scale(Vec2F(-1, 1)); drawable.fullbright |= forceFullbright; drawables.append(std::move(drawable)); + return drawables.back(); }; auto backArmDrawable = [&](String const& frameSet, Directives const& directives) -> Drawable { @@ -621,6 +635,35 @@ List<Drawable> Humanoid::render(bool withItems, bool withRotationAndScale) { return backArm; }; + Vec2F headPosition(0, bobYOffset); + if (dance.isValid()) + headPosition += danceStep->headOffset / TilePixels; + else if (m_state == Idle) + headPosition += m_identity.personality.headOffset / TilePixels; + else if (m_state == Run) + headPosition += m_headRunOffset; + else if (m_state == Swim || m_state == SwimIdle) + headPosition += m_headSwimOffset; + else if (m_state == Duck) + headPosition += m_headDuckOffset; + else if (m_state == Sit) + headPosition += m_headSitOffset; + else if (m_state == Lay) + headPosition += m_headLayOffset; + + auto applyHeadRotation = [&](Drawable& drawable) { + if (m_headRotation != 0.f) { + float dir = numericalDirection(m_facingDirection); + Vec2F rotationPoint = headPosition; + rotationPoint[0] *= dir; + rotationPoint[1] -= .25f; + float headX = (m_headRotation / ((float)Constants::pi * 2.f)); + drawable.rotate(m_headRotation, rotationPoint); + drawable.position[0] -= state() == State::Run ? (fmaxf(headX * dir, 0.f) * 2.f) * dir : headX; + drawable.position[1] -= fabsf(m_headRotation / ((float)Constants::pi * 4.f)); + } + }; + if (!m_backArmorFrameset.empty()) { auto frameGroup = frameBase(m_state); auto prefix = m_backArmorDirectives.prefix(); @@ -636,7 +679,9 @@ List<Drawable> Humanoid::render(bool withItems, bool withRotationAndScale) { auto drawable = Drawable::makeImage(std::move(image), 1.0f / TilePixels, true, Vec2F()); drawable.imagePart().addDirectives(getBackDirectives(), true); - addDrawable(std::move(drawable)); + Drawable& applied = addDrawable(std::move(drawable)); + if (m_backRotatesWithHead) + applyHeadRotation(applied); } if (backHand.holdingItem && !dance.isValid() && withItems) { @@ -695,36 +740,11 @@ List<Drawable> Humanoid::render(bool withItems, bool withRotationAndScale) { } } - Vec2F headPosition(0, bobYOffset); - if (dance.isValid()) - headPosition += danceStep->headOffset / TilePixels; - else if (m_state == Idle) - headPosition += m_identity.personality.headOffset / TilePixels; - else if (m_state == Run) - headPosition += m_headRunOffset; - else if (m_state == Swim || m_state == SwimIdle) - headPosition += m_headSwimOffset; - else if (m_state == Duck) - headPosition += m_headDuckOffset; - else if (m_state == Sit) - headPosition += m_headSitOffset; - else if (m_state == Lay) - headPosition += m_headLayOffset; - auto addHeadDrawable = [&](Drawable drawable, bool forceFullbright = false) { if (m_facingDirection == Direction::Left) drawable.scale(Vec2F(-1, 1)); drawable.fullbright |= forceFullbright; - if (m_headRotation != 0.f) { - float dir = numericalDirection(m_facingDirection); - Vec2F rotationPoint = headPosition; - rotationPoint[0] *= dir; - rotationPoint[1] -= .25f; - float headX = (m_headRotation / ((float)Constants::pi * 2.f)); - drawable.rotate(m_headRotation, rotationPoint); - drawable.position[0] -= state() == State::Run ? (fmaxf(headX * dir, 0.f) * 2.f) * dir : headX; - drawable.position[1] -= fabsf(m_headRotation / ((float)Constants::pi * 4.f)); - } + applyHeadRotation(drawable); drawables.append(std::move(drawable)); }; @@ -751,18 +771,32 @@ List<Drawable> Humanoid::render(bool withItems, bool withRotationAndScale) { } if (!m_bodyFrameset.empty() && !m_bodyHidden) { - String image; auto bodyDirectives = getBodyDirectives(); auto prefix = bodyDirectives.prefix(); + String frameName; if (dance.isValid() && danceStep->bodyFrame) - image = strf("{}:{}{}", m_bodyFrameset, *danceStep->bodyFrame, prefix); + frameName = strf("{}{}", *danceStep->bodyFrame, prefix); else if (m_state == Idle) - image = strf("{}:{}{}", m_bodyFrameset, m_identity.personality.idle, prefix); + frameName = strf("{}{}", m_identity.personality.idle, prefix); else - image = strf("{}:{}.{}{}", m_bodyFrameset, frameBase(m_state), bodyStateSeq, prefix); - auto drawable = Drawable::makeImage(std::move(image), 1.0f / TilePixels, true, {}); + frameName = strf("{}.{}{}", frameBase(m_state), bodyStateSeq, prefix); + String image = strf("{}:{}",m_bodyFrameset,frameName); + auto drawable = Drawable::makeImage(m_useBodyHeadMask ? image : std::move(image), 1.0f / TilePixels, true, {}); drawable.imagePart().addDirectives(bodyDirectives, true); + if (m_useBodyMask && !m_bodyMaskFrameset.empty()) { + String maskImage = strf("{}:{}",m_bodyMaskFrameset,frameName); + Directives maskDirectives = "?addmask="+maskImage+";0;0"; + drawable.imagePart().addDirectives(maskDirectives, true); + } addDrawable(std::move(drawable), m_bodyFullbright); + if (m_useBodyHeadMask && !m_bodyHeadMaskFrameset.empty()) { + String maskImage = strf("{}:{}",m_bodyHeadMaskFrameset,frameName); + Directives maskDirectives = "?addmask="+maskImage+";0;0"; + auto drawable = Drawable::makeImage(std::move(image), 1.0f / TilePixels, true, {}); + drawable.imagePart().addDirectives(bodyDirectives, true); + drawable.imagePart().addDirectives(maskDirectives, true); + addHeadDrawable(std::move(drawable), m_bodyFullbright); + } } if (!m_legsArmorFrameset.empty()) { @@ -1275,6 +1309,18 @@ String Humanoid::getBodyFromIdentity() const { GenderNames.getRight(m_identity.gender)); } +String Humanoid::getBodyMaskFromIdentity() const { + return strf("/humanoid/{}/mask/{}body.png", + m_identity.imagePath ? *m_identity.imagePath : m_identity.species, + GenderNames.getRight(m_identity.gender)); +} + +String Humanoid::getBodyHeadMaskFromIdentity() const { + return strf("/humanoid/{}/headmask/{}body.png", + m_identity.imagePath ? *m_identity.imagePath : m_identity.species, + GenderNames.getRight(m_identity.gender)); +} + String Humanoid::getFacialEmotesFromIdentity() const { return strf("/humanoid/{}/emote.png", m_identity.imagePath ? *m_identity.imagePath : m_identity.species); } diff --git a/source/game/StarHumanoid.hpp b/source/game/StarHumanoid.hpp index d11de1d..a3e9d19 100644 --- a/source/game/StarHumanoid.hpp +++ b/source/game/StarHumanoid.hpp @@ -178,6 +178,7 @@ public: void setFacingDirection(Direction facingDirection); void setMovingBackwards(bool movingBackwards); void setHeadRotation(float headRotation); + void setBackRotatesWithHead(bool backRotatesWithHead); void setRotation(float rotation); void setScale(Vec2F scale); @@ -262,6 +263,8 @@ public: String getHeadFromIdentity() const; String getBodyFromIdentity() const; + String getBodyMaskFromIdentity() const; + String getBodyHeadMaskFromIdentity() const; String getFacialEmotesFromIdentity() const; String getHairFromIdentity() const; String getFacialHairFromIdentity() const; @@ -329,6 +332,9 @@ private: Vec2F m_chestArmorOffset; Vec2F m_legsArmorOffset; Vec2F m_backArmorOffset; + + bool m_useBodyMask; + bool m_useBodyHeadMask; bool m_bodyHidden; @@ -345,6 +351,8 @@ private: String m_headFrameset; String m_bodyFrameset; + String m_bodyMaskFrameset; + String m_bodyHeadMaskFrameset; String m_backArmFrameset; String m_frontArmFrameset; String m_emoteFrameset; @@ -375,6 +383,7 @@ private: Maybe<String> m_dance; Direction m_facingDirection; bool m_movingBackwards; + bool m_backRotatesWithHead; float m_headRotation; float m_headRotationTarget; float m_rotation; diff --git a/source/game/StarPlayerStorage.cpp b/source/game/StarPlayerStorage.cpp index bba080e..7687e97 100644 --- a/source/game/StarPlayerStorage.cpp +++ b/source/game/StarPlayerStorage.cpp @@ -41,9 +41,12 @@ PlayerStorage::PlayerStorage(String const& storageDir) { try { auto json = VersionedJson::readFile(filename); Uuid uuid(json.content.getString("uuid")); - auto& playerCacheData = m_savedPlayersCache[uuid]; - playerCacheData = entityFactory->loadVersionedJson(json, EntityType::Player); - m_playerFileNames.insert(uuid, file.first.rsplit('.', 1).at(0)); + if (m_playerFileNames.insert(uuid, file.first.rsplit('.', 1).at(0))) { + auto& playerCacheData = m_savedPlayersCache[uuid]; + playerCacheData = entityFactory->loadVersionedJson(json, EntityType::Player); + } else { + Logger::warn("Duplicate player? Skipping player file {} because it has the same UUID as {}.player ({})", file.first, m_playerFileNames.getRight(uuid), uuid.hex()); + } } catch (std::exception const& e) { Logger::error("Error loading player file, ignoring! {} : {}", filename, outputException(e, false)); } @@ -168,7 +171,9 @@ Json PlayerStorage::savePlayer(PlayerPtr const& player) { if (playerCacheData != newPlayerData) { playerCacheData = newPlayerData; VersionedJson versionedJson = entityFactory->storeVersionedJson(EntityType::Player, playerCacheData); - VersionedJson::writeFile(versionedJson, File::relativeTo(m_storageDirectory, strf("{}.player", uuidFileName(uuid)))); + auto fileName = strf("{}.player", uuidFileName(uuid)); + VersionedJson::writeFile(versionedJson, File::relativeTo(m_storageDirectory, fileName)); + Logger::info("Saved player {} to {}", Text::stripEscapeCodes(player->name()), fileName); } return newPlayerData; } diff --git a/source/game/scripting/StarRootLuaBindings.cpp b/source/game/scripting/StarRootLuaBindings.cpp index b7c9a74..c45ef46 100644 --- a/source/game/scripting/StarRootLuaBindings.cpp +++ b/source/game/scripting/StarRootLuaBindings.cpp @@ -116,6 +116,11 @@ LuaCallbacks LuaBindings::makeRootCallbacks() { return table; }); + callbacks.registerCallback("assetSourceMetadata", [root](LuaEngine& engine, String const& assetSourcePath) { + auto assets = root->assets(); + return assets->assetSourceMetadata(assetSourcePath); + }); + callbacks.registerCallback("itemFile", [root](LuaEngine& engine, String const& itemName) -> Maybe<String> { return root->itemDatabase()->itemFile(itemName); }); |