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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2024-09-14 15:59:01 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2024-09-14 15:59:01 +1000
commit8155ec671581b051feca4187d5067ddbd149b387 (patch)
treefe87f75c0940b049fc0ea6def2b9508037be5b17
parent9dbc4daacc59c1fe506d803d1d8653a395c60822 (diff)
protected dungeon ID optimization + /settileprotection improvements
-rw-r--r--source/core/StarJsonExtra.hpp24
-rw-r--r--source/game/StarCommandProcessor.cpp35
-rw-r--r--source/game/StarEffectEmitter.cpp4
-rw-r--r--source/game/StarNetPackets.hpp2
-rw-r--r--source/game/StarWorldClient.cpp2
-rw-r--r--source/game/StarWorldClient.hpp2
-rw-r--r--source/game/StarWorldServer.cpp29
-rw-r--r--source/game/StarWorldServer.hpp5
8 files changed, 73 insertions, 30 deletions
diff --git a/source/core/StarJsonExtra.hpp b/source/core/StarJsonExtra.hpp
index 2a0ca28..ca5b510 100644
--- a/source/core/StarJsonExtra.hpp
+++ b/source/core/StarJsonExtra.hpp
@@ -211,32 +211,32 @@ Json jsonFromList(List<Value> const& list, Converter&& valueConvert) {
return res;
}
-template <typename Value>
-Set<Value> jsonToSet(Json const& v) {
- return jsonToSet<Value>(v, construct<Value>());
+template <typename SetType>
+SetType jsonToSet(Json const& v) {
+ return jsonToSet<SetType>(v, construct<Value>());
}
-template <typename Value, typename Converter>
-Set<Value> jsonToSet(Json const& v, Converter&& valueConvert) {
+template <typename SetType, typename Converter>
+SetType jsonToSet(Json const& v, Converter&& valueConvert) {
if (v.type() != Json::Type::Array)
throw JsonException("Json type is not an array in jsonToSet");
- Set<Value> res;
+ SetType res;
for (auto const& entry : v.iterateArray())
res.add(valueConvert(entry));
return res;
}
-template <typename Value>
-Json jsonFromSet(Set<Value> const& Set) {
- return jsonFromSet<Value>(Set, construct<Json>());
+template <typename SetType>
+Json jsonFromSet(SetType const& Set) {
+ return jsonFromSet<SetType>(Set, construct<Json>());
}
-template <typename Value, typename Converter>
-Json jsonFromSet(Set<Value> const& Set, Converter&& valueConvert) {
+template <typename SetType, typename Converter>
+Json jsonFromSet(SetType const& Set, Converter&& valueConvert) {
JsonArray res;
- for (auto entry : Set)
+ for (auto& entry : Set)
res.push_back(valueConvert(entry));
return res;
diff --git a/source/game/StarCommandProcessor.cpp b/source/game/StarCommandProcessor.cpp
index b5beb20..7b6915e 100644
--- a/source/game/StarCommandProcessor.cpp
+++ b/source/game/StarCommandProcessor.cpp
@@ -262,16 +262,33 @@ String CommandProcessor::setTileProtection(ConnectionId connectionId, String con
return "Not enough arguments to /settileprotection. Use /settileprotection <dungeonId> <protected>";
try {
- DungeonId dungeonId = lexicalCast<DungeonId>(arguments.at(0));
- bool isProtected = lexicalCast<bool>(arguments.at(1));
-
- bool done = m_universe->executeForClient(connectionId, [dungeonId, isProtected](WorldServer* world, PlayerPtr const&) {
- world->setTileProtection(dungeonId, isProtected);
- });
-
- return done ? "" : "Failed to set block protection.";
+ bool isProtected = lexicalCast<bool>(arguments.takeLast());
+ List<DungeonId> dungeonIds;
+ for (auto& banana : arguments) {
+ auto slices = banana.split("..");
+ auto it = slices.begin();
+ DungeonId previous = 0;
+ while (it != slices.end()) {
+ DungeonId current = lexicalCast<DungeonId>(*it);
+ dungeonIds.append(current);
+ if (it++ != slices.begin() && previous != current) {
+ if (current < previous) swap(previous, current);
+ for (DungeonId id = previous + 1; id != current; ++id)
+ dungeonIds.append(id);
+ }
+ previous = current;
+ }
+ }
+ size_t changed = 0;
+ if (!m_universe->executeForClient(connectionId, [&](WorldServer* world, PlayerPtr const&) {
+ changed = world->setTileProtection(dungeonIds, isProtected);
+ })) {
+ return "Invalid client state";
+ }
+ String output = strf("{} {} dungeon IDs", isProtected ? "Protected" : "Unprotected", changed);
+ return changed < dungeonIds.size() ? strf("{} ({} unchanged)", output, dungeonIds.size() - changed) : output;
} catch (BadLexicalCast const&) {
- return strf("Could not parse /settileprotection parameters. Use /settileprotection <dungeonId> <protected>", argumentString);
+ return strf("Could not parse /settileprotection parameters. Use /settileprotection <dungeonId...> <protected>", argumentString);
}
}
diff --git a/source/game/StarEffectEmitter.cpp b/source/game/StarEffectEmitter.cpp
index ddb0355..28e2986 100644
--- a/source/game/StarEffectEmitter.cpp
+++ b/source/game/StarEffectEmitter.cpp
@@ -94,14 +94,14 @@ void EffectEmitter::render(RenderCallback* renderCallback) {
Json EffectEmitter::toJson() const {
return JsonObject{{"activeSources",
- jsonFromSet<pair<String, String>>(m_activeSources.get(),
+ jsonFromSet<Set<pair<String, String>>>(m_activeSources.get(),
[](pair<String, String> const& entry) {
return JsonObject{{"position", entry.first}, {"source", entry.second}};
})}};
}
void EffectEmitter::fromJson(Json const& diskStore) {
- m_activeSources.set(jsonToSet<pair<String, String>>(diskStore.get("activeSources"),
+ m_activeSources.set(jsonToSet<Set<pair<String, String>>>(diskStore.get("activeSources"),
[](Json const& v) {
return pair<String, String>{v.getString("position"), v.getString("source")};
}));
diff --git a/source/game/StarNetPackets.hpp b/source/game/StarNetPackets.hpp
index 87a01cf..fc43212 100644
--- a/source/game/StarNetPackets.hpp
+++ b/source/game/StarNetPackets.hpp
@@ -415,7 +415,7 @@ struct WorldStartPacket : PacketBase<PacketType::WorldStart> {
bool respawnInWorld;
HashMap<DungeonId, float> dungeonIdGravity;
HashMap<DungeonId, bool> dungeonIdBreathable;
- Set<DungeonId> protectedDungeonIds;
+ StableHashSet<DungeonId> protectedDungeonIds;
Json worldProperties;
ConnectionId clientId;
bool localInterpolationMode;
diff --git a/source/game/StarWorldClient.cpp b/source/game/StarWorldClient.cpp
index ab5f9bf..d5c6bd7 100644
--- a/source/game/StarWorldClient.cpp
+++ b/source/game/StarWorldClient.cpp
@@ -1435,7 +1435,7 @@ bool WorldClient::isTileProtected(Vec2I const& pos) const {
if (!inWorld())
return true;
- auto tile = m_tileArray->tile(pos);
+ auto const& tile = m_tileArray->tile(pos);
return m_protectedDungeonIds.contains(tile.dungeonId);
}
diff --git a/source/game/StarWorldClient.hpp b/source/game/StarWorldClient.hpp
index 1616b10..2957661 100644
--- a/source/game/StarWorldClient.hpp
+++ b/source/game/StarWorldClient.hpp
@@ -367,7 +367,7 @@ private:
HashMap<DungeonId, float> m_dungeonIdGravity;
HashMap<DungeonId, bool> m_dungeonIdBreathable;
- Set<DungeonId> m_protectedDungeonIds;
+ StableHashSet<DungeonId> m_protectedDungeonIds;
HashMap<String, List<RpcPromiseKeeper<Vec2F>>> m_findUniqueEntityResponses;
HashMap<Uuid, RpcPromiseKeeper<Json>> m_entityMessageResponses;
diff --git a/source/game/StarWorldServer.cpp b/source/game/StarWorldServer.cpp
index e1e447d..c313771 100644
--- a/source/game/StarWorldServer.cpp
+++ b/source/game/StarWorldServer.cpp
@@ -1190,10 +1190,14 @@ bool WorldServer::isTileProtected(Vec2I const& pos) const {
if (!m_tileProtectionEnabled)
return false;
- auto tile = m_tileArray->tile(pos);
+ auto const& tile = m_tileArray->tile(pos);
return m_protectedDungeonIds.contains(tile.dungeonId);
}
+bool WorldServer::getTileProtection(DungeonId dungeonId) const {
+ return m_protectedDungeonIds.contains(dungeonId);
+}
+
void WorldServer::setTileProtection(DungeonId dungeonId, bool isProtected) {
bool updated = false;
if (isProtected) {
@@ -1205,9 +1209,28 @@ void WorldServer::setTileProtection(DungeonId dungeonId, bool isProtected) {
if (updated) {
for (auto const& pair : m_clientInfo)
pair.second->outgoingPackets.append(make_shared<UpdateTileProtectionPacket>(dungeonId, isProtected));
+
+ Logger::info("Protected dungeonIds for world set to {}", m_protectedDungeonIds);
}
+}
+
+size_t WorldServer::setTileProtection(List<DungeonId> const& dungeonIds, bool isProtected) {
+ List<PacketPtr> updates;
+ updates.reserve(dungeonIds.size());
+ for (auto const& dungeonId : dungeonIds)
+ if (isProtected ? m_protectedDungeonIds.add(dungeonId) : m_protectedDungeonIds.remove(dungeonId))
+ updates.append(make_shared<UpdateTileProtectionPacket>(dungeonId, isProtected));
+
+ if (updates.empty())
+ return 0;
+
+ for (auto const& pair : m_clientInfo)
+ pair.second->outgoingPackets.appendAll(updates);
- Logger::info("Protected dungeonIds for world set to {}", m_protectedDungeonIds);
+ auto newDungeonIds = m_protectedDungeonIds.values();
+ sort(newDungeonIds);
+ Logger::info("Protected dungeonIds for world set to {}", newDungeonIds);
+ return updates.size();
}
void WorldServer::setTileProtectionEnabled(bool enabled) {
@@ -2345,7 +2368,7 @@ void WorldServer::readMetadata() {
m_adjustPlayerStart = metadata.getBool("adjustPlayerStart");
m_worldTemplate = make_shared<WorldTemplate>(metadata.get("worldTemplate"));
m_centralStructure = WorldStructure(metadata.get("centralStructure"));
- m_protectedDungeonIds = jsonToSet<DungeonId>(metadata.get("protectedDungeonIds"), mem_fn(&Json::toUInt));
+ m_protectedDungeonIds = jsonToSet<StableHashSet<DungeonId>>(metadata.get("protectedDungeonIds"), mem_fn(&Json::toUInt));
m_worldProperties = metadata.getObject("worldProperties");
m_spawner.setActive(metadata.getBool("spawningEnabled"));
diff --git a/source/game/StarWorldServer.hpp b/source/game/StarWorldServer.hpp
index ea650ac..21c8e9f 100644
--- a/source/game/StarWorldServer.hpp
+++ b/source/game/StarWorldServer.hpp
@@ -180,7 +180,10 @@ public:
RpcPromise<Json> sendEntityMessage(Variant<EntityId, String> const& entity, String const& message, JsonArray const& args = {}) override;
bool isTileProtected(Vec2I const& pos) const override;
+ bool getTileProtection(DungeonId dungeonId) const;
void setTileProtection(DungeonId dungeonId, bool isProtected);
+ // sets a provided list of DungeonIds all at once and returns how many were changed
+ size_t setTileProtection(List<DungeonId> const& dungeonIds, bool isProtected);
// used to globally, temporarily disable protection for certain operations
void setTileProtectionEnabled(bool enabled);
@@ -396,7 +399,7 @@ private:
bool m_generatingDungeon;
HashMap<DungeonId, float> m_dungeonIdGravity;
HashMap<DungeonId, bool> m_dungeonIdBreathable;
- Set<DungeonId> m_protectedDungeonIds;
+ StableHashSet<DungeonId> m_protectedDungeonIds;
bool m_tileProtectionEnabled;
HashMap<Uuid, pair<ConnectionId, MVariant<ConnectionId, RpcPromiseKeeper<Json>>>> m_entityMessageResponses;