Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/game/StarSystemWorldClient.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/game/StarSystemWorldClient.cpp')
-rw-r--r--source/game/StarSystemWorldClient.cpp184
1 files changed, 184 insertions, 0 deletions
diff --git a/source/game/StarSystemWorldClient.cpp b/source/game/StarSystemWorldClient.cpp
new file mode 100644
index 0000000..9be0980
--- /dev/null
+++ b/source/game/StarSystemWorldClient.cpp
@@ -0,0 +1,184 @@
+#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() {
+ if (!m_ship)
+ return;
+
+ m_ship->clientUpdate(WorldTimestep);
+
+ 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(WorldTimestep);
+ for (auto p : m_objects)
+ p.second->clientUpdate(WorldTimestep);
+
+ 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);
+}
+
+}