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,16 +322,23 @@ 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);
}); };
if (!result.first.empty()) { // thanks to new prediction: do it aggressively until no changes occur
informTilePredictions(result.first); auto result = WorldImpl::splitTileModifications(m_entityMap, modificationList, allowEntityOverlap, m_tileGetterFunction, extraCheck);
m_outgoingPackets.append(make_shared<ModifyTileListPacket>(result.first, true)); while (true) {
if (!result.first.empty()) {
informTilePredictions(result.first);
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 {

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,17 +76,48 @@ 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();
modifications.append({pos, PlaceMaterial{layer, materialId(), placementHueShift(pos)}}); auto aimPosition = owner()->aimPosition();
if (!m_lastAimPosition)
m_lastAimPosition = aimPosition;
// Make sure not to make any more modifications than we have consumables. unsigned steps = 1;
if (modifications.size() > count()) Vec2F diff = {};
modifications.resize(count()); if (*m_lastAimPosition != aimPosition) {
size_t failed = world()->applyTileModifications(modifications, false).size(); diff = geo.diff(*m_lastAimPosition, aimPosition);
if (failed < modifications.size()) { float magnitude = diff.magnitude();
FireableItem::fire(mode, shifting, edgeTriggered); if (magnitude > 32) {
consume(modifications.size() - failed); 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 { MaterialId MaterialItem::materialId() const {

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;
}; };
} }