| 1124 | } |
| 1125 | |
| 1126 | void WorldClient::update(float dt) { |
| 1127 | if (!inWorld()) |
| 1128 | return; |
| 1129 | |
| 1130 | auto assets = Root::singleton().assets(); |
| 1131 | |
| 1132 | float expireTime = min(float(m_latency + 800), 2000.f); |
| 1133 | auto now = Time::monotonicMilliseconds(); |
| 1134 | eraseWhere(m_predictedTiles, [&](auto& pair) { |
| 1135 | float expiry = (float)(now - pair.second.time) / expireTime; |
| 1136 | auto center = Vec2F(pair.first) + Vec2F::filled(0.5f); |
| 1137 | auto size = Vec2F::filled(0.875f - expiry * 0.875f); |
| 1138 | auto poly = PolyF(RectF::withCenter(center, size)); |
| 1139 | SpatialLogger::logPoly("world", poly, Color::Cyan.mix(Color::Red, expiry).toRgba()); |
| 1140 | if (expiry >= 1.0f) { |
| 1141 | dirtyCollision(RectI::withSize(pair.first, { 1, 1 })); |
| 1142 | return true; |
| 1143 | } else { |
| 1144 | return false; |
| 1145 | } |
| 1146 | }); |
| 1147 | |
| 1148 | // Secret broadcasts are transmitted through DamageNotifications for vanilla server compatibility. |
| 1149 | // Because DamageNotification packets are spoofable, we have to sign the data so other clients can validate that it is legitimate. |
| 1150 | auto& publicKey = Curve25519::publicKey(); |
| 1151 | String publicKeyString((const char*)publicKey.data(), publicKey.size()); |
| 1152 | m_mainPlayer->setSecretProperty(SECRET_BROADCAST_PUBLIC_KEY, publicKeyString); |
| 1153 | // Temporary: Backwards compatibility with StarExtensions |
| 1154 | m_mainPlayer->effectsAnimator()->setGlobalTag("\0SE_VOICE_SIGNING_KEY"s, publicKeyString); |
| 1155 | |
| 1156 | ++m_currentStep; |
| 1157 | m_currentTime += dt; |
| 1158 | m_interpolationTracker.update(m_currentTime); |
| 1159 | |
| 1160 | List<WorldAction> triggeredActions; |
| 1161 | eraseWhere(m_timers, [&triggeredActions, dt](pair<float, WorldAction>& timer) { |
| 1162 | if ((timer.first -= dt) <= 0) { |
| 1163 | triggeredActions.append(timer.second); |
| 1164 | return true; |
| 1165 | } |
| 1166 | return false; |
| 1167 | }); |
| 1168 | |
| 1169 | for (auto const& action : triggeredActions) |
| 1170 | action(this); |
| 1171 | |
| 1172 | List<EntityId> toRemove; |
| 1173 | List<EntityId> clientPresenceEntities; |
| 1174 | m_entityMap->updateAllEntities([&](EntityPtr const& entity) { |
| 1175 | try { entity->update(dt, m_currentStep); } |
| 1176 | catch (StarException const& e) { |
| 1177 | if (entity->isMaster()) // this is YOUR problem!! |
| 1178 | throw e; |
| 1179 | else // this is THEIR problem!! |
| 1180 | Logger::error("WorldClient: Exception caught in {}::update ({}): {}", EntityTypeNames.getRight(entity->entityType()), entity->entityId(), e.what()); |
| 1181 | } |
| 1182 | |
| 1183 | if (entity->shouldDestroy() && entity->entityMode() == EntityMode::Master) |
nothing calls this directly
no test coverage detected