From 830d4deb7b020ef754d09718e351ae3c29a6dd0a Mon Sep 17 00:00:00 2001 From: Kae <80987908+Novaenia@users.noreply.github.com> Date: Mon, 31 Jul 2023 16:00:19 +1000 Subject: [PATCH] Tile placement improvements Placing materials is now done in a line to fix gaps at low framerates --- .../items/defaultParameters.config.patch | 3 + source/game/StarWorldClient.cpp | 23 +++++--- source/game/items/StarMaterialItem.cpp | 56 +++++++++++++++---- source/game/items/StarMaterialItem.hpp | 2 + 4 files changed, 64 insertions(+), 20 deletions(-) create mode 100644 assets/opensb/items/defaultParameters.config.patch diff --git a/assets/opensb/items/defaultParameters.config.patch b/assets/opensb/items/defaultParameters.config.patch new file mode 100644 index 0000000..b63aae1 --- /dev/null +++ b/assets/opensb/items/defaultParameters.config.patch @@ -0,0 +1,3 @@ +{ + "materialItems" : { "cooldown" : 0 } // tile prediction makes a cooldown pointless +} \ No newline at end of file diff --git a/source/game/StarWorldClient.cpp b/source/game/StarWorldClient.cpp index cc7a056..25e5ae7 100644 --- a/source/game/StarWorldClient.cpp +++ b/source/game/StarWorldClient.cpp @@ -321,17 +321,24 @@ TileModificationList WorldClient::validTileModifications(TileModificationList co TileModificationList WorldClient::applyTileModifications(TileModificationList const& modificationList, bool allowEntityOverlap) { if (!inWorld()) return {}; + + auto extraCheck = [this](Vec2I pos, TileModification) { + return !isTileProtected(pos); + }; - auto result = WorldImpl::splitTileModifications(m_entityMap, modificationList, allowEntityOverlap, m_tileGetterFunction, [this](Vec2I pos, TileModification) { - return !isTileProtected(pos); - }); + // thanks to new prediction: do it aggressively until no changes occur + auto result = WorldImpl::splitTileModifications(m_entityMap, modificationList, allowEntityOverlap, m_tileGetterFunction, extraCheck); + while (true) { + if (!result.first.empty()) { + informTilePredictions(result.first); + m_outgoingPackets.append(make_shared(result.first, true)); - if (!result.first.empty()) { - informTilePredictions(result.first); - m_outgoingPackets.append(make_shared(result.first, true)); + auto list = move(result.second); + result = WorldImpl::splitTileModifications(m_entityMap, list, allowEntityOverlap, m_tileGetterFunction, extraCheck); + } + else + return result.second; } - - return result.second; } float WorldClient::gravity(Vec2F const& pos) const { diff --git a/source/game/items/StarMaterialItem.cpp b/source/game/items/StarMaterialItem.cpp index 48b5c57..1cc1502 100644 --- a/source/game/items/StarMaterialItem.cpp +++ b/source/game/items/StarMaterialItem.cpp @@ -27,9 +27,10 @@ MaterialItem::MaterialItem(Json const& config, String const& directory, Json con setTwoHanded(config.getBool("twoHanded", true)); - setCooldownTime(Root::singleton().assets()->json("/items/defaultParameters.config:materialItems.cooldown").toFloat()); - m_blockRadius = Root::singleton().assets()->json("/items/defaultParameters.config:blockRadius").toFloat(); - m_altBlockRadius = Root::singleton().assets()->json("/items/defaultParameters.config:altBlockRadius").toFloat(); + auto defaultParameters = Root::singleton().assets()->json("/items/defaultParameters.config"); + setCooldownTime(config.queryFloat("materialItems.cooldown", defaultParameters.queryFloat("materialItems.cooldown"))); + m_blockRadius = config.getFloat("blockRadius", defaultParameters.getFloat("blockRadius")); + m_altBlockRadius = config.getFloat("altBlockRadius", defaultParameters.getFloat("altBlockRadius")); m_multiplace = config.getBool("allowMultiplace", BlockCollisionSet.contains(Root::singleton().materialDatabase()->materialCollisionKind(m_material))); m_shifting = false; @@ -75,17 +76,48 @@ void MaterialItem::fire(FireMode mode, bool shifting, bool edgeTriggered) { if (!multiplaceEnabled()) radius = 1; - for (auto pos : tileAreaBrush(radius, owner()->aimPosition(), true)) - modifications.append({pos, PlaceMaterial{layer, materialId(), placementHueShift(pos)}}); + auto geo = world()->geometry(); + auto aimPosition = owner()->aimPosition(); + if (!m_lastAimPosition) + m_lastAimPosition = aimPosition; - // Make sure not to make any more modifications than we have consumables. - if (modifications.size() > count()) - modifications.resize(count()); - size_t failed = world()->applyTileModifications(modifications, false).size(); - if (failed < modifications.size()) { - FireableItem::fire(mode, shifting, edgeTriggered); - consume(modifications.size() - failed); + unsigned steps = 1; + Vec2F diff = {}; + if (*m_lastAimPosition != aimPosition) { + diff = geo.diff(*m_lastAimPosition, aimPosition); + float magnitude = diff.magnitude(); + if (magnitude > 32) { + m_lastAimPosition = aimPosition + diff.normalized() * 32; + magnitude = 32; + } + + steps = (int)ceil(magnitude); } + + bool fail = true; + for (int i = 0; i != steps; ++i) { + auto placementOrigin = aimPosition + diff * ((float)i / steps); + for (Vec2I pos : tileAreaBrush(radius, placementOrigin, true)) + modifications.append({ pos, PlaceMaterial{layer, materialId(), placementHueShift(pos)} }); + + // Make sure not to make any more modifications than we have consumables. + if (modifications.size() > count()) + modifications.resize(count()); + size_t failed = world()->applyTileModifications(modifications, false).size(); + if (failed < modifications.size()) { + fail = false; + consume(modifications.size() - failed); + } + } + + if (!fail) + FireableItem::fire(mode, shifting, edgeTriggered); + + m_lastAimPosition = aimPosition; +} + +void MaterialItem::endFire(FireMode mode, bool shifting) { + m_lastAimPosition.reset(); } MaterialId MaterialItem::materialId() const { diff --git a/source/game/items/StarMaterialItem.hpp b/source/game/items/StarMaterialItem.hpp index ed92896..5f27531 100644 --- a/source/game/items/StarMaterialItem.hpp +++ b/source/game/items/StarMaterialItem.hpp @@ -23,6 +23,7 @@ public: List nonRotatedDrawables() const override; void fire(FireMode mode, bool shifting, bool edgeTriggered) override; + void endFire(FireMode mode, bool shifting) override; MaterialId materialId() const; MaterialHue materialHueShift() const; @@ -43,6 +44,7 @@ private: float m_altBlockRadius; bool m_shifting; bool m_multiplace; + Maybe m_lastAimPosition; }; }