Tile placement improvements

Placing materials is now done in a line to fix gaps at low framerates
This commit is contained in:
Kae 2023-07-31 16:00:19 +10:00
parent df83b02f1d
commit 830d4deb7b
4 changed files with 64 additions and 20 deletions

View File

@ -0,0 +1,3 @@
{
"materialItems" : { "cooldown" : 0 } // tile prediction makes a cooldown pointless
}

View File

@ -322,17 +322,24 @@ TileModificationList WorldClient::applyTileModifications(TileModificationList co
if (!inWorld()) if (!inWorld())
return {}; return {};
auto result = WorldImpl::splitTileModifications(m_entityMap, modificationList, allowEntityOverlap, m_tileGetterFunction, [this](Vec2I pos, TileModification) { auto extraCheck = [this](Vec2I pos, TileModification) {
return !isTileProtected(pos); 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()) { if (!result.first.empty()) {
informTilePredictions(result.first); informTilePredictions(result.first);
m_outgoingPackets.append(make_shared<ModifyTileListPacket>(result.first, true)); m_outgoingPackets.append(make_shared<ModifyTileListPacket>(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 { float WorldClient::gravity(Vec2F const& pos) const {
if (!inWorld()) if (!inWorld())

View File

@ -27,9 +27,10 @@ MaterialItem::MaterialItem(Json const& config, String const& directory, Json con
setTwoHanded(config.getBool("twoHanded", true)); setTwoHanded(config.getBool("twoHanded", true));
setCooldownTime(Root::singleton().assets()->json("/items/defaultParameters.config:materialItems.cooldown").toFloat()); auto defaultParameters = Root::singleton().assets()->json("/items/defaultParameters.config");
m_blockRadius = Root::singleton().assets()->json("/items/defaultParameters.config:blockRadius").toFloat(); setCooldownTime(config.queryFloat("materialItems.cooldown", defaultParameters.queryFloat("materialItems.cooldown")));
m_altBlockRadius = Root::singleton().assets()->json("/items/defaultParameters.config:altBlockRadius").toFloat(); 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_multiplace = config.getBool("allowMultiplace", BlockCollisionSet.contains(Root::singleton().materialDatabase()->materialCollisionKind(m_material)));
m_shifting = false; m_shifting = false;
@ -75,7 +76,28 @@ void MaterialItem::fire(FireMode mode, bool shifting, bool edgeTriggered) {
if (!multiplaceEnabled()) if (!multiplaceEnabled())
radius = 1; radius = 1;
for (auto pos : tileAreaBrush(radius, owner()->aimPosition(), true)) auto geo = world()->geometry();
auto aimPosition = owner()->aimPosition();
if (!m_lastAimPosition)
m_lastAimPosition = aimPosition;
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)} }); modifications.append({ pos, PlaceMaterial{layer, materialId(), placementHueShift(pos)} });
// Make sure not to make any more modifications than we have consumables. // Make sure not to make any more modifications than we have consumables.
@ -83,11 +105,21 @@ void MaterialItem::fire(FireMode mode, bool shifting, bool edgeTriggered) {
modifications.resize(count()); modifications.resize(count());
size_t failed = world()->applyTileModifications(modifications, false).size(); size_t failed = world()->applyTileModifications(modifications, false).size();
if (failed < modifications.size()) { if (failed < modifications.size()) {
FireableItem::fire(mode, shifting, edgeTriggered); fail = false;
consume(modifications.size() - failed); 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 { MaterialId MaterialItem::materialId() const {
return m_material; return m_material;
} }

View File

@ -23,6 +23,7 @@ public:
List<Drawable> nonRotatedDrawables() const override; List<Drawable> nonRotatedDrawables() const override;
void fire(FireMode mode, bool shifting, bool edgeTriggered) override; void fire(FireMode mode, bool shifting, bool edgeTriggered) override;
void endFire(FireMode mode, bool shifting) override;
MaterialId materialId() const; MaterialId materialId() const;
MaterialHue materialHueShift() const; MaterialHue materialHueShift() const;
@ -43,6 +44,7 @@ private:
float m_altBlockRadius; float m_altBlockRadius;
bool m_shifting; bool m_shifting;
bool m_multiplace; bool m_multiplace;
Maybe<Vec2F> m_lastAimPosition;
}; };
} }