4b0bc220e4
Context-specific (like per-world) timescales can also be added later
185 lines
5.9 KiB
C++
185 lines
5.9 KiB
C++
#include "StarSystemWorldClient.hpp"
|
|
#include "StarRoot.hpp"
|
|
#include "StarCelestialDatabase.hpp"
|
|
#include "StarClientContext.hpp"
|
|
#include "StarPlayerUniverseMap.hpp"
|
|
|
|
namespace Star {
|
|
|
|
SystemWorldClient::SystemWorldClient(ClockConstPtr universeClock, CelestialDatabasePtr celestialDatabase, PlayerUniverseMapPtr universeMap)
|
|
: SystemWorld(universeClock, celestialDatabase), m_universeMap(move(universeMap)) {}
|
|
|
|
CelestialCoordinate SystemWorldClient::currentSystem() const {
|
|
return CelestialCoordinate(m_location);
|
|
}
|
|
|
|
Maybe<Vec2F> SystemWorldClient::shipPosition() const {
|
|
if (m_ship)
|
|
return m_ship->position();
|
|
else
|
|
return {};
|
|
}
|
|
|
|
SystemLocation SystemWorldClient::shipLocation() const {
|
|
if (m_ship)
|
|
return m_ship->systemLocation();
|
|
else
|
|
return {};
|
|
}
|
|
|
|
SystemLocation SystemWorldClient::shipDestination() const {
|
|
if (m_ship)
|
|
return m_ship->destination();
|
|
else
|
|
return {};
|
|
}
|
|
|
|
// ship is flying if the system world is uninitialized or the ship doesn't have a location
|
|
bool SystemWorldClient::flying() const {
|
|
if (m_ship)
|
|
return m_ship->systemLocation().empty();
|
|
return true;
|
|
}
|
|
|
|
void SystemWorldClient::update(float dt) {
|
|
if (!m_ship)
|
|
return;
|
|
|
|
m_ship->clientUpdate(dt);
|
|
|
|
auto location = m_ship->systemLocation();
|
|
if (auto uuid = location.maybe<Uuid>()) {
|
|
if (auto object = getObject(*uuid)) {
|
|
Maybe<CelestialOrbit> orbit;
|
|
|
|
if (object->permanent())
|
|
m_universeMap->addMappedObject(CelestialCoordinate(m_location), *uuid, object->name(), object->orbit(), object->parameters());
|
|
else
|
|
m_universeMap->addMappedObject(CelestialCoordinate(m_location), *uuid, object->name());
|
|
}
|
|
} else if (auto coordinate = location.maybe<CelestialCoordinate>()) {
|
|
if (coordinate->isPlanetaryBody() || coordinate->isSatelliteBody())
|
|
m_universeMap->addMappedCoordinate(coordinate->planet());
|
|
} else if (auto orbit = location.maybe<CelestialOrbit>()) {
|
|
if (orbit->target.isPlanetaryBody() || orbit->target.isSatelliteBody())
|
|
m_universeMap->addMappedCoordinate(orbit->target.planet());
|
|
}
|
|
|
|
for (auto p : m_clientShips)
|
|
p.second->clientUpdate(dt);
|
|
for (auto p : m_objects)
|
|
p.second->clientUpdate(dt);
|
|
|
|
if (currentSystem().isNull()) {
|
|
m_objects.clear();
|
|
m_clientShips.clear();
|
|
m_ship = {};
|
|
m_location = Vec3I();
|
|
}
|
|
}
|
|
|
|
List<SystemObjectPtr> SystemWorldClient::objects() const {
|
|
return m_objects.values();
|
|
}
|
|
|
|
SystemObjectPtr SystemWorldClient::getObject(Uuid const& uuid) const {
|
|
return m_objects.maybe(uuid).value({});
|
|
}
|
|
|
|
List<SystemClientShipPtr> SystemWorldClient::ships() const
|
|
{
|
|
return m_clientShips.values();
|
|
}
|
|
|
|
SystemClientShipPtr SystemWorldClient::getShip(Uuid const & uuid) const
|
|
{
|
|
return m_clientShips.maybe(uuid).value({});
|
|
}
|
|
|
|
Uuid SystemWorldClient::spawnObject(String typeName, Maybe<Vec2F> position, Maybe<Uuid> const& uuid, JsonObject overrides) {
|
|
Uuid objectUuid = uuid.value(Uuid());
|
|
m_outgoingPackets.append(make_shared<SystemObjectSpawnPacket>(move(typeName), objectUuid, move(position), move(overrides)));
|
|
return objectUuid;
|
|
}
|
|
|
|
bool SystemWorldClient::handleIncomingPacket(PacketPtr packet) {
|
|
if (auto updatePacket = as<SystemWorldUpdatePacket>(packet)) {
|
|
auto location = m_ship->systemLocation();
|
|
for (auto p : updatePacket->shipUpdates) {
|
|
if (m_ship && p.first == m_ship->uuid())
|
|
m_ship->readNetState(p.second, SystemWorldTimestep);
|
|
else
|
|
m_clientShips[p.first]->readNetState(p.second, SystemWorldTimestep);
|
|
}
|
|
for (auto p : updatePacket->objectUpdates) {
|
|
auto object = getObject(p.first);
|
|
object->readNetState(p.second, SystemWorldTimestep);
|
|
}
|
|
|
|
} else if (auto createPacket = as<SystemObjectCreatePacket>(packet)) {
|
|
auto object = netLoadObject(createPacket->objectStore);
|
|
m_objects.set(object->uuid(), object);
|
|
|
|
} else if (auto destroyPacket = as<SystemObjectDestroyPacket>(packet)) {
|
|
m_objects.remove(destroyPacket->objectUuid);
|
|
m_universeMap->removeMappedObject(CelestialCoordinate(m_location), destroyPacket->objectUuid);
|
|
|
|
} else if (auto shipCreatePacket = as<SystemShipCreatePacket>(packet)) {
|
|
auto ship = netLoadShip(shipCreatePacket->shipStore);
|
|
m_clientShips.set(ship->uuid(), ship);
|
|
|
|
} else if (auto shipDestroyPacket = as<SystemShipDestroyPacket>(packet)) {
|
|
m_clientShips.remove(shipDestroyPacket->shipUuid);
|
|
|
|
} else if (auto startPacket = as<SystemWorldStartPacket>(packet)) {
|
|
m_objects.clear();
|
|
m_clientShips.clear();
|
|
m_location = startPacket->location;
|
|
for (auto netStore: startPacket->objectStores) {
|
|
auto object = netLoadObject(netStore);
|
|
m_objects.set(object->uuid(), object);
|
|
}
|
|
for (auto netStore : startPacket->shipStores) {
|
|
auto ship = netLoadShip(netStore);
|
|
m_clientShips.set(ship->uuid(), ship);
|
|
}
|
|
m_ship = make_shared<SystemClientShip>(this, startPacket->clientShip.first, startPacket->clientShip.second);
|
|
|
|
m_universeMap->addMappedCoordinate(CelestialCoordinate(m_location));
|
|
m_universeMap->filterMappedObjects(CelestialCoordinate(m_location), m_objects.keys());
|
|
} else {
|
|
// packet type not handled by system world client
|
|
return false;
|
|
}
|
|
|
|
// packet was handled
|
|
return true;
|
|
}
|
|
|
|
List<PacketPtr> SystemWorldClient::pullOutgoingPackets() {
|
|
return take(m_outgoingPackets);
|
|
}
|
|
|
|
SystemObjectPtr SystemWorldClient::netLoadObject(ByteArray netStore) {
|
|
DataStreamBuffer ds(move(netStore));
|
|
Uuid uuid = ds.read<Uuid>();
|
|
|
|
String name = ds.read<String>();
|
|
auto objectConfig = systemObjectConfig(name, uuid);
|
|
|
|
Vec2F position = ds.read<Vec2F>();
|
|
|
|
JsonObject parameters = ds.read<JsonObject>();
|
|
return make_shared<SystemObject>(objectConfig, uuid, position, parameters);
|
|
}
|
|
|
|
SystemClientShipPtr SystemWorldClient::netLoadShip(ByteArray netStore)
|
|
{
|
|
DataStreamBuffer ds(move(netStore));
|
|
Uuid uuid = ds.read<Uuid>();
|
|
SystemLocation location = ds.read<SystemLocation>();
|
|
return make_shared<SystemClientShip>(this, uuid, location);
|
|
}
|
|
|
|
}
|