Tile placement improvements
Placing materials is now done in a line to fix gaps at low framerates
This commit is contained in:
parent
df83b02f1d
commit
830d4deb7b
3
assets/opensb/items/defaultParameters.config.patch
Normal file
3
assets/opensb/items/defaultParameters.config.patch
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"materialItems" : { "cooldown" : 0 } // tile prediction makes a cooldown pointless
|
||||
}
|
@ -322,16 +322,23 @@ TileModificationList WorldClient::applyTileModifications(TileModificationList co
|
||||
if (!inWorld())
|
||||
return {};
|
||||
|
||||
auto result = WorldImpl::splitTileModifications(m_entityMap, modificationList, allowEntityOverlap, m_tileGetterFunction, [this](Vec2I pos, TileModification) {
|
||||
return !isTileProtected(pos);
|
||||
});
|
||||
auto extraCheck = [this](Vec2I pos, TileModification) {
|
||||
return !isTileProtected(pos);
|
||||
};
|
||||
|
||||
if (!result.first.empty()) {
|
||||
informTilePredictions(result.first);
|
||||
m_outgoingPackets.append(make_shared<ModifyTileListPacket>(result.first, true));
|
||||
// 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<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 {
|
||||
|
@ -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 {
|
||||
|
@ -23,6 +23,7 @@ public:
|
||||
List<Drawable> 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<Vec2F> m_lastAimPosition;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user